summaryrefslogtreecommitdiff
path: root/src/backend/taler-merchant-httpd_get-orders-ID.c
diff options
context:
space:
mode:
authorJonathan Buchanan <jonathan.russ.buchanan@gmail.com>2020-08-19 03:28:38 -0400
committerJonathan Buchanan <jonathan.russ.buchanan@gmail.com>2020-08-19 03:28:38 -0400
commitb77ef665b0f3876f2c27db2d5a9b154fa1a9ba0d (patch)
tree37f482c473bf00f78218bdc1305d0980f5486895 /src/backend/taler-merchant-httpd_get-orders-ID.c
parent807b6e0b125100b1dd8ec56521517522a0cbfd4f (diff)
downloadmerchant-b77ef665b0f3876f2c27db2d5a9b154fa1a9ba0d.tar.gz
merchant-b77ef665b0f3876f2c27db2d5a9b154fa1a9ba0d.tar.bz2
merchant-b77ef665b0f3876f2c27db2d5a9b154fa1a9ba0d.zip
long poll for pending refunds
Diffstat (limited to 'src/backend/taler-merchant-httpd_get-orders-ID.c')
-rw-r--r--src/backend/taler-merchant-httpd_get-orders-ID.c472
1 files changed, 14 insertions, 458 deletions
diff --git a/src/backend/taler-merchant-httpd_get-orders-ID.c b/src/backend/taler-merchant-httpd_get-orders-ID.c
index d6a52f40..142ba999 100644
--- a/src/backend/taler-merchant-httpd_get-orders-ID.c
+++ b/src/backend/taler-merchant-httpd_get-orders-ID.c
@@ -35,97 +35,6 @@
*/
#define MAX_RETRIES 5
-/**
- * Information we keep for each coin to be refunded.
- */
-struct CoinRefund
-{
-
- /**
- * Kept in a DLL.
- */
- struct CoinRefund *next;
-
- /**
- * Kept in a DLL.
- */
- struct CoinRefund *prev;
-
- /**
- * Request to connect to the target exchange.
- */
- struct TMH_EXCHANGES_FindOperation *fo;
-
- /**
- * Handle for the refund operation with the exchange.
- */
- struct TALER_EXCHANGE_RefundHandle *rh;
-
- /**
- * Request this operation is part of.
- */
- struct GetOrderData *god;
-
- /**
- * URL of the exchange for this @e coin_pub.
- */
- char *exchange_url;
-
- /**
- * Fully reply from the exchange, only possibly set if
- * we got a JSON reply and a non-#MHD_HTTP_OK error code
- */
- json_t *exchange_reply;
-
- /**
- * When did the merchant grant the refund. To be used to group events
- * in the wallet.
- */
- struct GNUNET_TIME_Absolute execution_time;
-
- /**
- * Coin to refund.
- */
- struct TALER_CoinSpendPublicKeyP coin_pub;
-
- /**
- * Refund transaction ID to use.
- */
- uint64_t rtransaction_id;
-
- /**
- * Unique serial number identifying the refund.
- */
- uint64_t refund_serial;
-
- /**
- * Amount to refund.
- */
- struct TALER_Amount refund_amount;
-
- /**
- * Public key of the exchange affirming the refund.
- */
- struct TALER_ExchangePublicKeyP exchange_pub;
-
- /**
- * Signature of the exchange affirming the refund.
- */
- struct TALER_ExchangeSignatureP exchange_sig;
-
- /**
- * HTTP status from the exchange, #MHD_HTTP_OK if
- * @a exchange_pub and @a exchange_sig are valid.
- */
- unsigned int exchange_status;
-
- /**
- * HTTP error code from the exchange.
- */
- enum TALER_ErrorCode exchange_code;
-
-};
-
/**
* Context for the operation.
@@ -156,16 +65,6 @@ struct GetOrderData
struct GetOrderData *prev;
/**
- * Refunds for this order. Head of DLL.
- */
- struct CoinRefund *cr_head;
-
- /**
- * Refunds for this order. Tail of DLL.
- */
- struct CoinRefund *cr_tail;
-
- /**
* Context of the request.
*/
struct TMH_HandlerContext *hc;
@@ -653,144 +552,6 @@ send_pay_request (struct GetOrderData *god,
/**
- * Check if @a god has sub-activities still pending.
- *
- * @param god request to check
- * @return true if activities are still pending
- */
-static bool
-god_pending (struct GetOrderData *god)
-{
- for (struct CoinRefund *cr = god->cr_head;
- NULL != cr;
- cr = cr->next)
- {
- if ( (NULL != cr->fo) ||
- (NULL != cr->rh) )
- return true;
- }
- return false;
-}
-
-
-/**
- * Check if @a god is ready to be resumed, and if so, do it.
- *
- * @param god refund request to be possibly ready
- */
-static void
-check_resume_god (struct GetOrderData *god)
-{
- if (god_pending (god))
- return;
- GNUNET_CONTAINER_DLL_remove (god_head,
- god_tail,
- god);
- GNUNET_assert (god->suspended);
- god->suspended = false;
- MHD_resume_connection (god->sc.con);
- TMH_trigger_daemon ();
-}
-
-
-//#if 0
-/**
- * Callbacks of this type are used to serve the result of submitting a
- * refund request to an exchange.
- *
- * @param cls a `struct CoinRefund`
- * @param hr HTTP response data
- * @param exchange_pub exchange key used to sign refund confirmation
- * @param exchange_sig exchange's signature over refund
- */
-static void
-refund_cb (void *cls,
- const struct TALER_EXCHANGE_HttpResponse *hr,
- const struct TALER_ExchangePublicKeyP *exchange_pub,
- const struct TALER_ExchangeSignatureP *exchange_sig)
-{
- struct CoinRefund *cr = cls;
-
- cr->rh = NULL;
- cr->exchange_status = hr->http_status;
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Exchange refund status for coin %s is %u\n",
- TALER_B2S (&cr->coin_pub),
- hr->http_status);
- if (MHD_HTTP_OK != hr->http_status)
- {
- cr->exchange_code = hr->ec;
- cr->exchange_reply = json_incref ((json_t*) hr->reply);
- }
- else
- {
- enum GNUNET_DB_QueryStatus qs;
-
- cr->exchange_pub = *exchange_pub;
- cr->exchange_sig = *exchange_sig;
- qs = TMH_db->insert_refund_proof (TMH_db->cls,
- cr->refund_serial,
- exchange_sig,
- exchange_pub);
- if (0 >= qs)
- {
- /* generally, this is relatively harmless for the merchant, but let's at
- least log this. */
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Failed to persist exchange response to /refund in database: %d\n",
- qs);
- }
- }
- check_resume_god (cr->god);
-}
-//#endif
-
-
-//#if 0
-/**
- * Function called with the result of a #TMH_EXCHANGES_find_exchange()
- * operation.
- *
- * @param cls a `struct CoinRefund *`
- * @param hr HTTP response details
- * @param eh handle to the exchange context
- * @param payto_uri payto://-URI of the exchange
- * @param wire_fee current applicable wire fee for dealing with @a eh, NULL if not available
- * @param exchange_trusted true if this exchange is trusted by config
- */
-static void
-exchange_found_cb (void *cls,
- const struct TALER_EXCHANGE_HttpResponse *hr,
- struct TALER_EXCHANGE_Handle *eh,
- const char *payto_uri,
- const struct TALER_Amount *wire_fee,
- bool exchange_trusted)
-{
- struct CoinRefund *cr = cls;
-
- (void) payto_uri;
- cr->fo = NULL;
- if (TALER_EC_NONE == hr->ec)
- {
- cr->rh = TALER_EXCHANGE_refund (eh,
- &cr->refund_amount,
- &cr->god->h_contract_terms,
- &cr->coin_pub,
- cr->rtransaction_id,
- &cr->god->hc->instance->merchant_priv,
- &refund_cb,
- cr);
- return;
- }
- cr->exchange_status = hr->http_status;
- cr->exchange_code = hr->ec;
- cr->exchange_reply = json_incref ((json_t*) hr->reply);
- check_resume_god (cr->god);
-}
-//#endif
-
-
-/**
* Function called with detailed information about a refund.
* It is responsible for packing up the data to return.
*
@@ -816,24 +577,12 @@ process_refunds_cb (void *cls,
bool pending)
{
struct GetOrderData *god = cls;
- struct CoinRefund *cr;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Found refund of %s for coin %s with reason `%s' in database\n",
TALER_amount2s (refund_amount),
TALER_B2S (coin_pub),
reason);
- cr = GNUNET_new (struct CoinRefund);
- cr->refund_serial = refund_serial;
- cr->exchange_url = GNUNET_strdup (exchange_url);
- cr->god = god;
- cr->coin_pub = *coin_pub;
- cr->rtransaction_id = rtransaction_id;
- cr->refund_amount = *refund_amount;
- cr->execution_time = timestamp;
- GNUNET_CONTAINER_DLL_insert (god->cr_head,
- god->cr_tail,
- cr);
if (god->refunded)
{
GNUNET_assert (0 <=
@@ -849,42 +598,6 @@ process_refunds_cb (void *cls,
/**
- * Clean up refund processing.
- *
- * @param god handle to clean up refund processing for
- */
-static void
-rf_cleanup (struct GetOrderData *god)
-{
- struct CoinRefund *cr;
-
- while (NULL != (cr = god->cr_head))
- {
- GNUNET_CONTAINER_DLL_remove (god->cr_head,
- god->cr_tail,
- cr);
- if (NULL != cr->fo)
- {
- TMH_EXCHANGES_find_exchange_cancel (cr->fo);
- cr->fo = NULL;
- }
- if (NULL != cr->rh)
- {
- TALER_EXCHANGE_refund_cancel (cr->rh);
- cr->rh = NULL;
- }
- if (NULL != cr->exchange_reply)
- {
- json_decref (cr->exchange_reply);
- cr->exchange_reply = NULL;
- }
- GNUNET_free (cr->exchange_url);
- GNUNET_free (cr);
- }
-}
-
-
-/**
* Clean up the session state for a GET /orders/$ID request.
*
* @param cls must be a `struct GetOrderData *`
@@ -894,7 +607,6 @@ god_cleanup (void *cls)
{
struct GetOrderData *god = cls;
- rf_cleanup (god);
if (NULL != god->contract_terms)
json_decref (god->contract_terms);
GNUNET_free (god);
@@ -1005,7 +717,6 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh,
}
}
-#if 0
{
const char *await_refund_obtained_s;
@@ -1019,7 +730,6 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh,
? 0 == strcasecmp (await_refund_obtained_s, "yes")
: false;
}
-#endif
{
const char *min_refund;
@@ -1302,19 +1012,8 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh,
}
}
- /* Before we reset the refunds, make sure we notify the client in the case
- of a non-200 status from the exchange. */
- for (struct CoinRefund *cr = god->cr_head;
- NULL != cr;
- cr = cr->next)
- {
- if (MHD_HTTP_OK != cr->exchange_status)
- goto REPLY;
- }
-
/* At this point, we know the contract was paid. Let's check for
refunds. First, clear away refunds found from previous invocations. */
- rf_cleanup (god);
GNUNET_assert (GNUNET_OK == TALER_amount_get_zero (TMH_currency,
&god->refund_amount));
qs = TMH_db->lookup_refunds_detailed (TMH_db->cls,
@@ -1331,66 +1030,12 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh,
"Failed to lookup refunds for contract");
}
-//#if 0
- /* Now launch exchange interactions, unless we already have the
- response in the database! */
- for (struct CoinRefund *cr = god->cr_head;
- NULL != cr;
- cr = cr->next)
- {
- enum GNUNET_DB_QueryStatus qs;
-
- qs = TMH_db->lookup_refund_proof (TMH_db->cls,
- cr->refund_serial,
- &cr->exchange_sig,
- &cr->exchange_pub);
- switch (qs)
- {
- case GNUNET_DB_STATUS_HARD_ERROR:
- case GNUNET_DB_STATUS_SOFT_ERROR:
- return TALER_MHD_reply_with_error (connection,
- MHD_HTTP_INTERNAL_SERVER_ERROR,
- TALER_EC_GET_ORDERS_DB_LOOKUP_ERROR,
- "Merchant database error");
- case GNUNET_DB_STATUS_SUCCESS_NO_RESULTS:
- /* We need to talk to the exchange */
- cr->fo = TMH_EXCHANGES_find_exchange (cr->exchange_url,
- NULL,
- GNUNET_NO,
- &exchange_found_cb,
- cr);
- break;
- case GNUNET_DB_STATUS_SUCCESS_ONE_RESULT:
- /* We got a reply earlier, set status accordingly */
- cr->exchange_status = MHD_HTTP_OK;
- break;
- }
- }
-//#endif
-#if 0
- if ( (god->sc.awaiting_refund_obtained) &&
- (god->refund_available))
- {
- /* Client is waiting for pending refunds to be picked up, suspend
- until timeout */
- struct GNUNET_TIME_Relative remaining;
-
- remaining = GNUNET_TIME_absolute_get_remaining (god->sc.long_poll_timeout);
- if (0 != remaining.rel_value_us)
- {
- /* yes, indeed suspend */
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Awaiting pending refunds\n");
- suspend_god (god);
- return MHD_YES;
- }
- }
-#endif
-
- if ( (god->sc.awaiting_refund) &&
- ( (! god->refunded) ||
- (1 != TALER_amount_cmp (&god->refund_amount,
- &god->sc.refund_expected)) ) )
+ if ( ((god->sc.awaiting_refund) &&
+ ( (! god->refunded) ||
+ (1 != TALER_amount_cmp (&god->refund_amount,
+ &god->sc.refund_expected)) )) ||
+ ((god->sc.awaiting_refund_obtained) &&
+ (god->refund_available)) )
{
/* Client is waiting for a refund larger than what we have, suspend
until timeout */
@@ -1400,106 +1045,21 @@ TMH_get_orders_ID (const struct TMH_RequestHandler *rh,
if (0 != remaining.rel_value_us)
{
/* yes, indeed suspend */
+ if (god->sc.awaiting_refund)
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Awaiting refund exceeding %s\n",
+ TALER_amount2s (&god->sc.refund_expected));
+ if (god->sc.awaiting_refund_obtained)
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Awaiting refund exceeding %s\n",
+ "Awaiting pending refunds\n",
TALER_amount2s (&god->sc.refund_expected));
suspend_god (god);
return MHD_YES;
}
}
- /* Check if there are still exchange operations pending */
- if (god_pending (god))
- {
- if (! god->suspended)
- {
- god->suspended = true;
- MHD_suspend_connection (connection);
- GNUNET_CONTAINER_DLL_insert (god_head,
- god_tail,
- god);
- }
- return MHD_YES; /* we're still talking to the exchange */
- }
-
/* All operations done, build final response */
-REPLY:
{
- json_t *ra;
-
- ra = json_array ();
- GNUNET_assert (NULL != ra);
- for (struct CoinRefund *cr = god->cr_head;
- NULL != cr;
- cr = cr->next)
- {
- json_t *refund;
-
- if (MHD_HTTP_OK != cr->exchange_status)
- {
- if (NULL == cr->exchange_reply)
- {
- refund = json_pack ("{s:s, s:I,s:I,s:o,s:o,s:o}"
- "type",
- "failure",
- "exchange_status",
- (json_int_t) cr->exchange_status,
- "rtransaction_id",
- (json_int_t) cr->rtransaction_id,
- "coin_pub",
- GNUNET_JSON_from_data_auto (&cr->coin_pub),
- "refund_amount",
- TALER_JSON_from_amount (&cr->refund_amount),
- "execution_time",
- GNUNET_JSON_from_time_abs (cr->execution_time));
- }
- else
- {
- refund = json_pack ("{s:s,s:I,s:I,s:O,s:I,s:o,s:o,s:o}"
- "type",
- "failure",
- "exchange_status",
- (json_int_t) cr->exchange_status,
- "exchange_code",
- (json_int_t) cr->exchange_code,
- "exchange_reply",
- cr->exchange_reply,
- "rtransaction_id",
- (json_int_t) cr->rtransaction_id,
- "coin_pub",
- GNUNET_JSON_from_data_auto (&cr->coin_pub),
- "refund_amount",
- TALER_JSON_from_amount (&cr->refund_amount),
- "execution_time",
- GNUNET_JSON_from_time_abs (cr->execution_time));
- }
- }
- else
- {
- refund = json_pack ("{s:s,s:I,s:o,s:o,s:I,s:o,s:o,s:o}",
- "type",
- "success",
- "exchange_status",
- (json_int_t) cr->exchange_status,
- "exchange_sig",
- GNUNET_JSON_from_data_auto (&cr->exchange_sig),
- "exchange_pub",
- GNUNET_JSON_from_data_auto (&cr->exchange_pub),
- "rtransaction_id",
- (json_int_t) cr->rtransaction_id,
- "coin_pub",
- GNUNET_JSON_from_data_auto (&cr->coin_pub),
- "refund_amount",
- TALER_JSON_from_amount (&cr->refund_amount),
- "execution_time",
- GNUNET_JSON_from_time_abs (cr->execution_time));
- }
- GNUNET_assert (
- 0 ==
- json_array_append_new (ra,
- refund));
- }
-
if (god->generate_html)
{
enum GNUNET_GenericReturnValue res;
@@ -1587,15 +1147,11 @@ REPLY:
return TALER_MHD_reply_json_pack (
connection,
MHD_HTTP_OK,
- "{s:b, s:b, s:o, s:o, s:o}",
+ "{s:b, s:b, s:o}",
"refunded", god->refunded,
"refund_pending", god->refund_available,
"refund_amount",
- TALER_JSON_from_amount (&god->refund_amount),
- "refunds",
- ra,
- "merchant_pub",
- GNUNET_JSON_from_data_auto (&hc->instance->merchant_pub));
+ TALER_JSON_from_amount (&god->refund_amount));
}
}
}