Browse Source

choose randomly from running dirservers, not always the first one

svn:r881
Roger Dingledine 20 years ago
parent
commit
4f2d556508
1 changed files with 30 additions and 13 deletions
  1. 30 13
      src/or/routers.c

+ 30 - 13
src/or/routers.c

@@ -50,31 +50,48 @@ void router_retry_connections(void) {
 }
 
 routerinfo_t *router_pick_directory_server(void) {
-  /* pick the first running router with a positive dir_port */
-  int i;
+  /* pick a random running router with a positive dir_port */
+  int i,j;
   routerinfo_t *router, *dirserver=NULL;
-  
+  int num_dirservers=0;
+
   if(!directory)
     return NULL;
 
   for(i=0;i<directory->n_routers;i++) {
     router = directory->routers[i];
     if(router->dir_port > 0 && router->is_running)
-      return router;
+      num_dirservers++;
+  }
+
+  if(!num_dirservers) {
+    log_fn(LOG_INFO,"No dirservers are reachable. Trying them all again.");
+    /* no running dir servers found? go through and mark them all as up,
+     * and we'll cycle through the list again. */
+    for(i=0;i<directory->n_routers;i++) {
+      router = directory->routers[i];
+      if(router->dir_port > 0) {
+        router->is_running = 1;
+        dirserver = router;
+      }
+    }
+    return dirserver;
   }
 
-  log_fn(LOG_INFO,"No dirservers are reachable. Trying them all again.");
-  /* no running dir servers found? go through and mark them all as up,
-   * and we'll cycle through the list again. */
-  for(i=0;i<directory->n_routers;i++) {
+  j = crypto_pseudo_rand_int(num_dirservers);
+  for (i=0;i<directory->n_routers;i++) {
     router = directory->routers[i];
-    if(router->dir_port > 0) {
-      router->is_running = 1;
-      dirserver = router;
+    if (router->dir_port > 0 && router->is_running) {
+      if (j)
+        --j;
+      else {
+        log_fn(LOG_DEBUG, "Chose server '%s'", router->nickname);
+        return router;
+      }
     }
   }
-
-  return dirserver;
+  assert(0);
+  return NULL;
 }
 
 routerinfo_t *router_pick_randomly_from_running(void) {