more work on API atomization

This commit is contained in:
Christian Grothoff 2023-07-03 17:51:13 +02:00
parent 75ea35722b
commit 290268e9af
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
3 changed files with 36 additions and 95 deletions

View File

@ -1062,14 +1062,18 @@ struct TALER_EXCHANGE_WireHandle;
* response are all valid). If the exchange's reply is not * response are all valid). If the exchange's reply is not
* well-formed, we return an HTTP status code of zero to @a cb. * well-formed, we return an HTTP status code of zero to @a cb.
* *
* @param exchange the exchange handle; the exchange must be ready to operate * @param ctx curl context
* @param url exchange base URL
* @param keys the keys of the exchange
* @param wire_cb the callback to call when a reply for this request is available * @param wire_cb the callback to call when a reply for this request is available
* @param wire_cb_cls closure for the above callback * @param wire_cb_cls closure for the above callback
* @return a handle for this request * @return a handle for this request
*/ */
struct TALER_EXCHANGE_WireHandle * struct TALER_EXCHANGE_WireHandle *
TALER_EXCHANGE_wire ( TALER_EXCHANGE_wire (
struct TALER_EXCHANGE_Handle *exchange, struct GNUNET_CURL_Context *ctx,
const char *url,
struct TALER_EXCHANGE_Keys *keys,
TALER_EXCHANGE_WireCallback wire_cb, TALER_EXCHANGE_WireCallback wire_cb,
void *wire_cb_cls); void *wire_cb_cls);

View File

@ -38,9 +38,9 @@ struct TALER_EXCHANGE_WireHandle
{ {
/** /**
* The connection to exchange this request handle will use * The keys of the exchange this request handle will use
*/ */
struct TALER_EXCHANGE_Handle *exchange; struct TALER_EXCHANGE_Keys *keys;
/** /**
* The url for this request. * The url for this request.
@ -199,7 +199,6 @@ handle_wire_finished (void *cls,
{ {
case 0: case 0:
wr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE; wr.hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
wh->exchange->wire_error_count++;
break; break;
case MHD_HTTP_OK: case MHD_HTTP_OK:
{ {
@ -220,7 +219,6 @@ handle_wire_finished (void *cls,
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
wh->exchange->wire_error_count = 0;
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_JSON_parse (j, GNUNET_JSON_parse (j,
spec, spec,
@ -232,19 +230,14 @@ handle_wire_finished (void *cls,
wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED; wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break; break;
} }
if (0 != GNUNET_memcmp (&wh->keys->master_pub,
&master_pub))
{ {
const struct TALER_EXCHANGE_Keys *key_state; /* bogus reply: master public key in /wire differs from that in /keys */
GNUNET_break_op (0);
key_state = TALER_EXCHANGE_get_keys (wh->exchange); wr.hr.http_status = 0;
if (0 != GNUNET_memcmp (&key_state->master_pub, wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
&master_pub)) break;
{
/* bogus reply: master public key in /wire differs from that in /keys */
GNUNET_break_op (0);
wr.hr.http_status = 0;
wr.hr.ec = TALER_EC_GENERIC_REPLY_MALFORMED;
break;
}
} }
wr.details.ok.accounts_len wr.details.ok.accounts_len
@ -321,8 +314,6 @@ handle_wire_finished (void *cls,
break; break;
default: default:
/* unexpected response code */ /* unexpected response code */
if (MHD_HTTP_GATEWAY_TIMEOUT == response_code)
wh->exchange->wire_error_count++;
GNUNET_break_op (0); GNUNET_break_op (0);
wr.hr.ec = TALER_JSON_get_error_code (j); wr.hr.ec = TALER_JSON_get_error_code (j);
wr.hr.hint = TALER_JSON_get_error_hint (j); wr.hr.hint = TALER_JSON_get_error_hint (j);
@ -339,61 +330,23 @@ handle_wire_finished (void *cls,
} }
/**
* Compute the network timeout for the next request to /wire.
*
* @param exchange the exchange handle
* @returns the timeout in seconds (for use by CURL)
*/
static long
get_wire_timeout_seconds (struct TALER_EXCHANGE_Handle *exchange)
{
return GNUNET_MIN (60,
5 + (1L << exchange->wire_error_count));
}
/**
* Obtain information about a exchange's wire instructions.
* A exchange may provide wire instructions for creating
* a reserve. The wire instructions also indicate
* which wire formats merchants may use with the exchange.
* This API is typically used by a wallet for wiring
* funds, and possibly by a merchant to determine
* supported wire formats.
*
* Note that while we return the (main) response verbatim to the
* caller for further processing, we do already verify that the
* response is well-formed (i.e. that signatures included in the
* response are all valid). If the exchange's reply is not well-formed,
* we return an HTTP status code of zero to @a cb.
*
* @param exchange the exchange handle; the exchange must be ready to operate
* @param wire_cb the callback to call when a reply for this request is available
* @param wire_cb_cls closure for the above callback
* @return a handle for this request
*/
struct TALER_EXCHANGE_WireHandle * struct TALER_EXCHANGE_WireHandle *
TALER_EXCHANGE_wire (struct TALER_EXCHANGE_Handle *exchange, TALER_EXCHANGE_wire (
TALER_EXCHANGE_WireCallback wire_cb, struct GNUNET_CURL_Context *ctx,
void *wire_cb_cls) const char *url,
struct TALER_EXCHANGE_Keys *keys,
TALER_EXCHANGE_WireCallback wire_cb,
void *wire_cb_cls)
{ {
struct TALER_EXCHANGE_WireHandle *wh; struct TALER_EXCHANGE_WireHandle *wh;
struct GNUNET_CURL_Context *ctx;
CURL *eh; CURL *eh;
if (GNUNET_YES !=
TEAH_handle_is_ready (exchange))
{
GNUNET_break (0);
return NULL;
}
wh = GNUNET_new (struct TALER_EXCHANGE_WireHandle); wh = GNUNET_new (struct TALER_EXCHANGE_WireHandle);
wh->exchange = exchange;
wh->cb = wire_cb; wh->cb = wire_cb;
wh->cb_cls = wire_cb_cls; wh->cb_cls = wire_cb_cls;
wh->url = TEAH_path_to_url (exchange, wh->url = TALER_url_join (url,
"/wire"); "wire",
NULL);
if (NULL == wh->url) if (NULL == wh->url)
{ {
GNUNET_free (wh); GNUNET_free (wh);
@ -410,8 +363,8 @@ TALER_EXCHANGE_wire (struct TALER_EXCHANGE_Handle *exchange,
GNUNET_break (CURLE_OK == GNUNET_break (CURLE_OK ==
curl_easy_setopt (eh, curl_easy_setopt (eh,
CURLOPT_TIMEOUT, CURLOPT_TIMEOUT,
get_wire_timeout_seconds (wh->exchange))); 60 /* seconds */));
ctx = TEAH_handle_to_context (exchange); wh->keys = TALER_EXCHANGE_keys_incref (keys);
wh->job = GNUNET_CURL_job_add_with_ct_json (ctx, wh->job = GNUNET_CURL_job_add_with_ct_json (ctx,
eh, eh,
&handle_wire_finished, &handle_wire_finished,
@ -420,14 +373,9 @@ TALER_EXCHANGE_wire (struct TALER_EXCHANGE_Handle *exchange,
} }
/**
* Cancel a wire information request. This function cannot be used
* on a request handle if a response is already served for it.
*
* @param wh the wire information request handle
*/
void void
TALER_EXCHANGE_wire_cancel (struct TALER_EXCHANGE_WireHandle *wh) TALER_EXCHANGE_wire_cancel (
struct TALER_EXCHANGE_WireHandle *wh)
{ {
if (NULL != wh->job) if (NULL != wh->job)
{ {
@ -435,6 +383,7 @@ TALER_EXCHANGE_wire_cancel (struct TALER_EXCHANGE_WireHandle *wh)
wh->job = NULL; wh->job = NULL;
} }
GNUNET_free (wh->url); GNUNET_free (wh->url);
TALER_EXCHANGE_keys_decref (wh->keys);
GNUNET_free (wh); GNUNET_free (wh);
} }

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2018 Taler Systems SA Copyright (C) 2018, 2023 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it TALER is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by under the terms of the GNU General Public License as published by
@ -191,16 +191,15 @@ wire_run (void *cls,
struct TALER_TESTING_Interpreter *is) struct TALER_TESTING_Interpreter *is)
{ {
struct WireState *ws = cls; struct WireState *ws = cls;
struct TALER_EXCHANGE_Handle *exchange
= TALER_TESTING_get_exchange (is);
ws->cmd = cmd; ws->cmd = cmd;
if (NULL == exchange)
return;
ws->is = is; ws->is = is;
ws->wh = TALER_EXCHANGE_wire (exchange, ws->wh = TALER_EXCHANGE_wire (
&wire_cb, TALER_TESTING_interpreter_get_context (is),
ws); TALER_TESTING_get_exchange_url (is),
TALER_TESTING_get_keys (is),
&wire_cb,
ws);
} }
@ -228,17 +227,6 @@ wire_cleanup (void *cls,
} }
/**
* Create a "wire" command.
*
* @param label the command label.
* @param expected_method which wire-transfer method is expected
* to be offered by the exchange.
* @param expected_fee the fee the exchange should charge.
* @param expected_response_code the HTTP response the exchange
* should return.
* @return the command.
*/
struct TALER_TESTING_Command struct TALER_TESTING_Command
TALER_TESTING_cmd_wire (const char *label, TALER_TESTING_cmd_wire (const char *label,
const char *expected_method, const char *expected_method,