diff options
-rw-r--r-- | src/backend/taler-merchant-httpd.c | 40 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd.h | 2 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_exchanges.c | 973 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_exchanges.h | 91 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_helper.c | 206 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_post-orders-ID-abort.c | 4 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_post-orders-ID-pay.c | 127 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_post-orders-ID-refund.c | 4 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_post-tips-ID-pickup.c | 6 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c | 4 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-get-orders-ID.c | 4 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-get-reserves-ID.c | 25 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_private-post-reserves.c | 4 | ||||
-rw-r--r-- | src/backend/taler-merchant-httpd_reserves.c | 2 |
14 files changed, 751 insertions, 741 deletions
diff --git a/src/backend/taler-merchant-httpd.c b/src/backend/taler-merchant-httpd.c index 00e4689c..1c8b80d0 100644 --- a/src/backend/taler-merchant-httpd.c +++ b/src/backend/taler-merchant-httpd.c @@ -145,6 +145,17 @@ static uint16_t port; * Should a "Connection: close" header be added to each HTTP response? */ static int merchant_connection_close; +/** + * Context for all exchange operations (useful to the event loop). + * FIXME: rename, move to taler-merchant-httpd.c + */ +struct GNUNET_CURL_Context *TMH_curl_ctx; + +/** + * Context for integrating #TMH_curl_ctx with the + * GNUnet event loop. + */ +static struct GNUNET_CURL_RescheduleContext *merchant_curl_rc; /** * Global return code @@ -329,6 +340,16 @@ do_shutdown (void *cls) TMH_by_id_map = NULL; } TALER_TEMPLATING_done (); + if (NULL != TMH_curl_ctx) + { + GNUNET_CURL_fini (TMH_curl_ctx); + TMH_curl_ctx = NULL; + } + if (NULL != merchant_curl_rc) + { + GNUNET_CURL_gnunet_rc_destroy (merchant_curl_rc); + merchant_curl_rc = NULL; + } } @@ -1915,6 +1936,25 @@ run (void *cls, result = GNUNET_SYSERR; GNUNET_SCHEDULER_add_shutdown (&do_shutdown, NULL); + + TMH_curl_ctx + = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, + &merchant_curl_rc); + if (NULL == TMH_curl_ctx) + { + GNUNET_break (0); + result = GNUNET_SYSERR; + GNUNET_SCHEDULER_shutdown (); + return; + } + merchant_curl_rc = GNUNET_CURL_gnunet_rc_create (TMH_curl_ctx); + /* Disable 100 continue processing */ + GNUNET_break (GNUNET_OK == + GNUNET_CURL_append_header (TMH_curl_ctx, + MHD_HTTP_HEADER_EXPECT ":")); + GNUNET_CURL_enable_async_scope_header (TMH_curl_ctx, + "Taler-Correlation-Id"); + if (GNUNET_OK != TALER_config_get_currency (cfg, &TMH_currency)) diff --git a/src/backend/taler-merchant-httpd.h b/src/backend/taler-merchant-httpd.h index 732c1bf3..e262b314 100644 --- a/src/backend/taler-merchant-httpd.h +++ b/src/backend/taler-merchant-httpd.h @@ -639,7 +639,7 @@ extern int TMH_force_audit; /** * Context for all CURL operations (useful to the event loop) */ -extern struct GNUNET_CURL_Context *merchant_curl_ctx; +extern struct GNUNET_CURL_Context *TMH_curl_ctx; /** * Handle to the database backend. diff --git a/src/backend/taler-merchant-httpd_exchanges.c b/src/backend/taler-merchant-httpd_exchanges.c index 665607c1..ff4360b0 100644 --- a/src/backend/taler-merchant-httpd_exchanges.c +++ b/src/backend/taler-merchant-httpd_exchanges.c @@ -66,18 +66,18 @@ /** * Information we keep for a pending #MMH_EXCHANGES_keys4exchange() operation. */ -struct TMH_EXCHANGES_Find2Operation +struct TMH_EXCHANGES_KeysOperation { /** * Kept in a DLL. */ - struct TMH_EXCHANGES_Find2Operation *next; + struct TMH_EXCHANGES_KeysOperation *next; /** * Kept in a DLL. */ - struct TMH_EXCHANGES_Find2Operation *prev; + struct TMH_EXCHANGES_KeysOperation *prev; /** * Function to call with the result. @@ -254,7 +254,7 @@ struct ExchangeAccount /** - * Exchange + * Internal representation for an exchange */ struct TMH_Exchange { @@ -272,12 +272,12 @@ struct TMH_Exchange /** * Head of FOs pending for this exchange. */ - struct TMH_EXCHANGES_Find2Operation *fo2_head; + struct TMH_EXCHANGES_KeysOperation *keys_head; /** * Tail of FOs pending for this exchange. */ - struct TMH_EXCHANGES_Find2Operation *fo2_tail; + struct TMH_EXCHANGES_KeysOperation *keys_tail; /** * Head of /wire pending for this exchange. @@ -290,6 +290,11 @@ struct TMH_Exchange struct TMH_EXCHANGES_WireOperation *w_tail; /** + * Request to /keys needed for our /wire operation. + */ + struct TMH_EXCHANGES_KeysOperation *ko; + + /** * Head of accounts of this exchange. */ struct ExchangeAccount *acc_head; @@ -335,8 +340,7 @@ struct TMH_Exchange struct FeesByWireMethod *wire_fees_tail; /** - * Master public key, guaranteed to be set ONLY for - * trusted exchanges. + * Master public key of the exchange. */ struct TALER_MasterPublicKeyP master_pub; @@ -377,16 +381,17 @@ struct TMH_Exchange /** - * Context for all exchange operations (useful to the event loop). - * FIXME: rename, move to taler-merchant-httpd.c + * Opaque wire details abstraction returned to a client after successfully + * obtaining /wire. */ -struct GNUNET_CURL_Context *merchant_curl_ctx; +struct TMH_ExchangeWireDetails +{ + /** + * Internal representation of the exchange + */ + struct TMH_Exchange *exchange; +}; -/** - * Context for integrating #merchant_curl_ctx with the - * GNUnet event loop. - */ -static struct GNUNET_CURL_RescheduleContext *merchant_curl_rc; /** * Head of exchanges we know about. @@ -405,19 +410,6 @@ static struct TMH_Exchange *exchange_tail; */ static int trusted_exchange_count; -/** - * Function called with information about who is auditing - * a particular exchange and what key the exchange is using. - * - * @param cls closure, will be `struct TMH_Exchange` - * @param kr response details - * @param[in] keys keys object returned - */ -static void -keys_mgmt_cb (void *cls, - const struct TALER_EXCHANGE_KeysResponse *kr, - struct TALER_EXCHANGE_Keys *keys); - /** * Free data structures within @a ea, but not @a ea @@ -475,6 +467,36 @@ purge_exchange_accounts (struct TMH_Exchange *exchange) /** + * Lookup exchange by @a exchange_url. Create one + * if it does not exist. + * + * @param exchange_url base URL to match against + * @return fresh entry if exchange was not yet known + */ +static struct TMH_Exchange * +lookup_exchange (const char *exchange_url) +{ + struct TMH_Exchange *exchange; + + for (exchange = exchange_head; + NULL != exchange; + exchange = exchange->next) + if (0 == strcmp (exchange->url, + exchange_url)) + return exchange; + exchange = GNUNET_new (struct TMH_Exchange); + exchange->url = GNUNET_strdup (exchange_url); + GNUNET_CONTAINER_DLL_insert (exchange_head, + exchange_tail, + exchange); + GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, + "The exchange `%s' is new\n", + exchange_url); + return exchange; +} + + +/** * Set the list of accounts of @a exchange. * * @param[in,out] exchange exchange to initialize or update @@ -536,10 +558,24 @@ set_exchange_accounts ( /** - * Retry getting information from the given exchange in - * the closure. + * Function called with information about who is auditing + * a particular exchange and what key the exchange is using. * - * @param cls the exchange + * @param cls closure, will be `struct TMH_Exchange` + * @param kr response details + * @param[in] keys keys object returned + */ +static void +keys_mgmt_cb ( + void *cls, + const struct TALER_EXCHANGE_KeysResponse *kr, + struct TALER_EXCHANGE_Keys *keys); + + +/** + * Retry getting keys from the given exchange in the closure. + * + * @param cls the `struct TMH_Exchange *` */ static void retry_exchange (void *cls) @@ -549,18 +585,31 @@ retry_exchange (void *cls) /* might be a scheduled reload and not our first attempt */ exchange->retry_task = NULL; if (NULL != exchange->conn) - return; + return; /* already trying */ + if ( (NULL != exchange->keys) && + (GNUNET_TIME_absolute_is_future ( + exchange->keys->key_data_expiration.abs_time)) ) + return; /* still have a valid reply */ + /* increment exponential-backoff */ + exchange->retry_delay + = RETRY_BACKOFF (exchange->retry_delay); + /* No download 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_DEBUG, - "Connecting to exchange %s in retry_exchange()\n", + "Fetching /keys from exchange %s in retry_exchange()\n", exchange->url); - if ( (NULL == exchange->keys) || - (GNUNET_TIME_absolute_is_past ( - exchange->keys->key_data_expiration.abs_time)) ) - exchange->conn = TALER_EXCHANGE_get_keys (merchant_curl_ctx, - exchange->url, - exchange->keys, - &keys_mgmt_cb, - exchange); + exchange->conn + = TALER_EXCHANGE_get_keys ( + TMH_curl_ctx, + exchange->url, + exchange->keys, + &keys_mgmt_cb, + exchange); /* Note: while the API spec says 'returns NULL on error', the implementation actually never returns NULL. */ GNUNET_break (NULL != exchange->conn); @@ -568,9 +617,200 @@ retry_exchange (void *cls) /** - * Function called with information about the wire fees - * for each wire method. Stores the wire fees with the - * exchange for later use. + * Check if we have any remaining pending requests for the + * given @a exchange, and if we have the required data, call + * the callback. + * + * @param exchange the exchange to check for pending find operations + * @return true if we need /wire data from @a exchange + */ +static bool +process_find_operations (struct TMH_Exchange *exchange) +{ + struct TMH_EXCHANGES_KeysOperation *fn2; + struct TMH_EXCHANGES_WireOperation *wn; + struct GNUNET_TIME_Timestamp now; + + fn2 = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Processing find operations for `%s'\n", + exchange->url); + for (struct TMH_EXCHANGES_KeysOperation *fo = exchange->keys_head; + NULL != fo; + fo = fn2) + { + fn2 = fo->next; + fo->fc (fo->fc_cls, + exchange->keys); + TMH_EXCHANGES_keys4exchange_cancel (fo); + } + if (! exchange->have_wire) + return true; + now = GNUNET_TIME_timestamp_get (); + for (struct FeesByWireMethod *fbw = exchange->wire_fees_head; + NULL != fbw; + fbw = fbw->next) + { + bool removed = false; + + while ( (NULL != fbw->af) && + (GNUNET_TIME_timestamp_cmp (fbw->af->end_date, + <, + now)) ) + { + struct TALER_EXCHANGE_WireAggregateFees *af = fbw->af; + + fbw->af = af->next; + GNUNET_free (af); + removed = true; + } + if (NULL == fbw->af) + { + /* Disagreement on the current time */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Exchange has no wire fees configured for `%s' wire method\n", + fbw->wire_method); + if (removed) + { + exchange->have_wire = false; + return true; /* We just removed previous fees, try fetching update */ + } + } + if (GNUNET_TIME_timestamp_cmp (fbw->af->start_date, + >, + now)) + { + /* Disagreement on the current time */ + GNUNET_log (GNUNET_ERROR_TYPE_ERROR, + "Exchange's earliest fee is %s ahead of our time. Clock skew issue?\n", + GNUNET_TIME_relative2s ( + GNUNET_TIME_absolute_get_remaining ( + fbw->af->start_date.abs_time), + true)); + } + } + + if (! exchange->have_wire) + return true; /* need /wire response to continue */ + { + struct TMH_ExchangeWireDetails wd = { + .exchange = exchange + }; + + wn = NULL; + for (struct TMH_EXCHANGES_WireOperation *w = exchange->w_head; + NULL != w; + w = wn) + { + wn = w->next; + w->fc (w->fc_cls, + &wd); + TMH_EXCHANGES_wire4exchange_cancel (w); + } + } + return false; +} + + +/** + * Task to asynchronously return keys operation result to caller. + * + * @param cls a `struct TMH_EXCHANGES_KeysOperation` + */ +static void +return_keys (void *cls) +{ + struct TMH_EXCHANGES_KeysOperation *fo = cls; + struct TMH_Exchange *exchange = fo->my_exchange; + + fo->at = NULL; + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Returning key data for %s instantly\n", + exchange->url); + process_find_operations (exchange); +} + + +struct TMH_EXCHANGES_KeysOperation * +TMH_EXCHANGES_keys4exchange ( + const char *chosen_exchange, + TMH_EXCHANGES_Find2Continuation fc, + void *fc_cls) +{ + struct TMH_Exchange *exchange; + struct TMH_EXCHANGES_KeysOperation *fo; + + if (NULL == TMH_curl_ctx) + { + GNUNET_break (0); + return NULL; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Trying to find chosen exchange `%s'\n", + chosen_exchange); + exchange = lookup_exchange (chosen_exchange); + fo = GNUNET_new (struct TMH_EXCHANGES_KeysOperation); + fo->fc = fc; + fo->fc_cls = fc_cls; + fo->my_exchange = exchange; + GNUNET_CONTAINER_DLL_insert (exchange->keys_head, + exchange->keys_tail, + fo); + if ( (NULL != exchange->keys) && + (GNUNET_TIME_absolute_is_future ( + exchange->keys->key_data_expiration.abs_time)) ) + { + /* We have a valid 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_keys, + fo); + return fo; + } + if ( (NULL == exchange->retry_task) && + (NULL == exchange->conn) ) + { + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "No valid keys, fetching /keys at %s\n", + GNUNET_TIME_absolute2s (exchange->first_retry)); + exchange->retry_task + = GNUNET_SCHEDULER_add_at (exchange->first_retry, + &retry_exchange, + exchange); + return fo; + } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Next /keys request scheduled for %s\n", + GNUNET_TIME_absolute2s ( + exchange->first_retry)); + /* No activity to launch, we are already doing so. */ + return fo; +} + + +void +TMH_EXCHANGES_keys4exchange_cancel ( + struct TMH_EXCHANGES_KeysOperation *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->keys_head, + exchange->keys_tail, + fo); + GNUNET_free (fo); +} + + +/** + * Function called with information about the wire fees for each wire method. + * Stores the wire fees with the exchange for later use. * * @param exchange connection to the exchange * @param master_pub public key of the exchange @@ -910,90 +1150,13 @@ get_wire_fees (struct TMH_Exchange *exchange, /** * Check if we have any remaining pending requests for the * given @a exchange, and if we have the required data, call - * the callback. + * the callback. If requests without /wire data remain, + * retry the /wire request after some delay. * - * @param exchange the exchange to check for pending find operations - * @return true if we need /wire data from @a exchange + * Must only be called if 'exchange->keys' is non-NULL. + * + * @param cls a `struct TMH_Exchange` to check */ -static bool -process_find_operations (struct TMH_Exchange *exchange) -{ - 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, - exchange->keys); - fn2 = fo->next; - TMH_EXCHANGES_keys4exchange_cancel (fo); - } - if (! exchange->have_wire) - return true; - now = GNUNET_TIME_timestamp_get (); - for (struct FeesByWireMethod *fbw = exchange->wire_fees_head; - NULL != fbw; - fbw = fbw->next) - { - bool removed = false; - - while ( (NULL != fbw->af) && - (GNUNET_TIME_timestamp_cmp (fbw->af->end_date, - <, - now)) ) - { - struct TALER_EXCHANGE_WireAggregateFees *af = fbw->af; - - fbw->af = af->next; - GNUNET_free (af); - removed = true; - } - if (NULL == fbw->af) - { - /* Disagreement on the current time */ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Exchange has no wire fees configured for `%s' wire method\n", - fbw->wire_method); - if (removed) - { - exchange->have_wire = false; - return true; /* We just removed previous fees, try fetching update */ - } - } - if (GNUNET_TIME_timestamp_cmp (fbw->af->start_date, - >, - now)) - { - /* Disagreement on the current time */ - GNUNET_log (GNUNET_ERROR_TYPE_ERROR, - "Exchange's earliest fee is %s ahead of our time. Clock skew issue?\n", - GNUNET_TIME_relative2s ( - GNUNET_TIME_absolute_get_remaining ( - fbw->af->start_date.abs_time), - true)); - } - } - - if (! exchange->have_wire) - return true; /* need /wire response to continue */ - 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; -} - - static void wire_task_cb (void *cls); @@ -1053,15 +1216,15 @@ handle_wire_data (void *cls, if (TALER_EC_NONE != ecx) { /* Report hard failure to all callbacks! */ - struct TMH_EXCHANGES_Find2Operation *fo2; + struct TMH_EXCHANGES_KeysOperation *keys; GNUNET_break_op (0); exchange->have_wire = false; - while (NULL != (fo2 = exchange->fo2_head)) + while (NULL != (keys = exchange->keys_head)) { - fo2->fc (fo2->fc_cls, - NULL); - TMH_EXCHANGES_keys4exchange_cancel (fo2); + keys->fc (keys->fc_cls, + NULL); + TMH_EXCHANGES_keys4exchange_cancel (keys); } return; } @@ -1091,16 +1254,6 @@ handle_wire_data (void *cls, } -/** - * Check if we have any remaining pending requests for the - * given @a exchange, and if we have the required data, call - * the callback. If requests without /wire data remain, - * retry the /wire request after some delay. - * - * Must only be called if 'exchange->keys' is non-NULL. - * - * @param cls a `struct TMH_Exchange` to check - */ static void wire_task_cb (void *cls) { @@ -1113,7 +1266,7 @@ wire_task_cb (void *cls) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Initiating /wire download\n"); exchange->wire_request - = TALER_EXCHANGE_wire (merchant_curl_ctx, + = TALER_EXCHANGE_wire (TMH_curl_ctx, exchange->url, exchange->keys, &handle_wire_data, @@ -1172,8 +1325,8 @@ free_exchange_entry (struct TMH_Exchange *exchange) GNUNET_SCHEDULER_cancel (exchange->retry_task); exchange->retry_task = NULL; } - GNUNET_assert (NULL == exchange->fo2_head); - GNUNET_assert (NULL == exchange->fo2_tail); + GNUNET_assert (NULL == exchange->keys_head); + GNUNET_assert (NULL == exchange->keys_tail); GNUNET_assert (NULL == exchange->w_head); GNUNET_assert (NULL == exchange->w_tail); GNUNET_free (exchange->url); @@ -1192,7 +1345,7 @@ static void fail_and_retry (struct TMH_Exchange *exchange, const struct TALER_EXCHANGE_HttpResponse *hr) { - struct TMH_EXCHANGES_Find2Operation *fo2; + struct TMH_EXCHANGES_KeysOperation *keys; struct TMH_EXCHANGES_WireOperation *w; if (NULL != exchange->wire_request) @@ -1205,11 +1358,11 @@ fail_and_retry (struct TMH_Exchange *exchange, GNUNET_SCHEDULER_cancel (exchange->wire_task); exchange->wire_task = NULL; } - while (NULL != (fo2 = exchange->fo2_head)) + while (NULL != (keys = exchange->keys_head)) { - fo2->fc (fo2->fc_cls, - NULL); - TMH_EXCHANGES_keys4exchange_cancel (fo2); + keys->fc (keys->fc_cls, + NULL); + TMH_EXCHANGES_keys4exchange_cancel (keys); } while (NULL != (w = exchange->w_head)) { @@ -1233,14 +1386,24 @@ fail_and_retry (struct TMH_Exchange *exchange, true)); if (NULL != exchange->retry_task) GNUNET_SCHEDULER_cancel (exchange->retry_task); - exchange->first_retry = GNUNET_TIME_relative_to_absolute ( - exchange->retry_delay); - exchange->retry_task = GNUNET_SCHEDULER_add_delayed (exchange->retry_delay, - &retry_exchange, - exchange); + exchange->first_retry + = GNUNET_TIME_relative_to_absolute ( + exchange->retry_delay); + exchange->retry_task + = GNUNET_SCHEDULER_add_delayed (exchange->retry_delay, + &retry_exchange, + exchange); } +/** + * Function called with the result of a + * /keys request to the exchange. + * + * @param cls a `struct TMH_Exchange *` + * @param kr response details + * @param[in] keys key data now owned by this function + */ static void keys_mgmt_cb (void *cls, const struct TALER_EXCHANGE_KeysResponse *kr, @@ -1293,13 +1456,14 @@ keys_mgmt_cb (void *cls, enum GNUNET_DB_QueryStatus qs; TMH_db->preflight (TMH_db->cls); - qs = TMH_db->insert_exchange_signkey (TMH_db->cls, - &keys->master_pub, - &sign_key->key, - sign_key->valid_from, - sign_key->valid_until, - sign_key->valid_legal, - &sign_key->master_sig); + qs = TMH_db->insert_exchange_signkey ( + TMH_db->cls, + &keys->master_pub, + &sign_key->key, + sign_key->valid_from, + sign_key->valid_until, + sign_key->valid_legal, + &sign_key->master_sig); /* 0 is OK, we may already have the key in the DB! */ if (0 > qs) { @@ -1315,7 +1479,7 @@ keys_mgmt_cb (void *cls, delay = GNUNET_TIME_absolute_get_remaining ( keys->key_data_expiration.abs_time); GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "/keys response from expires at %s! Retrying at that time!\n", + "/keys response expires at %s! Retrying at that time!\n", GNUNET_TIME_absolute2s ( keys->key_data_expiration.abs_time)); delay = GNUNET_TIME_relative_max (delay, @@ -1327,6 +1491,7 @@ keys_mgmt_cb (void *cls, = GNUNET_SCHEDULER_add_delayed (delay, &retry_exchange, exchange); + if ( (process_find_operations (exchange)) && (NULL == exchange->wire_request) && (NULL == exchange->wire_task) ) @@ -1335,7 +1500,7 @@ keys_mgmt_cb (void *cls, "Got key data, but also need wire data. Will request /wire now\n"); exchange->wire_request = TALER_EXCHANGE_wire ( - merchant_curl_ctx, + TMH_curl_ctx, exchange->url, exchange->keys, &handle_wire_data, @@ -1347,22 +1512,6 @@ keys_mgmt_cb (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 @@ -1376,115 +1525,6 @@ return_wire_result (void *cls) } -/** - * Lookup exchange by @a exchange_url. - * - * @param exchange_url base URL to match against - * @return NULL if exchange is not yet known - */ -static struct TMH_Exchange * -lookup_exchange (const char *exchange_url) -{ - for (struct TMH_Exchange *exchange = exchange_head; - NULL != exchange; - exchange = exchange->next) - if (0 == strcmp (exchange->url, - exchange_url)) - return exchange; - return NULL; -} - - -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->retry_task) - exchange->retry_task - = GNUNET_SCHEDULER_add_now (&retry_exchange, - exchange); - return fo; - } - - if (NULL != exchange->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->keys) && - (NULL == exchange->retry_task) ) - { - 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, @@ -1494,7 +1534,7 @@ TMH_EXCHANGES_wire4exchange ( struct TMH_Exchange *exchange; struct TMH_EXCHANGES_WireOperation *w; - if (NULL == merchant_curl_ctx) + if (NULL == TMH_curl_ctx) { GNUNET_break (0); return NULL; @@ -1502,21 +1542,7 @@ TMH_EXCHANGES_wire4exchange ( 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; @@ -1536,56 +1562,42 @@ TMH_EXCHANGES_wire4exchange ( w); return w; } - - if (NULL == exchange->wire_request) + if (NULL != exchange->wire_request) + return w; /* /wire request is active, do nothing */ + if ( (NULL != exchange->keys) && + (GNUNET_TIME_absolute_is_future ( + exchange->keys->key_data_expiration.abs_time)) ) { - if (NULL == exchange->conn) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Requesting /keys from `%s' to connect\n", - exchange->url); - exchange->conn = TALER_EXCHANGE_get_keys (merchant_curl_ctx, - exchange->url, - exchange->keys, - &keys_mgmt_cb, - exchange); - } - else - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Requesting /wire from `%s'\n", - exchange->url); - exchange->wire_request - = TALER_EXCHANGE_wire (merchant_curl_ctx, - exchange->url, - exchange->keys, - &handle_wire_data, - exchange); - } + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "Requesting /wire from `%s'\n", + exchange->url); + exchange->wire_request + = TALER_EXCHANGE_wire (TMH_curl_ctx, + exchange->url, + exchange->keys, + &handle_wire_data, + exchange); + return w; } - return w; -} - - -void -TMH_EXCHANGES_keys4exchange_cancel (struct TMH_EXCHANGES_Find2Operation *fo) -{ - struct TMH_Exchange *exchange = fo->my_exchange; + if ( (NULL == exchange->keys) && + ( (NULL != exchange->conn) || + (NULL != exchange->retry_task) ) ) + return w; /* /keys request active, do nothing */ - 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); + GNUNET_log (GNUNET_ERROR_TYPE_INFO, + "No valid keys, fetching /keys at %s\n", + GNUNET_TIME_absolute2s (exchange->first_retry)); + exchange->retry_task + = GNUNET_SCHEDULER_add_at (exchange->first_retry, + &retry_exchange, + exchange); + return w; } void -TMH_EXCHANGES_wire4exchange_cancel (struct TMH_EXCHANGES_WireOperation *w) +TMH_EXCHANGES_wire4exchange_cancel ( + struct TMH_EXCHANGES_WireOperation *w) { struct TMH_Exchange *exchange = w->my_exchange; @@ -1601,10 +1613,128 @@ TMH_EXCHANGES_wire4exchange_cancel (struct TMH_EXCHANGES_WireOperation *w) } +enum GNUNET_GenericReturnValue +TMH_EXCHANGES_lookup_wire_fee ( + const struct TMH_ExchangeWireDetails *wd, + const char *wire_method, + struct TALER_Amount *wire_fee) +{ + struct TMH_Exchange *exchange = wd->exchange; + const struct FeesByWireMethod *fbm; + const struct TALER_EXCHANGE_WireAggregateFees *af; + + if (! exchange->have_wire) + { + GNUNET_break (0); + return GNUNET_SYSERR; + } + fbm = get_wire_fees (exchange, + GNUNET_TIME_timestamp_get (), + wire_method); + if (NULL == fbm) + return GNUNET_NO; + af = fbm->af; + *wire_fee = af->fees.wire; + return GNUNET_OK; +} + + +enum GNUNET_GenericReturnValue +TMH_exchange_check_debit ( + const struct TMH_ExchangeWireDetails *wd, + const struct TMH_WireMethod *wm) +{ + struct TMH_Exchange *ex = wd->exchange; + for (struct ExchangeAccount *acc = ex->acc_head; + NULL != acc; + acc = acc->next) + { + bool ok = true; + + if (0 != strcmp (acc->wire_method, + wm->wire_method)) + continue; + if (NULL != acc->conversion_url) + continue; /* never use accounts with conversion */ + for (struct Restriction *r = acc->d_head; + NULL != r; + r = r->next) + { + switch (r->type) + { + case TALER_EXCHANGE_AR_INVALID: + GNUNET_break (0); + ok = false; + break; + case TALER_EXCHANGE_AR_DENY: + ok = false; + break; + case TALER_EXCHANGE_AR_REGEX: + if (0 != regexec (&r->details.regex.ex, + wm->payto_uri, + 0, NULL, 0)) + ok = false; + break; + } + if (! ok) + break; + } + + if (ok) + return GNUNET_OK; + } + return GNUNET_NO; +} + + +json_t * +TMH_exchange_get_acceptable (const struct TMH_WireMethod *wm) +{ + json_t *te = json_array (); + + GNUNET_assert (NULL != te); + for (struct TMH_Exchange *exchange = exchange_head; + NULL != exchange; + exchange = exchange->next) + { + json_t *j_exchange; + unsigned int priority; + + if (! exchange->trusted) + continue; + priority = 512; /* medium */ + if (exchange->have_wire) + { + struct TMH_ExchangeWireDetails wd = { + .exchange = exchange + }; + + if (GNUNET_OK == + TMH_exchange_check_debit (&wd, + wm)) + priority = 1024; /* high */ + else + priority = 0; /* negative response */ + } + j_exchange = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("url", + exchange->url), + GNUNET_JSON_pack_uint64 ("priority", + priority), + GNUNET_JSON_pack_data_auto ("master_pub", + &exchange->master_pub)); + GNUNET_assert (NULL != j_exchange); + GNUNET_assert (0 == + json_array_append_new (te, + j_exchange)); + } + return te; +} + + /** * Function called on each configuration section. Finds sections - * about exchanges, parses the entries and tries to connect to - * it in order to fetch /keys. + * about exchanges, parses the entries. * * @param cls closure, with a `const struct GNUNET_CONFIGURATION_Handle *` * @param section name of the section @@ -1677,7 +1807,7 @@ accept_exchanges (void *cls, GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR, section, "MASTER_KEY", - _ ("ill-formed EdDSA key")); + "malformed EdDSA key"); } GNUNET_free (mks); } @@ -1686,7 +1816,6 @@ accept_exchanges (void *cls, GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "MASTER_KEY missing in section '%s', not trusting exchange\n", section); - } GNUNET_CONTAINER_DLL_insert (exchange_head, exchange_tail, @@ -1698,53 +1827,8 @@ accept_exchanges (void *cls, enum GNUNET_GenericReturnValue -TMH_EXCHANGES_lookup_wire_fee (const char *exchange_url, - const char *wire_method, - struct TALER_Amount *wire_fee) -{ - struct TMH_Exchange *exchange; - const struct FeesByWireMethod *fbm; - const struct TALER_EXCHANGE_WireAggregateFees *af; - - exchange = lookup_exchange (exchange_url); - if (NULL == exchange) - { - return GNUNET_SYSERR; - } - if (! exchange->have_wire) - { - return GNUNET_SYSERR; - } - fbm = get_wire_fees (exchange, - GNUNET_TIME_timestamp_get (), - wire_method); - if (NULL == fbm) - return GNUNET_NO; - af = fbm->af; - *wire_fee = af->fees.wire; - return GNUNET_OK; -} - - -enum GNUNET_GenericReturnValue TMH_EXCHANGES_init (const struct GNUNET_CONFIGURATION_Handle *cfg) { - merchant_curl_ctx - = GNUNET_CURL_init (&GNUNET_CURL_gnunet_scheduler_reschedule, - &merchant_curl_rc); - if (NULL == merchant_curl_ctx) - { - GNUNET_break (0); - return GNUNET_SYSERR; - } - merchant_curl_rc = GNUNET_CURL_gnunet_rc_create (merchant_curl_ctx); - /* Disable 100 continue processing */ - GNUNET_break (GNUNET_OK == - GNUNET_CURL_append_header (merchant_curl_ctx, - MHD_HTTP_HEADER_EXPECT ":")); - - GNUNET_CURL_enable_async_scope_header (merchant_curl_ctx, - "Taler-Correlation-Id"); /* get exchanges from the merchant configuration and try to connect to them */ GNUNET_CONFIGURATION_iterate_sections (cfg, &accept_exchanges, @@ -1759,103 +1843,6 @@ TMH_EXCHANGES_done () { while (NULL != exchange_head) free_exchange_entry (exchange_head); - if (NULL != merchant_curl_ctx) - { - GNUNET_CURL_fini (merchant_curl_ctx); - merchant_curl_ctx = NULL; - } - if (NULL != merchant_curl_rc) - { - GNUNET_CURL_gnunet_rc_destroy (merchant_curl_rc); - merchant_curl_rc = NULL; - } -} - - -enum GNUNET_GenericReturnValue -TMH_exchange_check_debit (struct TMH_Exchange *ex, - const struct TMH_WireMethod *wm) -{ - for (struct ExchangeAccount *acc = ex->acc_head; - NULL != acc; - acc = acc->next) - { - bool ok = true; - - if (0 != strcmp (acc->wire_method, - wm->wire_method)) - continue; - if (NULL != acc->conversion_url) - continue; /* never use accounts with conversion */ - for (struct Restriction *r = acc->d_head; - NULL != r; - r = r->next) - { - switch (r->type) - { - case TALER_EXCHANGE_AR_INVALID: - GNUNET_break (0); - ok = false; - break; - case TALER_EXCHANGE_AR_DENY: - ok = false; - break; - case TALER_EXCHANGE_AR_REGEX: - if (0 != regexec (&r->details.regex.ex, - wm->payto_uri, - 0, NULL, 0)) - ok = false; - break; - } - if (! ok) - break; - } - - if (ok) - return GNUNET_OK; - } - return GNUNET_NO; -} - - -json_t * -TMH_exchange_get_acceptable (const struct TMH_WireMethod *wm) -{ - json_t *te = json_array (); - - GNUNET_assert (NULL != te); - for (struct TMH_Exchange *exchange = exchange_head; - NULL != exchange; - exchange = exchange->next) - { - json_t *j_exchange; - unsigned int priority; - - if (! exchange->trusted) - continue; - priority = 512; /* medium */ - if (exchange->have_wire) - { - if (GNUNET_OK == - TMH_exchange_check_debit (exchange, - wm)) - priority = 1024; /* high */ - else - priority = 0; /* negative response */ - } - j_exchange = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("url", - exchange->url), - GNUNET_JSON_pack_uint64 ("priority", - priority), - GNUNET_JSON_pack_data_auto ("master_pub", - &exchange->master_pub)); - GNUNET_assert (NULL != j_exchange); - GNUNET_assert (0 == - json_array_append_new (te, - j_exchange)); - } - return te; } diff --git a/src/backend/taler-merchant-httpd_exchanges.h b/src/backend/taler-merchant-httpd_exchanges.h index 5fc57a3e..2a2e9b13 100644 --- a/src/backend/taler-merchant-httpd_exchanges.h +++ b/src/backend/taler-merchant-httpd_exchanges.h @@ -37,21 +37,6 @@ struct TMH_Exchange; /** - * Check if we would trust @a ex to deposit funds - * into our account @a wm. Checks that both @a ex - * is trusted and that @a ex allows wire transfers - * into the account given in @a wm. - * - * @param ex the exchange to check - * @param wm the wire method to check with - * @return #GNUNET_OK if such a debit can happen - */ -enum GNUNET_GenericReturnValue -TMH_exchange_check_debit (struct TMH_Exchange *ex, - const struct TMH_WireMethod *wm); - - -/** * Return the list of exchanges we would find * acceptable for a payment given the @a wire_method. * @@ -96,6 +81,12 @@ typedef void /** + * Abstraction of wire knowledge returned internally. + */ +struct TMH_ExchangeWireDetails; + + +/** * Function called with the result of a #TMH_EXCHANGES_wire4exchange() * operation. * @@ -105,13 +96,13 @@ typedef void typedef void (*TMH_EXCHANGES_WireContinuation)( void *cls, - struct TMH_Exchange *wire); + const struct TMH_ExchangeWireDetails *wire); /** * Information we keep for a pending #MMH_EXCHANGES_keys4exchange() operation. */ -struct TMH_EXCHANGES_Find2Operation; +struct TMH_EXCHANGES_KeysOperation; /** * Information we keep for a pending #MMH_EXCHANGES_wire4exchange() operation. @@ -126,10 +117,20 @@ struct TMH_EXCHANGES_WireOperation; * @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); +struct TMH_EXCHANGES_KeysOperation * +TMH_EXCHANGES_keys4exchange ( + const char *exchange, + TMH_EXCHANGES_Find2Continuation fc, + void *fc_cls); + + +/** + * Abort pending keys details lookup operation. + * + * @param fo handle to operation to abort + */ +void +TMH_EXCHANGES_keys4exchange_cancel (struct TMH_EXCHANGES_KeysOperation *fo); /** @@ -140,9 +141,20 @@ TMH_EXCHANGES_keys4exchange (const char *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); +TMH_EXCHANGES_wire4exchange ( + const char *exchange, + TMH_EXCHANGES_WireContinuation fc, + void *fc_cls); + + +/** + * Abort pending wire details lookup operation. + * + * @param fo handle to operation to abort + */ +void +TMH_EXCHANGES_wire4exchange_cancel ( + struct TMH_EXCHANGES_WireOperation *fo); /** @@ -157,27 +169,26 @@ TMH_EXCHANGES_wire4exchange (const char *exchange, * #GNUNET_SYSERR if @a exchange_url did not yet respond properly to our /wire request */ enum GNUNET_GenericReturnValue -TMH_EXCHANGES_lookup_wire_fee (const char *exchange_url, - const char *wire_method, - struct TALER_Amount *wire_fee); +TMH_EXCHANGES_lookup_wire_fee ( + const struct TMH_ExchangeWireDetails *wd, + const char *wire_method, + struct TALER_Amount *wire_fee); /** - * 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. + * Check if we would trust @a ex to deposit funds + * into our account @a wm. Checks that both @a ex + * is trusted and that @a ex allows wire transfers + * into the account given in @a wm. * - * @param fo handle to operation to abort + * @param wd the wire details of the exchange to check + * @param wm the wire method to check with + * @return #GNUNET_OK if such a debit can happen */ -void -TMH_EXCHANGES_wire4exchange_cancel (struct TMH_EXCHANGES_WireOperation *fo); +enum GNUNET_GenericReturnValue +TMH_exchange_check_debit ( + const struct TMH_ExchangeWireDetails *wd, + const struct TMH_WireMethod *wm); #endif diff --git a/src/backend/taler-merchant-httpd_helper.c b/src/backend/taler-merchant-httpd_helper.c index 407323e2..172cb0a1 100644 --- a/src/backend/taler-merchant-httpd_helper.c +++ b/src/backend/taler-merchant-httpd_helper.c @@ -732,111 +732,6 @@ TMH_trigger_webhook (const char *instance, } -/** - * Closure for #add_matching_account(). - */ -struct ExchangeMatchContext -{ - /** - * Wire method to match, NULL for all. - */ - const char *wire_method; - - /** - * Array of accounts to return. - */ - json_t *accounts; -}; - - -/** - * If the given account is feasible, add it to the array - * of accounts we return. - * - * @param cls a `struct PostReserveContext` - * @param payto_uri URI of the account - * @param conversion_url URL of a conversion service - * @param debit_restrictions restrictions for debits from account - * @param credit_restrictions restrictions for credits to account - * @param master_sig signature affirming the account - */ -static void -add_matching_account (void *cls, - const char *payto_uri, - const char *conversion_url, - const json_t *debit_restrictions, - const json_t *credit_restrictions, - const struct TALER_MasterSignatureP *master_sig) -{ - struct ExchangeMatchContext *rc = cls; - char *method; - - method = TALER_payto_get_method (payto_uri); - if ( (NULL == rc->wire_method) || - (0 == strcmp (method, - rc->wire_method)) ) - { - json_t *acc; - - acc = GNUNET_JSON_PACK ( - GNUNET_JSON_pack_string ("payto_uri", - payto_uri), - GNUNET_JSON_pack_data_auto ("master_sig", - master_sig), - GNUNET_JSON_pack_allow_null ( - GNUNET_JSON_pack_string ("conversion_url", - conversion_url)), - GNUNET_JSON_pack_array_incref ("credit_restrictions", - (json_t *) credit_restrictions), - GNUNET_JSON_pack_array_incref ("debit_restrictions", - (json_t *) debit_restrictions) - ); - GNUNET_assert (0 == - json_array_append_new (rc->accounts, - acc)); - } - GNUNET_free (method); -} - - -/** - * Return JSON array with all of the exchange accounts - * that support the given @a wire_method. - * - * FIXME: bad API, doesn't inherently ensure that we - * actually did request /wire before! - * => move into t-m-h_exchanges.c and integrate with /wire - * logic there! - * - * @param master_pub master public key to match exchange by - * @param wire_method NULL for any - * @return JSON array with information about all matching accounts - */ -json_t * -TMH_exchange_accounts_by_method ( - const struct TALER_MasterPublicKeyP *master_pub, - const char *wire_method) -{ - struct ExchangeMatchContext emc = { - .wire_method = wire_method, - .accounts = json_array () - }; - enum GNUNET_DB_QueryStatus qs; - - GNUNET_assert (NULL != emc.accounts); - qs = TMH_db->select_accounts_by_exchange (TMH_db->cls, - master_pub, - &add_matching_account, - &emc); - if (qs < 0) - { - json_decref (emc.accounts); - return NULL; - } - return emc.accounts; -} - - enum GNUNET_GenericReturnValue TMH_base_url_by_connection (struct MHD_Connection *connection, const char *instance, @@ -948,3 +843,104 @@ TMH_taler_uri_by_connection (struct MHD_Connection *connection, } return GNUNET_OK; } + + +/** + * Closure for #add_matching_account(). + */ +struct ExchangeMatchContext +{ + /** + * Wire method to match, NULL for all. + */ + const char *wire_method; + + /** + * Array of accounts to return. + */ + json_t *accounts; +}; + + +/** + * If the given account is feasible, add it to the array + * of accounts we return. + * + * @param cls a `struct PostReserveContext` + * @param payto_uri URI of the account + * @param conversion_url URL of a conversion service + * @param debit_restrictions restrictions for debits from account + * @param credit_restrictions restrictions for credits to account + * @param master_sig signature affirming the account + */ +static void +add_matching_account ( + void *cls, + const char *payto_uri, + const char *conversion_url, + const json_t *debit_restrictions, + const json_t *credit_restrictions, + const struct TALER_MasterSignatureP *master_sig) +{ + struct ExchangeMatchContext *rc = cls; + char *method; + + method = TALER_payto_get_method (payto_uri); + if ( (NULL == rc->wire_method) || + (0 == strcmp (method, + rc->wire_method)) ) + { + json_t *acc; + + acc = GNUNET_JSON_PACK ( + GNUNET_JSON_pack_string ("payto_uri", + payto_uri), + GNUNET_JSON_pack_data_auto ("master_sig", + master_sig), + GNUNET_JSON_pack_allow_null ( + GNUNET_JSON_pack_string ("conversion_url", + conversion_url)), + GNUNET_JSON_pack_array_incref ("credit_restrictions", + (json_t *) credit_restrictions), + GNUNET_JSON_pack_array_incref ("debit_restrictions", + (json_t *) debit_restrictions) + ); + GNUNET_assert (0 == + json_array_append_new (rc->accounts, + acc)); + } + GNUNET_free (method); +} + + +/** + * Return JSON array with all of the exchange accounts + * that support the given @a wire_method. + * + * @param master_pub master public key to match exchange by + * @param wire_method NULL for any + * @return JSON array with information about all matching accounts + */ +json_t * +TMH_exchange_accounts_by_method ( + const struct TALER_MasterPublicKeyP *master_pub, + const char *wire_method) +{ + struct ExchangeMatchContext emc = { + .wire_method = wire_method, + .accounts = json_array () + }; + enum GNUNET_DB_QueryStatus qs; + + GNUNET_assert (NULL != emc.accounts); + qs = TMH_db->select_accounts_by_exchange (TMH_db->cls, + master_pub, + &add_matching_account, + &emc); + if (qs < 0) + { + json_decref (emc.accounts); + return NULL; + } + return emc.accounts; +} diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-abort.c b/src/backend/taler-merchant-httpd_post-orders-ID-abort.c index f5d76436..f63404b4 100644 --- a/src/backend/taler-merchant-httpd_post-orders-ID-abort.c +++ b/src/backend/taler-merchant-httpd_post-orders-ID-abort.c @@ -176,7 +176,7 @@ struct AbortContext * the exchange used for this transaction; NULL if no operation is * pending. */ - struct TMH_EXCHANGES_Find2Operation *fo; + struct TMH_EXCHANGES_KeysOperation *fo; /** * URL of the exchange used for the last @e fo. @@ -532,7 +532,7 @@ process_abort_with_exchange (void *cls, rdi->processed = true; ac->pending--; rdi->rh = TALER_EXCHANGE_refund ( - merchant_curl_ctx, + TMH_curl_ctx, ac->current_exchange, keys, &rdi->amount_with_fee, 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 3a051a3c..75bc4345 100644 --- a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c +++ b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c @@ -173,7 +173,7 @@ struct ExchangeGroup * the exchange used for this transaction; NULL if no operation is * pending. */ - struct TMH_EXCHANGES_Find2Operation *fo; + struct TMH_EXCHANGES_KeysOperation *fo; /** * Handle for operation to lookup /wire from @@ -189,6 +189,12 @@ struct ExchangeGroup const char *exchange_url; /** + * Wire fee that applies to this exchange for the + * given payment context's wire method. + */ + struct TALER_Amount wire_fee; + + /** * true if we already tried a forced /keys download. */ bool tried_force_keys; @@ -454,7 +460,7 @@ struct KycContext /** * Looking for the exchange. */ - struct TMH_EXCHANGES_Find2Operation *fo; + struct TMH_EXCHANGES_KeysOperation *fo; /** * Exchange this is about. @@ -636,20 +642,19 @@ resume_pay_with_response (struct PayContext *pc, * Resume payment processing with an error. * * @param pc operation to resume - * @param http_status http status code to return * @param ec taler error code to return * @param msg human readable error message */ static void resume_pay_with_error (struct PayContext *pc, - unsigned int http_status, enum TALER_ErrorCode ec, const char *msg) { - resume_pay_with_response (pc, - http_status, - TALER_MHD_make_error (ec, - msg)); + resume_pay_with_response ( + pc, + TALER_ErrorCode_get_http_status_safe (ec), + TALER_MHD_make_error (ec, + msg)); } @@ -795,7 +800,7 @@ process_kyc_with_exchange ( return; } kc->dg = TALER_EXCHANGE_deposits_get ( - merchant_curl_ctx, + TMH_curl_ctx, kc->exchange_url, keys, &kc->mi->merchant_priv, @@ -1007,7 +1012,6 @@ handle_batch_deposit_ok (struct ExchangeGroup *eg, GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); /* Forward error including 'proof' for the body */ resume_pay_with_error (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_STORE_FAILED, "insert_deposit"); return; @@ -1023,7 +1027,6 @@ handle_batch_deposit_ok (struct ExchangeGroup *eg, { GNUNET_break (0); resume_pay_with_error (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_COMMIT_FAILED, "insert_deposit"); } @@ -1032,7 +1035,6 @@ handle_batch_deposit_ok (struct ExchangeGroup *eg, if (GNUNET_DB_STATUS_SOFT_ERROR == qs) { resume_pay_with_error (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_SOFT_FAILURE, "insert_deposit"); return; @@ -1160,6 +1162,7 @@ process_pay_with_keys ( unsigned int group_size; eg->fo = NULL; + GNUNET_SCHEDULER_begin_async_scope (&hc->async_scope_id); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Processing payment with exchange %s\n", eg->exchange_url); @@ -1168,11 +1171,10 @@ process_pay_with_keys ( { GNUNET_break_op (0); pc->pending_at_eg--; - resume_pay_with_response ( + resume_pay_with_error ( pc, - MHD_HTTP_GATEWAY_TIMEOUT, - TALER_MHD_MAKE_JSON_PACK ( - TALER_JSON_pack_ec (TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT))); + TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT, + NULL); return; } @@ -1286,7 +1288,8 @@ AGE_FAIL: &dc->cdd.h_age_commitment); GNUNET_free (dc->age_commitment.keys); } - else if (is_age_restricted_denom && dc->no_h_age_commitment) + else if (is_age_restricted_denom && + dc->no_h_age_commitment) { /* The contract did not ask for a minimum_age but the client paid * with a coin that has age restriction enabled. We lack the hash @@ -1336,7 +1339,6 @@ AGE_FAIL: for (unsigned int i = 0; i<pc->coins_cnt; i++) { struct DepositConfirmation *dc = &pc->dc[i]; - enum GNUNET_GenericReturnValue ret; if (dc->found_in_db) continue; @@ -1344,36 +1346,13 @@ AGE_FAIL: eg->exchange_url)) continue; cdds[i] = dc->cdd; - ret = TMH_EXCHANGES_lookup_wire_fee (dc->exchange_url, - pc->wm->wire_method, - &dc->wire_fee); - if (GNUNET_OK != ret) - { - enum TALER_ErrorCode ec; - - fprintf (stderr, - "%d\n", - ret); - ec = (GNUNET_NO == ret) - ? TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED - : TALER_EC_MERCHANT_GENERIC_EXCHANGE_WIRE_REQUEST_FAILED; - pc->pending_at_eg--; - GNUNET_break_op (0); - resume_pay_with_response ( - pc, - TALER_ErrorCode_get_http_status_safe (ec), - TALER_MHD_MAKE_JSON_PACK ( - TALER_JSON_pack_ec (ec), - GNUNET_JSON_pack_string ("wire_method", - pc->wm->wire_method))); - return; - } + dc->wire_fee = eg->wire_fee; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Initiating batch deposit with %u coins\n", group_size); eg->bdh = TALER_EXCHANGE_batch_deposit ( - merchant_curl_ctx, + TMH_curl_ctx, eg->exchange_url, keys, &dcd, @@ -1413,23 +1392,24 @@ AGE_FAIL: static void process_pay_with_wire ( void *cls, - struct TMH_Exchange *wire) + const struct TMH_ExchangeWireDetails *wire) { struct ExchangeGroup *eg = cls; struct PayContext *pc = eg->pc; + struct TMH_HandlerContext *hc = pc->hc; + enum GNUNET_GenericReturnValue ret; eg->gwo = NULL; + GNUNET_SCHEDULER_begin_async_scope (&hc->async_scope_id); if (NULL == wire) { GNUNET_break_op (0); pc->pending_at_eg--; /* FIXME: define more specific error code... */ - resume_pay_with_response ( + resume_pay_with_error ( pc, - MHD_HTTP_BAD_GATEWAY, - TALER_MHD_MAKE_JSON_PACK ( - TALER_JSON_pack_ec ( - TALER_EC_MERCHANT_GENERIC_EXCHANGE_CONNECT_FAILURE))); + TALER_EC_MERCHANT_GENERIC_EXCHANGE_CONNECT_FAILURE, + NULL); return; } if (GNUNET_OK != @@ -1438,16 +1418,32 @@ process_pay_with_wire ( { GNUNET_break_op (0); pc->pending_at_eg--; - resume_pay_with_response ( + resume_pay_with_error ( pc, - MHD_HTTP_CONFLICT, - TALER_MHD_MAKE_JSON_PACK ( - TALER_JSON_pack_ec ( - TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED))); + TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED, + NULL); + return; + } + ret = TMH_EXCHANGES_lookup_wire_fee (wire, + pc->wm->wire_method, + &eg->wire_fee); + if (GNUNET_OK != ret) + { + enum TALER_ErrorCode ec; + + ec = (GNUNET_NO == ret) + ? TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_WIRE_METHOD_UNSUPPORTED + : TALER_EC_MERCHANT_GENERIC_EXCHANGE_WIRE_REQUEST_FAILED; + pc->pending_at_eg--; + GNUNET_break_op (0); + resume_pay_with_error ( + pc, + ec, + pc->wm->wire_method); return; } GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Fetching /keys for %s\n", + "Got /wire for %s, now going for /keys\n", eg->exchange_url); eg->fo = TMH_EXCHANGES_keys4exchange (eg->exchange_url, &process_pay_with_keys, @@ -1457,7 +1453,6 @@ process_pay_with_wire ( 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; @@ -1503,7 +1498,6 @@ start_batch_deposits (struct PayContext *pc) { GNUNET_break (0); 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; @@ -1665,7 +1659,6 @@ check_payment_sufficient (struct PayContext *pc) GNUNET_break (0); /* Overflow in these amounts? Very strange. */ resume_pay_with_error (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW, "Overflow adding up amounts"); return false; @@ -1676,7 +1669,6 @@ check_payment_sufficient (struct PayContext *pc) { GNUNET_break_op (0); resume_pay_with_error (pc, - MHD_HTTP_BAD_REQUEST, TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_FEES_EXCEED_PAYMENT, "Deposit fees exceed coin's contribution"); return false; @@ -1703,7 +1695,6 @@ check_payment_sufficient (struct PayContext *pc) { GNUNET_break_op (0); resume_pay_with_error (pc, - MHD_HTTP_CONFLICT, TALER_EC_GENERIC_CURRENCY_MISMATCH, total_wire_fee.currency); return false; @@ -1715,7 +1706,6 @@ check_payment_sufficient (struct PayContext *pc) { GNUNET_break (0); resume_pay_with_error (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_EXCHANGE_WIRE_FEE_ADDITION_FAILED, "could not add exchange wire fee to total"); return false; @@ -1750,7 +1740,6 @@ check_payment_sufficient (struct PayContext *pc) { GNUNET_break (0); resume_pay_with_error (pc, - MHD_HTTP_CONFLICT, TALER_EC_GENERIC_CURRENCY_MISMATCH, total_wire_fee.currency); return false; @@ -1787,7 +1776,6 @@ check_payment_sufficient (struct PayContext *pc) { GNUNET_break (0); resume_pay_with_error (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW, "Overflow adding up amounts"); return false; @@ -1815,7 +1803,6 @@ check_payment_sufficient (struct PayContext *pc) { GNUNET_break (0); resume_pay_with_error (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_AMOUNT_OVERFLOW, "Overflow adding up amounts"); return false; @@ -1839,7 +1826,6 @@ check_payment_sufficient (struct PayContext *pc) { GNUNET_break (0); resume_pay_with_error (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_REFUNDS_EXCEED_PAYMENTS, "refunded amount exceeds total payments"); return false; @@ -1854,7 +1840,6 @@ check_payment_sufficient (struct PayContext *pc) { GNUNET_break_op (0); resume_pay_with_error (pc, - MHD_HTTP_PAYMENT_REQUIRED, TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_REFUNDED, "contract not paid up due to refunds"); } @@ -1863,7 +1848,6 @@ check_payment_sufficient (struct PayContext *pc) { GNUNET_break_op (0); resume_pay_with_error (pc, - MHD_HTTP_NOT_ACCEPTABLE, TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_INSUFFICIENT_DUE_TO_FEES, "contract not paid up due to fees (client may have calculated them badly)"); } @@ -1871,7 +1855,6 @@ check_payment_sufficient (struct PayContext *pc) { GNUNET_break_op (0); resume_pay_with_error (pc, - MHD_HTTP_NOT_ACCEPTABLE, TALER_EC_MERCHANT_POST_ORDERS_ID_PAY_PAYMENT_INSUFFICIENT, "payment insufficient"); } @@ -1982,7 +1965,6 @@ execute_pay_transaction (struct PayContext *pc) { GNUNET_break (0); resume_pay_with_error (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_SOFT_FAILURE, NULL); return; @@ -2013,7 +1995,6 @@ execute_pay_transaction (struct PayContext *pc) { GNUNET_break (0); resume_pay_with_error (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_START_FAILED, NULL); return; @@ -2039,7 +2020,6 @@ execute_pay_transaction (struct PayContext *pc) /* Always report on hard error as well to enable diagnostics */ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); resume_pay_with_error (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_FETCH_FAILED, "lookup deposits"); return; @@ -2067,7 +2047,6 @@ execute_pay_transaction (struct PayContext *pc) /* Always report on hard error as well to enable diagnostics */ GNUNET_break (GNUNET_DB_STATUS_HARD_ERROR == qs); resume_pay_with_error (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_FETCH_FAILED, "lookup refunds"); return; @@ -2117,7 +2096,6 @@ execute_pay_transaction (struct PayContext *pc) } GNUNET_break (0); resume_pay_with_error (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_STORE_FAILED, "mark contract paid"); return; @@ -2153,7 +2131,6 @@ execute_pay_transaction (struct PayContext *pc) } GNUNET_break (0); resume_pay_with_error (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_STORE_FAILED, "failed to trigger webhooks"); return; @@ -2175,7 +2152,6 @@ execute_pay_transaction (struct PayContext *pc) } GNUNET_break (0); resume_pay_with_error (pc, - MHD_HTTP_INTERNAL_SERVER_ERROR, TALER_EC_GENERIC_DB_COMMIT_FAILED, NULL); return; @@ -2740,7 +2716,6 @@ handle_pay_timeout (void *cls) GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Resuming pay with error after timeout\n"); resume_pay_with_error (pc, - MHD_HTTP_GATEWAY_TIMEOUT, TALER_EC_MERCHANT_GENERIC_EXCHANGE_TIMEOUT, NULL); } diff --git a/src/backend/taler-merchant-httpd_post-orders-ID-refund.c b/src/backend/taler-merchant-httpd_post-orders-ID-refund.c index a20f6b12..ded6ff9d 100644 --- a/src/backend/taler-merchant-httpd_post-orders-ID-refund.c +++ b/src/backend/taler-merchant-httpd_post-orders-ID-refund.c @@ -51,7 +51,7 @@ struct CoinRefund /** * Request to connect to the target exchange. */ - struct TMH_EXCHANGES_Find2Operation *fo; + struct TMH_EXCHANGES_KeysOperation *fo; /** * Handle for the refund operation with the exchange. @@ -456,7 +456,7 @@ exchange_found_cb (void *cls, return; } cr->rh = TALER_EXCHANGE_refund ( - merchant_curl_ctx, + TMH_curl_ctx, cr->exchange_url, keys, &cr->refund_amount, 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 a87ea710..e8f9ba45 100644 --- a/src/backend/taler-merchant-httpd_post-tips-ID-pickup.c +++ b/src/backend/taler-merchant-httpd_post-tips-ID-pickup.c @@ -73,7 +73,7 @@ struct PlanchetOperation /** * Find operation (while active), later NULL. */ - struct TMH_EXCHANGES_Find2Operation *fo; + struct TMH_EXCHANGES_KeysOperation *fo; /** * Withdraw handle (NULL while @e fo is active). @@ -145,7 +145,7 @@ struct PickupContext /** * Find operation (while active), later NULL. */ - struct TMH_EXCHANGES_Find2Operation *fo; + struct TMH_EXCHANGES_KeysOperation *fo; /** * Which reserve are we draining? @@ -409,7 +409,7 @@ do_withdraw (void *cls, TALER_MHD_daemon_trigger (); /* we resumed, kick MHD */ return; } - po->w2h = TALER_EXCHANGE_withdraw2 (merchant_curl_ctx, + po->w2h = TALER_EXCHANGE_withdraw2 (TMH_curl_ctx, pc->exchange_url, keys, &po->pd, diff --git a/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c b/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c index 7c2f7a2c..f5b9d36e 100644 --- a/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c +++ b/src/backend/taler-merchant-httpd_private-get-instances-ID-kyc.c @@ -73,7 +73,7 @@ struct ExchangeKycRequest /** * Find operation where we connect to the respective exchange. */ - struct TMH_EXCHANGES_Find2Operation *fo; + struct TMH_EXCHANGES_KeysOperation *fo; /** * KYC request this exchange request is made for. @@ -676,7 +676,7 @@ kyc_with_exchange (void *cls, TALER_payto_hash (ekr->payto_uri, &h_payto); ekr->kyc = TALER_EXCHANGE_kyc_check ( - merchant_curl_ctx, + TMH_curl_ctx, ekr->exchange_url, keys, ekr->exchange_kyc_serial, 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 788c7bf1..6d2140d0 100644 --- a/src/backend/taler-merchant-httpd_private-get-orders-ID.c +++ b/src/backend/taler-merchant-httpd_private-get-orders-ID.c @@ -73,7 +73,7 @@ struct TransferQuery /** * Handle for ongoing exchange operation. */ - struct TMH_EXCHANGES_Find2Operation *fo; + struct TMH_EXCHANGES_KeysOperation *fo; /** * Overall request this TQ belongs with. @@ -614,7 +614,7 @@ exchange_found_cb (void *cls, return; } tq->dgh = TALER_EXCHANGE_deposits_get ( - merchant_curl_ctx, + TMH_curl_ctx, tq->exchange_url, keys, &gorc->hc->instance->merchant_priv, diff --git a/src/backend/taler-merchant-httpd_private-get-reserves-ID.c b/src/backend/taler-merchant-httpd_private-get-reserves-ID.c index 27ea2be1..4eaa6538 100644 --- a/src/backend/taler-merchant-httpd_private-get-reserves-ID.c +++ b/src/backend/taler-merchant-httpd_private-get-reserves-ID.c @@ -70,18 +70,19 @@ struct GetReserveContext * @param tips information about the tips created by this reserve */ static void -handle_reserve_details (void *cls, - struct GNUNET_TIME_Timestamp creation_time, - struct GNUNET_TIME_Timestamp expiration_time, - const struct TALER_Amount *merchant_initial_amount, - const struct TALER_Amount *exchange_initial_amount, - const struct TALER_Amount *picked_up_amount, - const struct TALER_Amount *committed_amount, - bool active, - const struct TALER_MasterPublicKeyP *master_pub, - const char *exchange_url, - unsigned int tips_length, - const struct TALER_MERCHANTDB_TipDetails *tips) +handle_reserve_details ( + void *cls, + struct GNUNET_TIME_Timestamp creation_time, + struct GNUNET_TIME_Timestamp expiration_time, + const struct TALER_Amount *merchant_initial_amount, + const struct TALER_Amount *exchange_initial_amount, + const struct TALER_Amount *picked_up_amount, + const struct TALER_Amount *committed_amount, + bool active, + const struct TALER_MasterPublicKeyP *master_pub, + const char *exchange_url, + unsigned int tips_length, + const struct TALER_MERCHANTDB_TipDetails *tips) { struct GetReserveContext *ctx = cls; json_t *tips_json; diff --git a/src/backend/taler-merchant-httpd_private-post-reserves.c b/src/backend/taler-merchant-httpd_private-post-reserves.c index 00e4a4ee..5ca8e768 100644 --- a/src/backend/taler-merchant-httpd_private-post-reserves.c +++ b/src/backend/taler-merchant-httpd_private-post-reserves.c @@ -86,7 +86,7 @@ struct PostReserveContext /** * Handle for contacting the exchange for /keys. */ - struct TMH_EXCHANGES_Find2Operation *fo; + struct TMH_EXCHANGES_KeysOperation *fo; /** * Handle for contacting the exchange for /wire. @@ -223,7 +223,7 @@ resume_request (struct PostReserveContext *rc) */ static void wire_cb (void *cls, - struct TMH_Exchange *wire) + const struct TMH_ExchangeWireDetails *wire) { struct PostReserveContext *rc = cls; diff --git a/src/backend/taler-merchant-httpd_reserves.c b/src/backend/taler-merchant-httpd_reserves.c index 83b70010..31dec87f 100644 --- a/src/backend/taler-merchant-httpd_reserves.c +++ b/src/backend/taler-merchant-httpd_reserves.c @@ -226,7 +226,7 @@ try_now (void *cls) struct Reserve *r = cls; r->tt = NULL; - r->gh = TALER_EXCHANGE_reserves_get (merchant_curl_ctx, + r->gh = TALER_EXCHANGE_reserves_get (TMH_curl_ctx, r->exchange_url, &r->reserve_pub, LONGPOLL_DELAY, |