[tor-commits] [tor/master] prop224: Add a circuit has closed callback

nickm at torproject.org nickm at torproject.org
Wed Aug 9 00:36:37 UTC 2017


commit 15864a1b70c1061a89f97a2054b1c19788af7dbc
Author: David Goulet <dgoulet at torproject.org>
Date:   Thu May 25 10:28:00 2017 -0400

    prop224: Add a circuit has closed callback
    
    When the circuit is about to be freed which has been marked close before, for
    introduction circuit we now call this has_closed() callback so we can cleanup
    any introduction point that have retried to many times or at least flag them
    that their circuit is not established anymore.
    
    Signed-off-by: David Goulet <dgoulet at torproject.org>
---
 src/or/circuitlist.c |  7 ++++++
 src/or/hs_service.c  | 64 ++++++++++++++++++++++++++++++++++++++++------------
 src/or/hs_service.h  |  2 ++
 3 files changed, 59 insertions(+), 14 deletions(-)

diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 39ebeb5f3..d891c89f3 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -1949,6 +1949,13 @@ circuit_about_to_free(circuit_t *circ)
      orig_reason);
   }
 
+  /* Notify the HS subsystem for any intro point circuit closing so it can be
+   * dealt with cleanly. */
+  if (circ->purpose == CIRCUIT_PURPOSE_S_ESTABLISH_INTRO ||
+      circ->purpose == CIRCUIT_PURPOSE_S_INTRO) {
+    hs_service_intro_circ_has_closed(TO_ORIGIN_CIRCUIT(circ));
+  }
+
   if (circ->purpose == CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT) {
     origin_circuit_t *ocirc = TO_ORIGIN_CIRCUIT(circ);
     int timed_out = (reason == END_CIRC_REASON_TIMEOUT);
diff --git a/src/or/hs_service.c b/src/or/hs_service.c
index 9f496b615..0b524a3a8 100644
--- a/src/or/hs_service.c
+++ b/src/or/hs_service.c
@@ -1584,18 +1584,10 @@ cleanup_intro_points(hs_service_t *service, time_t now)
        * node_t anymore (removed from our latest consensus) or if we've
        * reached the maximum number of retry with a non existing circuit. */
       if (has_expired || node == NULL ||
-          (ocirc == NULL &&
-           ip->circuit_retries > MAX_INTRO_POINT_CIRCUIT_RETRIES)) {
+          ip->circuit_retries > MAX_INTRO_POINT_CIRCUIT_RETRIES) {
         /* Remove intro point from descriptor map. We'll add it to the failed
          * map if we retried it too many times. */
         MAP_DEL_CURRENT(key);
-
-        /* We've retried too many times, remember it has a failed intro point
-         * so we don't pick it up again. It will be retried in
-         * INTRO_CIRC_RETRY_PERIOD seconds. */
-        if (ip->circuit_retries >= MAX_INTRO_POINT_CIRCUIT_RETRIES) {
-          remember_failing_intro_point(ip, desc, now);
-        }
         service_intro_point_free(ip);
 
         /* XXX: Legacy code does NOT do that, it keeps the circuit open until
@@ -1611,11 +1603,6 @@ cleanup_intro_points(hs_service_t *service, time_t now)
         }
         continue;
       }
-      if (ocirc == NULL) {
-        /* Circuit disappeared so make sure the intro point is updated. By
-         * keeping the object in the descriptor, we'll be able to retry. */
-        ip->circuit_established = 0;
-      }
     } DIGEST256MAP_FOREACH_END;
   } FOR_EACH_DESCRIPTOR_END;
 }
@@ -2386,6 +2373,55 @@ service_add_fnames_to_list(const hs_service_t *service, smartlist_t *list)
 /* Public API */
 /* ========== */
 
+/* Called once an introduction circuit is closed. If the circuit doesn't have
+ * a v3 identifier, it is ignored. */
+void
+hs_service_intro_circ_has_closed(origin_circuit_t *circ)
+{
+  hs_service_t *service = NULL;
+  hs_service_intro_point_t *ip = NULL;
+  hs_service_descriptor_t *desc = NULL;
+
+  tor_assert(circ);
+
+  if (circ->hs_ident == NULL) {
+    /* This is not a v3 circuit, ignore. */
+    goto end;
+  }
+
+  get_objects_from_ident(circ->hs_ident, &service, &ip, &desc);
+  if (service == NULL) {
+    log_warn(LD_REND, "Unable to find any hidden service associated "
+                      "identity key %s on intro circuit %u.",
+             ed25519_fmt(&circ->hs_ident->identity_pk),
+             TO_CIRCUIT(circ)->n_circ_id);
+    goto end;
+  }
+  if (ip == NULL) {
+    /* The introduction point object has already been removed probably by our
+     * cleanup process so ignore. */
+    goto end;
+  }
+  /* Can't have an intro point object without a descriptor. */
+  tor_assert(desc);
+
+  /* Circuit disappeared so make sure the intro point is updated. By
+   * keeping the object in the descriptor, we'll be able to retry. */
+  ip->circuit_established = 0;
+
+  /* We've retried too many times, remember it as a failed intro point so we
+   * don't pick it up again. It will be retried in INTRO_CIRC_RETRY_PERIOD
+   * seconds. */
+  if (ip->circuit_retries > MAX_INTRO_POINT_CIRCUIT_RETRIES) {
+    remember_failing_intro_point(ip, desc, approx_time());
+    service_intro_point_remove(service, ip);
+    service_intro_point_free(ip);
+  }
+
+ end:
+  return;
+}
+
 /* Given conn, a rendezvous edge connection acting as an exit stream, look up
  * the hidden service for the circuit circ, and look up the port and address
  * based on the connection port. Assign the actual connection address.
diff --git a/src/or/hs_service.h b/src/or/hs_service.h
index dc80622e3..bc29c3d82 100644
--- a/src/or/hs_service.h
+++ b/src/or/hs_service.h
@@ -270,6 +270,8 @@ int hs_service_receive_introduce2(origin_circuit_t *circ,
                                   const uint8_t *payload,
                                   size_t payload_len);
 
+void hs_service_intro_circ_has_closed(origin_circuit_t *circ);
+
 #ifdef HS_SERVICE_PRIVATE
 
 #ifdef TOR_UNIT_TESTS





More information about the tor-commits mailing list