phase 1 of #6067: update exchange HTTPD to new API style

This commit is contained in:
Christian Grothoff 2020-02-26 17:00:41 +01:00
parent 30b24448c8
commit fb9324338d
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
32 changed files with 869 additions and 727 deletions

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER 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 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
@ -147,6 +147,92 @@ static unsigned long long req_count;
static unsigned long long req_max; 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 * Function called whenever MHD is done with a request. If the
* request was a POST, we may have stored a `struct Buffer *` in the * request was a POST, we may have stored a `struct Buffer *` in the
@ -205,6 +291,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. * Handle incoming HTTP request.
* *
@ -229,134 +429,111 @@ handle_mhd_request (void *cls,
void **con_cls) void **con_cls)
{ {
static struct TEH_RequestHandler handlers[] = { 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: disallow everything */
{ "/robots.txt", MHD_HTTP_METHOD_GET, "text/plain", {
"User-agent: *\nDisallow: /\n", 0, .url = "robots.txt",
&TEH_MHD_handler_static_response, MHD_HTTP_OK }, .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, /* AGPL licensing page, redirect to source. As per the AGPL-license,
every deployment is required to offer the user a download of the every deployment is required to offer the user a download of the
source. We make this easy by including a redirect to the source source. We make this easy by including a redirect to the source
here. */ here. */
{ "/agpl", MHD_HTTP_METHOD_GET, "text/plain", {
NULL, 0, .url = "agpl",
&TEH_MHD_handler_agpl_redirect, MHD_HTTP_FOUND }, .method = MHD_HTTP_METHOD_GET,
.handler.get = &TEH_MHD_handler_agpl_redirect
},
/* Terms of service */ /* Terms of service */
{ "/terms", MHD_HTTP_METHOD_GET, NULL, {
NULL, 0, .url = "terms",
&TEH_handler_terms, MHD_HTTP_OK }, .method = MHD_HTTP_METHOD_GET,
.handler.get = &TEH_handler_terms
},
/* Privacy policy */ /* Privacy policy */
{ "/privacy", MHD_HTTP_METHOD_GET, NULL, {
NULL, 0, .url = "privacy",
&TEH_handler_privacy, MHD_HTTP_OK }, .method = MHD_HTTP_METHOD_GET,
.handler.get = &TEH_handler_privacy
},
/* Return key material and fundamental properties for this exchange */ /* Return key material and fundamental properties for this exchange */
{ "/keys", MHD_HTTP_METHOD_GET, "application/json", {
NULL, 0, .url = "/keys",
&TEH_KS_handler_keys, MHD_HTTP_OK }, .method = MHD_HTTP_METHOD_GET,
{ "/keys", NULL, "text/plain", .handler.get = &TEH_KS_handler_keys,
"Only GET is allowed", 0, },
&TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
/* Requests for wiring information */ /* Requests for wiring information */
{ "/wire", MHD_HTTP_METHOD_GET, "application/json", {
NULL, 0, .url = "wire",
&TEH_WIRE_handler_wire, MHD_HTTP_OK }, .method = MHD_HTTP_METHOD_GET,
{ "/wire", NULL, "text/plain", .handler.get = &TEH_WIRE_handler_wire
"Only GET is allowed", 0, },
&TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
/* Withdrawing coins / interaction with reserves */ /* Withdrawing coins / interaction with reserves */
{ "/reserve/status", MHD_HTTP_METHOD_GET, "application/json", {
NULL, 0, .url = "reserves",
&TEH_RESERVE_handler_reserve_status, MHD_HTTP_OK }, .method = MHD_HTTP_METHOD_GET,
{ "/reserve/status", NULL, "text/plain", .handler.get = &TEH_RESERVE_handler_reserve_status,
"Only GET is allowed", 0, .nargs = 1
&TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, },
{
{ "/reserve/withdraw", MHD_HTTP_METHOD_POST, "application/json", .url = "reserves",
NULL, 0, .method = MHD_HTTP_METHOD_POST,
&TEH_RESERVE_handler_reserve_withdraw, MHD_HTTP_OK }, .handler.post = &TEH_RESERVE_handler_reserve_withdraw,
{ "/reserve/withdraw", NULL, "text/plain", .nargs = 2
"Only POST is allowed", 0, },
&TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, /* coins */
{
/* Depositing coins */ .url = "coins",
{ "/deposit", MHD_HTTP_METHOD_POST, "application/json", .method = MHD_HTTP_METHOD_POST,
NULL, 0, .handler.post = &handle_post_coins,
&TEH_DEPOSIT_handler_deposit, MHD_HTTP_OK }, .nargs = 2
{ "/deposit", NULL, "text/plain", },
"Only POST is allowed", 0, {
&TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, .url = "coins",
.method = MHD_HTTP_METHOD_GET,
/* Refunding coins */ .handler.get = TEH_REFRESH_handler_link,
{ "/refund", MHD_HTTP_METHOD_POST, "application/json", .nargs = 2,
NULL, 0, },
&TEH_REFUND_handler_refund, MHD_HTTP_OK }, /* refreshing */
{ "/refund", NULL, "text/plain", {
"Only POST is allowed", 0, .url = "refreshes",
&TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, .method = MHD_HTTP_METHOD_POST,
.handler.post = &TEH_REFRESH_handler_reveal,
/* Dealing with change */ .nargs = 2
{ "/refresh/melt", MHD_HTTP_METHOD_POST, "application/json", },
NULL, 0, /* tracking transfers */
&TEH_REFRESH_handler_refresh_melt, MHD_HTTP_OK }, {
{ "/refresh/melt", NULL, "text/plain", .url = "transfers",
"Only POST is allowed", 0, .method = MHD_HTTP_METHOD_GET,
&TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, .handler.get = &TEH_TRACKING_handler_track_transfer,
.nargs = 1
{ "/refresh/reveal", MHD_HTTP_METHOD_POST, "application/json", },
NULL, 0, /* tracking deposits */
&TEH_REFRESH_handler_refresh_reveal, MHD_HTTP_OK }, {
{ "/refresh/reveal", NULL, "text/plain", .url = "deposits",
"Only POST is allowed", 0, .method = MHD_HTTP_METHOD_GET,
&TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED }, .handler.get = &TEH_TRACKING_handler_track_transaction,
.nargs = 4
{ "/refresh/reveal", MHD_HTTP_METHOD_POST, "application/json", },
NULL, 0, /* mark end of list */
&TEH_REFRESH_handler_refresh_reveal, MHD_HTTP_OK }, {
{ "/refresh/reveal", NULL, "text/plain", .url = NULL
"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
}; };
struct ExchangeHttpRequestClosure *ecls = *con_cls; struct ExchangeHttpRequestClosure *ecls = *con_cls;
int ret;
void **inner_cls; void **inner_cls;
struct GNUNET_AsyncScopeSave old_scope; struct GNUNET_AsyncScopeSave old_scope;
const char *correlation_id = NULL; const char *correlation_id = NULL;
@ -367,7 +544,8 @@ handle_mhd_request (void *cls,
{ {
unsigned long long cnt; 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); cnt = __sync_add_and_fetch (&req_count, 1LLU);
if (req_max == cnt) if (req_max == cnt)
{ {
@ -395,7 +573,8 @@ handle_mhd_request (void *cls,
} }
inner_cls = &ecls->opaque_post_parsing_context; 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) if (NULL != correlation_id)
GNUNET_log (GNUNET_ERROR_TYPE_INFO, GNUNET_log (GNUNET_ERROR_TYPE_INFO,
"Handling request (%s) for URL '%s', correlation_id=%s\n", "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 */ /* on repeated requests, check our cache first */
if (NULL != ecls->rh) if (NULL != ecls->rh)
{ {
ret = ecls->rh->handler (ecls->rh, int ret;
connection,
inner_cls, ret = proceed_with_handler (ecls->rh,
upload_data, connection,
upload_data_size); url,
inner_cls,
upload_data,
upload_data_size);
GNUNET_async_scope_restore (&old_scope); GNUNET_async_scope_restore (&old_scope);
return ret; return ret;
} }
if (0 == strcasecmp (method, if (0 == strcasecmp (method,
MHD_HTTP_METHOD_HEAD)) MHD_HTTP_METHOD_HEAD))
method = MHD_HTTP_METHOD_GET; /* treat HEAD as GET here, MHD will do the rest */ 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++)
/* parse first part of URL */
{ {
struct TEH_RequestHandler *rh = &handlers[i]; int found = GNUNET_NO;
size_t tok_size;
const char *tok;
const char *rest;
if (0 != strcmp (url, rh->url)) if ('\0' == url[0])
continue; /* strange, should start with '/', treat as just "/" */
url = "/";
/* The URL is a match! What we now do depends on the method. */ tok = url + 1;
if (0 == strcasecmp (method, MHD_HTTP_METHOD_OPTIONS)) rest = strchr (tok, '/');
if (NULL == rest)
{ {
GNUNET_async_scope_restore (&old_scope); tok_size = 0;
return TALER_MHD_reply_cors_preflight (connection); }
else
{
tok_size = rest - tok;
rest++; /* skip over '/' */
}
for (unsigned int i = 0; NULL != handlers[i].url; i++)
{
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) || if (GNUNET_YES == found)
(0 == strcasecmp (method,
rh->method)) )
{ {
/* cache to avoid the loop next time */ /* we found a matching address, but the method is wrong */
ecls->rh = rh; GNUNET_break_op (0);
/* run handler */ return TALER_MHD_reply_with_error (connection,
ret = rh->handler (rh, MHD_HTTP_METHOD_NOT_ALLOWED,
connection, TALER_EC_METHOD_INVALID,
inner_cls, "The HTTP method used is invalid for this URL");
upload_data,
upload_data_size);
GNUNET_async_scope_restore (&old_scope);
return ret;
} }
} }
/* No handler matches, generate not found */ /* No handler matches, generate not found */
ret = TEH_MHD_handler_static_response (&h404, {
connection, int ret;
inner_cls,
upload_data, ret = TALER_MHD_reply_with_error (connection,
upload_data_size); MHD_HTTP_NOT_FOUND,
GNUNET_async_scope_restore (&old_scope); TALER_EC_ENDPOINT_UNKNOWN,
return ret; "No handler found for the given URL");
GNUNET_async_scope_restore (&old_scope);
return ret;
}
} }

View File

@ -24,6 +24,8 @@
#define TALER_EXCHANGE_HTTPD_H #define TALER_EXCHANGE_HTTPD_H
#include <microhttpd.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; const char *url;
/** /**
* Method the handler is for, NULL for "all". * Method the handler is for.
*/ */
const char *method; 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). * Mime type to use in reply (hint, can be NULL).
*/ */
const char *mime_type; 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; 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; size_t data_size;
/** /**
* Function to call to handle the request. * Default response code. 0 for none provided.
*
* @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, unsigned int response_code;
struct MHD_Connection *connection,
void **connection_cls,
const char *upload_data,
size_t *upload_data_size);
/**
* Default response code.
*/
int response_code;
}; };

View File

@ -381,27 +381,22 @@ check_timestamp_current (struct GNUNET_TIME_Absolute ts)
/** /**
* Handle a "/deposit" request. Parses the JSON, and, if successful, * Handle a "/coins/$COIN_PUB/deposit" request. Parses the JSON, and, if
* passes the JSON data to #verify_and_execute_deposit() to further * successful, passes the JSON data to #verify_and_execute_deposit() to
* check the details of the operation specified. If everything checks * further check the details of the operation specified. If everything checks
* out, this will ultimately lead to the "/deposit" being executed, or * out, this will ultimately lead to the "/deposit" being executed, or
* rejected. * rejected.
* *
* @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param coin_pub public key of the coin
* @param upload_data upload data * @param root uploaded JSON data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, TEH_DEPOSIT_handler_deposit (struct MHD_Connection *connection,
struct MHD_Connection *connection, const struct TALER_CoinSpendPublicKeyP *coin_pub,
void **connection_cls, const json_t *root)
const char *upload_data,
size_t *upload_data_size)
{ {
json_t *json;
int res; int res;
json_t *wire; json_t *wire;
enum TALER_ErrorCode ec; enum TALER_ErrorCode ec;
@ -415,7 +410,6 @@ TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh,
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash", GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
&deposit.coin.denom_pub_hash), &deposit.coin.denom_pub_hash),
TALER_JSON_spec_denomination_signature ("ub_sig", &deposit.coin.denom_sig), 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 ("merchant_pub", &deposit.merchant_pub),
GNUNET_JSON_spec_fixed_auto ("h_contract_terms", &deposit.h_contract_terms), GNUNET_JSON_spec_fixed_auto ("h_contract_terms", &deposit.h_contract_terms),
GNUNET_JSON_spec_fixed_auto ("h_wire", &deposit.h_wire), 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 () 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, memset (&deposit,
0, 0,
sizeof (deposit)); sizeof (deposit));
deposit.coin.coin_pub = *coin_pub;
res = TALER_MHD_parse_json_data (connection, res = TALER_MHD_parse_json_data (connection,
json, root,
spec); spec);
json_decref (json);
if (GNUNET_SYSERR == res) if (GNUNET_SYSERR == res)
{ {
GNUNET_break (0); GNUNET_break (0);

View File

@ -29,22 +29,21 @@
/** /**
* Handle a "/deposit" request. Parses the JSON, and, if successful, * Handle a "/coins/$COIN_PUB/deposit" request. Parses the JSON, and, if
* checks the signatures. If everything checks out, this will * successful, passes the JSON data to #verify_and_execute_deposit() to
* ultimately lead to the "/deposit" being executed, or rejected. * 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 connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param coin_pub public key of the coin
* @param upload_data upload data * @param root uploaded JSON data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_DEPOSIT_handler_deposit (struct TEH_RequestHandler *rh, TEH_DEPOSIT_handler_deposit (struct MHD_Connection *connection,
struct MHD_Connection *connection, const struct TALER_CoinSpendPublicKeyP *coin_pub,
void **connection_cls, const json_t *root);
const char *upload_data,
size_t *upload_data_size);
#endif #endif

View File

@ -2381,17 +2381,13 @@ krd_search_comparator (const void *key,
* *
* @param rh context of the handler * @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (must be empty for this function)
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_KS_handler_keys (struct TEH_RequestHandler *rh, TEH_KS_handler_keys (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[])
const char *upload_data,
size_t *upload_data_size)
{ {
int ret; int ret;
const char *have_cherrypick; const char *have_cherrypick;
@ -2400,9 +2396,8 @@ TEH_KS_handler_keys (struct TEH_RequestHandler *rh,
struct GNUNET_TIME_Absolute now; struct GNUNET_TIME_Absolute now;
const struct KeysResponseData *krd; const struct KeysResponseData *krd;
(void) connection_cls; (void) rh;
(void) upload_data; (void) args;
(void) upload_data_size;
have_cherrypick = MHD_lookup_connection_value (connection, have_cherrypick = MHD_lookup_connection_value (connection,
MHD_GET_ARGUMENT_KIND, MHD_GET_ARGUMENT_KIND,
"last_issue_date"); "last_issue_date");
@ -2493,7 +2488,7 @@ TEH_KS_handler_keys (struct TEH_RequestHandler *rh,
"no key response found"); "no key response found");
} }
ret = MHD_queue_response (connection, ret = MHD_queue_response (connection,
rh->response_code, MHD_HTTP_OK,
(MHD_YES == TALER_MHD_can_compress (connection)) (MHD_YES == TALER_MHD_can_compress (connection))
? krd->response_compressed ? krd->response_compressed
: krd->response_uncompressed); : krd->response_uncompressed);

View File

@ -188,17 +188,13 @@ TEH_KS_sign (const struct GNUNET_CRYPTO_EccSignaturePurpose *purpose,
* *
* @param rh context of the handler * @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (must be empty for this function)
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_KS_handler_keys (struct TEH_RequestHandler *rh, TEH_KS_handler_keys (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[]);
const char *upload_data,
size_t *upload_data_size);
#endif #endif

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER 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 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
@ -39,27 +39,23 @@
* *
* @param rh context of the handler * @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (must be empty for this function)
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_MHD_handler_static_response (struct TEH_RequestHandler *rh, TEH_MHD_handler_static_response (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[])
const char *upload_data,
size_t *upload_data_size)
{ {
struct MHD_Response *response; struct MHD_Response *response;
int ret; int ret;
size_t dlen;
(void) connection_cls; (void) args;
(void) upload_data; dlen = (0 == rh->data_size)
(void) upload_data_size; ? strlen ((const char *) rh->data)
if (0 == rh->data_size) : rh->data_size;
rh->data_size = strlen ((const char *) rh->data); response = MHD_create_response_from_buffer (dlen,
response = MHD_create_response_from_buffer (rh->data_size,
(void *) rh->data, (void *) rh->data,
MHD_RESPMEM_PERSISTENT); MHD_RESPMEM_PERSISTENT);
if (NULL == response) if (NULL == response)
@ -86,22 +82,16 @@ TEH_MHD_handler_static_response (struct TEH_RequestHandler *rh,
* *
* @param rh context of the handler * @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (must be empty for this function)
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_MHD_handler_agpl_redirect (struct TEH_RequestHandler *rh, TEH_MHD_handler_agpl_redirect (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[])
const char *upload_data,
size_t *upload_data_size)
{ {
(void) rh; (void) rh;
(void) connection_cls; (void) args;
(void) upload_data;
(void) upload_data_size;
return TALER_MHD_reply_agpl (connection, return TALER_MHD_reply_agpl (connection,
"http://www.git.taler.net/?p=exchange.git"); "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 rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (must be empty for this function)
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int 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, struct MHD_Connection *connection,
void **connection_cls, const char *const args[])
const char *upload_data,
size_t *upload_data_size)
{ {
(void) connection_cls; (void) args;
(void) upload_data;
(void) upload_data_size;
return TALER_MHD_reply_with_error (connection, return TALER_MHD_reply_with_error (connection,
rh->response_code, rh->response_code,
TALER_EC_METHOD_INVALID, TALER_EC_METHOD_INVALID,

View File

@ -1,6 +1,6 @@
/* /*
This file is part of TALER 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 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
@ -34,17 +34,13 @@
* *
* @param rh context of the handler * @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (must be empty for this function)
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_MHD_handler_static_response (struct TEH_RequestHandler *rh, TEH_MHD_handler_static_response (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[]);
const char *upload_data,
size_t *upload_data_size);
/** /**
@ -53,40 +49,13 @@ TEH_MHD_handler_static_response (struct TEH_RequestHandler *rh,
* *
* @param rh context of the handler * @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (must be empty for this function)
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_MHD_handler_agpl_redirect (struct TEH_RequestHandler *rh, TEH_MHD_handler_agpl_redirect (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[]);
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,
...);
/** /**
@ -95,17 +64,13 @@ TEH_MHD_helper_send_json_pack (struct TEH_RequestHandler *rh,
* *
* @param rh context of the handler * @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (must be empty for this function)
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int 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, struct MHD_Connection *connection,
void **connection_cls, const char *const args[]);
const char *upload_data,
size_t *upload_data_size);
#endif #endif

View File

@ -562,27 +562,21 @@ verify_and_execute_recoup (struct MHD_Connection *connection,
/** /**
* Handle a "/recoup" request. Parses the JSON, and, if successful, * Handle a "/coins/$COIN_PUB/recoup" request. Parses the JSON, and, if
* passes the JSON data to #verify_and_execute_recoup() to * successful, passes the JSON data to #verify_and_execute_recoup() to further
* further check the details of the operation specified. If * check the details of the operation specified. If everything checks out,
* everything checks out, this will ultimately lead to the "/refund" * this will ultimately lead to the refund being executed, or rejected.
* being executed, or rejected.
* *
* @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param coin_pub public key of the coin
* @param upload_data upload data * @param root uploaded JSON data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_RECOUP_handler_recoup (struct TEH_RequestHandler *rh, TEH_RECOUP_handler_recoup (struct MHD_Connection *connection,
struct MHD_Connection *connection, const struct TALER_CoinSpendPublicKeyP *coin_pub,
void **connection_cls, const json_t *root)
const char *upload_data,
size_t *upload_data_size)
{ {
json_t *json;
int res; int res;
struct TALER_CoinPublicInfo coin; struct TALER_CoinPublicInfo coin;
struct TALER_DenominationBlindingKeyP coin_bks; struct TALER_DenominationBlindingKeyP coin_bks;
@ -593,8 +587,6 @@ TEH_RECOUP_handler_recoup (struct TEH_RequestHandler *rh,
&coin.denom_pub_hash), &coin.denom_pub_hash),
TALER_JSON_spec_denomination_signature ("denom_sig", TALER_JSON_spec_denomination_signature ("denom_sig",
&coin.denom_sig), &coin.denom_sig),
GNUNET_JSON_spec_fixed_auto ("coin_pub",
&coin.coin_pub),
GNUNET_JSON_spec_fixed_auto ("coin_blind_key_secret", GNUNET_JSON_spec_fixed_auto ("coin_blind_key_secret",
&coin_bks), &coin_bks),
GNUNET_JSON_spec_fixed_auto ("coin_sig", GNUNET_JSON_spec_fixed_auto ("coin_sig",
@ -605,20 +597,10 @@ TEH_RECOUP_handler_recoup (struct TEH_RequestHandler *rh,
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
(void) rh; coin.coin_pub = *coin_pub;
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, res = TALER_MHD_parse_json_data (connection,
json, root,
spec); spec);
json_decref (json);
if (GNUNET_SYSERR == res) if (GNUNET_SYSERR == res)
return MHD_NO; /* hard failure */ return MHD_NO; /* hard failure */
if (GNUNET_NO == res) if (GNUNET_NO == res)

View File

@ -27,25 +27,20 @@
/** /**
* Handle a "/recoup" request. Parses the JSON, and, if successful, * Handle a "/coins/$COIN_PUB/recoup" request. Parses the JSON, and, if
* passes the JSON data to #verify_and_execute_recoup() to * successful, passes the JSON data to #verify_and_execute_recoup() to further
* further check the details of the operation specified. If * check the details of the operation specified. If everything checks out,
* everything checks out, this will ultimately lead to the "/refund" * this will ultimately lead to the refund being executed, or rejected.
* being executed, or rejected.
* *
* @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param coin_pub public key of the coin
* @param upload_data upload data * @param root uploaded JSON data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_RECOUP_handler_recoup (struct TEH_RequestHandler *rh, TEH_RECOUP_handler_recoup (struct MHD_Connection *connection,
struct MHD_Connection *connection, const struct TALER_CoinSpendPublicKeyP *coin_pub,
void **connection_cls, const json_t *root);
const char *upload_data,
size_t *upload_data_size);
#endif #endif

View File

@ -172,43 +172,37 @@ refresh_link_transaction (void *cls,
/** /**
* Handle a "/refresh/link" request. Note that for "/refresh/link" * Handle a "/coins/$COIN_PUB/link" request.
* we do use a simple HTTP GET, and a HTTP POST!
* *
* @param rh context of the handler * @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (length: 2, first is the coin_pub, second must be "link")
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_REFRESH_handler_refresh_link (struct TEH_RequestHandler *rh, TEH_REFRESH_handler_link (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[2])
const char *upload_data,
size_t *upload_data_size)
{ {
int mhd_ret;
int res;
struct HTD_Context ctx; struct HTD_Context ctx;
int mhd_ret;
(void) rh; (void) rh;
(void) connection_cls;
(void) upload_data;
(void) upload_data_size;
memset (&ctx, memset (&ctx,
0, 0,
sizeof (ctx)); sizeof (ctx));
res = TALER_MHD_parse_request_arg_data (connection, if (GNUNET_OK !=
"coin_pub", GNUNET_STRINGS_string_to_data (args[0],
&ctx.coin_pub, strlen (args[0]),
sizeof (struct &ctx.coin_pub,
TALER_CoinSpendPublicKeyP)); sizeof (ctx.coin_pub)))
if (GNUNET_SYSERR == res) {
return MHD_NO; GNUNET_break_op (0);
if (GNUNET_OK != res) return TALER_MHD_reply_with_error (connection,
return MHD_YES; MHD_HTTP_BAD_REQUEST,
TALER_EC_COINS_INVALID_COIN_PUB,
"coin public key malformed");
}
ctx.mlist = json_array (); ctx.mlist = json_array ();
if (GNUNET_OK != if (GNUNET_OK !=
TEH_DB_run_transaction (connection, TEH_DB_run_transaction (connection,

View File

@ -29,21 +29,17 @@
/** /**
* Handle a "/refresh/link" request * Handle a "/coins/$COIN_PUB/link" request.
* *
* @param rh context of the handler * @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (length: 2, first is the coin_pub, second must be "link")
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_REFRESH_handler_refresh_link (struct TEH_RequestHandler *rh, TEH_REFRESH_handler_link (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[2]);
const char *upload_data,
size_t *upload_data_size);
#endif #endif

View File

@ -577,31 +577,24 @@ check_for_denomination_key (struct MHD_Connection *connection,
/** /**
* Handle a "/refresh/melt" request. Parses the request into the JSON * Handle a "/coins/$COIN_PUB/melt" request. Parses the request into the JSON
* components and then hands things of to #check_for_denomination_key() * components and then hands things of to #check_for_denomination_key() to
* to validate the melted coins, the signature and execute the melt * validate the melted coins, the signature and execute the melt using
* using handle_refresh_melt(). * handle_refresh_melt().
*
* @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param coin_pub public key of the coin
* @param upload_data upload data * @param root uploaded JSON data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, TEH_REFRESH_handler_melt (struct MHD_Connection *connection,
struct MHD_Connection *connection, const struct TALER_CoinSpendPublicKeyP *coin_pub,
void **connection_cls, const json_t *root)
const char *upload_data,
size_t *upload_data_size)
{ {
json_t *root;
struct RefreshMeltContext rmc; struct RefreshMeltContext rmc;
int res; int res;
struct GNUNET_JSON_Specification spec[] = { 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", TALER_JSON_spec_denomination_signature ("denom_sig",
&rmc.refresh_session.coin.denom_sig), &rmc.refresh_session.coin.denom_sig),
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash", 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 () 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, memset (&rmc,
0, 0,
sizeof (rmc)); sizeof (rmc));
rmc.refresh_session.coin.coin_pub = *coin_pub;
res = TALER_MHD_parse_json_data (connection, res = TALER_MHD_parse_json_data (connection,
root, root,
spec); spec);
json_decref (root);
if (GNUNET_OK != res) if (GNUNET_OK != res)
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;

View File

@ -29,25 +29,20 @@
/** /**
* Handle a "/refresh/melt" request after the first parsing has * Handle a "/coins/$COIN_PUB/melt" request. Parses the request into the JSON
* happened. We now need to validate the coins being melted and the * components and then hands things of to #check_for_denomination_key() to
* session signature and then hand things of to execute the melt * validate the melted coins, the signature and execute the melt using
* operation. This function parses the JSON arrays and then passes * handle_refresh_melt().
* processing on to #refresh_melt_transaction().
*
* @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param coin_pub public key of the coin
* @param upload_data upload data * @param root uploaded JSON data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_REFRESH_handler_refresh_melt (struct TEH_RequestHandler *rh, TEH_REFRESH_handler_melt (struct MHD_Connection *connection,
struct MHD_Connection *connection, const struct TALER_CoinSpendPublicKeyP *coin_pub,
void **connection_cls, const json_t *root);
const char *upload_data,
size_t *upload_data_size);
#endif #endif

View File

@ -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 * 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() * ultimately passes everything to #resolve_refresh_reveal_denominations()
* which will verify that the revealed information is valid then runs the * which will verify that the revealed information is valid then runs the
* 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 rh context of the handler
* @param connection the MHD connection to handle * @param coin_pub public key of the coin
* @param[in,out] connection_cls the connection's closure (can be updated) * @param root uploaded JSON data
* @param upload_data upload data * @param args array of additional options (length: 2, session hash and the string "reveal")
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_REFRESH_handler_refresh_reveal (struct TEH_RequestHandler *rh, TEH_REFRESH_handler_reveal (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const json_t *root,
const char *upload_data, const char *const args[2])
size_t *upload_data_size)
{ {
int res; int res;
json_t *root;
json_t *coin_evs; json_t *coin_evs;
json_t *transfer_privs; json_t *transfer_privs;
json_t *link_sigs; json_t *link_sigs;
@ -924,24 +921,34 @@ TEH_REFRESH_handler_refresh_reveal (struct TEH_RequestHandler *rh,
}; };
(void) 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, memset (&rctx,
0, 0,
sizeof (rctx)); 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, res = TALER_MHD_parse_json_data (connection,
root, root,
spec); spec);
json_decref (root);
if (GNUNET_OK != res) if (GNUNET_OK != res)
{ {
GNUNET_break_op (0); GNUNET_break_op (0);

View File

@ -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 * 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() * ultimately passes everything to #resolve_refresh_reveal_denominations()
* which will verify that the revealed information is valid then runs the * which will verify that the revealed information is valid then runs the
* 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 rh context of the handler
* @param connection the MHD connection to handle * @param coin_pub public key of the coin
* @param[in,out] connection_cls the connection's closure (can be updated) * @param root uploaded JSON data
* @param upload_data upload data * @param args array of additional options (length: 2, session hash and the string "reveal")
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_REFRESH_handler_refresh_reveal (struct TEH_RequestHandler *rh, TEH_REFRESH_handler_reveal (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const json_t *root,
const char *upload_data, const char *const args[2]);
size_t *upload_data_size);
#endif #endif

View File

@ -532,27 +532,21 @@ verify_and_execute_refund (struct MHD_Connection *connection,
/** /**
* Handle a "/refund" request. Parses the JSON, and, if successful, * Handle a "/coins/$COIN_PUB/refund" request. Parses the JSON, and, if
* passes the JSON data to #verify_and_execute_refund() to * successful, passes the JSON data to #verify_and_execute_refund() to further
* further check the details of the operation specified. If * check the details of the operation specified. If everything checks out,
* everything checks out, this will ultimately lead to the "/refund" * this will ultimately lead to the refund being executed, or rejected.
* being executed, or rejected.
* *
* @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param coin_pub public key of the coin
* @param upload_data upload data * @param root uploaded JSON data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_REFUND_handler_refund (struct TEH_RequestHandler *rh, TEH_REFUND_handler_refund (struct MHD_Connection *connection,
struct MHD_Connection *connection, const struct TALER_CoinSpendPublicKeyP *coin_pub,
void **connection_cls, const json_t *root)
const char *upload_data,
size_t *upload_data_size)
{ {
json_t *json;
int res; int res;
struct TALER_EXCHANGEDB_Refund refund; struct TALER_EXCHANGEDB_Refund refund;
struct GNUNET_JSON_Specification spec[] = { 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), TALER_JSON_spec_amount ("refund_fee", &refund.details.refund_fee),
GNUNET_JSON_spec_fixed_auto ("h_contract_terms", GNUNET_JSON_spec_fixed_auto ("h_contract_terms",
&refund.details.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_fixed_auto ("merchant_pub", &refund.details.merchant_pub),
GNUNET_JSON_spec_uint64 ("rtransaction_id", GNUNET_JSON_spec_uint64 ("rtransaction_id",
&refund.details.rtransaction_id), &refund.details.rtransaction_id),
@ -568,20 +561,10 @@ TEH_REFUND_handler_refund (struct TEH_RequestHandler *rh,
GNUNET_JSON_spec_end () GNUNET_JSON_spec_end ()
}; };
(void) rh; refund.coin.coin_pub = *coin_pub;
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, res = TALER_MHD_parse_json_data (connection,
json, root,
spec); spec);
json_decref (json);
if (GNUNET_SYSERR == res) if (GNUNET_SYSERR == res)
return MHD_NO; /* hard failure */ return MHD_NO; /* hard failure */
if (GNUNET_NO == res) if (GNUNET_NO == res)

View File

@ -29,24 +29,19 @@
/** /**
* Handle a "/refund" request. Parses the JSON, and, if successful, * Handle a "/coins/$COIN_PUB/refund" request. Parses the JSON, and, if
* passes the JSON data to #verify_and_execute_refund() to * successful, passes the JSON data to #verify_and_execute_refund() to further
* further check the details of the operation specified. If * check the details of the operation specified. If everything checks out,
* everything checks out, this will ultimately lead to the "/refund" * this will ultimately lead to the refund being executed, or rejected.
* being executed, or rejected.
* *
* @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param coin_pub public key of the coin
* @param upload_data upload data * @param root uploaded JSON data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_REFUND_handler_refund (struct TEH_RequestHandler *rh, TEH_REFUND_handler_refund (struct MHD_Connection *connection,
struct MHD_Connection *connection, const struct TALER_CoinSpendPublicKeyP *coin_pub,
void **connection_cls, const json_t *root);
const char *upload_data,
size_t *upload_data_size);
#endif #endif

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-2020 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
@ -15,7 +15,7 @@
*/ */
/** /**
* @file taler-exchange-httpd_reserve_status.c * @file taler-exchange-httpd_reserve_status.c
* @brief Handle /reserve/status requests * @brief Handle /reserves/$RESERVE_PUB GET requests
* @author Florian Dold * @author Florian Dold
* @author Benedikt Mueller * @author Benedikt Mueller
* @author Christian Grothoff * @author Christian Grothoff
@ -114,42 +114,37 @@ reserve_status_transaction (void *cls,
/** /**
* Handle a "/reserve/status" request. Parses the * Handle a GET "/reserves/" request. Parses the
* given "reserve_pub" argument (which should contain the * given "reserve_pub" in @a args (which should contain the
* 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 rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (length: 1, just the reserve_pub)
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_RESERVE_handler_reserve_status (struct TEH_RequestHandler *rh, TEH_RESERVE_handler_reserve_status (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[1])
const char *upload_data,
size_t *upload_data_size)
{ {
struct ReserveStatusContext rsc; struct ReserveStatusContext rsc;
int res;
int mhd_ret; int mhd_ret;
(void) rh; (void) rh;
(void) connection_cls; if (GNUNET_OK !=
(void) upload_data; GNUNET_STRINGS_string_to_data (args[0],
(void) upload_data_size; strlen (args[0]),
res = TALER_MHD_parse_request_arg_data (connection, &rsc.reserve_pub,
"reserve_pub", sizeof (rsc.reserve_pub)))
&rsc.reserve_pub, {
sizeof (struct GNUNET_break_op (0);
TALER_ReservePublicKeyP)); return TALER_MHD_reply_with_error (connection,
if (GNUNET_SYSERR == res) MHD_HTTP_BAD_REQUEST,
return MHD_NO; /* internal error */ TALER_EC_RESERVES_INVALID_RESERVE_PUB,
if (GNUNET_NO == res) "reserve public key malformed");
return MHD_YES; /* parse error */ }
rsc.rh = NULL; rsc.rh = NULL;
if (GNUNET_OK != if (GNUNET_OK !=
TEH_DB_run_transaction (connection, TEH_DB_run_transaction (connection,

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-2020 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
@ -15,7 +15,7 @@
*/ */
/** /**
* @file taler-exchange-httpd_reserve_status.h * @file taler-exchange-httpd_reserve_status.h
* @brief Handle /reserve/status requests * @brief Handle /reserves/$RESERVE_PUB GET requests
* @author Florian Dold * @author Florian Dold
* @author Benedikt Mueller * @author Benedikt Mueller
* @author Christian Grothoff * @author Christian Grothoff
@ -26,24 +26,21 @@
#include <microhttpd.h> #include <microhttpd.h>
#include "taler-exchange-httpd.h" #include "taler-exchange-httpd.h"
/** /**
* Handle a "/reserve/status" request. Parses the * Handle a GET "/reserves/" request. Parses the
* given "reserve_pub" argument (which should contain the * given "reserve_pub" in @a args (which should contain the
* 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 rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (length: 1, just the reserve_pub)
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_RESERVE_handler_reserve_status (struct TEH_RequestHandler *rh, TEH_RESERVE_handler_reserve_status (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[1]);
const char *upload_data,
size_t *upload_data_size);
#endif #endif

View File

@ -335,30 +335,27 @@ withdraw_transaction (void *cls,
/** /**
* Handle a "/reserve/withdraw" request. Parses the "reserve_pub" * Handle a "/reserves/$RESERVE_PUB/withdraw" request. Parses the
* EdDSA key of the reserve and the requested "denom_pub" which * "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 * specifies the key/value of the coin to be withdrawn, and checks that the
* that the signature "reserve_sig" makes this a valid withdrawal * signature "reserve_sig" makes this a valid withdrawal request from the
* request from the specified reserve. If so, the envelope * specified reserve. If so, the envelope with the blinded coin "coin_ev" is
* with the blinded coin "coin_ev" is passed down to execute the * passed down to execute the withdrawl operation.
* withdrawl operation.
* *
* @param rh context of the handler * @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param root uploaded JSON data
* @param upload_data upload data * @param args array of additional options (first must be the
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data * reserve public key, the second one should be "withdraw")
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh, TEH_RESERVE_handler_reserve_withdraw (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const json_t *root,
const char *upload_data, const char *const args[2])
size_t *upload_data_size)
{ {
struct WithdrawContext wc; struct WithdrawContext wc;
json_t *root;
int res; int res;
int mhd_ret; int mhd_ret;
unsigned int hc; unsigned int hc;
@ -369,8 +366,6 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh,
GNUNET_JSON_spec_varsize ("coin_ev", GNUNET_JSON_spec_varsize ("coin_ev",
(void **) &wc.blinded_msg, (void **) &wc.blinded_msg,
&wc.blinded_msg_len), &wc.blinded_msg_len),
GNUNET_JSON_spec_fixed_auto ("reserve_pub",
&wc.wsrd.reserve_pub),
GNUNET_JSON_spec_fixed_auto ("reserve_sig", GNUNET_JSON_spec_fixed_auto ("reserve_sig",
&wc.signature), &wc.signature),
GNUNET_JSON_spec_fixed_auto ("denom_pub_hash", GNUNET_JSON_spec_fixed_auto ("denom_pub_hash",
@ -379,19 +374,22 @@ TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh,
}; };
(void) rh; (void) rh;
res = TALER_MHD_parse_post_json (connection, if (GNUNET_OK !=
connection_cls, GNUNET_STRINGS_string_to_data (args[0],
upload_data, strlen (args[0]),
upload_data_size, &wc.wsrd.reserve_pub,
&root); sizeof (wc.wsrd.reserve_pub)))
if (GNUNET_SYSERR == res) {
return MHD_NO; GNUNET_break_op (0);
if ( (GNUNET_NO == res) || (NULL == root) ) return TALER_MHD_reply_with_error (connection,
return MHD_YES; MHD_HTTP_BAD_REQUEST,
TALER_EC_RESERVES_INVALID_RESERVE_PUB,
"reserve public key malformed");
}
res = TALER_MHD_parse_json_data (connection, res = TALER_MHD_parse_json_data (connection,
root, root,
spec); spec);
json_decref (root);
if (GNUNET_OK != res) if (GNUNET_OK != res)
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES; return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
wc.key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ()); wc.key_state = TEH_KS_acquire (GNUNET_TIME_absolute_get ());

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-2020 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
@ -28,26 +28,24 @@
/** /**
* Handle a "/reserve/withdraw" request. Parses the "reserve_pub" * Handle a "/reserves/$RESERVE_PUB/withdraw" request. Parses the
* EdDSA key of the reserve and the requested "denom_pub" which * "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 * specifies the key/value of the coin to be withdrawn, and checks that the
* that the signature "reserve_sig" makes this a valid withdrawl * signature "reserve_sig" makes this a valid withdrawl request from the
* request from the specified reserve. If so, the envelope * specified reserve. If so, the envelope with the blinded coin "coin_ev" is
* with the blinded coin "coin_ev" is passed down to execute the * passed down to execute the withdrawl operation.
* withdrawl operation.
* *
* @param rh context of the handler * @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param root uploaded JSON data
* @param upload_data upload data * @param args array of additional options (first must be the
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data * reserve public key, the second one should be "withdraw")
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_RESERVE_handler_reserve_withdraw (struct TEH_RequestHandler *rh, TEH_RESERVE_handler_reserve_withdraw (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const json_t *root,
const char *upload_data, const char *const args[2]);
size_t *upload_data_size);
#endif #endif

View File

@ -43,22 +43,16 @@ static struct TALER_MHD_Legal *pp;
* *
* @param rh context of the handler * @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (must be empty for this function)
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_handler_terms (struct TEH_RequestHandler *rh, TEH_handler_terms (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[])
const char *upload_data,
size_t *upload_data_size)
{ {
(void) rh; (void) rh;
(void) upload_data; (void) args;
(void) upload_data_size;
(void) connection_cls;
return TALER_MHD_reply_legal (connection, return TALER_MHD_reply_legal (connection,
tos); tos);
} }
@ -69,22 +63,16 @@ TEH_handler_terms (struct TEH_RequestHandler *rh,
* *
* @param rh context of the handler * @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (must be empty for this function)
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_handler_privacy (struct TEH_RequestHandler *rh, TEH_handler_privacy (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[])
const char *upload_data,
size_t *upload_data_size)
{ {
(void) rh; (void) rh;
(void) upload_data; (void) args;
(void) upload_data_size;
(void) connection_cls;
return TALER_MHD_reply_legal (connection, return TALER_MHD_reply_legal (connection,
pp); pp);
} }

View File

@ -34,34 +34,27 @@
* *
* @param rh context of the handler * @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (must be empty for this function)
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_handler_terms (struct TEH_RequestHandler *rh, TEH_handler_terms (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[]);
const char *upload_data,
size_t *upload_data_size);
/** /**
* Handle a "/privacy" request. * Handle a "/privacy" request.
* *
* @param rh context of the handler * @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (must be empty for this function)
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_handler_privacy (struct TEH_RequestHandler *rh, TEH_handler_privacy (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[]);
const char *upload_data,
size_t *upload_data_size);
/** /**

View File

@ -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 rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (length: 4, contains:
* @param upload_data upload data * h_wire, merchant_pub, h_contract_terms and coin_pub)
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_TRACKING_handler_track_transaction (struct TEH_RequestHandler *rh, TEH_TRACKING_handler_track_transaction (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[4])
const char *upload_data,
size_t *upload_data_size)
{ {
int res; int res;
json_t *json;
struct TALER_DepositTrackPS tps; struct TALER_DepositTrackPS tps;
struct TALER_MerchantSignatureP merchant_sig; 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; if (GNUNET_OK !=
res = TALER_MHD_parse_post_json (connection, GNUNET_STRINGS_string_to_data (args[0],
connection_cls, strlen (args[0]),
upload_data, &tps.h_wire,
upload_data_size, sizeof (tps.h_wire)))
&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)
{ {
json_decref (json); GNUNET_break_op (0);
return (GNUNET_NO == res) ? MHD_YES : MHD_NO; 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)))
{
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.size = htonl (sizeof (struct TALER_DepositTrackPS));
tps.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION); tps.purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION);
res = check_and_handle_track_transaction_request (connection, return check_and_handle_track_transaction_request (connection,
&tps, &tps,
&tps.merchant, &tps.merchant,
&merchant_sig); &merchant_sig);
GNUNET_JSON_parse_free (spec);
json_decref (json);
return res;
} }

View File

@ -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 rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (length: 4, contains:
* @param upload_data upload data * h_wire, merchant_pub, h_contract_terms and coin_pub)
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_TRACKING_handler_track_transaction (struct TEH_RequestHandler *rh, TEH_TRACKING_handler_track_transaction (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[4]);
const char *upload_data,
size_t *upload_data_size);
#endif #endif

View File

@ -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 rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (length: 1, just the wtid)
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_TRACKING_handler_track_transfer (struct TEH_RequestHandler *rh, TEH_TRACKING_handler_track_transfer (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[1])
const char *upload_data,
size_t *upload_data_size)
{ {
struct WtidTransactionContext ctx; struct WtidTransactionContext ctx;
int res;
int mhd_ret; int mhd_ret;
(void) rh; (void) rh;
(void) connection_cls; memset (&ctx,
(void) upload_data; 0,
(void) upload_data_size; sizeof (ctx));
memset (&ctx, 0, sizeof (ctx)); if (GNUNET_OK !=
res = TALER_MHD_parse_request_arg_data (connection, GNUNET_STRINGS_string_to_data (args[0],
"wtid", strlen (args[0]),
&ctx.wtid, &ctx.wtid,
sizeof (struct sizeof (ctx.wtid)))
TALER_WireTransferIdentifierRawP)); {
if (GNUNET_SYSERR == res) GNUNET_break_op (0);
return MHD_NO; /* internal error */ return TALER_MHD_reply_with_error (connection,
if (GNUNET_NO == res) MHD_HTTP_BAD_REQUEST,
return MHD_YES; /* parse error */ TALER_EC_TRANSFERS_INVALID_WTID,
"wire transfer identifier malformed");
}
if (GNUNET_OK != if (GNUNET_OK !=
TEH_DB_run_transaction (connection, TEH_DB_run_transaction (connection,
"run track transfer", "run track transfer",

View File

@ -27,20 +27,17 @@
/** /**
* Handle a "/track/transfer" request. * Handle a GET "/transfers/$WTID" request.
* *
* @param rh context of the handler * @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (length: 1, just the wtid)
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_TRACKING_handler_track_transfer (struct TEH_RequestHandler *rh, TEH_TRACKING_handler_track_transfer (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[1]);
const char *upload_data,
size_t *upload_data_size);
#endif #endif

View File

@ -25,7 +25,6 @@
#include "taler-exchange-httpd_validation.h" #include "taler-exchange-httpd_validation.h"
#include "taler-exchange-httpd_wire.h" #include "taler-exchange-httpd_wire.h"
#include "taler_exchangedb_lib.h" #include "taler_exchangedb_lib.h"
#include "taler_json_lib.h"
/** /**

View File

@ -124,22 +124,16 @@ TEH_WIRE_get_fees (const char *method)
* *
* @param rh context of the handler * @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (must be empty for this function)
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_WIRE_handler_wire (struct TEH_RequestHandler *rh, TEH_WIRE_handler_wire (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[])
const char *upload_data,
size_t *upload_data_size)
{ {
(void) rh; (void) rh;
(void) connection_cls; (void) args;
(void) upload_data;
(void) upload_data_size;
GNUNET_assert (NULL != wire_methods); GNUNET_assert (NULL != wire_methods);
return TALER_MHD_reply_json (connection, return TALER_MHD_reply_json (connection,
wire_methods, wire_methods,

View File

@ -51,17 +51,13 @@ TEH_WIRE_get_fees (const char *method);
* *
* @param rh context of the handler * @param rh context of the handler
* @param connection the MHD connection to handle * @param connection the MHD connection to handle
* @param[in,out] connection_cls the connection's closure (can be updated) * @param args array of additional options (must be empty for this function)
* @param upload_data upload data
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
* @return MHD result code * @return MHD result code
*/ */
int int
TEH_WIRE_handler_wire (struct TEH_RequestHandler *rh, TEH_WIRE_handler_wire (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection, struct MHD_Connection *connection,
void **connection_cls, const char *const args[]);
const char *upload_data,
size_t *upload_data_size);
#endif #endif

View File

@ -85,6 +85,32 @@ enum TALER_ErrorCode
*/ */
TALER_EC_METHOD_INVALID = 8, 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 * The exchange failed to even just initialize its connection to the
* database. This response is provided with HTTP status code * database. This response is provided with HTTP status code
@ -181,6 +207,50 @@ enum TALER_ErrorCode
*/ */
TALER_EC_DB_COIN_HISTORY_STORE_ERROR = 1014, 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 * The given reserve does not have sufficient funds to admit the
* requested withdraw operation at this time. The response includes * requested withdraw operation at this time. The response includes