aboutsummaryrefslogtreecommitdiff
path: root/src/backend/taler-merchant-httpd.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/taler-merchant-httpd.c')
-rw-r--r--src/backend/taler-merchant-httpd.c474
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,