[or-cvs] now circuit_get_newest returns an appropriate circ for your...

Roger Dingledine arma at seul.org
Fri Apr 2 22:23:18 UTC 2004


Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/home2/arma/work/onion/cvs/src/or

Modified Files:
	Makefile.am circuit.c connection_edge.c directory.c main.c 
	onion.c or.h rendcommon.c rendservice.c routerlist.c 
Added Files:
	rendclient.c 
Log Message:
now circuit_get_newest returns an appropriate circ for your purpose

connection_ap_handshake_attach_circuit attaches to a circ of the
right purpose

add a skeletal rendclient.c


--- NEW FILE: rendclient.c ---
/* Copyright 2004 Roger Dingledine */
/* See LICENSE for licensing information */
/* $Id: rendclient.c,v 1.1 2004/04/02 22:23:15 arma Exp $ */

#include "or.h"

/* send the introduce cell */
void
rend_client_intro_is_ready()
{


}

/* send the rendezvous cell */
void
rend_client_rendezvous_is_ready()
{


}

/* bob sent us a rendezvous cell, join the circs. */
void
rend_client_rendezvous()
{


}




void rend_client_desc_fetched(char *query) {


}

void rend_client_desc_not_fetched(char *query) {


}

/*
  Local Variables:
  mode:c
  indent-tabs-mode:nil
  c-basic-offset:2
  End:
*/

Index: Makefile.am
===================================================================
RCS file: /home/or/cvsroot/src/or/Makefile.am,v
retrieving revision 1.30
retrieving revision 1.31
diff -u -d -r1.30 -r1.31
--- Makefile.am	1 Apr 2004 04:07:09 -0000	1.30
+++ Makefile.am	2 Apr 2004 22:23:15 -0000	1.31
@@ -7,8 +7,8 @@
 tor_SOURCES = buffers.c circuit.c command.c config.c \
 	connection.c connection_edge.c connection_or.c \
 	cpuworker.c directory.c dirserv.c dns.c main.c \
-	onion.c rendcommon.c rendmid.c rendservice.c rephist.c \
-	router.c routerlist.c \
+	onion.c rendcommon.c rendclient.c rendmid.c \
+	rendservice.c rephist.c router.c routerlist.c \
 	tor_main.c
 
 tor_LDADD = ../common/libor.a
@@ -16,8 +16,8 @@
 test_SOURCES = buffers.c circuit.c command.c config.c \
 	connection.c connection_edge.c connection_or.c \
 	cpuworker.c directory.c dirserv.c dns.c main.c \
-	onion.c rendcommon.c rendmid.c rendservice.c rephist.c \
-	router.c routerlist.c \
+	onion.c rendcommon.c rendclient.c rendmid.c \
+	rendservice.c rephist.c router.c routerlist.c \
 	test.c
 
 test_LDADD = ../common/libor.a

Index: circuit.c
===================================================================
RCS file: /home/or/cvsroot/src/or/circuit.c,v
retrieving revision 1.169
retrieving revision 1.170
diff -u -d -r1.169 -r1.170
--- circuit.c	2 Apr 2004 21:56:52 -0000	1.169
+++ circuit.c	2 Apr 2004 22:23:15 -0000	1.170
@@ -255,34 +255,56 @@
  * If !conn, return newest.
  *
  * If must_be_open, ignore circs not in CIRCUIT_STATE_OPEN.
- * If must_be_clean, ignore circs that have been used before.
+ *
+ * circ_purpose specifies what sort of circuit we must have.
+ * If circ_purpose is not GENERAL, then conn must be defined.
  */
 circuit_t *circuit_get_newest(connection_t *conn,
-                              int must_be_open, int must_be_clean) {
+                              int must_be_open, uint8_t circ_purpose) {
   circuit_t *circ, *newest=NULL, *leastdirty=NULL;
   routerinfo_t *exitrouter;
 
   for (circ=global_circuitlist;circ;circ = circ->next) {
     if (!circ->cpath)
       continue; /* this circ doesn't start at us */
-    if (circ->purpose != CIRCUIT_PURPOSE_C_GENERAL)
-      continue; /* don't pick rendezvous circuits */
     if (must_be_open && (circ->state != CIRCUIT_STATE_OPEN || !circ->n_conn))
       continue; /* ignore non-open circs */
     if (circ->marked_for_close)
       continue;
+
+    if (circ->purpose != circ_purpose)
+      continue;
+
+#if 0
     if (must_be_clean && circ->timestamp_dirty)
       continue; /* ignore dirty circs */
+#endif
+
     if(conn) {
+      /* decide if this circ is suitable for this conn */
+
       if(circ->state == CIRCUIT_STATE_OPEN && circ->n_conn) /* open */
-        exitrouter = router_get_by_addr_port(circ->cpath->prev->addr, circ->cpath->prev->port);
+        exitrouter = router_get_by_addr_port(circ->cpath->prev->addr,
+                                             circ->cpath->prev->port);
       else /* not open */
         exitrouter = router_get_by_nickname(circ->build_state->chosen_exit);
-      if(!exitrouter || connection_ap_can_use_exit(conn, exitrouter) == ADDR_POLICY_REJECTED) {
-        /* can't exit from this router */
-        continue;
+
+      if(!exitrouter)
+        continue; /* this circuit is screwed and doesn't know it yet */
+
+      if(circ_purpose == CIRCUIT_PURPOSE_C_GENERAL) {
+        if(connection_ap_can_use_exit(conn, exitrouter) == ADDR_POLICY_REJECTED) {
+          /* can't exit from this router */
+          continue;
+        }
+      } else { /* not general */
+        if(rend_cmp_service_ids(conn->socks_request->address, circ->rend_service)) {
+          /* this circ is not for this conn */
+          continue;
+        }
       }
     }
+
     if(!newest || newest->timestamp_created < circ->timestamp_created) {
       newest = circ;
     }
@@ -1033,11 +1055,11 @@
       break;
     case CIRCUIT_PURPOSE_C_INTRODUCING:
       /* at Alice, connecting to intro point */
-      // alice sends introduce1 relay cell
+      rend_client_intro_is_ready(circ);
       break;
     case CIRCUIT_PURPOSE_C_ESTABLISH_REND:
       /* at Alice, waiting for Bob */
-      // alice launches a circuit to bob's intro point
+      rend_client_rendezvous_is_ready(circ);
       break;
     case CIRCUIT_PURPOSE_S_CONNECT_REND:
       /* at Bob, connecting to rend point */
@@ -1246,9 +1268,6 @@
       }
       circuit_rep_hist_note_result(circ);
       circuit_is_ready(circ); /* do other actions as necessary */
-      /* Tell any AP connections that have been waiting for a new
-       * circuit that one is ready. */
-      connection_ap_attach_pending();
       return 0;
     } else if (r<0) {
       log_fn(LOG_INFO,"Unable to extend circuit path.");

Index: connection_edge.c
===================================================================
RCS file: /home/or/cvsroot/src/or/connection_edge.c,v
retrieving revision 1.125
retrieving revision 1.126
diff -u -d -r1.125 -r1.126
--- connection_edge.c	1 Apr 2004 20:33:28 -0000	1.125
+++ connection_edge.c	2 Apr 2004 22:23:15 -0000	1.126
@@ -9,10 +9,7 @@
 extern char *conn_state_to_string[][_CONN_TYPE_MAX+1];
 
 static int connection_ap_handshake_process_socks(connection_t *conn);
-static int connection_ap_handshake_attach_circuit(connection_t *conn,
-                                                  int must_be_clean);
-static int connection_ap_handshake_attach_circuit_helper(connection_t *conn,
-                                                         int must_be_clean);
+static int connection_ap_handshake_attach_circuit(connection_t *conn);
 static void connection_ap_handshake_send_begin(connection_t *ap_conn, circuit_t *circ);
 
 static int connection_exit_begin_conn(cell_t *cell, circuit_t *circ);
@@ -377,9 +374,10 @@
         memcpy(&addr, cell->payload+RELAY_HEADER_SIZE+1, 4);
         addr = ntohl(addr);
         client_dns_set_entry(conn->socks_request->address, addr);
+        /* conn->purpose is still set to general */
         conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
         /* attaching to a dirty circuit is fine */
-        if(connection_ap_handshake_attach_circuit(conn, 0) >= 0)
+        if(connection_ap_handshake_attach_circuit(conn) >= 0)
           return 0;
         /* else, conn will get closed below */
       }
@@ -639,6 +637,7 @@
       conn->has_sent_end = 0;
       /* move it back into 'pending' state. */
       conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
+      /* conn->purpose is still set to general */
       circuit_detach_stream(circ, conn);
       /* kludge to make us not try this circuit again, yet to allow
        * current streams on it to survive if they can: make it
@@ -648,7 +647,7 @@
       /* give our stream another 15 seconds to try */
       conn->timestamp_lastread += 15;
       /* attaching to a dirty circuit is fine */
-      if(connection_ap_handshake_attach_circuit(conn,0)<0) {
+      if(connection_ap_handshake_attach_circuit(conn)<0) {
         /* it will never work */
         /* Don't need to send end -- we're not connected */
         connection_mark_for_close(conn, 0);
@@ -672,7 +671,7 @@
         conn->state != AP_CONN_STATE_CIRCUIT_WAIT)
       continue;
     /* attaching to a dirty circuit is fine */
-    if(connection_ap_handshake_attach_circuit(conn,0) < 0) {
+    if(connection_ap_handshake_attach_circuit(conn) < 0) {
       /* -1 means it will never work */
       /* Don't send end; there is no 'other side' yet */
       connection_mark_for_close(conn,0);
@@ -738,8 +737,9 @@
   if (rend_parse_rendezvous_address(socks->address) < 0) {
     /* normal request */
     conn->state = AP_CONN_STATE_CIRCUIT_WAIT;
+    conn->purpose = AP_PURPOSE_GENERAL;
     /* attaching to a dirty circuit is fine */
-    return connection_ap_handshake_attach_circuit(conn,0);
+    return connection_ap_handshake_attach_circuit(conn);
   } else {
     /* it's a hidden-service request */
     const char *descp;
@@ -747,59 +747,59 @@
 
     /* see if we already have it cached */
     if (rend_cache_lookup(socks->address, &descp, &desc_len) == 1) {
-      if(0){ //if a circuit already exists to this place, use it
-
-      } else {
-        /* go into some other state maybe? */
-        /* then launch a rendezvous circuit */
-        circuit_launch_new(CIRCUIT_PURPOSE_C_ESTABLISH_REND, NULL);
-      }
+      conn->purpose = AP_PURPOSE_RENDPOINT_WAIT;
+      return connection_ap_handshake_attach_circuit(conn);
+      //circuit_launch_new(CIRCUIT_PURPOSE_C_ESTABLISH_REND, NULL);
     } else {
+      conn->purpose = AP_PURPOSE_RENDDESC_WAIT;
       /* initiate a dir hidserv desc lookup */
-      /* go into a state where you'll be notified of the answer */
+      directory_initiate_command(router_pick_directory_server(),
+                                 DIR_PURPOSE_FETCH_RENDDESC,
+                                 socks->address, strlen(socks->address));
+      return 0;
     }
   }
   return 0;
 }
 
-static int connection_ap_handshake_attach_circuit(connection_t *conn,
-                                                  int must_be_clean) {
-  /* try attaching. launch new circuit if needed.
-   * return -1 if conn needs to die, else 0. */
-  switch(connection_ap_handshake_attach_circuit_helper(conn, must_be_clean)) {
-    case -1: /* it will never work */
-      return -1;
-    case 0: /* no useful circuits available */
-      if(!circuit_get_newest(conn, 0, must_be_clean)) {
-        /* is one already on the way? */
-        circuit_launch_new(CIRCUIT_PURPOSE_C_GENERAL, NULL);
-      }
-      return 0;
-    default: /* case 1, it succeeded, great */
-      return 0;
-  }
-}
-
 /* Try to find a safe live circuit for CONN_TYPE_AP connection conn. If
  * we don't find one: if conn cannot be handled by any known nodes,
- * warn and return -1; else tell conn to stop reading and return 0.
- * Otherwise, associate conn with a safe live circuit, start
- * sending a BEGIN cell down the circuit, and return 1.
+ * warn and return -1 (conn needs to die);
+ * else launch new circuit and return 0.
+ * Otherwise, associate conn with a safe live circuit, do the
+ * right next step, and return 1.
  */
-static int connection_ap_handshake_attach_circuit_helper(connection_t *conn,
-                                                         int must_be_clean) {
+static int connection_ap_handshake_attach_circuit(connection_t *conn) {
   circuit_t *circ;
   uint32_t addr;
+  int must_be_clean;
+  uint8_t desired_circuit_purpose;
 
   assert(conn);
   assert(conn->type == CONN_TYPE_AP);
   assert(conn->state == AP_CONN_STATE_CIRCUIT_WAIT);
   assert(conn->socks_request);
 
+  switch(conn->purpose) {
+    case AP_PURPOSE_GENERAL:
+    case AP_PURPOSE_RENDDESC_WAIT:
+      desired_circuit_purpose = CIRCUIT_PURPOSE_C_GENERAL;
+      break;
+    case AP_PURPOSE_RENDPOINT_WAIT:
+      desired_circuit_purpose = CIRCUIT_PURPOSE_C_ESTABLISH_REND;
+      break;
+    case AP_PURPOSE_INTROPOINT_WAIT:
+      desired_circuit_purpose = CIRCUIT_PURPOSE_C_INTRODUCING;
+      break;
+    default:
+      assert(0); /* never reached */
+  }
+
   /* find the circuit that we should use, if there is one. */
-  circ = circuit_get_newest(conn, 1, must_be_clean);
+  circ = circuit_get_newest(conn, 1, desired_circuit_purpose);
 
   if(!circ) {
+//XXX
     log_fn(LOG_INFO,"No safe circuit ready for edge connection; delaying.");
     addr = client_dns_lookup_entry(conn->socks_request->address);
     if(router_exit_policy_all_routers_reject(addr, conn->socks_request->port)) {
@@ -807,29 +807,37 @@
              conn->socks_request->address, conn->socks_request->port);
       return -1;
     }
-    connection_stop_reading(conn); /* don't read until the connected cell arrives */
+    if(!circuit_get_newest(conn, 0, desired_circuit_purpose)) {
+      /* is one already on the way? */
+      circuit_launch_new(desired_circuit_purpose, NULL);
+    }
     return 0;
   }
 
-  connection_start_reading(conn);
-
   /* here, print the circ's path. so people can figure out which circs are sucking. */
   circuit_log_path(LOG_INFO,circ);
 
   if(!circ->timestamp_dirty)
     circ->timestamp_dirty = time(NULL);
 
-  /* add it into the linked list of streams on this circuit */
-  log_fn(LOG_DEBUG,"attaching new conn to circ. n_circ_id %d.", circ->n_circ_id);
-  conn->next_stream = circ->p_streams;
-  /* assert_connection_ok(conn, time(NULL)); */
-  circ->p_streams = conn;
+  switch(conn->purpose) {
+    case AP_PURPOSE_GENERAL:
+    case AP_PURPOSE_RENDDESC_WAIT:
+      /* add it into the linked list of streams on this circuit */
+      log_fn(LOG_DEBUG,"attaching new conn to circ. n_circ_id %d.", circ->n_circ_id);
+      conn->next_stream = circ->p_streams;
+      /* assert_connection_ok(conn, time(NULL)); */
+      circ->p_streams = conn;
 
-  assert(circ->cpath && circ->cpath->prev);
-  assert(circ->cpath->prev->state == CPATH_STATE_OPEN);
-  conn->cpath_layer = circ->cpath->prev;
+      assert(circ->cpath && circ->cpath->prev);
+      assert(circ->cpath->prev->state == CPATH_STATE_OPEN);
+      conn->cpath_layer = circ->cpath->prev;
 
-  connection_ap_handshake_send_begin(conn, circ);
+      connection_ap_handshake_send_begin(conn, circ);
+      break;
+    case AP_PURPOSE_RENDPOINT_WAIT:
+    case AP_PURPOSE_INTROPOINT_WAIT:
+  }
 
   return 1;
 }
@@ -894,11 +902,6 @@
   ap_conn->package_window = STREAMWINDOW_START;
   ap_conn->deliver_window = STREAMWINDOW_START;
   ap_conn->state = AP_CONN_STATE_CONNECT_WAIT;
-  /* XXX Right now, we rely on the socks client not to send us any data
-   * XXX until we've sent back a socks reply.  (If it does, we could wind
-   * XXX up packaging that data and sending it to the exit, then later having
-   * XXX the exit refuse us.)
-   */
   log_fn(LOG_INFO,"Address/port sent, ap socket %d, n_circ_id %d",ap_conn->s,circ->n_circ_id);
   return;
 }
@@ -947,7 +950,7 @@
   connection_start_reading(conn);
 
   /* attaching to a dirty circuit is fine */
-  if (connection_ap_handshake_attach_circuit(conn, 0) < 0) {
+  if (connection_ap_handshake_attach_circuit(conn) < 0) {
     connection_mark_for_close(conn, 0);
     close(fd[1]);
     return -1;

Index: directory.c
===================================================================
RCS file: /home/or/cvsroot/src/or/directory.c,v
retrieving revision 1.79
retrieving revision 1.80
diff -u -d -r1.79 -r1.80
--- directory.c	1 Apr 2004 21:32:01 -0000	1.79
+++ directory.c	2 Apr 2004 22:23:15 -0000	1.80
@@ -275,11 +275,11 @@
             /* alice's ap_stream is just going to have to time out. */
           } else {
             /* success. notify pending connections about this. */
-            //alice_notify_desc_fetched(conn->rend_query);
+            rend_client_desc_fetched(conn->rend_query);
           }
           break;
         case 404:
-          //alice_notify_desc_not_fetched(conn->rend_query);
+          rend_client_desc_not_fetched(conn->rend_query);
           break;
         case 400:
           log_fn(LOG_WARN,"http status 400 (bad request). Dirserver didn't like our rendezvous query?");

Index: main.c
===================================================================
RCS file: /home/or/cvsroot/src/or/main.c,v
retrieving revision 1.221
retrieving revision 1.222
diff -u -d -r1.221 -r1.222
--- main.c	1 Apr 2004 21:32:01 -0000	1.221
+++ main.c	2 Apr 2004 22:23:15 -0000	1.222
@@ -384,7 +384,7 @@
 /* Build a new test circuit every 5 minutes */
 #define TESTING_CIRCUIT_INTERVAL 300
 
-    circ = circuit_get_newest(NULL, 1, 0);
+    circ = circuit_get_newest(NULL, 1, CIRCUIT_PURPOSE_C_GENERAL);
     if(time_to_new_circuit < now) {
       client_dns_clean();
       circuit_expire_unused_circuits();

Index: onion.c
===================================================================
RCS file: /home/or/cvsroot/src/or/onion.c,v
retrieving revision 1.137
retrieving revision 1.138
diff -u -d -r1.137 -r1.138
--- onion.c	1 Apr 2004 22:21:01 -0000	1.137
+++ onion.c	2 Apr 2004 22:23:15 -0000	1.138
@@ -8,6 +8,7 @@
  * they're here to prevent precedence issues with the .h files
  */
 void router_add_running_routers_to_smartlist(smartlist_t *sl);
+void add_nickname_list_to_smartlist(smartlist_t *sl, char *list);
 
 extern or_options_t options; /* command-line and config-file options */
 
@@ -166,32 +167,6 @@
 
 extern int has_fetched_directory;
 
-static void add_nickname_list_to_smartlist(smartlist_t *sl, char *list) {
-  char *start,*end;
-  char nick[MAX_NICKNAME_LEN];
-  routerinfo_t *router;
-
-  while(isspace((int)*list) || *list==',') list++;
-
-  start = list;
-  while(*start) {
-    end=start; while(*end && !isspace((int)*end) && *end != ',') end++;
-    memcpy(nick,start,end-start);
-    nick[end-start] = 0; /* null terminate it */
-    router = router_get_by_nickname(nick);
-    if (router) {
-      if (router->is_running)
-        smartlist_add(sl,router);
-      else
-        log_fn(LOG_INFO,"Nickname list includes '%s' which is known but down.",nick);
-    } else
-      log_fn(has_fetched_directory ? LOG_WARN : LOG_INFO,
-             "Nickname list includes '%s' which isn't a known router.",nick);
-    while(isspace((int)*end) || *end==',') end++;
-    start = end;
-  }
-}
-
 static int new_route_len(double cw, routerinfo_t **rarray, int rarray_len) {
   int num_acceptable_routers;
   int routelen;
@@ -227,33 +202,6 @@
   return routelen;
 }
 
-static routerinfo_t *choose_good_exit_server_rend(routerlist_t *dir)
-{
-  smartlist_t *sl, *excludednodes;
-  routerinfo_t *choice;
-
-  excludednodes = smartlist_create();
-  add_nickname_list_to_smartlist(excludednodes,options.RendExcludeNodes);
-
-  /* try the nodes in RendNodes first */
-  sl = smartlist_create();
-  add_nickname_list_to_smartlist(sl,options.RendNodes);
-  smartlist_subtract(sl,excludednodes);
-  choice = smartlist_choose(sl);
-  smartlist_free(sl);
-  if(!choice) {
-    sl = smartlist_create();
-    router_add_running_routers_to_smartlist(sl);
-    smartlist_subtract(sl,excludednodes);
-    choice = smartlist_choose(sl);
-    smartlist_free(sl);
-  }
-  smartlist_free(excludednodes);
-  if(!choice)
-    log_fn(LOG_WARN,"No available nodes when trying to choose rendezvous point. Failing.");
-  return choice;
-}
-
 static routerinfo_t *choose_good_exit_server_general(routerlist_t *dir)
 {
   int *n_supported;
@@ -386,7 +334,7 @@
   if(purpose == CIRCUIT_PURPOSE_C_GENERAL)
     return choose_good_exit_server_general(dir);
   else
-    return choose_good_exit_server_rend(dir);
+    return router_choose_random_node(dir, options.RendNodes, options.RendExcludeNodes);
 }
 
 cpath_build_state_t *onion_new_cpath_build_state(uint8_t purpose,

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.279
retrieving revision 1.280
diff -u -d -r1.279 -r1.280
--- or.h	2 Apr 2004 21:56:52 -0000	1.279
+++ or.h	2 Apr 2004 22:23:15 -0000	1.280
@@ -170,10 +170,13 @@
 #define AP_CONN_STATE_OPEN 8
 #define _AP_CONN_STATE_MAX 8
 
+/* only used if state==CIRCUIT_WAIT */
 #define _AP_PURPOSE_MIN 1
 #define AP_PURPOSE_GENERAL 1
-#define AP_PURPOSE_
-#define _AP_PURPOSE_MAX 1
+#define AP_PURPOSE_RENDDESC_WAIT 2
+#define AP_PURPOSE_RENDPOINT_WAIT 3
+#define AP_PURPOSE_INTROPOINT_WAIT 4
+#define _AP_PURPOSE_MAX 3
 
 #define _DIR_CONN_STATE_MIN 1
 #define DIR_CONN_STATE_CONNECTING 1
@@ -691,7 +694,7 @@
 circuit_t *circuit_get_by_circ_id_conn(uint16_t circ_id, connection_t *conn);
 circuit_t *circuit_get_by_conn(connection_t *conn);
 circuit_t *circuit_get_newest(connection_t *conn,
-                              int must_be_open, int must_be_clean);
+                              int must_be_open, uint8_t conn_purpose);
 circuit_t *circuit_get_next_by_service_and_purpose(circuit_t *circuit,
                                              const char *servid, int purpose);
 circuit_t *circuit_get_rendezvous(const char *cookie);
@@ -972,6 +975,7 @@
 /********************************* routerlist.c ***************************/
 
 routerinfo_t *router_pick_directory_server(void);
+routerinfo_t *router_choose_random_node(routerlist_t *dir, char *preferred, char *excluded);
 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);
@@ -1016,10 +1020,15 @@
 void rep_hist_note_disconnect(const char* nickname, time_t when);
 void rep_hist_note_connection_died(const char* nickname, time_t when);
 void rep_hist_note_extend_succeeded(const char *from_name,
-				    const char *to_name);
+                                    const char *to_name);
 void rep_hist_note_extend_failed(const char *from_name, const char *to_name);
 void rep_hist_dump_stats(time_t now, int severity);
 
+/********************************* rendclient.c ***************************/
+
+void rend_client_desc_fetched(char *query);
+void rend_client_desc_not_fetched(char *query);
+
 /********************************* rendcommon.c ***************************/
 
 typedef struct rend_service_descriptor_t {
@@ -1036,6 +1045,7 @@
                                    int *len_out);
 rend_service_descriptor_t *rend_parse_service_descriptor(const char *str, int len);
 int rend_get_service_id(crypto_pk_env_t *pk, char *out);
+int rend_cmp_service_ids(char *one, char *two);
 
 void rend_cache_init(void);
 void rend_cache_clean(void);

Index: rendcommon.c
===================================================================
RCS file: /home/or/cvsroot/src/or/rendcommon.c,v
retrieving revision 1.6
retrieving revision 1.7
diff -u -d -r1.6 -r1.7
--- rendcommon.c	1 Apr 2004 22:12:00 -0000	1.6
+++ rendcommon.c	2 Apr 2004 22:23:15 -0000	1.7
@@ -121,6 +121,10 @@
   return 0;
 }
 
+int rend_cmp_service_ids(char *one, char *two) {
+  return strcasecmp(one,two);
+}
+
 /* ==== Rendezvous service descriptor cache. */
 #define REND_CACHE_MAX_AGE 24*60*60
 #define REND_CACHE_MAX_SKEW 60*60

Index: rendservice.c
===================================================================
RCS file: /home/or/cvsroot/src/or/rendservice.c,v
retrieving revision 1.9
retrieving revision 1.10
diff -u -d -r1.9 -r1.10
--- rendservice.c	2 Apr 2004 22:06:46 -0000	1.9
+++ rendservice.c	2 Apr 2004 22:23:15 -0000	1.10
@@ -20,7 +20,7 @@
  */
 typedef struct rend_service_t {
   /* Fields specified in config file */
-  char *directory;
+  char *directory; /* where in the filesystem it stores it */
   smartlist_t *ports;
   char *intro_nodes;
   char *intro_exclude_nodes;

Index: routerlist.c
===================================================================
RCS file: /home/or/cvsroot/src/or/routerlist.c,v
retrieving revision 1.45
retrieving revision 1.46
diff -u -d -r1.45 -r1.46
--- routerlist.c	30 Mar 2004 22:59:00 -0000	1.45
+++ routerlist.c	2 Apr 2004 22:23:15 -0000	1.46
@@ -191,6 +191,32 @@
   return dirserver;
 }
 
+void add_nickname_list_to_smartlist(smartlist_t *sl, char *list) {
+  char *start,*end;
+  char nick[MAX_NICKNAME_LEN];
+  routerinfo_t *router;
+
+  while(isspace((int)*list) || *list==',') list++;
+
+  start = list;
+  while(*start) {
+    end=start; while(*end && !isspace((int)*end) && *end != ',') end++;
+    memcpy(nick,start,end-start);
+    nick[end-start] = 0; /* null terminate it */
+    router = router_get_by_nickname(nick);
+    if (router) {
+      if (router->is_running)
+        smartlist_add(sl,router);
+      else
+        log_fn(LOG_INFO,"Nickname list includes '%s' which is known but down.",nick);
+    } else
+      log_fn(has_fetched_directory ? LOG_WARN : LOG_INFO,
+             "Nickname list includes '%s' which isn't a known router.",nick);
+    while(isspace((int)*end) || *end==',') end++;
+    start = end;
+  }
+}
+
 void router_add_running_routers_to_smartlist(smartlist_t *sl) {
   routerinfo_t *router;
   int i;
@@ -207,6 +233,33 @@
   }
 }
 
+routerinfo_t *router_choose_random_node(routerlist_t *dir, char *preferred, char *excluded)
+{
+  smartlist_t *sl, *excludednodes;
+  routerinfo_t *choice;
+
+  excludednodes = smartlist_create();
+  add_nickname_list_to_smartlist(excludednodes,excluded);
+
+  /* try the nodes in RendNodes first */
+  sl = smartlist_create();
+  add_nickname_list_to_smartlist(sl,preferred);
+  smartlist_subtract(sl,excludednodes);
+  choice = smartlist_choose(sl);
+  smartlist_free(sl);
+  if(!choice) {
+    sl = smartlist_create();
+    router_add_running_routers_to_smartlist(sl);
+    smartlist_subtract(sl,excludednodes);
+    choice = smartlist_choose(sl);
+    smartlist_free(sl);
+  }
+  smartlist_free(excludednodes);
+  if(!choice)
+    log_fn(LOG_WARN,"No available nodes when trying to choose node. Failing.");
+  return choice;
+}
+
 routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port) {
   int i;
   routerinfo_t *router;



More information about the tor-commits mailing list