Browse Source

when we connect to a helper node for the first time, close
that connection and its circuits. this lets us go back to
using the old helper nodes rather than immediately using
the last one in the list.


svn:r5670

Roger Dingledine 20 years ago
parent
commit
60cd03069a
3 changed files with 36 additions and 19 deletions
  1. 24 13
      src/or/circuitbuild.c
  2. 11 5
      src/or/connection_or.c
  3. 1 1
      src/or/or.h

+ 24 - 13
src/or/circuitbuild.c

@@ -390,8 +390,8 @@ circuit_handle_first_hop(circuit_t *circ)
   return 0;
   return 0;
 }
 }
 
 
-/** Find circuits that are waiting on <b>or_conn</b> to become open,
- * if any, and get them to send their create cells forward.
+/** Find any circuits that are waiting on <b>or_conn</b> to become
+ * open and get them to send their create cells forward.
  *
  *
  * Status is 1 if connect succeeded, or 0 if connect failed.
  * Status is 1 if connect succeeded, or 0 if connect failed.
  */
  */
@@ -1927,7 +1927,7 @@ helper_nodes_set_status_from_directory(void)
     changed = 1;
     changed = 1;
 
 
   if (changed) {
   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));
            num_live_helpers(), smartlist_len(helper_nodes));
     helper_nodes_changed();
     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 <b>digest</b>
 /** Called when a connection to an OR with the identity digest <b>digest</b>
  * is established (<b>succeeded</b>==1) or has failed (<b>succeeded</b>==0).
  * is established (<b>succeeded</b>==1) or has failed (<b>succeeded</b>==0).
  * If the OR is a helper, change that helper's up/down status.
  * 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)
 helper_node_set_status(const char *digest, int succeeded)
 {
 {
   int changed = 0;
   int changed = 0;
+  int refuse_conn = 0;
 
 
   if (! helper_nodes)
   if (! helper_nodes)
-    return;
+    return 0;
 
 
   SMARTLIST_FOREACH(helper_nodes, helper_node_t *, helper,
   SMARTLIST_FOREACH(helper_nodes, helper_node_t *, helper,
     {
     {
       if (!memcmp(helper->identity, digest, DIGEST_LEN)) {
       if (!memcmp(helper->identity, digest, DIGEST_LEN)) {
         if (succeeded) {
         if (succeeded) {
           if (!helper->made_contact) {
           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;
             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,
             SMARTLIST_FOREACH(helper_nodes, helper_node_t *, h,
               {
               {
                 routerinfo_t *r = router_get_by_digest(h->identity);
                 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)
                 if (h == helper)
                   break;
                   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;
             changed = 1;
           }
           }
           if (helper->down_since) {
           if (helper->down_since) {
             /*XXXX shouldn't be so loud. NM */
             /*XXXX shouldn't be so loud. NM */
             notice(LD_CIRC,
             notice(LD_CIRC,
                    "Connection to formerly down helper node '%s' succeeded. "
                    "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));
                    num_live_helpers(), smartlist_len(helper_nodes));
             helper->down_since = 0;
             helper->down_since = 0;
             changed = 1;
             changed = 1;
@@ -1977,7 +1987,7 @@ helper_node_set_status(const char *digest, int succeeded)
           if (!helper->made_contact) { /* dump him */
           if (!helper->made_contact) { /* dump him */
             notice(LD_CIRC,
             notice(LD_CIRC,
                    "Connection to never-contacted helper node '%s' failed. "
                    "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,
                    helper->nickname,
                    num_live_helpers()-1, smartlist_len(helper_nodes)-1);
                    num_live_helpers()-1, smartlist_len(helper_nodes)-1);
             tor_free(helper);
             tor_free(helper);
@@ -1986,7 +1996,7 @@ helper_node_set_status(const char *digest, int succeeded)
           } else if (!helper->down_since) {
           } else if (!helper->down_since) {
             helper->down_since = time(NULL);
             helper->down_since = time(NULL);
             warn(LD_CIRC, "Connection to helper node '%s' failed."
             warn(LD_CIRC, "Connection to helper node '%s' failed."
-                 " %d/%d helpers usable.",
+                 " %d/%d helpers usable/new.",
                  helper->nickname,
                  helper->nickname,
                  num_live_helpers(), smartlist_len(helper_nodes));
                  num_live_helpers(), smartlist_len(helper_nodes));
             changed = 1;
             changed = 1;
@@ -1997,6 +2007,7 @@ helper_node_set_status(const char *digest, int succeeded)
 
 
   if (changed)
   if (changed)
     helper_nodes_changed();
     helper_nodes_changed();
+  return refuse_conn ? -1 : 0;
 }
 }
 
 
 /** Pick a live (up and listed) helper node from the list of helpers, and
 /** Pick a live (up and listed) helper node from the list of helpers, and

+ 11 - 5
src/or/connection_or.c

@@ -659,12 +659,13 @@ static int
 connection_tls_finish_handshake(connection_t *conn)
 connection_tls_finish_handshake(connection_t *conn)
 {
 {
   char digest_rcvd[DIGEST_LEN];
   char digest_rcvd[DIGEST_LEN];
+  int started_here = connection_or_nonopen_was_started_here(conn);
 
 
   debug(LD_OR,"tls handshake done. verifying.");
   debug(LD_OR,"tls handshake done. verifying.");
   if (connection_or_check_valid_handshake(conn, digest_rcvd) < 0)
   if (connection_or_check_valid_handshake(conn, digest_rcvd) < 0)
     return -1;
     return -1;
 
 
-  if (!connection_or_nonopen_was_started_here(conn)) {
+  if (!started_here) {
 #if 0
 #if 0
     connection_t *c;
     connection_t *c;
     if ((c=connection_or_get_by_identity_digest(digest_rcvd))) {
     if ((c=connection_or_get_by_identity_digest(digest_rcvd))) {
@@ -683,18 +684,23 @@ connection_tls_finish_handshake(connection_t *conn)
 
 
   directory_set_dirty();
   directory_set_dirty();
   conn->state = OR_CONN_STATE_OPEN;
   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);
   connection_watch_events(conn, EV_READ);
   circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */
   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;
   return 0;
 }
 }
 
 
 /** Pack <b>cell</b> into wire-format, and write it onto <b>conn</b>'s
 /** Pack <b>cell</b> into wire-format, and write it onto <b>conn</b>'s
  * outbuf.
  * 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.
  * ready, then try to flush the record now.
  */
  */
 void
 void

+ 1 - 1
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);
 routerinfo_t *build_state_get_exit_router(cpath_build_state_t *state);
 const char *build_state_get_exit_nickname(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_set_status_from_directory(void);
 void helper_nodes_update_state(or_state_t *state);
 void helper_nodes_update_state(or_state_t *state);
 int helper_nodes_parse_state(or_state_t *state, int set, const char **err);
 int helper_nodes_parse_state(or_state_t *state, int set, const char **err);