dirmngr: Avoid endless loop in case of HTTP error 503.
authorWerner Koch <wk@gnupg.org>
Wed, 3 Jul 2019 15:39:53 +0000 (17:39 +0200)
committerWerner Koch <wk@gnupg.org>
Wed, 3 Jul 2019 15:39:53 +0000 (17:39 +0200)
* dirmngr/ks-engine-hkp.c (SEND_REQUEST_EXTRA_RETRIES): New.
(handle_send_request_error): Use it for 503 and 504.
(ks_hkp_search, ks_hkp_get, ks_hkp_put): Pass a new var for
extra_tries.
--

This is a pretty stupid fix but one which works without much risk of
regressions.  We could have used the existing TRIES but in that case
the fallback to other host would have been too limited.  With the used
value we can have several fallbacks to other hosts.  Note that the
TRIES is still cumulative and not per host.

GnuPG-bug-id: 4600
Signed-off-by: Werner Koch <wk@gnupg.org>
dirmngr/ks-engine-hkp.c

index 0a360f0..ef33db2 100644 (file)
 /* Number of retries done for a dead host etc.  */
 #define SEND_REQUEST_RETRIES 3
 
+/* Number of retries done in case of transient errors.  */
+#define SEND_REQUEST_EXTRA_RETRIES 5
+
+
 enum ks_protocol { KS_PROTOCOL_HKP, KS_PROTOCOL_HKPS, KS_PROTOCOL_MAX };
 
 /* Objects used to maintain information about hosts.  */
@@ -1353,10 +1357,12 @@ send_request (ctrl_t ctrl, const char *request, const char *hostportstr,
    with REQUEST.  The function returns true if the caller shall try
    again.  TRIES_LEFT points to a variable to track the number of
    retries; this function decrements it and won't return true if it is
-   down to zero. */
+   down to zero.  EXTRA_TRIES_LEFT does the same but only for
+   transient http status codes.  */
 static int
 handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
-                           unsigned int http_status, unsigned int *tries_left)
+                           unsigned int http_status, unsigned int *tries_left,
+                           unsigned int *extra_tries_left)
 {
   int retry = 0;
 
@@ -1412,9 +1418,12 @@ handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
 
           case 503: /* Service Unavailable */
           case 504: /* Gateway Timeout    */
-            log_info ("selecting a different host due to a %u (%s)",
-                      http_status, http_status2string (http_status));
-            retry = 1;
+            if (*extra_tries_left)
+              {
+                log_info ("selecting a different host due to a %u (%s)",
+                          http_status, http_status2string (http_status));
+                retry = 2;
+              }
             break;
           }
       }
@@ -1424,8 +1433,16 @@ handle_send_request_error (ctrl_t ctrl, gpg_error_t err, const char *request,
       break;
     }
 
-  if (*tries_left)
-    --*tries_left;
+  if (retry == 2)
+    {
+      if (*extra_tries_left)
+        --*extra_tries_left;
+    }
+  else
+    {
+      if (*tries_left)
+        --*tries_left;
+    }
 
   return retry;
 }
@@ -1450,6 +1467,7 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
   char *httphost = NULL;
   unsigned int http_status;
   unsigned int tries = SEND_REQUEST_RETRIES;
+  unsigned int extra_tries = SEND_REQUEST_EXTRA_RETRIES;
 
   *r_fp = NULL;
 
@@ -1525,7 +1543,8 @@ ks_hkp_search (ctrl_t ctrl, parsed_uri_t uri, const char *pattern,
   /* Send the request.  */
   err = send_request (ctrl, request, hostport, httphost, httpflags,
                       NULL, NULL, &fp, &http_status);
-  if (handle_send_request_error (ctrl, err, request, http_status, &tries))
+  if (handle_send_request_error (ctrl, err, request, http_status,
+                                 &tries, &extra_tries))
     {
       reselect = 1;
       goto again;
@@ -1595,6 +1614,7 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
   unsigned int httpflags;
   unsigned int http_status;
   unsigned int tries = SEND_REQUEST_RETRIES;
+  unsigned int extra_tries = SEND_REQUEST_EXTRA_RETRIES;
 
   *r_fp = NULL;
 
@@ -1668,7 +1688,8 @@ ks_hkp_get (ctrl_t ctrl, parsed_uri_t uri, const char *keyspec, estream_t *r_fp)
   /* Send the request.  */
   err = send_request (ctrl, request, hostport, httphost, httpflags,
                       NULL, NULL, &fp, &http_status);
-  if (handle_send_request_error (ctrl, err, request, http_status, &tries))
+  if (handle_send_request_error (ctrl, err, request, http_status,
+                                 &tries, &extra_tries))
     {
       reselect = 1;
       goto again;
@@ -1744,6 +1765,7 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
   unsigned int httpflags;
   unsigned int http_status;
   unsigned int tries = SEND_REQUEST_RETRIES;
+  unsigned int extra_tries = SEND_REQUEST_EXTRA_RETRIES;
 
   parm.datastring = NULL;
 
@@ -1782,7 +1804,8 @@ ks_hkp_put (ctrl_t ctrl, parsed_uri_t uri, const void *data, size_t datalen)
   /* Send the request.  */
   err = send_request (ctrl, request, hostport, httphost, 0,
                       put_post_cb, &parm, &fp, &http_status);
-  if (handle_send_request_error (ctrl, err, request, http_status, &tries))
+  if (handle_send_request_error (ctrl, err, request, http_status,
+                                 &tries, &extra_tries))
     {
       reselect = 1;
       goto again;