diff options
author | Boss Marco <bossm8@students.bfh.ch> | 2019-11-18 21:09:39 +0100 |
---|---|---|
committer | Boss Marco <bossm8@students.bfh.ch> | 2019-11-18 21:09:39 +0100 |
commit | a267c2dc1633f2231391b54362b088ece1e1758d (patch) | |
tree | e80344335250a5b0ea3d795b6494b3fb74c5fa45 | |
parent | 345aeee5f72032e04031382db1c512707c1cceb4 (diff) | |
parent | e56ae2fb3292a76fa2328beb55bc586c371f9ca3 (diff) | |
download | taler-mdb-a267c2dc1633f2231391b54362b088ece1e1758d.tar.gz taler-mdb-a267c2dc1633f2231391b54362b088ece1e1758d.tar.bz2 taler-mdb-a267c2dc1633f2231391b54362b088ece1e1758d.zip |
merged refactor
-rw-r--r-- | .gitignore | 5 | ||||
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | README | 5 | ||||
-rw-r--r-- | configure.ac | 157 | ||||
-rw-r--r-- | contrib/uncrustify.cfg | 19 | ||||
-rw-r--r-- | src/Makefile.am | 21 | ||||
-rw-r--r-- | src/communication.c | 251 | ||||
-rw-r--r-- | src/communication.h | 52 | ||||
-rw-r--r-- | src/configuration.h | 53 | ||||
-rw-r--r-- | src/main.c | 1166 | ||||
-rw-r--r-- | src/nfc.c | 131 | ||||
-rw-r--r-- | src/nfc.h | 35 | ||||
-rw-r--r-- | src/product.c | 148 | ||||
-rw-r--r-- | src/product.h | 68 | ||||
-rwxr-xr-x | src/taler-mdb | bin | 0 -> 108040 bytes | |||
-rw-r--r-- | src/target.mk | 6 | ||||
-rw-r--r-- | src/wallet.c | 147 | ||||
-rw-r--r-- | src/wallet.h | 56 | ||||
-rw-r--r-- | taler.conf | 43 |
19 files changed, 1279 insertions, 1086 deletions
@@ -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 \ @@ -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 @@ -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", + ¤cy)) + { + 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 Binary files differnew file mode 100755 index 0000000..e67dc2b --- /dev/null +++ b/src/taler-mdb 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 |