diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 7fd39c411d..da87ca48c8 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -390,8 +390,8 @@ circuit_handle_first_hop(circuit_t *circ) return 0; } -/** Find circuits that are waiting on or_conn to become open, - * if any, and get them to send their create cells forward. +/** Find any circuits that are waiting on or_conn to become + * open and get them to send their create cells forward. * * Status is 1 if connect succeeded, or 0 if connect failed. */ @@ -1927,7 +1927,7 @@ helper_nodes_set_status_from_directory(void) changed = 1; if (changed) { - log_fn(severity, LD_CIRC, " (%d/%d helpers are usable)", + log_fn(severity, LD_CIRC, " (%d/%d helpers are usable/new)", num_live_helpers(), smartlist_len(helper_nodes)); helper_nodes_changed(); } @@ -1936,39 +1936,49 @@ helper_nodes_set_status_from_directory(void) /** Called when a connection to an OR with the identity digest digest * is established (succeeded==1) or has failed (succeeded==0). * If the OR is a helper, change that helper's up/down status. + * Return 0 normally, or -1 if we want to tear down the new connection. */ -void +int helper_node_set_status(const char *digest, int succeeded) { int changed = 0; + int refuse_conn = 0; if (! helper_nodes) - return; + return 0; SMARTLIST_FOREACH(helper_nodes, helper_node_t *, helper, { if (!memcmp(helper->identity, digest, DIGEST_LEN)) { if (succeeded) { if (!helper->made_contact) { + /* We've just added a new long-term helper node. Perhaps + * the network just came back? We should give our earlier + * helpers another try too, and close this connection so + * we don't use it before we've given the others a shot. */ helper->made_contact = 1; - /* We've just added a new long-term helper node. - * Perhaps the network just came back? We should - * give our earlier helpers another try too. */ + refuse_conn = 1; SMARTLIST_FOREACH(helper_nodes, helper_node_t *, h, { routerinfo_t *r = router_get_by_digest(h->identity); - h->down_since = 0; - if (r) r->is_running = 1; + if (h->made_contact) { + h->down_since = 0; + if (r) r->is_running = 1; + } if (h == helper) break; }); + notice(LD_CIRC, + "Connected to new helper node '%s'. Marking earlier " + "helpers up. %d/%d helpers usable/new.", helper->nickname, + num_live_helpers(), smartlist_len(helper_nodes)); changed = 1; } if (helper->down_since) { /*XXXX shouldn't be so loud. NM */ notice(LD_CIRC, "Connection to formerly down helper node '%s' succeeded. " - "%d/%d helpers usable.", helper->nickname, + "%d/%d helpers usable/new.", helper->nickname, num_live_helpers(), smartlist_len(helper_nodes)); helper->down_since = 0; changed = 1; @@ -1977,7 +1987,7 @@ helper_node_set_status(const char *digest, int succeeded) if (!helper->made_contact) { /* dump him */ notice(LD_CIRC, "Connection to never-contacted helper node '%s' failed. " - "Removing from the list. %d/%d helpers usable.", + "Removing from the list. %d/%d helpers usable/new.", helper->nickname, num_live_helpers()-1, smartlist_len(helper_nodes)-1); tor_free(helper); @@ -1986,7 +1996,7 @@ helper_node_set_status(const char *digest, int succeeded) } else if (!helper->down_since) { helper->down_since = time(NULL); warn(LD_CIRC, "Connection to helper node '%s' failed." - " %d/%d helpers usable.", + " %d/%d helpers usable/new.", helper->nickname, num_live_helpers(), smartlist_len(helper_nodes)); changed = 1; @@ -1997,6 +2007,7 @@ helper_node_set_status(const char *digest, int succeeded) if (changed) helper_nodes_changed(); + return refuse_conn ? -1 : 0; } /** Pick a live (up and listed) helper node from the list of helpers, and diff --git a/src/or/connection_or.c b/src/or/connection_or.c index 863595b6fe..d7dea97661 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -659,12 +659,13 @@ static int connection_tls_finish_handshake(connection_t *conn) { char digest_rcvd[DIGEST_LEN]; + int started_here = connection_or_nonopen_was_started_here(conn); debug(LD_OR,"tls handshake done. verifying."); if (connection_or_check_valid_handshake(conn, digest_rcvd) < 0) return -1; - if (!connection_or_nonopen_was_started_here(conn)) { + if (!started_here) { #if 0 connection_t *c; if ((c=connection_or_get_by_identity_digest(digest_rcvd))) { @@ -683,18 +684,23 @@ connection_tls_finish_handshake(connection_t *conn) directory_set_dirty(); conn->state = OR_CONN_STATE_OPEN; + control_event_or_conn_status(conn, OR_CONN_EVENT_CONNECTED); + if (started_here) { + rep_hist_note_connect_succeeded(conn->identity_digest, time(NULL)); + if (helper_node_set_status(conn->identity_digest, 1) < 0) { + /* pending circs get closed in circuit_about_to_close_connection() */ + return -1; + } + } connection_watch_events(conn, EV_READ); circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */ - rep_hist_note_connect_succeeded(conn->identity_digest, time(NULL)); - helper_node_set_status(conn->identity_digest, 1); - control_event_or_conn_status(conn, OR_CONN_EVENT_CONNECTED); return 0; } /** Pack cell into wire-format, and write it onto conn's * outbuf. * - * (Commented out) If it's an OR conn, and an entire TLS record is + * If it's an OR conn, and an entire TLS record is * ready, then try to flush the record now. */ void diff --git a/src/or/or.h b/src/or/or.h index c101ec1a95..4b17094b24 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1469,7 +1469,7 @@ void extend_info_free(extend_info_t *info); routerinfo_t *build_state_get_exit_router(cpath_build_state_t *state); const char *build_state_get_exit_nickname(cpath_build_state_t *state); -void helper_node_set_status(const char *digest, int succeeded); +int helper_node_set_status(const char *digest, int succeeded); void helper_nodes_set_status_from_directory(void); void helper_nodes_update_state(or_state_t *state); int helper_nodes_parse_state(or_state_t *state, int set, const char **err);