eliminate /admin/add/incoming (fixes #5172)
This commit is contained in:
parent
f7c9de73e1
commit
1897d65af5
@ -400,13 +400,10 @@ gap. See keys-duration.
|
|||||||
@section Serving
|
@section Serving
|
||||||
|
|
||||||
|
|
||||||
The exchange can serve HTTP over both TCP and UNIX domain socket. It
|
The exchange can serve HTTP over both TCP and UNIX domain socket.
|
||||||
needs this configuration @emph{twice}, because it opens one connection
|
|
||||||
for ordinary REST calls, and one for "/admin" and "/test" REST calls,
|
|
||||||
because the operator may want to restrict the access to "/admin".
|
|
||||||
|
|
||||||
The following values are to be configured under the section
|
The following values are to be configured in the section
|
||||||
@cite{[exchange]} and @cite{[exchange-admin]}:
|
@cite{[exchange]}:
|
||||||
|
|
||||||
|
|
||||||
@itemize
|
@itemize
|
||||||
@ -425,13 +422,9 @@ The following values are to be configured under the section
|
|||||||
|
|
||||||
@item
|
@item
|
||||||
@cite{unixpath_mode}: number giving the mode with the access
|
@cite{unixpath_mode}: number giving the mode with the access
|
||||||
permissiON MASK for the @cite{unixpath} (i.e. 660 = rw-rw----).
|
permission MASK for the @cite{unixpath} (i.e. 660 = rw-rw----).
|
||||||
@end itemize
|
@end itemize
|
||||||
|
|
||||||
The exchange can be started with the @cite{-D} option to disable the administrative
|
|
||||||
functions entirely. It is recommended that the administrative API is only
|
|
||||||
accessible via a properly protected UNIX domain socket.
|
|
||||||
|
|
||||||
|
|
||||||
@node Currency
|
@node Currency
|
||||||
@section Currency
|
@section Currency
|
||||||
@ -673,7 +666,7 @@ get signed by every auditor he wishes (or is forced to) work with.
|
|||||||
|
|
||||||
In a normal scenario, an auditor must have some way of receiving the blob to
|
In a normal scenario, an auditor must have some way of receiving the blob to
|
||||||
sign (Website, manual delivery, ..). Nonetheless, the exchange admin can fake
|
sign (Website, manual delivery, ..). Nonetheless, the exchange admin can fake
|
||||||
an auditor signature - for testing purposes - by running the following command
|
an auditor signature --- for testing purposes --- by running the following command
|
||||||
|
|
||||||
@example
|
@example
|
||||||
taler-auditor-sign -m EXCHANGE_MASTER_PUB -r BLOB -u AUDITOR_URI -o OUTPUT_FILE
|
taler-auditor-sign -m EXCHANGE_MASTER_PUB -r BLOB -u AUDITOR_URI -o OUTPUT_FILE
|
||||||
|
@ -43,7 +43,6 @@ taler_exchange_wirewatch_LDADD = \
|
|||||||
|
|
||||||
taler_exchange_httpd_SOURCES = \
|
taler_exchange_httpd_SOURCES = \
|
||||||
taler-exchange-httpd.c taler-exchange-httpd.h \
|
taler-exchange-httpd.c taler-exchange-httpd.h \
|
||||||
taler-exchange-httpd_admin.c taler-exchange-httpd_admin.h \
|
|
||||||
taler-exchange-httpd_db.c taler-exchange-httpd_db.h \
|
taler-exchange-httpd_db.c taler-exchange-httpd_db.h \
|
||||||
taler-exchange-httpd_deposit.c taler-exchange-httpd_deposit.h \
|
taler-exchange-httpd_deposit.c taler-exchange-httpd_deposit.h \
|
||||||
taler-exchange-httpd_keystate.c taler-exchange-httpd_keystate.h \
|
taler-exchange-httpd_keystate.c taler-exchange-httpd_keystate.h \
|
||||||
|
@ -36,18 +36,3 @@ PORT = 8081
|
|||||||
# Required for wire transfers as we need to include it in the wire
|
# Required for wire transfers as we need to include it in the wire
|
||||||
# transfers to enable tracking.
|
# transfers to enable tracking.
|
||||||
BASE_URL = http://localhost:8081/
|
BASE_URL = http://localhost:8081/
|
||||||
|
|
||||||
|
|
||||||
[exchange-admin]
|
|
||||||
# Network configuration for the /admin HTTP server
|
|
||||||
|
|
||||||
# serve via tcp socket (on PORT)
|
|
||||||
SERVE = tcp
|
|
||||||
|
|
||||||
# Unix domain socket to listen on,
|
|
||||||
# only effective with "SERVE = unix"
|
|
||||||
UNIXPATH = ${TALER_RUNTIME_DIR}/exchange-admin.http
|
|
||||||
UNIXPATH_MODE = 660
|
|
||||||
|
|
||||||
# HTTP port the exchange listens to
|
|
||||||
PORT = 18080
|
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include "taler-exchange-httpd_parsing.h"
|
#include "taler-exchange-httpd_parsing.h"
|
||||||
#include "taler-exchange-httpd_mhd.h"
|
#include "taler-exchange-httpd_mhd.h"
|
||||||
#include "taler-exchange-httpd_admin.h"
|
|
||||||
#include "taler-exchange-httpd_deposit.h"
|
#include "taler-exchange-httpd_deposit.h"
|
||||||
#include "taler-exchange-httpd_refund.h"
|
#include "taler-exchange-httpd_refund.h"
|
||||||
#include "taler-exchange-httpd_reserve_status.h"
|
#include "taler-exchange-httpd_reserve_status.h"
|
||||||
@ -95,16 +94,6 @@ static unsigned int connection_timeout = 30;
|
|||||||
*/
|
*/
|
||||||
static struct MHD_Daemon *mhd;
|
static struct MHD_Daemon *mhd;
|
||||||
|
|
||||||
/**
|
|
||||||
* The HTTP Daemon for /admin-requests.
|
|
||||||
*/
|
|
||||||
static struct MHD_Daemon *mhd_admin;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Do not offer /admin API.
|
|
||||||
*/
|
|
||||||
static int no_admin;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initialize the database by creating tables and indices.
|
* Initialize the database by creating tables and indices.
|
||||||
*/
|
*/
|
||||||
@ -115,33 +104,17 @@ static int init_db;
|
|||||||
*/
|
*/
|
||||||
static uint16_t serve_port;
|
static uint16_t serve_port;
|
||||||
|
|
||||||
/**
|
|
||||||
* Port to run the admin daemon on.
|
|
||||||
*/
|
|
||||||
static uint16_t serve_admin_port;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Path for the unix domain-socket
|
* Path for the unix domain-socket
|
||||||
* to run the daemon on.
|
* to run the daemon on.
|
||||||
*/
|
*/
|
||||||
static char *serve_unixpath;
|
static char *serve_unixpath;
|
||||||
|
|
||||||
/**
|
|
||||||
* Path for the unix domain-socket
|
|
||||||
* to run the admin daemon on.
|
|
||||||
*/
|
|
||||||
static char *serve_admin_unixpath;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* File mode for unix-domain socket.
|
* File mode for unix-domain socket.
|
||||||
*/
|
*/
|
||||||
static mode_t unixpath_mode;
|
static mode_t unixpath_mode;
|
||||||
|
|
||||||
/**
|
|
||||||
* File mode for unix-domain socket.
|
|
||||||
*/
|
|
||||||
static mode_t unixpath_admin_mode;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Function called whenever MHD is done with a request. If the
|
* Function called whenever MHD is done with a request. If the
|
||||||
@ -307,76 +280,6 @@ handle_mhd_request (void *cls,
|
|||||||
"Only GET is allowed", 0,
|
"Only GET is allowed", 0,
|
||||||
&TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
|
&TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
|
||||||
|
|
||||||
{ NULL, NULL, NULL, NULL, 0, 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 TEH_RequestHandler *rh;
|
|
||||||
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
|
||||||
"Handling request for URL '%s'\n",
|
|
||||||
url);
|
|
||||||
if (0 == strcasecmp (method,
|
|
||||||
MHD_HTTP_METHOD_HEAD))
|
|
||||||
method = MHD_HTTP_METHOD_GET; /* treat HEAD as GET here, MHD will do the rest */
|
|
||||||
for (unsigned int i=0;NULL != handlers[i].url;i++)
|
|
||||||
{
|
|
||||||
rh = &handlers[i];
|
|
||||||
if ( (0 == strcasecmp (url,
|
|
||||||
rh->url)) &&
|
|
||||||
( (NULL == rh->method) ||
|
|
||||||
(0 == strcasecmp (method,
|
|
||||||
rh->method)) ) )
|
|
||||||
return rh->handler (rh,
|
|
||||||
connection,
|
|
||||||
con_cls,
|
|
||||||
upload_data,
|
|
||||||
upload_data_size);
|
|
||||||
}
|
|
||||||
return TEH_MHD_handler_static_response (&h404,
|
|
||||||
connection,
|
|
||||||
con_cls,
|
|
||||||
upload_data,
|
|
||||||
upload_data_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle incoming administrative HTTP request.
|
|
||||||
*
|
|
||||||
* @param cls closure for MHD daemon (unused)
|
|
||||||
* @param connection the connection
|
|
||||||
* @param url the requested url
|
|
||||||
* @param method the method (POST, GET, ...)
|
|
||||||
* @param version HTTP version (ignored)
|
|
||||||
* @param upload_data request data
|
|
||||||
* @param upload_data_size size of @a upload_data in bytes
|
|
||||||
* @param con_cls closure for request (a `struct Buffer *`)
|
|
||||||
* @return MHD result code
|
|
||||||
*/
|
|
||||||
static int
|
|
||||||
handle_mhd_admin_request (void *cls,
|
|
||||||
struct MHD_Connection *connection,
|
|
||||||
const char *url,
|
|
||||||
const char *method,
|
|
||||||
const char *version,
|
|
||||||
const char *upload_data,
|
|
||||||
size_t *upload_data_size,
|
|
||||||
void **con_cls)
|
|
||||||
{
|
|
||||||
static struct TEH_RequestHandler handlers[] =
|
|
||||||
{
|
|
||||||
{ "/admin/add/incoming", MHD_HTTP_METHOD_POST, "application/json",
|
|
||||||
NULL, 0,
|
|
||||||
&TEH_ADMIN_handler_admin_add_incoming, MHD_HTTP_OK },
|
|
||||||
{ "/admin/add/incoming", NULL, "text/plain",
|
|
||||||
"Only POST is allowed", 0,
|
|
||||||
&TEH_MHD_handler_send_json_pack_error, MHD_HTTP_METHOD_NOT_ALLOWED },
|
|
||||||
|
|
||||||
#if HAVE_DEVELOPER
|
#if HAVE_DEVELOPER
|
||||||
/* Client crypto-interoperability test functions */
|
/* Client crypto-interoperability test functions */
|
||||||
{ "/test", MHD_HTTP_METHOD_POST, "application/json",
|
{ "/test", MHD_HTTP_METHOD_POST, "application/json",
|
||||||
@ -452,12 +355,14 @@ handle_mhd_admin_request (void *cls,
|
|||||||
&TEH_MHD_handler_static_response, MHD_HTTP_NOT_FOUND
|
&TEH_MHD_handler_static_response, MHD_HTTP_NOT_FOUND
|
||||||
};
|
};
|
||||||
struct TEH_RequestHandler *rh;
|
struct TEH_RequestHandler *rh;
|
||||||
unsigned int i;
|
|
||||||
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||||
"Handling request for URL '%s'\n",
|
"Handling request for URL '%s'\n",
|
||||||
url);
|
url);
|
||||||
for (i=0;NULL != handlers[i].url;i++)
|
if (0 == strcasecmp (method,
|
||||||
|
MHD_HTTP_METHOD_HEAD))
|
||||||
|
method = MHD_HTTP_METHOD_GET; /* treat HEAD as GET here, MHD will do the rest */
|
||||||
|
for (unsigned int i=0;NULL != handlers[i].url;i++)
|
||||||
{
|
{
|
||||||
rh = &handlers[i];
|
rh = &handlers[i];
|
||||||
if ( (0 == strcasecmp (url,
|
if ( (0 == strcasecmp (url,
|
||||||
@ -691,15 +596,6 @@ exchange_serve_process_config ()
|
|||||||
TEH_VALIDATION_done ();
|
TEH_VALIDATION_done ();
|
||||||
return GNUNET_SYSERR;
|
return GNUNET_SYSERR;
|
||||||
}
|
}
|
||||||
if (GNUNET_OK !=
|
|
||||||
parse_port_config ("exchange-admin",
|
|
||||||
&serve_admin_port,
|
|
||||||
&serve_admin_unixpath,
|
|
||||||
&unixpath_admin_mode))
|
|
||||||
{
|
|
||||||
TEH_VALIDATION_done ();
|
|
||||||
return GNUNET_SYSERR;
|
|
||||||
}
|
|
||||||
return GNUNET_OK;
|
return GNUNET_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -952,10 +848,6 @@ main (int argc,
|
|||||||
"force HTTP connections to be closed after each request",
|
"force HTTP connections to be closed after each request",
|
||||||
&TEH_exchange_connection_close),
|
&TEH_exchange_connection_close),
|
||||||
GNUNET_GETOPT_option_cfgfile (&cfgfile),
|
GNUNET_GETOPT_option_cfgfile (&cfgfile),
|
||||||
GNUNET_GETOPT_option_flag ('D',
|
|
||||||
"disable-admin",
|
|
||||||
"do not run the /admin-HTTP server",
|
|
||||||
&no_admin),
|
|
||||||
GNUNET_GETOPT_option_flag ('i',
|
GNUNET_GETOPT_option_flag ('i',
|
||||||
"init-db",
|
"init-db",
|
||||||
"create database tables and indicies if necessary",
|
"create database tables and indicies if necessary",
|
||||||
@ -982,7 +874,6 @@ main (int argc,
|
|||||||
const char *listen_pid;
|
const char *listen_pid;
|
||||||
const char *listen_fds;
|
const char *listen_fds;
|
||||||
int fh = -1;
|
int fh = -1;
|
||||||
int fh_admin = -1;
|
|
||||||
|
|
||||||
if (0 >=
|
if (0 >=
|
||||||
GNUNET_GETOPT_run ("taler-exchange-httpd",
|
GNUNET_GETOPT_run ("taler-exchange-httpd",
|
||||||
@ -1018,12 +909,9 @@ main (int argc,
|
|||||||
(getpid() == strtol (listen_pid,
|
(getpid() == strtol (listen_pid,
|
||||||
NULL,
|
NULL,
|
||||||
10)) &&
|
10)) &&
|
||||||
( (1 == strtoul (listen_fds,
|
(1 == strtoul (listen_fds,
|
||||||
NULL,
|
NULL,
|
||||||
10)) ||
|
10)) )
|
||||||
(2 == strtoul (listen_fds,
|
|
||||||
NULL,
|
|
||||||
10)) ) )
|
|
||||||
{
|
{
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
@ -1044,29 +932,6 @@ main (int argc,
|
|||||||
flags)) )
|
flags)) )
|
||||||
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
|
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
|
||||||
"fcntl");
|
"fcntl");
|
||||||
|
|
||||||
if (2 == strtoul (listen_fds,
|
|
||||||
NULL,
|
|
||||||
10))
|
|
||||||
{
|
|
||||||
fh_admin = 4;
|
|
||||||
flags = fcntl (fh_admin,
|
|
||||||
F_GETFD);
|
|
||||||
if ( (-1 == flags) &&
|
|
||||||
(EBADF == errno) )
|
|
||||||
{
|
|
||||||
fprintf (stderr,
|
|
||||||
"Bad listen socket passed, ignored\n");
|
|
||||||
fh_admin = -1;
|
|
||||||
}
|
|
||||||
flags |= FD_CLOEXEC;
|
|
||||||
if ( (-1 != fh_admin) &&
|
|
||||||
(0 != fcntl (fh_admin,
|
|
||||||
F_SETFD,
|
|
||||||
flags)) )
|
|
||||||
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
|
|
||||||
"fcntl");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* consider unix path */
|
/* consider unix path */
|
||||||
@ -1078,19 +943,6 @@ main (int argc,
|
|||||||
if (-1 == fh)
|
if (-1 == fh)
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if ( (-1 == fh_admin) &&
|
|
||||||
(0 == no_admin) &&
|
|
||||||
(NULL != serve_admin_unixpath) )
|
|
||||||
{
|
|
||||||
fh_admin = open_unix_path (serve_admin_unixpath,
|
|
||||||
unixpath_admin_mode);
|
|
||||||
if (-1 == fh_admin)
|
|
||||||
{
|
|
||||||
if (-1 != fh)
|
|
||||||
GNUNET_break (0 == close (fh));
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
mhd
|
mhd
|
||||||
= MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_PIPE_FOR_SHUTDOWN | MHD_USE_DEBUG | MHD_USE_DUAL_STACK,
|
= MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_PIPE_FOR_SHUTDOWN | MHD_USE_DEBUG | MHD_USE_DUAL_STACK,
|
||||||
@ -1112,30 +964,6 @@ main (int argc,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (0 == no_admin)
|
|
||||||
{
|
|
||||||
mhd_admin
|
|
||||||
= MHD_start_daemon (MHD_USE_SELECT_INTERNALLY | MHD_USE_PIPE_FOR_SHUTDOWN | MHD_USE_DEBUG,
|
|
||||||
(-1 == fh) ? serve_admin_port : 0,
|
|
||||||
NULL, NULL,
|
|
||||||
&handle_mhd_admin_request, NULL,
|
|
||||||
MHD_OPTION_LISTEN_SOCKET, fh_admin,
|
|
||||||
MHD_OPTION_EXTERNAL_LOGGER, &handle_mhd_logs, NULL,
|
|
||||||
MHD_OPTION_NOTIFY_COMPLETED, &handle_mhd_completion_callback, NULL,
|
|
||||||
MHD_OPTION_CONNECTION_TIMEOUT, connection_timeout,
|
|
||||||
#if HAVE_DEVELOPER
|
|
||||||
MHD_OPTION_NOTIFY_CONNECTION, &connection_done, NULL,
|
|
||||||
#endif
|
|
||||||
MHD_OPTION_END);
|
|
||||||
if (NULL == mhd_admin)
|
|
||||||
{
|
|
||||||
fprintf (stderr,
|
|
||||||
"Failed to start administrative HTTP server.\n");
|
|
||||||
MHD_stop_daemon (mhd);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if HAVE_DEVELOPER
|
#if HAVE_DEVELOPER
|
||||||
if (NULL != input_filename)
|
if (NULL != input_filename)
|
||||||
{
|
{
|
||||||
@ -1157,23 +985,14 @@ main (int argc,
|
|||||||
case GNUNET_OK:
|
case GNUNET_OK:
|
||||||
case GNUNET_SYSERR:
|
case GNUNET_SYSERR:
|
||||||
MHD_stop_daemon (mhd);
|
MHD_stop_daemon (mhd);
|
||||||
if (NULL != mhd_admin)
|
|
||||||
MHD_stop_daemon (mhd_admin);
|
|
||||||
break;
|
break;
|
||||||
case GNUNET_NO:
|
case GNUNET_NO:
|
||||||
{
|
{
|
||||||
MHD_socket sock = MHD_quiesce_daemon (mhd);
|
MHD_socket sock = MHD_quiesce_daemon (mhd);
|
||||||
MHD_socket admin_sock;
|
|
||||||
int admin_sock_opened = GNUNET_NO;
|
|
||||||
pid_t chld;
|
pid_t chld;
|
||||||
int flags;
|
int flags;
|
||||||
|
|
||||||
/* Set flags to make 'sock' inherited by child */
|
/* Set flags to make 'sock' inherited by child */
|
||||||
if (NULL != mhd_admin)
|
|
||||||
{
|
|
||||||
admin_sock = MHD_quiesce_daemon (mhd_admin);
|
|
||||||
admin_sock_opened = GNUNET_YES;
|
|
||||||
}
|
|
||||||
flags = fcntl (sock, F_GETFD);
|
flags = fcntl (sock, F_GETFD);
|
||||||
GNUNET_assert (-1 != flags);
|
GNUNET_assert (-1 != flags);
|
||||||
flags &= ~FD_CLOEXEC;
|
flags &= ~FD_CLOEXEC;
|
||||||
@ -1197,20 +1016,13 @@ main (int argc,
|
|||||||
"dup2");
|
"dup2");
|
||||||
_exit (1);
|
_exit (1);
|
||||||
}
|
}
|
||||||
if ( (GNUNET_YES == admin_sock_opened) &&
|
|
||||||
(4 != dup2 (admin_sock, 4)) )
|
|
||||||
{
|
|
||||||
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
|
|
||||||
"dup2");
|
|
||||||
_exit (1);
|
|
||||||
}
|
|
||||||
/* Tell the child that it is the desired recipient for FD #3 */
|
/* Tell the child that it is the desired recipient for FD #3 */
|
||||||
GNUNET_snprintf (pids,
|
GNUNET_snprintf (pids,
|
||||||
sizeof (pids),
|
sizeof (pids),
|
||||||
"%u",
|
"%u",
|
||||||
getpid ());
|
getpid ());
|
||||||
setenv ("LISTEN_PID", pids, 1);
|
setenv ("LISTEN_PID", pids, 1);
|
||||||
setenv ("LISTEN_FDS", (NULL != mhd_admin) ? "2" : "1", 1);
|
setenv ("LISTEN_FDS", "1", 1);
|
||||||
/* Finally, exec the (presumably) more recent exchange binary */
|
/* Finally, exec the (presumably) more recent exchange binary */
|
||||||
execvp ("taler-exchange-httpd",
|
execvp ("taler-exchange-httpd",
|
||||||
argv);
|
argv);
|
||||||
@ -1222,25 +1034,16 @@ main (int argc,
|
|||||||
before exiting; as the listen socket is no longer used,
|
before exiting; as the listen socket is no longer used,
|
||||||
close it here */
|
close it here */
|
||||||
GNUNET_break (0 == close (sock));
|
GNUNET_break (0 == close (sock));
|
||||||
if (GNUNET_YES == admin_sock_opened)
|
while (0 != MHD_get_daemon_info (mhd,
|
||||||
GNUNET_break (0 == close (admin_sock));
|
MHD_DAEMON_INFO_CURRENT_CONNECTIONS)->num_connections)
|
||||||
while ( (0 != MHD_get_daemon_info (mhd,
|
|
||||||
MHD_DAEMON_INFO_CURRENT_CONNECTIONS)->num_connections) ||
|
|
||||||
( (NULL != mhd_admin) &&
|
|
||||||
(0 != MHD_get_daemon_info (mhd_admin,
|
|
||||||
MHD_DAEMON_INFO_CURRENT_CONNECTIONS)->num_connections) ) )
|
|
||||||
sleep (1);
|
sleep (1);
|
||||||
/* Now we're really done, practice clean shutdown */
|
/* Now we're really done, practice clean shutdown */
|
||||||
MHD_stop_daemon (mhd);
|
MHD_stop_daemon (mhd);
|
||||||
if (NULL != mhd_admin)
|
|
||||||
MHD_stop_daemon (mhd_admin);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GNUNET_break (0);
|
GNUNET_break (0);
|
||||||
MHD_stop_daemon (mhd);
|
MHD_stop_daemon (mhd);
|
||||||
if (NULL != mhd_admin)
|
|
||||||
MHD_stop_daemon (mhd_admin);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
TALER_EXCHANGEDB_plugin_unload (TEH_plugin);
|
TALER_EXCHANGEDB_plugin_unload (TEH_plugin);
|
||||||
|
@ -1,218 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of TALER
|
|
||||||
Copyright (C) 2014, 2015 GNUnet e.V.
|
|
||||||
|
|
||||||
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
|
|
||||||
Foundation; either version 3, or (at your option) any later version.
|
|
||||||
|
|
||||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License along with
|
|
||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @file taler-exchange-httpd_admin.c
|
|
||||||
* @brief Handle /admin/ requests
|
|
||||||
* @author Christian Grothoff
|
|
||||||
*/
|
|
||||||
#include "platform.h"
|
|
||||||
#include <gnunet/gnunet_util_lib.h>
|
|
||||||
#include <jansson.h>
|
|
||||||
#include "taler-exchange-httpd_admin.h"
|
|
||||||
#include "taler-exchange-httpd_parsing.h"
|
|
||||||
#include "taler-exchange-httpd_responses.h"
|
|
||||||
#include "taler-exchange-httpd_validation.h"
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Closure for #admin_add_incoming_transaction()
|
|
||||||
*/
|
|
||||||
struct AddIncomingContext
|
|
||||||
{
|
|
||||||
/**
|
|
||||||
* public key of the reserve
|
|
||||||
*/
|
|
||||||
struct TALER_ReservePublicKeyP reserve_pub;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* amount to add to the reserve
|
|
||||||
*/
|
|
||||||
struct TALER_Amount amount;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* When did we receive the wire transfer
|
|
||||||
*/
|
|
||||||
struct GNUNET_TIME_Absolute execution_time;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* which account send the funds
|
|
||||||
*/
|
|
||||||
json_t *sender_account_details;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Information that uniquely identifies the transfer
|
|
||||||
*/
|
|
||||||
json_t *transfer_details;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set to the transaction status.
|
|
||||||
*/
|
|
||||||
enum GNUNET_DB_QueryStatus qs;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an incoming transaction to the database. Checks if the
|
|
||||||
* transaction is fresh (not a duplicate) and if so adds it to the
|
|
||||||
* database.
|
|
||||||
*
|
|
||||||
* If it returns a non-error code, the transaction logic MUST
|
|
||||||
* NOT queue a MHD response. IF it returns an hard error, the
|
|
||||||
* transaction logic MUST queue a MHD response and set @a mhd_ret. IF
|
|
||||||
* it returns the soft error code, the function MAY be called again to
|
|
||||||
* retry and MUST not queue a MHD response.
|
|
||||||
*
|
|
||||||
* @param cls closure with the `struct AddIncomingContext *`
|
|
||||||
* @param connection MHD request which triggered the transaction
|
|
||||||
* @param session database session to use
|
|
||||||
* @param[out] mhd_ret set to MHD response status for @a connection,
|
|
||||||
* if transaction failed (!)
|
|
||||||
* @return transaction status
|
|
||||||
*/
|
|
||||||
static enum GNUNET_DB_QueryStatus
|
|
||||||
admin_add_incoming_transaction (void *cls,
|
|
||||||
struct MHD_Connection *connection,
|
|
||||||
struct TALER_EXCHANGEDB_Session *session,
|
|
||||||
int *mhd_ret)
|
|
||||||
{
|
|
||||||
struct AddIncomingContext *aic = cls;
|
|
||||||
void *json_str;
|
|
||||||
|
|
||||||
json_str = json_dumps (aic->transfer_details,
|
|
||||||
JSON_INDENT(2));
|
|
||||||
if (NULL == json_str)
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
*mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
|
|
||||||
TALER_EC_PARSER_OUT_OF_MEMORY);
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
aic->qs = TEH_plugin->reserves_in_insert (TEH_plugin->cls,
|
|
||||||
session,
|
|
||||||
&aic->reserve_pub,
|
|
||||||
&aic->amount,
|
|
||||||
aic->execution_time,
|
|
||||||
aic->sender_account_details,
|
|
||||||
json_str,
|
|
||||||
strlen (json_str));
|
|
||||||
free (json_str);
|
|
||||||
|
|
||||||
if (GNUNET_DB_STATUS_HARD_ERROR == aic->qs)
|
|
||||||
{
|
|
||||||
GNUNET_break (0);
|
|
||||||
*mhd_ret = TEH_RESPONSE_reply_internal_db_error (connection,
|
|
||||||
TALER_EC_ADMIN_ADD_INCOMING_DB_STORE);
|
|
||||||
return GNUNET_DB_STATUS_HARD_ERROR;
|
|
||||||
}
|
|
||||||
return aic->qs;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle a "/admin/add/incoming" request. Parses the
|
|
||||||
* given "reserve_pub", "amount", "transaction" and "h_wire"
|
|
||||||
* details and adds the respective transaction to the database.
|
|
||||||
*
|
|
||||||
* @param rh context of the handler
|
|
||||||
* @param connection the MHD connection to handle
|
|
||||||
* @param[in,out] connection_cls the connection's closure (can be updated)
|
|
||||||
* @param upload_data upload data
|
|
||||||
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
|
|
||||||
* @return MHD result code
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
TEH_ADMIN_handler_admin_add_incoming (struct TEH_RequestHandler *rh,
|
|
||||||
struct MHD_Connection *connection,
|
|
||||||
void **connection_cls,
|
|
||||||
const char *upload_data,
|
|
||||||
size_t *upload_data_size)
|
|
||||||
{
|
|
||||||
struct AddIncomingContext aic;
|
|
||||||
enum TALER_ErrorCode ec;
|
|
||||||
char *emsg;
|
|
||||||
json_t *root;
|
|
||||||
struct GNUNET_JSON_Specification spec[] = {
|
|
||||||
GNUNET_JSON_spec_fixed_auto ("reserve_pub", &aic.reserve_pub),
|
|
||||||
TALER_JSON_spec_amount ("amount", &aic.amount),
|
|
||||||
GNUNET_JSON_spec_absolute_time ("execution_date", &aic.execution_time),
|
|
||||||
GNUNET_JSON_spec_json ("sender_account_details", &aic.sender_account_details),
|
|
||||||
GNUNET_JSON_spec_json ("transfer_details", &aic.transfer_details),
|
|
||||||
GNUNET_JSON_spec_end ()
|
|
||||||
};
|
|
||||||
int res;
|
|
||||||
int mhd_ret;
|
|
||||||
|
|
||||||
res = TEH_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;
|
|
||||||
res = TEH_PARSE_json_data (connection,
|
|
||||||
root,
|
|
||||||
spec);
|
|
||||||
json_decref (root);
|
|
||||||
if (GNUNET_OK != res)
|
|
||||||
{
|
|
||||||
GNUNET_break_op (0);
|
|
||||||
json_decref (root);
|
|
||||||
return (GNUNET_SYSERR == res) ? MHD_NO : MHD_YES;
|
|
||||||
}
|
|
||||||
if (TALER_EC_NONE !=
|
|
||||||
(ec = TEH_json_validate_wireformat (aic.sender_account_details,
|
|
||||||
GNUNET_NO,
|
|
||||||
&emsg)))
|
|
||||||
{
|
|
||||||
GNUNET_JSON_parse_free (spec);
|
|
||||||
mhd_ret = TEH_RESPONSE_reply_external_error (connection,
|
|
||||||
ec,
|
|
||||||
emsg);
|
|
||||||
GNUNET_free (emsg);
|
|
||||||
return mhd_ret;
|
|
||||||
}
|
|
||||||
if (0 != strcasecmp (aic.amount.currency,
|
|
||||||
TEH_exchange_currency_string))
|
|
||||||
{
|
|
||||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
|
||||||
"Exchange uses currency `%s', but /admin/add/incoming tried to use currency `%s'\n",
|
|
||||||
TEH_exchange_currency_string,
|
|
||||||
aic.amount.currency);
|
|
||||||
GNUNET_JSON_parse_free (spec);
|
|
||||||
return TEH_RESPONSE_reply_arg_invalid (connection,
|
|
||||||
TALER_EC_ADMIN_ADD_INCOMING_CURRENCY_UNSUPPORTED,
|
|
||||||
"amount:currency");
|
|
||||||
}
|
|
||||||
res = TEH_DB_run_transaction (connection,
|
|
||||||
&mhd_ret,
|
|
||||||
&admin_add_incoming_transaction,
|
|
||||||
&aic);
|
|
||||||
GNUNET_JSON_parse_free (spec);
|
|
||||||
if (GNUNET_OK != res)
|
|
||||||
return mhd_ret;
|
|
||||||
return TEH_RESPONSE_reply_json_pack (connection,
|
|
||||||
MHD_HTTP_OK,
|
|
||||||
"{s:s}",
|
|
||||||
"status",
|
|
||||||
(GNUNET_DB_STATUS_SUCCESS_ONE_RESULT == aic.qs)
|
|
||||||
? "NEW"
|
|
||||||
: "DUP");
|
|
||||||
}
|
|
||||||
|
|
||||||
/* end of taler-exchange-httpd_admin.c */
|
|
@ -1,46 +0,0 @@
|
|||||||
/*
|
|
||||||
This file is part of TALER
|
|
||||||
Copyright (C) 2014 GNUnet e.V.
|
|
||||||
|
|
||||||
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
|
|
||||||
Foundation; either version 3, or (at your option) any later version.
|
|
||||||
|
|
||||||
TALER is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
||||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
|
||||||
A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
|
|
||||||
|
|
||||||
You should have received a copy of the GNU Affero General Public License along with
|
|
||||||
TALER; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
|
|
||||||
*/
|
|
||||||
/**
|
|
||||||
* @file taler-exchange-httpd_admin.h
|
|
||||||
* @brief Handle /admin/ requests
|
|
||||||
* @author Christian Grothoff
|
|
||||||
*/
|
|
||||||
#ifndef TALER_EXCHANGE_HTTPD_ADMIN_H
|
|
||||||
#define TALER_EXCHANGE_HTTPD_ADMIN_H
|
|
||||||
|
|
||||||
#include <microhttpd.h>
|
|
||||||
#include "taler-exchange-httpd.h"
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle a "/admin/add/incoming" request. Parses the
|
|
||||||
* given "reserve_pub", "amount", "transaction" and "h_wire"
|
|
||||||
* details and adds the respective transaction to the database.
|
|
||||||
*
|
|
||||||
* @param rh context of the handler
|
|
||||||
* @param connection the MHD connection to handle
|
|
||||||
* @param[in,out] connection_cls the connection's closure (can be updated)
|
|
||||||
* @param upload_data upload data
|
|
||||||
* @param[in,out] upload_data_size number of bytes (left) in @a upload_data
|
|
||||||
* @return MHD result code
|
|
||||||
*/
|
|
||||||
int
|
|
||||||
TEH_ADMIN_handler_admin_add_incoming (struct TEH_RequestHandler *rh,
|
|
||||||
struct MHD_Connection *connection,
|
|
||||||
void **connection_cls,
|
|
||||||
const char *upload_data,
|
|
||||||
size_t *upload_data_size);
|
|
||||||
|
|
||||||
#endif
|
|
Loading…
Reference in New Issue
Block a user