diff options
author | Christian Grothoff <christian@grothoff.org> | 2022-05-09 14:37:46 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2022-05-09 14:37:46 +0200 |
commit | 2ead95eadce935dc95c8b6a3305e711d2b30561e (patch) | |
tree | d0cf64fa01fb486741507371cf41f3f69102fb09 /src | |
parent | 108bba2e83ddcc705fe506551253852f6ca7da41 (diff) | |
download | taler-mdb-2ead95eadce935dc95c8b6a3305e711d2b30561e.tar.gz taler-mdb-2ead95eadce935dc95c8b6a3305e711d2b30561e.tar.bz2 taler-mdb-2ead95eadce935dc95c8b6a3305e711d2b30561e.zip |
add support for multi-backend multi-currency deployments
Diffstat (limited to 'src')
-rw-r--r-- | src/main.c | 417 |
1 files changed, 244 insertions, 173 deletions
@@ -1,6 +1,6 @@ /* This file is part of TALER - Copyright (C) 2019, 2020 Taler Systems SA + Copyright (C) 2019, 2020, 2022 Taler Systems SA 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 @@ -58,6 +58,11 @@ along with /* for adafruit pitft display */ #include <linux/fb.h> +#ifndef EXIT_NOTCONFIGURED +#define EXIT_NOTCONFIGURED 6 +#endif + + /* Constants */ #define MAX_SIZE_RX_BUFFER 256 @@ -292,6 +297,11 @@ struct Product char *description; /** + * Authorization to header to use for this @e instance. + */ + char *auth_header; + + /** * Which instance should be used for billing? Full URL, replaces * the default base URL for orders involving this product. NULL if * we should use the #backend_base_url. @@ -313,7 +323,7 @@ struct Product * Set to #GNUNET_YES if this product was found * to have been sold out (VEND failure). */ - int sold_out; + bool sold_out; /** * Key for the product (optional, needed to test the application without vending machine) @@ -328,6 +338,17 @@ struct Product */ struct PaymentActivity { + + /** + * Curl context for communication with taler backend + */ + struct GNUNET_CURL_Context *ctx; + + /** + * Closure for #GNUNET_CURL_gnunet_scheduler_reschedule(). + */ + struct GNUNET_CURL_RescheduleContext *rc; + /** * Handle to a POST /orders operation */ @@ -390,16 +411,15 @@ struct PaymentActivity /** * Member to see if the wallet already received a uri - * GNUNET_YES, GNUNET_NO - * If yes, tunneling can be offered to the wallet + * If true, tunneling can be offered to the wallet. */ - int wallet_has_uri; + bool wallet_has_uri; /** - * Set to #GNUNET_YES once the product has been paid + * Set to true once the product has been paid * (and we are in the process of yielding the product). */ - int paid; + bool paid; }; @@ -468,7 +488,7 @@ struct MdbHandle /** * Indicates if a vend session is running or not */ - int session_running; + bool session_running; /** * File descriptor to the UART device file @@ -542,6 +562,16 @@ struct Refund struct Refund *prev; /** + * Curl context for communication with taler backend + */ + struct GNUNET_CURL_Context *ctx; + + /** + * Closure for #GNUNET_CURL_gnunet_scheduler_reschedule(). + */ + struct GNUNET_CURL_RescheduleContext *rc; + + /** * Handle to the ongoing operation. */ struct TALER_MERCHANT_OrderRefundHandle *orh; @@ -578,7 +608,7 @@ static int in_shutdown; * Flag set to remember that MDB needs shutdown * (because we were actually able to talk to MDB). */ -static int mdb_active; +static bool mdb_active; /** * Reference to the keyboard task @@ -591,21 +621,6 @@ static struct GNUNET_SCHEDULER_Task *keyboard_task; static struct GNUNET_SCHEDULER_Task *cancelbutton_task; /** - * Curl context for communication with taler backend - */ -static struct GNUNET_CURL_Context *ctx; - -/** - * Closure for #GNUNET_CURL_gnunet_scheduler_reschedule(). - */ -static struct GNUNET_CURL_RescheduleContext *rc; - -/** - * Currency read from configuration file - */ -static char *currency; - -/** * Taler Backend url read from configuration file */ static char *backend_base_url; @@ -616,11 +631,6 @@ static char *backend_base_url; static char *fulfillment_msg; /** - * Authorization for the taler backend - */ -static char *authorization; - -/** * ESSID of a WLAN network offered by the snack system, or NULL. */ static char *essid; @@ -756,6 +766,11 @@ static int disable_tty; static int sold_out_enabled; /** + * True if we have the 'reset' button on GPIO. + */ +static bool have_gpio; + +/** * Taler wallet application identifier */ static const uint8_t taler_aid[] = { 0xF0, 0x00, 0x54, 0x41, 0x4c, 0x45, 0x52 }; @@ -915,6 +930,25 @@ run_mdb_event_loop (void); /** + * Runs asynchronous cleanup part for freeing a + * payment activity. + * + * @param[in] cls a `struct PaymentActivity` to clean up + */ +static void +async_pa_cleanup_job (void *cls) +{ + struct PaymentActivity *pa = cls; + + if (NULL != pa->ctx) + GNUNET_CURL_fini (pa->ctx); + if (NULL != pa->rc) + GNUNET_CURL_gnunet_rc_destroy (pa->rc); + GNUNET_free (pa); +} + + +/** * @brief Cleanup all the data when a order has succeeded or got cancelled * * @param pa the payment activity to clean up @@ -928,15 +962,12 @@ cleanup_payment (struct PaymentActivity *pa) nfc_close (pa->pnd); } if (NULL != cancelbutton_task) - { GNUNET_SCHEDULER_cancel (cancelbutton_task); - cancelbutton_task = NULL; - } if (NULL != pa->po) TALER_MERCHANT_orders_post_cancel (pa->po); if (NULL != pa->ogh) TALER_MERCHANT_merchant_order_get_cancel (pa->ogh); - GNUNET_CURL_gnunet_scheduler_reschedule (&rc); + GNUNET_CURL_gnunet_scheduler_reschedule (&pa->rc); if (NULL != pa->task) GNUNET_SCHEDULER_cancel (pa->task); if (NULL != pa->delay_task) @@ -959,7 +990,8 @@ cleanup_payment (struct PaymentActivity *pa) GNUNET_free (pa->taler_pay_uri); } GNUNET_free (pa->order_id); - GNUNET_free (pa); + GNUNET_SCHEDULER_add_now (&async_pa_cleanup_job, + pa); } @@ -1047,19 +1079,8 @@ shutdown_task (void *cls) /* last ditch saying nicely goodbye to MDB */ in_shutdown = GNUNET_YES; mdb.cmd = &endSession; - run_mdb_event_loop (); - - if (NULL != ctx) - { - GNUNET_CURL_fini (ctx); - ctx = NULL; - } - if (NULL != rc) - { - GNUNET_CURL_gnunet_rc_destroy (rc); - rc = NULL; - } - + if (-1 != mdb.uartfd) + run_mdb_event_loop (); if ( (MAP_FAILED != qrDisplay.memory) && (NULL != qrDisplay.memory) ) { @@ -1082,12 +1103,13 @@ shutdown_task (void *cls) GNUNET_break (0 == close (qrDisplay.backlightfd)); qrDisplay.backlightfd = -1; } - if (0 < cancel_button.cancelbuttonfd) + if (-1 != cancel_button.cancelbuttonfd) { - GNUNET_break (0 == close (cancel_button.cancelbuttonfd)); + GNUNET_break (0 == + close (cancel_button.cancelbuttonfd)); cancel_button.cancelbuttonfd = open ("/sys/class/gpio/unexport", O_WRONLY); - if (0 > cancel_button.cancelbuttonfd) + if (-1 == cancel_button.cancelbuttonfd) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to open /gpio/unexport for cancel button\n"); @@ -1104,6 +1126,7 @@ shutdown_task (void *cls) } GNUNET_break (0 == close (cancel_button.cancelbuttonfd)); + cancel_button.cancelbuttonfd = -1; } } /* free the allocated productes read from config file */ @@ -1112,6 +1135,7 @@ shutdown_task (void *cls) for (unsigned int i = 0; i < products_length; i++) { GNUNET_free (products[i].description); + GNUNET_free (products[i].auth_header); GNUNET_free (products[i].instance); GNUNET_free (products[i].preview); } @@ -1186,7 +1210,7 @@ wallet_transmit_uri (void *cls) } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "'PUT DATA' command sent successfully via NFC\n"); - pa->wallet_has_uri = GNUNET_YES; + pa->wallet_has_uri = true; /* FIXME: or just offer Internet service here? */ /* transmit the uri again later, there can be many external failures, @@ -1406,7 +1430,7 @@ check_payment_cb (void *cls, if (TALER_MERCHANT_OSC_PAID == osr->status) { mdb.cmd = &cmd_approve_vend; - payment_activity->paid = GNUNET_YES; + payment_activity->paid = true; run_mdb_event_loop (); if ((disable_mdb) && (! disable_tty)) { @@ -1463,7 +1487,7 @@ check_payment_again (void *cls) pa->delay_pay_task = NULL; GNUNET_assert (NULL == pa->ogh); - pa->ogh = TALER_MERCHANT_merchant_order_get (ctx, + pa->ogh = TALER_MERCHANT_merchant_order_get (pa->ctx, pa->base_url, pa->order_id, NULL /* snack machine, no Web crap */, @@ -1509,7 +1533,7 @@ proposal_cb (void *cls, "Backend successfully created order `%s'\n", por->details.ok.order_id); pa->order_id = GNUNET_strdup (por->details.ok.order_id); - pa->ogh = TALER_MERCHANT_merchant_order_get (ctx, + pa->ogh = TALER_MERCHANT_merchant_order_get (pa->ctx, pa->base_url, pa->order_id, NULL /* snack machine, no Web crap */, @@ -1523,6 +1547,7 @@ proposal_cb (void *cls, static void start_read_cancel_button (void); + /** * @brief Launch a new order * @@ -1601,13 +1626,19 @@ launch_payment (struct Product *product) ? backend_base_url : product->instance); pa = GNUNET_new (struct PaymentActivity); + pa->ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, + &pa->rc); + pa->rc = GNUNET_CURL_gnunet_rc_create (pa->ctx); + GNUNET_assert (GNUNET_OK == + GNUNET_CURL_append_header (pa->ctx, + product->auth_header)); pa->product = product; pa->amount = product->price; /* put the order on the merchant's backend */ pa->base_url = (NULL == product->instance) ? backend_base_url : product->instance; - pa->po = TALER_MERCHANT_orders_post2 (ctx, + pa->po = TALER_MERCHANT_orders_post2 (pa->ctx, pa->base_url, orderReq, MAX_REFUND_DELAY, @@ -1624,11 +1655,11 @@ launch_payment (struct Product *product) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "TALER_MERCHANT_order_put failed (out of memory?)\n"); - GNUNET_free (pa); + cleanup_payment (pa); return NULL; } /* Start to read the button on the VM to cancel this payment */ - if (0 < cancel_button.cancelbuttonfd) + if (-1 != cancel_button.cancelbuttonfd) start_read_cancel_button (); return pa; } @@ -1652,6 +1683,25 @@ vend_success () /** + * Runs asynchronous cleanup part for freeing a + * refund activity. + * + * @param[in] cls a `struct Refund` to clean up + */ +static void +async_refund_cleanup_job (void *cls) +{ + struct Refund *r = cls; + + if (NULL != r->ctx) + GNUNET_CURL_fini (r->ctx); + if (NULL != r->rc) + GNUNET_CURL_gnunet_rc_destroy (r->rc); + GNUNET_free (r); +} + + +/** * @brief Callback to process a POST /refund request * * @param cls closure @@ -1680,7 +1730,8 @@ refund_complete_cb (void *cls, GNUNET_CONTAINER_DLL_remove (refund_head, refund_tail, r); - GNUNET_free (r); + GNUNET_SCHEDULER_add_now (&async_refund_cleanup_job, + r); } @@ -1702,11 +1753,17 @@ vend_failure (void) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received MDB vend failure for `%s', refunding customer\n", p->description); - p->sold_out = GNUNET_YES; + p->sold_out = true; mdb.cmd = &endSession; - mdb.session_running = GNUNET_NO; + mdb.session_running = false; r = GNUNET_new (struct Refund); - r->orh = TALER_MERCHANT_post_order_refund (ctx, + r->ctx = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, + &r->rc); + r->rc = GNUNET_CURL_gnunet_rc_create (r->ctx); + GNUNET_assert (GNUNET_OK == + GNUNET_CURL_append_header (r->ctx, + p->auth_header)); + r->orh = TALER_MERCHANT_post_order_refund (r->ctx, (NULL == p->instance) ? backend_base_url : p->instance, @@ -1766,14 +1823,14 @@ read_keyboard_command (void *cls) else { mdb.cmd = &endSession; - mdb.session_running = GNUNET_NO; + mdb.session_running = false; } run_mdb_event_loop (); cleanup_payment (payment_activity); payment_activity = NULL; break; case 'a': - payment_activity->paid = GNUNET_YES; + payment_activity->paid = true; mdb.cmd = &cmd_approve_vend; run_mdb_event_loop (); break; @@ -1819,7 +1876,7 @@ read_keyboard_command (void *cls) if (((char) input) == products[i].key) { if ( (sold_out_enabled) && - (GNUNET_YES == products[i].sold_out) ) + (products[i].sold_out) ) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Product %s sold out, denying vend\n", @@ -1885,7 +1942,7 @@ cancel_button_pressed (void *cls) /* The order was paid and if we know this, then it is also yielded, * just end the current session */ mdb.cmd = &endSession; - mdb.session_running = GNUNET_NO; + mdb.session_running = false; } run_mdb_event_loop (); cleanup_payment (payment_activity); @@ -1944,7 +2001,9 @@ start_read_keyboard () static void start_read_cancel_button () { - struct GNUNET_DISK_FileHandle fh = { cancel_button.cancelbuttonfd }; + struct GNUNET_DISK_FileHandle fh = { + cancel_button.cancelbuttonfd + }; GNUNET_assert (NULL == cancelbutton_task); cancelbutton_task = GNUNET_SCHEDULER_add_read_file ( @@ -2071,10 +2130,10 @@ static void handle_ack () { if (&cmd_begin_session == mdb.last_cmd) - mdb.session_running = GNUNET_YES; + mdb.session_running = true; if (&cmd_deny_vend == mdb.last_cmd) { - mdb.session_running = GNUNET_NO; + mdb.session_running = false; mdb.cmd = &endSession; } if (&cmd_reader_display_sold_out == mdb.last_cmd) @@ -2190,7 +2249,7 @@ handle_command (const char *hex, } unsigned int product; - GNUNET_break (GNUNET_YES == mdb.session_running); + GNUNET_break (mdb.session_running); /* NOTE: hex[4..7] contain the price */ if (12 > hex_len) { @@ -2216,7 +2275,7 @@ handle_command (const char *hex, "Product %u selected on MDB\n", product); if ( (sold_out_enabled) && - (GNUNET_YES == products[i].sold_out) ) + (products[i].sold_out) ) { GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Product %s sold out, denying vend\n", @@ -2236,12 +2295,12 @@ handle_command (const char *hex, break; } case VMC_VEND_SUCCESS: - GNUNET_break (GNUNET_YES == mdb.session_running); + GNUNET_break (mdb.session_running); vend_success (); break; case VMC_VEND_FAILURE: { - GNUNET_break (GNUNET_YES == mdb.session_running); + GNUNET_break (mdb.session_running); vend_failure (); break; } @@ -2249,7 +2308,7 @@ handle_command (const char *hex, { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received MDB session complete\n"); - mdb.session_running = GNUNET_NO; + mdb.session_running = false; mdb.cmd = &endSession; if (NULL != payment_activity) { @@ -2389,7 +2448,7 @@ handle_command (const char *hex, case VMC_READER_DISABLE: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received Reader Disable via MDB\n"); - mdb.session_running = GNUNET_NO; + mdb.session_running = false; if (NULL != payment_activity) { cleanup_payment (payment_activity); @@ -2400,23 +2459,23 @@ handle_command (const char *hex, if ( (sold_out_enabled) && (0 != strcmp (products[i].description, "empty")) && - (GNUNET_YES == products[i].sold_out) ) + (products[i].sold_out) ) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Resetting sold out state of product %s\n", products[i].description); - products[i].sold_out = GNUNET_NO; + products[i].sold_out = false; } } break; case VMC_READER_ENABLE: GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received Reader Enable via MDB\n"); - mdb.session_running = GNUNET_NO; + mdb.session_running = false; break; case VMC_READER_CANCEL: mdb.cmd = &cmd_reader_cancelled; - mdb.session_running = GNUNET_NO; + mdb.session_running = false; break; default: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -2441,7 +2500,7 @@ handle_command (const char *hex, GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Received command out of sequence from MDB (for command `%s')\n", (NULL != mdb.last_cmd) ? mdb.last_cmd->name : "?"); - mdb.session_running = GNUNET_NO; + mdb.session_running = false; if (mdb.last_cmd != &endSession) mdb.cmd = &endSession; else @@ -2496,7 +2555,7 @@ read_mdb_command (void *cls) while (mdb.rx_off > 0) { - mdb_active = GNUNET_YES; + mdb_active = true; /* find beginning of command */ for (cmdStartIdx = 0; cmdStartIdx < mdb.rx_off; cmdStartIdx++) if (VMC_CMD_START == mdb.rxBuffer[cmdStartIdx]) @@ -2555,7 +2614,7 @@ run_mdb_event_loop () struct GNUNET_DISK_FileHandle fh = { mdb.uartfd }; /* begin session if no cmd waits for sending and no cmd is received from the VMC */ - if ( (GNUNET_NO == mdb.session_running) && + if ( (! mdb.session_running) && (NULL == mdb.cmd) && (NULL == mdb.last_cmd) ) { @@ -2609,6 +2668,7 @@ static void read_products (void *cls, const char *section) { + const struct GNUNET_CONFIGURATION_Handle *cfg = cls; struct Product tmpProduct; char *tmpKey; char *thumbnail_fn; @@ -2620,7 +2680,7 @@ read_products (void *cls, return; /* the current section is a product, parse its specifications and store it in a temporary product */ if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cls, + GNUNET_CONFIGURATION_get_value_string (cfg, section, "description", &tmpProduct.description)) @@ -2635,15 +2695,15 @@ read_products (void *cls, if (0 == strcmp (tmpProduct.description, "empty")) { - tmpProduct.sold_out = GNUNET_YES; + tmpProduct.sold_out = true; } else { - tmpProduct.sold_out = GNUNET_NO; + tmpProduct.sold_out = false; } } if (GNUNET_OK != - TALER_config_get_amount (cls, + TALER_config_get_amount (cfg, section, "price", &tmpProduct.price)) @@ -2654,18 +2714,8 @@ read_products (void *cls, GNUNET_free (tmpProduct.description); return; } - if (0 != strcasecmp (currency, - tmpProduct.price.currency)) - { - GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, - section, - "price", - "currency mismatch"); - GNUNET_free (tmpProduct.description); - return; - } if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (cls, + GNUNET_CONFIGURATION_get_value_string (cfg, section, "key", &tmpKey)) @@ -2679,14 +2729,14 @@ read_products (void *cls, tmpProduct.key = '\0'; } if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cls, + GNUNET_CONFIGURATION_get_value_string (cfg, section, "instance", &tmpProduct.instance)) tmpProduct.instance = NULL; tmpProduct.preview = NULL; if (GNUNET_OK == - GNUNET_CONFIGURATION_get_value_string (cls, + GNUNET_CONFIGURATION_get_value_string (cfg, section, "thumbnail", &thumbnail_fn)) @@ -2778,7 +2828,7 @@ read_products (void *cls, GNUNET_free (thumbnail_fn); } if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_number (cls, + GNUNET_CONFIGURATION_get_value_number (cfg, section, "number", &tmpProduct.number)) @@ -2791,6 +2841,35 @@ read_products (void *cls, GNUNET_free (tmpProduct.preview); return; } + + { + char *auth; + + if ( (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + section, + "BACKEND-AUTHORIZATION", + &auth)) && + (GNUNET_OK != + GNUNET_CONFIGURATION_get_value_string (cfg, + "taler-mdb", + "BACKEND-AUTHORIZATION", + &auth)) ) + { + GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, + section, + "BACKEND-AUTHORIZATION"); + GNUNET_free (tmpProduct.description); + GNUNET_free (tmpProduct.instance); + GNUNET_free (tmpProduct.preview); + return; + } + GNUNET_asprintf (&tmpProduct.auth_header, + "%s: %s", + MHD_HTTP_HEADER_AUTHORIZATION, + auth); + GNUNET_free (auth); + } /* append the temporary product to the existing products */ GNUNET_array_append (products, products_length, @@ -2800,8 +2879,10 @@ read_products (void *cls, /** * @brief Initialise the uart device to send mdb commands + * + * @return #GNUNET_OK on success */ -static int +static enum GNUNET_GenericReturnValue mdb_init () { struct termios uart_opts_raw; @@ -2823,7 +2904,8 @@ mdb_init () return GNUNET_SYSERR; } - if (0 != tcgetattr (mdb.uartfd, &mdb.uart_opts_backup)) + if (0 != tcgetattr (mdb.uartfd, + &mdb.uart_opts_backup)) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR, "tcgetattr"); @@ -2886,14 +2968,6 @@ run (void *cls, (void) args; (void) cfgfile; - /* parse the configuration file */ - if (GNUNET_OK != - TALER_config_get_currency (cfg, - ¤cy)) - { - global_ret = EXIT_FAILURE; - return; - } /* parse the devices, if no config entry is found, a standard is used */ if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (cfg, @@ -2943,28 +3017,6 @@ run (void *cls, return; } { - char *auth; - - if (GNUNET_OK != - GNUNET_CONFIGURATION_get_value_string (cfg, - "taler-mdb", - "backend-authorization", - &auth)) - { - GNUNET_log_config_missing (GNUNET_ERROR_TYPE_ERROR, - "taler-mdb", - "backend-authorization"); - global_ret = EXIT_FAILURE; - return; - } - /* concat the authorization e.g. Authorization: ApiKey sandbox */ - GNUNET_asprintf (&authorization, - "%s: %s", - MHD_HTTP_HEADER_AUTHORIZATION, - auth); - GNUNET_free (auth); - } - { if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "taler-mdb", @@ -2992,7 +3044,13 @@ run (void *cls, GNUNET_CONFIGURATION_iterate_sections (cfg, &read_products, (void *) cfg); - GNUNET_assert (NULL != products); + if (NULL == products) + { + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "No valid products configured\n"); + global_ret = EXIT_NOTCONFIGURED; + return; + } GNUNET_SCHEDULER_add_shutdown (&shutdown_task, NULL); @@ -3011,22 +3069,13 @@ run (void *cls, nfc_init (&context); if (NULL == context) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "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)); - /* open gpio pin for cancel button */ { int efd; @@ -3035,20 +3084,31 @@ run (void *cls, O_WRONLY); if (-1 == efd) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to open /gpio/export for cancel button\n"); - global_ret = EXIT_FAILURE; - GNUNET_SCHEDULER_shutdown (); - return; + have_gpio = false; + } + else + { + if (2 != write (efd, + "23", + 2)) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, + "write", + "/sys/class/gpio/export"); + have_gpio = false; + } + else + { + have_gpio = true; + } + GNUNET_assert (0 == close (efd)); } - if (2 != write (efd, "23", 2)) - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, - "write", - "/sys/class/gpio/export"); - GNUNET_assert (0 == close (efd)); } /* set direction: input */ + if (have_gpio) { int dfd; @@ -3056,29 +3116,40 @@ run (void *cls, O_WRONLY); if (-1 == dfd) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unable to open /gpio/gpio23/direction for cancel button\n"); - global_ret = EXIT_FAILURE; - GNUNET_SCHEDULER_shutdown (); - return; + have_gpio = false; + } + else + { + if (2 != write (dfd, + "in", + 2)) + { + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, + "write", + "/sys/class/gpio/gpio23/direction"); + have_gpio = false; + } } - if (2 != write (dfd, "in", 2)) - GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, - "write", - "/sys/class/gpio/gpio23/direction"); GNUNET_assert (0 == close (dfd)); } - /* actually open fd for reading the state */ - cancel_button.cancelbuttonfd = open ("/sys/class/gpio/gpio23/value", - O_RDONLY); - if (-1 == cancel_button.cancelbuttonfd) + if (have_gpio) { - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Unable to open /gpio/gpio23/value for cancel button\n"); - global_ret = EXIT_FAILURE; - GNUNET_SCHEDULER_shutdown (); - return; + /* actually open fd for reading the state */ + cancel_button.cancelbuttonfd = open ("/sys/class/gpio/gpio23/value", + O_RDONLY); + if (-1 == cancel_button.cancelbuttonfd) + { + GNUNET_log (GNUNET_ERROR_TYPE_WARNING, + "Unable to open /gpio/gpio23/value for cancel button\n"); + have_gpio = false; + } + } + else + { + cancel_button.cancelbuttonfd = -1; } @@ -3121,11 +3192,11 @@ run (void *cls, } /* get pointer onto frame buffer */ - qrDisplay.memory = mmap (NULL, - qrDisplay.fix_info.smem_len, - PROT_READ | PROT_WRITE, MAP_SHARED, - qrDisplay.devicefd, - 0); + qrDisplay.memory = mmap (NULL, + qrDisplay.fix_info.smem_len, + PROT_READ | PROT_WRITE, MAP_SHARED, + qrDisplay.devicefd, + 0); if (MAP_FAILED == qrDisplay.memory) { GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, |