summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2020-02-26 17:00:41 +0100
committerChristian Grothoff <christian@grothoff.org>2020-02-26 17:00:41 +0100
commitfb9324338d9580b520b3713bf973bfcd9c49b569 (patch)
treeaa90b29dbad21957c864834895fe6b00272a058f /src
parent30b24448c8250b01eba8368f38c9ccdc2075f903 (diff)
downloadexchange-fb9324338d9580b520b3713bf973bfcd9c49b569.tar.gz
exchange-fb9324338d9580b520b3713bf973bfcd9c49b569.tar.bz2
exchange-fb9324338d9580b520b3713bf973bfcd9c49b569.zip
phase 1 of #6067: update exchange HTTPD to new API style
Diffstat (limited to 'src')
-rw-r--r--src/exchange/taler-exchange-httpd.c534
-rw-r--r--src/exchange/taler-exchange-httpd.h74
-rw-r--r--src/exchange/taler-exchange-httpd_deposit.c40
-rw-r--r--src/exchange/taler-exchange-httpd_deposit.h23
-rw-r--r--src/exchange/taler-exchange-httpd_keystate.c17
-rw-r--r--src/exchange/taler-exchange-httpd_keystate.h12
-rw-r--r--src/exchange/taler-exchange-httpd_mhd.c52
-rw-r--r--src/exchange/taler-exchange-httpd_mhd.h55
-rw-r--r--src/exchange/taler-exchange-httpd_recoup.c40
-rw-r--r--src/exchange/taler-exchange-httpd_recoup.h23
-rw-r--r--src/exchange/taler-exchange-httpd_refresh_link.c42
-rw-r--r--src/exchange/taler-exchange-httpd_refresh_link.h14
-rw-r--r--src/exchange/taler-exchange-httpd_refresh_melt.c41
-rw-r--r--src/exchange/taler-exchange-httpd_refresh_melt.h25
-rw-r--r--src/exchange/taler-exchange-httpd_refresh_reveal.c57
-rw-r--r--src/exchange/taler-exchange-httpd_refresh_reveal.h23
-rw-r--r--src/exchange/taler-exchange-httpd_refund.c39
-rw-r--r--src/exchange/taler-exchange-httpd_refund.h23
-rw-r--r--src/exchange/taler-exchange-httpd_reserve_status.c43
-rw-r--r--src/exchange/taler-exchange-httpd_reserve_status.h21
-rw-r--r--src/exchange/taler-exchange-httpd_reserve_withdraw.c52
-rw-r--r--src/exchange/taler-exchange-httpd_reserve_withdraw.h28
-rw-r--r--src/exchange/taler-exchange-httpd_terms.c28
-rw-r--r--src/exchange/taler-exchange-httpd_terms.h21
-rw-r--r--src/exchange/taler-exchange-httpd_track_transaction.c108
-rw-r--r--src/exchange/taler-exchange-httpd_track_transaction.h14
-rw-r--r--src/exchange/taler-exchange-httpd_track_transfer.c41
-rw-r--r--src/exchange/taler-exchange-httpd_track_transfer.h13
-rw-r--r--src/exchange/taler-exchange-httpd_validation.c1
-rw-r--r--src/exchange/taler-exchange-httpd_wire.c14
-rw-r--r--src/exchange/taler-exchange-httpd_wire.h12
-rw-r--r--src/include/taler_error_codes.h70
32 files changed, 871 insertions, 729 deletions
diff --git a/src/exchange/taler-exchange-httpd.c b/src/exchange/taler-exchange-httpd.c
index 6f021d726..288b4578d 100644
--- a/src/exchange/taler-exchange-httpd.c
+++ b/src/exchange/taler-exchange-httpd.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014, 2015, 2016, 2019 Taler Systems SA
+ Copyright (C) 2014-2020 Taler Systems SA
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
@@ -148,6 +148,92 @@ static unsigned long long req_max;
/**
+ * Handle a "/coins/$COIN_PUB/$OP" POST request. Parses the "coin_pub"
+ * EdDSA key of the coin and demultiplexes based on $OP.
+ *
+ * @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
+ */
+static int
+handle_post_coins (const struct TEH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ const json_t *root,
+ const char *const args[2])
+{
+ struct TALER_CoinSpendPublicKeyP coin_pub;
+ static const struct
+ {
+ /**
+ * Name of the operation (args[1])
+ */
+ const char *op;
+
+ /**
+ * Function to call to perform the operation.
+ *
+ * @param connection the MHD connection to handle
+ * @param coin_pub the public key of the coin
+ * @param root uploaded JSON data
+ * @return MHD result code
+ *///
+ int
+ (*handler)(struct MHD_Connection *connection,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const json_t *root);
+ } h[] = {
+ {
+ .op = "deposit",
+ .handler = &TEH_DEPOSIT_handler_deposit
+ },
+ {
+ .op = "melt",
+ .handler = &TEH_REFRESH_handler_melt
+ },
+ {
+ .op = "recoup",
+ .handler = &TEH_RECOUP_handler_recoup
+ },
+ {
+ .op = "refund",
+ .handler = &TEH_REFUND_handler_refund
+ },
+ {
+ .op = NULL,
+ .handler = NULL
+ },
+ };
+
+ (void) rh;
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (args[0],
+ strlen (args[0]),
+ &coin_pub,
+ sizeof (coin_pub)))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_COINS_INVALID_COIN_PUB,
+ "coin public key malformed");
+ }
+ for (unsigned int i = 0; NULL != h[i].op; i++)
+ if (0 == strcmp (h[i].op,
+ args[1]))
+ return h[i].handler (connection,
+ &coin_pub,
+ root);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_OPERATION_INVALID,
+ "requested operation on coin unknown");
+}
+
+
+/**
* Function called whenever MHD is done with a request. If the
* request was a POST, we may have stored a `struct Buffer *` in the
* @a con_cls that might still need to be cleaned up. Call the
@@ -206,6 +292,120 @@ is_valid_correlation_id (const char *correlation_id)
/**
+ * We found @a rh responsible for handling a request. Parse the
+ * @a upload_data (if applicable) and the @a url and call the
+ * handler.
+ *
+ * @param rh request handler to call
+ * @param connection connection being handled
+ * @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_size[in,out] number of bytes in @a upload_data
+ * @return MHD result code
+ */
+static int
+proceed_with_handler (const struct TEH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ const char *url,
+ void **inner_cls,
+ const char *upload_data,
+ size_t *upload_data_size)
+{
+ const char *args[rh->nargs + 1];
+ size_t ulen = strlen (url) + 1;
+ json_t *root;
+ int ret;
+
+ /* We do check for "ulen" here, because we'll later stack-allocate a buffer
+ of that size and don't want to enable malicious clients to cause us
+ huge stack allocations. */
+ if (ulen > 512)
+ {
+ /* 512 is simply "big enough", as it is bigger than "6 * 54",
+ which is the longest URL format we ever get (for
+ /deposits/). The value should be adjusted if we ever define protocol
+ endpoints with plausibly longer inputs. */
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_URI_TOO_LONG,
+ TALER_EC_URI_TOO_LONG,
+ "The URI given is too long");
+ }
+
+ /* All POST endpoints come with a body in JSON format. So we parse
+ the JSON here. */
+ if (0 == strcasecmp (rh->method,
+ MHD_HTTP_METHOD_POST))
+ {
+ int res;
+
+ res = TALER_MHD_parse_post_json (connection,
+ inner_cls,
+ upload_data,
+ upload_data_size,
+ &root);
+ if (GNUNET_SYSERR == res)
+ return MHD_NO;
+ if ( (GNUNET_NO == res) || (NULL == root) )
+ return MHD_YES;
+ }
+
+ {
+ char d[ulen];
+
+ /* Parse command-line arguments, if applicable */
+ if (rh->nargs > 0)
+ {
+ unsigned int i;
+
+ /* make a copy of 'url' because 'strtok()' will modify */
+ memcpy (d,
+ url,
+ ulen);
+ i = 0;
+ args[i++] = strtok (d, "/");
+ while ( (NULL != args[i - 1]) &&
+ (i < rh->nargs) )
+ args[i++] = strtok (NULL, "/");
+ /* make sure above loop ran nicely until completion, and also
+ that there is no excess data in 'd' afterwards */
+ if ( (i != rh->nargs) ||
+ (NULL == args[i - 1]) ||
+ (NULL != strtok (NULL, "/")) )
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_WRONG_NUMBER_OF_SEGMENTS,
+ "Number of segments does not match");
+ }
+ }
+
+ /* just to be safe(r), we always terminate the array with a NULL
+ (which handlers should not read, but at least if they do, they'll
+ crash pretty reliably... */
+ args[rh->nargs] = NULL;
+
+ /* Above logic ensures that 'root' is exactly non-NULL for POST operations */
+ if (NULL != root)
+ ret = rh->handler.post (rh,
+ connection,
+ root,
+ args);
+ else /* and we only have "POST" or "GET" in the API for at this point
+ (OPTIONS/HEAD are taken care of earlier) */
+ ret = rh->handler.get (rh,
+ connection,
+ args);
+ }
+ if (NULL != root)
+ json_decref (root);
+ return ret;
+}
+
+
+/**
* Handle incoming HTTP request.
*
* @param cls closure for MHD daemon (unused)
@@ -229,134 +429,111 @@ handle_mhd_request (void *cls,
void **con_cls)
{
static struct TEH_RequestHandler handlers[] = {
- /* Landing page, tell humans to go away. */
- { "/", MHD_HTTP_METHOD_GET, "text/plain",
- "Hello, I'm the Taler exchange. This HTTP server is not for humans.\n", 0,
- &TEH_MHD_handler_static_response, MHD_HTTP_OK },
/* /robots.txt: disallow everything */
- { "/robots.txt", MHD_HTTP_METHOD_GET, "text/plain",
- "User-agent: *\nDisallow: /\n", 0,
- &TEH_MHD_handler_static_response, MHD_HTTP_OK },
+ {
+ .url = "robots.txt",
+ .method = MHD_HTTP_METHOD_GET,
+ .handler.get = &TEH_MHD_handler_static_response,
+ .mime_type = "text/plain",
+ .data = "User-agent: *\nDisallow: /\n",
+ .response_code = MHD_HTTP_OK
+ },
+ /* Landing page, tell humans to go away. */
+ {
+ .url = "",
+ .method = MHD_HTTP_METHOD_GET,
+ .handler.get = TEH_MHD_handler_static_response,
+ .mime_type = "text/plain",
+ .data =
+ "Hello, I'm the Taler exchange. This HTTP server is not for humans.\n",
+ .response_code = MHD_HTTP_OK
+ },
/* AGPL licensing page, redirect to source. As per the AGPL-license,
every deployment is required to offer the user a download of the
source. We make this easy by including a redirect to the source
here. */
- { "/agpl", MHD_HTTP_METHOD_GET, "text/plain",
- NULL, 0,
- &TEH_MHD_handler_agpl_redirect, MHD_HTTP_FOUND },
+ {
+ .url = "agpl",
+ .method = MHD_HTTP_METHOD_GET,
+ .handler.get = &TEH_MHD_handler_agpl_redirect
+ },
/* Terms of service */
- { "/terms", MHD_HTTP_METHOD_GET, NULL,
- NULL, 0,
- &TEH_handler_terms, MHD_HTTP_OK },
+ {
+ .url = "terms",
+ .method = MHD_HTTP_METHOD_GET,
+ .handler.get = &TEH_handler_terms
+ },
/* Privacy policy */
- { "/privacy", MHD_HTTP_METHOD_GET, NULL,
- NULL, 0,
- &TEH_handler_privacy, MHD_HTTP_OK },
+ {
+ .url = "privacy",
+ .method = MHD_HTTP_METHOD_GET,
+ .handler.get = &TEH_handler_privacy
+ },
/* Return key material and fundamental properties for this exchange */
- { "/keys", MHD_HTTP_METHOD_GET, "application/json",
- NULL, 0,
- &TEH_KS_handler_keys, MHD_HTTP_OK },
- { "/keys", NULL, "text/plain",
- "Only GET is allowed", 0,
- &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
-
+ {
+ .url = "/keys",
+ .method = MHD_HTTP_METHOD_GET,
+ .handler.get = &TEH_KS_handler_keys,
+ },
/* Requests for wiring information */
- { "/wire", MHD_HTTP_METHOD_GET, "application/json",
- NULL, 0,
- &TEH_WIRE_handler_wire, MHD_HTTP_OK },
- { "/wire", NULL, "text/plain",
- "Only GET is allowed", 0,
- &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
-
+ {
+ .url = "wire",
+ .method = MHD_HTTP_METHOD_GET,
+ .handler.get = &TEH_WIRE_handler_wire
+ },
/* Withdrawing coins / interaction with reserves */
- { "/reserve/status", MHD_HTTP_METHOD_GET, "application/json",
- NULL, 0,
- &TEH_RESERVE_handler_reserve_status, MHD_HTTP_OK },
- { "/reserve/status", NULL, "text/plain",
- "Only GET is allowed", 0,
- &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
-
- { "/reserve/withdraw", MHD_HTTP_METHOD_POST, "application/json",
- NULL, 0,
- &TEH_RESERVE_handler_reserve_withdraw, MHD_HTTP_OK },
- { "/reserve/withdraw", NULL, "text/plain",
- "Only POST is allowed", 0,
- &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
-
- /* Depositing coins */
- { "/deposit", MHD_HTTP_METHOD_POST, "application/json",
- NULL, 0,
- &TEH_DEPOSIT_handler_deposit, MHD_HTTP_OK },
- { "/deposit", NULL, "text/plain",
- "Only POST is allowed", 0,
- &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
-
- /* Refunding coins */
- { "/refund", MHD_HTTP_METHOD_POST, "application/json",
- NULL, 0,
- &TEH_REFUND_handler_refund, MHD_HTTP_OK },
- { "/refund", NULL, "text/plain",
- "Only POST is allowed", 0,
- &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
-
- /* Dealing with change */
- { "/refresh/melt", MHD_HTTP_METHOD_POST, "application/json",
- NULL, 0,
- &TEH_REFRESH_handler_refresh_melt, MHD_HTTP_OK },
- { "/refresh/melt", NULL, "text/plain",
- "Only POST is allowed", 0,
- &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
-
- { "/refresh/reveal", MHD_HTTP_METHOD_POST, "application/json",
- NULL, 0,
- &TEH_REFRESH_handler_refresh_reveal, MHD_HTTP_OK },
- { "/refresh/reveal", NULL, "text/plain",
- "Only POST is allowed", 0,
- &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
-
- { "/refresh/reveal", MHD_HTTP_METHOD_POST, "application/json",
- NULL, 0,
- &TEH_REFRESH_handler_refresh_reveal, MHD_HTTP_OK },
- { "/refresh/reveal", NULL, "text/plain",
- "Only POST is allowed", 0,
- &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
-
- { "/refresh/link", MHD_HTTP_METHOD_GET, "application/json",
- NULL, 0,
- &TEH_REFRESH_handler_refresh_link, MHD_HTTP_OK },
- { "/refresh/link", NULL, "text/plain",
- "Only GET is allowed", 0,
- &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
-
- { "/track/transfer", MHD_HTTP_METHOD_GET, "application/json",
- NULL, 0,
- &TEH_TRACKING_handler_track_transfer, MHD_HTTP_OK },
- { "/track/transfer", NULL, "text/plain",
- "Only GET is allowed", 0,
- &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
- { "/track/transaction", MHD_HTTP_METHOD_POST, "application/json",
- NULL, 0,
- &TEH_TRACKING_handler_track_transaction, MHD_HTTP_OK },
- { "/track/transaction", NULL, "text/plain",
- "Only POST is allowed", 0,
- &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
-
- { "/recoup", MHD_HTTP_METHOD_POST, "application/json",
- NULL, 0,
- &TEH_RECOUP_handler_recoup, MHD_HTTP_OK },
- { "/refresh/link", NULL, "text/plain",
- "Only GET is allowed", 0,
- &TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
-
- { NULL, NULL, NULL, NULL, 0, NULL, 0 }
- };
- static struct TEH_RequestHandler h404 = {
- "", NULL, "text/html",
- "<html><title>404: not found</title></html>", 0,
- &TEH_MHD_handler_static_response, MHD_HTTP_NOT_FOUND
+ {
+ .url = "reserves",
+ .method = MHD_HTTP_METHOD_GET,
+ .handler.get = &TEH_RESERVE_handler_reserve_status,
+ .nargs = 1
+ },
+ {
+ .url = "reserves",
+ .method = MHD_HTTP_METHOD_POST,
+ .handler.post = &TEH_RESERVE_handler_reserve_withdraw,
+ .nargs = 2
+ },
+ /* coins */
+ {
+ .url = "coins",
+ .method = MHD_HTTP_METHOD_POST,
+ .handler.post = &handle_post_coins,
+ .nargs = 2
+ },
+ {
+ .url = "coins",
+ .method = MHD_HTTP_METHOD_GET,
+ .handler.get = TEH_REFRESH_handler_link,
+ .nargs = 2,
+ },
+ /* refreshing */
+ {
+ .url = "refreshes",
+ .method = MHD_HTTP_METHOD_POST,
+ .handler.post = &TEH_REFRESH_handler_reveal,
+ .nargs = 2
+ },
+ /* tracking transfers */
+ {
+ .url = "transfers",
+ .method = MHD_HTTP_METHOD_GET,
+ .handler.get = &TEH_TRACKING_handler_track_transfer,
+ .nargs = 1
+ },
+ /* tracking deposits */
+ {
+ .url = "deposits",
+ .method = MHD_HTTP_METHOD_GET,
+ .handler.get = &TEH_TRACKING_handler_track_transaction,
+ .nargs = 4
+ },
+ /* mark end of list */
+ {
+ .url = NULL
+ }
};
struct ExchangeHttpRequestClosure *ecls = *con_cls;
- int ret;
void **inner_cls;
struct GNUNET_AsyncScopeSave old_scope;
const char *correlation_id = NULL;
@@ -367,7 +544,8 @@ handle_mhd_request (void *cls,
{
unsigned long long cnt;
- GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Handling new request\n");
+ GNUNET_log (GNUNET_ERROR_TYPE_INFO,
+ "Handling new request\n");
cnt = __sync_add_and_fetch (&req_count, 1LLU);
if (req_max == cnt)
{
@@ -395,7 +573,8 @@ handle_mhd_request (void *cls,
}
inner_cls = &ecls->opaque_post_parsing_context;
- GNUNET_async_scope_enter (&ecls->async_scope_id, &old_scope);
+ GNUNET_async_scope_enter (&ecls->async_scope_id,
+ &old_scope);
if (NULL != correlation_id)
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Handling request (%s) for URL '%s', correlation_id=%s\n",
@@ -410,55 +589,100 @@ handle_mhd_request (void *cls,
/* on repeated requests, check our cache first */
if (NULL != ecls->rh)
{
- ret = ecls->rh->handler (ecls->rh,
- connection,
- inner_cls,
- upload_data,
- upload_data_size);
+ int ret;
+
+ ret = proceed_with_handler (ecls->rh,
+ connection,
+ url,
+ inner_cls,
+ upload_data,
+ upload_data_size);
GNUNET_async_scope_restore (&old_scope);
return ret;
}
+
if (0 == strcasecmp (method,
MHD_HTTP_METHOD_HEAD))
- method = MHD_HTTP_METHOD_GET; /* treat HEAD as GET here, MHD will do the rest */
- for (unsigned int i = 0; NULL != handlers[i].url; i++)
- {
- struct TEH_RequestHandler *rh = &handlers[i];
-
- if (0 != strcmp (url, rh->url))
- continue;
+ method = MHD_HTTP_METHOD_GET; /* treat HEAD as GET here, MHD will do the rest */
- /* The URL is a match! What we now do depends on the method. */
- if (0 == strcasecmp (method, MHD_HTTP_METHOD_OPTIONS))
+ /* parse first part of URL */
+ {
+ int found = GNUNET_NO;
+ size_t tok_size;
+ const char *tok;
+ const char *rest;
+
+ if ('\0' == url[0])
+ /* strange, should start with '/', treat as just "/" */
+ url = "/";
+ tok = url + 1;
+ rest = strchr (tok, '/');
+ if (NULL == rest)
+ {
+ tok_size = 0;
+ }
+ else
+ {
+ tok_size = rest - tok;
+ rest++; /* skip over '/' */
+ }
+ for (unsigned int i = 0; NULL != handlers[i].url; i++)
{
- GNUNET_async_scope_restore (&old_scope);
- return TALER_MHD_reply_cors_preflight (connection);
+ struct TEH_RequestHandler *rh = &handlers[i];
+
+ if (0 != strncmp (tok,
+ rh->url,
+ tok_size))
+ continue;
+ found = GNUNET_YES;
+ /* The URL is a match! What we now do depends on the method. */
+ if (0 == strcasecmp (method, MHD_HTTP_METHOD_OPTIONS))
+ {
+ GNUNET_async_scope_restore (&old_scope);
+ return TALER_MHD_reply_cors_preflight (connection);
+ }
+ GNUNET_assert (NULL != rh->method);
+ if (0 == strcasecmp (method,
+ rh->method))
+ {
+ int ret;
+
+ /* cache to avoid the loop next time */
+ ecls->rh = rh;
+ /* run handler */
+ ret = proceed_with_handler (rh,
+ connection,
+ url,
+ inner_cls,
+ upload_data,
+ upload_data_size);
+ GNUNET_async_scope_restore (&old_scope);
+ return ret;
+ }
}
- if ( (NULL == rh->method) ||
- (0 == strcasecmp (method,
- rh->method)) )
+ if (GNUNET_YES == found)
{
- /* cache to avoid the loop next time */
- ecls->rh = rh;
- /* run handler */
- ret = rh->handler (rh,
- connection,
- inner_cls,
- upload_data,
- upload_data_size);
- GNUNET_async_scope_restore (&old_scope);
- return ret;
+ /* we found a matching address, but the method is wrong */
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_METHOD_NOT_ALLOWED,
+ TALER_EC_METHOD_INVALID,
+ "The HTTP method used is invalid for this URL");
}
}
+
/* No handler matches, generate not found */
- ret = TEH_MHD_handler_static_response (&h404,
- connection,
- inner_cls,
- upload_data,
- upload_data_size);
- GNUNET_async_scope_restore (&old_scope);
- return ret;
+ {
+ int ret;
+
+ ret = TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_NOT_FOUND,
+ TALER_EC_ENDPOINT_UNKNOWN,
+ "No handler found for the given URL");
+ GNUNET_async_scope_restore (&old_scope);
+ return ret;
+ }
}
diff --git a/src/exchange/taler-exchange-httpd.h b/src/exchange/taler-exchange-httpd.h
index 38c611c66..8489d1790 100644
--- a/src/exchange/taler-exchange-httpd.h
+++ b/src/exchange/taler-exchange-httpd.h
@@ -24,6 +24,8 @@
#define TALER_EXCHANGE_HTTPD_H
#include <microhttpd.h>
+#include "taler_json_lib.h"
+#include "taler_crypto_lib.h"
/**
@@ -65,51 +67,77 @@ struct TEH_RequestHandler
{
/**
- * URL the handler is for.
+ * URL the handler is for (first part only).
*/
const char *url;
/**
- * Method the handler is for, NULL for "all".
+ * Method the handler is for.
*/
const char *method;
/**
+ * Callbacks for handling of the request. Which one is used
+ * depends on @e method.
+ */
+ union
+ {
+ /**
+ * Function to call to handle a GET requests (and those
+ * with @e method NULL).
+ *
+ * @param rh this struct
+ * @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
+ * @return MHD result code
+ */
+ int (*get)(const struct TEH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ const char *const args[]);
+
+
+ /**
+ * Function to call to handle a POST request.
+ *
+ * @param rh this struct
+ * @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 args array of arguments, needs to be of length @e args_expected
+ * @return MHD result code
+ */
+ int (*post)(const struct TEH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ const json_t *root,
+ const char *const args[]);
+
+ } handler;
+
+ /**
+ * Number of arguments this handler expects in the @a args array.
+ */
+ unsigned int nargs;
+
+ /**
* Mime type to use in reply (hint, can be NULL).
*/
const char *mime_type;
/**
- * Raw data for the @e handler
+ * Raw data for the @e handler, can be NULL for none provided.
*/
const void *data;
/**
- * Number of bytes in @e data, 0 for 0-terminated.
+ * Number of bytes in @e data, 0 for data is 0-terminated (!).
*/
size_t data_size;
/**
- * Function to call to handle the request.
- *
- * @param rh this struct
- * @param mime_type the @e mime_type for the reply (hint, can be NULL)
- * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
- * @return MHD result code
- */
- int (*handler)(struct TEH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
-
- /**
- * Default response code.
+ * Default response code. 0 for none provided.
*/
- int response_code;
+ unsigned int response_code;
};
diff --git a/src/exchange/taler-exchange-httpd_deposit.c b/src/exchange/taler-exchange-httpd_deposit.c
index 49b9cc2fc..da89ff47e 100644
--- a/src/exchange/taler-exchange-httpd_deposit.c
+++ b/src/exchange/taler-exchange-httpd_deposit.c
@@ -381,27 +381,22 @@ check_timestamp_current (struct GNUNET_TIME_Absolute ts)
/**
- * Handle a "/deposit" request. Parses the JSON, and, if successful,
- * passes the JSON data to #verify_and_execute_deposit() to further
- * check the details of the operation specified. If everything checks
+ * Handle a "/coins/$COIN_PUB/deposit" request. Parses the JSON, and, if
+ * successful, passes the JSON data to #verify_and_execute_deposit() to
+ * further check the details of the operation specified. If everything checks
* out, this will ultimately lead to the "/deposit" being executed, or
* rejected.
*
- * @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param coin_pub public key of the coin
+ * @param root uploaded JSON data
* @return MHD result code
*/
int
-TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+TEH_DEPOSIT_handler_deposit (struct MHD_Connection *connection,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const json_t *root)
{
- json_t *json;
int res;
json_t *wire;
enum TALER_ErrorCode ec;
@@ -415,7 +410,6 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
&deposit.coin.denom_pub_hash),
TALER_JSON_spec_denomination_signature ("ub_sig", &deposit.coin.denom_sig),
- GNUNET_JSON_spec_fixed_auto ("coin_pub", &deposit.coin.coin_pub),
GNUNET_JSON_spec_fixed_auto ("merchant_pub", &deposit.merchant_pub),
GNUNET_JSON_spec_fixed_auto ("h_contract_terms", &deposit.h_contract_terms),
GNUNET_JSON_spec_fixed_auto ("h_wire", &deposit.h_wire),
@@ -428,27 +422,13 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
GNUNET_JSON_spec_end ()
};
- (void) rh;
- res = TALER_MHD_parse_post_json (connection,
- connection_cls,
- upload_data,
- upload_data_size,
- &json);
- if (GNUNET_SYSERR == res)
- {
- GNUNET_break (0);
- return MHD_NO;
- }
- if ( (GNUNET_NO == res) ||
- (NULL == json) )
- return MHD_YES;
memset (&deposit,
0,
sizeof (deposit));
+ deposit.coin.coin_pub = *coin_pub;
res = TALER_MHD_parse_json_data (connection,
- json,
+ root,
spec);
- json_decref (json);
if (GNUNET_SYSERR == res)
{
GNUNET_break (0);
diff --git a/src/exchange/taler-exchange-httpd_deposit.h b/src/exchange/taler-exchange-httpd_deposit.h
index ed1f87d50..23c46c283 100644
--- a/src/exchange/taler-exchange-httpd_deposit.h
+++ b/src/exchange/taler-exchange-httpd_deposit.h
@@ -29,22 +29,21 @@
/**
- * Handle a "/deposit" request. Parses the JSON, and, if successful,
- * checks the signatures. If everything checks out, this will
- * ultimately lead to the "/deposit" being executed, or rejected.
+ * Handle a "/coins/$COIN_PUB/deposit" request. Parses the JSON, and, if
+ * successful, passes the JSON data to #verify_and_execute_deposit() to
+ * further check the details of the operation specified. If everything checks
+ * out, this will ultimately lead to the "/deposit" being executed, or
+ * rejected.
*
- * @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param coin_pub public key of the coin
+ * @param root uploaded JSON data
* @return MHD result code
*/
int
-TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
+TEH_DEPOSIT_handler_deposit (struct MHD_Connection *connection,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const json_t *root);
+
#endif
diff --git a/src/exchange/taler-exchange-httpd_keystate.c b/src/exchange/taler-exchange-httpd_keystate.c
index 27f22925d..f0ab2a0d7 100644
--- a/src/exchange/taler-exchange-httpd_keystate.c
+++ b/src/exchange/taler-exchange-httpd_keystate.c
@@ -2381,17 +2381,13 @@ krd_search_comparator (const void *key,
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (must be empty for this function)
* @return MHD result code
*/
int
-TEH_KS_handler_keys (struct TEH_RequestHandler *rh,
+TEH_KS_handler_keys (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+ const char *const args[])
{
int ret;
const char *have_cherrypick;
@@ -2400,9 +2396,8 @@ TEH_KS_handler_keys (struct TEH_RequestHandler *rh,
struct GNUNET_TIME_Absolute now;
const struct KeysResponseData *krd;
- (void) connection_cls;
- (void) upload_data;
- (void) upload_data_size;
+ (void) rh;
+ (void) args;
have_cherrypick = MHD_lookup_connection_value (connection,
MHD_GET_ARGUMENT_KIND,
"last_issue_date");
@@ -2493,7 +2488,7 @@ TEH_KS_handler_keys (struct TEH_RequestHandler *rh,
"no key response found");
}
ret = MHD_queue_response (connection,
- rh->response_code,
+ MHD_HTTP_OK,
(MHD_YES == TALER_MHD_can_compress (connection))
? krd->response_compressed
: krd->response_uncompressed);
diff --git a/src/exchange/taler-exchange-httpd_keystate.h b/src/exchange/taler-exchange-httpd_keystate.h
index ebcefa08a..a69060964 100644
--- a/src/exchange/taler-exchange-httpd_keystate.h
+++ b/src/exchange/taler-exchange-httpd_keystate.h
@@ -188,17 +188,13 @@ TEH_KS_sign (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (must be empty for this function)
* @return MHD result code
- */
+ */
int
-TEH_KS_handler_keys (struct TEH_RequestHandler *rh,
+TEH_KS_handler_keys (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
+ const char *const args[]);
#endif
diff --git a/src/exchange/taler-exchange-httpd_mhd.c b/src/exchange/taler-exchange-httpd_mhd.c
index 0f2ce033a..0d59fad1b 100644
--- a/src/exchange/taler-exchange-httpd_mhd.c
+++ b/src/exchange/taler-exchange-httpd_mhd.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014 Taler Systems SA
+ Copyright (C) 2014-2020 Taler Systems SA
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
@@ -39,27 +39,23 @@
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (must be empty for this function)
* @return MHD result code
*/
int
-TEH_MHD_handler_static_response (struct TEH_RequestHandler *rh,
+TEH_MHD_handler_static_response (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+ const char *const args[])
{
struct MHD_Response *response;
int ret;
+ size_t dlen;
- (void) connection_cls;
- (void) upload_data;
- (void) upload_data_size;
- if (0 == rh->data_size)
- rh->data_size = strlen ((const char *) rh->data);
- response = MHD_create_response_from_buffer (rh->data_size,
+ (void) args;
+ dlen = (0 == rh->data_size)
+ ? strlen ((const char *) rh->data)
+ : rh->data_size;
+ response = MHD_create_response_from_buffer (dlen,
(void *) rh->data,
MHD_RESPMEM_PERSISTENT);
if (NULL == response)
@@ -86,22 +82,16 @@ TEH_MHD_handler_static_response (struct TEH_RequestHandler *rh,
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (must be empty for this function)
* @return MHD result code
*/
int
-TEH_MHD_handler_agpl_redirect (struct TEH_RequestHandler *rh,
+TEH_MHD_handler_agpl_redirect (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+ const char *const args[])
{
(void) rh;
- (void) connection_cls;
- (void) upload_data;
- (void) upload_data_size;
+ (void) args;
return TALER_MHD_reply_agpl (connection,
"http://www.git.taler.net/?p=exchange.git");
}
@@ -113,21 +103,15 @@ TEH_MHD_handler_agpl_redirect (struct TEH_RequestHandler *rh,
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (must be empty for this function)
* @return MHD result code
*/
int
-TEH_MHD_handler_send_json_pack_error (struct TEH_RequestHandler *rh,
+TEH_MHD_handler_send_json_pack_error (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+ const char *const args[])
{
- (void) connection_cls;
- (void) upload_data;
- (void) upload_data_size;
+ (void) args;
return TALER_MHD_reply_with_error (connection,
rh->response_code,
TALER_EC_METHOD_INVALID,
diff --git a/src/exchange/taler-exchange-httpd_mhd.h b/src/exchange/taler-exchange-httpd_mhd.h
index 16fc5a014..0364f0463 100644
--- a/src/exchange/taler-exchange-httpd_mhd.h
+++ b/src/exchange/taler-exchange-httpd_mhd.h
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014 Taler Systems SA
+ Copyright (C) 2014-2020 Taler Systems SA
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
@@ -34,17 +34,13 @@
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (must be empty for this function)
* @return MHD result code
*/
int
-TEH_MHD_handler_static_response (struct TEH_RequestHandler *rh,
+TEH_MHD_handler_static_response (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
+ const char *const args[]);
/**
@@ -53,40 +49,13 @@ TEH_MHD_handler_static_response (struct TEH_RequestHandler *rh,
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (must be empty for this function)
* @return MHD result code
*/
int
-TEH_MHD_handler_agpl_redirect (struct TEH_RequestHandler *rh,
+TEH_MHD_handler_agpl_redirect (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
-
-
-/**
- * Function to call to handle the request by building a JSON
- * reply from varargs.
- *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param response_code HTTP response code to use
- * @param do_cache can the response be cached? (0: no, 1: yes)
- * @param fmt format string for pack
- * @param ... varargs
- * @return MHD result code
- */
-int
-TEH_MHD_helper_send_json_pack (struct TEH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void *connection_cls,
- int response_code,
- int do_cache,
- const char *fmt,
- ...);
+ const char *const args[]);
/**
@@ -95,17 +64,13 @@ TEH_MHD_helper_send_json_pack (struct TEH_RequestHandler *rh,
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (must be empty for this function)
* @return MHD result code
*/
int
-TEH_MHD_handler_send_json_pack_error (struct TEH_RequestHandler *rh,
+TEH_MHD_handler_send_json_pack_error (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
+ const char *const args[]);
#endif
diff --git a/src/exchange/taler-exchange-httpd_recoup.c b/src/exchange/taler-exchange-httpd_recoup.c
index 26bd65b46..f4cd99155 100644
--- a/src/exchange/taler-exchange-httpd_recoup.c
+++ b/src/exchange/taler-exchange-httpd_recoup.c
@@ -562,27 +562,21 @@ verify_and_execute_recoup (struct MHD_Connection *connection,
/**
- * Handle a "/recoup" request. Parses the JSON, and, if successful,
- * passes the JSON data to #verify_and_execute_recoup() to
- * further check the details of the operation specified. If
- * everything checks out, this will ultimately lead to the "/refund"
- * being executed, or rejected.
+ * Handle a "/coins/$COIN_PUB/recoup" request. Parses the JSON, and, if
+ * successful, passes the JSON data to #verify_and_execute_recoup() to further
+ * check the details of the operation specified. If everything checks out,
+ * this will ultimately lead to the refund being executed, or rejected.
*
- * @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param coin_pub public key of the coin
+ * @param root uploaded JSON data
* @return MHD result code
*/
int
-TEH_RECOUP_handler_recoup (struct TEH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+TEH_RECOUP_handler_recoup (struct MHD_Connection *connection,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const json_t *root)
{
- json_t *json;
int res;
struct TALER_CoinPublicInfo coin;
struct TALER_DenominationBlindingKeyP coin_bks;
@@ -593,8 +587,6 @@ TEH_RECOUP_handler_recoup (struct TEH_RequestHandler *rh,
&coin.denom_pub_hash),
TALER_JSON_spec_denomination_signature ("denom_sig",
&coin.denom_sig),
- GNUNET_JSON_spec_fixed_auto ("coin_pub",
- &coin.coin_pub),
GNUNET_JSON_spec_fixed_auto ("coin_blind_key_secret",
&coin_bks),
GNUNET_JSON_spec_fixed_auto ("coin_sig",
@@ -605,20 +597,10 @@ TEH_RECOUP_handler_recoup (struct TEH_RequestHandler *rh,
GNUNET_JSON_spec_end ()
};
- (void) rh;
- res = TALER_MHD_parse_post_json (connection,
- connection_cls,
- upload_data,
- upload_data_size,
- &json);
- if (GNUNET_SYSERR == res)
- return MHD_NO;
- if ( (GNUNET_NO == res) || (NULL == json) )
- return MHD_YES;
+ coin.coin_pub = *coin_pub;
res = TALER_MHD_parse_json_data (connection,
- json,
+ root,
spec);
- json_decref (json);
if (GNUNET_SYSERR == res)
return MHD_NO; /* hard failure */
if (GNUNET_NO == res)
diff --git a/src/exchange/taler-exchange-httpd_recoup.h b/src/exchange/taler-exchange-httpd_recoup.h
index 1baefc8ec..f86bf60e7 100644
--- a/src/exchange/taler-exchange-httpd_recoup.h
+++ b/src/exchange/taler-exchange-httpd_recoup.h
@@ -27,25 +27,20 @@
/**
- * Handle a "/recoup" request. Parses the JSON, and, if successful,
- * passes the JSON data to #verify_and_execute_recoup() to
- * further check the details of the operation specified. If
- * everything checks out, this will ultimately lead to the "/refund"
- * being executed, or rejected.
+ * Handle a "/coins/$COIN_PUB/recoup" request. Parses the JSON, and, if
+ * successful, passes the JSON data to #verify_and_execute_recoup() to further
+ * check the details of the operation specified. If everything checks out,
+ * this will ultimately lead to the refund being executed, or rejected.
*
- * @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param coin_pub public key of the coin
+ * @param root uploaded JSON data
* @return MHD result code
*/
int
-TEH_RECOUP_handler_recoup (struct TEH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
+TEH_RECOUP_handler_recoup (struct MHD_Connection *connection,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const json_t *root);
#endif
diff --git a/src/exchange/taler-exchange-httpd_refresh_link.c b/src/exchange/taler-exchange-httpd_refresh_link.c
index 5e4360912..6dbaed497 100644
--- a/src/exchange/taler-exchange-httpd_refresh_link.c
+++ b/src/exchange/taler-exchange-httpd_refresh_link.c
@@ -172,43 +172,37 @@ refresh_link_transaction (void *cls,
/**
- * Handle a "/refresh/link" request. Note that for "/refresh/link"
- * we do use a simple HTTP GET, and a HTTP POST!
+ * Handle a "/coins/$COIN_PUB/link" request.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (length: 2, first is the coin_pub, second must be "link")
* @return MHD result code
*/
int
-TEH_REFRESH_handler_refresh_link (struct TEH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+TEH_REFRESH_handler_link (const struct TEH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ const char *const args[2])
{
- int mhd_ret;
- int res;
struct HTD_Context ctx;
+ int mhd_ret;
(void) rh;
- (void) connection_cls;
- (void) upload_data;
- (void) upload_data_size;
memset (&ctx,
0,
sizeof (ctx));
- res = TALER_MHD_parse_request_arg_data (connection,
- "coin_pub",
- &ctx.coin_pub,
- sizeof (struct
- TALER_CoinSpendPublicKeyP));
- if (GNUNET_SYSERR == res)
- return MHD_NO;
- if (GNUNET_OK != res)
- return MHD_YES;
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (args[0],
+ strlen (args[0]),
+ &ctx.coin_pub,
+ sizeof (ctx.coin_pub)))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_COINS_INVALID_COIN_PUB,
+ "coin public key malformed");
+ }
ctx.mlist = json_array ();
if (GNUNET_OK !=
TEH_DB_run_transaction (connection,
diff --git a/src/exchange/taler-exchange-httpd_refresh_link.h b/src/exchange/taler-exchange-httpd_refresh_link.h
index d0fcff338..9469c4713 100644
--- a/src/exchange/taler-exchange-httpd_refresh_link.h
+++ b/src/exchange/taler-exchange-httpd_refresh_link.h
@@ -29,21 +29,17 @@
/**
- * Handle a "/refresh/link" request
+ * Handle a "/coins/$COIN_PUB/link" request.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (length: 2, first is the coin_pub, second must be "link")
* @return MHD result code
*/
int
-TEH_REFRESH_handler_refresh_link (struct TEH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
+TEH_REFRESH_handler_link (const struct TEH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ const char *const args[2]);
#endif
diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.c b/src/exchange/taler-exchange-httpd_refresh_melt.c
index c7dc700f7..9d92a4cee 100644
--- a/src/exchange/taler-exchange-httpd_refresh_melt.c
+++ b/src/exchange/taler-exchange-httpd_refresh_melt.c
@@ -577,31 +577,24 @@ check_for_denomination_key (struct MHD_Connection *connection,
/**
- * Handle a "/refresh/melt" request. Parses the request into the JSON
- * components and then hands things of to #check_for_denomination_key()
- * to validate the melted coins, the signature and execute the melt
- * using handle_refresh_melt().
- *
- * @param rh context of the handler
+ * Handle a "/coins/$COIN_PUB/melt" request. Parses the request into the JSON
+ * components and then hands things of to #check_for_denomination_key() to
+ * validate the melted coins, the signature and execute the melt using
+ * handle_refresh_melt().
+
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param coin_pub public key of the coin
+ * @param root uploaded JSON data
* @return MHD result code
*/
int
-TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+TEH_REFRESH_handler_melt (struct MHD_Connection *connection,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const json_t *root)
{
- json_t *root;
struct RefreshMeltContext rmc;
int res;
struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("coin_pub",
- &rmc.refresh_session.coin.coin_pub),
TALER_JSON_spec_denomination_signature ("denom_sig",
&rmc.refresh_session.coin.denom_sig),
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
@@ -615,25 +608,13 @@ TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh,
GNUNET_JSON_spec_end ()
};
- (void) rh;
- res = TALER_MHD_parse_post_json (connection,
- connection_cls,
- upload_data,
- upload_data_size,
- &root);
- if (GNUNET_SYSERR == res)
- return MHD_NO;
- if ( (GNUNET_NO == res) ||
- (NULL == root) )
- return MHD_YES;
-
memset (&rmc,
0,
sizeof (rmc));
+ rmc.refresh_session.coin.coin_pub = *coin_pub;
res = TALER_MHD_parse_json_data (connection,
root,
spec);
- json_decref (root);
if (GNUNET_OK != res)
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
diff --git a/src/exchange/taler-exchange-httpd_refresh_melt.h b/src/exchange/taler-exchange-httpd_refresh_melt.h
index c50fdcb4c..41488c818 100644
--- a/src/exchange/taler-exchange-httpd_refresh_melt.h
+++ b/src/exchange/taler-exchange-httpd_refresh_melt.h
@@ -29,25 +29,20 @@
/**
- * Handle a "/refresh/melt" request after the first parsing has
- * happened. We now need to validate the coins being melted and the
- * session signature and then hand things of to execute the melt
- * operation. This function parses the JSON arrays and then passes
- * processing on to #refresh_melt_transaction().
- *
- * @param rh context of the handler
+ * Handle a "/coins/$COIN_PUB/melt" request. Parses the request into the JSON
+ * components and then hands things of to #check_for_denomination_key() to
+ * validate the melted coins, the signature and execute the melt using
+ * handle_refresh_melt().
+
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param coin_pub public key of the coin
+ * @param root uploaded JSON data
* @return MHD result code
*/
int
-TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
+TEH_REFRESH_handler_melt (struct MHD_Connection *connection,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const json_t *root);
#endif
diff --git a/src/exchange/taler-exchange-httpd_refresh_reveal.c b/src/exchange/taler-exchange-httpd_refresh_reveal.c
index 1e03c8e7d..b7d7fb1c7 100644
--- a/src/exchange/taler-exchange-httpd_refresh_reveal.c
+++ b/src/exchange/taler-exchange-httpd_refresh_reveal.c
@@ -884,30 +884,27 @@ handle_refresh_reveal_json (struct MHD_Connection *connection,
/**
- * Handle a "/refresh/reveal" request. This time, the client reveals the
+ * Handle a "/refreshes/$RCH/reveal" request. This time, the client reveals the
* private transfer keys except for the cut-and-choose value returned from
- * "/refresh/melt". This function parses the revealed keys and secrets and
+ * "/coins/$COIN_PUB/melt". This function parses the revealed keys and secrets and
* ultimately passes everything to #resolve_refresh_reveal_denominations()
* which will verify that the revealed information is valid then runs the
* transaction in #refresh_reveal_transaction() and finally returns the signed
* refreshed coins.
*
* @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param coin_pub public key of the coin
+ * @param root uploaded JSON data
+ * @param args array of additional options (length: 2, session hash and the string "reveal")
* @return MHD result code
- */
+ */
int
-TEH_REFRESH_handler_refresh_reveal (struct TEH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+TEH_REFRESH_handler_reveal (const struct TEH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ const json_t *root,
+ const char *const args[2])
{
int res;
- json_t *root;
json_t *coin_evs;
json_t *transfer_privs;
json_t *link_sigs;
@@ -924,24 +921,34 @@ TEH_REFRESH_handler_refresh_reveal (struct TEH_RequestHandler *rh,
};
(void) rh;
- res = TALER_MHD_parse_post_json (connection,
- connection_cls,
- upload_data,
- upload_data_size,
- &root);
- if (GNUNET_SYSERR == res)
- return MHD_NO;
- if ( (GNUNET_NO == res) ||
- (NULL == root) )
- return MHD_YES;
-
memset (&rctx,
0,
sizeof (rctx));
+
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (args[0],
+ strlen (args[0]),
+ &rctx.rc,
+ sizeof (rctx.rc)))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_REFRESHES_INVALID_RCH,
+ "refresh commitment hash malformed");
+ }
+ if (0 != strcmp (args[1],
+ "reveal"))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_OPERATION_INVALID,
+ "expected 'reveal' operation");
+ }
res = TALER_MHD_parse_json_data (connection,
root,
spec);
- json_decref (root);
if (GNUNET_OK != res)
{
GNUNET_break_op (0);
diff --git a/src/exchange/taler-exchange-httpd_refresh_reveal.h b/src/exchange/taler-exchange-httpd_refresh_reveal.h
index 0b0c29b76..afc9adce5 100644
--- a/src/exchange/taler-exchange-httpd_refresh_reveal.h
+++ b/src/exchange/taler-exchange-httpd_refresh_reveal.h
@@ -29,26 +29,25 @@
/**
- * Handle a "/refresh/reveal" request. This time, the client reveals the
+ * Handle a "/refreshes/$RCH/reveal" request. This time, the client reveals the
* private transfer keys except for the cut-and-choose value returned from
- * "/refresh/melt". This function parses the revealed keys and secrets and
+ * "/coins/$COIN_PUB/melt". This function parses the revealed keys and secrets and
* ultimately passes everything to #resolve_refresh_reveal_denominations()
* which will verify that the revealed information is valid then runs the
* transaction in #refresh_reveal_transaction() and finally returns the signed
* refreshed coins.
*
* @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param coin_pub public key of the coin
+ * @param root uploaded JSON data
+ * @param args array of additional options (length: 2, session hash and the string "reveal")
* @return MHD result code
- */
+ */
int
-TEH_REFRESH_handler_refresh_reveal (struct TEH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
+TEH_REFRESH_handler_reveal (const struct TEH_RequestHandler *rh,
+ struct MHD_Connection *connection,
+ const json_t *root,
+ const char *const args[2]);
+
#endif
diff --git a/src/exchange/taler-exchange-httpd_refund.c b/src/exchange/taler-exchange-httpd_refund.c
index 8e24b9b47..e7e34e0ba 100644
--- a/src/exchange/taler-exchange-httpd_refund.c
+++ b/src/exchange/taler-exchange-httpd_refund.c
@@ -532,27 +532,21 @@ verify_and_execute_refund (struct MHD_Connection *connection,
/**
- * Handle a "/refund" request. Parses the JSON, and, if successful,
- * passes the JSON data to #verify_and_execute_refund() to
- * further check the details of the operation specified. If
- * everything checks out, this will ultimately lead to the "/refund"
- * being executed, or rejected.
+ * Handle a "/coins/$COIN_PUB/refund" request. Parses the JSON, and, if
+ * successful, passes the JSON data to #verify_and_execute_refund() to further
+ * check the details of the operation specified. If everything checks out,
+ * this will ultimately lead to the refund being executed, or rejected.
*
- * @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param coin_pub public key of the coin
+ * @param root uploaded JSON data
* @return MHD result code
*/
int
-TEH_REFUND_handler_refund (struct TEH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+TEH_REFUND_handler_refund (struct MHD_Connection *connection,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const json_t *root)
{
- json_t *json;
int res;
struct TALER_EXCHANGEDB_Refund refund;
struct GNUNET_JSON_Specification spec[] = {
@@ -560,7 +554,6 @@ TEH_REFUND_handler_refund (struct TEH_RequestHandler *rh,
TALER_JSON_spec_amount ("refund_fee", &refund.details.refund_fee),
GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
&refund.details.h_contract_terms),
- GNUNET_JSON_spec_fixed_auto ("coin_pub", &refund.coin.coin_pub),
GNUNET_JSON_spec_fixed_auto ("merchant_pub", &refund.details.merchant_pub),
GNUNET_JSON_spec_uint64 ("rtransaction_id",
&refund.details.rtransaction_id),
@@ -568,20 +561,10 @@ TEH_REFUND_handler_refund (struct TEH_RequestHandler *rh,
GNUNET_JSON_spec_end ()
};
- (void) rh;
- res = TALER_MHD_parse_post_json (connection,
- connection_cls,
- upload_data,
- upload_data_size,
- &json);
- if (GNUNET_SYSERR == res)
- return MHD_NO;
- if ( (GNUNET_NO == res) || (NULL == json) )
- return MHD_YES;
+ refund.coin.coin_pub = *coin_pub;
res = TALER_MHD_parse_json_data (connection,
- json,
+ root,
spec);
- json_decref (json);
if (GNUNET_SYSERR == res)
return MHD_NO; /* hard failure */
if (GNUNET_NO == res)
diff --git a/src/exchange/taler-exchange-httpd_refund.h b/src/exchange/taler-exchange-httpd_refund.h
index 4f2b868e8..b79419f16 100644
--- a/src/exchange/taler-exchange-httpd_refund.h
+++ b/src/exchange/taler-exchange-httpd_refund.h
@@ -29,24 +29,19 @@
/**
- * Handle a "/refund" request. Parses the JSON, and, if successful,
- * passes the JSON data to #verify_and_execute_refund() to
- * further check the details of the operation specified. If
- * everything checks out, this will ultimately lead to the "/refund"
- * being executed, or rejected.
+ * Handle a "/coins/$COIN_PUB/refund" request. Parses the JSON, and, if
+ * successful, passes the JSON data to #verify_and_execute_refund() to further
+ * check the details of the operation specified. If everything checks out,
+ * this will ultimately lead to the refund being executed, or rejected.
*
- * @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param coin_pub public key of the coin
+ * @param root uploaded JSON data
* @return MHD result code
*/
int
-TEH_REFUND_handler_refund (struct TEH_RequestHandler *rh,
- struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
+TEH_REFUND_handler_refund (struct MHD_Connection *connection,
+ const struct TALER_CoinSpendPublicKeyP *coin_pub,
+ const json_t *root);
#endif
diff --git a/src/exchange/taler-exchange-httpd_reserve_status.c b/src/exchange/taler-exchange-httpd_reserve_status.c
index e2d35aaec..251271254 100644
--- a/src/exchange/taler-exchange-httpd_reserve_status.c
+++ b/src/exchange/taler-exchange-httpd_reserve_status.c
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2017 Taler Systems SA
+ Copyright (C) 2014-2020 Taler Systems SA
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
@@ -15,7 +15,7 @@
*/
/**
* @file taler-exchange-httpd_reserve_status.c
- * @brief Handle /reserve/status requests
+ * @brief Handle /reserves/$RESERVE_PUB GET requests
* @author Florian Dold
* @author Benedikt Mueller
* @author Christian Grothoff
@@ -114,42 +114,37 @@ reserve_status_transaction (void *cls,
/**
- * Handle a "/reserve/status" request. Parses the
- * given "reserve_pub" argument (which should contain the
+ * 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
* status of the reserve.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (length: 1, just the reserve_pub)
* @return MHD result code
*/
int
-TEH_RESERVE_handler_reserve_status (struct TEH_RequestHandler *rh,
+TEH_RESERVE_handler_reserve_status (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+ const char *const args[1])
{
struct ReserveStatusContext rsc;
- int res;
int mhd_ret;
(void) rh;
- (void) connection_cls;
- (void) upload_data;
- (void) upload_data_size;
- res = TALER_MHD_parse_request_arg_data (connection,
- "reserve_pub",
- &rsc.reserve_pub,
- sizeof (struct
- TALER_ReservePublicKeyP));
- if (GNUNET_SYSERR == res)
- return MHD_NO; /* internal error */
- if (GNUNET_NO == res)
- return MHD_YES; /* parse error */
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (args[0],
+ strlen (args[0]),
+ &rsc.reserve_pub,
+ sizeof (rsc.reserve_pub)))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_RESERVES_INVALID_RESERVE_PUB,
+ "reserve public key malformed");
+ }
rsc.rh = NULL;
if (GNUNET_OK !=
TEH_DB_run_transaction (connection,
diff --git a/src/exchange/taler-exchange-httpd_reserve_status.h b/src/exchange/taler-exchange-httpd_reserve_status.h
index 67eba2309..584bd3dcb 100644
--- a/src/exchange/taler-exchange-httpd_reserve_status.h
+++ b/src/exchange/taler-exchange-httpd_reserve_status.h
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2017 Taler Systems SA
+ Copyright (C) 2014-2020 Taler Systems SA
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
@@ -15,7 +15,7 @@
*/
/**
* @file taler-exchange-httpd_reserve_status.h
- * @brief Handle /reserve/status requests
+ * @brief Handle /reserves/$RESERVE_PUB GET requests
* @author Florian Dold
* @author Benedikt Mueller
* @author Christian Grothoff
@@ -26,24 +26,21 @@
#include <microhttpd.h>
#include "taler-exchange-httpd.h"
+
/**
- * Handle a "/reserve/status" request. Parses the
- * given "reserve_pub" argument (which should contain the
+ * 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
* status of the reserve.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (length: 1, just the reserve_pub)
* @return MHD result code
- */
+ */
int
-TEH_RESERVE_handler_reserve_status (struct TEH_RequestHandler *rh,
+TEH_RESERVE_handler_reserve_status (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
+ const char *const args[1]);
#endif
diff --git a/src/exchange/taler-exchange-httpd_reserve_withdraw.c b/src/exchange/taler-exchange-httpd_reserve_withdraw.c
index 9daad0a02..25747eff0 100644
--- a/src/exchange/taler-exchange-httpd_reserve_withdraw.c
+++ b/src/exchange/taler-exchange-httpd_reserve_withdraw.c
@@ -335,30 +335,27 @@ withdraw_transaction (void *cls,
/**
- * Handle a "/reserve/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
- * withdrawl operation.
+ * 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 withdrawl operation.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @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
*/
int
-TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh,
+TEH_RESERVE_handler_reserve_withdraw (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+ const json_t *root,
+ const char *const args[2])
{
struct WithdrawContext wc;
- json_t *root;
int res;
int mhd_ret;
unsigned int hc;
@@ -369,8 +366,6 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh,
GNUNET_JSON_spec_varsize ("coin_ev",
(void **) &wc.blinded_msg,
&wc.blinded_msg_len),
- GNUNET_JSON_spec_fixed_auto ("reserve_pub",
- &wc.wsrd.reserve_pub),
GNUNET_JSON_spec_fixed_auto ("reserve_sig",
&wc.signature),
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
@@ -379,19 +374,22 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh,
};
(void) rh;
- res = TALER_MHD_parse_post_json (connection,
- connection_cls,
- upload_data,
- upload_data_size,
- &root);
- if (GNUNET_SYSERR == res)
- return MHD_NO;
- if ( (GNUNET_NO == res) || (NULL == root) )
- return MHD_YES;
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (args[0],
+ strlen (args[0]),
+ &wc.wsrd.reserve_pub,
+ sizeof (wc.wsrd.reserve_pub)))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_RESERVES_INVALID_RESERVE_PUB,
+ "reserve public key malformed");
+ }
+
res = TALER_MHD_parse_json_data (connection,
root,
spec);
- json_decref (root);
if (GNUNET_OK != res)
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
wc.key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());
diff --git a/src/exchange/taler-exchange-httpd_reserve_withdraw.h b/src/exchange/taler-exchange-httpd_reserve_withdraw.h
index 67b4cad0a..c3e56eaaf 100644
--- a/src/exchange/taler-exchange-httpd_reserve_withdraw.h
+++ b/src/exchange/taler-exchange-httpd_reserve_withdraw.h
@@ -1,6 +1,6 @@
/*
This file is part of TALER
- Copyright (C) 2014-2017 Taler Systems SA
+ Copyright (C) 2014-2020 Taler Systems SA
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
@@ -28,26 +28,24 @@
/**
- * Handle a "/reserve/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 withdrawl
- * request from the specified reserve. If so, the envelope
- * with the blinded coin "coin_ev" is passed down to execute the
- * withdrawl operation.
+ * 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 withdrawl request from the
+ * specified reserve. If so, the envelope with the blinded coin "coin_ev" is
+ * passed down to execute the withdrawl operation.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @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
*/
int
-TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh,
+TEH_RESERVE_handler_reserve_withdraw (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
+ const json_t *root,
+ const char *const args[2]);
#endif
diff --git a/src/exchange/taler-exchange-httpd_terms.c b/src/exchange/taler-exchange-httpd_terms.c
index 47905f601..121e1c780 100644
--- a/src/exchange/taler-exchange-httpd_terms.c
+++ b/src/exchange/taler-exchange-httpd_terms.c
@@ -43,22 +43,16 @@ static struct TALER_MHD_Legal *pp;
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (must be empty for this function)
* @return MHD result code
*/
int
-TEH_handler_terms (struct TEH_RequestHandler *rh,
+TEH_handler_terms (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+ const char *const args[])
{
(void) rh;
- (void) upload_data;
- (void) upload_data_size;
- (void) connection_cls;
+ (void) args;
return TALER_MHD_reply_legal (connection,
tos);
}
@@ -69,22 +63,16 @@ TEH_handler_terms (struct TEH_RequestHandler *rh,
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (must be empty for this function)
* @return MHD result code
*/
int
-TEH_handler_privacy (struct TEH_RequestHandler *rh,
+TEH_handler_privacy (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+ const char *const args[])
{
(void) rh;
- (void) upload_data;
- (void) upload_data_size;
- (void) connection_cls;
+ (void) args;
return TALER_MHD_reply_legal (connection,
pp);
}
diff --git a/src/exchange/taler-exchange-httpd_terms.h b/src/exchange/taler-exchange-httpd_terms.h
index 75909df9a..7fe7774ad 100644
--- a/src/exchange/taler-exchange-httpd_terms.h
+++ b/src/exchange/taler-exchange-httpd_terms.h
@@ -34,34 +34,27 @@
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (must be empty for this function)
* @return MHD result code
*/
int
-TEH_handler_terms (struct TEH_RequestHandler *rh,
+TEH_handler_terms (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
+ const char *const args[]);
+
/**
* Handle a "/privacy" request.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (must be empty for this function)
* @return MHD result code
*/
int
-TEH_handler_privacy (struct TEH_RequestHandler *rh,
+TEH_handler_privacy (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
+ const char *const args[]);
/**
diff --git a/src/exchange/taler-exchange-httpd_track_transaction.c b/src/exchange/taler-exchange-httpd_track_transaction.c
index e8143213a..d0f1d0aa3 100644
--- a/src/exchange/taler-exchange-httpd_track_transaction.c
+++ b/src/exchange/taler-exchange-httpd_track_transaction.c
@@ -336,62 +336,86 @@ check_and_handle_track_transaction_request (struct MHD_Connection *connection,
/**
- * Handle a "/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[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (length: 4, contains:
+ * h_wire, merchant_pub, h_contract_terms and coin_pub)
* @return MHD result code
- */
+ */
int
-TEH_TRACKING_handler_track_transaction (struct TEH_RequestHandler *rh,
+TEH_TRACKING_handler_track_transaction (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+ const char *const args[4])
{
int res;
- json_t *json;
struct TALER_DepositTrackPS tps;
struct TALER_MerchantSignatureP merchant_sig;
- struct GNUNET_JSON_Specification spec[] = {
- GNUNET_JSON_spec_fixed_auto ("h_wire", &tps.h_wire),
- GNUNET_JSON_spec_fixed_auto ("h_contract_terms", &tps.h_contract_terms),
- GNUNET_JSON_spec_fixed_auto ("coin_pub", &tps.coin_pub),
- GNUNET_JSON_spec_fixed_auto ("merchant_pub", &tps.merchant),
- GNUNET_JSON_spec_fixed_auto ("merchant_sig", &merchant_sig),
- GNUNET_JSON_spec_end ()
- };
-
- (void) rh;
- res = TALER_MHD_parse_post_json (connection,
- connection_cls,
- upload_data,
- upload_data_size,
- &json);
- if (GNUNET_SYSERR == res)
- return MHD_NO;
- if ( (GNUNET_NO == res) || (NULL == json) )
- return MHD_YES;
- res = TALER_MHD_parse_json_data (connection,
- json,
- spec);
- if (GNUNET_OK != res)
+
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (args[0],
+ strlen (args[0]),
+ &tps.h_wire,
+ sizeof (tps.h_wire)))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_DEPOSITS_INVALID_H_WIRE,
+ "wire hash malformed");
+ }
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (args[1],
+ strlen (args[1]),
+ &tps.merchant,
+ sizeof (tps.merchant)))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_DEPOSITS_INVALID_MERCHANT_PUB,
+ "merchant public key malformed");
+ }
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (args[2],
+ strlen (args[2]),
+ &tps.h_contract_terms,
+ sizeof (tps.h_contract_terms)))
{
- json_decref (json);
- return (GNUNET_NO == res) ? MHD_YES : MHD_NO;
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_DEPOSITS_INVALID_H_CONTRACT_TERMS,
+ "contract terms hash malformed");
}
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (args[3],
+ strlen (args[3]),
+ &tps.coin_pub,
+ sizeof (tps.coin_pub)))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_DEPOSITS_INVALID_COIN_PUB,
+ "coin public key malformed");
+ }
+ res = TALER_MHD_parse_request_arg_data (connection,
+ "merchant_sig",
+ &merchant_sig,
+ sizeof (merchant_sig));
+ if (GNUNET_SYSERR == res)
+ return MHD_NO; /* internal error */
+ if (GNUNET_NO == res)
+ return MHD_YES; /* parse error */
tps.purpose.size = htonl (sizeof (struct TALER_DepositTrackPS));
tps.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION);
- res = check_and_handle_track_transaction_request (connection,
- &tps,
- &tps.merchant,
- &merchant_sig);
- GNUNET_JSON_parse_free (spec);
- json_decref (json);
- return res;
+ return check_and_handle_track_transaction_request (connection,
+ &tps,
+ &tps.merchant,
+ &merchant_sig);
}
diff --git a/src/exchange/taler-exchange-httpd_track_transaction.h b/src/exchange/taler-exchange-httpd_track_transaction.h
index 929ee638e..5f54754f3 100644
--- a/src/exchange/taler-exchange-httpd_track_transaction.h
+++ b/src/exchange/taler-exchange-httpd_track_transaction.h
@@ -27,21 +27,19 @@
/**
- * Handle a "/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[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (length: 4, contains:
+ * h_wire, merchant_pub, h_contract_terms and coin_pub)
* @return MHD result code
*/
int
-TEH_TRACKING_handler_track_transaction (struct TEH_RequestHandler *rh,
+TEH_TRACKING_handler_track_transaction (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
+ const char *const args[4]);
#endif
diff --git a/src/exchange/taler-exchange-httpd_track_transfer.c b/src/exchange/taler-exchange-httpd_track_transfer.c
index 1a780c063..cff6045ef 100644
--- a/src/exchange/taler-exchange-httpd_track_transfer.c
+++ b/src/exchange/taler-exchange-httpd_track_transfer.c
@@ -482,40 +482,37 @@ free_ctx (struct WtidTransactionContext *ctx)
/**
- * Handle a "/track/transfer" request.
+ * Handle a GET "/transfers/$WTID" request.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (length: 1, just the wtid)
* @return MHD result code
*/
int
-TEH_TRACKING_handler_track_transfer (struct TEH_RequestHandler *rh,
+TEH_TRACKING_handler_track_transfer (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+ const char *const args[1])
{
struct WtidTransactionContext ctx;
- int res;
int mhd_ret;
(void) rh;
- (void) connection_cls;
- (void) upload_data;
- (void) upload_data_size;
- memset (&ctx, 0, sizeof (ctx));
- res = TALER_MHD_parse_request_arg_data (connection,
- "wtid",
- &ctx.wtid,
- sizeof (struct
- TALER_WireTransferIdentifierRawP));
- if (GNUNET_SYSERR == res)
- return MHD_NO; /* internal error */
- if (GNUNET_NO == res)
- return MHD_YES; /* parse error */
+ memset (&ctx,
+ 0,
+ sizeof (ctx));
+ if (GNUNET_OK !=
+ GNUNET_STRINGS_string_to_data (args[0],
+ strlen (args[0]),
+ &ctx.wtid,
+ sizeof (ctx.wtid)))
+ {
+ GNUNET_break_op (0);
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_BAD_REQUEST,
+ TALER_EC_TRANSFERS_INVALID_WTID,
+ "wire transfer identifier malformed");
+ }
if (GNUNET_OK !=
TEH_DB_run_transaction (connection,
"run track transfer",
diff --git a/src/exchange/taler-exchange-httpd_track_transfer.h b/src/exchange/taler-exchange-httpd_track_transfer.h
index c68cb288a..c6bd7c5d2 100644
--- a/src/exchange/taler-exchange-httpd_track_transfer.h
+++ b/src/exchange/taler-exchange-httpd_track_transfer.h
@@ -27,20 +27,17 @@
/**
- * Handle a "/track/transfer" request.
+ * Handle a GET "/transfers/$WTID" request.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (length: 1, just the wtid)
* @return MHD result code
*/
int
-TEH_TRACKING_handler_track_transfer (struct TEH_RequestHandler *rh,
+TEH_TRACKING_handler_track_transfer (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
+ const char *const args[1]);
+
#endif
diff --git a/src/exchange/taler-exchange-httpd_validation.c b/src/exchange/taler-exchange-httpd_validation.c
index e3dd8e86e..e55100e14 100644
--- a/src/exchange/taler-exchange-httpd_validation.c
+++ b/src/exchange/taler-exchange-httpd_validation.c
@@ -25,7 +25,6 @@
#include "taler-exchange-httpd_validation.h"
#include "taler-exchange-httpd_wire.h"
#include "taler_exchangedb_lib.h"
-#include "taler_json_lib.h"
/**
diff --git a/src/exchange/taler-exchange-httpd_wire.c b/src/exchange/taler-exchange-httpd_wire.c
index e4bcbec5a..de4e2db4d 100644
--- a/src/exchange/taler-exchange-httpd_wire.c
+++ b/src/exchange/taler-exchange-httpd_wire.c
@@ -124,22 +124,16 @@ TEH_WIRE_get_fees (const char *method)
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (must be empty for this function)
* @return MHD result code
*/
int
-TEH_WIRE_handler_wire (struct TEH_RequestHandler *rh,
+TEH_WIRE_handler_wire (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size)
+ const char *const args[])
{
(void) rh;
- (void) connection_cls;
- (void) upload_data;
- (void) upload_data_size;
+ (void) args;
GNUNET_assert (NULL != wire_methods);
return TALER_MHD_reply_json (connection,
wire_methods,
diff --git a/src/exchange/taler-exchange-httpd_wire.h b/src/exchange/taler-exchange-httpd_wire.h
index 75c60353f..ac4ea39cc 100644
--- a/src/exchange/taler-exchange-httpd_wire.h
+++ b/src/exchange/taler-exchange-httpd_wire.h
@@ -51,17 +51,13 @@ TEH_WIRE_get_fees (const char *method);
*
* @param rh context of the handler
* @param connection the MHD connection to handle
- * @param[in,out] connection_cls the connection's closure (can be updated)
- * @param upload_data upload data
- * @param[in,out] upload_data_size number of bytes (left) in @a upload_data
+ * @param args array of additional options (must be empty for this function)
* @return MHD result code
- */
+ */
int
-TEH_WIRE_handler_wire (struct TEH_RequestHandler *rh,
+TEH_WIRE_handler_wire (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
- void **connection_cls,
- const char *upload_data,
- size_t *upload_data_size);
+ const char *const args[]);
#endif
diff --git a/src/include/taler_error_codes.h b/src/include/taler_error_codes.h
index 917ac36db..1c48fe333 100644
--- a/src/include/taler_error_codes.h
+++ b/src/include/taler_error_codes.h
@@ -86,6 +86,32 @@ enum TALER_ErrorCode
TALER_EC_METHOD_INVALID = 8,
/**
+ * Operation specified invalid for this URL (resulting in a "NOT
+ * FOUND" for the overall response).
+ */
+ TALER_EC_OPERATION_INVALID = 9,
+
+ /**
+ * There is no endpoint defined for the URL provided by the client
+ * (returned together with a MHD_HTTP_NOT FOUND status code).
+ */
+ TALER_EC_ENDPOINT_UNKNOWN = 10,
+
+ /**
+ * The URI is longer than the longest URI the HTTP server is willing
+ * to parse. Returned together with an HTTP status code of
+ * MHD_HTTP_URI_TOO_LONG.
+ */
+ TALER_EC_URI_TOO_LONG = 11,
+
+ /**
+ * The number of segments included in the URI does not match the
+ * number of segments expected by the endpoint. (returned together
+ * with a MHD_HTTP_NOT FOUND status code).
+ */
+ TALER_EC_WRONG_NUMBER_OF_SEGMENTS = 12,
+
+ /**
* The exchange failed to even just initialize its connection to the
* database. This response is provided with HTTP status code
* MHD_HTTP_INTERNAL_SERVER_ERROR.
@@ -182,6 +208,50 @@ enum TALER_ErrorCode
TALER_EC_DB_COIN_HISTORY_STORE_ERROR = 1014,
/**
+ * The public key of given to a /coins/ handler was malformed.
+ */
+ TALER_EC_COINS_INVALID_COIN_PUB = 1050,
+
+ /**
+ * The public key of given to a /reserves/ handler was malformed.
+ */
+ TALER_EC_RESERVES_INVALID_RESERVE_PUB = 1051,
+
+ /**
+ * The public key of given to a /transfers/ handler was malformed.
+ */
+ TALER_EC_TRANSFERS_INVALID_WTID = 1052,
+
+ /**
+ * The hash of the wire details of given to a /deposits/ handler was
+ * malformed.
+ */
+ TALER_EC_DEPOSITS_INVALID_H_WIRE = 1053,
+
+ /**
+ * The merchant public key given to a /deposits/ handler was
+ * malformed.
+ */
+ TALER_EC_DEPOSITS_INVALID_MERCHANT_PUB = 1054,
+
+ /**
+ * The hash of the contract given to a /deposits/ handler was
+ * malformed.
+ */
+ TALER_EC_DEPOSITS_INVALID_H_CONTRACT_TERMS = 1055,
+
+ /**
+ * The coin public key given to a /deposits/ handler was malformed.
+ */
+ TALER_EC_DEPOSITS_INVALID_COIN_PUB = 1056,
+
+ /**
+ * The hash of the refresh commitment given to a /refreshes/ handler
+ * was malformed.
+ */
+ TALER_EC_REFRESHES_INVALID_RCH = 1057,
+
+ /**
* The given reserve does not have sufficient funds to admit the
* requested withdraw operation at this time. The response includes
* the current "balance" of the reserve as well as the transaction