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);