]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
hs-v3: Don't fetch descriptor if we have a pending request
authorDavid Goulet <dgoulet@torproject.org>
Tue, 26 Sep 2017 14:54:46 +0000 (10:54 -0400)
committerDavid Goulet <dgoulet@torproject.org>
Wed, 27 Sep 2017 13:24:35 +0000 (09:24 -0400)
If 6 SOCKS requests are opened at once, it would have triggered 6 fetches
which ultimately poke all 6 HSDir. We don't want that, if we have multiple
SOCKS requests for the same service, do one fetch only.

Signed-off-by: David Goulet <dgoulet@torproject.org>
src/or/connection_edge.c
src/or/hs_client.c
src/or/hs_client.h

index 9098cb690856d385cb177dcf34a195be17703c54..77dac62b09492d3ef067f69591b4286bd1bac00f 100644 (file)
@@ -1576,6 +1576,7 @@ connection_ap_handle_onion(entry_connection_t *conn,
          * connection. */
         goto end;
       case HS_CLIENT_FETCH_LAUNCHED:
+      case HS_CLIENT_FETCH_PENDING:
       case HS_CLIENT_FETCH_HAVE_DESC:
         return 0;
       case HS_CLIENT_FETCH_ERROR:
index 560ccf849981df2df91c4af411acb9dbd53971ed..8ed19529b5e653a97fd82f0c19d04ca4e5e6a2d6 100644 (file)
@@ -108,6 +108,34 @@ purge_hid_serv_request(const ed25519_public_key_t *identity_pk)
   hs_purge_hid_serv_from_last_hid_serv_requests(base64_blinded_pk);
 }
 
+/* Return true iff there is at least one pending directory descriptor request
+ * for the service identity_pk. */
+static int
+directory_request_is_pending(const ed25519_public_key_t *identity_pk)
+{
+  int ret = 0;
+  smartlist_t *conns =
+    connection_list_by_type_purpose(CONN_TYPE_DIR, DIR_PURPOSE_FETCH_HSDESC);
+
+  SMARTLIST_FOREACH_BEGIN(conns, connection_t *, conn) {
+    const hs_ident_dir_conn_t *ident = TO_DIR_CONN(conn)->hs_ident;
+    if (BUG(ident == NULL)) {
+      /* A directory connection fetching a service descriptor can't have an
+       * empty hidden service identifier. */
+      continue;
+    }
+    if (!ed25519_pubkey_eq(identity_pk, &ident->identity_pk)) {
+      continue;
+    }
+    ret = 1;
+    break;
+  } SMARTLIST_FOREACH_END(conn);
+
+  /* No ownership of the objects in this list. */
+  smartlist_free(conns);
+  return ret;
+}
+
 /* A v3 HS circuit successfully connected to the hidden service. Update the
  * stream state at <b>hs_conn_ident</b> appropriately. */
 static void
@@ -1046,6 +1074,12 @@ hs_client_refetch_hsdesc(const ed25519_public_key_t *identity_pk)
     }
   }
 
+  /* Don't try to refetch while we have a pending request for it. */
+  if (directory_request_is_pending(identity_pk)) {
+    log_info(LD_REND, "Already a pending directory request. Waiting on it.");
+    return HS_CLIENT_FETCH_PENDING;
+  }
+
   return fetch_v3_desc(identity_pk);
 }
 
index 08ab7736b6771d960041dd80d8077db88d69cd1c..1d0201903b1b343bd6eae1f48d250e4b6e84f2fc 100644 (file)
@@ -27,6 +27,8 @@ typedef enum {
   HS_CLIENT_FETCH_NOT_ALLOWED  = 3,
   /* We are missing information to be able to launch a request. */
   HS_CLIENT_FETCH_MISSING_INFO = 4,
+  /* There is a pending fetch for the requested service. */
+  HS_CLIENT_FETCH_PENDING      = 5,
 } hs_client_fetch_status_t;
 
 void hs_client_note_connection_attempt_succeeded(