Compare commits
10 Commits
1d0f9e338d
...
5104b43902
Author | SHA1 | Date | |
---|---|---|---|
5104b43902 | |||
|
dfe245814c | ||
|
ae866fc45d | ||
|
3a5eb9285c | ||
|
5ad1d0d3dd | ||
|
b3e4159c2e | ||
|
bbdc7649f7 | ||
|
5a7dd00125 | ||
|
e8fc5d8d5c | ||
|
170402203a |
@ -5,7 +5,8 @@ PartOf=taler-exchange.target
|
||||
[Service]
|
||||
User=taler-exchange-aggregator
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
Restart=always
|
||||
RestartSec=100ms
|
||||
ExecStart=/usr/bin/taler-exchange-aggregator -c /etc/taler/taler.conf
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
@ -5,7 +5,8 @@ PartOf=taler-exchange.target
|
||||
[Service]
|
||||
User=taler-exchange-closer
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
Restart=always
|
||||
RestartSec=100ms
|
||||
ExecStart=/usr/bin/taler-exchange-closer -c /etc/taler/taler.conf
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
@ -8,7 +8,11 @@ PartOf=taler-exchange.target
|
||||
[Service]
|
||||
User=taler-exchange-httpd
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
# Depending on the configuration, the service suicides and then
|
||||
# needs to be restarted.
|
||||
Restart=always
|
||||
# Do not dally on restarts.
|
||||
RestartSec=1ms
|
||||
ExecStart=/usr/bin/taler-exchange-httpd -c /etc/taler/taler.conf
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
26
debian/taler-exchange.taler-exchange-httpd@.service
vendored
Normal file
26
debian/taler-exchange.taler-exchange-httpd@.service
vendored
Normal file
@ -0,0 +1,26 @@
|
||||
% This is a systemd service template.
|
||||
[Unit]
|
||||
Description=GNU Taler payment system exchange REST API at %I
|
||||
AssertPathExists=/run/taler/exchange-httpd
|
||||
Requires=taler-exchange-httpd@%i.socket taler-exchange-secmod-rsa.service taler-exchange-secmod-eddsa.service
|
||||
After=postgres.service network.target taler-exchange-secmod-rsa.service taler-exchange-secmod-eddsa.service
|
||||
PartOf=taler-exchange.target
|
||||
|
||||
[Service]
|
||||
User=taler-exchange-httpd
|
||||
Type=simple
|
||||
# Depending on the configuration, the service suicides and then
|
||||
# needs to be restarted.
|
||||
Restart=always
|
||||
# Do not dally on restarts.
|
||||
RestartSec=1ms
|
||||
EnvironmentFile=/etc/environment
|
||||
ExecStart=/usr/bin/taler-exchange-httpd -c /etc/taler/taler.conf
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
PrivateTmp=no
|
||||
PrivateDevices=yes
|
||||
ProtectSystem=full
|
||||
|
||||
[Install]
|
||||
WantedBy=multi-user.target
|
14
debian/taler-exchange.taler-exchange-httpd@.socket
vendored
Normal file
14
debian/taler-exchange.taler-exchange-httpd@.socket
vendored
Normal file
@ -0,0 +1,14 @@
|
||||
[Unit]
|
||||
Description=Taler Exchange Socket at %I
|
||||
PartOf=taler-exchange-httpd@%i.service
|
||||
|
||||
[Socket]
|
||||
ListenStream=80
|
||||
Accept=no
|
||||
Service=taler-exchange-httpd@%i.service
|
||||
SocketUser=taler-exchange-httpd
|
||||
SocketGroup=www-data
|
||||
SocketMode=0660
|
||||
|
||||
[Install]
|
||||
WantedBy=sockets.target
|
@ -6,7 +6,8 @@ PartOf=taler-exchange.target
|
||||
[Service]
|
||||
User=taler-exchange-secmod-eddsa
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
Restart=always
|
||||
RestartSec=100ms
|
||||
ExecStart=/usr/bin/taler-exchange-secmod-eddsa -c /etc/taler/taler.conf
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
@ -6,7 +6,8 @@ PartOf=taler-exchange.target
|
||||
[Service]
|
||||
User=taler-exchange-secmod-rsa
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
Restart=always
|
||||
RestartSec=100ms
|
||||
ExecStart=/usr/bin/taler-exchange-secmod-rsa -c /etc/taler/taler.conf
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
@ -6,7 +6,8 @@ PartOf=taler-exchange.target
|
||||
[Service]
|
||||
User=taler-exchange-wire
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
Restart=always
|
||||
RestartSec=100ms
|
||||
ExecStart=/usr/bin/taler-exchange-transfer -c /etc/taler/taler.conf
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
@ -6,7 +6,8 @@ PartOf=taler-exchange.target
|
||||
[Service]
|
||||
User=taler-exchange-wire
|
||||
Type=simple
|
||||
Restart=on-failure
|
||||
Restart=always
|
||||
RestartSec=100ms
|
||||
ExecStart=/usr/bin/taler-exchange-wirewatch -c /etc/taler/taler.conf
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
|
16
debian/taler-exchange.taler-exchange-wirewatch@.service
vendored
Normal file
16
debian/taler-exchange.taler-exchange-wirewatch@.service
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
[Unit]
|
||||
Description=GNU Taler payment system exchange wirewatch service
|
||||
After=network.target
|
||||
PartOf=taler-exchange.target
|
||||
|
||||
[Service]
|
||||
User=taler-exchange-wire
|
||||
Type=simple
|
||||
Restart=always
|
||||
RestartSec=100ms
|
||||
ExecStart=/usr/bin/taler-exchange-wirewatch -c /etc/taler/taler.conf
|
||||
StandardOutput=journal
|
||||
StandardError=journal
|
||||
PrivateTmp=yes
|
||||
PrivateDevices=yes
|
||||
ProtectSystem=full
|
@ -40,6 +40,9 @@ PORT = 8081
|
||||
# transfers to enable tracking.
|
||||
BASE_URL = http://localhost:8081/
|
||||
|
||||
# Maximum number of requests this process should handle before
|
||||
# committing suicide.
|
||||
# MAX_REQUESTS =
|
||||
|
||||
# How long should the aggregator sleep if it has nothing to do?
|
||||
AGGREGATOR_IDLE_SLEEP_INTERVAL = 60 s
|
||||
|
@ -76,6 +76,11 @@ static int allow_address_reuse;
|
||||
*/
|
||||
const struct GNUNET_CONFIGURATION_Handle *TEH_cfg;
|
||||
|
||||
/**
|
||||
* Handle to the HTTP server.
|
||||
*/
|
||||
static struct MHD_Daemon *mhd;
|
||||
|
||||
/**
|
||||
* Our KYC configuration.
|
||||
*/
|
||||
@ -122,6 +127,17 @@ static unsigned int connection_timeout = 30;
|
||||
*/
|
||||
static int connection_close;
|
||||
|
||||
/**
|
||||
* -I command-line flag given?
|
||||
*/
|
||||
int TEH_check_invariants_flag;
|
||||
|
||||
/**
|
||||
* True if we should commit suicide once all active
|
||||
* connections are finished.
|
||||
*/
|
||||
bool TEH_suicide;
|
||||
|
||||
/**
|
||||
* Value to return from main()
|
||||
*/
|
||||
@ -137,6 +153,11 @@ static uint16_t serve_port;
|
||||
*/
|
||||
static unsigned long long req_count;
|
||||
|
||||
/**
|
||||
* Counter for the number of open connections.
|
||||
*/
|
||||
static unsigned long long active_connections;
|
||||
|
||||
/**
|
||||
* Limit for the number of requests this HTTP may process before restarting.
|
||||
* (This was added as one way of dealing with unavoidable memory fragmentation
|
||||
@ -262,6 +283,45 @@ handle_post_coins (struct TEH_RequestContext *rc,
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Increments our request counter and checks if this
|
||||
* process should commit suicide.
|
||||
*/
|
||||
static void
|
||||
check_suicide (void)
|
||||
{
|
||||
int fd;
|
||||
pid_t chld;
|
||||
unsigned long long cnt;
|
||||
|
||||
cnt = req_count++;
|
||||
if (req_max != cnt)
|
||||
return;
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Restarting exchange service after %llu requests\n",
|
||||
cnt);
|
||||
/* Stop accepting new connections */
|
||||
fd = MHD_quiesce_daemon (mhd);
|
||||
GNUNET_break (0 == close (fd));
|
||||
/* Continue handling existing connections in child,
|
||||
so that this process can die and be replaced by
|
||||
systemd with a fresh one */
|
||||
chld = fork ();
|
||||
if (-1 == chld)
|
||||
{
|
||||
GNUNET_log_strerror (GNUNET_ERROR_TYPE_ERROR,
|
||||
"fork");
|
||||
_exit (1);
|
||||
}
|
||||
if (0 != chld)
|
||||
{
|
||||
/* We are the parent, instant-suicide! */
|
||||
_exit (0);
|
||||
}
|
||||
TEH_suicide = true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function called whenever MHD is done with a request. If the
|
||||
* request was a POST, we may have stored a `struct Buffer *` in the
|
||||
@ -290,6 +350,7 @@ handle_mhd_completion_callback (void *cls,
|
||||
return;
|
||||
GNUNET_async_scope_enter (&rc->async_scope_id,
|
||||
&old_scope);
|
||||
check_suicide ();
|
||||
TEH_check_invariants ();
|
||||
if (NULL != rc->rh_cleaner)
|
||||
rc->rh_cleaner (rc);
|
||||
@ -1642,8 +1703,19 @@ connection_done (void *cls,
|
||||
(void) cls;
|
||||
(void) connection;
|
||||
(void) socket_context;
|
||||
unsigned long long cnt;
|
||||
|
||||
switch (toe)
|
||||
{
|
||||
case MHD_CONNECTION_NOTIFY_STARTED:
|
||||
active_connections++;
|
||||
break;
|
||||
case MHD_CONNECTION_NOTIFY_CLOSED:
|
||||
active_connections--;
|
||||
if (TEH_suicide &&
|
||||
(0 == active_connections) )
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
break;
|
||||
}
|
||||
#if HAVE_DEVELOPER
|
||||
/* We only act if the connection is closed. */
|
||||
if (MHD_CONNECTION_NOTIFY_CLOSED != toe)
|
||||
@ -1651,15 +1723,6 @@ connection_done (void *cls,
|
||||
if (NULL != input_filename)
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
#endif
|
||||
cnt = req_count++;
|
||||
if (req_max == cnt)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Restarting exchange service after %llu requests\n",
|
||||
cnt);
|
||||
(void) kill (getpid (),
|
||||
SIGTERM);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -1780,46 +1843,42 @@ run (void *cls,
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
return;
|
||||
}
|
||||
{
|
||||
struct MHD_Daemon *mhd;
|
||||
|
||||
mhd = MHD_start_daemon (MHD_USE_SUSPEND_RESUME
|
||||
| MHD_USE_PIPE_FOR_SHUTDOWN
|
||||
| MHD_USE_DEBUG | MHD_USE_DUAL_STACK
|
||||
| MHD_USE_TCP_FASTOPEN,
|
||||
(-1 == fh) ? serve_port : 0,
|
||||
NULL, NULL,
|
||||
&handle_mhd_request, NULL,
|
||||
MHD_OPTION_LISTEN_BACKLOG_SIZE,
|
||||
(unsigned int) 1024,
|
||||
MHD_OPTION_LISTEN_SOCKET,
|
||||
fh,
|
||||
MHD_OPTION_EXTERNAL_LOGGER,
|
||||
&TALER_MHD_handle_logs,
|
||||
NULL,
|
||||
MHD_OPTION_NOTIFY_COMPLETED,
|
||||
&handle_mhd_completion_callback,
|
||||
NULL,
|
||||
MHD_OPTION_NOTIFY_CONNECTION,
|
||||
&connection_done,
|
||||
NULL,
|
||||
MHD_OPTION_CONNECTION_TIMEOUT,
|
||||
connection_timeout,
|
||||
(0 == allow_address_reuse)
|
||||
mhd = MHD_start_daemon (MHD_USE_SUSPEND_RESUME
|
||||
| MHD_USE_PIPE_FOR_SHUTDOWN
|
||||
| MHD_USE_DEBUG | MHD_USE_DUAL_STACK
|
||||
| MHD_USE_TCP_FASTOPEN,
|
||||
(-1 == fh) ? serve_port : 0,
|
||||
NULL, NULL,
|
||||
&handle_mhd_request, NULL,
|
||||
MHD_OPTION_LISTEN_BACKLOG_SIZE,
|
||||
(unsigned int) 1024,
|
||||
MHD_OPTION_LISTEN_SOCKET,
|
||||
fh,
|
||||
MHD_OPTION_EXTERNAL_LOGGER,
|
||||
&TALER_MHD_handle_logs,
|
||||
NULL,
|
||||
MHD_OPTION_NOTIFY_COMPLETED,
|
||||
&handle_mhd_completion_callback,
|
||||
NULL,
|
||||
MHD_OPTION_NOTIFY_CONNECTION,
|
||||
&connection_done,
|
||||
NULL,
|
||||
MHD_OPTION_CONNECTION_TIMEOUT,
|
||||
connection_timeout,
|
||||
(0 == allow_address_reuse)
|
||||
? MHD_OPTION_END
|
||||
: MHD_OPTION_LISTENING_ADDRESS_REUSE,
|
||||
(unsigned int) allow_address_reuse,
|
||||
MHD_OPTION_END);
|
||||
if (NULL == mhd)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to launch HTTP service. Is the port in use?\n");
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
return;
|
||||
}
|
||||
global_ret = EXIT_SUCCESS;
|
||||
TALER_MHD_daemon_start (mhd);
|
||||
(unsigned int) allow_address_reuse,
|
||||
MHD_OPTION_END);
|
||||
if (NULL == mhd)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
|
||||
"Failed to launch HTTP service. Is the port in use?\n");
|
||||
GNUNET_SCHEDULER_shutdown ();
|
||||
return;
|
||||
}
|
||||
global_ret = EXIT_SUCCESS;
|
||||
TALER_MHD_daemon_start (mhd);
|
||||
atexit (&write_stats);
|
||||
|
||||
#if HAVE_DEVELOPER
|
||||
@ -1849,6 +1908,10 @@ main (int argc,
|
||||
"connection-close",
|
||||
"force HTTP connections to be closed after each request",
|
||||
&connection_close),
|
||||
GNUNET_GETOPT_option_flag ('I',
|
||||
"check-invariants",
|
||||
"enable expensive invariant checks",
|
||||
&TEH_check_invariants_flag),
|
||||
GNUNET_GETOPT_option_flag ('r',
|
||||
"allow-reuse-address",
|
||||
"allow multiple HTTPDs to listen to the same port",
|
||||
|
@ -144,6 +144,11 @@ extern const struct GNUNET_CONFIGURATION_Handle *TEH_cfg;
|
||||
*/
|
||||
extern char *TEH_exchange_directory;
|
||||
|
||||
/**
|
||||
* -I command-line flag given?
|
||||
*/
|
||||
extern int TEH_check_invariants_flag;
|
||||
|
||||
/**
|
||||
* Are clients allowed to request /keys for times other than the
|
||||
* current time? Allowing this could be abused in a DoS-attack
|
||||
@ -157,6 +162,13 @@ extern int TEH_allow_keys_timetravel;
|
||||
*/
|
||||
extern char *TEH_revocation_directory;
|
||||
|
||||
/**
|
||||
* True if we should commit suicide once all active
|
||||
* connections are finished. Also forces /keys requests
|
||||
* to terminate if they are long-polling.
|
||||
*/
|
||||
extern bool TEH_suicide;
|
||||
|
||||
/**
|
||||
* Master public key (according to the
|
||||
* configuration in the exchange directory).
|
||||
|
@ -36,6 +36,12 @@
|
||||
#define SKR_LIMIT 32
|
||||
|
||||
|
||||
/**
|
||||
* When do we forcefully timeout a /keys request?
|
||||
*/
|
||||
#define KEYS_TIMEOUT GNUNET_TIME_UNIT_MINUTES
|
||||
|
||||
|
||||
/**
|
||||
* Taler protocol version in the format CURRENT:REVISION:AGE
|
||||
* as used by GNU libtool. See
|
||||
@ -355,6 +361,11 @@ struct SuspendedKeysRequests
|
||||
* The suspended connection.
|
||||
*/
|
||||
struct MHD_Connection *connection;
|
||||
|
||||
/**
|
||||
* When does this request timeout?
|
||||
*/
|
||||
struct GNUNET_TIME_Absolute timeout;
|
||||
};
|
||||
|
||||
|
||||
@ -398,6 +409,11 @@ static unsigned int skr_size;
|
||||
*/
|
||||
static struct MHD_Connection *skr_connection;
|
||||
|
||||
/**
|
||||
* Task to force timeouts on /keys requests.
|
||||
*/
|
||||
static struct GNUNET_SCHEDULER_Task *keys_tt;
|
||||
|
||||
/**
|
||||
* For how long should a signing key be legally retained?
|
||||
* Configuration value.
|
||||
@ -419,6 +435,40 @@ static struct TALER_SecurityModulePublicKeyP esign_sm_pub;
|
||||
*/
|
||||
static bool terminating;
|
||||
|
||||
|
||||
/**
|
||||
* Function called to forcefully resume suspended keys requests.
|
||||
*
|
||||
* @param cls unused, NULL
|
||||
*/
|
||||
static void
|
||||
keys_timeout_cb (void *cls)
|
||||
{
|
||||
struct SuspendedKeysRequests *skr;
|
||||
|
||||
(void) cls;
|
||||
keys_tt = NULL;
|
||||
while (NULL != (skr = skr_head))
|
||||
{
|
||||
if (GNUNET_TIME_absolute_is_future (skr->timeout))
|
||||
break;
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Resuming /keys request due to timeout\n");
|
||||
GNUNET_CONTAINER_DLL_remove (skr_head,
|
||||
skr_tail,
|
||||
skr);
|
||||
MHD_resume_connection (skr->connection);
|
||||
TALER_MHD_daemon_trigger ();
|
||||
GNUNET_free (skr);
|
||||
}
|
||||
if (NULL == skr)
|
||||
return;
|
||||
keys_tt = GNUNET_SCHEDULER_add_at (skr->timeout,
|
||||
&keys_timeout_cb,
|
||||
NULL);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Suspend /keys request while we (hopefully) are waiting to be
|
||||
* provisioned with key material.
|
||||
@ -445,6 +495,13 @@ suspend_request (struct MHD_Connection *connection)
|
||||
GNUNET_CONTAINER_DLL_insert (skr_head,
|
||||
skr_tail,
|
||||
skr);
|
||||
skr->timeout = GNUNET_TIME_relative_to_absolute (KEYS_TIMEOUT);
|
||||
if (NULL == keys_tt)
|
||||
{
|
||||
keys_tt = GNUNET_SCHEDULER_add_at (skr->timeout,
|
||||
&keys_timeout_cb,
|
||||
NULL);
|
||||
}
|
||||
skr_size++;
|
||||
if (skr_size > SKR_LIMIT)
|
||||
{
|
||||
@ -477,9 +534,8 @@ check_dk (void *cls,
|
||||
{
|
||||
struct TEH_DenominationKey *dk = value;
|
||||
|
||||
|
||||
(void) cls;
|
||||
(void) hc;
|
||||
(void) value;
|
||||
GNUNET_assert (TALER_DENOMINATION_INVALID != dk->denom_pub.cipher);
|
||||
if (TALER_DENOMINATION_RSA == dk->denom_pub.cipher)
|
||||
GNUNET_assert (GNUNET_CRYPTO_rsa_public_key_check (
|
||||
@ -493,6 +549,8 @@ TEH_check_invariants ()
|
||||
{
|
||||
struct TEH_KeyStateHandle *ksh;
|
||||
|
||||
if (0 == TEH_check_invariants_flag)
|
||||
return;
|
||||
ksh = TEH_keys_get_state ();
|
||||
if (NULL == ksh)
|
||||
return;
|
||||
@ -1073,6 +1131,11 @@ TEH_keys_init ()
|
||||
void
|
||||
TEH_keys_finished ()
|
||||
{
|
||||
if (NULL != keys_tt)
|
||||
{
|
||||
GNUNET_SCHEDULER_cancel (keys_tt);
|
||||
keys_tt = NULL;
|
||||
}
|
||||
if (NULL != key_state)
|
||||
destroy_key_state (key_state,
|
||||
true);
|
||||
@ -2282,13 +2345,17 @@ TEH_keys_get_handler (struct TEH_RequestContext *rc,
|
||||
ksh = TEH_keys_get_state ();
|
||||
if (NULL == ksh)
|
||||
{
|
||||
if ( (SKR_LIMIT == skr_size) &&
|
||||
(rc->connection == skr_connection) )
|
||||
if ( ( (SKR_LIMIT == skr_size) &&
|
||||
(rc->connection == skr_connection) ) ||
|
||||
TEH_suicide)
|
||||
{
|
||||
return TALER_MHD_reply_with_error (rc->connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
|
||||
"too many connections suspended on /keys");
|
||||
return TALER_MHD_reply_with_error (
|
||||
rc->connection,
|
||||
MHD_HTTP_SERVICE_UNAVAILABLE,
|
||||
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
|
||||
TEH_suicide
|
||||
? "server terminating"
|
||||
: "too many connections suspended waiting on /keys");
|
||||
}
|
||||
return suspend_request (rc->connection);
|
||||
}
|
||||
@ -2688,7 +2755,7 @@ TEH_keys_management_get_keys_handler (const struct TEH_RequestHandler *rh,
|
||||
if (NULL == ksh)
|
||||
{
|
||||
return TALER_MHD_reply_with_error (connection,
|
||||
MHD_HTTP_INTERNAL_SERVER_ERROR,
|
||||
MHD_HTTP_SERVICE_UNAVAILABLE,
|
||||
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
|
||||
"no key state");
|
||||
}
|
||||
|
@ -271,6 +271,7 @@ refreshes_reveal_transaction (void *cls,
|
||||
|
||||
/* Obtain basic information about the refresh operation and what
|
||||
gamma we committed to. */
|
||||
// FIXME: why do we do 'get_melt' twice?
|
||||
qs = TEH_plugin->get_melt (TEH_plugin->cls,
|
||||
&rctx->rc,
|
||||
&melt);
|
||||
@ -611,6 +612,7 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
||||
{
|
||||
enum GNUNET_DB_QueryStatus qs;
|
||||
|
||||
// FIXME: why do we do 'get_melt' twice?
|
||||
if (GNUNET_DB_STATUS_SUCCESS_ONE_RESULT !=
|
||||
(qs = TEH_plugin->get_melt (TEH_plugin->cls,
|
||||
&rctx->rc,
|
||||
@ -682,9 +684,13 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
||||
rctx->dks = dks;
|
||||
rctx->link_sigs = link_sigs;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Optimistically creating %u signatures\n",
|
||||
(unsigned int) rctx->num_fresh_coins);
|
||||
/* sign _early_ (optimistic!) to keep out of transaction scope! */
|
||||
rctx->ev_sigs = GNUNET_new_array (rctx->num_fresh_coins,
|
||||
struct TALER_BlindedDenominationSignature);
|
||||
// FIXME: this is sequential, modify logic to enable parallel signing!
|
||||
for (unsigned int i = 0; i<rctx->num_fresh_coins; i++)
|
||||
{
|
||||
enum TALER_ErrorCode ec = TALER_EC_NONE;
|
||||
@ -705,6 +711,8 @@ resolve_refreshes_reveal_denominations (struct MHD_Connection *connection,
|
||||
}
|
||||
}
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Signatures ready, starting DB interaction\n");
|
||||
/* We try the three transactions a few times, as theoretically
|
||||
the pre-check might be satisfied by a concurrent transaction
|
||||
voiding our final commit due to uniqueness violation; naturally,
|
||||
|
@ -37,6 +37,11 @@ struct AuthchangeState
|
||||
* What is the new authorization token to send?
|
||||
*/
|
||||
const char *auth_token;
|
||||
|
||||
/**
|
||||
* Old context, clean up on termination.
|
||||
*/
|
||||
struct GNUNET_CURL_Context *old_ctx;
|
||||
};
|
||||
|
||||
|
||||
@ -55,11 +60,7 @@ authchange_run (void *cls,
|
||||
struct AuthchangeState *ss = cls;
|
||||
|
||||
(void) cmd;
|
||||
if (NULL != is->ctx)
|
||||
{
|
||||
GNUNET_CURL_fini (is->ctx);
|
||||
is->ctx = NULL;
|
||||
}
|
||||
ss->old_ctx = is->ctx;
|
||||
if (NULL != is->rc)
|
||||
{
|
||||
GNUNET_CURL_gnunet_rc_destroy (is->rc);
|
||||
@ -101,6 +102,11 @@ authchange_cleanup (void *cls,
|
||||
struct AuthchangeState *ss = cls;
|
||||
|
||||
(void) cmd;
|
||||
if (NULL != ss->old_ctx)
|
||||
{
|
||||
GNUNET_CURL_fini (ss->old_ctx);
|
||||
ss->old_ctx = NULL;
|
||||
}
|
||||
GNUNET_free (ss);
|
||||
}
|
||||
|
||||
|
@ -42,11 +42,11 @@ TALER_mhd_is_https (struct MHD_Connection *connection)
|
||||
|
||||
if (NULL != forwarded_proto)
|
||||
{
|
||||
if (0 == strcmp (forwarded_proto,
|
||||
"https"))
|
||||
if (0 == strcasecmp (forwarded_proto,
|
||||
"https"))
|
||||
return GNUNET_YES;
|
||||
if (0 == strcmp (forwarded_proto,
|
||||
"http"))
|
||||
if (0 == strcasecmp (forwarded_proto,
|
||||
"http"))
|
||||
return GNUNET_NO;
|
||||
GNUNET_break (0);
|
||||
return GNUNET_SYSERR;
|
||||
|
@ -74,17 +74,15 @@ static volatile bool in_shutdown;
|
||||
|
||||
|
||||
enum GNUNET_GenericReturnValue
|
||||
TES_transmit (int sock,
|
||||
const struct GNUNET_MessageHeader *hdr)
|
||||
TES_transmit_raw (int sock,
|
||||
size_t end,
|
||||
const void *pos)
|
||||
{
|
||||
ssize_t off = 0;
|
||||
const void *pos = hdr;
|
||||
uint16_t end = ntohs (hdr->size);
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Sending message of type %u and length %u\n",
|
||||
(unsigned int) ntohs (hdr->type),
|
||||
(unsigned int) ntohs (hdr->size));
|
||||
"Sending message of length %u\n",
|
||||
(unsigned int) end);
|
||||
while (off < end)
|
||||
{
|
||||
ssize_t ret = send (sock,
|
||||
@ -118,6 +116,20 @@ TES_transmit (int sock,
|
||||
}
|
||||
|
||||
|
||||
enum GNUNET_GenericReturnValue
|
||||
TES_transmit (int sock,
|
||||
const struct GNUNET_MessageHeader *hdr)
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Sending message of type %u and length %u\n",
|
||||
(unsigned int) ntohs (hdr->type),
|
||||
(unsigned int) ntohs (hdr->size));
|
||||
return TES_transmit_raw (sock,
|
||||
ntohs (hdr->size),
|
||||
hdr);
|
||||
}
|
||||
|
||||
|
||||
struct GNUNET_NETWORK_Handle *
|
||||
TES_open_socket (const char *unixpath)
|
||||
{
|
||||
|
@ -51,6 +51,19 @@ TES_transmit (int sock,
|
||||
const struct GNUNET_MessageHeader *hdr);
|
||||
|
||||
|
||||
/**
|
||||
* Transmit @a end bytes from @a pos on @a sock.
|
||||
*
|
||||
* @param sock where to send the data
|
||||
* @param end how many bytes to send
|
||||
* @param pos first address with data
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
enum GNUNET_GenericReturnValue
|
||||
TES_transmit_raw (int sock,
|
||||
size_t end,
|
||||
const void *pos);
|
||||
|
||||
/**
|
||||
* Information we keep for a client connected to us.
|
||||
*/
|
||||
|
@ -85,6 +85,11 @@ struct DenominationKey
|
||||
*/
|
||||
struct GNUNET_CRYPTO_RsaPublicKey *denom_pub;
|
||||
|
||||
/**
|
||||
* Message to transmit to clients to introduce this public key.
|
||||
*/
|
||||
struct TALER_CRYPTO_RsaKeyAvailableNotification *an;
|
||||
|
||||
/**
|
||||
* Hash of this denomination's public key.
|
||||
*/
|
||||
@ -214,7 +219,6 @@ static struct GNUNET_CONTAINER_MultiHashMap *keys;
|
||||
*/
|
||||
static struct GNUNET_SCHEDULER_Task *keygen_task;
|
||||
|
||||
|
||||
/**
|
||||
* Lock for the keys queue.
|
||||
*/
|
||||
@ -227,15 +231,12 @@ static uint64_t key_gen;
|
||||
|
||||
|
||||
/**
|
||||
* Notify @a client about @a dk becoming available.
|
||||
* Generate the announcement message for @a dk.
|
||||
*
|
||||
* @param[in,out] client the client to notify; possible freed if transmission fails
|
||||
* @param dk the key to notify @a client about
|
||||
* @return #GNUNET_OK on success
|
||||
* @param[in,out] denomination key to generate the announcement for
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
notify_client_dk_add (struct TES_Client *client,
|
||||
const struct DenominationKey *dk)
|
||||
static void
|
||||
generate_response (struct DenominationKey *dk)
|
||||
{
|
||||
struct Denomination *denom = dk->denom;
|
||||
size_t nlen = strlen (denom->section) + 1;
|
||||
@ -273,55 +274,7 @@ notify_client_dk_add (struct TES_Client *client,
|
||||
memcpy (p + buf_len,
|
||||
denom->section,
|
||||
nlen);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Sending RSA denomination key %s (%s)\n",
|
||||
GNUNET_h2s (&dk->h_rsa.hash),
|
||||
denom->section);
|
||||
if (GNUNET_OK !=
|
||||
TES_transmit (client->csock,
|
||||
&an->header))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Client %p must have disconnected\n",
|
||||
client);
|
||||
GNUNET_free (an);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
GNUNET_free (an);
|
||||
return GNUNET_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Notify @a client about @a dk being purged.
|
||||
*
|
||||
* @param[in,out] client the client to notify; possible freed if transmission fails
|
||||
* @param dk the key to notify @a client about
|
||||
* @return #GNUNET_OK on success
|
||||
*/
|
||||
static enum GNUNET_GenericReturnValue
|
||||
notify_client_dk_del (struct TES_Client *client,
|
||||
const struct DenominationKey *dk)
|
||||
{
|
||||
struct TALER_CRYPTO_RsaKeyPurgeNotification pn = {
|
||||
.header.type = htons (TALER_HELPER_RSA_MT_PURGE),
|
||||
.header.size = htons (sizeof (pn)),
|
||||
.h_rsa = dk->h_rsa
|
||||
};
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Sending RSA denomination expiration %s\n",
|
||||
GNUNET_h2s (&dk->h_rsa.hash));
|
||||
if (GNUNET_OK !=
|
||||
TES_transmit (client->csock,
|
||||
&pn.header))
|
||||
{
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Client %p must have disconnected\n",
|
||||
client);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
return GNUNET_OK;
|
||||
dk->an = an;
|
||||
}
|
||||
|
||||
|
||||
@ -342,6 +295,7 @@ handle_sign_request (struct TES_Client *client,
|
||||
const void *blinded_msg = &sr[1];
|
||||
size_t blinded_msg_size = ntohs (sr->header.size) - sizeof (*sr);
|
||||
struct GNUNET_CRYPTO_RsaSignature *rsa_signature;
|
||||
struct GNUNET_TIME_Absolute now = GNUNET_TIME_absolute_get ();
|
||||
|
||||
GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
|
||||
dk = GNUNET_CONTAINER_multihashmap_get (keys,
|
||||
@ -407,6 +361,7 @@ handle_sign_request (struct TES_Client *client,
|
||||
return TES_transmit (client->csock,
|
||||
&sf.header);
|
||||
}
|
||||
|
||||
{
|
||||
struct TALER_CRYPTO_SignResponse *sr;
|
||||
void *buf;
|
||||
@ -427,7 +382,10 @@ handle_sign_request (struct TES_Client *client,
|
||||
buf_size);
|
||||
GNUNET_free (buf);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Sending RSA signature\n");
|
||||
"Sending RSA signature after %s\n",
|
||||
GNUNET_STRINGS_relative_time_to_string (
|
||||
GNUNET_TIME_absolute_get_duration (now),
|
||||
GNUNET_YES));
|
||||
ret = TES_transmit (client->csock,
|
||||
&sr->header);
|
||||
GNUNET_free (sr);
|
||||
@ -502,6 +460,7 @@ setup_key (struct DenominationKey *dk,
|
||||
dk->denom_priv = priv;
|
||||
dk->denom_pub = pub;
|
||||
dk->key_gen = key_gen;
|
||||
generate_response (dk);
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONTAINER_multihashmap_put (
|
||||
keys,
|
||||
@ -514,6 +473,7 @@ setup_key (struct DenominationKey *dk,
|
||||
GNUNET_CRYPTO_rsa_private_key_free (dk->denom_priv);
|
||||
GNUNET_CRYPTO_rsa_public_key_free (dk->denom_pub);
|
||||
GNUNET_free (dk->filename);
|
||||
GNUNET_free (dk->an);
|
||||
GNUNET_free (dk);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
@ -660,6 +620,12 @@ rsa_work_dispatch (struct TES_Client *client,
|
||||
static enum GNUNET_GenericReturnValue
|
||||
rsa_client_init (struct TES_Client *client)
|
||||
{
|
||||
size_t obs = 0;
|
||||
char *buf;
|
||||
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Initializing new client %p\n",
|
||||
client);
|
||||
GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
|
||||
for (struct Denomination *denom = denom_head;
|
||||
NULL != denom;
|
||||
@ -669,20 +635,39 @@ rsa_client_init (struct TES_Client *client)
|
||||
NULL != dk;
|
||||
dk = dk->next)
|
||||
{
|
||||
if (GNUNET_OK !=
|
||||
notify_client_dk_add (client,
|
||||
dk))
|
||||
{
|
||||
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Client %p must have disconnected\n",
|
||||
client);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
obs += ntohs (dk->an->header.size);
|
||||
}
|
||||
}
|
||||
buf = GNUNET_malloc (obs);
|
||||
obs = 0;
|
||||
for (struct Denomination *denom = denom_head;
|
||||
NULL != denom;
|
||||
denom = denom->next)
|
||||
{
|
||||
for (struct DenominationKey *dk = denom->keys_head;
|
||||
NULL != dk;
|
||||
dk = dk->next)
|
||||
{
|
||||
memcpy (&buf[obs],
|
||||
dk->an,
|
||||
ntohs (dk->an->header.size));
|
||||
obs += ntohs (dk->an->header.size);
|
||||
}
|
||||
}
|
||||
client->key_gen = key_gen;
|
||||
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
||||
if (GNUNET_OK !=
|
||||
TES_transmit_raw (client->csock,
|
||||
obs,
|
||||
buf))
|
||||
{
|
||||
GNUNET_free (buf);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_INFO,
|
||||
"Client %p must have disconnected\n",
|
||||
client);
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
GNUNET_free (buf);
|
||||
{
|
||||
struct GNUNET_MessageHeader synced = {
|
||||
.type = htons (TALER_HELPER_RSA_SYNCED),
|
||||
@ -714,7 +699,36 @@ rsa_client_init (struct TES_Client *client)
|
||||
static enum GNUNET_GenericReturnValue
|
||||
rsa_update_client_keys (struct TES_Client *client)
|
||||
{
|
||||
size_t obs = 0;
|
||||
char *buf;
|
||||
enum GNUNET_GenericReturnValue ret;
|
||||
|
||||
GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
|
||||
for (struct Denomination *denom = denom_head;
|
||||
NULL != denom;
|
||||
denom = denom->next)
|
||||
{
|
||||
for (struct DenominationKey *key = denom->keys_head;
|
||||
NULL != key;
|
||||
key = key->next)
|
||||
{
|
||||
if (key->key_gen <= client->key_gen)
|
||||
continue;
|
||||
if (key->purge)
|
||||
obs += sizeof (struct TALER_CRYPTO_RsaKeyPurgeNotification);
|
||||
else
|
||||
obs += ntohs (key->an->header.size);
|
||||
}
|
||||
}
|
||||
if (0 == obs)
|
||||
{
|
||||
/* nothing to do */
|
||||
client->key_gen = key_gen;
|
||||
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
||||
return GNUNET_OK;
|
||||
}
|
||||
buf = GNUNET_malloc (obs);
|
||||
obs = 0;
|
||||
for (struct Denomination *denom = denom_head;
|
||||
NULL != denom;
|
||||
denom = denom->next)
|
||||
@ -727,29 +741,33 @@ rsa_update_client_keys (struct TES_Client *client)
|
||||
continue;
|
||||
if (key->purge)
|
||||
{
|
||||
if (GNUNET_OK !=
|
||||
notify_client_dk_del (client,
|
||||
key))
|
||||
{
|
||||
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
struct TALER_CRYPTO_RsaKeyPurgeNotification pn = {
|
||||
.header.type = htons (TALER_HELPER_RSA_MT_PURGE),
|
||||
.header.size = htons (sizeof (pn)),
|
||||
.h_rsa = key->h_rsa
|
||||
};
|
||||
|
||||
memcpy (&buf[obs],
|
||||
&pn,
|
||||
sizeof (pn));
|
||||
obs += sizeof (pn);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (GNUNET_OK !=
|
||||
notify_client_dk_add (client,
|
||||
key))
|
||||
{
|
||||
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
||||
return GNUNET_SYSERR;
|
||||
}
|
||||
memcpy (&buf[obs],
|
||||
key->an,
|
||||
ntohs (key->an->header.size));
|
||||
obs += ntohs (key->an->header.size);
|
||||
}
|
||||
}
|
||||
}
|
||||
client->key_gen = key_gen;
|
||||
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
||||
return GNUNET_OK;
|
||||
ret = TES_transmit_raw (client->csock,
|
||||
obs,
|
||||
buf);
|
||||
GNUNET_free (buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
@ -896,6 +914,7 @@ update_keys (struct Denomination *denom,
|
||||
GNUNET_free (key->filename);
|
||||
GNUNET_CRYPTO_rsa_private_key_free (key->denom_priv);
|
||||
GNUNET_CRYPTO_rsa_public_key_free (key->denom_pub);
|
||||
GNUNET_free (key->an);
|
||||
GNUNET_free (key);
|
||||
key = nxt;
|
||||
}
|
||||
@ -943,6 +962,8 @@ update_denominations (void *cls)
|
||||
keygen_task = NULL;
|
||||
now = GNUNET_TIME_absolute_get ();
|
||||
(void) GNUNET_TIME_round_abs (&now);
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Updating denominations ...\n");
|
||||
GNUNET_assert (0 == pthread_mutex_lock (&keys_lock));
|
||||
do {
|
||||
denom = denom_head;
|
||||
@ -953,6 +974,8 @@ update_denominations (void *cls)
|
||||
return;
|
||||
} while (denom != denom_head);
|
||||
GNUNET_assert (0 == pthread_mutex_unlock (&keys_lock));
|
||||
GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
|
||||
"Updating denominations finished ...\n");
|
||||
if (wake)
|
||||
TES_wake_clients ();
|
||||
keygen_task = GNUNET_SCHEDULER_add_at (denomination_action_time (denom),
|
||||
@ -1041,6 +1064,7 @@ parse_key (struct Denomination *denom,
|
||||
TALER_rsa_pub_hash (pub,
|
||||
&dk->h_rsa);
|
||||
dk->denom_pub = pub;
|
||||
generate_response (dk);
|
||||
if (GNUNET_OK !=
|
||||
GNUNET_CONTAINER_multihashmap_put (
|
||||
keys,
|
||||
@ -1054,6 +1078,7 @@ parse_key (struct Denomination *denom,
|
||||
filename);
|
||||
GNUNET_CRYPTO_rsa_private_key_free (priv);
|
||||
GNUNET_CRYPTO_rsa_public_key_free (pub);
|
||||
GNUNET_free (dk->an);
|
||||
GNUNET_free (dk);
|
||||
return;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user