summaryrefslogtreecommitdiff
path: root/src/backend/taler-merchant-httpd_tip-pickup.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/taler-merchant-httpd_tip-pickup.c')
-rw-r--r--src/backend/taler-merchant-httpd_tip-pickup.c167
1 files changed, 110 insertions, 57 deletions
diff --git a/src/backend/taler-merchant-httpd_tip-pickup.c b/src/backend/taler-merchant-httpd_tip-pickup.c
index cfcbd052..9d90464e 100644
--- a/src/backend/taler-merchant-httpd_tip-pickup.c
+++ b/src/backend/taler-merchant-httpd_tip-pickup.c
@@ -73,10 +73,19 @@ struct PickupContext
/**
* Placeholder for #TALER_MHD_parse_post_json() to keep its internal state.
*/
-
void *json_parse_context;
/**
+ * Kept in a DLL while suspended.
+ */
+ struct PickupContext *next;
+
+ /**
+ * Kept in a DLL while suspended.
+ */
+ struct PickupContext *prev;
+
+ /**
* URL of the exchange this tip uses.
*/
char *exchange_url;
@@ -134,10 +143,45 @@ struct PickupContext
*/
const char *error_hint;
+ /**
+ * Set to #GNUNET_YES if @e connection was suspended.
+ */
+ int suspended;
+
};
/**
+ * Kept in a DLL while suspended.
+ */
+static struct PickupContext *pc_head;
+
+/**
+ * Kept in a DLL while suspended.
+ */
+static struct PickupContext *pc_tail;
+
+
+/**
+ * We are shutting down, force resuming all suspended pickup operations.
+ */
+void
+MH_force_tip_pickup_resume ()
+{
+ struct PickupContext *pc;
+
+ while (NULL != (pc = pc_head))
+ {
+ GNUNET_assert (GNUNET_YES == pc->suspended);
+ GNUNET_CONTAINER_DLL_remove (pc_head,
+ pc_tail,
+ pc);
+ MHD_resume_connection (pc->connection);
+ }
+}
+
+
+/**
* Custom cleanup routine for a `struct PickupContext`.
*
* @param hc the `struct PickupContext` to clean up.
@@ -274,38 +318,36 @@ run_pickup (struct MHD_Connection *connection,
* operation.
*
* @param cls closure with the `struct PickupContext`
+ * @param hr HTTP response details
* @param eh handle to the exchange context
* @param wire_fee current applicable wire fee for dealing with @a eh, NULL if not available
* @param exchange_trusted #GNUNET_YES if this exchange is trusted by config
- * @param ec error code, #TALER_EC_NONE on success
- * @param http_status the HTTP status we got from the exchange
- * @param error_reply the full reply from the exchange, NULL if
- * the response was NOT in JSON or on success
*/
static void
exchange_found_cb (void *cls,
+ const struct TALER_EXCHANGE_HttpResponse *hr,
struct TALER_EXCHANGE_Handle *eh,
const struct TALER_Amount *wire_fee,
- int exchange_trusted,
- enum TALER_ErrorCode ec,
- unsigned int http_status,
- const json_t *error_reply)
+ int exchange_trusted)
{
struct PickupContext *pc = cls;
const struct TALER_EXCHANGE_Keys *keys;
- struct GNUNET_HashContext *hc;
struct TALER_Amount total;
int ae;
pc->fo = NULL;
+ GNUNET_assert (GNUNET_YES == pc->suspended);
+ GNUNET_CONTAINER_DLL_remove (pc_head,
+ pc_tail,
+ pc);
MHD_resume_connection (pc->connection);
+ TMH_trigger_daemon ();
if (NULL == eh)
{
// FIXME: #6014: forward error details!
pc->ec = TALER_EC_TIP_PICKUP_EXCHANGE_DOWN;
pc->error_hint = "failed to contact exchange, check URL";
pc->response_code = MHD_HTTP_FAILED_DEPENDENCY;
- TMH_trigger_daemon ();
return;
}
keys = TALER_EXCHANGE_get_keys (eh);
@@ -316,7 +358,6 @@ exchange_found_cb (void *cls,
pc->error_hint =
"could not obtain denomination keys from exchange, check URL";
pc->response_code = MHD_HTTP_FAILED_DEPENDENCY;
- TMH_trigger_daemon ();
return;
}
GNUNET_assert (0 != pc->planchets_len);
@@ -327,68 +368,70 @@ exchange_found_cb (void *cls,
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Calculating tip amount over %u planchets!\n",
pc->planchets_len);
- hc = GNUNET_CRYPTO_hash_context_start ();
- for (unsigned int i = 0; i<pc->planchets_len; i++)
{
- struct PlanchetDetail *pd = &pc->planchets[i];
- const struct TALER_EXCHANGE_DenomPublicKey *dk;
- struct TALER_Amount amount_with_fee;
+ struct GNUNET_HashContext *hc;
- dk = TALER_EXCHANGE_get_denomination_key_by_hash (keys,
- &pd->wr.h_denomination_pub);
- if (NULL == dk)
- {
- pc->ec = TALER_EC_TIP_PICKUP_EXCHANGE_LACKED_KEY;
- pc->error_hint = "could not find matching denomination key";
- pc->response_code = MHD_HTTP_NOT_FOUND;
- GNUNET_CRYPTO_hash_context_abort (hc);
- TMH_trigger_daemon ();
- return;
- }
- GNUNET_CRYPTO_hash_context_read (hc,
- &pd->wr.h_denomination_pub,
- sizeof (struct GNUNET_HashCode));
- GNUNET_CRYPTO_hash_context_read (hc,
- pd->coin_ev,
- pd->coin_ev_size);
- if (0 >
- TALER_amount_add (&amount_with_fee,
- &dk->value,
- &dk->fee_withdraw))
- {
- ae = GNUNET_YES;
- }
- if (0 == i)
- {
- total = amount_with_fee;
- }
- else
+ hc = GNUNET_CRYPTO_hash_context_start ();
+ for (unsigned int i = 0; i<pc->planchets_len; i++)
{
+ struct PlanchetDetail *pd = &pc->planchets[i];
+ const struct TALER_EXCHANGE_DenomPublicKey *dk;
+ struct TALER_Amount amount_with_fee;
+
+ dk = TALER_EXCHANGE_get_denomination_key_by_hash (keys,
+ &pd->wr.
+ h_denomination_pub);
+ if (NULL == dk)
+ {
+ pc->ec = TALER_EC_TIP_PICKUP_EXCHANGE_LACKED_KEY;
+ pc->error_hint = "could not find matching denomination key";
+ pc->response_code = MHD_HTTP_NOT_FOUND;
+ GNUNET_CRYPTO_hash_context_abort (hc);
+ return;
+ }
+ GNUNET_CRYPTO_hash_context_read (hc,
+ &pd->wr.h_denomination_pub,
+ sizeof (struct GNUNET_HashCode));
+ GNUNET_CRYPTO_hash_context_read (hc,
+ pd->coin_ev,
+ pd->coin_ev_size);
if (0 >
- TALER_amount_add (&total,
- &total,
- &amount_with_fee))
+ TALER_amount_add (&amount_with_fee,
+ &dk->value,
+ &dk->fee_withdraw))
{
ae = GNUNET_YES;
}
+ if (0 == i)
+ {
+ total = amount_with_fee;
+ }
+ else
+ {
+ if (0 >
+ TALER_amount_add (&total,
+ &total,
+ &amount_with_fee))
+ {
+ ae = GNUNET_YES;
+ }
+ }
+ TALER_amount_hton (&pd->wr.withdraw_fee,
+ &dk->fee_withdraw);
+ TALER_amount_hton (&pd->wr.amount_with_fee,
+ &amount_with_fee);
}
- TALER_amount_hton (&pd->wr.withdraw_fee,
- &dk->fee_withdraw);
- TALER_amount_hton (&pd->wr.amount_with_fee,
- &amount_with_fee);
+ GNUNET_CRYPTO_hash_context_finish (hc,
+ &pc->pickup_id);
}
- GNUNET_CRYPTO_hash_context_finish (hc,
- &pc->pickup_id);
if (GNUNET_YES == ae)
{
pc->ec = TALER_EC_TIP_PICKUP_EXCHANGE_AMOUNT_OVERFLOW;
pc->error_hint = "error computing total value of the tip";
pc->response_code = MHD_HTTP_BAD_REQUEST;
- TMH_trigger_daemon ();
return;
}
pc->total = total;
- TMH_trigger_daemon ();
}
@@ -406,6 +449,10 @@ prepare_pickup (struct PickupContext *pc)
enum GNUNET_DB_QueryStatus qs;
db->preflight (db->cls);
+ /* FIXME: do not pass NULL's, *do* get the
+ data from the DB, we may be able to avoid
+ most of the processing if we already have
+ a valid result! */
qs = db->lookup_tip_by_id (db->cls,
&pc->tip_id,
&pc->exchange_url,
@@ -453,6 +500,12 @@ prepare_pickup (struct PickupContext *pc)
TALER_EC_INTERNAL_INVARIANT_FAILURE,
"consult server logs");
}
+ /* continued asynchronously in exchange_found_cb() */
+ GNUNET_assert (GNUNET_NO == pc->suspended);
+ pc->suspended = GNUNET_YES;
+ GNUNET_CONTAINER_DLL_insert (pc_head,
+ pc_tail,
+ pc);
MHD_suspend_connection (pc->connection);
return MHD_YES;
}