summaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2023-05-01 19:38:05 +0200
committerChristian Grothoff <christian@grothoff.org>2023-05-01 19:38:05 +0200
commit3db683d6e794c72448824d1e4ed75d6636bf3b22 (patch)
tree60d8d6622cae16814a8585cd165f01d301ad45c5 /src/backend
parent583c01c6224dd317f9665e623b02a32b74fdf74a (diff)
downloadmerchant-3db683d6e794c72448824d1e4ed75d6636bf3b22.tar.gz
merchant-3db683d6e794c72448824d1e4ed75d6636bf3b22.tar.bz2
merchant-3db683d6e794c72448824d1e4ed75d6636bf3b22.zip
-fix FTBFS and /wire fetching logic
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/taler-merchant-httpd_exchanges.c278
-rw-r--r--src/backend/taler-merchant-httpd_post-orders-ID-pay.c3
2 files changed, 138 insertions, 143 deletions
diff --git a/src/backend/taler-merchant-httpd_exchanges.c b/src/backend/taler-merchant-httpd_exchanges.c
index 90875836..df38bca2 100644
--- a/src/backend/taler-merchant-httpd_exchanges.c
+++ b/src/backend/taler-merchant-httpd_exchanges.c
@@ -30,9 +30,10 @@
#define MAX_RETRIES 3
/**
- * Delay after which we'll re-fetch key information from the exchange.
+ * Minimum delay after which we'll re-fetch key information from the exchange.
*/
-#define RELOAD_DELAY GNUNET_TIME_relative_multiply (GNUNET_TIME_UNIT_MINUTES, 2)
+#define MIN_RELOAD_DELAY GNUNET_TIME_relative_multiply ( \
+ GNUNET_TIME_UNIT_MINUTES, 2)
/**
* Delay after which we'll allow clients to force us to re-fetch key
@@ -99,11 +100,6 @@ struct TMH_EXCHANGES_FindOperation
struct Exchange *my_exchange;
/**
- * Wire method we care about for fees, NULL if we do not care about wire fees.
- */
- char *wire_method;
-
- /**
* Task scheduled to asynchronously return the result to
* the find continuation.
*/
@@ -209,6 +205,11 @@ struct 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;
@@ -224,11 +225,11 @@ struct Exchange
struct GNUNET_SCHEDULER_Task *retry_task;
/**
- * true to indicate that there is an ongoing
- * transfer we are waiting for,
- * false to indicate that key data is up-to-date.
+ * Falsoe to indicate that there is a /keys request
+ * we are waiting for.
+ * True to indicate that /keys data is up-to-date.
*/
- bool pending;
+ bool have_keys;
/**
* true if this exchange is from our configuration and
@@ -278,10 +279,10 @@ json_t *TMH_trusted_exchanges;
* a particular exchange and what key the exchange is using.
*
* @param cls closure, will be `struct Exchange` so that
- * when this function gets called, it will change the flag 'pending'
- * to 'false'. Note: 'keys' is automatically saved inside the exchange's
+ * 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 Exchange', when
- * this callback is called. Thus, once 'pending' turns 'false',
+ * 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 kr response details
@@ -577,6 +578,8 @@ process_wire_accounts (struct Exchange *exchange,
{
TMH_db->rollback (TMH_db->cls);
GNUNET_break (0);
+ json_decref (debit_restrictions);
+ json_decref (credit_restrictions);
return TALER_EC_MERCHANT_GENERIC_EXCHANGE_WIRE_REQUEST_FAILED;
}
}
@@ -588,6 +591,8 @@ process_wire_accounts (struct Exchange *exchange,
{
TMH_db->rollback (TMH_db->cls);
GNUNET_break (0);
+ json_decref (debit_restrictions);
+ json_decref (credit_restrictions);
return TALER_EC_MERCHANT_GENERIC_EXCHANGE_WIRE_REQUEST_FAILED;
}
}
@@ -598,6 +603,8 @@ process_wire_accounts (struct Exchange *exchange,
debit_restrictions,
credit_restrictions,
&account->master_sig);
+ json_decref (debit_restrictions);
+ json_decref (credit_restrictions);
if (qs < 0)
{
TMH_db->rollback (TMH_db->cls);
@@ -677,87 +684,72 @@ process_find_operations (struct Exchange *exchange)
{
struct TMH_EXCHANGES_FindOperation *fn;
struct GNUNET_TIME_Timestamp now;
- bool need_wire;
+ if (! exchange->have_wire)
+ return true;
now = GNUNET_TIME_timestamp_get ();
- need_wire = false;
- for (struct TMH_EXCHANGES_FindOperation *fo = exchange->fo_head;
- NULL != fo;
- fo = fn)
+ for (struct FeesByWireMethod *fbw = exchange->wire_fees_head;
+ NULL != fbw;
+ fbw = fbw->next)
{
- const struct FeesByWireMethod *fbw;
+ bool removed = false;
- fn = fo->next;
- if (NULL != fo->wire_method)
+ while ( (NULL != fbw->af) &&
+ (GNUNET_TIME_timestamp_cmp (fbw->af->end_date,
+ <,
+ now)) )
{
- /* Find fee structure for our wire method */
- fbw = get_wire_fees (exchange,
- now,
- fo->wire_method);
- if (NULL == fbw)
- {
- need_wire = true;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Missing wire fees for exchange %s and method %s\n",
- exchange->url,
- fo->wire_method);
- /* Do not warn if this is before our first attempt */
- if (! GNUNET_TIME_relative_is_zero (exchange->wire_retry_delay))
- GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Exchange does not support `%s' wire method (will retry later)\n",
- fo->wire_method);
- fbw = NULL;
- continue;
- }
- 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 (will retry later)\n",
- fo->wire_method);
- fbw = NULL;
- continue;
- }
- if (GNUNET_TIME_timestamp_cmp (fbw->af->start_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)
{
- /* 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));
- fbw = NULL;
- continue;
+ exchange->have_wire = false;
+ return true; /* We just removed previous fees, try fetching update */
}
}
- else
+ if (GNUNET_TIME_timestamp_cmp (fbw->af->start_date,
+ >,
+ now))
{
- /* no wire transfer method given, so we yield no fee */
- fbw = NULL;
+ /* 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));
}
- {
- struct TALER_EXCHANGE_HttpResponse hr = {
- .http_status = MHD_HTTP_OK,
- };
+ }
- if ( (NULL != fo->wire_method) &&
- (! exchange->have_wire) )
- {
- /* We needed /wire, but didn't get it. That's not "200 OK". */
- hr.http_status = MHD_HTTP_BAD_GATEWAY;
- hr.ec = TALER_EC_MERCHANT_GENERIC_EXCHANGE_WIRE_REQUEST_FAILED;
- }
- fo->fc (fo->fc_cls,
- &hr,
- exchange->conn,
- exchange->trusted);
- }
+ 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->trusted);
+ fn = fo->next;
TMH_EXCHANGES_find_exchange_cancel (fo);
}
- return need_wire;
+ return false;
}
@@ -772,7 +764,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->pending' is #GNUNET_NO,
+ * Must only be called if 'exchange->have_keys' is true.
* that is #TALER_EXCHANGE_get_keys() will succeed.
*
* @param cls closure, a `struct Exchange`
@@ -855,8 +847,8 @@ handle_wire_data (void *cls,
exchange->wire_retry_delay);
exchange->wire_retry_delay = RETRY_BACKOFF (exchange->wire_retry_delay);
GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
- "Exchange does not support our wire method. Retrying in %s\n",
-
+ "Need %s/wire, next download attempt in %s\n",
+ exchange->url,
GNUNET_STRINGS_relative_time_to_string (
exchange->wire_retry_delay,
true));
@@ -874,7 +866,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->pending' is #GNUNET_NO,
+ * Must only be called if 'exchange->have_keys' is true,
* that is #TALER_EXCHANGE_get_keys() will succeed.
*
* @param cls a `struct Exchange` to check
@@ -885,7 +877,7 @@ wire_task_cb (void *cls)
struct Exchange *exchange = cls;
exchange->wire_task = NULL;
- GNUNET_assert (! exchange->pending);
+ GNUNET_assert (exchange->have_keys);
if (! process_find_operations (exchange))
return; /* no more need */
GNUNET_assert (NULL == exchange->wire_request);
@@ -965,7 +957,7 @@ fail_and_retry (struct Exchange *exchange,
{
struct TMH_EXCHANGES_FindOperation *fo;
- exchange->pending = true;
+ exchange->have_keys = false;
if (NULL != exchange->wire_request)
{
TALER_EXCHANGE_wire_cancel (exchange->wire_request);
@@ -998,7 +990,7 @@ fail_and_retry (struct Exchange *exchange,
(int) hr->ec,
hr->http_status,
GNUNET_STRINGS_relative_time_to_string (exchange->retry_delay,
- GNUNET_YES));
+ true));
if (NULL != exchange->retry_task)
GNUNET_SCHEDULER_cancel (exchange->retry_task);
exchange->first_retry = GNUNET_TIME_relative_to_absolute (
@@ -1014,7 +1006,6 @@ keys_mgmt_cb (void *cls,
const struct TALER_EXCHANGE_KeysResponse *kr)
{
struct Exchange *exchange = cls;
- struct GNUNET_TIME_Timestamp expire;
struct GNUNET_TIME_Relative delay;
const struct TALER_EXCHANGE_Keys *keys;
@@ -1077,26 +1068,19 @@ keys_mgmt_cb (void *cls,
}
}
- exchange->first_retry = GNUNET_TIME_relative_to_absolute (RELOAD_DELAY);
- expire = TALER_EXCHANGE_check_keys_current (exchange->conn,
- TALER_EXCHANGE_CKF_NONE);
- if (0 == GNUNET_TIME_absolute_is_zero (expire.abs_time))
- {
- delay = RELOAD_DELAY;
- }
- else
- {
- delay = GNUNET_TIME_absolute_get_remaining (expire.abs_time);
- GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "/keys response from expires at %s! Retrying at that time!\n",
- GNUNET_TIME_absolute2s (expire.abs_time));
- }
- if (GNUNET_TIME_relative_is_zero (delay))
- {
- GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
- "/keys response from exchange expired immediately! Retrying in 1 minute.\n");
- delay = GNUNET_TIME_UNIT_MINUTES;
- }
+ 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);
+ delay = GNUNET_TIME_absolute_get_remaining (
+ exchange->keys_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));
+ delay = GNUNET_TIME_relative_max (delay,
+ MIN_RELOAD_DELAY);
exchange->retry_delay = GNUNET_TIME_UNIT_ZERO;
if (NULL != exchange->retry_task)
GNUNET_SCHEDULER_cancel (exchange->retry_task);
@@ -1104,16 +1088,17 @@ keys_mgmt_cb (void *cls,
= GNUNET_SCHEDULER_add_delayed (delay,
&retry_exchange,
exchange);
- exchange->pending = false;
+ exchange->have_keys = true;
if ( (process_find_operations (exchange)) &&
(NULL == exchange->wire_request) &&
(NULL == exchange->wire_task) )
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Got key data, but also need wire data. Will request /wire now\n");
- exchange->wire_request = TALER_EXCHANGE_wire (exchange->conn,
- &handle_wire_data,
- exchange);
+ exchange->wire_request
+ = TALER_EXCHANGE_wire (exchange->conn,
+ &handle_wire_data,
+ exchange);
}
}
@@ -1132,13 +1117,16 @@ return_result (void *cls)
fo->at = NULL;
if ( (process_find_operations (exchange)) &&
(NULL == exchange->wire_request) &&
- (! exchange->pending) &&
+ (exchange->have_keys) &&
(NULL != exchange->wire_task) )
{
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
- "Do not have current wire data. Will re-request /wire in 1 minute\n");
+ "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 (GNUNET_TIME_UNIT_MINUTES,
+ = GNUNET_SCHEDULER_add_delayed (exchange->wire_retry_delay,
&wire_task_cb,
exchange);
}
@@ -1172,8 +1160,6 @@ TMH_EXCHANGES_find_exchange (const char *chosen_exchange,
{
struct Exchange *exchange;
struct TMH_EXCHANGES_FindOperation *fo;
- struct GNUNET_TIME_Timestamp now;
- const char *wire_method = NULL;
if (NULL == merchant_curl_ctx)
{
@@ -1190,7 +1176,6 @@ TMH_EXCHANGES_find_exchange (const char *chosen_exchange,
/* This is a new exchange */
exchange = GNUNET_new (struct Exchange);
exchange->url = GNUNET_strdup (chosen_exchange);
- exchange->pending = true;
GNUNET_CONTAINER_DLL_insert (exchange_head,
exchange_tail,
exchange);
@@ -1203,13 +1188,13 @@ TMH_EXCHANGES_find_exchange (const char *chosen_exchange,
fo->fc = fc;
fo->fc_cls = fc_cls;
fo->my_exchange = exchange;
- if (NULL != wire_method)
- fo->wire_method = GNUNET_strdup (wire_method);
GNUNET_CONTAINER_DLL_insert (exchange->fo_head,
exchange->fo_tail,
fo);
- if ( (force_reload) &&
- (GNUNET_TIME_absolute_is_past (exchange->first_retry)) )
+ 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);
@@ -1222,25 +1207,20 @@ TMH_EXCHANGES_find_exchange (const char *chosen_exchange,
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"/keys retry forced, waiting until %s\n",
GNUNET_TIME_absolute2s (exchange->first_retry));
- /* NOTE: return value tells us how long /keys should still
- be valid. */
- (void) TALER_EXCHANGE_check_keys_current (exchange->conn,
- TALER_EXCHANGE_CKF_FORCE_DOWNLOAD);
+ exchange->keys_expiration
+ = TALER_EXCHANGE_check_keys_current (exchange->conn,
+ TALER_EXCHANGE_CKF_FORCE_DOWNLOAD);
return fo;
}
- now = GNUNET_TIME_timestamp_get ();
- if ( (! exchange->pending) &&
- ( (NULL == fo->wire_method) ||
- (NULL != get_wire_fees (exchange,
- now,
- fo->wire_method)) ) )
+ 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",
- chosen_exchange);
+ exchange->url);
GNUNET_assert (NULL == fo->at);
fo->at = GNUNET_SCHEDULER_add_now (&return_result,
fo);
@@ -1250,23 +1230,28 @@ TMH_EXCHANGES_find_exchange (const char *chosen_exchange,
/* If new or resumed, (re)try fetching /keys */
if ( (NULL == exchange->conn) &&
(NULL == exchange->retry_task) &&
- (exchange->pending) )
+ (! exchange->have_keys) )
{
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
"Do not have current /keys data for `%s'. Will request /keys now\n",
- chosen_exchange);
+ exchange->url);
exchange->retry_task = GNUNET_SCHEDULER_add_now (&retry_exchange,
exchange);
+ return fo;
}
- else if ( (! exchange->pending) &&
- (NULL == exchange->wire_task) &&
- (NULL == exchange->wire_request) )
+ 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 /wire now\n");
+ "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;
}
@@ -1284,7 +1269,6 @@ TMH_EXCHANGES_find_exchange_cancel (struct TMH_EXCHANGES_FindOperation *fo)
GNUNET_CONTAINER_DLL_remove (exchange->fo_head,
exchange->fo_tail,
fo);
- GNUNET_free (fo->wire_method);
GNUNET_free (fo);
}
@@ -1378,7 +1362,6 @@ accept_exchanges (void *cls,
GNUNET_CONTAINER_DLL_insert (exchange_head,
exchange_tail,
exchange);
- exchange->pending = true;
GNUNET_assert (NULL == exchange->retry_task);
exchange->retry_task = GNUNET_SCHEDULER_add_now (&retry_exchange,
exchange);
@@ -1396,9 +1379,18 @@ TMH_EXCHANGES_lookup_wire_fee (const char *exchange_url,
exchange = lookup_exchange (exchange_url);
if (NULL == exchange)
+ {
+ fprintf (stderr,
+ "No %s yet\n",
+ exchange_url);
return GNUNET_SYSERR;
+ }
if (! exchange->have_wire)
+ {
+ fprintf (stderr,
+ "No wire yet\n");
return GNUNET_SYSERR;
+ }
fbm = get_wire_fees (exchange,
GNUNET_TIME_timestamp_get (),
wire_method);
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 55e345e6..afec3b25 100644
--- a/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
+++ b/src/backend/taler-merchant-httpd_post-orders-ID-pay.c
@@ -1440,6 +1440,9 @@ AGE_FAIL:
{
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;