summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--configure.ac109
-rw-r--r--src/Makefile.am3
-rw-r--r--src/main.c359
-rw-r--r--src/nfc.c2
5 files changed, 350 insertions, 125 deletions
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/configure.ac b/configure.ac
index 0551c7c..36a65c3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -68,10 +68,117 @@ AC_CHECK_FUNCS([strstr])
+# Save before checking for libraries
+LIBS_SAVE=$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
-LIBS_SAVE=$LIBS
+
# check for libgnurl
# libgnurl
diff --git a/src/Makefile.am b/src/Makefile.am
index 3105b63..9e157b4 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,6 +13,9 @@ taler_nfc_SOURCES = \
communication.c communication.h \
main.c
taler_nfc_LDADD = \
+ -ltalermerchant \
+ -ltalerutil \
+ -lgnunetutil \
-ljansson \
-lnfc \
-lpthread \
diff --git a/src/main.c b/src/main.c
index 4ff8a5d..e55d2b3 100644
--- a/src/main.c
+++ b/src/main.c
@@ -16,14 +16,12 @@ 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 ...
*/
-
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -33,27 +31,51 @@ along with
#include <curl/curl.h>
#include <gnunet/platform.h>
#include <gnunet/gnunet_util_lib.h>
+#include <taler/taler_merchant_service.h>
#include "nfc.h"
#include "communication.h"
#include "configuration.h"
#include "product.h"
-ProductOrder product;
+static int global_ret;
+
+static struct GNUNET_SCHEDULER_Task *super_task;
+
+static struct GNUNET_CURL_Context *ctx;
+
+static struct GNUNET_CURL_RescheduleContext *;
+
+struct PaymentActivity
+{
+ ProductOrder product;
+
+ struct TALER_MERCHANT_PollPaymentOperation *ppo;
+
+ struct TALER_MERCHANT_ProposalOperation *po;
+
+ nfc_device *pnd;
+};
+
nfc_context *context;
-void *_SNACK_start_nfc_transmission (void *ignored)
+
+static struct PaymentActivity *payment_activity;
+
+
+static void *
+start_nfc_transmission (void *ignored)
{
/* supress warning about unused variable */
(void) ignored;
- if ( pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL) != 0 )
+ if (pthread_setcanceltype (PTHREAD_CANCEL_ASYNCHRONOUS, NULL) != 0)
{
printf ("Error setting thread cancelling type\n");
}
/* start endless transmission loop (until threads gets cancelled) */
- while ( 1 )
+ while (1)
{
if ( pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL) != 0 )
{
@@ -69,67 +91,58 @@ void *_SNACK_start_nfc_transmission (void *ignored)
return EXIT_SUCCESS;
}
-int main (int argc, char*const*argv)
-{
- CURL *curl;
- char*cfgFile;
- struct GNUNET_CONFIGURATION_Handle *cfgHandle;
-
- /* prepare config file name */
- cfgFile = GNUNET_malloc (strlen (SNACK_DEFAULT_CONFIG_FILE) + 1);
- strcpy (cfgFile, SNACK_DEFAULT_CONFIG_FILE);
- /* the available command line options */
- struct GNUNET_GETOPT_CommandLineOption options[] = {
- GNUNET_GETOPT_option_help (
- "This is an application for snack machines with nfc. Running with GNU taler.\n"
- "Current taler wallet AID: F00054414c4552\n"),
- GNUNET_GETOPT_option_cfgfile (&cfgFile),
- GNUNET_GETOPT_OPTION_END
- };
- /* parse the command line */
- if ( GNUNET_GETOPT_run ("taler-mdb\n", options, argc, argv) <= 0 )
+static void
+shutdown_task (void *cls)
+{
+ (void) cls;
+ /* clear all initialized data */
+ if (NULL != context)
+ nfc_exit (context);
+ if (NULL != product)
+ SNACK_product_exit (&product);
+ if (NULL != curl)
+ SNACK_taler_exit (&curl);
+ if (NULL != super_task)
+ GNUNET_SCHEDULER_cancel (super_task);
+ if (NULL != ctx)
{
- GNUNET_free (cfgFile);
- return EXIT_SUCCESS;
+ GNUNET_CURL_fini (ctx);
+ ctx = NULL;
}
-
- /* setup logger */
- GNUNET_assert
- (GNUNET_OK == GNUNET_log_setup ("taler-mdb", "DEBUG", NULL)); // "taler-mdb.log"));
-
- /* load config file */
- cfgHandle = GNUNET_CONFIGURATION_create ();
- if (GNUNET_OK != GNUNET_CONFIGURATION_parse (cfgHandle, cfgFile))
+ if (NULL != rc)
{
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "main: unable to load config file %s\n", cfgFile);
- GNUNET_CONFIGURATION_destroy (cfgHandle);
- GNUNET_free (cfgFile);
- return EXIT_FAILURE;
+ GNUNET_CURL_gnunet_rc_destroy (rc);
+ rc = NULL;
}
+}
+
+static void
+run (void *cls,
+ char *const *args,
+ const char *cfgfile,
+ const struct GNUNET_CONFIGURATION_Handle *cfg)
+{
/* inizialize product */
- if ( SNACK_product_init (&product, cfgHandle) )
+ if ( SNACK_product_init (&product, cfg) )
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"main: unable to init product structure\n");
- GNUNET_CONFIGURATION_destroy (cfgHandle);
- GNUNET_free (cfgFile);
- return EXIT_FAILURE;
+ global_ret = EXIT_FAILURE;
+ return;
}
-
- /* free cfg because its not needed anymore ( everything is now stored in product ) */
- GNUNET_CONFIGURATION_destroy (cfgHandle);
- GNUNET_free (cfgFile);
-
+ GNUNET_SCHEDULER_add_shutdown (&shutdown_task,
+ NULL);
/* initialize nfc */
nfc_init (&context);
if ( ! context )
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "main: unable to init nfc\n");
- return EXIT_FAILURE;
+ global_ret = EXIT_FAILURE;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
}
/* inizialize taler */
@@ -137,103 +150,205 @@ int main (int argc, char*const*argv)
{
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
"main: nable to init taler communication\n");
- return EXIT_FAILURE;
+ global_ret = EXIT_FAILURE;
+ GNUNET_SCHEDULER_shutdown ();
+ return;
}
+ ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule,
+ &is.rc);
+ rc = GNUNET_CURL_gnunet_rc_create (ctx);
+ start_read_keyboard ();
+}
+
+
+static void
+start_read_keyboard ()
+{
+ struct GNUNET_DISK_FileHandle fh = { FILENO_STDIN };
+
+ printf ("Waiting for MBD input\n");
+ printf ("Enter to simulate Snickers, x to quit\n");
+ super_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_ABS,
+ fh,
+ &read_product_info,
+ NULL);
+}
- /* superloop */
- while ( true )
- {
- printf ("Waiting for MBD input\n");
- printf ("Enter to simulate Snickers, x to quit\n");
- if ( getchar () == 'x' )
- break;
- /* DEMO snickers */
+static void
+read_product_info (void *cls)
+{
+ int input;
+
+ super_task = NULL;
+ input = getchar ();
+ if ( (EOF == input) ||
+ ('x' == (char) input) )
+ {
+ GNUNET_SCHEDULER_shutdown ();
+ return;
+ }
+ switch ((char) input)
+ {
+ case 'c':
+ if (NULL != payment_activity)
+ {
+ cancel_payment (payment_activity);
+ payment_activity = NULL;
+ }
+ break;
+ case 's':
+ GNUNET_assert (NULL == payment_activity);
product.amount = "0.1";
product.product = "Snickers";
+ payment_activity = launch_payment (&product);
+ break;
+ }
+ start_read_keyboard ();
+}
- /* create the order request */
- SNACK_taler_create_order_req (&product);
+static void
+cancel_payment (struct PaymentActivity *pa)
+{
+ if (NULL != pa->po)
+ TALER_MERCHANT_proposal_cancel (pa->po);
+ GNUNET_free (pa);
+}
- /* create the order */
- while ( SNACK_taler_create_order (curl, &product) )
- ;
- /* store the order id into the struct */
- SNACK_product_set_order_id (&product);
+static void
+proposal_cb (void *cls,
+ unsigned int http_status,
+ enum TALER_ErrorCode ec,
+ const json_t *obj,
+ const char *order_id)
+{
+ struct PaymentActivity *pa = cls;
- /* store the url to check wheter the payment happened or not */
- SNACK_product_set_check_url (&product);
+ pa->po = NULL;
+ // use(order_id);
+ // start_nfc_transmission(pa);
+ // pa->pnd = open();
+ //
+}
- /* check the payment status for the first time */
- while ( SNACK_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 */
- SNACK_product_set_pay_url (&product);
+static struct PaymentActivity *
+launch_payment (const Product *product)
+{
+ struct PaymentActivity *pa;
+
+ pa = GNUNET_new (struct PaymentActivity);
+ pa->product = *product;
+ // SEE: SNACK_taler_create_order_req (&product);
+ order = json ();
+ pa->po = TALER_MERCHANT_order_put (ctx,
+ backend_url,
+ order,
+ &proposal_cb,
+ pa);
+}
- /* start a thread to send payment request to taler wallet */
- pthread_t nfcThread;
- if ( pthread_create (&nfcThread, NULL, _SNACK_start_nfc_transmission,
- NULL) )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "main: thread creation failed\n");
- return EXIT_FAILURE;
- }
+static void foo ()
+{
+ /* create the order request */
+ SNACK_taler_create_order_req (&product);
- /* check the payment status, if paid exit while loop and end thread transmitting nfc messages */
- while ( ! product.paid )
- {
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "main: order payment processing\n");
- sleep (5);
+ /* create the order */
+ while ( SNACK_taler_create_order (curl, &product) )
+ ;
- while ( SNACK_taler_check_payment_status (curl, &product) )
- ;
+ /* store the order id into the struct */
+ SNACK_product_set_order_id (&product);
- /* set the boolean paid member of ProductOrder struct */
- SNACK_product_set_paid_status (&product);
+ /* store the url to check wheter the payment happened or not */
+ SNACK_product_set_check_url (&product);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "main: payment status paid: %s\n",
- (product.paid ? "true" : "false") );
- }
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "main: order no.: %s paid!\n",
- product.orderID);
+ /* check the payment status for the first time */
+ while ( SNACK_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 */
+ SNACK_product_set_pay_url (&product);
- /* -----------------
- Here comes the code for releasing the product
- ----------------- */
+ /* start a thread to send payment request to taler wallet */
+ pthread_t nfcThread;
+ if ( pthread_create (&nfcThread,
+ NULL,
+ &start_nfc_transmission,
+ NULL) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "main: thread creation failed\n");
+ return EXIT_FAILURE;
+ }
+ /* check the payment status, if paid exit while loop and end thread transmitting nfc messages */
+ while ( ! product.paid )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "main: order payment processing\n");
+ sleep (5);
- /* send cancel request to nfc thread */
- while ( pthread_cancel (nfcThread) != 0 )
- {
- printf ("Error sending cancel request to thread for nfc transmission");
- }
+ while ( SNACK_taler_check_payment_status (curl, &product) )
+ ;
- void*res;
- if ( pthread_join (nfcThread, &res) == 0 )
- {
- printf ("Thread for nfc transmission finished\n");
- fflush (stdout);
- }
- else if ( res == PTHREAD_CANCELED )
- {
- printf ("Thread for nfc transmission finished\n");
- fflush (stdout);
- }
+ /* set the boolean paid member of ProductOrder struct */
+ SNACK_product_set_paid_status (&product);
+
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "main: payment status paid: %s\n",
+ (product.paid ? "true" : "false") );
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO, "main: order no.: %s paid!\n",
+ product.orderID);
+
+
+ /* -----------------
+ Here comes the code for releasing the product
+ ----------------- */
- /* reset the product */
- SNACK_product_reset (&product);
+ /* send cancel request to nfc thread */
+ while ( pthread_cancel (nfcThread) != 0 )
+ {
+ printf ("Error sending cancel request to thread for nfc transmission");
}
- /* end of superloop */
- /* clear all initialized data */
- nfc_exit (context);
- SNACK_product_exit (&product);
- SNACK_taler_exit (&curl);
+ void*res;
+ if ( pthread_join (nfcThread, &res) == 0 )
+ {
+ printf ("Thread for nfc transmission finished\n");
+ fflush (stdout);
+ }
+ else if ( res == PTHREAD_CANCELED )
+ {
+ printf ("Thread for nfc transmission finished\n");
+ fflush (stdout);
+ }
- return EXIT_SUCCESS;
+ /* reset the product */
+ SNACK_product_reset (&product);
+
+}
+
+
+
+int
+main (int argc,
+ char*const*argv)
+{
+ /* the available command line options */
+ struct GNUNET_GETOPT_CommandLineOption options[] = {
+ GNUNET_GETOPT_OPTION_END
+ };
+
+ if (GNUNET_OK !=
+ 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))
+ return 1;
+ return global_ret;
}
diff --git a/src/nfc.c b/src/nfc.c
index 025e5cb..52fc153 100644
--- a/src/nfc.c
+++ b/src/nfc.c
@@ -103,7 +103,7 @@ int SNACK_nfc_connect_target (nfc_device *pnd, nfc_target *nt)
while ( ctr > 0 )
{
- /* set uid lenght to zero ( in case of second selecting the length still has the old value ) */
+ /* set uid length 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 )