Browse Source

pick nodes for a circuit only from those the directory says are up

svn:r880
Roger Dingledine 21 years ago
parent
commit
63f81bddae
3 changed files with 48 additions and 12 deletions
  1. 16 10
      src/or/onion.c
  2. 1 2
      src/or/or.h
  3. 31 0
      src/or/routers.c

+ 16 - 10
src/or/onion.c

@@ -439,20 +439,14 @@ int onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t *state, rout
 {
   int cur_len;
   crypt_path_t *cpath, *hop;
-  routerinfo_t **rarray, *r;
+  routerinfo_t *r;
   routerinfo_t *choice;
-  int rarray_len;
   int i;
-  directory_t *dir;
   int n_failures;
 
   assert(head_ptr);
   assert(router_out);
 
-  router_get_directory(&dir);
-  rarray = dir->routers;
-  rarray_len = dir->n_routers;
-  
   if (!*head_ptr) {
     cur_len = 0;
   } else {
@@ -486,14 +480,26 @@ int onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t *state, rout
   /* XXX through each of these, don't pick nodes that are down */
   if(cur_len == 0) { /* picking entry node */
     log_fn(LOG_DEBUG, "Contemplating first hop: random choice.");
-    choice = rarray[crypto_pseudo_rand_int(rarray_len)];
+    choice = router_pick_randomly_from_running();
+    if(!choice) {
+      log_fn(LOG_WARN,"No routers are running while picking entry node. Failing.");
+      return -1;
+    }
   } else if (cur_len == state->desired_path_len - 1) { /* Picking last node */
     log_fn(LOG_DEBUG, "Contemplating last hop: choice already made.");
     choice = router_get_by_nickname(state->chosen_exit);
-    /* XXX check if null */
+    if(!choice) {
+      log_fn(LOG_WARN,"Our chosen exit %s is no longer in the directory? Failing.",
+             state->chosen_exit);
+      return -1;
+    }
   } else {
     log_fn(LOG_DEBUG, "Contemplating intermediate hop: random choice.");
-    choice = rarray[crypto_pseudo_rand_int(rarray_len)];
+    choice = router_pick_randomly_from_running();
+    if(!choice) {
+      log_fn(LOG_WARN,"No routers are running while picking intermediate node. Failing.");
+      return -1;
+    }
   }
   log_fn(LOG_DEBUG,"Contemplating router %s for hop %d (exit is %s)",
          choice->nickname, cur_len, state->chosen_exit);

+ 1 - 2
src/or/or.h

@@ -730,15 +730,14 @@ cpath_build_state_t *onion_new_cpath_build_state(void);
 
 /********************************* routers.c ***************************/
 
-int learn_my_address(struct sockaddr_in *me);
 void router_retry_connections(void);
 routerinfo_t *router_pick_directory_server(void);
+routerinfo_t *router_pick_randomly_from_running(void);
 void router_upload_desc_to_dirservers(void);
 routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port);
 routerinfo_t *router_get_by_link_pk(crypto_pk_env_t *pk);
 routerinfo_t *router_get_by_nickname(char *nickname);
 void router_get_directory(directory_t **pdirectory);
-int router_is_me(uint32_t addr, uint16_t port);
 void router_mark_as_down(char *nickname);
 int router_get_list_from_file(char *routerfile);
 int router_get_router_hash(char *s, char *digest);

+ 31 - 0
src/or/routers.c

@@ -77,6 +77,37 @@ routerinfo_t *router_pick_directory_server(void) {
   return dirserver;
 }
 
+routerinfo_t *router_pick_randomly_from_running(void) {
+  int i,j;
+  int num_running=0;
+
+  if(!directory)
+    return NULL;
+
+  for(i=0;i<directory->n_routers;i++) {
+    if(directory->routers[i]->is_running)
+      num_running++;
+  }
+
+  if(!num_running) {
+    log_fn(LOG_INFO,"No routers are running. Returning NULL.");
+    return NULL;
+  }
+  j = crypto_pseudo_rand_int(num_running);
+  for (i=0;i<directory->n_routers;i++) {
+    if (directory->routers[i]->is_running) {
+      if (j)
+        --j;
+      else {
+        log_fn(LOG_DEBUG, "Chose server '%s'", directory->routers[i]->nickname);
+        return directory->routers[i];
+      }
+    }
+  }
+  assert(0);
+  return NULL;
+}
+
 void router_upload_desc_to_dirservers(void) {
   int i;
   routerinfo_t *router;