summaryrefslogtreecommitdiff
path: root/src/exchange/taler-exchange-httpd_keys.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/exchange/taler-exchange-httpd_keys.c')
-rw-r--r--src/exchange/taler-exchange-httpd_keys.c83
1 files changed, 74 insertions, 9 deletions
diff --git a/src/exchange/taler-exchange-httpd_keys.c b/src/exchange/taler-exchange-httpd_keys.c
index 6ac39aa80..bff057a50 100644
--- a/src/exchange/taler-exchange-httpd_keys.c
+++ b/src/exchange/taler-exchange-httpd_keys.c
@@ -37,6 +37,12 @@
/**
+ * 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
* https://www.gnu.org/software/libtool/manual/html_node/Libtool-versioning.html
@@ -355,6 +361,11 @@ struct SuspendedKeysRequests
* The suspended connection.
*/
struct MHD_Connection *connection;
+
+ /**
+ * When does this request timeout?
+ */
+ struct GNUNET_TIME_Absolute timeout;
};
@@ -399,6 +410,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 (
@@ -1073,6 +1129,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 +2343,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 +2753,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");
}