gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-exchange] branch master updated: -change handler signatures to pr


From: gnunet
Subject: [taler-exchange] branch master updated: -change handler signatures to prepare for long polling support
Date: Sat, 21 Aug 2021 14:01:39 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new f93a0592 -change handler signatures to prepare for long polling support
f93a0592 is described below

commit f93a0592b29b66c6bbacbb38f42e8dfd5a3a6aee
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Sat Aug 21 14:00:29 2021 +0200

    -change handler signatures to prepare for long polling support
---
 src/exchange/taler-exchange-httpd.c                | 201 +++++++++------------
 src/exchange/taler-exchange-httpd.h                |  77 ++++++--
 src/exchange/taler-exchange-httpd_deposits_get.c   |  30 +--
 src/exchange/taler-exchange-httpd_deposits_get.h   |   8 +-
 src/exchange/taler-exchange-httpd_keys.c           |  21 +--
 src/exchange/taler-exchange-httpd_keys.h           |   6 +-
 src/exchange/taler-exchange-httpd_link.c           |  27 +--
 src/exchange/taler-exchange-httpd_link.h           |   6 +-
 src/exchange/taler-exchange-httpd_mhd.c            |  32 +---
 src/exchange/taler-exchange-httpd_mhd.h            |  14 +-
 .../taler-exchange-httpd_refreshes_reveal.c        |  39 ++--
 .../taler-exchange-httpd_refreshes_reveal.h        |   8 +-
 src/exchange/taler-exchange-httpd_reserves_get.c   |  62 +++++--
 src/exchange/taler-exchange-httpd_reserves_get.h   |   6 +-
 src/exchange/taler-exchange-httpd_terms.c          |  35 +---
 src/exchange/taler-exchange-httpd_terms.h          |  14 +-
 src/exchange/taler-exchange-httpd_transfers_get.c  |  20 +-
 src/exchange/taler-exchange-httpd_transfers_get.h  |   8 +-
 src/exchange/taler-exchange-httpd_wire.c           |  10 +-
 src/exchange/taler-exchange-httpd_wire.h           |   8 +-
 src/exchange/taler-exchange-httpd_withdraw.c       |  41 ++---
 src/exchange/taler-exchange-httpd_withdraw.h       |   8 +-
 22 files changed, 289 insertions(+), 392 deletions(-)

diff --git a/src/exchange/taler-exchange-httpd.c 
b/src/exchange/taler-exchange-httpd.c
index 4a206b13..c39df21a 100644
--- a/src/exchange/taler-exchange-httpd.c
+++ b/src/exchange/taler-exchange-httpd.c
@@ -56,33 +56,6 @@
 #define UNIX_BACKLOG 500
 
 
-/**
- * Type of the closure associated with each HTTP request to the exchange.
- */
-struct ExchangeHttpRequestClosure
-{
-  /**
-   * Async Scope ID associated with this request.
-   */
-  struct GNUNET_AsyncScopeId async_scope_id;
-
-  /**
-   * Opaque parsing context.
-   */
-  void *opaque_post_parsing_context;
-
-  /**
-   * Cached request handler for this request (once we have found one).
-   */
-  struct TEH_RequestHandler *rh;
-
-  /**
-   * Request URL (for logging).
-   */
-  const char *url;
-};
-
-
 /**
  * Are clients allowed to request /keys for times other than the
  * current time? Allowing this could be abused in a DoS-attack
@@ -204,16 +177,14 @@ r404 (struct MHD_Connection *connection,
  * Handle a "/coins/$COIN_PUB/$OP" POST request.  Parses the "coin_pub"
  * EdDSA key of the coin and demultiplexes based on $OP.
  *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
+ * @param rc request context
  * @param root uploaded JSON data
  * @param args array of additional options (first must be the
  *         reserve public key, the second one should be "withdraw")
  * @return MHD result code
  */
 static MHD_RESULT
-handle_post_coins (const struct TEH_RequestHandler *rh,
-                   struct MHD_Connection *connection,
+handle_post_coins (struct TEH_RequestContext *rc,
                    const json_t *root,
                    const char *const args[2])
 {
@@ -253,7 +224,6 @@ handle_post_coins (const struct TEH_RequestHandler *rh,
     },
   };
 
-  (void) rh;
   if (GNUNET_OK !=
       GNUNET_STRINGS_string_to_data (args[0],
                                      strlen (args[0]),
@@ -261,7 +231,7 @@ handle_post_coins (const struct TEH_RequestHandler *rh,
                                      sizeof (coin_pub)))
   {
     GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_BAD_REQUEST,
                                        
TALER_EC_EXCHANGE_GENERIC_COINS_INVALID_COIN_PUB,
                                        args[0]);
@@ -269,10 +239,11 @@ handle_post_coins (const struct TEH_RequestHandler *rh,
   for (unsigned int i = 0; NULL != h[i].op; i++)
     if (0 == strcmp (h[i].op,
                      args[1]))
-      return h[i].handler (connection,
+      return h[i].handler (rc->connection,
                            &coin_pub,
                            root);
-  return r404 (connection, args[1]);
+  return r404 (rc->connection,
+               args[1]);
 }
 
 
@@ -296,14 +267,16 @@ handle_mhd_completion_callback (void *cls,
                                 void **con_cls,
                                 enum MHD_RequestTerminationCode toe)
 {
-  struct ExchangeHttpRequestClosure *ecls = *con_cls;
+  struct TEH_RequestContext *rc = *con_cls;
   struct GNUNET_AsyncScopeSave old_scope;
 
   (void) cls;
-  if (NULL == ecls)
+  if (NULL == rc)
     return;
-  GNUNET_async_scope_enter (&ecls->async_scope_id,
+  GNUNET_async_scope_enter (&rc->async_scope_id,
                             &old_scope);
+  if (NULL != rc->rh_cleaner)
+    rc->rh_cleaner (rc);
   {
 #if MHD_VERSION >= 0x00097304
     const union MHD_ConnectionInfo *ci;
@@ -315,52 +288,49 @@ handle_mhd_completion_callback (void *cls,
       http_status = ci->http_status;
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Request for `%s' completed with HTTP status %u (%d)\n",
-                ecls->url,
+                rc->url,
                 http_status,
                 toe);
 #else
     (void) connection;
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
                 "Request for `%s' completed (%d)\n",
-                ecls->url,
+                rc->url,
                 toe);
 #endif
   }
 
-  TALER_MHD_parse_post_cleanup_callback (ecls->opaque_post_parsing_context);
+  TALER_MHD_parse_post_cleanup_callback (rc->opaque_post_parsing_context);
   /* Sanity-check that we didn't leave any transactions hanging */
   /* NOTE: In high-performance production, we could consider
      removing this as it should not be needed and might be costly
      (to be benchmarked). */
   TEH_plugin->preflight (TEH_plugin->cls,
                          TEH_plugin->get_session (TEH_plugin->cls));
-  GNUNET_free (ecls);
+  GNUNET_free (rc);
   *con_cls = NULL;
   GNUNET_async_scope_restore (&old_scope);
 }
 
 
 /**
- * We found @a rh responsible for handling a request. Parse the
+ * We found a request handler responsible for handling a request. Parse the
  * @a upload_data (if applicable) and the @a url and call the
  * handler.
  *
- * @param rh request handler to call
- * @param connection connection being handled
+ * @param rc request context
  * @param url rest of the URL to parse
- * @param inner_cls closure for the handler, if needed
  * @param upload_data upload data to parse (if available)
  * @param[in,out] upload_data_size number of bytes in @a upload_data
  * @return MHD result code
  */
 static MHD_RESULT
-proceed_with_handler (const struct TEH_RequestHandler *rh,
-                      struct MHD_Connection *connection,
+proceed_with_handler (struct TEH_RequestContext *rc,
                       const char *url,
-                      void **inner_cls,
                       const char *upload_data,
                       size_t *upload_data_size)
 {
+  const struct TEH_RequestHandler *rh = rc->rh;
   const char *args[rh->nargs + 1];
   size_t ulen = strlen (url) + 1;
   json_t *root = NULL;
@@ -376,7 +346,7 @@ proceed_with_handler (const struct TEH_RequestHandler *rh,
        /deposits/).  The value should be adjusted if we ever define protocol
        endpoints with plausibly longer inputs.  */
     GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_URI_TOO_LONG,
                                        TALER_EC_GENERIC_URI_TOO_LONG,
                                        url);
@@ -389,8 +359,8 @@ proceed_with_handler (const struct TEH_RequestHandler *rh,
   {
     enum GNUNET_GenericReturnValue res;
 
-    res = TALER_MHD_parse_post_json (connection,
-                                     inner_cls,
+    res = TALER_MHD_parse_post_json (rc->connection,
+                                     &rc->opaque_post_parsing_context,
                                      upload_data,
                                      upload_data_size,
                                      &root);
@@ -447,7 +417,7 @@ proceed_with_handler (const struct TEH_RequestHandler *rh,
                          url);
         GNUNET_break_op (0);
         json_decref (root);
-        return TALER_MHD_reply_with_error (connection,
+        return TALER_MHD_reply_with_error (rc->connection,
                                            MHD_HTTP_NOT_FOUND,
                                            
TALER_EC_EXCHANGE_GENERIC_WRONG_NUMBER_OF_SEGMENTS,
                                            emsg);
@@ -458,18 +428,15 @@ proceed_with_handler (const struct TEH_RequestHandler *rh,
       args[i] = NULL;
     }
 
-
     /* Above logic ensures that 'root' is exactly non-NULL for POST operations,
        so we test for 'root' to decide which handler to invoke. */
     if (NULL != root)
-      ret = rh->handler.post (rh,
-                              connection,
+      ret = rh->handler.post (rc,
                               root,
                               args);
     else /* We also only have "POST" or "GET" in the API for at this point
             (OPTIONS/HEAD are taken care of earlier) */
-      ret = rh->handler.get (rh,
-                             connection,
+      ret = rh->handler.get (rc,
                              args);
   }
   json_decref (root);
@@ -480,14 +447,13 @@ proceed_with_handler (const struct TEH_RequestHandler *rh,
 /**
  * Handle a "/seed" request.
  *
- * @param rh context of the handler
+ * @param rc request context
  * @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
-handler_seed (const struct TEH_RequestHandler *rh,
-              struct MHD_Connection *connection,
+handler_seed (struct TEH_RequestContext *rc,
               const char *const args[])
 {
 #define SEED_SIZE 32
@@ -495,7 +461,6 @@ handler_seed (const struct TEH_RequestHandler *rh,
   MHD_RESULT ret;
   struct MHD_Response *resp;
 
-  (void) rh;
   body = malloc (SEED_SIZE); /* must use malloc(), because MHD will use free() 
*/
   if (NULL == body)
     return MHD_NO;
@@ -506,7 +471,7 @@ handler_seed (const struct TEH_RequestHandler *rh,
                                           body,
                                           MHD_RESPMEM_MUST_FREE);
   TALER_MHD_add_global_headers (resp);
-  ret = MHD_queue_response (connection,
+  ret = MHD_queue_response (rc->connection,
                             MHD_HTTP_OK,
                             resp);
   GNUNET_break (MHD_YES == ret);
@@ -519,22 +484,21 @@ 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 rc request context
  * @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,
+handle_post_management (struct TEH_RequestContext *rc,
                         const json_t *root,
                         const char *const args[])
 {
   if (NULL == args[0])
   {
     GNUNET_break_op (0);
-    return r404 (connection, "/management");
+    return r404 (rc->connection,
+                 "/management");
   }
   if (0 == strcmp (args[0],
                    "auditors"))
@@ -542,14 +506,14 @@ handle_post_management (const struct TEH_RequestHandler 
*rh,
     struct TALER_AuditorPublicKeyP auditor_pub;
 
     if (NULL == args[1])
-      return TEH_handler_management_auditors (connection,
+      return TEH_handler_management_auditors (rc->connection,
                                               root);
     if ( (NULL == args[1]) ||
          (NULL == args[2]) ||
          (0 != strcmp (args[2],
                        "disable")) ||
          (NULL != args[3]) )
-      return r404 (connection,
+      return r404 (rc->connection,
                    "/management/auditors/$AUDITOR_PUB/disable");
     if (GNUNET_OK !=
         GNUNET_STRINGS_string_to_data (args[1],
@@ -558,12 +522,12 @@ handle_post_management (const struct TEH_RequestHandler 
*rh,
                                        sizeof (auditor_pub)))
     {
       GNUNET_break_op (0);
-      return TALER_MHD_reply_with_error (connection,
+      return TALER_MHD_reply_with_error (rc->connection,
                                          MHD_HTTP_BAD_REQUEST,
                                          TALER_EC_GENERIC_PARAMETER_MALFORMED,
                                          args[1]);
     }
-    return TEH_handler_management_auditors_AP_disable (connection,
+    return TEH_handler_management_auditors_AP_disable (rc->connection,
                                                        &auditor_pub,
                                                        root);
   }
@@ -578,7 +542,7 @@ handle_post_management (const struct TEH_RequestHandler *rh,
          (0 != strcmp (args[2],
                        "revoke")) ||
          (NULL != args[3]) )
-      return r404 (connection,
+      return r404 (rc->connection,
                    "/management/denominations/$HDP/revoke");
     if (GNUNET_OK !=
         GNUNET_STRINGS_string_to_data (args[1],
@@ -587,12 +551,12 @@ handle_post_management (const struct TEH_RequestHandler 
*rh,
                                        sizeof (h_denom_pub)))
     {
       GNUNET_break_op (0);
-      return TALER_MHD_reply_with_error (connection,
+      return TALER_MHD_reply_with_error (rc->connection,
                                          MHD_HTTP_BAD_REQUEST,
                                          TALER_EC_GENERIC_PARAMETER_MALFORMED,
                                          args[1]);
     }
-    return TEH_handler_management_denominations_HDP_revoke (connection,
+    return TEH_handler_management_denominations_HDP_revoke (rc->connection,
                                                             &h_denom_pub,
                                                             root);
   }
@@ -607,7 +571,7 @@ handle_post_management (const struct TEH_RequestHandler *rh,
          (0 != strcmp (args[2],
                        "revoke")) ||
          (NULL != args[3]) )
-      return r404 (connection,
+      return r404 (rc->connection,
                    "/management/signkeys/$HDP/revoke");
     if (GNUNET_OK !=
         GNUNET_STRINGS_string_to_data (args[1],
@@ -616,12 +580,12 @@ handle_post_management (const struct TEH_RequestHandler 
*rh,
                                        sizeof (exchange_pub)))
     {
       GNUNET_break_op (0);
-      return TALER_MHD_reply_with_error (connection,
+      return TALER_MHD_reply_with_error (rc->connection,
                                          MHD_HTTP_BAD_REQUEST,
                                          TALER_EC_GENERIC_PARAMETER_MALFORMED,
                                          args[1]);
     }
-    return TEH_handler_management_signkeys_EP_revoke (connection,
+    return TEH_handler_management_signkeys_EP_revoke (rc->connection,
                                                       &exchange_pub,
                                                       root);
   }
@@ -631,25 +595,27 @@ handle_post_management (const struct TEH_RequestHandler 
*rh,
     if (NULL != args[1])
     {
       GNUNET_break_op (0);
-      return r404 (connection, "/management/keys/*");
+      return r404 (rc->connection,
+                   "/management/keys/*");
     }
-    return TEH_handler_management_post_keys (connection,
+    return TEH_handler_management_post_keys (rc->connection,
                                              root);
   }
   if (0 == strcmp (args[0],
                    "wire"))
   {
     if (NULL == args[1])
-      return TEH_handler_management_post_wire (connection,
+      return TEH_handler_management_post_wire (rc->connection,
                                                root);
     if ( (0 != strcmp (args[1],
                        "disable")) ||
          (NULL != args[2]) )
     {
       GNUNET_break_op (0);
-      return r404 (connection, "/management/wire/disable");
+      return r404 (rc->connection,
+                   "/management/wire/disable");
     }
-    return TEH_handler_management_post_wire_disable (connection,
+    return TEH_handler_management_post_wire_disable (rc->connection,
                                                      root);
   }
   if (0 == strcmp (args[0],
@@ -658,27 +624,28 @@ handle_post_management (const struct TEH_RequestHandler 
*rh,
     if (NULL != args[1])
     {
       GNUNET_break_op (0);
-      return r404 (connection, "/management/wire-fee/*");
+      return r404 (rc->connection,
+                   "/management/wire-fee/*");
     }
-    return TEH_handler_management_post_wire_fees (connection,
+    return TEH_handler_management_post_wire_fees (rc->connection,
                                                   root);
   }
   GNUNET_break_op (0);
-  return r404 (connection, "/management/*");
+  return r404 (rc->connection,
+               "/management/*");
 }
 
 
 /**
  * Handle a get "/management" request.
  *
- * @param rh context of the handler
+ * @param rc request context
  * @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,
+handle_get_management (struct TEH_RequestContext *rc,
                        const char *const args[1])
 {
   if ( (NULL != args[0]) &&
@@ -686,26 +653,25 @@ handle_get_management (const struct TEH_RequestHandler 
*rh,
                      "keys")) &&
        (NULL == args[1]) )
   {
-    return TEH_keys_management_get_keys_handler (rh,
-                                                 connection);
+    return TEH_keys_management_get_keys_handler (rc->rh,
+                                                 rc->connection);
   }
   GNUNET_break_op (0);
-  return r404 (connection, "/management/*");
+  return r404 (rc->connection,
+               "/management/*");
 }
 
 
 /**
  * Handle POST "/auditors/..." requests.
  *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
+ * @param rc request context
  * @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,
+handle_post_auditors (struct TEH_RequestContext *rc,
                       const json_t *root,
                       const char *const args[])
 {
@@ -717,7 +683,8 @@ handle_post_auditors (const struct TEH_RequestHandler *rh,
        (NULL != args[2]) )
   {
     GNUNET_break_op (0);
-    return r404 (connection, "/auditors/$AUDITOR_PUB/$H_DENOM_PUB");
+    return r404 (rc->connection,
+                 "/auditors/$AUDITOR_PUB/$H_DENOM_PUB");
   }
 
   if (GNUNET_OK !=
@@ -727,7 +694,7 @@ handle_post_auditors (const struct TEH_RequestHandler *rh,
                                      sizeof (auditor_pub)))
   {
     GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_BAD_REQUEST,
                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
                                        args[0]);
@@ -739,12 +706,12 @@ handle_post_auditors (const struct TEH_RequestHandler *rh,
                                      sizeof (h_denom_pub)))
   {
     GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_BAD_REQUEST,
                                        TALER_EC_GENERIC_PARAMETER_MALFORMED,
                                        args[1]);
   }
-  return TEH_handler_auditors (connection,
+  return TEH_handler_auditors (rc->connection,
                                &auditor_pub,
                                &h_denom_pub,
                                root);
@@ -761,7 +728,7 @@ handle_post_auditors (const struct TEH_RequestHandler *rh,
  * @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 *`)
+ * @param con_cls closure for request (a `struct TEH_RequestContext *`)
  * @return MHD result code
  */
 static MHD_RESULT
@@ -907,14 +874,13 @@ handle_mhd_request (void *cls,
       .url = NULL
     }
   };
-  struct ExchangeHttpRequestClosure *ecls = *con_cls;
-  void **inner_cls;
+  struct TEH_RequestContext *rc = *con_cls;
   struct GNUNET_AsyncScopeSave old_scope;
   const char *correlation_id = NULL;
 
   (void) cls;
   (void) version;
-  if (NULL == ecls)
+  if (NULL == rc)
   {
     unsigned long long cnt;
 
@@ -933,15 +899,17 @@ handle_mhd_request (void *cls,
     }
 
     /* We're in a new async scope! */
-    ecls = *con_cls = GNUNET_new (struct ExchangeHttpRequestClosure);
-    GNUNET_async_scope_fresh (&ecls->async_scope_id);
-    ecls->url = url;
+    rc = *con_cls = GNUNET_new (struct TEH_RequestContext);
+    GNUNET_async_scope_fresh (&rc->async_scope_id);
+    rc->url = url;
+    rc->connection = connection;
     /* We only read the correlation ID on the first callback for every client 
*/
     correlation_id = MHD_lookup_connection_value (connection,
                                                   MHD_HEADER_KIND,
                                                   "Taler-Correlation-Id");
-    if ((NULL != correlation_id) &&
-        (GNUNET_YES != GNUNET_CURL_is_valid_scope_id (correlation_id)))
+    if ( (NULL != correlation_id) &&
+         (GNUNET_YES !=
+          GNUNET_CURL_is_valid_scope_id (correlation_id)) )
     {
       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
                   "illegal incoming correlation ID\n");
@@ -949,8 +917,7 @@ handle_mhd_request (void *cls,
     }
   }
 
-  inner_cls = &ecls->opaque_post_parsing_context;
-  GNUNET_async_scope_enter (&ecls->async_scope_id,
+  GNUNET_async_scope_enter (&rc->async_scope_id,
                             &old_scope);
   if (NULL != correlation_id)
     GNUNET_log (GNUNET_ERROR_TYPE_INFO,
@@ -964,7 +931,7 @@ handle_mhd_request (void *cls,
                 method,
                 url);
   /* on repeated requests, check our cache first */
-  if (NULL != ecls->rh)
+  if (NULL != rc->rh)
   {
     MHD_RESULT ret;
     const char *start;
@@ -975,10 +942,8 @@ handle_mhd_request (void *cls,
     start = strchr (url + 1, '/');
     if (NULL == start)
       start = "";
-    ret = proceed_with_handler (ecls->rh,
-                                connection,
+    ret = proceed_with_handler (rc,
                                 start,
-                                inner_cls,
                                 upload_data,
                                 upload_data_size);
     GNUNET_async_scope_restore (&old_scope);
@@ -1039,12 +1004,10 @@ handle_mhd_request (void *cls,
         MHD_RESULT ret;
 
         /* cache to avoid the loop next time */
-        ecls->rh = rh;
+        rc->rh = rh;
         /* run handler */
-        ret = proceed_with_handler (rh,
-                                    connection,
+        ret = proceed_with_handler (rc,
                                     url + tok_size + 1,
-                                    inner_cls,
                                     upload_data,
                                     upload_data_size);
         GNUNET_async_scope_restore (&old_scope);
diff --git a/src/exchange/taler-exchange-httpd.h 
b/src/exchange/taler-exchange-httpd.h
index 497ff16a..eaecc972 100644
--- a/src/exchange/taler-exchange-httpd.h
+++ b/src/exchange/taler-exchange-httpd.h
@@ -83,6 +83,62 @@ extern char *TEH_currency;
  */
 extern volatile bool MHD_terminating;
 
+
+/**
+ * @brief Struct describing an URL and the handler for it.
+ */
+struct TEH_RequestHandler;
+
+
+/**
+ * @brief Context in which the exchange is processing
+ *        all requests
+ */
+struct TEH_RequestContext
+{
+
+  /**
+   * Async Scope ID associated with this request.
+   */
+  struct GNUNET_AsyncScopeId async_scope_id;
+
+  /**
+   * Opaque parsing context.
+   */
+  void *opaque_post_parsing_context;
+
+  /**
+   * Request handler responsible for this request.
+   */
+  const struct TEH_RequestHandler *rh;
+
+  /**
+   * Request URL (for logging).
+   */
+  const char *url;
+
+  /**
+   * Connection we are processing.
+   */
+  struct MHD_Connection *connection;
+
+  /**
+   * @e rh-specific cleanup routine. Function called
+   * upon completion of the request that should
+   * clean up @a rh_ctx. Can be NULL.
+   */
+  void
+  (*rh_cleaner)(struct TEH_RequestContext *rc);
+
+  /**
+   * @e rh-specific context. Place where the request
+   * handler can associate state with this request.
+   * Can be NULL.
+   */
+  void *rh_ctx;
+};
+
+
 /**
  * @brief Struct describing an URL and the handler for it.
  */
@@ -109,31 +165,28 @@ struct TEH_RequestHandler
      * Function to call to handle a GET requests (and those
      * with @e method NULL).
      *
-     * @param rh this struct
+     * @param rc context for the request
      * @param mime_type the @e mime_type for the reply (hint, can be NULL)
-     * @param connection the MHD connection to handle
      * @param args array of arguments, needs to be of length @e args_expected
      * @return MHD result code
      */
-    MHD_RESULT (*get)(const struct TEH_RequestHandler *rh,
-                      struct MHD_Connection *connection,
-                      const char *const args[]);
+    MHD_RESULT
+    (*get)(struct TEH_RequestContext *rc,
+           const char *const args[]);
 
 
     /**
      * Function to call to handle a POST request.
      *
-     * @param rh this struct
-     * @param mime_type the @e mime_type for the reply (hint, can be NULL)
-     * @param connection the MHD connection to handle
+     * @param rc context for the request
      * @param json uploaded JSON data
      * @param args array of arguments, needs to be of length @e args_expected
      * @return MHD result code
      */
-    MHD_RESULT (*post)(const struct TEH_RequestHandler *rh,
-                       struct MHD_Connection *connection,
-                       const json_t *root,
-                       const char *const args[]);
+    MHD_RESULT
+    (*post)(struct TEH_RequestContext *rc,
+            const json_t *root,
+            const char *const args[]);
 
   } handler;
 
diff --git a/src/exchange/taler-exchange-httpd_deposits_get.c 
b/src/exchange/taler-exchange-httpd_deposits_get.c
index c51e0f42..f32b88b6 100644
--- a/src/exchange/taler-exchange-httpd_deposits_get.c
+++ b/src/exchange/taler-exchange-httpd_deposits_get.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2017 Taler Systems SA
+  Copyright (C) 2014-2017, 2021 Taler Systems SA
 
   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
@@ -298,19 +298,8 @@ handle_track_transaction_request (
 }
 
 
-/**
- * Handle a "/deposits/$H_WIRE/$MERCHANT_PUB/$H_CONTRACT_TERMS/$COIN_PUB"
- * request.
- *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param args array of additional options (length: 4, contains:
- *      h_wire, merchant_pub, h_contract_terms and coin_pub)
- * @return MHD result code
-  */
 MHD_RESULT
-TEH_handler_deposits_get (const struct TEH_RequestHandler *rh,
-                          struct MHD_Connection *connection,
+TEH_handler_deposits_get (struct TEH_RequestContext *rc,
                           const char *const args[4])
 {
   enum GNUNET_GenericReturnValue res;
@@ -320,7 +309,6 @@ TEH_handler_deposits_get (const struct TEH_RequestHandler 
*rh,
     .purpose.purpose = htonl (TALER_SIGNATURE_MERCHANT_TRACK_TRANSACTION)
   };
 
-  (void) rh;
   if (GNUNET_OK !=
       GNUNET_STRINGS_string_to_data (args[0],
                                      strlen (args[0]),
@@ -328,7 +316,7 @@ TEH_handler_deposits_get (const struct TEH_RequestHandler 
*rh,
                                      sizeof (tps.h_wire)))
   {
     GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_BAD_REQUEST,
                                        
TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_H_WIRE,
                                        args[0]);
@@ -340,7 +328,7 @@ TEH_handler_deposits_get (const struct TEH_RequestHandler 
*rh,
                                      sizeof (tps.merchant)))
   {
     GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_BAD_REQUEST,
                                        
TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_MERCHANT_PUB,
                                        args[1]);
@@ -352,7 +340,7 @@ TEH_handler_deposits_get (const struct TEH_RequestHandler 
*rh,
                                      sizeof (tps.h_contract_terms)))
   {
     GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_BAD_REQUEST,
                                        
TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_H_CONTRACT_TERMS,
                                        args[2]);
@@ -364,12 +352,12 @@ TEH_handler_deposits_get (const struct TEH_RequestHandler 
*rh,
                                      sizeof (tps.coin_pub)))
   {
     GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_BAD_REQUEST,
                                        
TALER_EC_EXCHANGE_DEPOSITS_GET_INVALID_COIN_PUB,
                                        args[3]);
   }
-  res = TALER_MHD_parse_request_arg_data (connection,
+  res = TALER_MHD_parse_request_arg_data (rc->connection,
                                           "merchant_sig",
                                           &merchant_sig,
                                           sizeof (merchant_sig));
@@ -384,13 +372,13 @@ TEH_handler_deposits_get (const struct TEH_RequestHandler 
*rh,
                                   &tps.merchant.eddsa_pub))
   {
     GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_FORBIDDEN,
                                        
TALER_EC_EXCHANGE_DEPOSITS_GET_MERCHANT_SIGNATURE_INVALID,
                                        NULL);
   }
 
-  return handle_track_transaction_request (connection,
+  return handle_track_transaction_request (rc->connection,
                                            &tps,
                                            &tps.merchant);
 }
diff --git a/src/exchange/taler-exchange-httpd_deposits_get.h 
b/src/exchange/taler-exchange-httpd_deposits_get.h
index a745c5de..aee7521a 100644
--- a/src/exchange/taler-exchange-httpd_deposits_get.h
+++ b/src/exchange/taler-exchange-httpd_deposits_get.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2017 Taler Systems SA
+  Copyright (C) 2014-2017, 2021 Taler Systems SA
 
   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
@@ -30,15 +30,13 @@
  * Handle a "/deposits/$H_WIRE/$MERCHANT_PUB/$H_CONTRACT_TERMS/$COIN_PUB"
  * request.
  *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
+ * @param rc request context
  * @param args array of additional options (length: 4, contains:
  *      h_wire, merchant_pub, h_contract_terms and coin_pub)
  * @return MHD result code
   */
 MHD_RESULT
-TEH_handler_deposits_get (const struct TEH_RequestHandler *rh,
-                          struct MHD_Connection *connection,
+TEH_handler_deposits_get (struct TEH_RequestContext *rc,
                           const char *const args[4]);
 
 
diff --git a/src/exchange/taler-exchange-httpd_keys.c 
b/src/exchange/taler-exchange-httpd_keys.c
index 0cc8c831..216afd7c 100644
--- a/src/exchange/taler-exchange-httpd_keys.c
+++ b/src/exchange/taler-exchange-httpd_keys.c
@@ -2053,18 +2053,16 @@ krd_search_comparator (const void *key,
 
 
 MHD_RESULT
-TEH_keys_get_handler (const struct TEH_RequestHandler *rh,
-                      struct MHD_Connection *connection,
+TEH_keys_get_handler (struct TEH_RequestContext *rc,
                       const char *const args[])
 {
   struct GNUNET_TIME_Absolute last_issue_date;
 
-  (void) rh;
   (void) args;
   {
     const char *have_cherrypick;
 
-    have_cherrypick = MHD_lookup_connection_value (connection,
+    have_cherrypick = MHD_lookup_connection_value (rc->connection,
                                                    MHD_GET_ARGUMENT_KIND,
                                                    "last_issue_date");
     if (NULL != have_cherrypick)
@@ -2077,7 +2075,7 @@ TEH_keys_get_handler (const struct TEH_RequestHandler *rh,
                   &cherrypickn))
       {
         GNUNET_break_op (0);
-        return TALER_MHD_reply_with_error (connection,
+        return TALER_MHD_reply_with_error (rc->connection,
                                            MHD_HTTP_BAD_REQUEST,
                                            
TALER_EC_GENERIC_PARAMETER_MALFORMED,
                                            have_cherrypick);
@@ -2103,16 +2101,16 @@ TEH_keys_get_handler (const struct TEH_RequestHandler 
*rh,
     {
       GNUNET_assert (0 == pthread_mutex_lock (&skr_mutex));
       if ( (SKR_LIMIT == skr_size) &&
-           (connection == skr_connection) )
+           (rc->connection == skr_connection) )
       {
         GNUNET_assert (0 == pthread_mutex_unlock (&skr_mutex));
-        return TALER_MHD_reply_with_error (connection,
+        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");
       }
       GNUNET_assert (0 == pthread_mutex_unlock (&skr_mutex));
-      return suspend_request (connection);
+      return suspend_request (rc->connection);
     }
     krd = bsearch (&last_issue_date,
                    ksh->krd_array,
@@ -2140,14 +2138,15 @@ TEH_keys_get_handler (const struct TEH_RequestHandler 
*rh,
          NOT_FOUND situation. But, OTOH, for 'sane' clients it is more likely
          to be our fault, so let's speculatively assume we are to blame ;-) 
*///
       GNUNET_break (0);
-      return TALER_MHD_reply_with_error (connection,
+      return TALER_MHD_reply_with_error (rc->connection,
                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
                                          
TALER_EC_EXCHANGE_GENERIC_KEYS_MISSING,
                                          "no key data for given timestamp");
     }
-    return MHD_queue_response (connection,
+    return MHD_queue_response (rc->connection,
                                MHD_HTTP_OK,
-                               (MHD_YES == TALER_MHD_can_compress (connection))
+                               (MHD_YES ==
+                                TALER_MHD_can_compress (rc->connection))
                                ? krd->response_compressed
                                : krd->response_uncompressed);
   }
diff --git a/src/exchange/taler-exchange-httpd_keys.h 
b/src/exchange/taler-exchange-httpd_keys.h
index 8d2aae9d..6c685366 100644
--- a/src/exchange/taler-exchange-httpd_keys.h
+++ b/src/exchange/taler-exchange-httpd_keys.h
@@ -324,14 +324,12 @@ TEH_keys_exchange_revoke (const struct 
TALER_ExchangePublicKeyP *exchange_pub);
  * Function to call to handle requests to "/keys" by sending
  * back our current key material.
  *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
+ * @param rc request context
  * @param args array of additional options (must be empty for this function)
  * @return MHD result code
  */
 MHD_RESULT
-TEH_keys_get_handler (const struct TEH_RequestHandler *rh,
-                      struct MHD_Connection *connection,
+TEH_keys_get_handler (struct TEH_RequestContext *rc,
                       const char *const args[]);
 
 
diff --git a/src/exchange/taler-exchange-httpd_link.c 
b/src/exchange/taler-exchange-httpd_link.c
index a39e5864..bbb02752 100644
--- a/src/exchange/taler-exchange-httpd_link.c
+++ b/src/exchange/taler-exchange-httpd_link.c
@@ -169,23 +169,13 @@ link_transaction (void *cls,
 }
 
 
-/**
- * Handle a "/coins/$COIN_PUB/link" request.
- *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param args array of additional options (length: 2, first is the coin_pub, 
second must be "link")
- * @return MHD result code
-  */
 MHD_RESULT
-TEH_handler_link (const struct TEH_RequestHandler *rh,
-                  struct MHD_Connection *connection,
+TEH_handler_link (struct TEH_RequestContext *rc,
                   const char *const args[2])
 {
   struct HTD_Context ctx;
   MHD_RESULT mhd_ret;
 
-  (void) rh;
   memset (&ctx,
           0,
           sizeof (ctx));
@@ -196,22 +186,15 @@ TEH_handler_link (const struct TEH_RequestHandler *rh,
                                      sizeof (ctx.coin_pub)))
   {
     GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_BAD_REQUEST,
                                        
TALER_EC_EXCHANGE_GENERIC_COINS_INVALID_COIN_PUB,
                                        args[0]);
   }
   ctx.mlist = json_array ();
-  if (NULL == ctx.mlist)
-  {
-    GNUNET_break (0);
-    return TALER_MHD_reply_with_error (connection,
-                                       MHD_HTTP_INTERNAL_SERVER_ERROR,
-                                       
TALER_EC_GENERIC_JSON_ALLOCATION_FAILURE,
-                                       "json_array() call failed");
-  }
+  GNUNET_assert (NULL != ctx.mlist);
   if (GNUNET_OK !=
-      TEH_DB_run_transaction (connection,
+      TEH_DB_run_transaction (rc->connection,
                               "run link",
                               &mhd_ret,
                               &link_transaction,
@@ -221,7 +204,7 @@ TEH_handler_link (const struct TEH_RequestHandler *rh,
       json_decref (ctx.mlist);
     return mhd_ret;
   }
-  mhd_ret = TALER_MHD_reply_json (connection,
+  mhd_ret = TALER_MHD_reply_json (rc->connection,
                                   ctx.mlist,
                                   MHD_HTTP_OK);
   json_decref (ctx.mlist);
diff --git a/src/exchange/taler-exchange-httpd_link.h 
b/src/exchange/taler-exchange-httpd_link.h
index 4c9651a9..01679e87 100644
--- a/src/exchange/taler-exchange-httpd_link.h
+++ b/src/exchange/taler-exchange-httpd_link.h
@@ -31,14 +31,12 @@
 /**
  * Handle a "/coins/$COIN_PUB/link" request.
  *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
+ * @param rc request context
  * @param args array of additional options (length: 2, first is the coin_pub, 
second must be "link")
  * @return MHD result code
   */
 MHD_RESULT
-TEH_handler_link (const struct TEH_RequestHandler *rh,
-                  struct MHD_Connection *connection,
+TEH_handler_link (struct TEH_RequestContext *rc,
                   const char *const args[2]);
 
 
diff --git a/src/exchange/taler-exchange-httpd_mhd.c 
b/src/exchange/taler-exchange-httpd_mhd.c
index c9c6303b..8d07c3cf 100644
--- a/src/exchange/taler-exchange-httpd_mhd.c
+++ b/src/exchange/taler-exchange-httpd_mhd.c
@@ -34,27 +34,18 @@
 #include "taler-exchange-httpd_mhd.h"
 
 
-/**
- * Function to call to handle the request by sending
- * back static data from the @a rh.
- *
- * @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
- */
 MHD_RESULT
-TEH_handler_static_response (const struct TEH_RequestHandler *rh,
-                             struct MHD_Connection *connection,
+TEH_handler_static_response (struct TEH_RequestContext *rc,
                              const char *const args[])
 {
+  const struct TEH_RequestHandler *rh = rc->rh;
   size_t dlen;
 
   (void) args;
   dlen = (0 == rh->data_size)
          ? strlen ((const char *) rh->data)
          : rh->data_size;
-  return TALER_MHD_reply_static (connection,
+  return TALER_MHD_reply_static (rc->connection,
                                  rh->response_code,
                                  rh->mime_type,
                                  rh->data,
@@ -62,24 +53,13 @@ TEH_handler_static_response (const struct 
TEH_RequestHandler *rh,
 }
 
 
-/**
- * Function to call to handle the request by sending
- * back a redirect to the AGPL source code.
- *
- * @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
- */
 MHD_RESULT
-TEH_handler_agpl_redirect (const struct TEH_RequestHandler *rh,
-                           struct MHD_Connection *connection,
+TEH_handler_agpl_redirect (struct TEH_RequestContext *rc,
                            const char *const args[])
 {
-  (void) rh;
   (void) args;
-  return TALER_MHD_reply_agpl (connection,
-                               "http://www.git.taler.net/?p=exchange.git";);
+  return TALER_MHD_reply_agpl (rc->connection,
+                               "https://git.taler.net/?p=exchange.git";);
 }
 
 
diff --git a/src/exchange/taler-exchange-httpd_mhd.h 
b/src/exchange/taler-exchange-httpd_mhd.h
index 7547780d..270b0539 100644
--- a/src/exchange/taler-exchange-httpd_mhd.h
+++ b/src/exchange/taler-exchange-httpd_mhd.h
@@ -30,16 +30,14 @@
 
 /**
  * Function to call to handle the request by sending
- * back static data from the @a rh.
+ * back static data from the request handler.
  *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
+ * @param rc request context
  * @param args array of additional options (must be empty for this function)
  * @return MHD result code
  */
 MHD_RESULT
-TEH_handler_static_response (const struct TEH_RequestHandler *rh,
-                             struct MHD_Connection *connection,
+TEH_handler_static_response (struct TEH_RequestContext *rc,
                              const char *const args[]);
 
 
@@ -47,14 +45,12 @@ TEH_handler_static_response (const struct 
TEH_RequestHandler *rh,
  * Function to call to handle the request by sending
  * back a redirect to the AGPL source code.
  *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
+ * @param rc request context
  * @param args array of additional options (must be empty for this function)
  * @return MHD result code
  */
 MHD_RESULT
-TEH_handler_agpl_redirect (const struct TEH_RequestHandler *rh,
-                           struct MHD_Connection *connection,
+TEH_handler_agpl_redirect (struct TEH_RequestContext *rc,
                            const char *const args[]);
 
 
diff --git a/src/exchange/taler-exchange-httpd_refreshes_reveal.c 
b/src/exchange/taler-exchange-httpd_refreshes_reveal.c
index 2a5c3aca..dc4bdf0e 100644
--- a/src/exchange/taler-exchange-httpd_refreshes_reveal.c
+++ b/src/exchange/taler-exchange-httpd_refreshes_reveal.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2019 Taler Systems SA
+  Copyright (C) 2014-2019, 2021 Taler Systems SA
 
   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
@@ -805,7 +805,7 @@ cleanup:
  * @param coin_evs envelopes of gamma-selected coins to be signed
  * @return MHD result code
  */
-static int
+static MHD_RESULT
 handle_refreshes_reveal_json (struct MHD_Connection *connection,
                               struct RevealContext *rctx,
                               const json_t *tp_json,
@@ -853,7 +853,7 @@ handle_refreshes_reveal_json (struct MHD_Connection 
*connection,
       GNUNET_JSON_spec_fixed_auto (NULL, &rctx->transfer_privs[i]),
       GNUNET_JSON_spec_end ()
     };
-    int res;
+    enum GNUNET_GenericReturnValue res;
 
     res = TALER_MHD_parse_json_array (connection,
                                       tp_json,
@@ -872,24 +872,8 @@ handle_refreshes_reveal_json (struct MHD_Connection 
*connection,
 }
 
 
-/**
- * Handle a "/refreshes/$RCH/reveal" request. This time, the client reveals the
- * private transfer keys except for the cut-and-choose value returned from
- * "/coins/$COIN_PUB/melt".  This function parses the revealed keys and 
secrets and
- * ultimately passes everything to resolve_refreshes_reveal_denominations()
- * which will verify that the revealed information is valid then runs the
- * transaction in refreshes_reveal_transaction() and finally returns the signed
- * refreshed coins.
- *
- * @param rh context of the handler
- * @param connection MHD request handle
- * @param root uploaded JSON data
- * @param args array of additional options (length: 2, session hash and the 
string "reveal")
- * @return MHD result code
- */
 MHD_RESULT
-TEH_handler_reveal (const struct TEH_RequestHandler *rh,
-                    struct MHD_Connection *connection,
+TEH_handler_reveal (struct TEH_RequestContext *rc,
                     const json_t *root,
                     const char *const args[2])
 {
@@ -907,7 +891,6 @@ TEH_handler_reveal (const struct TEH_RequestHandler *rh,
     GNUNET_JSON_spec_end ()
   };
 
-  (void) rh;
   memset (&rctx,
           0,
           sizeof (rctx));
@@ -918,7 +901,7 @@ TEH_handler_reveal (const struct TEH_RequestHandler *rh,
                                      sizeof (rctx.rc)))
   {
     GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_BAD_REQUEST,
                                        
TALER_EC_EXCHANGE_REFRESHES_REVEAL_INVALID_RCH,
                                        args[0]);
@@ -927,16 +910,16 @@ TEH_handler_reveal (const struct TEH_RequestHandler *rh,
                    "reveal"))
   {
     GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_BAD_REQUEST,
                                        
TALER_EC_EXCHANGE_REFRESHES_REVEAL_OPERATION_INVALID,
                                        args[1]);
   }
 
   {
-    int res;
+    enum GNUNET_GenericReturnValue res;
 
-    res = TALER_MHD_parse_json_data (connection,
+    res = TALER_MHD_parse_json_data (rc->connection,
                                      root,
                                      spec);
     if (GNUNET_OK != res)
@@ -952,16 +935,16 @@ TEH_handler_reveal (const struct TEH_RequestHandler *rh,
   {
     GNUNET_JSON_parse_free (spec);
     GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_BAD_REQUEST,
                                        
TALER_EC_EXCHANGE_REFRESHES_REVEAL_CNC_TRANSFER_ARRAY_SIZE_INVALID,
                                        NULL);
   }
 
   {
-    int res;
+    MHD_RESULT res;
 
-    res = handle_refreshes_reveal_json (connection,
+    res = handle_refreshes_reveal_json (rc->connection,
                                         &rctx,
                                         transfer_privs,
                                         link_sigs,
diff --git a/src/exchange/taler-exchange-httpd_refreshes_reveal.h 
b/src/exchange/taler-exchange-httpd_refreshes_reveal.h
index b9806dbd..30716995 100644
--- a/src/exchange/taler-exchange-httpd_refreshes_reveal.h
+++ b/src/exchange/taler-exchange-httpd_refreshes_reveal.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2017 Taler Systems SA
+  Copyright (C) 2014-2017, 2021 Taler Systems SA
 
   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
@@ -37,15 +37,13 @@
  * transaction in refresh_reveal_transaction() and finally returns the signed
  * refreshed coins.
  *
- * @param rh context of the handler
- * @param connection MHD request handle
+ * @param rc request context
  * @param root uploaded JSON data
  * @param args array of additional options (length: 2, session hash and the 
string "reveal")
  * @return MHD result code
  */
 MHD_RESULT
-TEH_handler_reveal (const struct TEH_RequestHandler *rh,
-                    struct MHD_Connection *connection,
+TEH_handler_reveal (struct TEH_RequestContext *rc,
                     const json_t *root,
                     const char *const args[2]);
 
diff --git a/src/exchange/taler-exchange-httpd_reserves_get.c 
b/src/exchange/taler-exchange-httpd_reserves_get.c
index 6ad393a2..d08543a4 100644
--- a/src/exchange/taler-exchange-httpd_reserves_get.c
+++ b/src/exchange/taler-exchange-httpd_reserves_get.c
@@ -29,6 +29,45 @@
 #include "taler-exchange-httpd_responses.h"
 
 
+/**
+ * Reserve GET request that is long-polling.
+ */
+struct ReservePoller
+{
+  /**
+   * Kept in a DLL.
+   */
+  struct ReservePoller *next;
+
+  /**
+   * Kept in a DLL.
+   */
+  struct ReservePoller *prev;
+
+  /**
+   * Connection we are handling.
+   */
+  struct MHD_Connection *connection;
+
+  /**
+   * Entry in the timeout heap.
+   */
+  struct GNUNET_CONTAINER_HeapNode *hn;
+
+  /**
+   * Subscription for the database event we are
+   * waiting for.
+   */
+  struct GNUNET_DB_EventHandler *eh;
+
+  /**
+   * When will this request time out?
+   */
+  struct GNUNET_TIME_Absolute timeout;
+
+};
+
+
 /**
  * Send reserve history to client.
  *
@@ -112,26 +151,13 @@ reserve_history_transaction (void *cls,
 }
 
 
-/**
- * Handle a GET "/reserves/" request.  Parses the
- * given "reserve_pub" in @a args (which should contain the
- * EdDSA public key of a reserve) and then respond with the
- * history of the reserve.
- *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param args array of additional options (length: 1, just the reserve_pub)
- * @return MHD result code
- */
 MHD_RESULT
-TEH_handler_reserves_get (const struct TEH_RequestHandler *rh,
-                          struct MHD_Connection *connection,
+TEH_handler_reserves_get (struct TEH_RequestContext *rc,
                           const char *const args[1])
 {
   struct ReserveHistoryContext rsc;
   MHD_RESULT mhd_ret;
 
-  (void) rh;
   if (GNUNET_OK !=
       GNUNET_STRINGS_string_to_data (args[0],
                                      strlen (args[0]),
@@ -139,14 +165,14 @@ TEH_handler_reserves_get (const struct TEH_RequestHandler 
*rh,
                                      sizeof (rsc.reserve_pub)))
   {
     GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_BAD_REQUEST,
                                        
TALER_EC_MERCHANT_GENERIC_RESERVE_PUB_MALFORMED,
                                        args[0]);
   }
   rsc.rh = NULL;
   if (GNUNET_OK !=
-      TEH_DB_run_transaction (connection,
+      TEH_DB_run_transaction (rc->connection,
                               "get reserve history",
                               &mhd_ret,
                               &reserve_history_transaction,
@@ -155,11 +181,11 @@ TEH_handler_reserves_get (const struct TEH_RequestHandler 
*rh,
 
   /* generate proper response */
   if (NULL == rsc.rh)
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_NOT_FOUND,
                                        
TALER_EC_EXCHANGE_RESERVES_GET_STATUS_UNKNOWN,
                                        args[0]);
-  mhd_ret = reply_reserve_history_success (connection,
+  mhd_ret = reply_reserve_history_success (rc->connection,
                                            rsc.rh);
   TEH_plugin->free_reserve_history (TEH_plugin->cls,
                                     rsc.rh);
diff --git a/src/exchange/taler-exchange-httpd_reserves_get.h 
b/src/exchange/taler-exchange-httpd_reserves_get.h
index b46a6a44..1eb9ab60 100644
--- a/src/exchange/taler-exchange-httpd_reserves_get.h
+++ b/src/exchange/taler-exchange-httpd_reserves_get.h
@@ -33,14 +33,12 @@
  * EdDSA public key of a reserve) and then respond with the
  * status of the reserve.
  *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
+ * @param rc request context
  * @param args array of additional options (length: 1, just the reserve_pub)
  * @return MHD result code
  */
 MHD_RESULT
-TEH_handler_reserves_get (const struct TEH_RequestHandler *rh,
-                          struct MHD_Connection *connection,
+TEH_handler_reserves_get (struct TEH_RequestContext *rc,
                           const char *const args[1]);
 
 #endif
diff --git a/src/exchange/taler-exchange-httpd_terms.c 
b/src/exchange/taler-exchange-httpd_terms.c
index 1c703021..10114f15 100644
--- a/src/exchange/taler-exchange-httpd_terms.c
+++ b/src/exchange/taler-exchange-httpd_terms.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2019 Taler Systems SA
+  Copyright (C) 2019, 2021 Taler Systems SA
 
   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
@@ -38,51 +38,26 @@ static struct TALER_MHD_Legal *tos;
 static struct TALER_MHD_Legal *pp;
 
 
-/**
- * Handle a "/terms" 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
- */
 MHD_RESULT
-TEH_handler_terms (const struct TEH_RequestHandler *rh,
-                   struct MHD_Connection *connection,
+TEH_handler_terms (struct TEH_RequestContext *rc,
                    const char *const args[])
 {
-  (void) rh;
   (void) args;
-  return TALER_MHD_reply_legal (connection,
+  return TALER_MHD_reply_legal (rc->connection,
                                 tos);
 }
 
 
-/**
- * Handle a "/privacy" 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
- */
 MHD_RESULT
-TEH_handler_privacy (const struct TEH_RequestHandler *rh,
-                     struct MHD_Connection *connection,
+TEH_handler_privacy (struct TEH_RequestContext *rc,
                      const char *const args[])
 {
-  (void) rh;
   (void) args;
-  return TALER_MHD_reply_legal (connection,
+  return TALER_MHD_reply_legal (rc->connection,
                                 pp);
 }
 
 
-/**
- * Load our terms of service as per configuration.
- *
- * @param cfg configuration to process
- */
 void
 TEH_load_terms (const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
diff --git a/src/exchange/taler-exchange-httpd_terms.h 
b/src/exchange/taler-exchange-httpd_terms.h
index 3cbd3688..9815080f 100644
--- a/src/exchange/taler-exchange-httpd_terms.h
+++ b/src/exchange/taler-exchange-httpd_terms.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2019 Taler Systems SA
+  Copyright (C) 2019, 2021 Taler Systems SA
 
   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
@@ -32,28 +32,24 @@
 /**
  * Handle a "/terms" request.
  *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
+ * @param rc request context
  * @param args array of additional options (must be empty for this function)
  * @return MHD result code
  */
 MHD_RESULT
-TEH_handler_terms (const struct TEH_RequestHandler *rh,
-                   struct MHD_Connection *connection,
+TEH_handler_terms (struct TEH_RequestContext *rc,
                    const char *const args[]);
 
 
 /**
  * Handle a "/privacy" request.
  *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
+ * @param rc request context
  * @param args array of additional options (must be empty for this function)
  * @return MHD result code
  */
 MHD_RESULT
-TEH_handler_privacy (const struct TEH_RequestHandler *rh,
-                     struct MHD_Connection *connection,
+TEH_handler_privacy (struct TEH_RequestContext *rc,
                      const char *const args[]);
 
 
diff --git a/src/exchange/taler-exchange-httpd_transfers_get.c 
b/src/exchange/taler-exchange-httpd_transfers_get.c
index c4e276cc..9fd343a5 100644
--- a/src/exchange/taler-exchange-httpd_transfers_get.c
+++ b/src/exchange/taler-exchange-httpd_transfers_get.c
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2018 Taler Systems SA
+  Copyright (C) 2014-2018, 2021 Taler Systems SA
 
   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
@@ -499,23 +499,13 @@ get_transfer_deposits (void *cls,
 }
 
 
-/**
- * Handle a GET "/transfers/$WTID" request.
- *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param args array of additional options (length: 1, just the wtid)
- * @return MHD result code
- */
 MHD_RESULT
-TEH_handler_transfers_get (const struct TEH_RequestHandler *rh,
-                           struct MHD_Connection *connection,
+TEH_handler_transfers_get (struct TEH_RequestContext *rc,
                            const char *const args[1])
 {
   struct WtidTransactionContext ctx;
   MHD_RESULT mhd_ret;
 
-  (void) rh;
   memset (&ctx,
           0,
           sizeof (ctx));
@@ -526,13 +516,13 @@ TEH_handler_transfers_get (const struct 
TEH_RequestHandler *rh,
                                      sizeof (ctx.wtid)))
   {
     GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_BAD_REQUEST,
                                        
TALER_EC_EXCHANGE_TRANSFERS_GET_WTID_MALFORMED,
                                        args[0]);
   }
   if (GNUNET_OK !=
-      TEH_DB_run_transaction (connection,
+      TEH_DB_run_transaction (rc->connection,
                               "run transfers GET",
                               &mhd_ret,
                               &get_transfer_deposits,
@@ -541,7 +531,7 @@ TEH_handler_transfers_get (const struct TEH_RequestHandler 
*rh,
     free_ctx (&ctx);
     return mhd_ret;
   }
-  mhd_ret = reply_transfer_details (connection,
+  mhd_ret = reply_transfer_details (rc->connection,
                                     &ctx.total,
                                     &ctx.merchant_pub,
                                     &ctx.h_wire,
diff --git a/src/exchange/taler-exchange-httpd_transfers_get.h 
b/src/exchange/taler-exchange-httpd_transfers_get.h
index 83c17334..8a92a5ff 100644
--- a/src/exchange/taler-exchange-httpd_transfers_get.h
+++ b/src/exchange/taler-exchange-httpd_transfers_get.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2017 Taler Systems SA
+  Copyright (C) 2014-2017, 2021 Taler Systems SA
 
   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
@@ -29,14 +29,12 @@
 /**
  * Handle a GET "/transfers/$WTID" request.
  *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
+ * @param rc request context of the handler
  * @param args array of additional options (length: 1, just the wtid)
  * @return MHD result code
  */
 MHD_RESULT
-TEH_handler_transfers_get (const struct TEH_RequestHandler *rh,
-                           struct MHD_Connection *connection,
+TEH_handler_transfers_get (struct TEH_RequestContext *rc,
                            const char *const args[1]);
 
 
diff --git a/src/exchange/taler-exchange-httpd_wire.c 
b/src/exchange/taler-exchange-httpd_wire.c
index 2617b574..7246939d 100644
--- a/src/exchange/taler-exchange-httpd_wire.c
+++ b/src/exchange/taler-exchange-httpd_wire.c
@@ -95,7 +95,7 @@ destroy_wire_state_cb (void *cls)
 }
 
 
-int
+enum GNUNET_GenericReturnValue
 TEH_WIRE_init ()
 {
   if (0 !=
@@ -369,21 +369,19 @@ get_wire_state (void)
 
 
 MHD_RESULT
-TEH_handler_wire (const struct TEH_RequestHandler *rh,
-                  struct MHD_Connection *connection,
+TEH_handler_wire (struct TEH_RequestContext *rc,
                   const char *const args[])
 {
   struct WireStateHandle *wsh;
 
-  (void) rh;
   (void) args;
   wsh = get_wire_state ();
   if (NULL == wsh)
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_INTERNAL_SERVER_ERROR,
                                        
TALER_EC_EXCHANGE_GENERIC_BAD_CONFIGURATION,
                                        NULL);
-  return TALER_MHD_reply_json (connection,
+  return TALER_MHD_reply_json (rc->connection,
                                wsh->wire_reply,
                                wsh->http_status);
 }
diff --git a/src/exchange/taler-exchange-httpd_wire.h 
b/src/exchange/taler-exchange-httpd_wire.h
index ba556477..18bec788 100644
--- a/src/exchange/taler-exchange-httpd_wire.h
+++ b/src/exchange/taler-exchange-httpd_wire.h
@@ -31,7 +31,7 @@
  *
  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error.
  */
-int
+enum GNUNET_GenericReturnValue
 TEH_WIRE_init (void);
 
 
@@ -58,14 +58,12 @@ TEH_wire_update_state (void);
 /**
  * Handle a "/wire" request.
  *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
+ * @param rc request context
  * @param args array of additional options (must be empty for this function)
  * @return MHD result code
  */
 MHD_RESULT
-TEH_handler_wire (const struct TEH_RequestHandler *rh,
-                  struct MHD_Connection *connection,
+TEH_handler_wire (struct TEH_RequestContext *rc,
                   const char *const args[]);
 
 
diff --git a/src/exchange/taler-exchange-httpd_withdraw.c 
b/src/exchange/taler-exchange-httpd_withdraw.c
index 7be56084..7d10bb8e 100644
--- a/src/exchange/taler-exchange-httpd_withdraw.c
+++ b/src/exchange/taler-exchange-httpd_withdraw.c
@@ -316,24 +316,8 @@ withdraw_transaction (void *cls,
 }
 
 
-/**
- * Handle a "/reserves/$RESERVE_PUB/withdraw" request.  Parses the
- * "reserve_pub" EdDSA key of the reserve and the requested "denom_pub" which
- * specifies the key/value of the coin to be withdrawn, and checks that the
- * signature "reserve_sig" makes this a valid withdrawal request from the
- * specified reserve.  If so, the envelope with the blinded coin "coin_ev" is
- * passed down to execute the withdrawal operation.
- *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
- * @param root uploaded JSON data
- * @param args array of additional options (first must be the
- *         reserve public key, the second one should be "withdraw")
- * @return MHD result code
- */
 MHD_RESULT
-TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
-                      struct MHD_Connection *connection,
+TEH_handler_withdraw (struct TEH_RequestContext *rc,
                       const json_t *root,
                       const char *const args[2])
 {
@@ -351,7 +335,6 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
   enum TALER_ErrorCode ec;
   struct TEH_DenominationKey *dk;
 
-  (void) rh;
   if (GNUNET_OK !=
       GNUNET_STRINGS_string_to_data (args[0],
                                      strlen (args[0]),
@@ -359,7 +342,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
                                      sizeof (wc.wsrd.reserve_pub)))
   {
     GNUNET_break_op (0);
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_BAD_REQUEST,
                                        
TALER_EC_MERCHANT_GENERIC_RESERVE_PUB_MALFORMED,
                                        args[0]);
@@ -368,7 +351,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
   {
     enum GNUNET_GenericReturnValue res;
 
-    res = TALER_MHD_parse_json_data (connection,
+    res = TALER_MHD_parse_json_data (rc->connection,
                                      root,
                                      spec);
     if (GNUNET_OK != res)
@@ -379,7 +362,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
     struct GNUNET_TIME_Absolute now;
 
     dk = TEH_keys_denomination_by_hash (&wc.denom_pub_hash,
-                                        connection,
+                                        rc->connection,
                                         &mret);
     if (NULL == dk)
     {
@@ -397,7 +380,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
       /* This denomination is past the expiration time for withdraws */
       GNUNET_JSON_parse_free (spec);
       return TEH_RESPONSE_reply_expired_denom_pub_hash (
-        connection,
+        rc->connection,
         &wc.denom_pub_hash,
         now,
         TALER_EC_EXCHANGE_GENERIC_DENOMINATION_EXPIRED,
@@ -412,7 +395,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
       /* This denomination is not yet valid */
       GNUNET_JSON_parse_free (spec);
       return TEH_RESPONSE_reply_expired_denom_pub_hash (
-        connection,
+        rc->connection,
         &wc.denom_pub_hash,
         now,
         TALER_EC_EXCHANGE_GENERIC_DENOMINATION_VALIDITY_IN_FUTURE,
@@ -427,7 +410,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
       /* This denomination has been revoked */
       GNUNET_JSON_parse_free (spec);
       return TEH_RESPONSE_reply_expired_denom_pub_hash (
-        connection,
+        rc->connection,
         &wc.denom_pub_hash,
         now,
         TALER_EC_EXCHANGE_GENERIC_DENOMINATION_REVOKED,
@@ -442,7 +425,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
                           &dk->meta.fee_withdraw))
     {
       GNUNET_JSON_parse_free (spec);
-      return TALER_MHD_reply_with_error (connection,
+      return TALER_MHD_reply_with_error (rc->connection,
                                          MHD_HTTP_INTERNAL_SERVER_ERROR,
                                          
TALER_EC_EXCHANGE_WITHDRAW_AMOUNT_FEE_OVERFLOW,
                                          NULL);
@@ -470,7 +453,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
     TALER_LOG_WARNING (
       "Client supplied invalid signature for withdraw request\n");
     GNUNET_JSON_parse_free (spec);
-    return TALER_MHD_reply_with_error (connection,
+    return TALER_MHD_reply_with_error (rc->connection,
                                        MHD_HTTP_FORBIDDEN,
                                        
TALER_EC_EXCHANGE_WITHDRAW_RESERVE_SIGNATURE_INVALID,
                                        NULL);
@@ -487,7 +470,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
   {
     GNUNET_break (0);
     GNUNET_JSON_parse_free (spec);
-    return TALER_MHD_reply_with_ec (connection,
+    return TALER_MHD_reply_with_ec (rc->connection,
                                     ec,
                                     NULL);
   }
@@ -498,7 +481,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
     MHD_RESULT mhd_ret;
 
     if (GNUNET_OK !=
-        TEH_DB_run_transaction (connection,
+        TEH_DB_run_transaction (rc->connection,
                                 "run withdraw",
                                 &mhd_ret,
                                 &withdraw_transaction,
@@ -520,7 +503,7 @@ TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
     MHD_RESULT ret;
 
     ret = TALER_MHD_REPLY_JSON_PACK (
-      connection,
+      rc->connection,
       MHD_HTTP_OK,
       GNUNET_JSON_pack_rsa_signature ("ev_sig",
                                       wc.collectable.sig.rsa_signature));
diff --git a/src/exchange/taler-exchange-httpd_withdraw.h 
b/src/exchange/taler-exchange-httpd_withdraw.h
index 8b248597..8d2d8c18 100644
--- a/src/exchange/taler-exchange-httpd_withdraw.h
+++ b/src/exchange/taler-exchange-httpd_withdraw.h
@@ -1,6 +1,6 @@
 /*
   This file is part of TALER
-  Copyright (C) 2014-2020 Taler Systems SA
+  Copyright (C) 2014-2021 Taler Systems SA
 
   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
@@ -35,16 +35,14 @@
  * specified reserve.  If so, the envelope with the blinded coin "coin_ev" is
  * passed down to execute the withdrawal operation.
  *
- * @param rh context of the handler
- * @param connection the MHD connection to handle
+ * @param rc request context
  * @param root uploaded JSON data
  * @param args array of additional options (first must be the
  *         reserve public key, the second one should be "withdraw")
  * @return MHD result code
   */
 MHD_RESULT
-TEH_handler_withdraw (const struct TEH_RequestHandler *rh,
-                      struct MHD_Connection *connection,
+TEH_handler_withdraw (struct TEH_RequestContext *rc,
                       const json_t *root,
                       const char *const args[2]);
 

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]