-change handler signatures to prepare for long polling support

This commit is contained in:
Christian Grothoff 2021-08-21 14:00:29 +02:00
parent a51f39217e
commit f93a0592b2
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
22 changed files with 289 additions and 392 deletions

View File

@ -56,33 +56,6 @@
#define UNIX_BACKLOG 500 #define UNIX_BACKLOG 500
/**
* Type of the closure associated with each HTTP request to the exchange.
*/
struct ExchangeHttpRequestClosure
{
/**
* Async Scope ID associated with this request.
*/
struct GNUNET_AsyncScopeId async_scope_id;
/**
* Opaque parsing context.
*/
void *opaque_post_parsing_context;
/**
* Cached request handler for this request (once we have found one).
*/
struct TEH_RequestHandler *rh;
/**
* Request URL (for logging).
*/
const char *url;
};
/** /**
* Are clients allowed to request /keys for times other than the * Are clients allowed to request /keys for times other than the
* current time? Allowing this could be abused in a DoS-attack * current time? Allowing this could be abused in a DoS-attack
@ -204,16 +177,14 @@ r404 (struct MHD_Connection *connection,
* Handle a "/coins/$COIN_PUB/$OP" POST request. Parses the "coin_pub" * Handle a "/coins/$COIN_PUB/$OP" POST request. Parses the "coin_pub"
* EdDSA key of the coin and demultiplexes based on $OP. * EdDSA key of the coin and demultiplexes based on $OP.
* *
* @param rh context of the handler * @param rc request context
* @param connection the MHD connection to handle
* @param root uploaded JSON data * @param root uploaded JSON data
* @param args array of additional options (first must be the * @param args array of additional options (first must be the
* reserve public key, the second one should be "withdraw") * reserve public key, the second one should be "withdraw")
* @return MHD result code * @return MHD result code
*/ */
static MHD_RESULT static MHD_RESULT
handle_post_coins (const struct TEH_RequestHandler *rh, handle_post_coins (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const json_t *root, const json_t *root,
const char *const args[2]) const char *const args[2])
{ {
@ -253,7 +224,6 @@ handle_post_coins (const struct TEH_RequestHandler *rh,
}, },
}; };
(void) rh;
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_STRINGS_string_to_data (args[0], GNUNET_STRINGS_string_to_data (args[0],
strlen (args[0]), strlen (args[0]),
@ -261,7 +231,7 @@ handle_post_coins (const struct TEH_RequestHandler *rh,
sizeof (coin_pub))) sizeof (coin_pub)))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_GENERIC_COINS_INVALID_COIN_PUB, TALER_EC_EXCHANGE_GENERIC_COINS_INVALID_COIN_PUB,
args[0]); args[0]);
@ -269,10 +239,11 @@ handle_post_coins (const struct TEH_RequestHandler *rh,
for (unsigned int i = 0; NULL != h[i].op; i++) for (unsigned int i = 0; NULL != h[i].op; i++)
if (0 == strcmp (h[i].op, if (0 == strcmp (h[i].op,
args[1])) args[1]))
return h[i].handler (connection, return h[i].handler (rc->connection,
&coin_pub, &coin_pub,
root); root);
return r404 (connection, args[1]); return r404 (rc->connection,
args[1]);
} }
@ -296,14 +267,16 @@ handle_mhd_completion_callback (void *cls,
void **con_cls, void **con_cls,
enum MHD_RequestTerminationCode toe) enum MHD_RequestTerminationCode toe)
{ {
struct ExchangeHttpRequestClosure *ecls = *con_cls; struct TEH_RequestContext *rc = *con_cls;
struct GNUNET_AsyncScopeSave old_scope; struct GNUNET_AsyncScopeSave old_scope;
(void) cls; (void) cls;
if (NULL == ecls) if (NULL == rc)
return; return;
GNUNET_async_scope_enter (&ecls->async_scope_id, GNUNET_async_scope_enter (&rc->async_scope_id,
&old_scope); &old_scope);
if (NULL != rc->rh_cleaner)
rc->rh_cleaner (rc);
{ {
#if MHD_VERSION >= 0x00097304 #if MHD_VERSION >= 0x00097304
const union MHD_ConnectionInfo *ci; const union MHD_ConnectionInfo *ci;
@ -315,52 +288,49 @@ handle_mhd_completion_callback (void *cls,
http_status = ci->http_status; http_status = ci->http_status;
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Request for `%s' completed with HTTP status %u (%d)\n", "Request for `%s' completed with HTTP status %u (%d)\n",
ecls->url, rc->url,
http_status, http_status,
toe); toe);
#else #else
(void) connection; (void) connection;
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Request for `%s' completed (%d)\n", "Request for `%s' completed (%d)\n",
ecls->url, rc->url,
toe); toe);
#endif #endif
} }
TALER_MHD_parse_post_cleanup_callback (ecls->opaque_post_parsing_context); TALER_MHD_parse_post_cleanup_callback (rc->opaque_post_parsing_context);
/* Sanity-check that we didn't leave any transactions hanging */ /* Sanity-check that we didn't leave any transactions hanging */
/* NOTE: In high-performance production, we could consider /* NOTE: In high-performance production, we could consider
removing this as it should not be needed and might be costly removing this as it should not be needed and might be costly
(to be benchmarked). */ (to be benchmarked). */
TEH_plugin->preflight (TEH_plugin->cls, TEH_plugin->preflight (TEH_plugin->cls,
TEH_plugin->get_session (TEH_plugin->cls)); TEH_plugin->get_session (TEH_plugin->cls));
GNUNET_free (ecls); GNUNET_free (rc);
*con_cls = NULL; *con_cls = NULL;
GNUNET_async_scope_restore (&old_scope); GNUNET_async_scope_restore (&old_scope);
} }
/** /**
* We found @a rh responsible for handling a request. Parse the * We found a request handler responsible for handling a request. Parse the
* @a upload_data (if applicable) and the @a url and call the * @a upload_data (if applicable) and the @a url and call the
* handler. * handler.
* *
* @param rh request handler to call * @param rc request context
* @param connection connection being handled
* @param url rest of the URL to parse * @param url rest of the URL to parse
* @param inner_cls closure for the handler, if needed
* @param upload_data upload data to parse (if available) * @param upload_data upload data to parse (if available)
* @param[in,out] upload_data_size number of bytes in @a upload_data * @param[in,out] upload_data_size number of bytes in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
static MHD_RESULT static MHD_RESULT
proceed_with_handler (const struct TEH_RequestHandler *rh, proceed_with_handler (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *url, const char *url,
void **inner_cls,
const char *upload_data, const char *upload_data,
size_t *upload_data_size) size_t *upload_data_size)
{ {
const struct TEH_RequestHandler *rh = rc->rh;
const char *args[rh->nargs + 1]; const char *args[rh->nargs + 1];
size_t ulen = strlen (url) + 1; size_t ulen = strlen (url) + 1;
json_t *root = NULL; json_t *root = NULL;
@ -376,7 +346,7 @@ proceed_with_handler (const struct TEH_RequestHandler *rh,
/deposits/). The value should be adjusted if we ever define protocol /deposits/). The value should be adjusted if we ever define protocol
endpoints with plausibly longer inputs. */ endpoints with plausibly longer inputs. */
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_URI_TOO_LONG, MHD_HTTP_URI_TOO_LONG,
TALER_EC_GENERIC_URI_TOO_LONG, TALER_EC_GENERIC_URI_TOO_LONG,
url); url);
@ -389,8 +359,8 @@ proceed_with_handler (const struct TEH_RequestHandler *rh,
{ {
enum GNUNET_GenericReturnValue res; enum GNUNET_GenericReturnValue res;
res = TALER_MHD_parse_post_json (connection, res = TALER_MHD_parse_post_json (rc->connection,
inner_cls, &rc->opaque_post_parsing_context,
upload_data, upload_data,
upload_data_size, upload_data_size,
&root); &root);
@ -447,7 +417,7 @@ proceed_with_handler (const struct TEH_RequestHandler *rh,
url); url);
GNUNET_break_op (0); GNUNET_break_op (0);
json_decref (root); json_decref (root);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_NOT_FOUND, MHD_HTTP_NOT_FOUND,
TALER_EC_EXCHANGE_GENERIC_WRONG_NUMBER_OF_SEGMENTS, TALER_EC_EXCHANGE_GENERIC_WRONG_NUMBER_OF_SEGMENTS,
emsg); emsg);
@ -458,18 +428,15 @@ proceed_with_handler (const struct TEH_RequestHandler *rh,
args[i] = NULL; args[i] = NULL;
} }
/* Above logic ensures that 'root' is exactly non-NULL for POST operations, /* Above logic ensures that 'root' is exactly non-NULL for POST operations,
so we test for 'root' to decide which handler to invoke. */ so we test for 'root' to decide which handler to invoke. */
if (NULL != root) if (NULL != root)
ret = rh->handler.post (rh, ret = rh->handler.post (rc,
connection,
root, root,
args); args);
else /* We also only have "POST" or "GET" in the API for at this point else /* We also only have "POST" or "GET" in the API for at this point
(OPTIONS/HEAD are taken care of earlier) */ (OPTIONS/HEAD are taken care of earlier) */
ret = rh->handler.get (rh, ret = rh->handler.get (rc,
connection,
args); args);
} }
json_decref (root); json_decref (root);
@ -480,14 +447,13 @@ proceed_with_handler (const struct TEH_RequestHandler *rh,
/** /**
* Handle a "/seed" request. * Handle a "/seed" request.
* *
* @param rh context of the handler * @param rc request context
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param args array of additional options (must be empty for this function) * @param args array of additional options (must be empty for this function)
* @return MHD result code * @return MHD result code
*/ */
static MHD_RESULT static MHD_RESULT
handler_seed (const struct TEH_RequestHandler *rh, handler_seed (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[]) const char *const args[])
{ {
#define SEED_SIZE 32 #define SEED_SIZE 32
@ -495,7 +461,6 @@ handler_seed (const struct TEH_RequestHandler *rh,
MHD_RESULT ret; MHD_RESULT ret;
struct MHD_Response *resp; struct MHD_Response *resp;
(void) rh;
body = malloc (SEED_SIZE); /* must use malloc(), because MHD will use free() */ body = malloc (SEED_SIZE); /* must use malloc(), because MHD will use free() */
if (NULL == body) if (NULL == body)
return MHD_NO; return MHD_NO;
@ -506,7 +471,7 @@ handler_seed (const struct TEH_RequestHandler *rh,
body, body,
MHD_RESPMEM_MUST_FREE); MHD_RESPMEM_MUST_FREE);
TALER_MHD_add_global_headers (resp); TALER_MHD_add_global_headers (resp);
ret = MHD_queue_response (connection, ret = MHD_queue_response (rc->connection,
MHD_HTTP_OK, MHD_HTTP_OK,
resp); resp);
GNUNET_break (MHD_YES == ret); GNUNET_break (MHD_YES == ret);
@ -519,22 +484,21 @@ handler_seed (const struct TEH_RequestHandler *rh,
/** /**
* Handle POST "/management/..." requests. * Handle POST "/management/..." requests.
* *
* @param rh context of the handler * @param rc request context
* @param connection the MHD connection to handle
* @param root uploaded JSON data * @param root uploaded JSON data
* @param args array of additional options * @param args array of additional options
* @return MHD result code * @return MHD result code
*/ */
static MHD_RESULT static MHD_RESULT
handle_post_management (const struct TEH_RequestHandler *rh, handle_post_management (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const json_t *root, const json_t *root,
const char *const args[]) const char *const args[])
{ {
if (NULL == args[0]) if (NULL == args[0])
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return r404 (connection, "/management"); return r404 (rc->connection,
"/management");
} }
if (0 == strcmp (args[0], if (0 == strcmp (args[0],
"auditors")) "auditors"))
@ -542,14 +506,14 @@ handle_post_management (const struct TEH_RequestHandler *rh,
struct TALER_AuditorPublicKeyP auditor_pub; struct TALER_AuditorPublicKeyP auditor_pub;
if (NULL == args[1]) if (NULL == args[1])
return TEH_handler_management_auditors (connection, return TEH_handler_management_auditors (rc->connection,
root); root);
if ( (NULL == args[1]) || if ( (NULL == args[1]) ||
(NULL == args[2]) || (NULL == args[2]) ||
(0 != strcmp (args[2], (0 != strcmp (args[2],
"disable")) || "disable")) ||
(NULL != args[3]) ) (NULL != args[3]) )
return r404 (connection, return r404 (rc->connection,
"/management/auditors/$AUDITOR_PUB/disable"); "/management/auditors/$AUDITOR_PUB/disable");
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_STRINGS_string_to_data (args[1], GNUNET_STRINGS_string_to_data (args[1],
@ -558,12 +522,12 @@ handle_post_management (const struct TEH_RequestHandler *rh,
sizeof (auditor_pub))) sizeof (auditor_pub)))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED, TALER_EC_GENERIC_PARAMETER_MALFORMED,
args[1]); args[1]);
} }
return TEH_handler_management_auditors_AP_disable (connection, return TEH_handler_management_auditors_AP_disable (rc->connection,
&auditor_pub, &auditor_pub,
root); root);
} }
@ -578,7 +542,7 @@ handle_post_management (const struct TEH_RequestHandler *rh,
(0 != strcmp (args[2], (0 != strcmp (args[2],
"revoke")) || "revoke")) ||
(NULL != args[3]) ) (NULL != args[3]) )
return r404 (connection, return r404 (rc->connection,
"/management/denominations/$HDP/revoke"); "/management/denominations/$HDP/revoke");
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_STRINGS_string_to_data (args[1], GNUNET_STRINGS_string_to_data (args[1],
@ -587,12 +551,12 @@ handle_post_management (const struct TEH_RequestHandler *rh,
sizeof (h_denom_pub))) sizeof (h_denom_pub)))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED, TALER_EC_GENERIC_PARAMETER_MALFORMED,
args[1]); args[1]);
} }
return TEH_handler_management_denominations_HDP_revoke (connection, return TEH_handler_management_denominations_HDP_revoke (rc->connection,
&h_denom_pub, &h_denom_pub,
root); root);
} }
@ -607,7 +571,7 @@ handle_post_management (const struct TEH_RequestHandler *rh,
(0 != strcmp (args[2], (0 != strcmp (args[2],
"revoke")) || "revoke")) ||
(NULL != args[3]) ) (NULL != args[3]) )
return r404 (connection, return r404 (rc->connection,
"/management/signkeys/$HDP/revoke"); "/management/signkeys/$HDP/revoke");
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_STRINGS_string_to_data (args[1], GNUNET_STRINGS_string_to_data (args[1],
@ -616,12 +580,12 @@ handle_post_management (const struct TEH_RequestHandler *rh,
sizeof (exchange_pub))) sizeof (exchange_pub)))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED, TALER_EC_GENERIC_PARAMETER_MALFORMED,
args[1]); args[1]);
} }
return TEH_handler_management_signkeys_EP_revoke (connection, return TEH_handler_management_signkeys_EP_revoke (rc->connection,
&exchange_pub, &exchange_pub,
root); root);
} }
@ -631,25 +595,27 @@ handle_post_management (const struct TEH_RequestHandler *rh,
if (NULL != args[1]) if (NULL != args[1])
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return r404 (connection, "/management/keys/*"); return r404 (rc->connection,
"/management/keys/*");
} }
return TEH_handler_management_post_keys (connection, return TEH_handler_management_post_keys (rc->connection,
root); root);
} }
if (0 == strcmp (args[0], if (0 == strcmp (args[0],
"wire")) "wire"))
{ {
if (NULL == args[1]) if (NULL == args[1])
return TEH_handler_management_post_wire (connection, return TEH_handler_management_post_wire (rc->connection,
root); root);
if ( (0 != strcmp (args[1], if ( (0 != strcmp (args[1],
"disable")) || "disable")) ||
(NULL != args[2]) ) (NULL != args[2]) )
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return r404 (connection, "/management/wire/disable"); return r404 (rc->connection,
"/management/wire/disable");
} }
return TEH_handler_management_post_wire_disable (connection, return TEH_handler_management_post_wire_disable (rc->connection,
root); root);
} }
if (0 == strcmp (args[0], if (0 == strcmp (args[0],
@ -658,27 +624,28 @@ handle_post_management (const struct TEH_RequestHandler *rh,
if (NULL != args[1]) if (NULL != args[1])
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return r404 (connection, "/management/wire-fee/*"); return r404 (rc->connection,
"/management/wire-fee/*");
} }
return TEH_handler_management_post_wire_fees (connection, return TEH_handler_management_post_wire_fees (rc->connection,
root); root);
} }
GNUNET_break_op (0); GNUNET_break_op (0);
return r404 (connection, "/management/*"); return r404 (rc->connection,
"/management/*");
} }
/** /**
* Handle a get "/management" request. * Handle a get "/management" request.
* *
* @param rh context of the handler * @param rc request context
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param args array of additional options (must be empty for this function) * @param args array of additional options (must be empty for this function)
* @return MHD result code * @return MHD result code
*/ */
static MHD_RESULT static MHD_RESULT
handle_get_management (const struct TEH_RequestHandler *rh, handle_get_management (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[1]) const char *const args[1])
{ {
if ( (NULL != args[0]) && if ( (NULL != args[0]) &&
@ -686,26 +653,25 @@ handle_get_management (const struct TEH_RequestHandler *rh,
"keys")) && "keys")) &&
(NULL == args[1]) ) (NULL == args[1]) )
{ {
return TEH_keys_management_get_keys_handler (rh, return TEH_keys_management_get_keys_handler (rc->rh,
connection); rc->connection);
} }
GNUNET_break_op (0); GNUNET_break_op (0);
return r404 (connection, "/management/*"); return r404 (rc->connection,
"/management/*");
} }
/** /**
* Handle POST "/auditors/..." requests. * Handle POST "/auditors/..." requests.
* *
* @param rh context of the handler * @param rc request context
* @param connection the MHD connection to handle
* @param root uploaded JSON data * @param root uploaded JSON data
* @param args array of additional options * @param args array of additional options
* @return MHD result code * @return MHD result code
*/ */
static MHD_RESULT static MHD_RESULT
handle_post_auditors (const struct TEH_RequestHandler *rh, handle_post_auditors (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const json_t *root, const json_t *root,
const char *const args[]) const char *const args[])
{ {
@ -717,7 +683,8 @@ handle_post_auditors (const struct TEH_RequestHandler *rh,
(NULL != args[2]) ) (NULL != args[2]) )
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return r404 (connection, "/auditors/$AUDITOR_PUB/$H_DENOM_PUB"); return r404 (rc->connection,
"/auditors/$AUDITOR_PUB/$H_DENOM_PUB");
} }
if (GNUNET_OK != if (GNUNET_OK !=
@ -727,7 +694,7 @@ handle_post_auditors (const struct TEH_RequestHandler *rh,
sizeof (auditor_pub))) sizeof (auditor_pub)))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED, TALER_EC_GENERIC_PARAMETER_MALFORMED,
args[0]); args[0]);
@ -739,12 +706,12 @@ handle_post_auditors (const struct TEH_RequestHandler *rh,
sizeof (h_denom_pub))) sizeof (h_denom_pub)))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED, TALER_EC_GENERIC_PARAMETER_MALFORMED,
args[1]); args[1]);
} }
return TEH_handler_auditors (connection, return TEH_handler_auditors (rc->connection,
&auditor_pub, &auditor_pub,
&h_denom_pub, &h_denom_pub,
root); root);
@ -761,7 +728,7 @@ handle_post_auditors (const struct TEH_RequestHandler *rh,
* @param version HTTP version (ignored) * @param version HTTP version (ignored)
* @param upload_data request data * @param upload_data request data
* @param upload_data_size size of @a upload_data in bytes * @param upload_data_size size of @a upload_data in bytes
* @param con_cls closure for request (a `struct Buffer *`) * @param con_cls closure for request (a `struct TEH_RequestContext *`)
* @return MHD result code * @return MHD result code
*/ */
static MHD_RESULT static MHD_RESULT
@ -907,14 +874,13 @@ handle_mhd_request (void *cls,
.url = NULL .url = NULL
} }
}; };
struct ExchangeHttpRequestClosure *ecls = *con_cls; struct TEH_RequestContext *rc = *con_cls;
void **inner_cls;
struct GNUNET_AsyncScopeSave old_scope; struct GNUNET_AsyncScopeSave old_scope;
const char *correlation_id = NULL; const char *correlation_id = NULL;
(void) cls; (void) cls;
(void) version; (void) version;
if (NULL == ecls) if (NULL == rc)
{ {
unsigned long long cnt; unsigned long long cnt;
@ -933,15 +899,17 @@ handle_mhd_request (void *cls,
} }
/* We're in a new async scope! */ /* We're in a new async scope! */
ecls = *con_cls = GNUNET_new (struct ExchangeHttpRequestClosure); rc = *con_cls = GNUNET_new (struct TEH_RequestContext);
GNUNET_async_scope_fresh (&ecls->async_scope_id); GNUNET_async_scope_fresh (&rc->async_scope_id);
ecls->url = url; rc->url = url;
rc->connection = connection;
/* We only read the correlation ID on the first callback for every client */ /* We only read the correlation ID on the first callback for every client */
correlation_id = MHD_lookup_connection_value (connection, correlation_id = MHD_lookup_connection_value (connection,
MHD_HEADER_KIND, MHD_HEADER_KIND,
"Taler-Correlation-Id"); "Taler-Correlation-Id");
if ((NULL != correlation_id) && if ( (NULL != correlation_id) &&
(GNUNET_YES != GNUNET_CURL_is_valid_scope_id (correlation_id))) (GNUNET_YES !=
GNUNET_CURL_is_valid_scope_id (correlation_id)) )
{ {
GNUNET_log (GNUNET_ERROR_TYPE_WARNING, GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
"illegal incoming correlation ID\n"); "illegal incoming correlation ID\n");
@ -949,8 +917,7 @@ handle_mhd_request (void *cls,
} }
} }
inner_cls = &ecls->opaque_post_parsing_context; GNUNET_async_scope_enter (&rc->async_scope_id,
GNUNET_async_scope_enter (&ecls->async_scope_id,
&old_scope); &old_scope);
if (NULL != correlation_id) if (NULL != correlation_id)
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@ -964,7 +931,7 @@ handle_mhd_request (void *cls,
method, method,
url); url);
/* on repeated requests, check our cache first */ /* on repeated requests, check our cache first */
if (NULL != ecls->rh) if (NULL != rc->rh)
{ {
MHD_RESULT ret; MHD_RESULT ret;
const char *start; const char *start;
@ -975,10 +942,8 @@ handle_mhd_request (void *cls,
start = strchr (url + 1, '/'); start = strchr (url + 1, '/');
if (NULL == start) if (NULL == start)
start = ""; start = "";
ret = proceed_with_handler (ecls->rh, ret = proceed_with_handler (rc,
connection,
start, start,
inner_cls,
upload_data, upload_data,
upload_data_size); upload_data_size);
GNUNET_async_scope_restore (&old_scope); GNUNET_async_scope_restore (&old_scope);
@ -1039,12 +1004,10 @@ handle_mhd_request (void *cls,
MHD_RESULT ret; MHD_RESULT ret;
/* cache to avoid the loop next time */ /* cache to avoid the loop next time */
ecls->rh = rh; rc->rh = rh;
/* run handler */ /* run handler */
ret = proceed_with_handler (rh, ret = proceed_with_handler (rc,
connection,
url + tok_size + 1, url + tok_size + 1,
inner_cls,
upload_data, upload_data,
upload_data_size); upload_data_size);
GNUNET_async_scope_restore (&old_scope); GNUNET_async_scope_restore (&old_scope);

View File

@ -83,6 +83,62 @@ extern char *TEH_currency;
*/ */
extern volatile bool MHD_terminating; extern volatile bool MHD_terminating;
/**
* @brief Struct describing an URL and the handler for it.
*/
struct TEH_RequestHandler;
/**
* @brief Context in which the exchange is processing
* all requests
*/
struct TEH_RequestContext
{
/**
* Async Scope ID associated with this request.
*/
struct GNUNET_AsyncScopeId async_scope_id;
/**
* Opaque parsing context.
*/
void *opaque_post_parsing_context;
/**
* Request handler responsible for this request.
*/
const struct TEH_RequestHandler *rh;
/**
* Request URL (for logging).
*/
const char *url;
/**
* Connection we are processing.
*/
struct MHD_Connection *connection;
/**
* @e rh-specific cleanup routine. Function called
* upon completion of the request that should
* clean up @a rh_ctx. Can be NULL.
*/
void
(*rh_cleaner)(struct TEH_RequestContext *rc);
/**
* @e rh-specific context. Place where the request
* handler can associate state with this request.
* Can be NULL.
*/
void *rh_ctx;
};
/** /**
* @brief Struct describing an URL and the handler for it. * @brief Struct describing an URL and the handler for it.
*/ */
@ -109,31 +165,28 @@ struct TEH_RequestHandler
* Function to call to handle a GET requests (and those * Function to call to handle a GET requests (and those
* with @e method NULL). * with @e method NULL).
* *
* @param rh this struct * @param rc context for the request
* @param mime_type the @e mime_type for the reply (hint, can be NULL) * @param mime_type the @e mime_type for the reply (hint, can be NULL)
* @param connection the MHD connection to handle
* @param args array of arguments, needs to be of length @e args_expected * @param args array of arguments, needs to be of length @e args_expected
* @return MHD result code * @return MHD result code
*/ */
MHD_RESULT (*get)(const struct TEH_RequestHandler *rh, MHD_RESULT
struct MHD_Connection *connection, (*get)(struct TEH_RequestContext *rc,
const char *const args[]); const char *const args[]);
/** /**
* Function to call to handle a POST request. * Function to call to handle a POST request.
* *
* @param rh this struct * @param rc context for the request
* @param mime_type the @e mime_type for the reply (hint, can be NULL)
* @param connection the MHD connection to handle
* @param json uploaded JSON data * @param json uploaded JSON data
* @param args array of arguments, needs to be of length @e args_expected * @param args array of arguments, needs to be of length @e args_expected
* @return MHD result code * @return MHD result code
*/ */
MHD_RESULT (*post)(const struct TEH_RequestHandler *rh, MHD_RESULT
struct MHD_Connection *connection, (*post)(struct TEH_RequestContext *rc,
const json_t *root, const json_t *root,
const char *const args[]); const char *const args[]);
} handler; } handler;

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014-2017 Taler Systems SA Copyright (C) 2014-2017, 2021 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software terms of the GNU Affero General Public License as published by the Free Software
@ -298,19 +298,8 @@ handle_track_transaction_request (
} }
/**
* Handle a "/deposits/$H_WIRE/$MERCHANT_PUB/$H_CONTRACT_TERMS/$COIN_PUB"
* request.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
* @param args array of additional options (length: 4, contains:
* h_wire, merchant_pub, h_contract_terms and coin_pub)
* @return MHD result code
*/
MHD_RESULT MHD_RESULT
TEH_handler_deposits_get (const struct TEH_RequestHandler *rh, TEH_handler_deposits_get (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[4]) const char *const args[4])
{ {
enum GNUNET_GenericReturnValue res; enum GNUNET_GenericReturnValue res;
@ -320,7 +309,6 @@ TEH_handler_deposits_get (const struct TEH_RequestHandler *rh,
.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION) .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION)
}; };
(void) rh;
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_STRINGS_string_to_data (args[0], GNUNET_STRINGS_string_to_data (args[0],
strlen (args[0]), strlen (args[0]),
@ -328,7 +316,7 @@ TEH_handler_deposits_get (const struct TEH_RequestHandler *rh,
sizeof (tps.h_wire))) sizeof (tps.h_wire)))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_H_WIRE, TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_H_WIRE,
args[0]); args[0]);
@ -340,7 +328,7 @@ TEH_handler_deposits_get (const struct TEH_RequestHandler *rh,
sizeof (tps.merchant))) sizeof (tps.merchant)))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_MERCHANT_PUB, TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_MERCHANT_PUB,
args[1]); args[1]);
@ -352,7 +340,7 @@ TEH_handler_deposits_get (const struct TEH_RequestHandler *rh,
sizeof (tps.h_contract_terms))) sizeof (tps.h_contract_terms)))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_H_CONTRACT_TERMS, TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_H_CONTRACT_TERMS,
args[2]); args[2]);
@ -364,12 +352,12 @@ TEH_handler_deposits_get (const struct TEH_RequestHandler *rh,
sizeof (tps.coin_pub))) sizeof (tps.coin_pub)))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_COIN_PUB, TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_COIN_PUB,
args[3]); args[3]);
} }
res = TALER_MHD_parse_request_arg_data (connection, res = TALER_MHD_parse_request_arg_data (rc->connection,
"merchant_sig", "merchant_sig",
&merchant_sig, &merchant_sig,
sizeof (merchant_sig)); sizeof (merchant_sig));
@ -384,13 +372,13 @@ TEH_handler_deposits_get (const struct TEH_RequestHandler *rh,
&tps.merchant.eddsa_pub)) &tps.merchant.eddsa_pub))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_FORBIDDEN, MHD_HTTP_FORBIDDEN,
TALER_EC_EXCHANGE_DEPOSITS_GET_MERCHANT_SIGNATURE_INVALID, TALER_EC_EXCHANGE_DEPOSITS_GET_MERCHANT_SIGNATURE_INVALID,
NULL); NULL);
} }
return handle_track_transaction_request (connection, return handle_track_transaction_request (rc->connection,
&tps, &tps,
&tps.merchant); &tps.merchant);
} }

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014-2017 Taler Systems SA Copyright (C) 2014-2017, 2021 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software terms of the GNU Affero General Public License as published by the Free Software
@ -30,15 +30,13 @@
* Handle a "/deposits/$H_WIRE/$MERCHANT_PUB/$H_CONTRACT_TERMS/$COIN_PUB" * Handle a "/deposits/$H_WIRE/$MERCHANT_PUB/$H_CONTRACT_TERMS/$COIN_PUB"
* request. * request.
* *
* @param rh context of the handler * @param rc request context
* @param connection the MHD connection to handle
* @param args array of additional options (length: 4, contains: * @param args array of additional options (length: 4, contains:
* h_wire, merchant_pub, h_contract_terms and coin_pub) * h_wire, merchant_pub, h_contract_terms and coin_pub)
* @return MHD result code * @return MHD result code
*/ */
MHD_RESULT MHD_RESULT
TEH_handler_deposits_get (const struct TEH_RequestHandler *rh, TEH_handler_deposits_get (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[4]); const char *const args[4]);

View File

@ -2053,18 +2053,16 @@ krd_search_comparator (const void *key,
MHD_RESULT MHD_RESULT
TEH_keys_get_handler (const struct TEH_RequestHandler *rh, TEH_keys_get_handler (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[]) const char *const args[])
{ {
struct GNUNET_TIME_Absolute last_issue_date; struct GNUNET_TIME_Absolute last_issue_date;
(void) rh;
(void) args; (void) args;
{ {
const char *have_cherrypick; const char *have_cherrypick;
have_cherrypick = MHD_lookup_connection_value (connection, have_cherrypick = MHD_lookup_connection_value (rc->connection,
MHD_GET_ARGUMENT_KIND, MHD_GET_ARGUMENT_KIND,
"last_issue_date"); "last_issue_date");
if (NULL != have_cherrypick) if (NULL != have_cherrypick)
@ -2077,7 +2075,7 @@ TEH_keys_get_handler (const struct TEH_RequestHandler *rh,
&cherrypickn)) &cherrypickn))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED, TALER_EC_GENERIC_PARAMETER_MALFORMED,
have_cherrypick); have_cherrypick);
@ -2103,16 +2101,16 @@ TEH_keys_get_handler (const struct TEH_RequestHandler *rh,
{ {
GNUNET_assert (0 == pthread_mutex_lock (&skr_mutex)); GNUNET_assert (0 == pthread_mutex_lock (&skr_mutex));
if ( (SKR_LIMIT == skr_size) && if ( (SKR_LIMIT == skr_size) &&
(connection == skr_connection) ) (rc->connection == skr_connection) )
{ {
GNUNET_assert (0 == pthread_mutex_unlock (&skr_mutex)); GNUNET_assert (0 == pthread_mutex_unlock (&skr_mutex));
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_INTERNAL_SERVER_ERROR, MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING, TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
"too many connections suspended on /keys"); "too many connections suspended on /keys");
} }
GNUNET_assert (0 == pthread_mutex_unlock (&skr_mutex)); GNUNET_assert (0 == pthread_mutex_unlock (&skr_mutex));
return suspend_request (connection); return suspend_request (rc->connection);
} }
krd = bsearch (&last_issue_date, krd = bsearch (&last_issue_date,
ksh->krd_array, ksh->krd_array,
@ -2140,14 +2138,15 @@ TEH_keys_get_handler (const struct TEH_RequestHandler *rh,
NOT_FOUND situation. But, OTOH, for 'sane' clients it is more likely NOT_FOUND situation. But, OTOH, for 'sane' clients it is more likely
to be our fault, so let's speculatively assume we are to blame ;-) */// to be our fault, so let's speculatively assume we are to blame ;-) *///
GNUNET_break (0); GNUNET_break (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_INTERNAL_SERVER_ERROR, MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING, TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
"no key data for given timestamp"); "no key data for given timestamp");
} }
return MHD_queue_response (connection, return MHD_queue_response (rc->connection,
MHD_HTTP_OK, MHD_HTTP_OK,
(MHD_YES == TALER_MHD_can_compress (connection)) (MHD_YES ==
TALER_MHD_can_compress (rc->connection))
? krd->response_compressed ? krd->response_compressed
: krd->response_uncompressed); : krd->response_uncompressed);
} }

View File

@ -324,14 +324,12 @@ TEH_keys_exchange_revoke (const struct TALER_ExchangePublicKeyP *exchange_pub);
* Function to call to handle requests to "/keys" by sending * Function to call to handle requests to "/keys" by sending
* back our current key material. * back our current key material.
* *
* @param rh context of the handler * @param rc request context
* @param connection the MHD connection to handle
* @param args array of additional options (must be empty for this function) * @param args array of additional options (must be empty for this function)
* @return MHD result code * @return MHD result code
*/ */
MHD_RESULT MHD_RESULT
TEH_keys_get_handler (const struct TEH_RequestHandler *rh, TEH_keys_get_handler (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[]); const char *const args[]);

View File

@ -169,23 +169,13 @@ link_transaction (void *cls,
} }
/**
* Handle a "/coins/$COIN_PUB/link" request.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
* @param args array of additional options (length: 2, first is the coin_pub, second must be "link")
* @return MHD result code
*/
MHD_RESULT MHD_RESULT
TEH_handler_link (const struct TEH_RequestHandler *rh, TEH_handler_link (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[2]) const char *const args[2])
{ {
struct HTD_Context ctx; struct HTD_Context ctx;
MHD_RESULT mhd_ret; MHD_RESULT mhd_ret;
(void) rh;
memset (&ctx, memset (&ctx,
0, 0,
sizeof (ctx)); sizeof (ctx));
@ -196,22 +186,15 @@ TEH_handler_link (const struct TEH_RequestHandler *rh,
sizeof (ctx.coin_pub))) sizeof (ctx.coin_pub)))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_GENERIC_COINS_INVALID_COIN_PUB, TALER_EC_EXCHANGE_GENERIC_COINS_INVALID_COIN_PUB,
args[0]); args[0]);
} }
ctx.mlist = json_array (); ctx.mlist = json_array ();
if (NULL == ctx.mlist) GNUNET_assert (NULL != ctx.mlist);
{
GNUNET_break (0);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_GENERIC_JSON_ALLOCATION_FAILURE,
"json_array() call failed");
}
if (GNUNET_OK != if (GNUNET_OK !=
TEH_DB_run_transaction (connection, TEH_DB_run_transaction (rc->connection,
"run link", "run link",
&mhd_ret, &mhd_ret,
&link_transaction, &link_transaction,
@ -221,7 +204,7 @@ TEH_handler_link (const struct TEH_RequestHandler *rh,
json_decref (ctx.mlist); json_decref (ctx.mlist);
return mhd_ret; return mhd_ret;
} }
mhd_ret = TALER_MHD_reply_json (connection, mhd_ret = TALER_MHD_reply_json (rc->connection,
ctx.mlist, ctx.mlist,
MHD_HTTP_OK); MHD_HTTP_OK);
json_decref (ctx.mlist); json_decref (ctx.mlist);

View File

@ -31,14 +31,12 @@
/** /**
* Handle a "/coins/$COIN_PUB/link" request. * Handle a "/coins/$COIN_PUB/link" request.
* *
* @param rh context of the handler * @param rc request context
* @param connection the MHD connection to handle
* @param args array of additional options (length: 2, first is the coin_pub, second must be "link") * @param args array of additional options (length: 2, first is the coin_pub, second must be "link")
* @return MHD result code * @return MHD result code
*/ */
MHD_RESULT MHD_RESULT
TEH_handler_link (const struct TEH_RequestHandler *rh, TEH_handler_link (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[2]); const char *const args[2]);

View File

@ -34,27 +34,18 @@
#include "taler-exchange-httpd_mhd.h" #include "taler-exchange-httpd_mhd.h"
/**
* Function to call to handle the request by sending
* back static data from the @a rh.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
* @param args array of additional options (must be empty for this function)
* @return MHD result code
*/
MHD_RESULT MHD_RESULT
TEH_handler_static_response (const struct TEH_RequestHandler *rh, TEH_handler_static_response (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[]) const char *const args[])
{ {
const struct TEH_RequestHandler *rh = rc->rh;
size_t dlen; size_t dlen;
(void) args; (void) args;
dlen = (0 == rh->data_size) dlen = (0 == rh->data_size)
? strlen ((const char *) rh->data) ? strlen ((const char *) rh->data)
: rh->data_size; : rh->data_size;
return TALER_MHD_reply_static (connection, return TALER_MHD_reply_static (rc->connection,
rh->response_code, rh->response_code,
rh->mime_type, rh->mime_type,
rh->data, rh->data,
@ -62,24 +53,13 @@ TEH_handler_static_response (const struct TEH_RequestHandler *rh,
} }
/**
* Function to call to handle the request by sending
* back a redirect to the AGPL source code.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
* @param args array of additional options (must be empty for this function)
* @return MHD result code
*/
MHD_RESULT MHD_RESULT
TEH_handler_agpl_redirect (const struct TEH_RequestHandler *rh, TEH_handler_agpl_redirect (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[]) const char *const args[])
{ {
(void) rh;
(void) args; (void) args;
return TALER_MHD_reply_agpl (connection, return TALER_MHD_reply_agpl (rc->connection,
"http://www.git.taler.net/?p=exchange.git"); "https://git.taler.net/?p=exchange.git");
} }

View File

@ -30,16 +30,14 @@
/** /**
* Function to call to handle the request by sending * Function to call to handle the request by sending
* back static data from the @a rh. * back static data from the request handler.
* *
* @param rh context of the handler * @param rc request context
* @param connection the MHD connection to handle
* @param args array of additional options (must be empty for this function) * @param args array of additional options (must be empty for this function)
* @return MHD result code * @return MHD result code
*/ */
MHD_RESULT MHD_RESULT
TEH_handler_static_response (const struct TEH_RequestHandler *rh, TEH_handler_static_response (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[]); const char *const args[]);
@ -47,14 +45,12 @@ TEH_handler_static_response (const struct TEH_RequestHandler *rh,
* Function to call to handle the request by sending * Function to call to handle the request by sending
* back a redirect to the AGPL source code. * back a redirect to the AGPL source code.
* *
* @param rh context of the handler * @param rc request context
* @param connection the MHD connection to handle
* @param args array of additional options (must be empty for this function) * @param args array of additional options (must be empty for this function)
* @return MHD result code * @return MHD result code
*/ */
MHD_RESULT MHD_RESULT
TEH_handler_agpl_redirect (const struct TEH_RequestHandler *rh, TEH_handler_agpl_redirect (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[]); const char *const args[]);

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014-2019 Taler Systems SA Copyright (C) 2014-2019, 2021 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software terms of the GNU Affero General Public License as published by the Free Software
@ -805,7 +805,7 @@ cleanup:
* @param coin_evs envelopes of gamma-selected coins to be signed * @param coin_evs envelopes of gamma-selected coins to be signed
* @return MHD result code * @return MHD result code
*/ */
static int static MHD_RESULT
handle_refreshes_reveal_json (struct MHD_Connection *connection, handle_refreshes_reveal_json (struct MHD_Connection *connection,
struct RevealContext *rctx, struct RevealContext *rctx,
const json_t *tp_json, const json_t *tp_json,
@ -853,7 +853,7 @@ handle_refreshes_reveal_json (struct MHD_Connection *connection,
GNUNET_JSON_spec_fixed_auto (NULL, &rctx->transfer_privs[i]), GNUNET_JSON_spec_fixed_auto (NULL, &rctx->transfer_privs[i]),
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
int res; enum GNUNET_GenericReturnValue res;
res = TALER_MHD_parse_json_array (connection, res = TALER_MHD_parse_json_array (connection,
tp_json, tp_json,
@ -872,24 +872,8 @@ handle_refreshes_reveal_json (struct MHD_Connection *connection,
} }
/**
* Handle a "/refreshes/$RCH/reveal" request. This time, the client reveals the
* private transfer keys except for the cut-and-choose value returned from
* "/coins/$COIN_PUB/melt". This function parses the revealed keys and secrets and
* ultimately passes everything to resolve_refreshes_reveal_denominations()
* which will verify that the revealed information is valid then runs the
* transaction in refreshes_reveal_transaction() and finally returns the signed
* refreshed coins.
*
* @param rh context of the handler
* @param connection MHD request handle
* @param root uploaded JSON data
* @param args array of additional options (length: 2, session hash and the string "reveal")
* @return MHD result code
*/
MHD_RESULT MHD_RESULT
TEH_handler_reveal (const struct TEH_RequestHandler *rh, TEH_handler_reveal (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const json_t *root, const json_t *root,
const char *const args[2]) const char *const args[2])
{ {
@ -907,7 +891,6 @@ TEH_handler_reveal (const struct TEH_RequestHandler *rh,
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
(void) rh;
memset (&rctx, memset (&rctx,
0, 0,
sizeof (rctx)); sizeof (rctx));
@ -918,7 +901,7 @@ TEH_handler_reveal (const struct TEH_RequestHandler *rh,
sizeof (rctx.rc))) sizeof (rctx.rc)))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_REFRESHES_REVEAL_INVALID_RCH, TALER_EC_EXCHANGE_REFRESHES_REVEAL_INVALID_RCH,
args[0]); args[0]);
@ -927,16 +910,16 @@ TEH_handler_reveal (const struct TEH_RequestHandler *rh,
"reveal")) "reveal"))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_REFRESHES_REVEAL_OPERATION_INVALID, TALER_EC_EXCHANGE_REFRESHES_REVEAL_OPERATION_INVALID,
args[1]); args[1]);
} }
{ {
int res; enum GNUNET_GenericReturnValue res;
res = TALER_MHD_parse_json_data (connection, res = TALER_MHD_parse_json_data (rc->connection,
root, root,
spec); spec);
if (GNUNET_OK != res) if (GNUNET_OK != res)
@ -952,16 +935,16 @@ TEH_handler_reveal (const struct TEH_RequestHandler *rh,
{ {
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_REFRESHES_REVEAL_CNC_TRANSFER_ARRAY_SIZE_INVALID, TALER_EC_EXCHANGE_REFRESHES_REVEAL_CNC_TRANSFER_ARRAY_SIZE_INVALID,
NULL); NULL);
} }
{ {
int res; MHD_RESULT res;
res = handle_refreshes_reveal_json (connection, res = handle_refreshes_reveal_json (rc->connection,
&rctx, &rctx,
transfer_privs, transfer_privs,
link_sigs, link_sigs,

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014-2017 Taler Systems SA Copyright (C) 2014-2017, 2021 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software terms of the GNU Affero General Public License as published by the Free Software
@ -37,15 +37,13 @@
* transaction in refresh_reveal_transaction() and finally returns the signed * transaction in refresh_reveal_transaction() and finally returns the signed
* refreshed coins. * refreshed coins.
* *
* @param rh context of the handler * @param rc request context
* @param connection MHD request handle
* @param root uploaded JSON data * @param root uploaded JSON data
* @param args array of additional options (length: 2, session hash and the string "reveal") * @param args array of additional options (length: 2, session hash and the string "reveal")
* @return MHD result code * @return MHD result code
*/ */
MHD_RESULT MHD_RESULT
TEH_handler_reveal (const struct TEH_RequestHandler *rh, TEH_handler_reveal (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const json_t *root, const json_t *root,
const char *const args[2]); const char *const args[2]);

View File

@ -29,6 +29,45 @@
#include "taler-exchange-httpd_responses.h" #include "taler-exchange-httpd_responses.h"
/**
* Reserve GET request that is long-polling.
*/
struct ReservePoller
{
/**
* Kept in a DLL.
*/
struct ReservePoller *next;
/**
* Kept in a DLL.
*/
struct ReservePoller *prev;
/**
* Connection we are handling.
*/
struct MHD_Connection *connection;
/**
* Entry in the timeout heap.
*/
struct GNUNET_CONTAINER_HeapNode *hn;
/**
* Subscription for the database event we are
* waiting for.
*/
struct GNUNET_DB_EventHandler *eh;
/**
* When will this request time out?
*/
struct GNUNET_TIME_Absolute timeout;
};
/** /**
* Send reserve history to client. * Send reserve history to client.
* *
@ -112,26 +151,13 @@ reserve_history_transaction (void *cls,
} }
/**
* Handle a GET "/reserves/" request. Parses the
* given "reserve_pub" in @a args (which should contain the
* EdDSA public key of a reserve) and then respond with the
* history of the reserve.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
* @param args array of additional options (length: 1, just the reserve_pub)
* @return MHD result code
*/
MHD_RESULT MHD_RESULT
TEH_handler_reserves_get (const struct TEH_RequestHandler *rh, TEH_handler_reserves_get (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[1]) const char *const args[1])
{ {
struct ReserveHistoryContext rsc; struct ReserveHistoryContext rsc;
MHD_RESULT mhd_ret; MHD_RESULT mhd_ret;
(void) rh;
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_STRINGS_string_to_data (args[0], GNUNET_STRINGS_string_to_data (args[0],
strlen (args[0]), strlen (args[0]),
@ -139,14 +165,14 @@ TEH_handler_reserves_get (const struct TEH_RequestHandler *rh,
sizeof (rsc.reserve_pub))) sizeof (rsc.reserve_pub)))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
TALER_EC_MERCHANT_GENERIC_RESERVE_PUB_MALFORMED, TALER_EC_MERCHANT_GENERIC_RESERVE_PUB_MALFORMED,
args[0]); args[0]);
} }
rsc.rh = NULL; rsc.rh = NULL;
if (GNUNET_OK != if (GNUNET_OK !=
TEH_DB_run_transaction (connection, TEH_DB_run_transaction (rc->connection,
"get reserve history", "get reserve history",
&mhd_ret, &mhd_ret,
&reserve_history_transaction, &reserve_history_transaction,
@ -155,11 +181,11 @@ TEH_handler_reserves_get (const struct TEH_RequestHandler *rh,
/* generate proper response */ /* generate proper response */
if (NULL == rsc.rh) if (NULL == rsc.rh)
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_NOT_FOUND, MHD_HTTP_NOT_FOUND,
TALER_EC_EXCHANGE_RESERVES_GET_STATUS_UNKNOWN, TALER_EC_EXCHANGE_RESERVES_GET_STATUS_UNKNOWN,
args[0]); args[0]);
mhd_ret = reply_reserve_history_success (connection, mhd_ret = reply_reserve_history_success (rc->connection,
rsc.rh); rsc.rh);
TEH_plugin->free_reserve_history (TEH_plugin->cls, TEH_plugin->free_reserve_history (TEH_plugin->cls,
rsc.rh); rsc.rh);

View File

@ -33,14 +33,12 @@
* EdDSA public key of a reserve) and then respond with the * EdDSA public key of a reserve) and then respond with the
* status of the reserve. * status of the reserve.
* *
* @param rh context of the handler * @param rc request context
* @param connection the MHD connection to handle
* @param args array of additional options (length: 1, just the reserve_pub) * @param args array of additional options (length: 1, just the reserve_pub)
* @return MHD result code * @return MHD result code
*/ */
MHD_RESULT MHD_RESULT
TEH_handler_reserves_get (const struct TEH_RequestHandler *rh, TEH_handler_reserves_get (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[1]); const char *const args[1]);
#endif #endif

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2019 Taler Systems SA Copyright (C) 2019, 2021 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software terms of the GNU Affero General Public License as published by the Free Software
@ -38,51 +38,26 @@ static struct TALER_MHD_Legal *tos;
static struct TALER_MHD_Legal *pp; static struct TALER_MHD_Legal *pp;
/**
* Handle a "/terms" request.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
* @param args array of additional options (must be empty for this function)
* @return MHD result code
*/
MHD_RESULT MHD_RESULT
TEH_handler_terms (const struct TEH_RequestHandler *rh, TEH_handler_terms (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[]) const char *const args[])
{ {
(void) rh;
(void) args; (void) args;
return TALER_MHD_reply_legal (connection, return TALER_MHD_reply_legal (rc->connection,
tos); tos);
} }
/**
* Handle a "/privacy" request.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
* @param args array of additional options (must be empty for this function)
* @return MHD result code
*/
MHD_RESULT MHD_RESULT
TEH_handler_privacy (const struct TEH_RequestHandler *rh, TEH_handler_privacy (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[]) const char *const args[])
{ {
(void) rh;
(void) args; (void) args;
return TALER_MHD_reply_legal (connection, return TALER_MHD_reply_legal (rc->connection,
pp); pp);
} }
/**
* Load our terms of service as per configuration.
*
* @param cfg configuration to process
*/
void void
TEH_load_terms (const struct GNUNET_CONFIGURATION_Handle *cfg) TEH_load_terms (const struct GNUNET_CONFIGURATION_Handle *cfg)
{ {

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2019 Taler Systems SA Copyright (C) 2019, 2021 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software terms of the GNU Affero General Public License as published by the Free Software
@ -32,28 +32,24 @@
/** /**
* Handle a "/terms" request. * Handle a "/terms" request.
* *
* @param rh context of the handler * @param rc request context
* @param connection the MHD connection to handle
* @param args array of additional options (must be empty for this function) * @param args array of additional options (must be empty for this function)
* @return MHD result code * @return MHD result code
*/ */
MHD_RESULT MHD_RESULT
TEH_handler_terms (const struct TEH_RequestHandler *rh, TEH_handler_terms (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[]); const char *const args[]);
/** /**
* Handle a "/privacy" request. * Handle a "/privacy" request.
* *
* @param rh context of the handler * @param rc request context
* @param connection the MHD connection to handle
* @param args array of additional options (must be empty for this function) * @param args array of additional options (must be empty for this function)
* @return MHD result code * @return MHD result code
*/ */
MHD_RESULT MHD_RESULT
TEH_handler_privacy (const struct TEH_RequestHandler *rh, TEH_handler_privacy (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[]); const char *const args[]);

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014-2018 Taler Systems SA Copyright (C) 2014-2018, 2021 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software terms of the GNU Affero General Public License as published by the Free Software
@ -499,23 +499,13 @@ get_transfer_deposits (void *cls,
} }
/**
* Handle a GET "/transfers/$WTID" request.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
* @param args array of additional options (length: 1, just the wtid)
* @return MHD result code
*/
MHD_RESULT MHD_RESULT
TEH_handler_transfers_get (const struct TEH_RequestHandler *rh, TEH_handler_transfers_get (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[1]) const char *const args[1])
{ {
struct WtidTransactionContext ctx; struct WtidTransactionContext ctx;
MHD_RESULT mhd_ret; MHD_RESULT mhd_ret;
(void) rh;
memset (&ctx, memset (&ctx,
0, 0,
sizeof (ctx)); sizeof (ctx));
@ -526,13 +516,13 @@ TEH_handler_transfers_get (const struct TEH_RequestHandler *rh,
sizeof (ctx.wtid))) sizeof (ctx.wtid)))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
TALER_EC_EXCHANGE_TRANSFERS_GET_WTID_MALFORMED, TALER_EC_EXCHANGE_TRANSFERS_GET_WTID_MALFORMED,
args[0]); args[0]);
} }
if (GNUNET_OK != if (GNUNET_OK !=
TEH_DB_run_transaction (connection, TEH_DB_run_transaction (rc->connection,
"run transfers GET", "run transfers GET",
&mhd_ret, &mhd_ret,
&get_transfer_deposits, &get_transfer_deposits,
@ -541,7 +531,7 @@ TEH_handler_transfers_get (const struct TEH_RequestHandler *rh,
free_ctx (&ctx); free_ctx (&ctx);
return mhd_ret; return mhd_ret;
} }
mhd_ret = reply_transfer_details (connection, mhd_ret = reply_transfer_details (rc->connection,
&ctx.total, &ctx.total,
&ctx.merchant_pub, &ctx.merchant_pub,
&ctx.h_wire, &ctx.h_wire,

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014-2017 Taler Systems SA Copyright (C) 2014-2017, 2021 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software terms of the GNU Affero General Public License as published by the Free Software
@ -29,14 +29,12 @@
/** /**
* Handle a GET "/transfers/$WTID" request. * Handle a GET "/transfers/$WTID" request.
* *
* @param rh context of the handler * @param rc request context of the handler
* @param connection the MHD connection to handle
* @param args array of additional options (length: 1, just the wtid) * @param args array of additional options (length: 1, just the wtid)
* @return MHD result code * @return MHD result code
*/ */
MHD_RESULT MHD_RESULT
TEH_handler_transfers_get (const struct TEH_RequestHandler *rh, TEH_handler_transfers_get (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[1]); const char *const args[1]);

View File

@ -95,7 +95,7 @@ destroy_wire_state_cb (void *cls)
} }
int enum GNUNET_GenericReturnValue
TEH_WIRE_init () TEH_WIRE_init ()
{ {
if (0 != if (0 !=
@ -369,21 +369,19 @@ get_wire_state (void)
MHD_RESULT MHD_RESULT
TEH_handler_wire (const struct TEH_RequestHandler *rh, TEH_handler_wire (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[]) const char *const args[])
{ {
struct WireStateHandle *wsh; struct WireStateHandle *wsh;
(void) rh;
(void) args; (void) args;
wsh = get_wire_state (); wsh = get_wire_state ();
if (NULL == wsh) if (NULL == wsh)
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_INTERNAL_SERVER_ERROR, MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION, TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
NULL); NULL);
return TALER_MHD_reply_json (connection, return TALER_MHD_reply_json (rc->connection,
wsh->wire_reply, wsh->wire_reply,
wsh->http_status); wsh->http_status);
} }

View File

@ -31,7 +31,7 @@
* *
* @return #GNUNET_OK on success, #GNUNET_SYSERR on error. * @return #GNUNET_OK on success, #GNUNET_SYSERR on error.
*/ */
int enum GNUNET_GenericReturnValue
TEH_WIRE_init (void); TEH_WIRE_init (void);
@ -58,14 +58,12 @@ TEH_wire_update_state (void);
/** /**
* Handle a "/wire" request. * Handle a "/wire" request.
* *
* @param rh context of the handler * @param rc request context
* @param connection the MHD connection to handle
* @param args array of additional options (must be empty for this function) * @param args array of additional options (must be empty for this function)
* @return MHD result code * @return MHD result code
*/ */
MHD_RESULT MHD_RESULT
TEH_handler_wire (const struct TEH_RequestHandler *rh, TEH_handler_wire (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const char *const args[]); const char *const args[]);

View File

@ -316,24 +316,8 @@ withdraw_transaction (void *cls,
} }
/**
* Handle a "/reserves/$RESERVE_PUB/withdraw" request. Parses the
* "reserve_pub" EdDSA key of the reserve and the requested "denom_pub" which
* specifies the key/value of the coin to be withdrawn, and checks that the
* signature "reserve_sig" makes this a valid withdrawal request from the
* specified reserve. If so, the envelope with the blinded coin "coin_ev" is
* passed down to execute the withdrawal operation.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
* @param root uploaded JSON data
* @param args array of additional options (first must be the
* reserve public key, the second one should be "withdraw")
* @return MHD result code
*/
MHD_RESULT MHD_RESULT
TEH_handler_withdraw (const struct TEH_RequestHandler *rh, TEH_handler_withdraw (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const json_t *root, const json_t *root,
const char *const args[2]) const char *const args[2])
{ {
@ -351,7 +335,6 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
enum TALER_ErrorCode ec; enum TALER_ErrorCode ec;
struct TEH_DenominationKey *dk; struct TEH_DenominationKey *dk;
(void) rh;
if (GNUNET_OK != if (GNUNET_OK !=
GNUNET_STRINGS_string_to_data (args[0], GNUNET_STRINGS_string_to_data (args[0],
strlen (args[0]), strlen (args[0]),
@ -359,7 +342,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
sizeof (wc.wsrd.reserve_pub))) sizeof (wc.wsrd.reserve_pub)))
{ {
GNUNET_break_op (0); GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_BAD_REQUEST, MHD_HTTP_BAD_REQUEST,
TALER_EC_MERCHANT_GENERIC_RESERVE_PUB_MALFORMED, TALER_EC_MERCHANT_GENERIC_RESERVE_PUB_MALFORMED,
args[0]); args[0]);
@ -368,7 +351,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
{ {
enum GNUNET_GenericReturnValue res; enum GNUNET_GenericReturnValue res;
res = TALER_MHD_parse_json_data (connection, res = TALER_MHD_parse_json_data (rc->connection,
root, root,
spec); spec);
if (GNUNET_OK != res) if (GNUNET_OK != res)
@ -379,7 +362,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Absolute now;
dk = TEH_keys_denomination_by_hash (&wc.denom_pub_hash, dk = TEH_keys_denomination_by_hash (&wc.denom_pub_hash,
connection, rc->connection,
&mret); &mret);
if (NULL == dk) if (NULL == dk)
{ {
@ -397,7 +380,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
/* This denomination is past the expiration time for withdraws */ /* This denomination is past the expiration time for withdraws */
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
return TEH_RESPONSE_reply_expired_denom_pub_hash ( return TEH_RESPONSE_reply_expired_denom_pub_hash (
connection, rc->connection,
&wc.denom_pub_hash, &wc.denom_pub_hash,
now, now,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED, TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
@ -412,7 +395,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
/* This denomination is not yet valid */ /* This denomination is not yet valid */
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
return TEH_RESPONSE_reply_expired_denom_pub_hash ( return TEH_RESPONSE_reply_expired_denom_pub_hash (
connection, rc->connection,
&wc.denom_pub_hash, &wc.denom_pub_hash,
now, now,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE, TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
@ -427,7 +410,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
/* This denomination has been revoked */ /* This denomination has been revoked */
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
return TEH_RESPONSE_reply_expired_denom_pub_hash ( return TEH_RESPONSE_reply_expired_denom_pub_hash (
connection, rc->connection,
&wc.denom_pub_hash, &wc.denom_pub_hash,
now, now,
TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED, TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
@ -442,7 +425,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
&dk->meta.fee_withdraw)) &dk->meta.fee_withdraw))
{ {
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_INTERNAL_SERVER_ERROR, MHD_HTTP_INTERNAL_SERVER_ERROR,
TALER_EC_EXCHANGE_WITHDRAW_AMOUNT_FEE_OVERFLOW, TALER_EC_EXCHANGE_WITHDRAW_AMOUNT_FEE_OVERFLOW,
NULL); NULL);
@ -470,7 +453,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
TALER_LOG_WARNING ( TALER_LOG_WARNING (
"Client supplied invalid signature for withdraw request\n"); "Client supplied invalid signature for withdraw request\n");
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (rc->connection,
MHD_HTTP_FORBIDDEN, MHD_HTTP_FORBIDDEN,
TALER_EC_EXCHANGE_WITHDRAW_RESERVE_SIGNATURE_INVALID, TALER_EC_EXCHANGE_WITHDRAW_RESERVE_SIGNATURE_INVALID,
NULL); NULL);
@ -487,7 +470,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
{ {
GNUNET_break (0); GNUNET_break (0);
GNUNET_JSON_parse_free (spec); GNUNET_JSON_parse_free (spec);
return TALER_MHD_reply_with_ec (connection, return TALER_MHD_reply_with_ec (rc->connection,
ec, ec,
NULL); NULL);
} }
@ -498,7 +481,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
MHD_RESULT mhd_ret; MHD_RESULT mhd_ret;
if (GNUNET_OK != if (GNUNET_OK !=
TEH_DB_run_transaction (connection, TEH_DB_run_transaction (rc->connection,
"run withdraw", "run withdraw",
&mhd_ret, &mhd_ret,
&withdraw_transaction, &withdraw_transaction,
@ -520,7 +503,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
MHD_RESULT ret; MHD_RESULT ret;
ret = TALER_MHD_REPLY_JSON_PACK ( ret = TALER_MHD_REPLY_JSON_PACK (
connection, rc->connection,
MHD_HTTP_OK, MHD_HTTP_OK,
GNUNET_JSON_pack_rsa_signature ("ev_sig", GNUNET_JSON_pack_rsa_signature ("ev_sig",
wc.collectable.sig.rsa_signature)); wc.collectable.sig.rsa_signature));

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER This file is part of TALER
Copyright (C) 2014-2020 Taler Systems SA Copyright (C) 2014-2021 Taler Systems SA
TALER is free software; you can redistribute it and/or modify it under the TALER is free software; you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License as published by the Free Software terms of the GNU Affero General Public License as published by the Free Software
@ -35,16 +35,14 @@
* specified reserve. If so, the envelope with the blinded coin "coin_ev" is * specified reserve. If so, the envelope with the blinded coin "coin_ev" is
* passed down to execute the withdrawal operation. * passed down to execute the withdrawal operation.
* *
* @param rh context of the handler * @param rc request context
* @param connection the MHD connection to handle
* @param root uploaded JSON data * @param root uploaded JSON data
* @param args array of additional options (first must be the * @param args array of additional options (first must be the
* reserve public key, the second one should be "withdraw") * reserve public key, the second one should be "withdraw")
* @return MHD result code * @return MHD result code
*/ */
MHD_RESULT MHD_RESULT
TEH_handler_withdraw (const struct TEH_RequestHandler *rh, TEH_handler_withdraw (struct TEH_RequestContext *rc,
struct MHD_Connection *connection,
const json_t *root, const json_t *root,
const char *const args[2]); const char *const args[2]);