Browse Source

tor now tolerates down dirservers better

svn:r2031
Roger Dingledine 20 years ago
parent
commit
2325050b1b
4 changed files with 38 additions and 8 deletions
  1. 8 4
      src/or/connection.c
  2. 4 0
      src/or/directory.c
  3. 1 0
      src/or/or.h
  4. 25 4
      src/or/routerlist.c

+ 8 - 4
src/or/connection.c

@@ -709,16 +709,20 @@ int connection_handle_read(connection_t *conn) {
   }
 
   if(connection_read_to_buf(conn) < 0) {
+    /* There's a read error; kill the connection.*/
+    connection_close_immediate(conn); /* Don't flush; connection is dead. */
+    conn->has_sent_end = 1;
+    connection_mark_for_close(conn);
     if(conn->type == CONN_TYPE_DIR &&
        conn->state == DIR_CONN_STATE_CONNECTING) {
        /* it's a directory server and connecting failed: forget about this router */
        /* XXX I suspect pollerr may make Windows not get to this point. :( */
        router_mark_as_down(conn->identity_digest);
+       if(conn->purpose == DIR_PURPOSE_FETCH_DIR && !all_directory_servers_down()) {
+         log_fn(LOG_INFO,"Giving up on dirserver %s; trying another.", conn->nickname);
+         directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR, NULL, 0);
+       }
     }
-    /* There's a read error; kill the connection.*/
-    connection_close_immediate(conn); /* Don't flush; connection is dead. */
-    conn->has_sent_end = 1;
-    connection_mark_for_close(conn);
     return -1;
   }
   if(connection_process_inbuf(conn) < 0) {

+ 4 - 0
src/or/directory.c

@@ -150,6 +150,10 @@ directory_initiate_command(routerinfo_t *router, uint8_t purpose,
     switch(connection_connect(conn, conn->address, conn->addr, conn->port)) {
       case -1:
         router_mark_as_down(conn->identity_digest); /* don't try him again */
+        if(purpose == DIR_PURPOSE_FETCH_DIR && !all_directory_servers_down) {
+          log_fn(LOG_INFO,"Giving up on dirserver %s; trying another.", conn->nickname);
+          directory_get_from_dirserver(purpose, payload, payload_len);
+        }
         connection_free(conn);
         return;
       case 1:

+ 1 - 0
src/or/or.h

@@ -1348,6 +1348,7 @@ int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
 /********************************* routerlist.c ***************************/
 
 routerinfo_t *router_pick_directory_server(void);
+int all_directory_servers_down(void);
 struct smartlist_t;
 void add_nickname_list_to_smartlist(struct smartlist_t *sl, const char *list);
 void router_add_running_routers_to_smartlist(struct smartlist_t *sl);

+ 25 - 4
src/or/routerlist.c

@@ -62,7 +62,7 @@ routerinfo_t *router_pick_directory_server(void) {
  * routerlist. */
 static routerinfo_t *router_pick_directory_server_impl(void) {
   int i;
-  routerinfo_t *router, *dirserver=NULL;
+  routerinfo_t *router;
   smartlist_t *sl;
 
   if(!routerlist)
@@ -87,17 +87,38 @@ static routerinfo_t *router_pick_directory_server_impl(void) {
 
   /* No running dir servers found? go through and mark them all as up,
    * so we cycle through the list again. */
+  sl = smartlist_create();
   for(i=0; i < smartlist_len(routerlist->routers); i++) {
     router = smartlist_get(routerlist->routers, i);
     if(router->is_trusted_dir) {
       tor_assert(router->dir_port > 0);
       router->is_running = 1;
-      dirserver = router;
+      smartlist_add(sl, router);
     }
   }
-  if(!dirserver)
+  router = smartlist_choose(sl);
+  smartlist_free(sl);
+  if(!router)
     log_fn(LOG_WARN,"No dirservers in directory! Returning NULL.");
-  return dirserver;
+  return router;
+}
+
+/** Return 0 if \exists an authoritative dirserver that's currently
+ * thought to be running, else return 1.
+ */
+int all_directory_servers_down(void) {
+  int i;
+  routerinfo_t *router;
+  if(!routerlist)
+    return 1; /* if no dirservers, I guess they're all down */
+  for(i=0;i< smartlist_len(routerlist->routers); i++) {
+    router = smartlist_get(routerlist->routers, i);
+    if(router->is_running && router->is_trusted_dir) {
+      tor_assert(router->dir_port > 0);
+      return 0;
+    }
+  }
+  return 1;
 }
 
 /** Given a comma-and-whitespace separated list of nicknames, see which