taler-mdb

GNU Taler Extensions and Integrations
Log | Files | Refs | Submodules | README | LICENSE

commit 01cc8d8cdc9079d58ff5d0458809bb5caa2e4964
parent 9065ce55d75b8bdabd3d646ab09375a282ace96c
Author: Christian Grothoff <christian@grothoff.org>
Date:   Wed,  4 Dec 2019 16:58:15 +0100

fix my TODOs

Diffstat:
Msrc/main.c | 286+++++++++++++++++++++++++++++++++++++++++++++++++++++--------------------------
1 file changed, 194 insertions(+), 92 deletions(-)

diff --git a/src/main.c b/src/main.c @@ -25,17 +25,6 @@ along with * TODO: * - comment code (Boss) * - replace remaining MDB magic constants with #defines (Hofer) -* - support command line option to "disable_mdb" to run without -* connected MDB (instead of failing to launch); in this -* mode, print out what WOULD be done with MDB (Grothoff) -* - in keyboard interaction, distinguish between -* payment pending and payment not pending, allow -* 'c', only if pending (Grothoff) -* - have new state for waiting for MDB to signal vend success/failure -* in keyboard interaction prompt for success y/n at that time (or c cancel) (Grothoff) -* - add key strokes for "failure to vend" and "vend successful" -* (useful when faking MDB interaction), factor out function for - the respective operations! (Grothoff) * - implement refunds on failure to vend (TBD) */ #include "config.h" @@ -263,6 +252,12 @@ struct PaymentActivity * If yes, tunneling can be offered to the wallet */ int wallet_has_uri; + + /** + * Set to #GNUNET_YES once the product has been paid + * (and we are in the process of yielding the product). + */ + int paid; }; @@ -577,6 +572,7 @@ show_qrcode (const char *uri) write (qrDisplay.backlightfd, "1", 1); } + #endif @@ -584,7 +580,6 @@ static void run_mdb_event_loop (void); - /** * Cleanup all the data when a order has succeeded or got cancelled * @param pa the payment activity to clean up @@ -601,6 +596,7 @@ cleanup_payment (struct PaymentActivity *pa) TALER_MERCHANT_proposal_cancel (pa->po); if (NULL != pa->cpo) TALER_MERCHANT_check_payment_cancel (pa->cpo); + GNUNET_CURL_gnunet_scheduler_reschedule (&rc); if (NULL != pa->task) GNUNET_SCHEDULER_cancel (pa->task); if (NULL != pa->delay_task) @@ -636,7 +632,8 @@ mdb_shutdown () GNUNET_SCHEDULER_cancel (mdb.wtask); mdb.wtask = NULL; } - + if (disable_mdb) + return; /* restore UART */ if (0 != tcsetattr (mdb.uartfd, TCSAFLUSH, @@ -946,6 +943,10 @@ open_nfc_reader (void *cls) } +static void +start_read_keyboard (void); + + /** * Callback to process a GET /check-payment request * @@ -976,6 +977,7 @@ check_payment_cb (void *cls, (void) refunded; (void) refund_amount; (void) obj; + GNUNET_assert (payment_activity == pa); pa->cpo = NULL; if (MHD_HTTP_OK != http_status) { @@ -993,9 +995,14 @@ check_payment_cb (void *cls, if (paid) { mdb.cmd = &approveVend; - cleanup_payment (pa); - GNUNET_assert (payment_activity == pa); - payment_activity = NULL; + payment_activity->paid = GNUNET_YES; + run_mdb_event_loop (); + if (disable_mdb) + { + GNUNET_SCHEDULER_cancel (keyboard_task); + keyboard_task = NULL; + start_read_keyboard (); + } return; } else @@ -1158,8 +1165,41 @@ launch_payment (const struct Product *product) } +/** + * Vending successful, conclude payment activity. + */ static void -start_read_keyboard (void); +vend_success () +{ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "MDB vend success received\n"); + GNUNET_break (NULL != payment_activity); + if (NULL != payment_activity) + { + cleanup_payment (payment_activity); + payment_activity = NULL; + } +} + + +/** + * Vending failed, provide refund. + */ +static void +vend_failure () +{ + GNUNET_break (NULL != payment_activity); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Received MDB vend failure, refunding customer (FIXME: not implemented)\n"); + mdb.cmd = &endSession; + mdb.session_running = GNUNET_NO; + /* FIXME: refund logic here! */ + if (NULL != payment_activity) + { + cleanup_payment (payment_activity); + payment_activity = NULL; + } +} /** @@ -1181,36 +1221,56 @@ read_keyboard_command (void *cls) GNUNET_SCHEDULER_shutdown (); return; } - if ((char) input == 'c') + if (NULL != payment_activity) { - if (NULL != payment_activity) + switch ((char) input) { - mdb.cmd = &denyVend; + case 'c': + if (GNUNET_NO == payment_activity->paid) + { + mdb.cmd = &denyVend; + } + else + { + mdb.cmd = &endSession; + mdb.session_running = GNUNET_NO; + } run_mdb_event_loop (); cleanup_payment (payment_activity); payment_activity = NULL; - } - else - { - fprintf (stderr, - "No purchase activity pending\n"); - } - start_read_keyboard (); - return; - } - if ((char) input == 'a') - { - if (NULL != payment_activity) - { + break; + case 'a': + payment_activity->paid = GNUNET_YES; mdb.cmd = &approveVend; run_mdb_event_loop (); - cleanup_payment (payment_activity); - payment_activity = NULL; - } - else - { + break; + case 'n': + if (disable_mdb) + { + vend_failure (); + } + else + { + fprintf (stderr, + "Cannot fail to vend at this time, waiting for payment\n"); + } + break; + case 'y': + if (disable_mdb) + { + vend_success (); + } + else + { + fprintf (stderr, + "Cannot succeed to vend at this time, waiting for payment\n"); + } + break; + default: fprintf (stderr, - "No purchase activity pending\n"); + "Unknown command `%c'\n", + input); + break; } start_read_keyboard (); return; @@ -1245,13 +1305,28 @@ 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 ("'a' to fake payment for the last purchase\n" - "'c' to cancel last purchase\n" - "'x' to quit\n"); + if (NULL == payment_activity) + { + for (unsigned int i = 0; i < products_length; i++) + printf ("'%c' to buy %s\n", + products[i].key, + products[i].description); + } + else + { + if (GNUNET_NO == payment_activity->paid) + { + printf ("'a' to fake payment for the last purchase\n" + "'c' to cancel last purchase\n"); + } + else + { + if (disable_mdb) + printf ("'y' to simulate product successfully dispensed\n" + "'n' to simulate product failed to be dispensed\n"); + } + } + printf ("'x' to quit\n"); printf ("Waiting for keyboard input\n"); keyboard_task = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, &fh, @@ -1267,6 +1342,15 @@ write_mdb_command (void *cls) (void) cls; mdb.wtask = NULL; + if (disable_mdb) + { + if (NULL == mdb.cmd) + return; + mdb.last_cmd = mdb.cmd; + mdb.cmd = NULL; + run_mdb_event_loop (); + return; + } if (mdb.tx_off < mdb.tx_len) { ssize_t ret = write (mdb.uartfd, @@ -1345,6 +1429,29 @@ write_mdb_command (void *cls) /** + * MDB acknowledged the last command, proceed. + */ +static void +handle_ack () +{ + if (&beginSession == mdb.last_cmd) + mdb.session_running = GNUNET_YES; + if (&denyVend == mdb.last_cmd) + { + mdb.session_running = GNUNET_NO; + mdb.cmd = &endSession; + } + mdb.last_cmd = NULL; + /* Cause the write-task to be re-scheduled now */ + if (NULL != mdb.wtask) + { + GNUNET_SCHEDULER_cancel (mdb.wtask); + mdb.wtask = NULL; + } +} + + +/** * * @param hex_len number of characters in @a hex */ @@ -1440,22 +1547,12 @@ handle_command (const char *hex, } case VMC_VEND_SUCCESS: GNUNET_break (GNUNET_YES == mdb.session_running); - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Vend Success\n"); + vend_success (); break; case VMC_VEND_FAILURE: { GNUNET_break (GNUNET_YES == mdb.session_running); - mdb.cmd = &endSession; - mdb.session_running = GNUNET_NO; - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Received MDB vend failure, refunding customer (FIXME: not implemented)\n"); - /* FIXME: refund logic here! */ - if (NULL != payment_activity) - { - cleanup_payment (payment_activity); - payment_activity = NULL; - } + vend_failure (); break; } case VMC_VEND_SESSION_COMPLETE: @@ -1522,19 +1619,7 @@ handle_command (const char *hex, GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Received acknowledgement (for command `%s') from MDB\n", (NULL != mdb.last_cmd) ? mdb.last_cmd->name : "?"); - if (&beginSession == mdb.last_cmd) - mdb.session_running = GNUNET_YES; - if (&denyVend == mdb.last_cmd) - { - mdb.session_running = GNUNET_NO; - mdb.cmd = &endSession; - } - mdb.last_cmd = NULL; - if (NULL != mdb.wtask) - { - GNUNET_SCHEDULER_cancel (mdb.wtask); - mdb.wtask = NULL; - } + handle_ack (); break; case VMC_OOSQ: GNUNET_log (GNUNET_ERROR_TYPE_WARNING, @@ -1572,6 +1657,7 @@ read_mdb_command (void *cls) size_t cmdEndIdx; (void) cls; + GNUNET_assert (! disable_mdb); mdb.rtask = NULL; ret = read (mdb.uartfd, &mdb.rxBuffer[mdb.rx_off], @@ -1639,8 +1725,7 @@ run_mdb_event_loop () { struct GNUNET_DISK_FileHandle fh = { mdb.uartfd }; - if (disable_mdb) - return; + return; if ( (GNUNET_NO == mdb.session_running) && (NULL == mdb.cmd) && (NULL == mdb.last_cmd) ) @@ -1649,11 +1734,26 @@ run_mdb_event_loop () if ( (NULL == mdb.wtask) && ( (NULL != mdb.cmd) || (mdb.tx_len > mdb.tx_off) ) ) - mdb.wtask = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, - &fh, - &write_mdb_command, - NULL); - if (NULL == mdb.rtask) + { + if (disable_mdb) + mdb.wtask = GNUNET_SCHEDULER_add_now (&write_mdb_command, + NULL); + else + mdb.wtask = GNUNET_SCHEDULER_add_write_file (GNUNET_TIME_UNIT_FOREVER_REL, + &fh, + &write_mdb_command, + NULL); + } + if ( (disable_mdb) && + (NULL != mdb.last_cmd) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Faking acknowledgement (for command `%s') from MDB\n", + mdb.last_cmd->name); + handle_ack (); + } + if ( (NULL == mdb.rtask) && + (! disable_mdb) ) mdb.rtask = GNUNET_SCHEDULER_add_read_file (GNUNET_TIME_UNIT_FOREVER_REL, &fh, &read_mdb_command, @@ -1748,7 +1848,10 @@ mdb_init () struct termios uart_opts_raw; if (disable_mdb) + { + run_mdb_event_loop (); return GNUNET_OK; + } /* open uart connection */ if (0 > (mdb.uartfd = open (uart_device_filename, O_RDWR | O_NOCTTY | O_NDELAY))) @@ -1961,9 +2064,7 @@ run (void *cls, &qrDisplay.var_info); /* store current screeninfo for reset */ - memcpy (&qrDisplay.orig_vinfo, - &qrDisplay.var_info, - sizeof(struct fb_var_screeninfo)); + qrDisplay.orig_vinfo = qrDisplay.var_info; if (16 != qrDisplay.var_info.bits_per_pixel) { @@ -1973,8 +2074,8 @@ run (void *cls, FBIOPUT_VSCREENINFO, &qrDisplay.var_info)) { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Error setting display bpp to 16\n"); + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "ioctl(FBIOPUT_VSCREENINFO)"); return; } } @@ -1984,8 +2085,8 @@ run (void *cls, FBIOGET_FSCREENINFO, &qrDisplay.fix_info)) { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "Error reading fixed display information\n"); + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "ioctl(FBIOGET_FSCREENINFO)"); return; } @@ -1999,8 +2100,8 @@ run (void *cls, /* open backlight file to turn display backlight on and off */ if (0 > qrDisplay.devicefd) { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "failed to map display memory\n"); + GNUNET_log_strerror (GNUNET_ERROR_TYPE_WARNING, + "mmap"); return; } @@ -2013,8 +2114,9 @@ run (void *cls, "/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"); + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, + "open", + "/sys/class/backlight/soc:backlight/brightness"); } else { @@ -2023,9 +2125,9 @@ run (void *cls, } else { - GNUNET_log (GNUNET_ERROR_TYPE_WARNING, - "open(), could not open framebuffer device %s\n", - framebuffer_device_filename); + GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_WARNING, + "open", + framebuffer_device_filename); } #endif start_read_keyboard ();