From a9acdb8f53d408248ae6fa1b803a6c259a34854c Mon Sep 17 00:00:00 2001 From: Roger Dingledine Date: Mon, 24 Mar 2008 05:48:51 +0000 Subject: [PATCH] when our onehop circuits were failing, nobody was telling the streams. so they waited 120 seconds before timing out. this was particularly bad during bootstrapping, if an authority is down or not answering right. svn:r14163 --- src/or/circuituse.c | 3 +++ src/or/connection_edge.c | 29 +++++++++++++++++++++++++++++ src/or/or.h | 1 + 3 files changed, 33 insertions(+) diff --git a/src/or/circuituse.c b/src/or/circuituse.c index 404b7485be..313a6c54d6 100644 --- a/src/or/circuituse.c +++ b/src/or/circuituse.c @@ -744,6 +744,9 @@ circuit_build_failed(origin_circuit_t *circ) n_conn->_base.or_is_obsolete = 1; entry_guard_register_connect_status(n_conn->identity_digest, 0, time(NULL)); + /* if there are any one-hop streams waiting on this circuit, fail + * them now so they can retry elsewhere. */ + connection_ap_fail_onehop(n_conn->identity_digest); } } diff --git a/src/or/connection_edge.c b/src/or/connection_edge.c index a231623981..7d5c4ffb7e 100644 --- a/src/or/connection_edge.c +++ b/src/or/connection_edge.c @@ -460,6 +460,35 @@ connection_ap_attach_pending(void) }); } +/** Tell any AP streams that are waiting for a onehop tunnel to + * failed_digest that they are going to fail. */ +/* XXX021 We should get rid of this function, and instead attach + * onehop streams to circ->p_streams so they get marked in + * circuit_mark_for_close like normal p_streams. */ +void +connection_ap_fail_onehop(const char *failed_digest) +{ + edge_connection_t *edge_conn; + char digest[DIGEST_LEN]; + smartlist_t *conns = get_connection_array(); + SMARTLIST_FOREACH(conns, connection_t *, conn, + { + if (conn->marked_for_close || + conn->type != CONN_TYPE_AP || + conn->state != AP_CONN_STATE_CIRCUIT_WAIT) + continue; + edge_conn = TO_EDGE_CONN(conn); + if (!edge_conn->want_onehop) + continue; + if (!hexdigest_to_digest(edge_conn->chosen_exit_name, digest) && + !memcmp(digest, failed_digest, DIGEST_LEN)) { + log_info(LD_APP, "Closing onehop stream to '%s' because the OR conn " + "just failed.", edge_conn->chosen_exit_name); + connection_mark_unattached_ap(edge_conn, END_STREAM_REASON_TIMEOUT); + } + }); +} + /** A circuit failed to finish on its last hop info. If there * are any streams waiting with this exit node in mind, but they * don't absolutely require it, make them give up on it. diff --git a/src/or/or.h b/src/or/or.h index 695701b903..a21384b9c5 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2812,6 +2812,7 @@ int connection_edge_is_rendezvous_stream(edge_connection_t *conn); int connection_ap_can_use_exit(edge_connection_t *conn, routerinfo_t *exit); void connection_ap_expire_beginning(void); void connection_ap_attach_pending(void); +void connection_ap_fail_onehop(const char *failed_digest); void circuit_discard_optional_exit_enclaves(extend_info_t *info); int connection_ap_detach_retriable(edge_connection_t *conn, origin_circuit_t *circ,