diff options
author | Christian Grothoff <christian@grothoff.org> | 2024-10-01 14:05:42 +0200 |
---|---|---|
committer | Christian Grothoff <christian@grothoff.org> | 2024-10-01 14:05:42 +0200 |
commit | 12c8aeb66e1a1f8dc8b4cefa78c11459e6a657d3 (patch) | |
tree | b56a74c94bdafe79626398a80a997b34f631d257 | |
parent | 1e2a6651223c41f9c3ed09c2e98678d175b0e2cc (diff) |
fix #9197: wait at most 250ms for /keys from exchanges before giving up
-rw-r--r-- | src/backend/taler-merchant-httpd_private-post-orders.c | 71 | ||||
-rw-r--r-- | src/include/taler_merchant_service.h | 15 |
2 files changed, 86 insertions, 0 deletions
diff --git a/src/backend/taler-merchant-httpd_private-post-orders.c b/src/backend/taler-merchant-httpd_private-post-orders.c index 7053ac70..c1583791 100644 --- a/src/backend/taler-merchant-httpd_private-post-orders.c +++ b/src/backend/taler-merchant-httpd_private-post-orders.c @@ -68,6 +68,14 @@ */ #define STANDARD_LABEL_MERCHANT_ADDRESS "_ma" +/** + * How long do we wait at most for /keys from the exchange(s)? + * Ensures that we do not block forever just because some exchange + * fails to respond *or* because our taler-merchant-keyscheck + * refuses a forced download. + */ +#define MAX_KEYS_WAIT \ + GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MILLISECONDS, 250) /** * Generate the base URL for the given merchant instance. @@ -449,6 +457,17 @@ struct OrderContext * order creation requests exceeds legal limits. */ struct TALER_Amount total_exchange_limit; + + /** + * How long do we wait at most until giving up on getting keys? + */ + struct GNUNET_TIME_Absolute keys_timeout; + + /** + * Task to wake us up on @e keys_timeout. + */ + struct GNUNET_SCHEDULER_Task *wakeup_task; + } set_exchanges; /** @@ -664,6 +683,11 @@ clean_order (void *cls) GNUNET_free (rx->url); GNUNET_free (rx); } + if (NULL != oc->set_exchanges.wakeup_task) + { + GNUNET_SCHEDULER_cancel (oc->set_exchanges.wakeup_task); + oc->set_exchanges.wakeup_task = NULL; + } if (NULL != oc->set_exchanges.exchanges) { json_decref (oc->set_exchanges.exchanges); @@ -2105,6 +2129,28 @@ notify_kyc_required (const struct OrderContext *oc) /** + * Task run when we are timing out on /keys and will just + * proceed with what we got. + * + * @param cls our `struct OrderContext *` to resume + */ +static void +wakeup_timeout (void *cls) +{ + struct OrderContext *oc = cls; + + oc->set_exchanges.wakeup_task = NULL; + GNUNET_assert (GNUNET_YES == oc->suspended); + GNUNET_CONTAINER_DLL_remove (oc_head, + oc_tail, + oc); + MHD_resume_connection (oc->connection); + oc->suspended = GNUNET_NO; + TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ +} + + +/** * Set list of acceptable exchanges in @a oc. Upon success, continue * processing with set_max_fee(). * @@ -2114,6 +2160,11 @@ notify_kyc_required (const struct OrderContext *oc) static bool set_exchanges (struct OrderContext *oc) { + if (NULL != oc->set_exchanges.wakeup_task) + { + GNUNET_SCHEDULER_cancel (oc->set_exchanges.wakeup_task); + oc->set_exchanges.wakeup_task = NULL; + } if (TALER_amount_is_zero (&oc->parse_order.brutto)) { /* Total amount is zero, so we don't actually need exchanges! */ @@ -2127,6 +2178,8 @@ set_exchanges (struct OrderContext *oc) matter. */ if (NULL == oc->set_exchanges.exchanges) { + oc->set_exchanges.keys_timeout + = GNUNET_TIME_relative_to_absolute (MAX_KEYS_WAIT); oc->set_exchanges.exchanges = json_array (); GNUNET_assert (NULL != oc->set_exchanges.exchanges); GNUNET_assert ( @@ -2147,11 +2200,29 @@ set_exchanges (struct OrderContext *oc) oc); } } + if (GNUNET_TIME_absolute_is_past (oc->set_exchanges.keys_timeout)) + { + struct RekeyExchange *rx; + + while (NULL != (rx = oc->set_exchanges.pending_reload_head)) + { + GNUNET_CONTAINER_DLL_remove (oc->set_exchanges.pending_reload_head, + oc->set_exchanges.pending_reload_tail, + rx); + TMH_EXCHANGES_keys4exchange_cancel (rx->fo); + GNUNET_free (rx->url); + GNUNET_free (rx); + } + } if (NULL != oc->set_exchanges.pending_reload_head) { GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Still trying to (re)load %skeys\n", oc->set_exchanges.pending_reload_head->url); + oc->set_exchanges.wakeup_task + = GNUNET_SCHEDULER_add_at (oc->set_exchanges.keys_timeout, + &wakeup_timeout, + oc); MHD_suspend_connection (oc->connection); oc->suspended = GNUNET_YES; GNUNET_CONTAINER_DLL_insert (oc_head, diff --git a/src/include/taler_merchant_service.h b/src/include/taler_merchant_service.h index 05ea273b..0ad7dc75 100644 --- a/src/include/taler_merchant_service.h +++ b/src/include/taler_merchant_service.h @@ -3239,6 +3239,21 @@ struct TALER_MERCHANT_PayResponse // TODO: might want to return further details on errors, // especially refund signatures on double-pay conflict. + struct + { + + /** + * Array of exchange URLs which had legal problems. + */ + const char **exchanges; + + /** + * Length of the @e exchanges array. + */ + unsigned int num_exchanges; + + } unavailable_for_legal_reasons; + } details; }; |