summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBoss Marco <bossm8@students.bfh.ch>2019-11-18 21:09:39 +0100
committerBoss Marco <bossm8@students.bfh.ch>2019-11-18 21:09:39 +0100
commita267c2dc1633f2231391b54362b088ece1e1758d (patch)
treee80344335250a5b0ea3d795b6494b3fb74c5fa45
parent345aeee5f72032e04031382db1c512707c1cceb4 (diff)
parente56ae2fb3292a76fa2328beb55bc586c371f9ca3 (diff)
downloadtaler-mdb-a267c2dc1633f2231391b54362b088ece1e1758d.tar.gz
taler-mdb-a267c2dc1633f2231391b54362b088ece1e1758d.tar.bz2
taler-mdb-a267c2dc1633f2231391b54362b088ece1e1758d.zip
merged refactor
-rw-r--r--.gitignore5
-rw-r--r--Makefile.am2
-rw-r--r--README5
-rw-r--r--configure.ac157
-rw-r--r--contrib/uncrustify.cfg19
-rw-r--r--src/Makefile.am21
-rw-r--r--src/communication.c251
-rw-r--r--src/communication.h52
-rw-r--r--src/configuration.h53
-rw-r--r--src/main.c1166
-rw-r--r--src/nfc.c131
-rw-r--r--src/nfc.h35
-rw-r--r--src/product.c148
-rw-r--r--src/product.h68
-rwxr-xr-xsrc/taler-mdbbin0 -> 108040 bytes
-rw-r--r--src/target.mk6
-rw-r--r--src/wallet.c147
-rw-r--r--src/wallet.h56
-rw-r--r--taler.conf43
19 files changed, 1279 insertions, 1086 deletions
diff --git a/.gitignore b/.gitignore
index 9fe581f..c06dbe9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,5 +19,8 @@ src/Makefile
src/Makefile.am~
src/Makefile.in
stamp-h1
-
+*.pro*
+.qmake*
+build
uncrustify.cfg
+
diff --git a/Makefile.am b/Makefile.am
index 38153e1..40e718c 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = src doc .
+SUBDIRS = src .
EXTRA_DIST = \
AUTHORS \
diff --git a/README b/README
index 488d3cd..0aa8bb0 100644
--- a/README
+++ b/README
@@ -19,8 +19,9 @@
This is a app to run a snack machine as taler merchant with nfc payment interface.
#### Tasks
- * Add libjansson to parse and create json objects
- * Build system, makefile provided is not suitable
+ * fix bug when order pending -> press cancel -> abort from gunent scheduler
+ Nov 12 18:47:04-224202 util-scheduler-4656 ERROR `select' failed at scheduler.c:2336 with error: Bad file descriptor
+ Nov 12 18:47:04-224321 taler-mdb-4656 ERROR Assertion failed at scheduler.c:2370. Aborting.
#### Remarks
* When using an ACR122 device there may be problems with libnfc, see libnfc for further information
diff --git a/configure.ac b/configure.ac
index b3e673e..7dd8013 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,15 +3,18 @@
AC_PREREQ([2.69])
AC_INIT([FULL-PACKAGE-NAME], [VERSION], [BUG-REPORT-ADDRESS])
-AC_CONFIG_SRCDIR([src/product.c])
+AC_CONFIG_SRCDIR([src/main.c])
AC_CONFIG_HEADERS([config.h])
# Checks for programs.
AM_INIT_AUTOMAKE
AC_PROG_CC
+# Checks for libraries.
+AC_CHECK_LIB([nfc], [nfc_open])
+
# Checks for header files.
-AC_CHECK_HEADERS([stdlib.h string.h unistd.h])
+AC_CHECK_HEADERS([stdlib.h string.h unistd.h sys/un.h netinet/in.h netinet/ip.h])
# Checks for typedefs, structures, and compiler characteristics.
AC_CHECK_HEADER_STDBOOL
@@ -65,15 +68,149 @@ AC_CHECK_FUNCS([strstr])
-# Save before checking libgnurl/libcurl
-CFLAGS_SAVE=$CFLAGS
-LDFLAGS_SAVE=$LDFLAGS
+# Save before checking for libraries
LIBS_SAVE=$LIBS
-# Checks for libraries.
-AC_CHECK_LIB([nfc], [nfc_open],,[AC_MSG_ERROR([libnfc required])])
+
+# test for libqrencode
+qrencode=0
+QR_LIBS="-lqrencode"
+AC_MSG_CHECKING(for libqrencode)
+AC_ARG_WITH(qrencode,
+ [ --with-qrencode=PFX Base of libqrencode installation],
+ [AC_MSG_RESULT([$with_qrencode])
+ AS_CASE([$with_qrencode],
+ [no],[],
+ [yes],[
+ AC_CHECK_HEADERS(qrencode.h,qrencode=1)
+ ],
+ [
+ CPPFLAGS="-I$with_qrencode/include $CPPFLAGS"
+ QR_CFLAGS="-I$with_qrencode/include"
+ QR_LIBS="-L$with_qrencode/lib -lqrencode"
+ AC_CHECK_HEADERS(qrencode.h,qrencode=1)
+ ])
+ ],
+ [AC_MSG_RESULT([--with-qrencode not specified])
+ AC_CHECK_HEADERS(qrencode.h,qrencode=1)])
+
+AS_IF([test "$qrencode" != 1],
+[
+QR_LIBS=""
+QR_CFLAGS=""
+])
+
+AC_SUBST(QR_CFLAGS)
+AC_SUBST(QR_LIBS)
+
+
+# Check for Taler's libtalermerchant
+libtalermerchant=0
+AC_MSG_CHECKING([for libtalermerchant])
+AC_ARG_WITH(merchant,
+ [AS_HELP_STRING([--with-merchant=PFX], [base of Taler MERCHANT installation])],
+ [AC_MSG_RESULT([given as $with_merchant])],
+ [AC_MSG_RESULT(not given)
+ with_merchant=yes])
+AS_CASE([$with_merchant],
+ [yes], [],
+ [no], [AC_MSG_ERROR([--with-merchant is required])],
+ [LDFLAGS="-L$with_merchant/lib $LDFLAGS"
+ CPPFLAGS="-I$with_merchant/include $CPPFLAGS $POSTGRESQL_CPPFLAGS"])
+
+AC_CHECK_HEADERS([taler/taler_merchant_service.h],
+ [AC_CHECK_LIB([talermerchant], [TALER_MERCHANT_poll_payment], libtalermerchant=1)],
+ [], [#ifdef HAVE_TALER_PLATFORM_H
+ #include <taler/platform.h>
+ #endif])
+
+
+
+# Check for GNUnet's libgnunetutil.
+libgnunetutil=0
+AC_MSG_CHECKING([for libgnunetutil])
+AC_ARG_WITH(gnunet,
+ [AS_HELP_STRING([--with-gnunet=PFX], [base of GNUnet installation])],
+ [AC_MSG_RESULT([given as $with_gnunet])],
+ [AC_MSG_RESULT(not given)
+ with_gnunet=yes])
+AS_CASE([$with_gnunet],
+ [yes], [],
+ [no], [AC_MSG_ERROR([--with-gnunet is required])],
+ [LDFLAGS="-L$with_gnunet/lib $LDFLAGS"
+ CPPFLAGS="-I$with_gnunet/include $CPPFLAGS"])
+AC_CHECK_HEADERS([gnunet/platform.h gnunet/gnunet_util_lib.h],
+ [AC_CHECK_LIB([gnunetutil], [GNUNET_SCHEDULER_run], libgnunetutil=1)],
+ [], [#ifdef HAVE_GNUNET_PLATFORM_H
+ #include <gnunet/platform.h>
+ #endif])
+AS_IF([test $libgnunetutil != 1],
+ [AC_MSG_ERROR([[
+***
+*** You need libgnunetutil to build this program.
+*** This library is part of GNUnet, available at
+*** https://gnunet.org
+*** ]])])
+
+# Check for GNUnet's libgnunetjson.
+libgnunetjson=0
+AC_MSG_CHECKING([for libgnunetjson])
+AC_ARG_WITH(gnunet,
+ [AS_HELP_STRING([--with-gnunet=PFX], [base of GNUnet installation])],
+ [AC_MSG_RESULT([given as $with_gnunet])],
+ [AC_MSG_RESULT(not given)
+ with_gnunet=yes])
+AS_CASE([$with_gnunet],
+ [yes], [],
+ [no], [AC_MSG_ERROR([--with-gnunet is required])],
+ [LDFLAGS="-L$with_gnunet/lib $LDFLAGS"
+ CPPFLAGS="-I$with_gnunet/include $CPPFLAGS"])
+AC_CHECK_HEADERS([gnunet/platform.h gnunet/gnunet_json_lib.h],
+ [AC_CHECK_LIB([gnunetjson], [GNUNET_JSON_parse], libgnunetjson=1)],
+ [], [#ifdef HAVE_GNUNET_PLATFORM_H
+ #include <gnunet/platform.h>
+ #endif])
+AS_IF([test $libgnunetjson != 1],
+ [AC_MSG_ERROR([[
+***
+*** You need libgnunetjson to build this program.
+*** Make sure you have libjansson installed while
+*** building GNUnet.
+*** ]])])
+
+# Check for GNUnet's libgnunetcurl.
+libgnunetcurl=0
+AC_MSG_CHECKING([for libgnunetcurl])
+AC_ARG_WITH(gnunet,
+ [AS_HELP_STRING([--with-gnunet=PFX], [base of GNUnet installation])],
+ [AC_MSG_RESULT([given as $with_gnunet])],
+ [AC_MSG_RESULT(not given)
+ with_gnunet=yes])
+AS_CASE([$with_gnunet],
+ [yes], [],
+ [no], [AC_MSG_ERROR([--with-gnunet is required])],
+ [LDFLAGS="-L$with_gnunet/lib $LDFLAGS"
+ CPPFLAGS="-I$with_gnunet/include $CPPFLAGS"])
+AC_CHECK_HEADERS([gnunet/platform.h gnunet/gnunet_curl_lib.h],
+ [AC_CHECK_LIB([gnunetcurl], [GNUNET_CURL_get_select_info], libgnunetcurl=1)],
+ [], [#ifdef HAVE_GNUNET_PLATFORM_H
+ #include <gnunet/platform.h>
+ #endif])
+AS_IF([test $libgnunetcurl != 1],
+ [AC_MSG_ERROR([[
+***
+*** You need libgnunetcurl to build this program.
+*** Make sure you have libcurl or libgnurl installed while
+*** building GNUnet.
+*** ]])])
+
+
+# Save before checking libgnurl/libcurl
+CFLAGS_SAVE=$CFLAGS
+LDFLAGS_SAVE=$LDFLAGS
+
# check for libgnurl
# libgnurl
@@ -141,6 +278,10 @@ LIBS=$LIBS_SAVE
AC_CONFIG_FILES([Makefile
- doc/Makefile
src/Makefile])
AC_OUTPUT
+
+if test "$qrencode" != 1
+then
+ AC_MSG_WARN([taler-mdb will not include QR support])
+fi
diff --git a/contrib/uncrustify.cfg b/contrib/uncrustify.cfg
index 8c9df2c..cc9552f 100644
--- a/contrib/uncrustify.cfg
+++ b/contrib/uncrustify.cfg
@@ -49,12 +49,8 @@ nl_assign_brace=remove
# No extra newlines that cause noisy diffs
nl_start_of_file=remove
-nl_after_func_proto = 2
-nl_after_func_body = 3
# If there's no new line, it's not a text file!
nl_end_of_file=add
-nl_max_blank_in_func = 3
-nl_max = 3
sp_inside_paren = remove
@@ -73,23 +69,10 @@ sp_between_ptr_star = remove
sp_before_sparen = add
sp_inside_fparen = remove
-sp_inside_sparen = remove
# add space before function call and decl: "foo (x)"
sp_func_call_paren = add
sp_func_proto_paren = add
sp_func_proto_paren_empty = add
sp_func_def_paren = add
-sp_func_def_paren_empty = add
-
-# We'd want it for "if ( (foo) || (bar) )", but not for "if (m())",
-# so as uncrustify doesn't give exactly what we want => ignore
-sp_paren_paren = ignore
-sp_inside_paren = remove
-sp_bool = force
-
-nl_func_type_name = force
-#nl_branch_else = add
-nl_else_brace = add
-nl_elseif_brace = add
-nl_for_brace = add
+sp_func_def_paren_empty = add \ No newline at end of file
diff --git a/src/Makefile.am b/src/Makefile.am
index 3105b63..881df65 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,28 +1,29 @@
# This Makefile.am is in the public domain
-bin_PROGRAMS = taler-nfc
+bin_PROGRAMS = taler-mdb
if USE_COVERAGE
AM_CFLAGS = --coverage -O0
XLIB = -lgcov
endif
-taler_nfc_SOURCES = \
- nfc.c nfc.h \
- wallet.c wallet.h \
- product.c product.h \
- communication.c communication.h \
+taler_mdb_SOURCES = \
main.c
-taler_nfc_LDADD = \
+taler_mdb_LDADD = \
+ -ltalermerchant \
+ -ltalerjson \
+ -ltalerutil \
+ -lgnunetcurl \
+ -lgnunetutil \
-ljansson \
-lnfc \
- -lpthread \
+ @QR_LIBS@ \
$(XLIB)
if HAVE_LIBCURL
-taler_nfc_LDADD += -lcurl
+taler_mdb_LDADD += -lcurl
else
if HAVE_LIBGNURL
-taler_nfc_LDADD += -lgnurl
+taler_mdb_LDADD += -lgnurl
endif
endif
diff --git a/src/communication.c b/src/communication.c
deleted file mode 100644
index a62e5e8..0000000
--- a/src/communication.c
+++ /dev/null
@@ -1,251 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2019 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more
-details.
-
- You should have received a copy of the GNU General Public License
-along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-
-/**
-* @file communication.c
-* @brief functions to communicate with taler backend
-* @author BOSS Marco
-*/
-
-#include <string.h>
-#include <stdbool.h>
-
-#include "communication.h"
-#include "wallet.h"
-#include "configuration.h"
-
-
-int
-taler_init (CURL **curl)
-{
- if (*curl != NULL)
- {
- printf ("taler_init: curl handle already initialized\n");
- return EXIT_FAILURE;
- }
-
- // initialize curl
- CURLcode result = curl_global_init (CURL_GLOBAL_ALL);
- *curl = curl_easy_init ();
- if (! (*curl) || (result != CURLE_OK) )
- {
- printf ("taler_init: could not inizialize curl handle\n");
- return EXIT_FAILURE;
- }
-
- return EXIT_SUCCESS;
-}
-
-
-void
-taler_exit (CURL **curl)
-{
- curl_easy_cleanup (*curl);
- curl_global_cleanup ();
-}
-
-
-int
-taler_alloc_string (char **string, size_t size)
-{
- *string = malloc (size);
- if (! (*string) )
- {
- printf ("taler_alloc: unable to allocate string");
- exit (EXIT_FAILURE);
- }
- return EXIT_SUCCESS;
-}
-
-
-static size_t
-_taler_write_response (void *contents, size_t size, size_t nmemb,
- void *userp)
-{
- size_t realSize = size * nmemb;
- struct TalerResponse *response = (struct TalerResponse *) userp;
-
- char *tempString = realloc (response->string, response->size + realSize + 1);
- if (! tempString)
- {
- printf ("Allocation failure");
- return EXIT_FAILURE;
- }
-
- response->string = tempString;
- memcpy (&(response->string[response->size]), contents, realSize);
- response->size += realSize;
- response->string[response->size] = 0;
-
- return realSize;
-}
-
-
-int
-taler_create_order_req (ProductOrder *product)
-{
- char buffer[256];
-
- sprintf (buffer, JSON_ORDER, product->product, product->currency,
- product->amount, product->product);
-
- char*temp = realloc (product->orderRequest, strlen (buffer) + 1);
- if (! temp)
- {
- printf ("could not allocate order\n");
- return EXIT_FAILURE;
- }
-
- product->orderRequest = temp;
- strcpy (product->orderRequest, buffer);
- printf ("Created order Request: \n%s\n\n", product->orderRequest);
-
- return EXIT_SUCCESS;
-}
-
-
-int
-taler_create_order (CURL *curl, ProductOrder *product)
-{
- // reset the response size
- product->response->size = 0;
-
- // set the url
- char url[ strlen (BACKEND_BASE_URL) + strlen (ORDER) + 1 ];
- sprintf (url, "%s%s", BACKEND_BASE_URL, ORDER);
- curl_easy_setopt (curl, CURLOPT_URL, url);
-
- // set the authentication headers
- struct curl_slist *list = NULL;
- list = curl_slist_append (list, AUTH_HEADER);
- curl_easy_setopt (curl, CURLOPT_HTTPHEADER, list);
-
- // curl option "post"
- curl_easy_setopt (curl, CURLOPT_HTTPPOST, true);
- curl_easy_setopt (curl, CURLOPT_POSTFIELDS, product->orderRequest);
-
- // pass the write function and the struct to write to
- curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, _taler_write_response);
- curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *) product->response);
-
- // perform the call
- CURLcode result = curl_easy_perform (curl);
- if (result != CURLE_OK)
- {
- printf ("could not communicate with \"%s\"\n", url);
- return EXIT_FAILURE;
- }
-
- // reset the curl options
- curl_easy_reset (curl);
-
- // clean up
- curl_slist_free_all (list);
-
- return EXIT_SUCCESS;
-}
-
-
-int
-taler_check_payment_status (CURL *curl, ProductOrder *product)
-{
- // reset the response size
- product->response->size = 0;
-
- // set the url
- curl_easy_setopt (curl, CURLOPT_URL, product->checkUrl);
-
- // set the authentication headers
- struct curl_slist *list = NULL;
- list = curl_slist_append (list, AUTH_HEADER);
- curl_easy_setopt (curl, CURLOPT_HTTPHEADER, list);
-
- // curl option "get"
- curl_easy_setopt (curl, CURLOPT_HTTPGET, true);
-
- // pass the write function and the struct to write to
- curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, _taler_write_response);
- curl_easy_setopt (curl, CURLOPT_WRITEDATA, (void *) product->response);
-
- // perform the call
- CURLcode result = curl_easy_perform (curl);
- if (result != CURLE_OK)
- {
- printf ("could not communicate with \"%s\"\n", product->checkUrl);
- return EXIT_FAILURE;
- }
-
- // reset the curl options
- curl_easy_reset (curl);
-
- // clean up
- curl_slist_free_all (list);
-
- return EXIT_SUCCESS;
-}
-
-
-int
-taler_parse_json (const TalerResponse *response, const char *memberName,
- char **returnStr, bool isBoolean)
-{
- if (! (*returnStr) )
- taler_alloc_string (returnStr, 1);
- char *result = NULL;
- char *temp = NULL;
- char mbr[64];
-
- if (isBoolean)
- {
- // If the wanted member is of type boolean
- sprintf (mbr, "\"%s\": true", memberName);
- if ( (temp = strstr (response->string, mbr)) != NULL)
- result = "true";
- else
- result = "false";
- }
- else
- {
- // String type members
- sprintf (mbr, "\"%s\":", memberName);
- if ( (temp = strstr (response->string, mbr)) != NULL)
- {
- if ( (temp = strstr (response->string, ": ")) != NULL)
- {
- result = strtok (temp, "\"");
- result = strtok (NULL, "\"");
- }
- }
- }
- if (! result)
- {
- printf ("taler_parse_json: no member named \"%s\" found!\n\n", memberName);
- return EXIT_FAILURE;
- }
- temp = realloc (*returnStr, strlen (result) + 1);
- if (! temp)
- {
- printf ("taler_parse_json: could not allocate memory for member\n");
- return EXIT_FAILURE;
- }
- *returnStr = temp;
- strcpy (*returnStr, result);
-
- return EXIT_SUCCESS;
-}
diff --git a/src/communication.h b/src/communication.h
deleted file mode 100644
index 91cef87..0000000
--- a/src/communication.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2019 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more
-details.
-
- You should have received a copy of the GNU General Public License
-along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-
-/**
-* @file communication.h
-* @brief functions to communicate with taler backend
-* @author BOSS Marco
-*/
-
-
-#ifndef COMM_H
-#define COMM_H
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <curl/curl.h>
-
-#include "product.h"
-
-int taler_init (CURL **curl);
-
-void taler_exit (CURL **curl);
-
-int taler_alloc_string (char **string, size_t size);
-
-int taler_create_order_req (ProductOrder *product);
-
-int taler_create_order (CURL *curl, ProductOrder *product);
-
-int taler_check_payment_status (CURL *curl, ProductOrder *product);
-
-int taler_parse_json (const TalerResponse *response, const char *memberName,
- char **returnStr, bool isBoolean);
-
-#endif // COMM_H
diff --git a/src/configuration.h b/src/configuration.h
deleted file mode 100644
index aa0be01..0000000
--- a/src/configuration.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2019 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more
-details.
-
- You should have received a copy of the GNU General Public License
-along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-
-/**
-* @file configuration.h
-* @brief in this file you can set your url specifications needed to comminicate with taler
-* @author BOSS Marco
-*/
-
-#ifndef URL_H
-#define URL_H
-
-static const char*const ORDER = "/order";
-static const char*const CHECK = "/check-payment";
-static const char*const ORDER_CHECK = "?order_id=";
-
-static const char*const BACKEND_BASE_URL = "https://backend.demo.taler.net";
-
-static const char*const AUTH_HEADER = "Authorization: ApiKey sandbox";
-
-static const char*const JSON_PAID = "paid";
-static const char*const JSON_PAY_URI = "taler_pay_uri";
-static const char*const JSON_ORDER_ID = "order_id";
-
-
-//// will be replaced with libjansson functionalites -----------------------------------------------------------------------------------
-// ajust sprintf in taler_create_order_req communication.c if changed
-static const char*const JSON_ORDER = "{\n"
- " \"order\":"
- " {\n"
- " \"summary\": \"%s\",\n"
- " \"amount\": \"%s:%s\",\n"
- " \"fulfillment_url\": \"taler://fulfillment-success/Enjoy+your+%s!\"\n"
- " }\n"
- "}";
-
-#endif // URL_H
diff --git a/src/main.c b/src/main.c
index 0880b01..76abaac 100644
--- a/src/main.c
+++ b/src/main.c
@@ -16,170 +16,1138 @@ details.
along with
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
-
/**
* @file main.c
* @brief main functionality of the application
-* @author BOSS Marco
-* @author ...
+* @author Boss Marco
+* @author Christian Grothoff
*/
-
+#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <pthread.h>
#include <unistd.h>
+#include <sys/socket.h>
+#if HAVE_SYS_UN_H
+#include <sys/un.h>
+#endif
+#if HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#if HAVE_NETINET_IP_H
+#include <netinet/ip.h> /* superset of previous */
+#endif
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <termios.h>
#include <nfc/nfc.h>
-#include <curl/curl.h>
+#include <microhttpd.h>
+#include <gnunet/gnunet_util_lib.h>
+#include <taler/taler_json_lib.h>
+#include <taler/taler_merchant_service.h>
+#if HAVE_QRENCODE_H /* for adafruit pitft display */
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <linux/fb.h>
+#endif
+
+/**
+ * Disable i18n support.
+ */
+#define _(s) (s)
+
+#define BACKEND_POLL_TIMEOUT GNUNET_TIME_UNIT_MINUTES
+
+#define NFC_FAILURE_RETRY_FREQ GNUNET_TIME_UNIT_SECONDS
+
+/**
+ * Timeout in milliseconds for libnfc operations.
+ */
+#define NFC_TIMEOUT 500
+
+#define MAX_HTTP_RETRY_FREQ GNUNET_TIME_relative_multiply ( \
+ GNUNET_TIME_UNIT_MILLISECONDS, 500)
+
+/**
+ * Code returned by libnfc in case of success.
+ */
+#define APDU_SUCCESS "\x90\x00"
+
+/**
+ * Code returned by libnfc in case Taler wallet is not installed.
+ */
+#define APDU_NOT_FOUND "\x6a\x82"
+
+/* upper and lower bounds for mifare targets uid length */
+#define UID_LEN_UPPER 7
+#define UID_LEN_LOWER 4
+
+
+/* curl auth header */
+#define SNACK_CURL_AUTH_HEADER "Authorization"
+
+/**
+ * @brief FRAMEBUFFER_DEVICE framebuffer device to diplay qr code
+ */
+const char *FRAMEBUFFER_DEVICE = "/dev/fb1";
+
+/* Wallet AID */
+static const uint8_t taler_aid[] = { 0xF0, 0x00, 0x54, 0x41, 0x4c, 0x45, 0x52 };
+
+/* APDU commands */
+static const uint8_t select_file[] = { 0x00, 0xA4, 0x04, 0x00, 0x07 };
+static const uint8_t put_data[] = { 0x00, 0xDA, 0x01, 0x00, 0x7c, 0x01 };
+
+#if FUTURE_FEATURES
+/* tunneling */
+static const uint8_t get_data[] = { 0x00, 0xCA, 0x01, 0x00, 0x00, 0x00 };
+#endif
+
+
+struct Product
+{
+ struct TALER_Amount price;
+
+ char *description;
+
+ char *number;
+
+ char key;
+};
+
+
+struct PaymentActivity
+{
+ struct TALER_MERCHANT_ProposalOperation *po;
-#include "nfc.h"
-#include "communication.h"
-#include "product.h"
+ struct TALER_MERCHANT_CheckPaymentOperation *cpo;
-const char *CURRENCY = "KUDOS";
+ char *order_id;
+ char *taler_pay_uri;
-ProductOrder product;
-nfc_context *context = NULL;
+ nfc_device *pnd;
+ nfc_target nt;
-void *
-start_nfc_transmission (void *ignored)
+ struct GNUNET_SCHEDULER_Task *task;
+
+ struct GNUNET_SCHEDULER_Task *delay_task;
+
+ int wallet_has_uri;
+};
+
+
+struct Display
+{
+ int devicefd;
+
+ int backlightfd;
+
+ uint16_t *memory;
+
+ struct fb_var_screeninfo orig_vinfo;
+
+ struct fb_var_screeninfo var_info;
+
+ struct fb_fix_screeninfo fix_info;
+};
+
+
+static nfc_context *context;
+
+static int global_ret;
+
+static struct GNUNET_SCHEDULER_Task *keyboard_task;
+
+static struct GNUNET_CURL_Context *ctx;
+
+static struct GNUNET_CURL_RescheduleContext *rc;
+
+static char *currency;
+
+static char *backendBaseUrl;
+
+static char *fulfillmentUrl;
+
+static char *fulfillmentMsg;
+
+static char *authorization;
+
+static struct PaymentActivity *payment_activity;
+
+static struct Product *products;
+
+static struct Display qrDisplay;
+
+static unsigned int products_length;
+
+
+#if HAVE_QRENCODE_H
+#include <qrencode.h>
+
+/**
+ * Create the QR code image for our zone.
+ *
+ * @param uri what text to show in the QR code
+ */
+static void
+show_qrcode (const char *uri)
{
- // supress warning about unused variable
- (void) ignored;
+ QRinput *qri;
+ QRcode *qrc;
+ unsigned int size;
+ char *upper;
+ size_t xOff;
+ size_t yOff;
- if (pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL) != 0)
+ if (0 > qrDisplay.devicefd)
+ return; /* no display, no dice */
+ qri = QRinput_new2 (0, QR_ECLEVEL_L);
+ if (NULL == qri)
{
- printf ("Error setting thread cancelling type\n");
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "QRinput_new2");
+ return;
}
- // start endless transmission loop (until threads gets cancelled)
- while (1)
+ upper = GNUNET_strdup (uri);
+ /* NOTE: this line fails, Taler wallet likes URIs only lower-case!
+ => Wallet bug! */
+ // GNUNET_STRINGS_utf8_toupper (uri, upper);
+ /* first try encoding as uppercase-only alpha-numerical
+ QR code (much smaller encoding); if that fails, also
+ try using binary encoding (in case nick contains
+ special characters). */
+ if ( (0 !=
+ QRinput_append (qri,
+ QR_MODE_AN,
+ strlen (upper),
+ (unsigned char *) upper)) &&
+ (0 !=
+ QRinput_append (qri,
+ QR_MODE_8,
+ strlen (upper),
+ (unsigned char *) upper)))
{
- if (pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL) != 0)
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "QRinput_append");
+ GNUNET_free (upper);
+ return;
+ }
+ GNUNET_free (upper);
+ qrc = QRcode_encodeInput (qri);
+ if (NULL == qrc)
+ {
+ GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING,
+ "QRcode_encodeInput");
+ QRinput_free (qri);
+ return;
+ }
+
+ /* +8 for 4-pixels border */
+ size = GNUNET_MIN (qrDisplay.var_info.xres,
+ qrDisplay.var_info.yres);
+ unsigned int nwidth = qrc->width + 8; /* 4 pixel border */
+ xOff = 4 * size / nwidth;
+ yOff = 4 * size / nwidth;
+ if (qrDisplay.var_info.xres < qrDisplay.var_info.yres)
+ yOff += (qrDisplay.var_info.yres - qrDisplay.var_info.xres) / 2;
+ else
+ xOff += (qrDisplay.var_info.xres - qrDisplay.var_info.yres) / 2;
+ for (unsigned int x = 0; x < qrDisplay.var_info.xres - 2 * xOff; x++)
+ for (unsigned int y = 0; y < qrDisplay.var_info.yres - 2 * yOff; y++)
+ {
+ unsigned int xoff = x * nwidth / size;
+ unsigned int yoff = y * nwidth / size;
+ unsigned int off = xoff + yoff * qrc->width;
+ if ( (xoff >= (unsigned) qrc->width) ||
+ (yoff >= (unsigned) qrc->width) )
+ continue;
+ qrDisplay.memory[(y + yOff) * qrDisplay.var_info.xres + (x + xOff)] =
+ (0 == (qrc->data[off] & 1)) ? 0xFFFF : 0x0000;
+ }
+
+ QRcode_free (qrc);
+ QRinput_free (qri);
+
+ if (0 < qrDisplay.backlightfd)
+ write (qrDisplay.backlightfd, "1", 1);
+}
+
+#endif
+
+
+static void
+cleanup_payment (struct PaymentActivity *pa)
+{
+ if (NULL != pa->pnd)
+ {
+ nfc_abort_command (pa->pnd);
+ nfc_close (pa->pnd);
+ }
+ if (NULL != pa->po)
+ TALER_MERCHANT_proposal_cancel (pa->po);
+ if (NULL != pa->cpo)
+ TALER_MERCHANT_check_payment_cancel (pa->cpo);
+ if (NULL != pa->task)
+ GNUNET_SCHEDULER_cancel (pa->task);
+ if (NULL != pa->delay_task)
+ GNUNET_SCHEDULER_cancel (pa->delay_task);
+ if (NULL != pa->taler_pay_uri)
+ {
+#if HAVE_QRENCODE_H
+ if (NULL != qrDisplay.memory)
+ memset (qrDisplay.memory,
+ 0xFF,
+ qrDisplay.var_info.xres * qrDisplay.var_info.yres
+ * sizeof (uint16_t));
+ if (0 < qrDisplay.backlightfd)
+ write (qrDisplay.backlightfd, "0", 1);
+#endif
+ GNUNET_free (pa->taler_pay_uri);
+ }
+ GNUNET_free_non_null (pa->order_id);
+ GNUNET_free (pa);
+}
+
+
+static void
+shutdown_task (void *cls)
+{
+ (void) cls;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Shutdown initiated\n");
+ if (NULL != context)
+ {
+ nfc_exit (context);
+ context = NULL;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "NFC down\n");
+ if (NULL != payment_activity)
+ {
+ cleanup_payment (payment_activity);
+ payment_activity = NULL;
+ }
+ if (NULL != keyboard_task)
+ {
+ GNUNET_SCHEDULER_cancel (keyboard_task);
+ keyboard_task = NULL;
+ }
+ if (NULL != ctx)
+ {
+ GNUNET_CURL_fini (ctx);
+ ctx = NULL;
+ }
+ if (NULL != rc)
+ {
+ GNUNET_CURL_gnunet_rc_destroy (rc);
+ rc = NULL;
+ }
+ if (NULL != qrDisplay.memory)
+ {
+ /* free the display data */
+ munmap (qrDisplay.memory,
+ qrDisplay.fix_info.smem_len);
+ qrDisplay.memory = NULL;
+ /* reset original state */
+ if (0 > ioctl (qrDisplay.devicefd,
+ FBIOPUT_VSCREENINFO,
+ &qrDisplay.orig_vinfo))
{
- printf ("Error setting thread cancelling state\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "failed to reset originial display state\n");
}
- nfc_transmit (context, product.payUrl, strlen (product.payUrl) );
- if (pthread_setcancelstate (PTHREAD_CANCEL_ENABLE, NULL) != 0)
+ /* close device */
+ close (qrDisplay.devicefd);
+ qrDisplay.devicefd = -1;
+ if (0 < qrDisplay.backlightfd)
+ close (qrDisplay.backlightfd);
+ qrDisplay.backlightfd = -1;
+ }
+ if (NULL != products)
+ {
+ for (unsigned int i = 0; i < products_length; i++)
{
- printf ("Error setting thread cancelling state\n");
+ GNUNET_free (products[i].description);
+ GNUNET_free (products[i].number);
}
- sleep (1);
+ GNUNET_array_grow (products,
+ products_length,
+ 0);
}
- return EXIT_SUCCESS;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Shutdown complete\n");
}
-int
-main ( )
+static void
+check_payment_again (void *cls);
+
+
+static void
+connect_target (void *cls);
+
+
+static void
+wallet_select_aid (void *cls);
+
+
+static void
+wallet_transmit_uri (void *cls)
{
- // initialize nfc
- nfc_init (&context);
- if (! context)
+ struct PaymentActivity *pa = cls;
+ uint8_t response[] = { 0x00, 0x00 };
+ size_t slen = strlen (pa->taler_pay_uri);
+ uint8_t message[sizeof (put_data) + slen];
+
+ pa->delay_task = NULL;
+ memcpy (message, put_data, sizeof (put_data));
+ memcpy (&message[sizeof (put_data)], pa->taler_pay_uri, slen);
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Sending 'PUT DATA' command for `%s' to wallet\n",
+ pa->taler_pay_uri);
+ if (0 > nfc_initiator_transceive_bytes (pa->pnd,
+ message,
+ sizeof (message),
+ response,
+ sizeof(response),
+ NFC_TIMEOUT))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Failed to send command\n");
+ pa->task = GNUNET_SCHEDULER_add_now (&connect_target,
+ pa);
+ return;
+ }
+ if (0 != memcmp (response,
+ APDU_SUCCESS,
+ sizeof (response)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "'PUT DATA' command transmission failed, return code: %x%x\n",
+ response[0],
+ response[1]);
+ pa->task = GNUNET_SCHEDULER_add_now (&connect_target,
+ pa);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "'PUT DATA' command sent successfully\n");
+ pa->wallet_has_uri = GNUNET_YES;
+ /* FIXME: or just offer Internet service here? */
+ pa->delay_task = GNUNET_SCHEDULER_add_delayed (MAX_HTTP_RETRY_FREQ,
+ &wallet_transmit_uri,
+ pa);
+}
+
+
+static void
+wallet_select_aid (void *cls)
+{
+ struct PaymentActivity *pa = cls;
+ uint8_t response[] = { 0x00, 0x00 };
+ uint8_t message[sizeof(select_file) + sizeof(taler_aid)];
+
+ pa->task = NULL;
+ memcpy (message, select_file, sizeof (select_file));
+ memcpy (&message[sizeof (select_file)], taler_aid, sizeof (taler_aid));
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Trying to find Taler wallet\n");
+ if (0 > nfc_initiator_transceive_bytes (pa->pnd,
+ message,
+ sizeof (message),
+ response,
+ sizeof (response),
+ NFC_TIMEOUT))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Failed to transceive with NFC app, trying to find another NFC client\n");
+ pa->task = GNUNET_SCHEDULER_add_now (&connect_target,
+ pa);
+ return;
+ }
+ if (0 == memcmp (response,
+ APDU_SUCCESS,
+ sizeof (response)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Taler wallet found\n");
+ pa->delay_task = GNUNET_SCHEDULER_add_now (&wallet_transmit_uri,
+ pa);
+ return;
+ }
+ if (0 == memcmp (response,
+ APDU_NOT_FOUND,
+ sizeof (response)))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Taler wallet NOT found on this device\n");
+ pa->task = GNUNET_SCHEDULER_add_now (&connect_target,
+ pa);
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "AID selection failure, return code: %x%x, trying to find another NFC client\n",
+ response[0],
+ response[1]);
+ pa->task = GNUNET_SCHEDULER_add_delayed (NFC_FAILURE_RETRY_FREQ,
+ &connect_target,
+ pa);
+}
+
+
+static void
+connect_target (void *cls)
+{
+ struct PaymentActivity *pa = cls;
+ const nfc_modulation nmMifare = {
+ .nmt = NMT_ISO14443A,
+ .nbr = NBR_212,
+ };
+
+ pa->task = NULL;
+ pa->nt.nti.nai.szUidLen = 0;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Trying to find NFC client\n");
+ if (0 > nfc_initiator_poll_target (pa->pnd,
+ &nmMifare,
+ 1,
+ 0x01,
+ 0x01,
+ &pa->nt))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Failed to connect to NFC target\n");
+ }
+ else if ( (pa->nt.nti.nai.szUidLen > UID_LEN_UPPER) ||
+ (pa->nt.nti.nai.szUidLen < UID_LEN_LOWER) )
{
- printf ("Unable to init libnfc\n");
- return EXIT_FAILURE;
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to connect, wrong NFC modulation\n");
}
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Found NFC client\n");
+ pa->task = GNUNET_SCHEDULER_add_now (&wallet_select_aid,
+ pa);
+ return;
+ }
+ pa->task = GNUNET_SCHEDULER_add_delayed (NFC_FAILURE_RETRY_FREQ,
+ &connect_target,
+ pa);
+}
+
- // initialize taler
- CURL *curl = NULL;
- if (taler_init (&curl) )
+static void
+connect_nfc (void *cls)
+{
+ struct PaymentActivity *pa = cls;
+
+ pa->task = NULL;
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Trying to open NFC device\n");
+ pa->pnd = nfc_open (context, NULL);
+ if (NULL == pa->pnd)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Payment inititation: Unable to open nfc device\n");
+ pa->task = GNUNET_SCHEDULER_add_delayed (NFC_FAILURE_RETRY_FREQ,
+ &connect_nfc,
+ pa);
+ return;
+ }
+ if (0 > nfc_initiator_init (pa->pnd))
{
- printf ("Unable to init taler communication\n");
- return EXIT_FAILURE;
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to initialize NFC device: %s",
+ nfc_strerror (pa->pnd));
+ cleanup_payment (pa);
+ GNUNET_assert (payment_activity == pa);
+ payment_activity = NULL;
+ return;
}
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "NFC in operation %s / %s\n",
+ nfc_device_get_name (pa->pnd),
+ nfc_device_get_connstring (pa->pnd));
+ pa->task = GNUNET_SCHEDULER_add_now (&connect_target,
+ pa);
+}
+
+
+/**
+ * Callback to process a GET /check-payment request
+ *
+ * @param cls closure
+ * @param http_status HTTP status code for this request
+ * @param obj raw response body
+ * @param paid #GNUNET_YES if the payment is settled, #GNUNET_NO if not
+ * settled, #GNUNET_SYSERR on error
+ * (note that refunded payments are returned as paid!)
+ * @param refunded #GNUNET_YES if there is at least on refund on this payment,
+ * #GNUNET_NO if refunded, #GNUNET_SYSERR or error
+ * @param refunded_amount amount that was refunded, NULL if there
+ * was no refund
+ * @param taler_pay_uri the URI that instructs the wallets to process
+ * the payment
+ */
+static void
+check_payment_cb (void *cls,
+ unsigned int http_status,
+ const json_t *obj,
+ int paid,
+ int refunded,
+ struct TALER_Amount *refund_amount,
+ const char *taler_pay_uri)
+{
+ struct PaymentActivity *pa = cls;
+ (void) refunded;
+ (void) refund_amount;
+ (void) obj;
- // initialize product
- if (product_init (&product, CURRENCY) )
+ pa->cpo = NULL;
+ if (MHD_HTTP_OK != http_status)
{
- printf ("Unable to init product\n");
- return EXIT_FAILURE;
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Backend request to /check-payment failed: %u",
+ http_status);
+ cleanup_payment (pa);
+ GNUNET_assert (payment_activity == pa);
+ payment_activity = NULL;
+ return;
}
+ if (paid)
+ {
+ fprintf (stderr,
+ "FIXME: yield product here!\n");
+ /* FIXME: later: continue to offer Internet UNTIL
+ NFC device disconnects (if NFC connected) */
+ cleanup_payment (pa);
+ GNUNET_assert (payment_activity == pa);
+ payment_activity = NULL;
+ return;
+ }
+ else
+ {
+ /* Start to check for payment. Note that we do this even before
+ we talked successfully to the wallet via NFC because we MAY show the
+ QR code in the future and in that case the payment may happen
+ anytime even before the NFC communication succeeds. */
+ if ( (NULL == pa->cpo) &&
+ (NULL == pa->delay_task) )
+ {
+ pa->delay_task = GNUNET_SCHEDULER_add_delayed (MAX_HTTP_RETRY_FREQ,
+ &check_payment_again,
+ pa);
+ }
+ }
+ if (NULL == pa->taler_pay_uri)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Trying to talk to wallet to give it pay URI `%s'\n",
+ taler_pay_uri);
+ GNUNET_assert (NULL == pa->pnd);
+ pa->taler_pay_uri = GNUNET_strdup (taler_pay_uri);
+#if HAVE_QRENCODE_H
+ show_qrcode (taler_pay_uri);
+#endif
+ pa->task = GNUNET_SCHEDULER_add_now (&connect_nfc,
+ pa);
+ }
+}
- while (true)
+
+static void
+check_payment_again (void *cls)
+{
+ struct PaymentActivity *pa = cls;
+
+ pa->delay_task = NULL;
+ GNUNET_assert (NULL == pa->cpo);
+ pa->cpo = TALER_MERCHANT_check_payment (ctx,
+ backendBaseUrl,
+ pa->order_id,
+ NULL /* snack machine, no Web crap */,
+ BACKEND_POLL_TIMEOUT,
+ &check_payment_cb,
+ pa);
+}
+
+
+static void
+proposal_cb (void *cls,
+ unsigned int http_status,
+ enum TALER_ErrorCode ec,
+ const json_t *obj,
+ const char *order_id)
+{
+ (void) obj;
+ struct PaymentActivity *pa = cls;
+
+ pa->po = NULL;
+ if (MHD_HTTP_OK != http_status)
{
- printf ("Waiting for MBD input\n");
- printf ("Enter to simulate Snickers, x to quit\n");
- if (getchar () == 'x')
- break;
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Failed to setup order with backend: %u/%d\n",
+ http_status,
+ (int) ec);
+ cleanup_payment (pa);
+ GNUNET_assert (payment_activity == pa);
+ payment_activity = NULL;
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Backend successfully created order `%s'\n",
+ order_id);
+ pa->order_id = GNUNET_strdup (order_id);
+ pa->cpo = TALER_MERCHANT_check_payment (ctx,
+ backendBaseUrl,
+ pa->order_id,
+ NULL /* snack machine, no Web crap */,
+ GNUNET_TIME_UNIT_ZERO,
+ &check_payment_cb,
+ pa);
- // DEMO snickers
- product.amount = "0.1";
- product.product = "Snickers";
+}
- // create the order request
- taler_create_order_req (&product);
+static struct PaymentActivity *
+launch_payment (const struct Product *product)
+{
+ struct PaymentActivity *pa;
+ json_t *orderReq;
+ char *fulflmntUrl;
+ struct GNUNET_ShortHashCode uuid;
+ char *uuid_s;
- // create the order
- while (taler_create_order (curl, &product) )
- ;
+ /* We need to ensure that every fulfillment URL is unique;
+ most easily done by adding a random nonce, as we may
+ not have a reliable counter or clock on the machine */
+ GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
+ &uuid,
+ sizeof (uuid));
+ uuid_s = GNUNET_STRINGS_data_to_string_alloc (&uuid,
+ sizeof (uuid));
+ /* create the fulfillment url, e.g. "taler://fulfillment-success/Enjoy+your+ice+cream!"; */
+ GNUNET_asprintf (&fulflmntUrl,
+ "%s%s%s#%s",
+ fulfillmentUrl,
+ fulfillmentMsg,
+ product->description,
+ uuid_s);
+ GNUNET_free (uuid_s);
+ /* create the json object for the order request */
+ orderReq = json_pack ("{ s:s, s:o, s:s }",
+ "summary", product->description,
+ "amount", TALER_JSON_from_amount (&product->price),
+ "fulfillment_url", fulflmntUrl);
+ GNUNET_free (fulflmntUrl);
+ if (NULL == orderReq)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "json_pack failed (out of memory?)\n");
+ return NULL;
+ }
+ pa = GNUNET_new (struct PaymentActivity);
+ pa->po = TALER_MERCHANT_order_put (ctx,
+ backendBaseUrl,
+ orderReq,
+ &proposal_cb,
+ pa);
+ json_decref (orderReq);
+ if (NULL == pa->po)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "TALER_MERCHANT_order_put failed (out of memory?)\n");
+ GNUNET_free (pa);
+ return NULL;
+ }
+ return pa;
+}
- // store the order id into the struct
- product_set_order_id (&product);
- // store the url to check wheter the payment happened or not
- product_set_check_url (&product);
+static void
+start_read_keyboard (void);
- // check the payment status for the first time
- while (taler_check_payment_status (curl, &product) )
- ;
- // store the url to pay, to do this task the payment status has to be called before, because the url will be in the response
- product_set_pay_url (&product);
+static void
+read_keyboard_command (void *cls)
+{
+ (void) cls;
+ int input;
- // start a thread to send payment request to taler wallet
- pthread_t nfcThread;
- if (pthread_create (&nfcThread, NULL, start_nfc_transmission, NULL) )
+ keyboard_task = NULL;
+ input = getchar ();
+ if ( (EOF == input) ||
+ ('x' == (char) input) )
+ {
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ if ((char) input == 'c')
+ {
+ if (NULL != payment_activity)
+ {
+ cleanup_payment (payment_activity);
+ payment_activity = NULL;
+ }
+ else
{
- printf ("Could not create thread");
- return EXIT_FAILURE;
+ fprintf (stderr,
+ "No purchase activity pending\n");
}
+ start_read_keyboard ();
+ return;
+ }
+ if (NULL != payment_activity)
+ {
+ fprintf (stderr,
+ "Purchase activity already pending\n");
+ start_read_keyboard ();
+ return;
+ }
+ for (unsigned int i = 0; i < products_length; i++)
+ if (((char) input) == products[i].key)
+ {
+ payment_activity = launch_payment (&products[i]);
+ start_read_keyboard ();
+ return;
+ }
+ fprintf (stderr,
+ "Unknown command '%c'\n",
+ (char) input);
+ start_read_keyboard ();
+}
+
- // check the payment status, if paid exit while loop and end thread transmitting nfc messages
- while (! product.paid)
+static void
+start_read_keyboard ()
+{
+ struct GNUNET_DISK_FileHandle fh = { STDIN_FILENO };
+
+ GNUNET_assert (NULL == keyboard_task);
+ for (unsigned int i = 0; i < products_length; i++)
+ printf ("'%c' to buy %s\n",
+ products[i].key,
+ products[i].description);
+ printf ("'c' to cancel last purchase\n'x' to quit\n");
+ printf ("Waiting for keyboard input\n");
+ keyboard_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL,
+ &fh,
+ &read_keyboard_command,
+ NULL);
+}
+
+
+static void
+read_products (void *cls,
+ const char *section)
+{
+ struct Product tmpProduct;
+ char *tmpKey;
+
+ if (0 != strncmp (section,
+ "product-",
+ strlen ("product-")))
+ return;
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cls,
+ section,
+ "description",
+ &tmpProduct.description))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ section,
+ "description");
+ return;
+ }
+ if (GNUNET_OK !=
+ TALER_config_get_denom (cls,
+ section,
+ "price",
+ &tmpProduct.price))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ section,
+ "price");
+ GNUNET_free (tmpProduct.description);
+ return;
+ }
+ if (0 != strcasecmp (currency,
+ tmpProduct.price.currency))
+ {
+ GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
+ section,
+ "price",
+ "currency missmatch");
+ GNUNET_free (tmpProduct.description);
+ return;
+ }
+ if (GNUNET_OK ==
+ GNUNET_CONFIGURATION_get_value_string (cls,
+ section,
+ "key",
+ &tmpKey))
+ {
+ tmpProduct.key = tmpKey[0];
+ GNUNET_free (tmpKey);
+ }
+ else
+ {
+ /* no key */
+ tmpProduct.key = '\0';
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cls,
+ section,
+ "number",
+ &tmpProduct.number))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ section,
+ "number");
+ GNUNET_free (tmpProduct.description);
+ return;
+ }
+ GNUNET_array_append (products,
+ products_length,
+ tmpProduct);
+}
+
+
+static void
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
+ (void) cls;
+ (void) args;
+ (void) cfgfile;
+
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ "taler",
+ "currency",
+ &currency))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "taler",
+ "currency");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ "taler-mdb",
+ "backend-base-url",
+ &backendBaseUrl))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "taler-mdb",
+ "backend-base-url");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ {
+ char *auth;
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ "taler-mdb",
+ "backend-authorization",
+ &auth))
{
- printf ("Order payment processing\n");
- fflush (stdout);
- sleep (5);
- while (taler_check_payment_status (curl, &product) )
- ;
- // set the boolean paid member of ProductOrder struct
- product_set_paid_status (&product);
- printf ("Payment status paid: %s\n\n", (product.paid ? "true" :
- "false") );
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "taler-mdb",
+ "backend-authorization");
+ global_ret = EXIT_FAILURE;
+ return;
}
- printf ("Order no.: %s paid!\n\n", product.orderID);
+ GNUNET_asprintf (&authorization,
+ "%s: %s",
+ MHD_HTTP_HEADER_AUTHORIZATION,
+ auth);
+ GNUNET_free (auth);
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ "taler-mdb",
+ "fulfillment-url",
+ &fulfillmentUrl))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "taler-mdb",
+ "fulfillment-url");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ if (GNUNET_OK !=
+ GNUNET_CONFIGURATION_get_value_string (cfg,
+ "taler-mdb",
+ "fulfillment-msg",
+ &fulfillmentMsg))
+ {
+ GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR,
+ "taler-mdb",
+ "fulfillment-msgcurrency");
+ global_ret = EXIT_FAILURE;
+ return;
+ }
+ GNUNET_CONFIGURATION_iterate_sections (cfg,
+ &read_products,
+ (void *) cfg);
+ GNUNET_assert (NULL != products);
- // send cancel request to nfc thread
- while (pthread_cancel (nfcThread) != 0)
+ GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+ NULL);
+ /* initialize nfc */
+ nfc_init (&context);
+ if (NULL == context)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+ "Unable to initialize nfc (nfc_init() failed)\n");
+ global_ret = EXIT_FAILURE;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+
+ /* initialize HTTP client */
+ ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
+ &rc);
+ rc = GNUNET_CURL_gnunet_rc_create (ctx);
+ /* setup authorization */
+ GNUNET_assert (GNUNET_OK ==
+ GNUNET_CURL_append_header (ctx,
+ authorization));
+#if HAVE_QRENCODE_H
+ /* open the framebuffer device */
+ qrDisplay.devicefd = open (FRAMEBUFFER_DEVICE,
+ O_RDWR);
+ if (0 < qrDisplay.devicefd)
+ {
+ /* read information about the screen */
+ ioctl (qrDisplay.devicefd,
+ FBIOGET_VSCREENINFO,
+ &qrDisplay.var_info);
+
+ /* store current screeninfo for reset */
+ memcpy (&qrDisplay.orig_vinfo,
+ &qrDisplay.var_info,
+ sizeof(struct fb_var_screeninfo));
+
+ if (16 != qrDisplay.var_info.bits_per_pixel)
{
- printf ("Error sending cancel request to thread for nfc transmission");
+ /* Change variable info to 16 bit per pixel */
+ qrDisplay.var_info.bits_per_pixel = 16;
+ if (0 > ioctl (qrDisplay.devicefd,
+ FBIOPUT_VSCREENINFO,
+ &qrDisplay.var_info))
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Error setting display bpp to 16\n");
+ return;
+ }
}
- void*res;
- if (pthread_join (nfcThread, &res) == 0)
+
+ /* Get fixed screen information */
+ if (0 > ioctl (qrDisplay.devicefd,
+ FBIOGET_FSCREENINFO,
+ &qrDisplay.fix_info))
{
- printf ("Thread for nfc transmission finished\n");
- fflush (stdout);
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "Error reading fixed display information\n");
+ return;
}
- else if (res == PTHREAD_CANCELED)
+
+ /* get pointer onto frame buffer */
+ qrDisplay.memory = mmap (NULL,
+ qrDisplay.fix_info.smem_len,
+ PROT_READ | PROT_WRITE, MAP_SHARED,
+ qrDisplay.devicefd,
+ 0);
+
+ /* open backlight file to turn display backlight on and off */
+ if (0 > qrDisplay.devicefd)
{
- printf ("Thread for nfc transmission finished\n");
- fflush (stdout);
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "failed to map display memory\n");
+ return;
}
- // reset the product
- product_reset (&product);
+ memset (qrDisplay.memory,
+ 0xFF,
+ qrDisplay.var_info.xres * qrDisplay.var_info.yres
+ * sizeof (uint16_t));
+ qrDisplay.backlightfd = open (
+ "/sys/class/backlight/soc:backlight/brightness", O_WRONLY);
+ if (0 > qrDisplay.backlightfd)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "failed to load \"/sys/class/backlight/soc:backlight/brightness\", display backlight will not be changed\n");
+ }
+ else
+ {
+ write (qrDisplay.backlightfd, "0", 1);
+ }
}
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+ "open(), could not open framebuffer device %s\n",
+ FRAMEBUFFER_DEVICE);
+ }
+#endif
+
+ start_read_keyboard ();
+}
- // clear all initialized data
- nfc_exit (context);
- product_exit (&product);
- taler_exit (&curl);
- return EXIT_SUCCESS;
+int
+main (int argc,
+ char*const*argv)
+{
+ struct termios tty_opts_backup, tty_opts_raw;
+ int ret;
+ /* the available command line options */
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+ int have_tty;
+ have_tty = isatty (STDIN_FILENO);
+ if (have_tty)
+ {
+ if (0 != tcgetattr (STDIN_FILENO, &tty_opts_backup))
+ fprintf (stderr,
+ "Failed to get terminal discipline\n");
+ tty_opts_raw = tty_opts_backup;
+ tty_opts_raw.c_lflag &= ~(ECHO | ECHONL | ICANON);
+ if (0 != tcsetattr (STDIN_FILENO, TCSANOW, &tty_opts_raw))
+ fprintf (stderr,
+ "Failed to set terminal discipline\n");
+ }
+ ret = GNUNET_PROGRAM_run (argc,
+ argv,
+ "taler-mdb",
+ "This is an application for snack machines to pay with GNU Taler via nfc.\n",
+ options,
+ &run,
+ NULL);
+ if (have_tty)
+ {
+ // Restore previous TTY settings
+ if (0 != tcsetattr (STDIN_FILENO, TCSANOW, &tty_opts_backup))
+ fprintf (stderr,
+ "Failed to restore terminal discipline\n");
+ }
+ if (GNUNET_OK != ret)
+ return 1;
+ return global_ret;
}
diff --git a/src/nfc.c b/src/nfc.c
deleted file mode 100644
index 20cdb01..0000000
--- a/src/nfc.c
+++ /dev/null
@@ -1,131 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2019 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more
-details.
-
- You should have received a copy of the GNU General Public License
-along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-
-/**
-* @file nfc.c
-* @brief functions used to comunicate over nfc interface
-* @author BOSS Marco
-*/
-
-#include <string.h>
-#include <unistd.h>
-
-#include "nfc.h"
-#include "wallet.h"
-
-// upper and lower bounds for mifare targets uid length
-#define UID_LEN_UPPER 7
-#define UID_LEN_LOWER 4
-
-
-int
-nfc_transmit (nfc_context *context, const char *talerPayUrl, size_t urlSize)
-{
- nfc_device *pnd;
-
- pnd = nfc_open (context, NULL); // NULL could be replaced with connstring if the correct is known
- if (! pnd)
- {
- printf ("Unable to open NFC device\n");
- return EXIT_FAILURE;
- }
-
- // initialize device as reader
- if (nfc_initiator_init (pnd) < 0)
- {
- nfc_perror (pnd, "nfc_initiator_init");
- nfc_close (pnd);
- return EXIT_FAILURE;
- }
-
- printf ("Device %s opened: '%s'\n\n", nfc_device_get_name (pnd),
- nfc_device_get_connstring (pnd) );
-
- nfc_target nt;
-
- // connect to a target device
- if (nfc_connect_target (pnd, &nt) )
- {
- nfc_close (pnd);
- return EXIT_FAILURE;
- }
-
- // send the message to the wallet
- if (wallet_transmit (pnd, talerPayUrl, urlSize) )
- {
- // the transmition failed, the target has to be reselected when using MIFARE as defined in libnfc --> exit
- nfc_close (pnd);
- return EXIT_FAILURE;
- }
-
- // clean up
- nfc_initiator_deselect_target (pnd);
- nfc_close (pnd);
-
- return EXIT_SUCCESS;
-}
-
-
-int
-nfc_connect_target (nfc_device *pnd, nfc_target *nt)
-{
- const nfc_modulation nmMifare[] = { {
- .nmt = NMT_ISO14443A,
- .nbr = NBR_106,
- } };
-
- printf ("nfc_connect_target: trying to connect to target\n");
- int ctr = 2;
- while (ctr > 0)
- {
- // set uid lenght to zero ( in case of second selecting the length still has the old value )
- nt->nti.nai.szUidLen = 0;
- if (nfc_initiator_select_passive_target (pnd, nmMifare[0], NULL, 0, nt) <=
- 0)
- {
- printf ("nfc_connect_target: failed to connect\n");
- }
- else if ( (nt->nti.nai.szUidLen > UID_LEN_UPPER) ||
- (nt->nti.nai.szUidLen < UID_LEN_LOWER) )
- {
- printf ("nfc_connect_target: failed to connect\n");
- }
- else
- {
- printf ("nfc_connect_target: Target selected!\n");
- nfc_display_target_uid (nt);
- return EXIT_SUCCESS;
- }
- sleep (1);
- ctr--;
- }
- return EXIT_FAILURE;
-}
-
-
-void
-nfc_display_target_uid (nfc_target *nt)
-{
- printf ("UID: ");
- for (unsigned int uidPos = 0; uidPos < nt->nti.nai.szUidLen; uidPos++)
- {
- printf ("%.2x ", nt->nti.nai.abtUid[uidPos]);
- }
- printf ("\n\n");
-}
diff --git a/src/nfc.h b/src/nfc.h
deleted file mode 100644
index a89d370..0000000
--- a/src/nfc.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2019 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more
-details.
-
- You should have received a copy of the GNU General Public License
-along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-
-/**
-* @file nfc.h
-* @brief functions used to comunicate over nfc interface
-* @author BOSS Marco
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <nfc/nfc.h>
-
-int nfc_transmit (nfc_context *context, const char *talerPayUrl, size_t
- urlSize);
-
-int nfc_connect_target (nfc_device *pnd, nfc_target *nt);
-
-void nfc_display_target_uid (nfc_target *nt);
diff --git a/src/product.c b/src/product.c
deleted file mode 100644
index 522a38c..0000000
--- a/src/product.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2019 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more
-details.
-
- You should have received a copy of the GNU General Public License
-along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-
-/**
-* @file product.c
-* @brief defined a product order with the attributes of the product and
-the links used to communicate with taler. Provides setter methods to set
-the attributes.
-* @author BOSS Marco
-*/
-
-#include <string.h>
-
-#include "product.h"
-#include "configuration.h"
-#include "communication.h"
-
-
-void
-product_reset (ProductOrder *product)
-{
- product->amount = NULL;
- product->product = NULL;
- product->paid = false;
-}
-
-
-int
-product_init (ProductOrder *product, const char *currency)
-{
- if (! product)
- {
- printf ("product_init: product order struct must be provided\n");
- return EXIT_FAILURE;
- }
-
- // malloc for every string member with size 1, every other func just calls realloc, because this struct gets used over and over again
- product->response = malloc (sizeof(TalerResponse) );
- if (! product->response)
- {
- printf ("product_init: unable to allocate memory for response struct\n");
- return EXIT_FAILURE;
- }
- if (taler_alloc_string (&(product->response->string), 1) )
- return EXIT_FAILURE;
- if (taler_alloc_string (&(product->orderID), 1) )
- return EXIT_FAILURE;
- if (taler_alloc_string (&(product->orderRequest), 1) )
- return EXIT_FAILURE;
- if (taler_alloc_string (&(product->payUrl), 1) )
- return EXIT_FAILURE;
- if (taler_alloc_string (&(product->checkUrl), 1) )
- return EXIT_FAILURE;
- if (taler_alloc_string (&(product->currency), strlen (currency) + 1) )
- return EXIT_FAILURE;
- strcpy (product->currency, currency);
- product->amount = NULL;
- product->product = NULL;
- product->paid = false;
-
- return EXIT_SUCCESS;
-}
-
-
-void
-product_exit (ProductOrder *product)
-{
- free (product->response->string);
- free (product->response);
- free (product->orderID);
- free (product->orderRequest);
- free (product->payUrl);
- free (product->checkUrl);
- free (product->currency);
- product->amount = NULL;
- product->product = NULL;
- product->paid = false;
-}
-
-
-int
-product_set_check_url (ProductOrder *product)
-{
- size_t len = strlen (BACKEND_BASE_URL) + strlen (CHECK);
- char *url = realloc (product->checkUrl, len + strlen (ORDER_CHECK) + strlen (
- product->orderID) + 1);
- if (! url)
- {
- printf ("could not allocate memory for order url\n");
- return EXIT_FAILURE;
- }
-
- product->checkUrl = url;
- sprintf (product->checkUrl, "%s%s%s%s", BACKEND_BASE_URL, CHECK, ORDER_CHECK,
- product->orderID);
- printf ("Url to check payment: %s\n\n", product->checkUrl);
-
- return EXIT_SUCCESS;
-}
-
-
-int
-product_set_order_id (ProductOrder *product)
-{
- return taler_parse_json (product->response, JSON_ORDER_ID,
- &(product->orderID), false);
-}
-
-
-int
-product_set_pay_url (ProductOrder *product)
-{
- return taler_parse_json (product->response, JSON_PAY_URI, &(product->payUrl),
- false);
-}
-
-
-int
-product_set_paid_status (ProductOrder *product)
-{
- char *temp = NULL;
- if (taler_alloc_string (&temp, 1) == EXIT_SUCCESS)
- {
- taler_parse_json (product->response, JSON_PAID, &temp, true);
- if (strcmp (temp, "true") == 0)
- product->paid = true;
- free (temp);
- return EXIT_SUCCESS;
- }
-
- return EXIT_FAILURE;
-}
diff --git a/src/product.h b/src/product.h
deleted file mode 100644
index c091e63..0000000
--- a/src/product.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2019 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more
-details.
-
- You should have received a copy of the GNU General Public License
-along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-
-/**
-* @file product.h
-* @brief defined a product order with the attributes of the product and
-the links used to communicate with taler. Provides setter methods to set
-the attributes.
-* @author BOSS Marco
-*/
-
-#ifndef PRODUCT_H
-#define PRODUCT_H
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdbool.h>
-
-typedef struct TalerResponse
-{
- char *string;
- size_t size;
-} TalerResponse;
-
-typedef struct ProductOrder
-{
- char *product;
- char *currency;
- char *amount;
- char *orderRequest;
- char *orderID;
- char *checkUrl;
- char *payUrl;
- bool paid;
- TalerResponse *response;
-} ProductOrder;
-
-int product_init (ProductOrder *product, const char*currency);
-
-void product_exit (ProductOrder *product);
-
-void product_reset (ProductOrder *product);
-
-int product_set_check_url (ProductOrder *product);
-
-int product_set_order_id (ProductOrder *product);
-
-int product_set_pay_url (ProductOrder *product);
-
-int product_set_paid_status (ProductOrder *product);
-
-#endif // PRODUCT_H
diff --git a/src/taler-mdb b/src/taler-mdb
new file mode 100755
index 0000000..e67dc2b
--- /dev/null
+++ b/src/taler-mdb
Binary files differ
diff --git a/src/target.mk b/src/target.mk
deleted file mode 100644
index bb77a0f..0000000
--- a/src/target.mk
+++ /dev/null
@@ -1,6 +0,0 @@
-TARGET_USER = pi
-TARGET_ADDRESS = 192.168.3.10
-SSH_PORT = 22
-CROSS_TOOLS = $(HOME)/embedded/x-tools
-CROSS = armv8-rpi3-linux-gnueabihf
-TARGET_ARCH = armv8
diff --git a/src/wallet.c b/src/wallet.c
deleted file mode 100644
index 321f751..0000000
--- a/src/wallet.c
+++ /dev/null
@@ -1,147 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2019 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more
-details.
-
- You should have received a copy of the GNU General Public License
-along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-
-/**
-* @file wallet.c
-* @brief functions to communicate with taler wallet over nfc
-* @author BOSS Marco
-*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include "wallet.h"
-
-
-int
-wallet_select_aid (nfc_device *pnd)
-{
- uint8_t response[] = { 0x00, 0x00 };
-
- int size = sizeof(select_file) + sizeof(taler_aid);
- uint8_t message[size];
- if (concat_message (select_file, sizeof(select_file), taler_aid, message,
- size) )
- return EXIT_FAILURE;
-
- printf ("wallet_select_aid: Selecting Taler apk using AID: ");
- for (unsigned int i = 0; i < sizeof(taler_aid); ++i)
- printf ("%.2x", taler_aid[i]);
- printf ("\n");
-
- if (nfc_initiator_transceive_bytes (pnd, message, size, response,
- sizeof(response), TRANSMIT_TIMEOUT) < 0)
- {
- printf ("wallet_select_aid: Failed to select apk\n\n");
- return EXIT_FAILURE;
- }
-
- return check_response (response, sizeof(response) );
-}
-
-
-int
-wallet_put_message (nfc_device *pnd, const char *msg, size_t msgSize)
-{
- uint8_t response[] = { 0x00, 0x00 };
-
- int size = sizeof(put_data) + msgSize;
- uint8_t message[size];
- if (concat_message (put_data, sizeof(put_data), (const uint8_t*) msg,
- message, size) )
- return EXIT_FAILURE;
-
- printf ("wallet_put_messsage: Sending 'PUT DATA' command to wallet\n");
-
- if (nfc_initiator_transceive_bytes (pnd, message, size, response,
- sizeof(response), TRANSMIT_TIMEOUT) < 0)
- {
- printf ("wallet_put_message: Failed to put message\n\n");
- return EXIT_FAILURE;
- }
-
- return check_response (response, sizeof(response) );
-}
-
-
-int
-wallet_transmit (nfc_device *pnd, const char *msg, size_t msgLen)
-{
- if (! msg)
- {
- printf ("wallet_transmit: No message to send\n\n");
- return EXIT_FAILURE;
- }
-
- if (wallet_select_aid (pnd) )
- return EXIT_FAILURE;
- printf ("wallet_transmit: Taler wallet apk selected\n\n");
- if (wallet_put_message (pnd, msg, msgLen) )
- return EXIT_FAILURE;
- printf ("wallet_transmit: Transmitted message to taler wallet\n\n");
-
- return EXIT_SUCCESS;
-}
-
-
-int
-check_response (uint8_t *response, uint8_t responseLen)
-{
- if (strcmp ((char*) response, APDU_SUCCESS) == 0)
- {
- printf ("Transmission success\n");
- }
- else
- {
- printf ("Transmission failure, return code: ");
- for (uint8_t i = 0; i < responseLen; ++i)
- {
- printf ("%.2x ", response[i]);
- }
- printf ("\n");
- return EXIT_FAILURE;
- }
-
- return EXIT_SUCCESS;
-}
-
-
-int
-concat_message (const uint8_t*command, size_t commandSize, const
- uint8_t*message, uint8_t *retMsg, size_t returnSize)
-{
- if (! command || ! message)
- {
- printf ("concat_message: command and message can't be null");
- return EXIT_FAILURE;
- }
-
- uint8_t i = 0;
- for (; i < commandSize; ++i)
- {
- retMsg[i] = command[i];
- }
- for (; i < returnSize; ++i)
- {
- retMsg[i] = message[i - commandSize];
- }
-
- return EXIT_SUCCESS;
-}
diff --git a/src/wallet.h b/src/wallet.h
deleted file mode 100644
index 5944b5d..0000000
--- a/src/wallet.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/*
- This file is part of TALER
- Copyright (C) 2019 GNUnet e.V.
-
- TALER is free software; you can redistribute it and/or modify it under the
- terms of the GNU General Public License as published by the Free Software
- Foundation; either version 3, or (at your option) any later version.
-
- TALER is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY; without even the implied warranty of MERCHANTABILITY or
-FITNESS FOR
- A PARTICULAR PURPOSE. See the GNU General Public License for more
-details.
-
- You should have received a copy of the GNU General Public License
-along with
- TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
-*/
-
-/**
-* @file wallet.h
-* @brief functions to communicate with taler wallet over nfc
-* @author BOSS Marco
-*/
-
-#ifndef WALLET_H
-#define WALLET_H
-
-#include <nfc/nfc.h>
-
-
-// New AID
-// static uint8_t taler_aid[] = { 0xF0, 0x00, 0x54, 0x41, 0x4c, 0x45, 0x52 };
-
-// Demo AID until uptade
-static const uint8_t taler_aid[] = { 0xA0, 0x00, 0x00, 0x02, 0x47, 0x10, 0x01 };
-
-#define TRANSMIT_TIMEOUT 500
-
-// APDU commands
-#define APDU_SUCCESS "\x90\x00"
-static const uint8_t select_file[] = { 0x00, 0xA4, 0x04, 0x00, 0x07 };
-static const uint8_t put_data[] = { 0x00, 0xDA, 0x01, 0x00, 0x7c, 0x01 };
-
-int wallet_select_aid (nfc_device *pnd);
-
-int wallet_put_message (nfc_device *pnd, const char *msg, size_t msgSize);
-
-int wallet_transmit (nfc_device*pnd, const char *msg, size_t msgLen);
-
-int concat_message (const uint8_t*command, size_t commandSize, const
- uint8_t *message, uint8_t *retMsg, size_t returnSize);
-
-int check_response (uint8_t *response, uint8_t responseLen);
-
-#endif // WALLET_H
diff --git a/taler.conf b/taler.conf
new file mode 100644
index 0000000..4c34022
--- /dev/null
+++ b/taler.conf
@@ -0,0 +1,43 @@
+[taler]
+currency = TESTKUDOS
+
+[taler-mdb]
+backend-base-url = http://backend.test.taler.net/
+backend-authorization = ApiKey sandbox
+# taler url for success message (see taler documentation)
+fulfillment-url = taler://fulfillment-success
+# alternative url (see taler documentation)
+#fulfillment-url = https(s)://
+# Message to diplay after purchase is completed,
+# will be concatenated with product
+# must be url - utf8 encoded
+fulfillment-msg = /Enjoy+your+
+
+#Products
+#end declaration
+
+[product-3]
+description = KitKat
+price = TESTKUDOS:0.1
+key = k
+number = 4
+
+[product-2]
+description = Mars
+price = TESTKUDOS:0.1
+key = m
+number = 3
+#twix
+
+[product-1]
+description = Twix
+price = TESTKUDOS:0.1
+key = t
+number = 2
+#snickers
+
+[product-0]
+description = Snickers
+price = TESTKUDOS:0.1
+key = s
+number = 1