[or-cvs] Refactor onion_generate_cpath to build cpaths one hop at a ...

Nick Mathewson nickm at seul.org
Wed Nov 12 02:32:23 UTC 2003


Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/tmp/cvs-serv16984/or

Modified Files:
	circuit.c onion.c or.h 
Log Message:
Refactor onion_generate_cpath to build cpaths one hop at a time.  This
is a the first step in computing hops one step at a time.  Next, we move
the responsibility for calling onion_extend_cpath into circuit.c

(Later, we may want to special-case onion_extend_cpath to treat entry
and exit routers differently.)


Index: circuit.c
===================================================================
RCS file: /home/or/cvsroot/src/or/circuit.c,v
retrieving revision 1.84
retrieving revision 1.85
diff -u -d -r1.84 -r1.85
--- circuit.c	11 Nov 2003 17:21:35 -0000	1.84
+++ circuit.c	12 Nov 2003 02:32:20 -0000	1.85
@@ -6,7 +6,6 @@
 
 extern or_options_t options; /* command-line and config-file options */
 
-static void circuit_free_cpath(crypt_path_t *cpath);
 static void circuit_free_cpath_node(crypt_path_t *victim);
 static circ_id_t get_unique_circ_id_by_addr_port(uint32_t addr, uint16_t port, int circ_id_type);  
 
@@ -90,7 +89,7 @@
   free(circ);
 }
 
-static void circuit_free_cpath(crypt_path_t *cpath) {
+void circuit_free_cpath(crypt_path_t *cpath) {
   crypt_path_t *victim, *head=cpath;
 
   if(!cpath)

Index: onion.c
===================================================================
RCS file: /home/or/cvsroot/src/or/onion.c,v
retrieving revision 1.76
retrieving revision 1.77
diff -u -d -r1.76 -r1.77
--- onion.c	11 Nov 2003 03:01:48 -0000	1.76
+++ onion.c	12 Nov 2003 02:32:20 -0000	1.77
@@ -179,71 +179,37 @@
   return len;
 }
 
-/* returns an array of pointers to routent that define a new route through the OR network
- * int cw is the coin weight to use when choosing the route 
- * order of routers is from last to first
- */
-static unsigned int *new_route(double cw, routerinfo_t **rarray, int rarray_len, int *routelen) {
-  int i;
+static int new_route_len(double cw, routerinfo_t **rarray, int rarray_len) {
   int num_acceptable_routers;
-  unsigned int *route;
-  unsigned int oldchoice, choice;
+  int routelen;
 
-  assert((cw >= 0) && (cw < 1) && (rarray) && (routelen) ); /* valid parameters */
+  assert((cw >= 0) && (cw < 1) && (rarray) ); /* valid parameters */
 
-  *routelen = chooselen(cw);
-  if (*routelen == -1) {
+  routelen = chooselen(cw);
+  if (routelen == -1) {
     log_fn(LOG_WARN,"Choosing route length failed.");
-    return NULL;
+    return -1;
   }
-  log_fn(LOG_DEBUG,"Chosen route length %d (%d routers available).",*routelen, rarray_len);
+  log_fn(LOG_DEBUG,"Chosen route length %d (%d routers available).",routelen, rarray_len);
 
   num_acceptable_routers = count_acceptable_routers(rarray, rarray_len);
 
   if(num_acceptable_routers < 2) {
     log_fn(LOG_INFO,"Not enough acceptable routers. Failing.");
-    return NULL;
+    return -1;
   }
 
-  if(num_acceptable_routers < *routelen) {
-    log_fn(LOG_INFO,"Not enough routers: cutting routelen from %d to %d.",*routelen, num_acceptable_routers);
-    *routelen = num_acceptable_routers;
+  if(num_acceptable_routers < routelen) {
+    log_fn(LOG_INFO,"Not enough routers: cutting routelen from %d to %d.",routelen, num_acceptable_routers);
+    routelen = num_acceptable_routers;
   }
 
-  if(*routelen < 1) {
+  if (routelen < 1) {
     log_fn(LOG_WARN,"Didn't find any acceptable routers. Failing.");
-    return NULL;
+    return -1;
   }
 
-  /* allocate memory for the new route */
-  route = (unsigned int *)tor_malloc(*routelen * sizeof(unsigned int));
- 
-  oldchoice = rarray_len;
-  for(i=0;i<*routelen;i++) {
-//    log_fn(LOG_DEBUG,"Choosing hop %u.",i);
-    if (CRYPTO_PSEUDO_RAND_INT(choice)) {
-      free(route);
-      return NULL;
-    }
-
-    choice = choice % rarray_len;
-    log_fn(LOG_DEBUG,"Contemplating router %u.",choice);
-    if(choice == oldchoice ||
-       (oldchoice < rarray_len && !crypto_pk_cmp_keys(rarray[choice]->onion_pkey, rarray[oldchoice]->onion_pkey)) ||
-      (options.OnionRouter && !connection_twin_get_by_addr_port(rarray[choice]->addr, rarray[choice]->or_port))) {
-      /* Same router as last choice, or router twin,
-       *   or no routers with that key are connected to us.
-       * Try again. */
-      log_fn(LOG_DEBUG,"Picked a router %d that won't work as next hop.",choice);
-      i--;
-      continue;  
-    }
-    log_fn(LOG_DEBUG,"Chosen router %u for hop %u.",choice,i);
-    oldchoice = choice;
-    route[i] = choice;
-  }
-   
-  return route;
+  return routelen;
 }
 
 static int count_acceptable_routers(routerinfo_t **rarray, int rarray_len) {
@@ -276,76 +242,117 @@
   return num;
 }
 
+/* XXX This function should be replaced by calls to onion_extend_cpath */
 crypt_path_t *onion_generate_cpath(routerinfo_t **firsthop) {
-  int routelen; /* length of the route */
-  unsigned int *route; /* hops in the route as an array of indexes into rarray */
+  int routelen;
   crypt_path_t *cpath=NULL;
+  int r;
   directory_t *dir;
   routerinfo_t **rarray;
   int rarray_len;
-  int i;
-  crypt_path_t *hop;
-  routerinfo_t *router;
-  struct in_addr netaddr;
+
+  assert(firsthop);
+  *firsthop = NULL;
 
   router_get_directory(&dir);
   rarray = dir->routers;
   rarray_len = dir->n_routers;
-
-  /* choose a route */
-  route = new_route(options.CoinWeight, rarray, rarray_len, &routelen);
-  if (!route) {
-    log_fn(LOG_INFO,"Error choosing a route through the OR network.");
-    return NULL;
+  
+  routelen = new_route_len(options.CoinWeight, rarray, rarray_len);
+  if (routelen < 0) return NULL;
+  
+  while (1) {
+    r = onion_extend_cpath(&cpath, routelen, cpath ? NULL : firsthop);
+    if (r < 0) {
+      if (cpath) circuit_free_cpath(cpath);
+      return NULL;
+    } else if (r == 1) {
+      break;
+    }
+    /* r == 0; keep on chugging. */
   }
-  log_fn(LOG_DEBUG,"Chosen a route of length %u: ",routelen);
+  return cpath;
+}
 
-  *firsthop = rarray[route[routelen-1]];
-  assert(*firsthop); /* should always be defined */
+int onion_extend_cpath(crypt_path_t **head_ptr, int path_len, routerinfo_t **router_out)
+{
+  int cur_len;
+  crypt_path_t *cpath, *hop;
+  routerinfo_t **rarray, *r;
+  unsigned int choice;
+  int rarray_len;
+  int i;
+  directory_t *dir;
 
-  for(i=0; i<routelen; i++) {
-    netaddr.s_addr = htonl((rarray[route[i]])->addr);
+  assert(head_ptr);
+  if (router_out)
+    *router_out = NULL;
 
-    log_fn(LOG_DEBUG,"%u : %s:%u, %u/%u",routelen-i,
-        inet_ntoa(netaddr),
-        (rarray[route[i]])->or_port,
-        (int) (rarray[route[i]])->onion_pkey,
-        crypto_pk_keysize((rarray[route[i]])->onion_pkey));
+  router_get_directory(&dir);
+  rarray = dir->routers;
+  rarray_len = dir->n_routers;
+  
+  if (!*head_ptr) {
+    cur_len = 0;
+  } else {
+    cur_len = 1;
+    for (cpath = *head_ptr; cpath->next != *head_ptr; cpath = cpath->next) {
+      ++cur_len;
+    }
   }
+  if (cur_len >= path_len) { return 1; }
+  log_fn(LOG_DEBUG, "Path is %d long; we want %d", cur_len, path_len);
 
-  /* create the cpath layer by layer, starting at the last hop */
-  for (i=0;i<routelen;i++) {
-    router = rarray[route[i]];
-
-    /* build up the crypt_path */
-    hop = (crypt_path_t *)tor_malloc(sizeof(crypt_path_t));
-    memset(hop, 0, sizeof(crypt_path_t));
-
-    /* link hop into the cpath, at the front */
-    hop->next = cpath;
-    hop->prev = NULL;
-    hop->state = CPATH_STATE_CLOSED;
-    if(cpath) {
-      cpath->prev = hop;
+ again:
+  if (CRYPTO_PSEUDO_RAND_INT(choice)) {
+    return -1;
+  }
+  choice %= rarray_len;
+  log_fn(LOG_DEBUG,"Contemplating router %s for hop %d",
+         rarray[choice]->nickname, cur_len);
+  for (i = 0, cpath = *head_ptr; i < cur_len; ++i, cpath=cpath->next) {
+    r = router_get_by_addr_port(cpath->addr, cpath->port);
+    if ((r && !crypto_pk_cmp_keys(r->onion_pkey, rarray[choice]->onion_pkey))
+        || (cpath->addr == rarray[choice]->addr && 
+            cpath->port == rarray[choice]->or_port)
+        || (options.OnionRouter && 
+            !(connection_twin_get_by_addr_port(rarray[choice]->addr,
+                                               rarray[choice]->or_port)))) {
+      log_fn(LOG_DEBUG, "Picked an already-selected router for hop %d; retrying.",
+             cur_len);
+      goto again;
     }
-    cpath = hop;
-
-    hop->port = rarray[route[i]]->or_port;
-    hop->addr = rarray[route[i]]->addr;
-
-    hop->package_window = CIRCWINDOW_START;
-    hop->deliver_window = CIRCWINDOW_START;
+  }
+  
+  /* Okay, so we haven't used 'choice' before. */
+  hop = (crypt_path_t *)tor_malloc(sizeof(crypt_path_t));
+  memset(hop, 0, sizeof(crypt_path_t));
 
-    log_fn(LOG_DEBUG,"Building hop %u of crypt path.",i+1);
+  /* link hop into the cpath, at the end. */
+  if (*head_ptr) {
+    hop->next = (*head_ptr);
+    hop->prev = (*head_ptr)->prev;
+    (*head_ptr)->prev->next = hop;
+    (*head_ptr)->prev = hop;
+  } else {
+    *head_ptr = hop;
+    hop->prev = hop->next = hop;
   }
 
-  /* now link cpath->prev to the end of cpath */
-  for(hop=cpath; hop->next; hop=hop->next) ;
-  hop->next = cpath;
-  cpath->prev = hop;
+  hop->state = CPATH_STATE_CLOSED;
+  
+  hop->port = rarray[choice]->or_port;
+  hop->addr = rarray[choice]->addr;
+  
+  hop->package_window = CIRCWINDOW_START;
+  hop->deliver_window = CIRCWINDOW_START;
 
-  free(route);
-  return cpath;
+  log_fn(LOG_DEBUG, "Extended circuit path with %s for hop %d", 
+         rarray[choice]->nickname, cur_len);
+  
+  if (router_out)
+    *router_out = rarray[choice];
+  return 0;
 }
 
 /*----------------------------------------------------------------------*/
@@ -425,7 +432,7 @@
   if (crypto_cipher_encrypt(cipher, pubkey+pkbytes, dhbytes+16-pkbytes,
                             onion_skin_out+pkbytes))
     goto err;
-
+  
   free(pubkey);
   crypto_free_cipher_env(cipher);
   *handshake_state_out = dh;
@@ -564,3 +571,5 @@
   c-basic-offset:2
   End:
 */
+
+

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.178
retrieving revision 1.179
diff -u -d -r1.178 -r1.179
--- or.h	11 Nov 2003 04:13:37 -0000	1.178
+++ or.h	12 Nov 2003 02:32:20 -0000	1.179
@@ -502,6 +502,7 @@
 void circuit_remove(circuit_t *circ);
 circuit_t *circuit_new(circ_id_t p_circ_id, connection_t *p_conn);
 void circuit_free(circuit_t *circ);
+void circuit_free_cpath(crypt_path_t *cpath);
 
 circuit_t *circuit_enumerate_by_naddr_nport(circuit_t *start, uint32_t naddr, uint16_t nport);
 circuit_t *circuit_get_by_circ_id_conn(circ_id_t circ_id, connection_t *conn);
@@ -692,6 +693,7 @@
 int onionskin_answer(circuit_t *circ, unsigned char *payload, unsigned char *keys);
 
 crypt_path_t *onion_generate_cpath(routerinfo_t **firsthop);
+int onion_extend_cpath(crypt_path_t **head_ptr, int path_len, routerinfo_t **router_out);
 
 int onion_skin_create(crypto_pk_env_t *router_key,
                       crypto_dh_env_t **handshake_state_out,



More information about the tor-commits mailing list