aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Grothoff <christian@grothoff.org>2021-07-21 16:08:50 +0200
committerChristian Grothoff <christian@grothoff.org>2021-07-21 16:08:50 +0200
commit3721780f16f61727e0f29505a32c4aa43b53ed51 (patch)
tree4276a4fda32ddd95a1b5de16ba23bb63a6dab7a5
parent453a21b5ba3a09231c4e621df13db2cd67783bb0 (diff)
fix bug where suspended /keys requests eat up all sockets
-rw-r--r--src/exchange/taler-exchange-httpd_keys.c43
1 files changed, 43 insertions, 0 deletions
diff --git a/src/exchange/taler-exchange-httpd_keys.c b/src/exchange/taler-exchange-httpd_keys.c
index fc38c7ac9..b703b2209 100644
--- a/src/exchange/taler-exchange-httpd_keys.c
+++ b/src/exchange/taler-exchange-httpd_keys.c
@@ -29,6 +29,13 @@
/**
+ * How many /keys request do we hold in suspension at
+ * most at any time?
+ */
+#define SKR_LIMIT 32
+
+
+/**
* 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
@@ -357,6 +364,18 @@ static struct SuspendedKeysRequests *skr_head;
static struct SuspendedKeysRequests *skr_tail;
/**
+ * Number of entries in the @e skr_head DLL.
+ */
+static unsigned int skr_size;
+
+/**
+ * Handle to a connection that should be force-resumed
+ * with a hard error due to @a skr_size hitting
+ * #SKR_LIMIT.
+ */
+static struct MHD_Connection *skr_connection;
+
+/**
* For how long should a signing key be legally retained?
* Configuration value.
*/
@@ -423,6 +442,18 @@ suspend_request (struct MHD_Connection *connection)
GNUNET_CONTAINER_DLL_insert (skr_head,
skr_tail,
skr);
+ skr_size++;
+ if (skr_size > SKR_LIMIT)
+ {
+ skr = skr_tail;
+ GNUNET_CONTAINER_DLL_remove (skr_head,
+ skr_tail,
+ skr);
+ skr_size--;
+ skr_connection = skr->connection;
+ MHD_resume_connection (skr->connection);
+ GNUNET_free (skr);
+ }
GNUNET_assert (0 == pthread_mutex_unlock (&skr_mutex));
return MHD_YES;
}
@@ -441,6 +472,7 @@ TEH_resume_keys_requests (bool do_shutdown)
GNUNET_CONTAINER_DLL_remove (skr_head,
skr_tail,
skr);
+ skr_size--;
MHD_resume_connection (skr->connection);
GNUNET_free (skr);
}
@@ -2058,6 +2090,17 @@ TEH_keys_get_handler (const struct TEH_RequestHandler *rh,
ksh = TEH_keys_get_state ();
if (NULL == ksh)
{
+ GNUNET_assert (0 == pthread_mutex_lock (&skr_mutex));
+ if ( (SKR_LIMIT == skr_size) &&
+ (connection == skr_connection) )
+ {
+ GNUNET_assert (0 == pthread_mutex_unlock (&skr_mutex));
+ return TALER_MHD_reply_with_error (connection,
+ MHD_HTTP_INTERNAL_SERVER_ERROR,
+ TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
+ "too many connections suspended on /keys");
+ }
+ GNUNET_assert (0 == pthread_mutex_unlock (&skr_mutex));
return suspend_request (connection);
}
krd = bsearch (&last_issue_date,