diff options
Diffstat (limited to 'src/backend/taler-merchant-httpd_exchanges.c')
-rw-r--r-- | src/backend/taler-merchant-httpd_exchanges.c | 426 |
1 files changed, 62 insertions, 364 deletions
diff --git a/src/backend/taler-merchant-httpd_exchanges.c b/src/backend/taler-merchant-httpd_exchanges.c index c0138537..665607c1 100644 --- a/src/backend/taler-merchant-httpd_exchanges.c +++ b/src/backend/taler-merchant-httpd_exchanges.c @@ -64,46 +64,6 @@ /** - * Information we keep for a pending #MMH_EXCHANGES_find_exchange() operation. - */ -struct TMH_EXCHANGES_FindOperation -{ - - /** - * Kept in a DLL. - */ - struct TMH_EXCHANGES_FindOperation *next; - - /** - * Kept in a DLL. - */ - struct TMH_EXCHANGES_FindOperation *prev; - - /** - * Function to call with the result. - */ - TMH_EXCHANGES_FindContinuation 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_keys4exchange() operation. */ struct TMH_EXCHANGES_Find2Operation @@ -312,16 +272,6 @@ struct TMH_Exchange /** * Head of FOs pending for this exchange. */ - struct TMH_EXCHANGES_FindOperation *fo_head; - - /** - * Tail of FOs pending for this exchange. - */ - struct TMH_EXCHANGES_FindOperation *fo_tail; - - /** - * Head of FOs pending for this exchange. - */ struct TMH_EXCHANGES_Find2Operation *fo2_head; /** @@ -357,7 +307,12 @@ struct TMH_Exchange /** * A connection to this exchange */ - struct TALER_EXCHANGE_Handle *conn; + struct TALER_EXCHANGE_GetKeysHandle *conn; + + /** + * The keys of this exchange + */ + struct TALER_EXCHANGE_Keys *keys; /** * Active /wire request to the exchange, or NULL. @@ -391,11 +346,6 @@ struct TMH_Exchange struct GNUNET_TIME_Absolute first_retry; /** - * How soon should we re-download /keys? - */ - struct GNUNET_TIME_Timestamp keys_expiration; - - /** * How long should we wait between the next retry? */ struct GNUNET_TIME_Relative retry_delay; @@ -411,13 +361,6 @@ struct TMH_Exchange struct GNUNET_SCHEDULER_Task *retry_task; /** - * Falsoe to indicate that there is a /keys request - * we are waiting for. - * True to indicate that /keys data is up-to-date. - */ - bool have_keys; - - /** * true if this exchange is from our configuration and * explicitly trusted, false if we need to check each * key to be sure it is trusted. @@ -466,18 +409,14 @@ 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` so that - * when this function gets called, it will change the flag 'have_keys' - * to 'true'. Note: 'keys' is automatically saved inside the exchange's - * handle, which is contained inside 'struct TMH_Exchange', when - * this callback is called. Thus, once 'have_keys' turns 'true', - * it is safe to call 'TALER_EXCHANGE_get_keys()' on the exchange's handle, - * in order to get the "good" keys. + * @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); + const struct TALER_EXCHANGE_KeysResponse *kr, + struct TALER_EXCHANGE_Keys *keys); /** @@ -544,9 +483,10 @@ purge_exchange_accounts (struct TMH_Exchange *exchange) * @return #GNUNET_OK on success */ static enum GNUNET_GenericReturnValue -set_exchange_accounts (struct TMH_Exchange *exchange, - unsigned int accounts_len, - const struct TALER_EXCHANGE_WireAccount *accounts) +set_exchange_accounts ( + struct TMH_Exchange *exchange, + unsigned int accounts_len, + const struct TALER_EXCHANGE_WireAccount accounts[static accounts_len]) { purge_exchange_accounts (exchange); for (unsigned int i = 0; i<accounts_len; i++) @@ -608,32 +548,19 @@ retry_exchange (void *cls) /* might be a scheduled reload and not our first attempt */ exchange->retry_task = NULL; + if (NULL != exchange->conn) + return; GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Connecting to exchange %s in retry_exchange()\n", exchange->url); - if (NULL == exchange->conn) - { - exchange->conn = TALER_EXCHANGE_connect (merchant_curl_ctx, - exchange->url, - &keys_mgmt_cb, - exchange, - TALER_EXCHANGE_OPTION_END); - } - else - { - struct GNUNET_TIME_Timestamp next; - - next = TALER_EXCHANGE_check_keys_current (exchange->conn, - TALER_EXCHANGE_CKF_NONE, - NULL, - NULL); - if (! GNUNET_TIME_absolute_is_zero (next.abs_time)) - { - exchange->retry_task = GNUNET_SCHEDULER_add_at (next.abs_time, - &retry_exchange, - exchange); - } - } + 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); /* Note: while the API spec says 'returns NULL on error', the implementation actually never returns NULL. */ GNUNET_break (NULL != exchange->conn); @@ -652,10 +579,11 @@ retry_exchange (void *cls) * @return #TALER_EC_NONE on success */ static enum TALER_ErrorCode -process_wire_fees (struct TMH_Exchange *exchange, - const struct TALER_MasterPublicKeyP *master_pub, - unsigned int num_methods, - const struct TALER_EXCHANGE_WireFeesByMethod *fbm) +process_wire_fees ( + struct TMH_Exchange *exchange, + const struct TALER_MasterPublicKeyP *master_pub, + unsigned int num_methods, + const struct TALER_EXCHANGE_WireFeesByMethod fbm[static num_methods]) { for (unsigned int i = 0; i<num_methods; i++) { @@ -990,7 +918,6 @@ get_wire_fees (struct TMH_Exchange *exchange, 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; @@ -1001,7 +928,7 @@ process_find_operations (struct TMH_Exchange *exchange) fo = fn2) { fo->fc (fo->fc_cls, - TALER_EXCHANGE_get_keys (exchange->conn)); + exchange->keys); fn2 = fo->next; TMH_EXCHANGES_keys4exchange_cancel (fo); } @@ -1053,22 +980,6 @@ process_find_operations (struct TMH_Exchange *exchange) if (! exchange->have_wire) return true; /* need /wire response to continue */ - fn = NULL; - for (struct TMH_EXCHANGES_FindOperation *fo = exchange->fo_head; - NULL != fo; - fo = fn) - { - struct TALER_EXCHANGE_HttpResponse hr = { - .http_status = MHD_HTTP_OK, - }; - - fo->fc (fo->fc_cls, - &hr, - exchange->conn, - exchange); - fn = fo->next; - TMH_EXCHANGES_find_exchange_cancel (fo); - } wn = NULL; for (struct TMH_EXCHANGES_WireOperation *w = exchange->w_head; NULL != w; @@ -1094,8 +1005,7 @@ wire_task_cb (void *cls); * If the request fails to generate a valid response from the * exchange, @a http_status will also be zero. * - * Must only be called if 'exchange->have_keys' is true. - * that is #TALER_EXCHANGE_get_keys() will succeed. + * Must only be called if 'exchange->keys' is non-NULL. * * @param cls closure, a `struct TMH_Exchange` * @param wr response details @@ -1113,7 +1023,6 @@ handle_wire_data (void *cls, "Received /wire response\n"); if (MHD_HTTP_OK != wr->hr.http_status) { - struct TMH_EXCHANGES_FindOperation *fo; struct TMH_EXCHANGES_WireOperation *w; exchange->have_wire = false; @@ -1122,14 +1031,6 @@ handle_wire_data (void *cls, exchange->url, wr->hr.http_status, wr->hr.ec); - while (NULL != (fo = exchange->fo_head)) - { - fo->fc (fo->fc_cls, - &wr->hr, - exchange->conn, - false); - TMH_EXCHANGES_find_exchange_cancel (fo); - } while (NULL != (w = exchange->w_head)) { w->fc (w->fc_cls, @@ -1138,7 +1039,7 @@ handle_wire_data (void *cls, } return; } - keys = TALER_EXCHANGE_get_keys (exchange->conn); + keys = exchange->keys; GNUNET_assert (NULL != keys); ecx = process_wire_accounts (exchange, &keys->master_pub, @@ -1152,24 +1053,10 @@ handle_wire_data (void *cls, if (TALER_EC_NONE != ecx) { /* 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, - .reply = wr->hr.reply - }; GNUNET_break_op (0); exchange->have_wire = false; - while (NULL != (fo = exchange->fo_head)) - { - fo->fc (fo->fc_cls, - &hrx, - NULL, - false); - TMH_EXCHANGES_find_exchange_cancel (fo); - } while (NULL != (fo2 = exchange->fo2_head)) { fo2->fc (fo2->fc_cls, @@ -1210,8 +1097,7 @@ handle_wire_data (void *cls, * the callback. If requests without /wire data remain, * retry the /wire request after some delay. * - * Must only be called if 'exchange->have_keys' is true, - * that is #TALER_EXCHANGE_get_keys() will succeed. + * Must only be called if 'exchange->keys' is non-NULL. * * @param cls a `struct TMH_Exchange` to check */ @@ -1221,7 +1107,6 @@ wire_task_cb (void *cls) struct TMH_Exchange *exchange = cls; exchange->wire_task = NULL; - GNUNET_assert (exchange->have_keys); if (! process_find_operations (exchange)) return; /* no more need */ GNUNET_assert (NULL == exchange->wire_request); @@ -1230,7 +1115,7 @@ wire_task_cb (void *cls) exchange->wire_request = TALER_EXCHANGE_wire (merchant_curl_ctx, exchange->url, - TALER_EXCHANGE_get_keys (exchange->conn), + exchange->keys, &handle_wire_data, exchange); } @@ -1277,16 +1162,16 @@ free_exchange_entry (struct TMH_Exchange *exchange) } if (NULL != exchange->conn) { - TALER_EXCHANGE_disconnect (exchange->conn); + TALER_EXCHANGE_get_keys_cancel (exchange->conn); exchange->conn = NULL; } + TALER_EXCHANGE_keys_decref (exchange->keys); + exchange->keys = NULL; if (NULL != exchange->retry_task) { GNUNET_SCHEDULER_cancel (exchange->retry_task); exchange->retry_task = NULL; } - 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); @@ -1307,11 +1192,9 @@ static void 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) { TALER_EXCHANGE_wire_cancel (exchange->wire_request); @@ -1322,14 +1205,6 @@ fail_and_retry (struct TMH_Exchange *exchange, GNUNET_SCHEDULER_cancel (exchange->wire_task); exchange->wire_task = NULL; } - while (NULL != (fo = exchange->fo_head)) - { - fo->fc (fo->fc_cls, - hr, - NULL, - false); - TMH_EXCHANGES_find_exchange_cancel (fo); - } while (NULL != (fo2 = exchange->fo2_head)) { fo2->fc (fo2->fc_cls, @@ -1342,8 +1217,7 @@ fail_and_retry (struct TMH_Exchange *exchange, NULL); TMH_EXCHANGES_wire4exchange_cancel (w); } - if ( (NULL == exchange->fo_head) && - (TALER_EC_GENERIC_CONFIGURATION_INVALID == hr->ec) ) + if (TALER_EC_GENERIC_CONFIGURATION_INVALID == hr->ec) { /* This can NEVER work, so don't retry */ free_exchange_entry (exchange); @@ -1369,19 +1243,21 @@ fail_and_retry (struct TMH_Exchange *exchange, static void keys_mgmt_cb (void *cls, - const struct TALER_EXCHANGE_KeysResponse *kr) + const struct TALER_EXCHANGE_KeysResponse *kr, + struct TALER_EXCHANGE_Keys *keys) { struct TMH_Exchange *exchange = cls; struct GNUNET_TIME_Relative delay; - const struct TALER_EXCHANGE_Keys *keys; + exchange->conn = NULL; if (MHD_HTTP_OK != kr->hr.http_status) { fail_and_retry (exchange, &kr->hr); return; } - keys = kr->details.ok.keys; + TALER_EXCHANGE_keys_decref (exchange->keys); + exchange->keys = keys; if ( (exchange->trusted) && (0 != GNUNET_memcmp (&exchange->master_pub, &keys->master_pub)) ) @@ -1436,17 +1312,12 @@ keys_mgmt_cb (void *cls, exchange->first_retry = GNUNET_TIME_relative_to_absolute (MIN_RELOAD_DELAY); - exchange->keys_expiration - = TALER_EXCHANGE_check_keys_current (exchange->conn, - TALER_EXCHANGE_CKF_NONE, - NULL, - NULL); delay = GNUNET_TIME_absolute_get_remaining ( - exchange->keys_expiration.abs_time); + keys->key_data_expiration.abs_time); GNUNET_log (GNUNET_ERROR_TYPE_INFO, "/keys response from expires at %s! Retrying at that time!\n", GNUNET_TIME_absolute2s ( - exchange->keys_expiration.abs_time)); + keys->key_data_expiration.abs_time)); delay = GNUNET_TIME_relative_max (delay, MIN_RELOAD_DELAY); exchange->retry_delay = GNUNET_TIME_UNIT_ZERO; @@ -1456,7 +1327,6 @@ keys_mgmt_cb (void *cls, = GNUNET_SCHEDULER_add_delayed (delay, &retry_exchange, exchange); - exchange->have_keys = true; if ( (process_find_operations (exchange)) && (NULL == exchange->wire_request) && (NULL == exchange->wire_task) ) @@ -1467,7 +1337,7 @@ keys_mgmt_cb (void *cls, = TALER_EXCHANGE_wire ( merchant_curl_ctx, exchange->url, - TALER_EXCHANGE_get_keys (exchange->conn), + exchange->keys, &handle_wire_data, exchange); } @@ -1477,36 +1347,6 @@ keys_mgmt_cb (void *cls, /** * Task to return find operation result asynchronously to caller. * - * @param cls a `struct TMH_EXCHANGES_FindOperation` - */ -static void -return_result (void *cls) -{ - struct TMH_EXCHANGES_FindOperation *fo = cls; - struct TMH_Exchange *exchange = fo->my_exchange; - - fo->at = NULL; - if ( (process_find_operations (exchange)) && - (NULL == exchange->wire_request) && - (exchange->have_keys) && - (NULL != exchange->wire_task) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Do not have current wire data. Will re-request /wire in %s\n", - GNUNET_STRINGS_relative_time_to_string ( - exchange->wire_retry_delay, - true)); - exchange->wire_task - = GNUNET_SCHEDULER_add_delayed (exchange->wire_retry_delay, - &wire_task_cb, - exchange); - } -} - - -/** - * Task to return find operation result asynchronously to caller. - * * @param cls a `struct TMH_EXCHANGES_Find2Operation` */ static void @@ -1555,124 +1395,6 @@ lookup_exchange (const char *exchange_url) } -struct TMH_EXCHANGES_FindOperation * -TMH_EXCHANGES_find_exchange (const char *chosen_exchange, - bool force_reload, - TMH_EXCHANGES_FindContinuation fc, - void *fc_cls) -{ - struct TMH_Exchange *exchange; - struct TMH_EXCHANGES_FindOperation *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_FindOperation); - fo->fc = fc; - fo->fc_cls = fc_cls; - fo->my_exchange = exchange; - GNUNET_CONTAINER_DLL_insert (exchange->fo_head, - exchange->fo_tail, - fo); - - if ( (GNUNET_TIME_absolute_is_past (exchange->first_retry)) && - (force_reload || - (GNUNET_TIME_absolute_is_past ( - exchange->keys_expiration.abs_time))) ) - { - /* 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) && - (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 == fo->at); - fo->at = GNUNET_SCHEDULER_add_now (&return_result, - 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; - } - if ( (exchange->have_keys) && - (! exchange->have_wire) && - (NULL == exchange->wire_task) && - (NULL == exchange->wire_request) ) - { - GNUNET_log (GNUNET_ERROR_TYPE_INFO, - "Do not have required /wire data. Will re-request %s/wire now\n", - exchange->url); - exchange->wire_task = GNUNET_SCHEDULER_add_now (&wire_task_cb, - exchange); - return fo; - } - /* No activity to launch, we are already doing so */ - return fo; -} - - struct TMH_EXCHANGES_Find2Operation * TMH_EXCHANGES_keys4exchange ( const char *chosen_exchange, @@ -1726,26 +1448,15 @@ TMH_EXCHANGES_keys4exchange ( 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 */ + + if (NULL == exchange->retry_task) 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) + if (NULL != exchange->keys) { /* We are not currently waiting for a reply, immediately return result */ @@ -1759,9 +1470,8 @@ TMH_EXCHANGES_keys4exchange ( } /* If new or resumed, (re)try fetching /keys */ - if ( (NULL == exchange->conn) && - (NULL == exchange->retry_task) && - (! exchange->have_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", @@ -1834,11 +1544,11 @@ TMH_EXCHANGES_wire4exchange ( 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); + exchange->conn = TALER_EXCHANGE_get_keys (merchant_curl_ctx, + exchange->url, + exchange->keys, + &keys_mgmt_cb, + exchange); } else { @@ -1848,7 +1558,7 @@ TMH_EXCHANGES_wire4exchange ( exchange->wire_request = TALER_EXCHANGE_wire (merchant_curl_ctx, exchange->url, - TALER_EXCHANGE_get_keys (exchange->conn), + exchange->keys, &handle_wire_data, exchange); } @@ -1858,23 +1568,6 @@ TMH_EXCHANGES_wire4exchange ( void -TMH_EXCHANGES_find_exchange_cancel (struct TMH_EXCHANGES_FindOperation *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->fo_head, - exchange->fo_tail, - fo); - GNUNET_free (fo); -} - - -void TMH_EXCHANGES_keys4exchange_cancel (struct TMH_EXCHANGES_Find2Operation *fo) { struct TMH_Exchange *exchange = fo->my_exchange; @@ -2045,6 +1738,11 @@ TMH_EXCHANGES_init (const struct GNUNET_CONFIGURATION_Handle *cfg) 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 */ |