add dispatching logic for (most) of the new endpoints

This commit is contained in:
Christian Grothoff 2020-12-01 00:34:04 +01:00
parent 862054f6f2
commit 65915731a9
No known key found for this signature in database
GPG Key ID: 939E6BE1E29FC3CC
8 changed files with 319 additions and 38 deletions

View File

@ -28,20 +28,22 @@
#include <pthread.h>
#include <sys/resource.h>
#include "taler_mhd_lib.h"
#include "taler-exchange-httpd_mhd.h"
#include "taler-exchange-httpd_auditors.h"
#include "taler-exchange-httpd_deposit.h"
#include "taler-exchange-httpd_refund.h"
#include "taler-exchange-httpd_reserves_get.h"
#include "taler-exchange-httpd_withdraw.h"
#include "taler-exchange-httpd_recoup.h"
#include "taler-exchange-httpd_link.h"
#include "taler-exchange-httpd_melt.h"
#include "taler-exchange-httpd_refreshes_reveal.h"
#include "taler-exchange-httpd_terms.h"
#include "taler-exchange-httpd_transfers_get.h"
#include "taler-exchange-httpd_deposits_get.h"
#include "taler-exchange-httpd_keystate.h"
#include "taler-exchange-httpd_link.h"
#include "taler-exchange-httpd_management.h"
#include "taler-exchange-httpd_melt.h"
#include "taler-exchange-httpd_mhd.h"
#include "taler-exchange-httpd_recoup.h"
#include "taler-exchange-httpd_refreshes_reveal.h"
#include "taler-exchange-httpd_refund.h"
#include "taler-exchange-httpd_reserves_get.h"
#include "taler-exchange-httpd_terms.h"
#include "taler-exchange-httpd_transfers_get.h"
#include "taler-exchange-httpd_wire.h"
#include "taler-exchange-httpd_withdraw.h"
#include "taler_exchangedb_plugin.h"
#include <gnunet/gnunet_mhd_compat.h>
@ -177,6 +179,24 @@ typedef MHD_RESULT
const json_t *root);
/**
* Generate a 404 "not found" reply on @a connection with
* the hint @a details.
*
* @param connection where to send the reply on
* @param details details for the error message, can be NULL
*/
static MHD_RESULT
r404 (struct MHD_Connection *connection,
const char *details)
{
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_NOT_FOUND,
TALER_EC_EXCHANGE_GENERIC_OPERATION_UNKNOWN,
details);
}
/**
* Handle a "/coins/$COIN_PUB/$OP" POST request. Parses the "coin_pub"
* EdDSA key of the coin and demultiplexes based on $OP.
@ -249,10 +269,7 @@ handle_post_coins (const struct TEH_RequestHandler *rh,
return h[i].handler (connection,
&coin_pub,
root);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_NOT_FOUND,
TALER_EC_EXCHANGE_GENERIC_OPERATION_UNKNOWN,
args[1]);
return r404 (connection, args[1]);
}
@ -367,6 +384,7 @@ proceed_with_handler (const struct TEH_RequestHandler *rh,
char d[ulen];
/* Parse command-line arguments, if applicable */
args[0] = NULL;
if (rh->nargs > 0)
{
unsigned int i;
@ -384,9 +402,10 @@ proceed_with_handler (const struct TEH_RequestHandler *rh,
args[i++] = strtok_r (NULL, "/", &sp);
/* 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 != (fin = strtok_r (NULL, "/", &sp))) )
if ( (! rh->nargs_is_upper_bound) &&
( (i != rh->nargs) ||
(NULL == args[i - 1]) ||
(NULL != (fin = strtok_r (NULL, "/", &sp))) ) )
{
char emsg[128 + 512];
@ -407,12 +426,12 @@ proceed_with_handler (const struct TEH_RequestHandler *rh,
TALER_EC_EXCHANGE_GENERIC_WRONG_NUMBER_OF_SEGMENTS,
emsg);
}
/* just to be safe(r), we always terminate the array with a NULL
(even if handlers requested precise number of arguments) */
args[i] = NULL;
}
/* 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,
so we test for 'root' to decide which handler to invoke. */
@ -472,6 +491,244 @@ handler_seed (const struct TEH_RequestHandler *rh,
}
/**
* Handle POST "/management/..." requests.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
* @param root uploaded JSON data
* @param args array of additional options
* @return MHD result code
*/
static MHD_RESULT
handle_post_management (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
const json_t *root,
const char *const args[])
{
if (NULL == args[0])
{
GNUNET_break_op (0);
return r404 (connection, "/management");
}
if (0 == strcmp (args[0],
"auditors"))
{
struct TALER_AuditorPublicKeyP auditor_pub;
if (NULL == args[1])
return TEH_handler_management_auditors (connection,
root);
if ( (NULL == args[1]) ||
(NULL == args[2]) ||
(0 != strcmp (args[2],
"disable")) ||
(NULL != args[3]) )
return r404 (connection,
"/management/auditors/$AUDITOR_PUB/disable");
if (GNUNET_OK !=
GNUNET_STRINGS_string_to_data (args[1],
strlen (args[1]),
&auditor_pub,
sizeof (auditor_pub)))
{
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
args[1]);
}
return TEH_handler_management_auditors_AP_disable (connection,
&auditor_pub,
root);
}
if (0 == strcmp (args[0],
"denominations"))
{
struct GNUNET_HashCode h_denom_pub;
if ( (NULL == args[0]) ||
(NULL == args[1]) ||
(NULL == args[2]) ||
(0 != strcmp (args[2],
"revoke")) ||
(NULL != args[3]) )
return r404 (connection,
"/management/denominations/$HDP/revoke");
if (GNUNET_OK !=
GNUNET_STRINGS_string_to_data (args[2],
strlen (args[2]),
&h_denom_pub,
sizeof (h_denom_pub)))
{
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
args[2]);
}
return TEH_handler_management_denominations_HDP_revoke (connection,
&h_denom_pub,
root);
}
if (0 == strcmp (args[0],
"signkeys"))
{
struct TALER_ExchangePublicKeyP exchange_pub;
if ( (NULL == args[0]) ||
(NULL == args[1]) ||
(NULL == args[2]) ||
(0 != strcmp (args[2],
"revoke")) ||
(NULL != args[3]) )
return r404 (connection,
"/management/signkeys/$HDP/revoke");
if (GNUNET_OK !=
GNUNET_STRINGS_string_to_data (args[2],
strlen (args[2]),
&exchange_pub,
sizeof (exchange_pub)))
{
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
args[2]);
}
return TEH_handler_management_signkeys_EP_revoke (connection,
&exchange_pub,
root);
}
#if FIXME
/* not yet implemented! */
if (0 == strcmp (args[0],
"keys"))
{
if (NULL != args[1])
{
GNUNET_break_op (0);
return r404 (connection, "/management/keys/*");
}
return TEH_handler_management_post_keys (connection,
root);
}
#endif
if (0 == strcmp (args[0],
"wire"))
{
if (NULL == args[1])
return TEH_handler_management_denominations_wire (connection,
root);
if ( (0 != strcmp (args[1],
"disable")) ||
(NULL != args[2]) )
{
GNUNET_break_op (0);
return r404 (connection, "/management/wire/disable");
}
return TEH_handler_management_denominations_wire_disable (connection,
root);
}
if (0 == strcmp (args[0],
"wire-fees"))
{
if (NULL != args[1])
{
GNUNET_break_op (0);
return r404 (connection, "/management/wire-fees/*");
}
return TEH_handler_management_post_wire_fees (connection,
root);
}
GNUNET_break_op (0);
return r404 (connection, "/management/*");
}
/**
* Handle a get "/management" request.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
* @param args array of additional options (must be empty for this function)
* @return MHD result code
*/
static MHD_RESULT
handle_get_management (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
const char *const args[1])
{
if ( (NULL == args[0]) ||
(0 != strcmp (args[0],
"keys")) ||
(NULL != args[1]) )
{
GNUNET_break_op (0);
return r404 (connection, "/management/*");
}
GNUNET_break (0); // not implemented
return MHD_NO;
}
/**
* Handle POST "/auditors/..." requests.
*
* @param rh context of the handler
* @param connection the MHD connection to handle
* @param root uploaded JSON data
* @param args array of additional options
* @return MHD result code
*/
static MHD_RESULT
handle_post_auditors (const struct TEH_RequestHandler *rh,
struct MHD_Connection *connection,
const json_t *root,
const char *const args[])
{
struct TALER_AuditorPublicKeyP auditor_pub;
struct GNUNET_HashCode h_denom_pub;
if ( (NULL == args[0]) ||
(NULL == args[1]) ||
(NULL != args[0]) )
{
GNUNET_break_op (0);
return r404 (connection, "/auditors/$AUDITOR_PUB/$H_DENOM_PUB");
}
if (GNUNET_OK !=
GNUNET_STRINGS_string_to_data (args[0],
strlen (args[0]),
&auditor_pub,
sizeof (auditor_pub)))
{
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
args[0]);
}
if (GNUNET_OK !=
GNUNET_STRINGS_string_to_data (args[1],
strlen (args[1]),
&h_denom_pub,
sizeof (h_denom_pub)))
{
GNUNET_break_op (0);
return TALER_MHD_reply_with_error (connection,
MHD_HTTP_BAD_REQUEST,
TALER_EC_GENERIC_PARAMETER_MALFORMED,
args[1]);
}
return TEH_handler_auditors (connection,
&auditor_pub,
&h_denom_pub,
root);
}
/**
* Handle incoming HTTP request.
*
@ -600,6 +857,29 @@ handle_mhd_request (void *cls,
.handler.get = &TEH_handler_deposits_get,
.nargs = 4
},
/* POST management endpoints */
{
.url = "management",
.method = MHD_HTTP_METHOD_POST,
.handler.post = &handle_post_management,
.nargs = 4,
.nargs_is_upper_bound = true
},
/* GET management endpoints (we only really have "/management/keys") */
{
.url = "management",
.method = MHD_HTTP_METHOD_GET,
.handler.get = &handle_get_management,
.nargs = 1
},
/* auditor endpoints */
{
.url = "auditors",
.method = MHD_HTTP_METHOD_POST,
.handler.post = &handle_post_auditors,
.nargs = 4,
.nargs_is_upper_bound = true
},
/* mark end of list */
{
.url = NULL

View File

@ -133,6 +133,12 @@ struct TEH_RequestHandler
*/
unsigned int nargs;
/**
* Is the number of arguments given in @e nargs only an upper bound,
* and calling with fewer arguments could be OK?
*/
bool nargs_is_upper_bound;
/**
* Mime type to use in reply (hint, can be NULL).
*/

View File

@ -209,7 +209,7 @@ add_auditor_denom_sig (void *cls,
MHD_RESULT
TEH_handler_management_denominations_auditors (
TEH_handler_auditors (
struct MHD_Connection *connection,
const struct TALER_AuditorPublicKeyP *auditor_pub,
const struct GNUNET_HashCode *h_denom_pub,
@ -255,4 +255,4 @@ TEH_handler_management_denominations_auditors (
}
/* end of taler-exchange-httpd_management_auditors.c */
/* end of taler-exchange-httpd_auditors.c */

View File

@ -36,7 +36,7 @@
* @return MHD result code
*/
MHD_RESULT
TEH_handler_management_denominations_auditors (
TEH_handler_auditors (
struct MHD_Connection *connection,
const struct TALER_AuditorPublicKeyP *auditor_pub,
const struct GNUNET_HashCode *h_denom_pub,

View File

@ -29,14 +29,12 @@
* Handle a "/management/auditors" request.
*
* @param connection the MHD connection to handle
* @param h_denom_pub hash of the public key of the denomination to revoke
* @param root uploaded JSON data
* @return MHD result code
*/
MHD_RESULT
TEH_handler_management_auditors (
struct MHD_Connection *connection,
const struct GNUNET_HashCode *h_denom_pub,
const json_t *root);
@ -44,14 +42,14 @@ TEH_handler_management_auditors (
* Handle a "/management/auditors/$AUDITOR_PUB/disable" request.
*
* @param connection the MHD connection to handle
* @param h_denom_pub hash of the public key of the denomination to revoke
* @param auditor_pub public key of the auditor to disable
* @param root uploaded JSON data
* @return MHD result code
*/
MHD_RESULT
TEH_handler_management_auditors_AP_disable (
struct MHD_Connection *connection,
const struct GNUNET_HashCode *h_denom_pub,
const struct TALER_AuditorPublicKeyP *auditor_pub,
const json_t *root);
@ -89,16 +87,15 @@ TEH_handler_management_signkeys_EP_revoke (
* Handle a POST "/management/keys" request.
*
* @param connection the MHD connection to handle
* @param h_denom_pub hash of the public key of the denomination to revoke
* @param root uploaded JSON data
* @return MHD result code
*/
MHD_RESULT
TEH_handler_management_post_keys (
struct MHD_Connection *connection,
const struct GNUNET_HashCode *h_denom_pub,
const json_t *root);
/**
* Handle a "/management/wire" request.
*
@ -113,7 +110,7 @@ TEH_handler_management_denominations_wire (
/**
* Handle a "/management/wire" request.
* Handle a "/management/wire/disable" request.
*
* @param connection the MHD connection to handle
* @param root uploaded JSON data

View File

@ -145,7 +145,6 @@ add_auditor (void *cls,
MHD_RESULT
TEH_handler_management_auditors (
struct MHD_Connection *connection,
const struct GNUNET_HashCode *h_denom_pub,
const json_t *root)
{
struct AddAuditorContext aac;

View File

@ -137,16 +137,16 @@ del_auditor (void *cls,
MHD_RESULT
TEH_handler_management_auditors_AP_disable (
struct MHD_Connection *connection,
const struct GNUNET_HashCode *h_denom_pub,
const struct TALER_AuditorPublicKeyP *auditor_pub,
const json_t *root)
{
struct TALER_MasterSignatureP master_sig;
struct DelAuditorContext dac;
struct DelAuditorContext dac = {
.auditor_pub = *auditor_pub
};
struct GNUNET_JSON_Specification spec[] = {
GNUNET_JSON_spec_fixed_auto ("master_sig",
&master_sig),
GNUNET_JSON_spec_fixed_auto ("auditor_pub",
&dac.auditor_pub),
TALER_JSON_spec_absolute_time ("validity_end",
&dac.validity_end),
GNUNET_JSON_spec_end ()
@ -171,7 +171,7 @@ TEH_handler_management_auditors_AP_disable (
TALER_SIGNATURE_MASTER_DEL_AUDITOR),
.purpose.size = htonl (sizeof (da)),
.end_date = GNUNET_TIME_absolute_hton (dac.validity_end),
.auditor_pub = dac.auditor_pub
.auditor_pub = *auditor_pub
};
if (GNUNET_OK !=

View File

@ -323,7 +323,6 @@ add_keys (void *cls,
MHD_RESULT
TEH_handler_management_post_keys (
struct MHD_Connection *connection,
const struct GNUNET_HashCode *h_denom_pub,
const json_t *root)
{
struct AddKeysContext akc;