gnunet-svn
[Top][All Lists]
Advanced

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

[taler-exchange] branch master updated: dynamic curl timeouts for /keys


From: gnunet
Subject: [taler-exchange] branch master updated: dynamic curl timeouts for /keys and /wire requests
Date: Tue, 12 Jan 2021 15:12:28 +0100

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

dold pushed a commit to branch master
in repository exchange.

The following commit(s) were added to refs/heads/master by this push:
     new 8f887a21 dynamic curl timeouts for /keys and /wire requests
8f887a21 is described below

commit 8f887a215e115d7e5f10a558b465521a6da0133c
Author: Florian Dold <florian@dold.me>
AuthorDate: Tue Jan 12 15:08:15 2021 +0100

    dynamic curl timeouts for /keys and /wire requests
---
 src/lib/exchange_api_handle.c | 120 ++++++++---------------------------------
 src/lib/exchange_api_handle.h | 121 ++++++++++++++++++++++++++++++++++++++++++
 src/lib/exchange_api_wire.c   |  24 +++++++++
 3 files changed, 166 insertions(+), 99 deletions(-)

diff --git a/src/lib/exchange_api_handle.c b/src/lib/exchange_api_handle.c
index c3ed6373..bd6f1cfb 100644
--- a/src/lib/exchange_api_handle.c
+++ b/src/lib/exchange_api_handle.c
@@ -68,27 +68,6 @@
   GNUNET_log (type, "Curl function `%s' has failed at `%s:%d' with error: %s", 
\
               function, __FILE__, __LINE__, curl_easy_strerror (code));
 
-/**
- * Stages of initialization for the `struct TALER_EXCHANGE_Handle`
- */
-enum ExchangeHandleState
-{
-  /**
-   * Just allocated.
-   */
-  MHS_INIT = 0,
-
-  /**
-   * Obtained the exchange's certification data and keys.
-   */
-  MHS_CERT = 1,
-
-  /**
-   * Failed to initialize (fatal).
-   */
-  MHS_FAILED = 2
-};
-
 
 /**
  * Data for the request to get the /keys of a exchange.
@@ -145,83 +124,6 @@ struct TEAH_AuditorListEntry
 };
 
 
-/**
- * Handle to the exchange
- */
-struct TALER_EXCHANGE_Handle
-{
-  /**
-   * The context of this handle
-   */
-  struct GNUNET_CURL_Context *ctx;
-
-  /**
-   * The URL of the exchange (i.e. "http://exchange.taler.net/";)
-   */
-  char *url;
-
-  /**
-   * Function to call with the exchange's certification data,
-   * NULL if this has already been done.
-   */
-  TALER_EXCHANGE_CertificationCallback cert_cb;
-
-  /**
-   * Closure to pass to @e cert_cb.
-   */
-  void *cert_cb_cls;
-
-  /**
-   * Data for the request to get the /keys of a exchange,
-   * NULL once we are past stage #MHS_INIT.
-   */
-  struct KeysRequest *kr;
-
-  /**
-   * Task for retrying /keys request.
-   */
-  struct GNUNET_SCHEDULER_Task *retry_task;
-
-  /**
-   * Raw key data of the exchange, only valid if
-   * @e handshake_complete is past stage #MHS_CERT.
-   */
-  json_t *key_data_raw;
-
-  /**
-   * Head of DLL of auditors of this exchange.
-   */
-  struct TEAH_AuditorListEntry *auditors_head;
-
-  /**
-   * Tail of DLL of auditors of this exchange.
-   */
-  struct TEAH_AuditorListEntry *auditors_tail;
-
-  /**
-   * Key data of the exchange, only valid if
-   * @e handshake_complete is past stage #MHS_CERT.
-   */
-  struct TALER_EXCHANGE_Keys key_data;
-
-  /**
-   * Retry /keys frequency.
-   */
-  struct GNUNET_TIME_Relative retry_delay;
-
-  /**
-   * When does @e key_data expire?
-   */
-  struct GNUNET_TIME_Absolute key_data_expiration;
-
-  /**
-   * Stage of the exchange's initialization routines.
-   */
-  enum ExchangeHandleState state;
-
-};
-
-
 /* ***************** Internal /keys fetching ************* */
 
 /**
@@ -250,6 +152,7 @@ struct KeysRequest
    */
   struct GNUNET_TIME_Absolute expire;
 
+  struct GNUNET_SCHEDULER_Task *timeout_task;
 };
 
 
@@ -1201,6 +1104,8 @@ keys_completed_cb (void *cls,
   {
   case 0:
     free_keys_request (kr);
+    /* FIXME:  Maybe we should only increment when we know it's a timeout? */
+    exchange->keys_error_count++;
     exchange->kr = NULL;
     GNUNET_assert (NULL == exchange->retry_task);
     exchange->retry_delay = EXCHANGE_LIB_BACKOFF (exchange->retry_delay);
@@ -1209,6 +1114,7 @@ keys_completed_cb (void *cls,
                                                          exchange);
     return;
   case MHD_HTTP_OK:
+    exchange->keys_error_count = 0;
     if (NULL == j)
     {
       response_code = 0;
@@ -1290,6 +1196,8 @@ keys_completed_cb (void *cls,
     exchange->retry_delay = GNUNET_TIME_UNIT_ZERO;
     break;
   default:
+    if (MHD_HTTP_GATEWAY_TIMEOUT == response_code)
+      exchange->keys_error_count++;
     hr.ec = TALER_JSON_get_error_code (j);
     hr.hint = TALER_JSON_get_error_hint (j);
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -1882,6 +1790,20 @@ TALER_EXCHANGE_connect (
 }
 
 
+/**
+ * Compute the network timeout for the next request to /keys.
+ *
+ * @param exchange the exchange handle
+ * @returns the timeout in seconds (for use by CURL)
+ */
+static long
+get_keys_timeout_seconds (struct TALER_EXCHANGE_Handle *exchange)
+{
+  return GNUNET_MIN (60,
+                     5 + (1L << exchange->keys_error_count));
+}
+
+
 /**
  * Initiate download of /keys from the exchange.
  *
@@ -1936,7 +1858,7 @@ request_keys (void *cls)
   GNUNET_break (CURLE_OK ==
                 curl_easy_setopt (eh,
                                   CURLOPT_TIMEOUT,
-                                  (long) 300));
+                                  get_keys_timeout_seconds (exchange)));
   GNUNET_assert (CURLE_OK ==
                  curl_easy_setopt (eh,
                                    CURLOPT_HEADERFUNCTION,
diff --git a/src/lib/exchange_api_handle.h b/src/lib/exchange_api_handle.h
index b4b8ccf5..1a7e8ee7 100644
--- a/src/lib/exchange_api_handle.h
+++ b/src/lib/exchange_api_handle.h
@@ -58,6 +58,118 @@ struct TEAH_AuditorInteractionEntry
   struct TALER_AUDITOR_DepositConfirmationHandle *dch;
 };
 
+/**
+ * Stages of initialization for the `struct TALER_EXCHANGE_Handle`
+ */
+enum ExchangeHandleState
+{
+  /**
+   * Just allocated.
+   */
+  MHS_INIT = 0,
+
+  /**
+   * Obtained the exchange's certification data and keys.
+   */
+  MHS_CERT = 1,
+
+  /**
+   * Failed to initialize (fatal).
+   */
+  MHS_FAILED = 2
+};
+
+
+/**
+ * Handle to the exchange
+ */
+struct TALER_EXCHANGE_Handle
+{
+  /**
+   * The context of this handle
+   */
+  struct GNUNET_CURL_Context *ctx;
+
+  /**
+   * The URL of the exchange (i.e. "http://exchange.taler.net/";)
+   */
+  char *url;
+
+  /**
+   * Function to call with the exchange's certification data,
+   * NULL if this has already been done.
+   */
+  TALER_EXCHANGE_CertificationCallback cert_cb;
+
+  /**
+   * Closure to pass to @e cert_cb.
+   */
+  void *cert_cb_cls;
+
+  /**
+   * Data for the request to get the /keys of a exchange,
+   * NULL once we are past stage #MHS_INIT.
+   */
+  struct KeysRequest *kr;
+
+  /**
+   * Task for retrying /keys request.
+   */
+  struct GNUNET_SCHEDULER_Task *retry_task;
+
+  /**
+   * Raw key data of the exchange, only valid if
+   * @e handshake_complete is past stage #MHS_CERT.
+   */
+  json_t *key_data_raw;
+
+  /**
+   * Head of DLL of auditors of this exchange.
+   */
+  struct TEAH_AuditorListEntry *auditors_head;
+
+  /**
+   * Tail of DLL of auditors of this exchange.
+   */
+  struct TEAH_AuditorListEntry *auditors_tail;
+
+  /**
+   * Key data of the exchange, only valid if
+   * @e handshake_complete is past stage #MHS_CERT.
+   */
+  struct TALER_EXCHANGE_Keys key_data;
+
+  /**
+   * Retry /keys frequency.
+   */
+  struct GNUNET_TIME_Relative retry_delay;
+
+  /**
+   * When does @e key_data expire?
+   */
+  struct GNUNET_TIME_Absolute key_data_expiration;
+
+  /**
+   * Number of subsequent failed requests to /keys.
+   *
+   * Used to compute the CURL timeout for the request.
+   */
+  unsigned int keys_error_count;
+
+  /**
+   * Number of subsequent failed requests to /wire.
+   *
+   * Used to compute the CURL timeout for the request.
+   */
+  unsigned int wire_error_count;
+
+  /**
+   * Stage of the exchange's initialization routines.
+   */
+  enum ExchangeHandleState state;
+
+};
+
 
 /**
  * Function called for each auditor to give us a chance to possibly
@@ -111,6 +223,15 @@ struct GNUNET_CURL_Context *
 TEAH_handle_to_context (struct TALER_EXCHANGE_Handle *h);
 
 
+/**
+ * Check if the handle is ready to process requests.
+ *
+ * @param h the exchange handle to query
+ * @return #GNUNET_YES if we are ready, #GNUNET_NO if not
+ */
+int
+TEAH_handle_is_ready (struct TALER_EXCHANGE_Handle *h);
+
 /**
  * Check if the handle is ready to process requests.
  *
diff --git a/src/lib/exchange_api_wire.c b/src/lib/exchange_api_wire.c
index 8653d5a9..eb0894c8 100644
--- a/src/lib/exchange_api_wire.c
+++ b/src/lib/exchange_api_wire.c
@@ -219,6 +219,8 @@ handle_wire_finished (void *cls,
   {
   case 0:
     hr.ec = TALER_EC_GENERIC_INVALID_RESPONSE;
+    /* FIXME:  Maybe we should only increment when we know it's a timeout? */
+    wh->exchange->wire_error_count++;
     break;
   case MHD_HTTP_OK:
     {
@@ -233,6 +235,8 @@ handle_wire_finished (void *cls,
         GNUNET_JSON_spec_end ()
       };
 
+      wh->exchange->wire_error_count = 0;
+
       if (GNUNET_OK !=
           GNUNET_JSON_parse (j,
                              spec,
@@ -356,6 +360,8 @@ handle_wire_finished (void *cls,
     break;
   default:
     /* unexpected response code */
+    if (MHD_HTTP_GATEWAY_TIMEOUT == response_code)
+      wh->exchange->wire_error_count++;
     GNUNET_break_op (0);
     hr.ec = TALER_JSON_get_error_code (j);
     hr.hint = TALER_JSON_get_error_hint (j);
@@ -374,6 +380,20 @@ handle_wire_finished (void *cls,
 }
 
 
+/**
+ * Compute the network timeout for the next request to /wire.
+ *
+ * @param exchange the exchange handle
+ * @returns the timeout in seconds (for use by CURL)
+ */
+static long
+get_wire_timeout_seconds (struct TALER_EXCHANGE_Handle *exchange)
+{
+  return GNUNET_MIN (60,
+                     5 + (1L << exchange->wire_error_count));
+}
+
+
 /**
  * Obtain information about a exchange's wire instructions.
  * A exchange may provide wire instructions for creating
@@ -416,6 +436,10 @@ TALER_EXCHANGE_wire (struct TALER_EXCHANGE_Handle 
*exchange,
   wh->url = TEAH_path_to_url (exchange,
                               "/wire");
   eh = TALER_EXCHANGE_curl_easy_get_ (wh->url);
+  GNUNET_break (CURLE_OK ==
+                curl_easy_setopt (eh,
+                                  CURLOPT_TIMEOUT,
+                                  get_wire_timeout_seconds (wh->exchange)));
   if (NULL == eh)
   {
     GNUNET_break (0);

-- 
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]