aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2023-06-25 16:09:11 +0200
committerChristian Grothoff <christian@grothoff.org>2023-06-25 16:09:11 +0200
commit0d8aeec575f6e12bb06a5eedeabf70436058595a (patch)
treecf119dc4cc4463763fce2566a504d549145b1367
parentbb0967ea0f5d501079981ea33f21f4c133815234 (diff)
-adapt to latest exchange API change
-rw-r--r--src/backend/taler-merchant-httpd_exchanges.c402
-rw-r--r--src/backend/taler-merchant-httpd_exchanges.h80
-rw-r--r--src/backend/taler-merchant-httpd_post-orders-ID-pay.c213
3 files changed, 580 insertions, 115 deletions
diff --git a/src/backend/taler-merchant-httpd_exchanges.c b/src/backend/taler-merchant-httpd_exchanges.c
index 090cef95..5bce19a4 100644
--- a/src/backend/taler-merchant-httpd_exchanges.c
+++ b/src/backend/taler-merchant-httpd_exchanges.c
@@ -104,6 +104,86 @@ struct TMH_EXCHANGES_FindOperation
/**
+ * Information we keep for a pending #MMH_EXCHANGES_keys4exchange() operation.
+ */
+struct TMH_EXCHANGES_Find2Operation
+{
+
+ /**
+ * Kept in a DLL.
+ */
+ struct TMH_EXCHANGES_Find2Operation *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct TMH_EXCHANGES_Find2Operation *prev;
+
+ /**
+ * Function to call with the result.
+ */
+ TMH_EXCHANGES_Find2Continuation fc;
+
+ /**
+ * Closure for @e fc.
+ */
+ void *fc_cls;
+
+ /**
+ * Exchange we wait for the /keys for.
+ */
+ struct TMH_Exchange *my_exchange;
+
+ /**
+ * Task scheduled to asynchronously return the result to
+ * the find continuation.
+ */
+ struct GNUNET_SCHEDULER_Task *at;
+
+};
+
+
+/**
+ * Information we keep for a pending #MMH_EXCHANGES_wire4exchange() operation.
+ */
+struct TMH_EXCHANGES_WireOperation
+{
+
+ /**
+ * Kept in a DLL.
+ */
+ struct TMH_EXCHANGES_WireOperation *next;
+
+ /**
+ * Kept in a DLL.
+ */
+ struct TMH_EXCHANGES_WireOperation *prev;
+
+ /**
+ * Function to call with the result.
+ */
+ TMH_EXCHANGES_WireContinuation fc;
+
+ /**
+ * Closure for @e fc.
+ */
+ void *fc_cls;
+
+ /**
+ * Exchange we wait for the /wire for.
+ */
+ struct TMH_Exchange *my_exchange;
+
+ /**
+ * Task scheduled to asynchronously return the result to
+ * the find continuation.
+ */
+ struct GNUNET_SCHEDULER_Task *at;
+
+};
+
+
+/**
* Information about wire transfer fees of an exchange, by wire method.
*/
struct FeesByWireMethod
@@ -240,6 +320,26 @@ struct TMH_Exchange
struct TMH_EXCHANGES_FindOperation *fo_tail;
/**
+ * Head of FOs pending for this exchange.
+ */
+ struct TMH_EXCHANGES_Find2Operation *fo2_head;
+
+ /**
+ * Tail of FOs pending for this exchange.
+ */
+ struct TMH_EXCHANGES_Find2Operation *fo2_tail;
+
+ /**
+ * Head of /wire pending for this exchange.
+ */
+ struct TMH_EXCHANGES_WireOperation *w_head;
+
+ /**
+ * Tail of /wire pending for this exchange.
+ */
+ struct TMH_EXCHANGES_WireOperation *w_tail;
+
+ /**
* Head of accounts of this exchange.
*/
struct ExchangeAccount *acc_head;
@@ -891,8 +991,20 @@ static bool
process_find_operations (struct TMH_Exchange *exchange)
{
struct TMH_EXCHANGES_FindOperation *fn;
+ struct TMH_EXCHANGES_Find2Operation *fn2;
+ struct TMH_EXCHANGES_WireOperation *wn;
struct GNUNET_TIME_Timestamp now;
+ fn2 = NULL;
+ for (struct TMH_EXCHANGES_Find2Operation *fo = exchange->fo2_head;
+ NULL != fo;
+ fo = fn2)
+ {
+ fo->fc (fo->fc_cls,
+ TALER_EXCHANGE_get_keys (exchange->conn));
+ fn2 = fo->next;
+ TMH_EXCHANGES_keys4exchange_cancel (fo);
+ }
if (! exchange->have_wire)
return true;
now = GNUNET_TIME_timestamp_get ();
@@ -957,6 +1069,16 @@ process_find_operations (struct TMH_Exchange *exchange)
fn = fo->next;
TMH_EXCHANGES_find_exchange_cancel (fo);
}
+ wn = NULL;
+ for (struct TMH_EXCHANGES_WireOperation *w = exchange->w_head;
+ NULL != w;
+ w = wn)
+ {
+ w->fc (w->fc_cls,
+ exchange);
+ wn = w->next;
+ TMH_EXCHANGES_wire4exchange_cancel (w);
+ }
return false;
}
@@ -992,6 +1114,7 @@ handle_wire_data (void *cls,
if (MHD_HTTP_OK != wr->hr.http_status)
{
struct TMH_EXCHANGES_FindOperation *fo;
+ struct TMH_EXCHANGES_WireOperation *w;
exchange->have_wire = false;
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
@@ -1007,6 +1130,12 @@ handle_wire_data (void *cls,
false);
TMH_EXCHANGES_find_exchange_cancel (fo);
}
+ while (NULL != (w = exchange->w_head))
+ {
+ w->fc (w->fc_cls,
+ NULL);
+ TMH_EXCHANGES_wire4exchange_cancel (w);
+ }
return;
}
keys = TALER_EXCHANGE_get_keys (exchange->conn);
@@ -1024,6 +1153,7 @@ handle_wire_data (void *cls,
{
/* Report hard failure to all callbacks! */
struct TMH_EXCHANGES_FindOperation *fo;
+ struct TMH_EXCHANGES_Find2Operation *fo2;
struct TALER_EXCHANGE_HttpResponse hrx = {
.ec = ecx,
.http_status = 0,
@@ -1040,6 +1170,12 @@ handle_wire_data (void *cls,
false);
TMH_EXCHANGES_find_exchange_cancel (fo);
}
+ while (NULL != (fo2 = exchange->fo2_head))
+ {
+ fo2->fc (fo2->fc_cls,
+ NULL);
+ TMH_EXCHANGES_keys4exchange_cancel (fo2);
+ }
return;
}
exchange->have_wire = true;
@@ -1148,6 +1284,10 @@ free_exchange_entry (struct TMH_Exchange *exchange)
}
GNUNET_assert (NULL == exchange->fo_head);
GNUNET_assert (NULL == exchange->fo_tail);
+ GNUNET_assert (NULL == exchange->fo2_head);
+ GNUNET_assert (NULL == exchange->fo2_tail);
+ GNUNET_assert (NULL == exchange->w_head);
+ GNUNET_assert (NULL == exchange->w_tail);
GNUNET_free (exchange->url);
GNUNET_free (exchange);
}
@@ -1165,6 +1305,8 @@ fail_and_retry (struct TMH_Exchange *exchange,
const struct TALER_EXCHANGE_HttpResponse *hr)
{
struct TMH_EXCHANGES_FindOperation *fo;
+ struct TMH_EXCHANGES_Find2Operation *fo2;
+ struct TMH_EXCHANGES_WireOperation *w;
exchange->have_keys = false;
if (NULL != exchange->wire_request)
@@ -1185,6 +1327,18 @@ fail_and_retry (struct TMH_Exchange *exchange,
false);
TMH_EXCHANGES_find_exchange_cancel (fo);
}
+ while (NULL != (fo2 = exchange->fo2_head))
+ {
+ fo2->fc (fo2->fc_cls,
+ NULL);
+ TMH_EXCHANGES_keys4exchange_cancel (fo2);
+ }
+ while (NULL != (w = exchange->w_head))
+ {
+ w->fc (w->fc_cls,
+ NULL);
+ TMH_EXCHANGES_wire4exchange_cancel (w);
+ }
if ( (NULL == exchange->fo_head) &&
(TALER_EC_GENERIC_CONFIGURATION_INVALID == hr->ec) )
{
@@ -1345,6 +1499,38 @@ return_result (void *cls)
/**
+ * Task to return find operation result asynchronously to caller.
+ *
+ * @param cls a `struct TMH_EXCHANGES_Find2Operation`
+ */
+static void
+return_result2 (void *cls)
+{
+ struct TMH_EXCHANGES_Find2Operation *fo = cls;
+ struct TMH_Exchange *exchange = fo->my_exchange;
+
+ fo->at = NULL;
+ process_find_operations (exchange);
+}
+
+
+/**
+ * Task to return find operation result asynchronously to caller.
+ *
+ * @param cls a `struct TMH_EXCHANGES_WireOperation`
+ */
+static void
+return_wire_result (void *cls)
+{
+ struct TMH_EXCHANGES_WireOperation *w = cls;
+ struct TMH_Exchange *exchange = w->my_exchange;
+
+ w->at = NULL;
+ process_find_operations (exchange);
+}
+
+
+/**
* Lookup exchange by @a exchange_url.
*
* @param exchange_url base URL to match against
@@ -1481,6 +1667,188 @@ TMH_EXCHANGES_find_exchange (const char *chosen_exchange,
}
+struct TMH_EXCHANGES_Find2Operation *
+TMH_EXCHANGES_keys4exchange (
+ const char *chosen_exchange,
+ TMH_EXCHANGES_Find2Continuation fc,
+ void *fc_cls)
+{
+ struct TMH_Exchange *exchange;
+ struct TMH_EXCHANGES_Find2Operation *fo;
+
+ if (NULL == merchant_curl_ctx)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Trying to find chosen exchange `%s'\n",
+ chosen_exchange);
+ /* Check if the exchange is known */
+ exchange = lookup_exchange (chosen_exchange);
+ if (NULL == exchange)
+ {
+ /* This is a new exchange */
+ exchange = GNUNET_new (struct TMH_Exchange);
+ exchange->url = GNUNET_strdup (chosen_exchange);
+ GNUNET_CONTAINER_DLL_insert (exchange_head,
+ exchange_tail,
+ exchange);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "The exchange `%s' is new\n",
+ chosen_exchange);
+ }
+
+ fo = GNUNET_new (struct TMH_EXCHANGES_Find2Operation);
+ fo->fc = fc;
+ fo->fc_cls = fc_cls;
+ fo->my_exchange = exchange;
+ GNUNET_CONTAINER_DLL_insert (exchange->fo2_head,
+ exchange->fo2_tail,
+ fo);
+
+ if (GNUNET_TIME_absolute_is_past (exchange->first_retry))
+ {
+ /* increment exponential-backoff */
+ exchange->retry_delay = RETRY_BACKOFF (exchange->retry_delay);
+ /* do not allow forced check until both backoff and #FORCED_RELOAD_DELAY
+ are satisfied again */
+ exchange->first_retry
+ = GNUNET_TIME_relative_to_absolute (GNUNET_TIME_relative_max (
+ exchange->retry_delay,
+ FORCED_RELOAD_DELAY));
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "/keys retry forced, waiting until %s\n",
+ GNUNET_TIME_absolute2s (exchange->first_retry));
+ if (NULL == exchange->conn)
+ {
+ /* Not connected at all yet */
+ exchange->retry_task
+ = GNUNET_SCHEDULER_add_now (&retry_exchange,
+ exchange);
+ }
+ else
+ {
+ /* Use existing connection, but update /keys */
+ exchange->keys_expiration
+ = TALER_EXCHANGE_check_keys_current (exchange->conn,
+ TALER_EXCHANGE_CKF_FORCE_DOWNLOAD,
+ NULL,
+ NULL);
+ }
+ return fo;
+ }
+
+ if (exchange->have_keys)
+ {
+ /* We are not currently waiting for a reply, immediately
+ return result */
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "The exchange `%s' is ready\n",
+ exchange->url);
+ GNUNET_assert (NULL == fo->at);
+ fo->at = GNUNET_SCHEDULER_add_now (&return_result2,
+ fo);
+ return fo;
+ }
+
+ /* If new or resumed, (re)try fetching /keys */
+ if ( (NULL == exchange->conn) &&
+ (NULL == exchange->retry_task) &&
+ (! exchange->have_keys) )
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Do not have current /keys data for `%s'. Will request /keys now\n",
+ exchange->url);
+ exchange->retry_task = GNUNET_SCHEDULER_add_now (&retry_exchange,
+ exchange);
+ return fo;
+ }
+ /* No activity to launch, we are already doing so */
+ return fo;
+}
+
+
+struct TMH_EXCHANGES_WireOperation *
+TMH_EXCHANGES_wire4exchange (
+ const char *chosen_exchange,
+ TMH_EXCHANGES_WireContinuation fc,
+ void *fc_cls)
+{
+ struct TMH_Exchange *exchange;
+ struct TMH_EXCHANGES_WireOperation *w;
+
+ if (NULL == merchant_curl_ctx)
+ {
+ GNUNET_break (0);
+ return NULL;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "Trying to find chosen exchange `%s'\n",
+ chosen_exchange);
+ /* Check if the exchange is known */
+ exchange = lookup_exchange (chosen_exchange);
+ if (NULL == exchange)
+ {
+ /* This is a new exchange */
+ exchange = GNUNET_new (struct TMH_Exchange);
+ exchange->url = GNUNET_strdup (chosen_exchange);
+ GNUNET_CONTAINER_DLL_insert (exchange_head,
+ exchange_tail,
+ exchange);
+ GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+ "The exchange `%s' is new\n",
+ chosen_exchange);
+ }
+
+ w = GNUNET_new (struct TMH_EXCHANGES_WireOperation);
+ w->fc = fc;
+ w->fc_cls = fc_cls;
+ w->my_exchange = exchange;
+ GNUNET_CONTAINER_DLL_insert (exchange->w_head,
+ exchange->w_tail,
+ w);
+ if (exchange->have_wire)
+ {
+ /* We are not currently waiting for a reply, immediately
+ return result */
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "The exchange `%s' is ready\n",
+ exchange->url);
+ GNUNET_assert (NULL == w->at);
+ w->at = GNUNET_SCHEDULER_add_now (&return_wire_result,
+ w);
+ return w;
+ }
+
+ if (NULL == exchange->wire_request)
+ {
+ if (NULL == exchange->conn)
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Requesting /keys from `%s' to connect\n",
+ exchange->url);
+ exchange->conn = TALER_EXCHANGE_connect (merchant_curl_ctx,
+ exchange->url,
+ &keys_mgmt_cb,
+ exchange,
+ TALER_EXCHANGE_OPTION_END);
+ }
+ else
+ {
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Requesting /wire from `%s'\n",
+ exchange->url);
+ exchange->wire_request
+ = TALER_EXCHANGE_wire (exchange->conn,
+ &handle_wire_data,
+ exchange);
+ }
+ }
+ return w;
+}
+
+
void
TMH_EXCHANGES_find_exchange_cancel (struct TMH_EXCHANGES_FindOperation *fo)
{
@@ -1498,6 +1866,40 @@ TMH_EXCHANGES_find_exchange_cancel (struct TMH_EXCHANGES_FindOperation *fo)
}
+void
+TMH_EXCHANGES_keys4exchange_cancel (struct TMH_EXCHANGES_Find2Operation *fo)
+{
+ struct TMH_Exchange *exchange = fo->my_exchange;
+
+ if (NULL != fo->at)
+ {
+ GNUNET_SCHEDULER_cancel (fo->at);
+ fo->at = NULL;
+ }
+ GNUNET_CONTAINER_DLL_remove (exchange->fo2_head,
+ exchange->fo2_tail,
+ fo);
+ GNUNET_free (fo);
+}
+
+
+void
+TMH_EXCHANGES_wire4exchange_cancel (struct TMH_EXCHANGES_WireOperation *w)
+{
+ struct TMH_Exchange *exchange = w->my_exchange;
+
+ if (NULL != w->at)
+ {
+ GNUNET_SCHEDULER_cancel (w->at);
+ w->at = NULL;
+ }
+ GNUNET_CONTAINER_DLL_remove (exchange->w_head,
+ exchange->w_tail,
+ w);
+ GNUNET_free (w);
+}
+
+
/**
* Function called on each configuration section. Finds sections
* about exchanges, parses the entries and tries to connect to
diff --git a/src/backend/taler-merchant-httpd_exchanges.h b/src/backend/taler-merchant-httpd_exchanges.h
index 23424f40..89ba4030 100644
--- a/src/backend/taler-merchant-httpd_exchanges.h
+++ b/src/backend/taler-merchant-httpd_exchanges.h
@@ -100,10 +100,46 @@ typedef void
/**
+ * Function called with the result of a #TMH_EXCHANGES_keys4exchange()
+ * operation.
+ *
+ * @param cls closure
+ * @param keys the keys of the exchange
+ */
+typedef void
+(*TMH_EXCHANGES_Find2Continuation)(
+ void *cls,
+ struct TALER_EXCHANGE_Keys *keys);
+
+
+/**
+ * Function called with the result of a #TMH_EXCHANGES_wire4exchange()
+ * operation.
+ *
+ * @param cls closure
+ * @param wire the wire data of the exchange
+ */
+typedef void
+(*TMH_EXCHANGES_WireContinuation)(
+ void *cls,
+ struct TMH_Exchange *wire);
+
+
+/**
* Information we keep for a pending #MMH_EXCHANGES_find_exchange() operation.
*/
struct TMH_EXCHANGES_FindOperation;
+/**
+ * Information we keep for a pending #MMH_EXCHANGES_keys4exchange() operation.
+ */
+struct TMH_EXCHANGES_Find2Operation;
+
+/**
+ * Information we keep for a pending #MMH_EXCHANGES_wire4exchange() operation.
+ */
+struct TMH_EXCHANGES_WireOperation;
+
/**
* Find a exchange that matches @a chosen_exchange. If we cannot connect
@@ -124,6 +160,32 @@ TMH_EXCHANGES_find_exchange (const char *chosen_exchange,
/**
+ * Get /keys of the given @a exchange.
+ *
+ * @param exchange URL of the exchange we would like to talk to
+ * @param fc function to call with the handles for the exchange
+ * @param fc_cls closure for @a fc
+ */
+struct TMH_EXCHANGES_Find2Operation *
+TMH_EXCHANGES_keys4exchange (const char *exchange,
+ TMH_EXCHANGES_Find2Continuation fc,
+ void *fc_cls);
+
+
+/**
+ * Get /wire of the given @a exchange.
+ *
+ * @param exchange URL of the exchange we would like to talk to
+ * @param fc function to call with the handles for the exchange
+ * @param fc_cls closure for @a fc
+ */
+struct TMH_EXCHANGES_WireOperation *
+TMH_EXCHANGES_wire4exchange (const char *exchange,
+ TMH_EXCHANGES_WireContinuation fc,
+ void *fc_cls);
+
+
+/**
* Lookup current wire fee by @a exchange_url and
* @a wire_method.
*
@@ -149,4 +211,22 @@ void
TMH_EXCHANGES_find_exchange_cancel (struct TMH_EXCHANGES_FindOperation *fo);
+/**
+ * Abort pending keys details lookup operation.
+ *
+ * @param fo handle to operation to abort
+ */
+void
+TMH_EXCHANGES_keys4exchange_cancel (struct TMH_EXCHANGES_Find2Operation *fo);
+
+
+/**
+ * Abort pending wire details lookup operation.
+ *
+ * @param fo handle to operation to abort
+ */
+void
+TMH_EXCHANGES_wire4exchange_cancel (struct TMH_EXCHANGES_WireOperation *fo);
+
+
#endif
diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
index 04224ac5..28ba72df 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
@@ -70,12 +70,6 @@ struct DepositConfirmation
struct PayContext *pc;
/**
- * Handle to the deposit operation we are performing for
- * this coin, NULL after the operation is done.
- */
- struct TALER_EXCHANGE_DepositHandle *dh;
-
- /**
* URL of the exchange that issued this coin.
*/
char *exchange_url;
@@ -179,7 +173,14 @@ struct ExchangeGroup
* the exchange used for this transaction; NULL if no operation is
* pending.
*/
- struct TMH_EXCHANGES_FindOperation *fo;
+ struct TMH_EXCHANGES_Find2Operation *fo;
+
+ /**
+ * Handle for operation to lookup /wire from
+ * the exchange used for this transaction; NULL if no operation is
+ * pending.
+ */
+ struct TMH_EXCHANGES_WireOperation *gwo;
/**
* URL of the exchange that issued this coin. Aliases
@@ -570,29 +571,6 @@ get_pay_timeout (unsigned int num_coins)
}
-/**
- * Abort all pending /deposit operations.
- *
- * @param pc pay context to abort
- */
-static void
-abort_active_deposits (struct PayContext *pc)
-{
- GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
- "Aborting pending /deposit operations\n");
- for (unsigned int i = 0; i<pc->coins_cnt; i++)
- {
- struct DepositConfirmation *dci = &pc->dc[i];
-
- if (NULL != dci->dh)
- {
- TALER_EXCHANGE_deposit_cancel (dci->dh);
- dci->dh = NULL;
- }
- }
-}
-
-
void
TMH_force_pc_resume ()
{
@@ -609,7 +587,6 @@ TMH_force_pc_resume ()
NULL != pc;
pc = pc->next)
{
- abort_active_deposits (pc);
if (NULL != pc->timeout_task)
{
GNUNET_SCHEDULER_cancel (pc->timeout_task);
@@ -638,7 +615,6 @@ resume_pay_with_response (struct PayContext *pc,
unsigned int response_code,
struct MHD_Response *response)
{
- abort_active_deposits (pc);
pc->response_code = response_code;
pc->response = response;
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -697,7 +673,6 @@ pay_context_cleanup (void *cls)
json_decref (pc->contract_terms);
pc->contract_terms = NULL;
}
- abort_active_deposits (pc);
for (unsigned int i = 0; i<pc->coins_cnt; i++)
{
struct DepositConfirmation *dc = &pc->dc[i];
@@ -711,7 +686,9 @@ pay_context_cleanup (void *cls)
struct ExchangeGroup *eg = pc->egs[i];
if (NULL != eg->fo)
- TMH_EXCHANGES_find_exchange_cancel (eg->fo);
+ TMH_EXCHANGES_keys4exchange_cancel (eg->fo);
+ if (NULL != eg->gwo)
+ TMH_EXCHANGES_wire4exchange_cancel (eg->gwo);
GNUNET_free (eg);
}
GNUNET_free (pc->egs);
@@ -1170,35 +1147,29 @@ batch_deposit_cb (
/**
- * Function called with the result of our exchange lookup.
+ * Function called with the result of our exchange keys lookup.
*
* @param cls the `struct ExchangeGroup`
- * @param hr HTTP response details
- * @param exchange_handle NULL if exchange was not found to be acceptable
- * @param ih internal handle to the exchange
+ * @param keys the keys of the exchange
*/
static void
-process_pay_with_exchange (
+process_pay_with_keys (
void *cls,
- const struct TALER_EXCHANGE_HttpResponse *hr,
- struct TALER_EXCHANGE_Handle *exchange_handle,
- struct TMH_Exchange *ih)
+ struct TALER_EXCHANGE_Keys *keys)
{
struct ExchangeGroup *eg = cls;
struct PayContext *pc = eg->pc;
struct TMH_HandlerContext *hc = pc->hc;
- const struct TALER_EXCHANGE_Keys *keys;
unsigned int group_size;
eg->fo = NULL;
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Processing payment with exchange %s\n",
- (NULL == exchange_handle)
- ? "<null>"
- : TALER_EXCHANGE_get_base_url (exchange_handle));
+ eg->exchange_url);
GNUNET_assert (GNUNET_YES == pc->suspended);
- if (NULL == hr)
+ if (NULL == keys)
{
+ GNUNET_break_op (0);
pc->pending_at_eg--;
resume_pay_with_response (
pc,
@@ -1207,45 +1178,6 @@ process_pay_with_exchange (
TALER_JSON_pack_ec (TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT)));
return;
}
- if ( (MHD_HTTP_OK != hr->http_status) ||
- (NULL == exchange_handle) )
- {
- pc->pending_at_eg--;
- resume_pay_with_response (
- pc,
- MHD_HTTP_BAD_GATEWAY,
- TALER_MHD_MAKE_JSON_PACK (
- TALER_JSON_pack_ec (
- TALER_EC_MERCHANT_GENERIC_EXCHANGE_CONNECT_FAILURE),
- TMH_pack_exchange_reply (hr)));
- return;
- }
- if (GNUNET_OK !=
- TMH_exchange_check_debit (ih,
- pc->wm))
- {
- GNUNET_break_op (0);
- pc->pending_at_eg--;
- resume_pay_with_response (
- pc,
- MHD_HTTP_CONFLICT,
- TALER_MHD_MAKE_JSON_PACK (
- TALER_JSON_pack_ec (
- TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED)));
- return;
- }
-
- keys = TALER_EXCHANGE_get_keys (exchange_handle);
- if (NULL == keys)
- {
- pc->pending_at_eg--;
- GNUNET_break (0); /* should not be possible if HTTP status is #MHD_HTTP_OK */
- resume_pay_with_error (pc,
- MHD_HTTP_BAD_GATEWAY,
- TALER_EC_MERCHANT_GENERIC_EXCHANGE_KEYS_FAILURE,
- NULL);
- return;
- }
/* Initiate /batch-deposit operation for all coins of
the current exchange (!) */
@@ -1267,21 +1199,6 @@ process_pay_with_exchange (
&dc->cdd.h_denom_pub);
if (NULL == denom_details)
{
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Denomination not found, re-fetching /keys\n");
- if (! eg->tried_force_keys)
- {
- /* let's try *forcing* a re-download of /keys from the exchange.
- Maybe the wallet has seen /keys that we missed. */
- eg->tried_force_keys = true;
- eg->fo = TMH_EXCHANGES_find_exchange (eg->exchange_url,
- true,
- &process_pay_with_exchange,
- eg);
- if (NULL != eg->fo)
- return;
- }
- /* Forcing failed or we already did it, give up */
pc->pending_at_eg--;
resume_pay_with_response (
pc,
@@ -1292,9 +1209,9 @@ process_pay_with_exchange (
GNUNET_JSON_pack_data_auto ("h_denom_pub",
&dc->cdd.h_denom_pub),
GNUNET_JSON_pack_allow_null (
- GNUNET_JSON_pack_object_incref (
+ GNUNET_JSON_pack_object_steal (
"exchange_keys",
- (json_t *) TALER_EXCHANGE_get_keys_raw (exchange_handle)))));
+ TALER_EXCHANGE_keys_to_json (keys)))));
return;
}
dc->deposit_fee = denom_details->fees.deposit;
@@ -1458,13 +1375,16 @@ AGE_FAIL:
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Initiating batch deposit with %u coins\n",
group_size);
- eg->bdh = TALER_EXCHANGE_batch_deposit (exchange_handle,
- &dcd,
- group_size,
- cdds,
- &batch_deposit_cb,
- eg,
- &ec);
+ eg->bdh = TALER_EXCHANGE_batch_deposit (
+ merchant_curl_ctx,
+ eg->exchange_url,
+ keys,
+ &dcd,
+ group_size,
+ cdds,
+ &batch_deposit_cb,
+ eg,
+ &ec);
if (NULL == eg->bdh)
{
/* Signature was invalid or some other constraint was not satisfied. If
@@ -1488,6 +1408,67 @@ AGE_FAIL:
/**
+ * Function called with the result of our exchange lookup.
+ *
+ * @param cls the `struct ExchangeGroup`
+ * @param keys the keys of the exchange
+ */
+static void
+process_pay_with_wire (
+ void *cls,
+ struct TMH_Exchange *wire)
+{
+ struct ExchangeGroup *eg = cls;
+ struct PayContext *pc = eg->pc;
+
+ eg->gwo = NULL;
+ if (NULL == wire)
+ {
+ GNUNET_break_op (0);
+ pc->pending_at_eg--;
+ /* FIXME: define more specific error code... */
+ resume_pay_with_response (
+ pc,
+ MHD_HTTP_BAD_GATEWAY,
+ TALER_MHD_MAKE_JSON_PACK (
+ TALER_JSON_pack_ec (
+ TALER_EC_MERCHANT_GENERIC_EXCHANGE_CONNECT_FAILURE)));
+ return;
+ }
+ if (GNUNET_OK !=
+ TMH_exchange_check_debit (wire,
+ pc->wm))
+ {
+ GNUNET_break_op (0);
+ pc->pending_at_eg--;
+ resume_pay_with_response (
+ pc,
+ MHD_HTTP_CONFLICT,
+ TALER_MHD_MAKE_JSON_PACK (
+ TALER_JSON_pack_ec (
+ TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED)));
+ return;
+ }
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Fetching /keys for %s\n",
+ eg->exchange_url);
+ eg->fo = TMH_EXCHANGES_keys4exchange (eg->exchange_url,
+ &process_pay_with_keys,
+ eg);
+ if (NULL == eg->fo)
+ {
+ GNUNET_break (0);
+ pc->pending_at_eg--;
+ resume_pay_with_error (pc,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_LOOKUP_FAILED,
+ "Failed to lookup exchange by URL");
+ return;
+ }
+}
+
+
+/**
* Start batch deposits for all exchanges involved
* in this payment.
*
@@ -1515,11 +1496,13 @@ start_batch_deposits (struct PayContext *pc)
}
if (! have_coins)
continue; /* no coins left to deposit at this exchange */
- eg->fo = TMH_EXCHANGES_find_exchange (eg->exchange_url,
- false,
- &process_pay_with_exchange,
- eg);
- if (NULL == eg->fo)
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Getting /wire details for %s\n",
+ eg->exchange_url);
+ eg->gwo = TMH_EXCHANGES_wire4exchange (eg->exchange_url,
+ &process_pay_with_wire,
+ eg);
+ if (NULL == eg->gwo)
{
GNUNET_break (0);
resume_pay_with_error (pc,