diff options
Diffstat (limited to 'src/backend/taler-merchant-httpd.c')
-rw-r--r-- | src/backend/taler-merchant-httpd.c | 474 |
1 files changed, 8 insertions, 466 deletions
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c index d48c2f92..f95beb3e 100644 --- a/src/backend/taler-merchant-httpd.c +++ b/src/backend/taler-merchant-httpd.c @@ -137,23 +137,6 @@ static int merchant_connection_close; static int result; /** - * MIN-Heap of suspended connections to resume when the timeout expires, - * ordered by timeout. Values are of type `struct MHD_Connection` - */ -static struct GNUNET_CONTAINER_Heap *resume_timeout_heap; - -/** - * Hash map from H(order_id,merchant_pub) to `struct MHD_Connection` - * entries to resume when a payment is made for the given order. - */ -static struct GNUNET_CONTAINER_MultiHashMap *payment_trigger_map; - -/** - * Task responsible for timeouts in the #resume_timeout_heap. - */ -static struct GNUNET_SCHEDULER_Task *resume_timeout_task; - -/** * Our configuration. */ static const struct GNUNET_CONFIGURATION_Handle *cfg; @@ -164,24 +147,6 @@ static const struct GNUNET_CONFIGURATION_Handle *cfg; char *TMH_default_auth; -/** - * Holds data needed to determine when to resume a connection for - * GET /orders/$ORDER_ID - */ -struct ResumeData -{ - /** - * How much of the order has been refunded. - */ - const struct TALER_Amount *refund_amount; - - /** - * Whether the refunds for the order were obtained. - */ - bool obtained; -}; - - int TMH_check_auth (const char *token, const struct GNUNET_ShortHashCode *salt, @@ -292,393 +257,6 @@ TMH_instance_free_cb (void *cls, /** - * Callback that frees all the elements in the #payment_trigger_map. - * This function should actually never be called, as by the time we - * get to it, all payment triggers should have been cleaned up! - * - * @param cls closure, NULL - * @param key current key - * @param value a `struct TMH_SuspendedConnection` - * @return #GNUNET_OK - */ -static int -payment_trigger_free (void *cls, - const struct GNUNET_HashCode *key, - void *value) -{ - struct TMH_SuspendedConnection *sc = value; - - (void) cls; - (void) key; - (void) sc; /* cannot really 'clean up' */ - GNUNET_break (0); - return GNUNET_OK; -} - - -/** - * Compute @a key to use for @a order_id and @a mpub in our - * #payment_trigger_map. - * - * @param order_id an order ID - * @param mpub an instance public key - * @param[out] key set to the hash map key to use - */ -static void -compute_pay_key (const char *order_id, - const struct TALER_MerchantPublicKeyP *mpub, - struct GNUNET_HashCode *key) -{ - size_t olen = strlen (order_id); - char buf[sizeof (*mpub) + olen]; - - /* sanity check for arithmetic overflow */ - GNUNET_assert (olen < 1024 * 1024); - memcpy (buf, - mpub, - sizeof (*mpub)); - memcpy (&buf[sizeof (*mpub)], - order_id, - olen); - GNUNET_CRYPTO_hash (buf, - sizeof (buf), - key); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Pay key for `%s' is %s\n", - order_id, - GNUNET_h2s (key)); -} - - -/** - * Compute @a key to use for @a session_id and @a fulfillment_url in our - * #payment_trigger_map. - * - * @param session_id the session for which @a fulfillment_url matters - * @param fulfillment_url fullfillment URL of an order - * @param[out] key set to the hash map key to use - */ -static void -compute_pay_key2 (const char *session_id, - const char *fulfillment_url, - struct GNUNET_HashCode *key) -{ - size_t slen = strlen (session_id) + 1; - size_t ulen = strlen (fulfillment_url) + 1; - char buf[slen + ulen]; - - memcpy (buf, - session_id, - slen); - memcpy (&buf[slen], - fulfillment_url, - ulen); - GNUNET_CRYPTO_hash (buf, - sizeof (buf), - key); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Pay key2 for %s/%s is %s\n", - session_id, - fulfillment_url, - GNUNET_h2s (key)); -} - - -/** - * Resume processing all suspended connections past timeout. - * - * @param cls unused - */ -static void -do_resume (void *cls) -{ - struct TMH_SuspendedConnection *sc; - - (void) cls; - resume_timeout_task = NULL; - while (1) - { - sc = GNUNET_CONTAINER_heap_peek (resume_timeout_heap); - if (NULL == sc) - return; - if (GNUNET_TIME_absolute_is_future (sc->long_poll_timeout)) - break; - GNUNET_assert (sc == - GNUNET_CONTAINER_heap_remove_root (resume_timeout_heap)); - sc->hn = NULL; - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (payment_trigger_map, - &sc->key, - sc)); - if (sc->has_key2) - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (payment_trigger_map, - &sc->key2, - sc)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Resuming long polled job due to timeout\n"); - MHD_resume_connection (sc->con); - TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ - } - if (NULL != resume_timeout_task) - GNUNET_SCHEDULER_cancel (resume_timeout_task); - resume_timeout_task = GNUNET_SCHEDULER_add_at (sc->long_poll_timeout, - &do_resume, - NULL); -} - - -/** - * Suspend connection from @a sc until payment has been received. - * - * @param order_id the order that we are waiting on - * @param session_id session ID of the requester - * @param fulfillment_url fulfillment URL of the contract - * @param mi the merchant instance we are waiting on - * @param sc connection to suspend - * @param min_refund refund amount we are waiting on to be exceeded before resuming, - * NULL if we are not waiting for refunds - */ -void -TMH_long_poll_suspend (const char *order_id, - const char *session_id, - const char *fulfillment_url, - const struct TMH_MerchantInstance *mi, - struct TMH_SuspendedConnection *sc, - const struct TALER_Amount *min_refund) -{ - compute_pay_key (order_id, - &mi->merchant_pub, - &sc->key); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Suspending operation on key %s\n", - GNUNET_h2s (&sc->key)); - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (payment_trigger_map, - &sc->key, - sc, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); - if ( (NULL != session_id) && - (NULL != fulfillment_url) ) - { - sc->has_key2 = true; - compute_pay_key2 (session_id, - fulfillment_url, - &sc->key2); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Suspending operation on %s/%s key2 %s\n", - session_id, - fulfillment_url, - GNUNET_h2s (&sc->key2)); - GNUNET_assert (GNUNET_OK == - GNUNET_CONTAINER_multihashmap_put (payment_trigger_map, - &sc->key2, - sc, - GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE)); - } - if (NULL != min_refund) - { - sc->awaiting_refund = true; - sc->refund_expected = *min_refund; - } - sc->hn = GNUNET_CONTAINER_heap_insert (resume_timeout_heap, - sc, - sc->long_poll_timeout.abs_value_us); - MHD_suspend_connection (sc->con); - if (NULL != resume_timeout_task) - { - GNUNET_SCHEDULER_cancel (resume_timeout_task); - resume_timeout_task = NULL; - } - sc = GNUNET_CONTAINER_heap_peek (resume_timeout_heap); - resume_timeout_task = GNUNET_SCHEDULER_add_at (sc->long_poll_timeout, - &do_resume, - NULL); -} - - -/** - * Function called to resume suspended connections. - * - * @param cls pointer to a `struct TALER_Amount` indicating the refund amount, or NULL - * @param key key in the #payment_trigger_map - * @param value a `struct TMH_SuspendedConnection` to resume - * @return #GNUNET_OK (continue to iterate) - */ -static int -resume_operation (void *cls, - const struct GNUNET_HashCode *key, - void *value) -{ - const struct ResumeData *rd = cls; - struct TMH_SuspendedConnection *sc = value; - - GNUNET_assert (0 == - GNUNET_memcmp (key, - &sc->key)); - /* If the conditions are satisfied partially, turn them off for future - calls. */ - if ( (sc->awaiting_refund_obtained) && - (rd->obtained)) - sc->awaiting_refund_obtained = false; - if ( (sc->awaiting_refund) && - ( (NULL != rd->refund_amount) && - (1 == TALER_amount_cmp (rd->refund_amount, - &sc->refund_expected)) ) ) - sc->awaiting_refund = false; - - if ( (sc->awaiting_refund_obtained) && - (! rd->obtained)) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Not awaking client, refunds not yet obtained\n"); - return GNUNET_OK; - } - if ( (sc->awaiting_refund) && - ( (NULL == rd->refund_amount) || - (1 != TALER_amount_cmp (rd->refund_amount, - &sc->refund_expected)) ) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Not awaking client, refund amount of %s not yet satisfied\n", - TALER_amount2s (&sc->refund_expected)); - return GNUNET_OK; /* skip */ - } - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Resuming operation suspended pending payment on key %s\n", - GNUNET_h2s (key)); - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (payment_trigger_map, - key, - sc)); - if (sc->has_key2) - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (payment_trigger_map, - &sc->key2, - sc)); - GNUNET_assert (sc == - GNUNET_CONTAINER_heap_remove_node (sc->hn)); - sc->hn = NULL; - MHD_resume_connection (sc->con); - TALER_MHD_daemon_trigger (); - return GNUNET_OK; -} - - -/** - * Find out if we have any clients long-polling for @a order_id to be - * confirmed at merchant @a mpub, and if so, tell them to resume. - * - * @param order_id the order that was paid or refunded - * @param mi the merchant instance where the payment or refund happened - * @param refund_amount refunded amount, if the trigger was a refund, otherwise NULL - * @param obtained if true, the wallet has obtained the refunds for the order - */ -void -TMH_long_poll_resume (const char *order_id, - const struct TMH_MerchantInstance *mi, - const struct TALER_Amount *refund_amount, - bool obtained) -{ - struct GNUNET_HashCode key; - struct ResumeData rd = { - .refund_amount = refund_amount, - .obtained = obtained - }; - int ret; - - compute_pay_key (order_id, - &mi->merchant_pub, - &key); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Resuming operations suspended pending payment on key %s up to refund %s\n", - GNUNET_h2s (&key), - (NULL != refund_amount) - ? TALER_amount2s (refund_amount) - : "<none>"); - ret = GNUNET_CONTAINER_multihashmap_get_multiple (payment_trigger_map, - &key, - &resume_operation, - (void *) &rd); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "%u operations remain suspended pending payment (%d)\n", - GNUNET_CONTAINER_multihashmap_size (payment_trigger_map), - ret); -} - - -/** - * Function called to resume suspended connections. - * - * @param cls NULL - * @param key key in the #payment_trigger_map - * @param value a `struct TMH_SuspendedConnection` to resume - * @return #GNUNET_OK (continue to iterate) - */ -static int -resume_operation2 (void *cls, - const struct GNUNET_HashCode *key, - void *value) -{ - struct TMH_SuspendedConnection *sc = value; - - GNUNET_assert (sc->has_key2); - GNUNET_assert (0 == GNUNET_memcmp (key, - &sc->key2)); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Resuming operation suspended pending payment on key %s\n", - GNUNET_h2s (key)); - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (payment_trigger_map, - &sc->key, - sc)); - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (payment_trigger_map, - &sc->key2, - sc)); - GNUNET_assert (sc == - GNUNET_CONTAINER_heap_remove_node (sc->hn)); - sc->hn = NULL; - MHD_resume_connection (sc->con); - TALER_MHD_daemon_trigger (); - return GNUNET_OK; -} - - -/** - * Find out if we have any clients long-polling for @a order_id to be - * confirmed at merchant @a mpub, and if so, tell them to resume. - * - * @param session_id the session for which @a fulfillment_url became paid - * @param fulfillment_url fullfillment URL of which an order was paid - */ -void -TMH_long_poll_resume2 (const char *session_id, - const char *fulfillment_url) -{ - struct GNUNET_HashCode key; - int ret; - - compute_pay_key2 (session_id, - fulfillment_url, - &key); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "Resuming operations suspended pending payment on %s/%s with key2 %s\n", - session_id, - fulfillment_url, - GNUNET_h2s (&key)); - ret = GNUNET_CONTAINER_multihashmap_get_multiple (payment_trigger_map, - &key, - &resume_operation2, - NULL); - GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, - "%u operations remain suspended pending payment (%d)\n", - GNUNET_CONTAINER_multihashmap_size (payment_trigger_map), - ret); -} - - -/** * Shutdown task (magically invoked when the application is being * quit) * @@ -687,9 +265,6 @@ TMH_long_poll_resume2 (const char *session_id, static void do_shutdown (void *cls) { - struct TMH_SuspendedConnection *sc; - struct MHD_Daemon *mhd; - (void) cls; TMH_force_ac_resume (); TMH_force_pc_resume (); @@ -698,27 +273,12 @@ do_shutdown (void *cls) TMH_force_tip_pickup_resume (); TMH_force_wallet_get_order_resume (); TMH_force_wallet_refund_order_resume (); - mhd = TALER_MHD_daemon_stop (); - /* resume all suspended connections, must be done before stopping #mhd */ - if (NULL != resume_timeout_heap) { - while (NULL != (sc = GNUNET_CONTAINER_heap_remove_root ( - resume_timeout_heap))) - { - sc->hn = NULL; - GNUNET_assert (GNUNET_YES == - GNUNET_CONTAINER_multihashmap_remove (payment_trigger_map, - &sc->key, - sc)); - MHD_resume_connection (sc->con); - } - GNUNET_CONTAINER_heap_destroy (resume_timeout_heap); - resume_timeout_heap = NULL; - } - if (NULL != mhd) - { - MHD_stop_daemon (mhd); - mhd = NULL; + struct MHD_Daemon *mhd; + + mhd = TALER_MHD_daemon_stop (); + if (NULL != mhd) + MHD_stop_daemon (mhd); } TMH_RESERVES_done (); if (NULL != instance_eh) @@ -733,19 +293,6 @@ do_shutdown (void *cls) } TMH_EXCHANGES_done (); TMH_AUDITORS_done (); - if (NULL != resume_timeout_task) - { - GNUNET_SCHEDULER_cancel (resume_timeout_task); - resume_timeout_task = NULL; - } - if (NULL != payment_trigger_map) - { - GNUNET_CONTAINER_multihashmap_iterate (payment_trigger_map, - &payment_trigger_free, - NULL); - GNUNET_CONTAINER_multihashmap_destroy (payment_trigger_map); - payment_trigger_map = NULL; - } if (NULL != TMH_by_id_map) { GNUNET_CONTAINER_multihashmap_iterate (TMH_by_id_map, @@ -2019,7 +1566,7 @@ load_instances (void *cls, ( (0 == extra_len) || ('\0' != id[extra_len - 1]) ) ) { - GNUNET_break (0); /* bogus notification */ + GNUNET_break (0 == extra_len); extra = NULL; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, @@ -2073,7 +1620,7 @@ TMH_reload_instances (const char *id) { struct GNUNET_DB_EventHeaderP es = { es.size = ntohs (sizeof (es)), - es.type = ntohs (sizeof (TALER_DBEVENT_MERCHANT_INSTANCE_SETTINGS)) + es.type = ntohs (TALER_DBEVENT_MERCHANT_INSTANCE_SETTINGS) }; GNUNET_log (GNUNET_ERROR_TYPE_INFO, @@ -2127,11 +1674,6 @@ run (void *cls, result = GNUNET_SYSERR; GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); - resume_timeout_heap - = GNUNET_CONTAINER_heap_create (GNUNET_CONTAINER_HEAP_ORDER_MIN); - payment_trigger_map - = GNUNET_CONTAINER_multihashmap_create (16, - GNUNET_YES); if (GNUNET_OK != TALER_config_get_currency (cfg, &TMH_currency)) @@ -2209,7 +1751,7 @@ run (void *cls, { struct GNUNET_DB_EventHeaderP es = { es.size = ntohs (sizeof (es)), - es.type = ntohs (sizeof (TALER_DBEVENT_MERCHANT_INSTANCE_SETTINGS)) + es.type = ntohs (TALER_DBEVENT_MERCHANT_INSTANCE_SETTINGS) }; instance_eh = TMH_db->event_listen (TMH_db->cls, |