From 175162ba4469d7a6bbee7dd9d5dcd2e2d9195e01 Mon Sep 17 00:00:00 2001 From: Christian Grothoff Date: Fri, 12 Jun 2020 10:22:12 +0200 Subject: do not forget to kick MHD --- src/backend/taler-merchant-httpd.c | 1 + .../taler-merchant-httpd_post-tips-ID-pickup.c | 8 + .../taler-merchant-httpd_private-get-orders-ID.c | 201 +++++++++++++++------ .../taler-merchant-httpd_private-get-orders.c | 2 + 4 files changed, 156 insertions(+), 56 deletions(-) (limited to 'src/backend') diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c index a73feabc..1aad33fd 100644 --- a/src/backend/taler-merchant-httpd.c +++ b/src/backend/taler-merchant-httpd.c @@ -291,6 +291,7 @@ do_resume (void *cls) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Resuming long polled job due to timeout\n"); MHD_resume_connection (sc->con); + TMH_trigger_daemon (); /* we resumed, kick MHD */ } resume_timeout_task = GNUNET_SCHEDULER_add_at (sc->long_poll_timeout, &do_resume, diff --git a/src/backend/taler-merchant-httpd_post-tips-ID-pickup.c b/src/backend/taler-merchant-httpd_post-tips-ID-pickup.c index e6437c39..bf1e3297 100644 --- a/src/backend/taler-merchant-httpd_post-tips-ID-pickup.c +++ b/src/backend/taler-merchant-httpd_post-tips-ID-pickup.c @@ -297,6 +297,7 @@ withdraw_cb (void *cls, "exchange_http_status", (json_int_t) hr->http_status, "exchange_reply", hr->reply); MHD_resume_connection (pc->connection); + TMH_trigger_daemon (); /* we resumed, kick MHD */ return; } qs = TMH_db->insert_pickup_blind_signature (TMH_db->cls, @@ -311,12 +312,14 @@ withdraw_cb (void *cls, TALER_EC_TIP_PICKUP_DB_STORE_HARD_ERROR, "Could not store blind signature in DB"); MHD_resume_connection (pc->connection); + TMH_trigger_daemon (); /* we resumed, kick MHD */ return; } if (NULL == pc->po_head) { stop_operations (pc); /* stops timeout job */ MHD_resume_connection (pc->connection); + TMH_trigger_daemon (); /* we resumed, kick MHD */ } } @@ -360,6 +363,7 @@ do_withdraw (void *cls, "exchange_http_status", (json_int_t) hr->http_status, "exchange_reply", hr->reply); MHD_resume_connection (pc->connection); + TMH_trigger_daemon (); /* we resumed, kick MHD */ return; } po->w2h = TALER_EXCHANGE_withdraw2 (eh, @@ -423,6 +427,7 @@ do_timeout (void *cls) TALER_EC_TIP_PICKUP_EXCHANGE_TIMEOUT, "Timeout trying to withdraw from exchange (try again later)"); MHD_resume_connection (pc->connection); + TMH_trigger_daemon (); /* we resumed, kick MHD */ } @@ -464,6 +469,7 @@ compute_total_requested (void *cls, "exchange_http_status", (json_int_t) hr->http_status, "exchange_reply", hr->reply); MHD_resume_connection (pc->connection); + TMH_trigger_daemon (); /* we resumed, kick MHD */ return; } TALER_amount_get_zero (TMH_currency, @@ -486,6 +492,7 @@ compute_total_requested (void *cls, "exchange_http_status", (json_int_t) hr->http_status, "exchange_reply", hr->reply); MHD_resume_connection (pc->connection); + TMH_trigger_daemon (); /* we resumed, kick MHD */ return; } @@ -502,6 +509,7 @@ compute_total_requested (void *cls, TALER_MHD_make_error (TALER_EC_TIP_PICKUP_SUMMATION_FAILED, "Could not add up values to compute pickup total"); MHD_resume_connection (pc->connection); + TMH_trigger_daemon (); /* we resumed, kick MHD */ return; } } diff --git a/src/backend/taler-merchant-httpd_private-get-orders-ID.c b/src/backend/taler-merchant-httpd_private-get-orders-ID.c index 5635d634..336d83fa 100644 --- a/src/backend/taler-merchant-httpd_private-get-orders-ID.c +++ b/src/backend/taler-merchant-httpd_private-get-orders-ID.c @@ -164,11 +164,17 @@ struct GetOrderRequestContext json_t *contract_terms; /** - * Wire details for the payment, to be returned to the query. NULL + * Wire details for the payment, to be returned in the reply. NULL * if not available. */ json_t *wire_details; + /** + * Problems we encountered when looking up Wire details + * for the payment, to be returned. NULL if not available. + */ + json_t *wire_reports; + /** * Details about refunds, NULL if there are no refunds. */ @@ -230,6 +236,11 @@ struct GetOrderRequestContext */ enum TALER_ErrorCode wire_ec; + /** + * HTTP status to return with @e wire_ec, 0 if @e wire_ec is #TALER_EC_NONE. + */ + unsigned int wire_hc; + /** * Set to true if this payment has been refunded and * @e refund_amount is initialized. @@ -257,15 +268,17 @@ static struct GetOrderRequestContext *gorc_tail; /** + * Resume processing the request, cancelling all pending asynchronous + * operations. * * @param gorc request to resume + * @param http_status HTTP status to return, 0 to continue with success * @param ec error code for the request, #TALER_EC_NONE on success - * @param exchange_hr details from exchange, NULL if exchange is blameless */ static void gorc_resume (struct GetOrderRequestContext *gorc, - enum TALER_ErrorCode ec, - const struct TALER_EXCHANGE_HttpResponse *exchange_hr) + unsigned int http_status, + enum TALER_ErrorCode ec) { struct TransferQuery *tq; @@ -287,16 +300,58 @@ gorc_resume (struct GetOrderRequestContext *gorc, tq->dgh = NULL; } } + gorc->wire_hc = http_status; gorc->wire_ec = ec; - if (NULL != exchange_hr) - { - gorc->exchange_hc = exchange_hr->http_status; - gorc->exchange_ec = exchange_hr->ec; - } GNUNET_CONTAINER_DLL_remove (gorc_head, gorc_tail, gorc); MHD_resume_connection (gorc->sc.con); + TMH_trigger_daemon (); /* we resumed, kick MHD */ +} + + +/** + * Add a report about trouble obtaining wire transfer data to the reply. + * + * @param gorc request to add wire report to + * @param ec error code to add + * @param hint human-readable hint + * @param coin_pub public key of the affected coin + * @param exchange_hr details from exchange, NULL if exchange is blameless + */ +static void +gorc_report (struct GetOrderRequestContext *gorc, + enum TALER_ErrorCode ec, + const char *hint, + struct TALER_CoinSpendPublicKeyP *coin_pub, + const struct TALER_EXCHANGE_HttpResponse *exchange_hr) +{ + if (NULL != exchange_hr) + GNUNET_assert (0 == + json_array_append_new ( + gorc->wire_reports, + json_pack ("{s:I, s:s, s:o, s:I, s:I}", + "code", + (json_int_t) ec, + "hint", + hint, + "coin_pub", + GNUNET_JSON_from_data_auto (coin_pub), + "exchange_ec", + (json_int_t) exchange_hr->ec, + "exchange_hc", + (json_int_t) exchange_hr->http_status))); + else + GNUNET_assert (0 == + json_array_append_new ( + gorc->wire_reports, + json_pack ("{s:I, s:s, s:o}", + "code", + (json_int_t) ec, + "hint", + hint, + "coin_pub", + GNUNET_JSON_from_data_auto (coin_pub)))); } @@ -313,8 +368,8 @@ exchange_timeout_cb (void *cls) gorc->tt = NULL; gorc_resume (gorc, - TALER_EC_GET_ORDERS_EXCHANGE_TIMEOUT, - NULL); + MHD_HTTP_REQUEST_TIMEOUT, + TALER_EC_GET_ORDERS_EXCHANGE_TIMEOUT); } @@ -338,10 +393,16 @@ deposit_get_cb (void *cls, tq); if (NULL == dd) { - gorc_resume (gorc, + gorc_report (gorc, TALER_EC_GET_ORDERS_EXCHANGE_TRACKING_FAILURE, + "Exchange failed to return tracking data", + &tq->coin_pub, hr); GNUNET_free (tq); + if (NULL == gorc->tq_head) + gorc_resume (gorc, + 0, + TALER_EC_NONE); return; } else if (MHD_HTTP_OK == hr->http_status) @@ -353,10 +414,16 @@ deposit_get_cb (void *cls, dd); if (qs < 0) { - gorc_resume (gorc, + gorc_report (gorc, TALER_EC_GET_ORDERS_DB_STORE_TRACKING_FAILURE, + "Merchant backend failed to store transfer details in DB", + &tq->coin_pub, NULL); GNUNET_free (tq); + if (NULL == gorc->tq_head) + gorc_resume (gorc, + 0, + TALER_EC_NONE); return; } /* Compute total amount *wired* */ @@ -365,10 +432,16 @@ deposit_get_cb (void *cls, &gorc->deposits_total, &dd->coin_contribution)) { - gorc_resume (gorc, + gorc_report (gorc, TALER_EC_GET_ORDERS_AMOUNT_ARITHMETIC_FAILURE, + "Merchant backend could not sum up deposit total", + &tq->coin_pub, NULL); GNUNET_free (tq); + if (NULL == gorc->tq_head) + gorc_resume (gorc, + 0, + TALER_EC_NONE); return; } if (0 > @@ -376,24 +449,35 @@ deposit_get_cb (void *cls, &gorc->deposit_fees_total, &tq->deposit_fee)) { - gorc_resume (gorc, + gorc_report (gorc, TALER_EC_GET_ORDERS_AMOUNT_ARITHMETIC_FAILURE, + "Merchant backend could not sum up deposit fees", + &tq->coin_pub, NULL); GNUNET_free (tq); + if (NULL == gorc->tq_head) + gorc_resume (gorc, + 0, + TALER_EC_NONE); return; } } else { /* got a 'preliminary' reply from the exchange, simply skip */ + gorc_report (gorc, + TALER_EC_NONE, + "Exchange returned preliminary response", + &tq->coin_pub, + hr); } GNUNET_free (tq); if (NULL != gorc->tq_head) return; /* *all* are done, resume! */ gorc_resume (gorc, - TALER_EC_NONE, - NULL); + 0, + TALER_EC_NONE); } @@ -427,9 +511,11 @@ exchange_found_cb (void *cls, gorc->tq_tail, tq); GNUNET_free (tq); + gorc->exchange_hc = hr->http_status; + gorc->exchange_ec = hr->ec; gorc_resume (gorc, - TALER_EC_GET_ORDERS_EXCHANGE_LOOKUP_FAILURE, - hr); + MHD_HTTP_FAILED_DEPENDENCY, + TALER_EC_GET_ORDERS_EXCHANGE_LOOKUP_FAILURE); return; } tq->dgh = TALER_EXCHANGE_deposits_get (eh, @@ -446,8 +532,8 @@ exchange_found_cb (void *cls, tq); GNUNET_free (tq); gorc_resume (gorc, - TALER_EC_GET_ORDERS_EXCHANGE_REQUEST_FAILURE, - NULL); + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GET_ORDERS_EXCHANGE_REQUEST_FAILURE); } } @@ -498,8 +584,8 @@ deposit_cb (void *cls, if (NULL == tq->fo) { gorc_resume (gorc, - TALER_EC_GET_ORDERS_EXCHANGE_LOOKUP_FAILURE, - NULL); + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GET_ORDERS_EXCHANGE_LOOKUP_START_FAILURE); } } @@ -520,6 +606,8 @@ gorc_cleanup (void *cls) json_decref (gorc->wire_details); if (NULL != gorc->refund_details) json_decref (gorc->refund_details); + if (NULL != gorc->wire_reports) + json_decref (gorc->wire_reports); GNUNET_assert (NULL == gorc->tt); GNUNET_free (gorc); } @@ -551,11 +639,6 @@ process_refunds_cb (void *cls, { struct GetOrderRequestContext *gorc = cls; - if (NULL == gorc->refund_details) - { - gorc->refund_details = json_array (); - GNUNET_assert (NULL != gorc->refund_details); - } GNUNET_assert (0 == json_array_append_new ( gorc->refund_details, @@ -566,15 +649,6 @@ process_refunds_cb (void *cls, GNUNET_JSON_from_time_abs (timestamp), "reason", reason))); - if (gorc->refunded) - { - GNUNET_assert (0 <= - TALER_amount_add (&gorc->refund_amount, - &gorc->refund_amount, - refund_amount)); - return; - } - /* For refunded coins, we are not charged deposit fees, so subtract those again */ for (struct TransferQuery *tq = gorc->tq_head; @@ -591,7 +665,10 @@ process_refunds_cb (void *cls, &tq->deposit_fee)); } } - gorc->refund_amount = *refund_amount; + GNUNET_assert (0 <= + TALER_amount_add (&gorc->refund_amount, + &gorc->refund_amount, + refund_amount)); gorc->refunded = true; } @@ -669,12 +746,18 @@ TMH_private_get_orders_ID (const struct TMH_RequestHandler *rh, if (NULL == gorc) { /* First time here, parse request and check order is known */ + GNUNET_assert (NULL != hc->infix); gorc = GNUNET_new (struct GetOrderRequestContext); hc->cc = &gorc_cleanup; hc->ctx = gorc; gorc->sc.con = connection; gorc->hc = hc; - GNUNET_assert (NULL != hc->infix); + gorc->wire_details = json_array (); + GNUNET_assert (NULL != gorc->wire_details); + gorc->refund_details = json_array (); + GNUNET_assert (NULL != gorc->refund_details); + gorc->wire_reports = json_array (); + GNUNET_assert (NULL != gorc->wire_reports); gorc->session_id = MHD_lookup_connection_value (connection, MHD_GET_ARGUMENT_KIND, "session_id"); @@ -792,15 +875,19 @@ TMH_private_get_orders_ID (const struct TMH_RequestHandler *rh, &gorc->h_contract_terms)) { GNUNET_break (0); - return (MHD_YES == - TALER_MHD_reply_with_error (connection, - MHD_HTTP_INTERNAL_SERVER_ERROR, - TALER_EC_GET_ORDERS_FAILED_COMPUTE_PROPOSAL_HASH, - "Failed to hash contract terms")) - ? GNUNET_NO - : GNUNET_SYSERR; + return TALER_MHD_reply_with_error (connection, + MHD_HTTP_INTERNAL_SERVER_ERROR, + TALER_EC_GET_ORDERS_FAILED_COMPUTE_PROPOSAL_HASH, + "Failed to hash contract terms"); } } + if (TALER_EC_NONE != gorc->wire_ec) + { + return TALER_MHD_reply_with_error (connection, + gorc->wire_hc, + gorc->wire_ec, + "Failed to obtain wire details"); + } GNUNET_assert (NULL != gorc->contract_terms); @@ -926,6 +1013,9 @@ TMH_private_get_orders_ID (const struct TMH_RequestHandler *rh, /* Accumulate refunds, if any. */ { + GNUNET_assert (GNUNET_OK == + TALER_amount_get_zero (TMH_currency, + &gorc->refund_amount)); qs = TMH_db->lookup_refunds_detailed (TMH_db->cls, hc->instance->settings.id, &gorc->h_contract_terms, @@ -945,8 +1035,6 @@ TMH_private_get_orders_ID (const struct TMH_RequestHandler *rh, { MHD_RESULT ret; - gorc->wire_details = json_array (); - GNUNET_assert (NULL != gorc->wire_details); GNUNET_assert (GNUNET_OK == TALER_amount_get_zero (TMH_currency, &gorc->deposits_total)); @@ -1008,10 +1096,10 @@ TMH_private_get_orders_ID (const struct TMH_RequestHandler *rh, ret = TALER_MHD_reply_json_pack (connection, MHD_HTTP_OK, - "{s:I, s:I, s:I, s:o, s:O," - " s:b, s:b, s:o?, s:o?, s:o?}", - "wire_ec", - (json_int_t) gorc->wire_ec, + "{s:o, s:I, s:I, s:o, s:O," + " s:b, s:b, s:b, s:o, s:o, s:o}", + "wire_reports", + gorc->wire_reports, "exchange_ec", (json_int_t) gorc->exchange_ec, "exchange_hc", @@ -1025,16 +1113,17 @@ TMH_private_get_orders_ID (const struct TMH_RequestHandler *rh, true, "refunded", gorc->refunded, + "wired", + wired, "refund_amount", - (gorc->refunded) - ? TALER_JSON_from_amount ( - &gorc->refund_amount) - : NULL, + TALER_JSON_from_amount ( + &gorc->refund_amount), "wire_details", gorc->wire_details, "refund_details", gorc->refund_details); gorc->wire_details = NULL; + gorc->wire_reports = NULL; gorc->refund_details = NULL; return ret; } diff --git a/src/backend/taler-merchant-httpd_private-get-orders.c b/src/backend/taler-merchant-httpd_private-get-orders.c index e8351511..669a2e3b 100644 --- a/src/backend/taler-merchant-httpd_private-get-orders.c +++ b/src/backend/taler-merchant-httpd_private-get-orders.c @@ -162,6 +162,7 @@ order_timeout (void *cls) po); json_decref (po->pa); MHD_resume_connection (po->con); + TMH_trigger_daemon (); /* we resumed, kick MHD */ GNUNET_free (po->instance_id); GNUNET_free (po); } @@ -285,6 +286,7 @@ TMH_notify_order_change (const char *instance_id, GNUNET_assert (po == GNUNET_CONTAINER_heap_remove_node (po->hn)); MHD_resume_connection (po->con); + TMH_trigger_daemon (); /* we resumed, kick MHD */ json_decref (po->pa); GNUNET_free (po->instance_id); GNUNET_free (po); -- cgit v1.2.3