diff options
author | Christian Grothoff <christian@grothoff.org> | 2024-01-14 00:43:37 +0100 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2024-01-14 00:43:37 +0100 |
commit | aa9c8a4a51cbbd80baa7e53d114c84ac3bfdb3b3 (patch) | |
tree | 85210c78f91d9b7426f4b396b167e994c13b6036 | |
parent | 74635648a0c6ab901dcbbd5a69a605a5fb29e0e6 (diff) | |
download | taler-mdb-aa9c8a4a51cbbd80baa7e53d114c84ac3bfdb3b3.tar.gz taler-mdb-aa9c8a4a51cbbd80baa7e53d114c84ac3bfdb3b3.tar.bz2 taler-mdb-aa9c8a4a51cbbd80baa7e53d114c84ac3bfdb3b3.zip |
add error display logic to main code
-rw-r--r-- | contrib/Makefile.am | 1 | ||||
-rwxr-xr-x | contrib/taler-mdb-ads.sh | 56 | ||||
-rwxr-xr-x[-rw-r--r--] | contrib/taler-mdb-show.sh | 4 | ||||
-rw-r--r-- | debian/etc/taler-mdb.conf | 3 | ||||
-rw-r--r-- | src/.gitignore | 1 | ||||
-rw-r--r-- | src/taler-mdb.c | 201 |
6 files changed, 245 insertions, 21 deletions
diff --git a/contrib/Makefile.am b/contrib/Makefile.am index 2d6d46b..d0e7036 100644 --- a/contrib/Makefile.am +++ b/contrib/Makefile.am @@ -13,6 +13,7 @@ img_DATA = \ png/maintenance.png bin_SCRIPTS = \ + taler-mdb-ads.sh \ taler-mdb-show.sh \ taler-mdb-network-check.sh diff --git a/contrib/taler-mdb-ads.sh b/contrib/taler-mdb-ads.sh new file mode 100755 index 0000000..f097ba2 --- /dev/null +++ b/contrib/taler-mdb-ads.sh @@ -0,0 +1,56 @@ +#!/bin/bash + +set -eu + +function cleanup() +{ + taler-mdb-display -c "$CONF" -i + exit 0 +} + +trap cleanup EXIT + +CONF="$HOME/.config/taler.conf" + +# Parse command-line options +while getopts ':c:h' OPTION; do + case "$OPTION" in + c) + CONF="$OPTARG" + ;; + h) + echo 'Supported options:' + # shellcheck disable=SC2016 + echo ' -c $CONF -- set configuration' + ;; + ?) + exit_fail "Unrecognized command line option" + ;; + esac +done +shift $((OPTIND - 1)) + +taler-mdb-display -c "$CONF" + +FBDEV=$(taler-config -c "$CONF" -s taler-mdb -o FRAMEBUFFER_DEVICE) + +DATA_HOME=$(taler-config -c "$CONF" -s paths -o TALER_DATA_HOME) + +while true +do + HOUR=$(date +%H) + if [[ HOUR -ge 8 && HOUR -lt 22 ]] + then + taler-mdb-display -c "$CONF" + for AD in $(ls "${DATA_HOME}/ads/*" | shuf) + do + DELAY=$(echo "$AD" | awk -F'[-.]' '{print $(NF-1)}') + fbi -d "$FBDEV" -a -m "768x576-75" -vt 2 -nocomments -noverbose "$AD" + sleep "$DELAY" + done + taler-mdb-display -c "$CONF" -i + else + # Night time, save power! + sleep 600 + fi +done diff --git a/contrib/taler-mdb-show.sh b/contrib/taler-mdb-show.sh index 7073b9f..c06a089 100644..100755 --- a/contrib/taler-mdb-show.sh +++ b/contrib/taler-mdb-show.sh @@ -34,7 +34,9 @@ taler-mdb-display -c "$CONF" FBDEV=$(taler-config -c "$CONF" -s taler-mdb -o FRAMEBUFFER_DEVICE) -fbi -d "$FBDEV" -a -m "768x576-75" -vt 2 -nocomments -noverbose "$1.png" +DATA_HOME=$(taler-config -c "$CONF" -s paths -o TALER_DATA_HOME) + +fbi -d "$FBDEV" -a -m "768x576-75" -vt 2 -nocomments -noverbose "${DATA_HOME}/mdb/$1.png" while true do diff --git a/debian/etc/taler-mdb.conf b/debian/etc/taler-mdb.conf index 94dfcdd..561256b 100644 --- a/debian/etc/taler-mdb.conf +++ b/debian/etc/taler-mdb.conf @@ -7,6 +7,9 @@ BACKEND_BASE_URL = http://backend.demo.taler.net/ # Secret key to talk to *all* instances we use. BACKEND_AUTHORIZATION = "Bearer secret-token:sandbox" +# Program to use to show ads. +ADVERTISEMENT_COMMAND = taler-mdb-ads.sh -c /etc/taler-mdb.conf + # Message to diplay after purchase is completed, FULFILLMENT_MSG = Enjoy your ${PRODUCT_DESCRIPTION} diff --git a/src/.gitignore b/src/.gitignore index f66074a..c6b6bf5 100644 --- a/src/.gitignore +++ b/src/.gitignore @@ -1,3 +1,4 @@ *.o taler-nfc taler-coin-acceptor +taler-mdb-display diff --git a/src/taler-mdb.c b/src/taler-mdb.c index 431a505..3acd633 100644 --- a/src/taler-mdb.c +++ b/src/taler-mdb.c @@ -84,6 +84,12 @@ along with GNUNET_TIME_UNIT_MINUTES, 2) /** + * How long to show a transient error. + */ +#define ERR_DELAY GNUNET_TIME_relative_multiply ( \ + GNUNET_TIME_UNIT_SECONDS, 30) + +/** * How long could it take at most for us to notify the Taler merchant * backend to grant a refund to a user if dispensing the product * failed? (Very conservative value here, for vending machines brewing @@ -634,16 +640,33 @@ static struct GNUNET_SCHEDULER_Task *keyboard_task; static struct GNUNET_SCHEDULER_Task *cancelbutton_task; /** + * Task to stop showing transient errors. + */ +static struct GNUNET_SCHEDULER_Task *err_stop_task; + +/** * Handle to the process showing messages/advertisements * while we are inactive. */ static struct GNUNET_OS_Process *adv_child; /** - * Name of the process to run when advertising is enabled. + * Handle to the process showing error messages + * while we have one. + */ +static struct GNUNET_OS_Process *err_child; + +/** + * Command to run when advertising is enabled. + * Can be NULL. + */ +static char *adv_process_command; + +/** + * Command to run when advertising is enabled. * Can be NULL. */ -static char *adv_process_filename; +static char *err_process_command; /** * Taler Backend url read from configuration file @@ -817,6 +840,135 @@ static struct Display qrDisplay; /** + * Start process using the @a command command-line. + * + * @param command command to run + * @param ... extra arguments to pass + * @return process handle, NULL on failure + */ +static struct GNUNET_OS_Process * +start_command (const char *command, + ...) +{ + char **argv = NULL; + unsigned int argc = 0; + char *cpy = GNUNET_strdup (adv_process_command); + struct GNUNET_OS_Process *ret; + va_list ap; + const char *arg; + + for (const char *tok = strtok (cpy, " "); + NULL != tok; + tok = strtok (NULL, " ")) + { + GNUNET_array_append (argv, + argc, + GNUNET_strdup (tok)); + } + va_start (ap, + command); + while (NULL != (arg = va_arg (ap, + const char *))) + { + GNUNET_array_append (argv, + argc, + GNUNET_strdup (arg)); + } + va_end (ap); + GNUNET_array_append (argv, + argc, + NULL); + ret = GNUNET_OS_start_process_vap (GNUNET_OS_INHERIT_STD_NONE, + NULL, + NULL, + NULL, + argv[0], + argv); + for (unsigned int i = 0; i<argc; i++) + GNUNET_free (argv[i]); + GNUNET_array_grow (argv, + argc, + 0); + GNUNET_free (cpy); + return ret; +} + + +/** + * Stop the process showing an error. + */ +static void +hide_error (void) +{ + if (NULL == err_child) + return; + if (NULL != err_stop_task) + { + GNUNET_SCHEDULER_cancel (err_stop_task); + err_stop_task = NULL; + } + GNUNET_break (0 == + GNUNET_OS_process_kill (err_child, + SIGTERM)); + GNUNET_break (GNUNET_OK == + GNUNET_OS_process_wait (err_child)); + GNUNET_OS_process_destroy (err_child); + err_child = NULL; +} + + +/** + * Show an error using the respective error process + * command. + * + * @param err_type type of the error to pass to the command + */ +static void +show_error (const char *err_type) +{ + hide_error (); /* just to be sure */ + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Showing error `%s'\n", + err_type); + if (NULL == err_process_command) + { + return; + } + err_child = start_command (err_process_command, + err_type, + NULL); +} + + +/** + * Task to stop the process showing an error. + * + * @param cls NULL + */ +static void +do_hide_error (void *cls) +{ + err_stop_task = NULL; + hide_error (); +} + + +/** + * Briefly show a temporary error. + * + * @param err_type error to show + */ +static void +temporary_error (const char *err_type) +{ + show_error (err_type); + err_stop_task = GNUNET_SCHEDULER_add_delayed (ERR_DELAY, + &do_hide_error, + NULL); +} + + +/** * Stop the advertising process. */ static void @@ -841,15 +993,10 @@ static void start_advertising (void) { stop_advertising (); /* just to be sure */ - if (NULL == adv_process_filename) + if (NULL == adv_process_command) return; - adv_child = GNUNET_OS_start_process (GNUNET_OS_INHERIT_STD_NONE, - NULL, - NULL, - NULL, - adv_process_filename, - adv_process_filename, - NULL); + adv_child = start_command (adv_process_command, + NULL); } @@ -874,6 +1021,7 @@ show_qrcode (const char *uri) const char *dddash; stop_advertising (); + hide_error (); if (0 > qrDisplay.devicefd) return; /* no display, no dice */ /* find the fourth '/' in the payto://pay/hostname/-uri */ @@ -1149,6 +1297,7 @@ mdb_shutdown (void) GNUNET_SCHEDULER_cancel (mdb.wtask); mdb.wtask = NULL; } + hide_error (); stop_advertising (); if (disable_mdb) return; @@ -1385,8 +1534,12 @@ wallet_select_aid (void *cls) pa->task = NULL; /* append the taler wallet aid to the select file command */ - memcpy (message, select_file, sizeof (select_file)); - memcpy (&message[sizeof (select_file)], taler_aid, sizeof (taler_aid)); + memcpy (message, + select_file, + sizeof (select_file)); + memcpy (&message[sizeof (select_file)], + taler_aid, + sizeof (taler_aid)); /* send the select file command via nfc */ GNUNET_log (GNUNET_ERROR_TYPE_INFO, @@ -1567,6 +1720,7 @@ check_payment_cb (void *cls, hr->http_status, (int) hr->ec); mdb.cmd = &cmd_reader_display_backend_not_reachable; + temporary_error ("backend-unexpected-failure"); run_mdb_event_loop (); cleanup_payment (pa); GNUNET_assert (payment_activity == pa); @@ -1575,9 +1729,8 @@ check_payment_cb (void *cls, } GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Backend request to /check-payment returned: %u/%d\n", - hr->http_status, - (int) osr->details.ok.status); + "Backend request to /check-payment returned: %u\n", + hr->http_status); if ( (MHD_HTTP_OK == hr->http_status) && (TALER_MERCHANT_OSC_PAID == osr->details.ok.status) ) { @@ -1674,6 +1827,7 @@ proposal_cb (void *cls, json_dumpf (por->hr.reply, stderr, 0); + temporary_error ("backend-temporary-failure"); mdb.cmd = &cmd_reader_display_backend_not_reachable; run_mdb_event_loop (); cleanup_payment (pa); @@ -1832,6 +1986,7 @@ launch_payment (struct Product *product) { GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "TALER_MERCHANT_order_put failed (out of memory?)\n"); + temporary_error ("internal-failure"); cleanup_payment (pa); return NULL; } @@ -2429,8 +2584,8 @@ handle_command (const char *hex, "Received command with wrong checksum `%.*s'\n", (int) hex_len, hex); + temporary_error ("err-num-read-fail"); break; - } unsigned int product; @@ -2466,6 +2621,7 @@ handle_command (const char *hex, "Product %s sold out, denying vend\n", products[i].description); mdb.cmd = &cmd_reader_display_sold_out; + temporary_error ("err-sold-out"); return; } payment_activity = launch_payment (&products[i]); @@ -2476,6 +2632,7 @@ handle_command (const char *hex, GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Unknown product %u selected on MDB, denying vend\n", product); + temporary_error ("unknown-product"); mdb.cmd = &cmd_deny_vend; break; } @@ -3203,10 +3360,14 @@ run (void *cls, global_ret = EXIT_FAILURE; return; } - (void) GNUNET_CONFIGURATION_get_value_filename (cfg, - "taler-mdb", - "ADVERTISEMENT_BINARY", - &adv_process_filename); + (void) GNUNET_CONFIGURATION_get_value_string (cfg, + "taler-mdb", + "ADVERTISEMENT_COMMAND", + &adv_process_command); + (void) GNUNET_CONFIGURATION_get_value_string (cfg, + "taler-mdb", + "FAIL_COMMAND", + &err_process_command); if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_string (cfg, "taler-mdb", |