commit 15864a1b70c1061a89f97a2054b1c19788af7dbc Author: David Goulet dgoulet@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@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