[or-cvs] revamp circuit node selection to use smartlists:
Roger Dingledine
arma at seul.org
Sat Dec 13 07:01:48 UTC 2003
Update of /home/or/cvsroot/src/or
In directory moria.mit.edu:/home2/arma/work/onion/cvs/src/or
Modified Files:
onion.c or.h routerlist.c test.c
Log Message:
revamp circuit node selection to use smartlists:
* now we know for sure if an acceptable node is available; we
don't have to keep guessing and checking
* we try options.EntryNodes first for picking the first node
Index: onion.c
===================================================================
RCS file: /home/or/cvsroot/src/or/onion.c,v
retrieving revision 1.106
retrieving revision 1.107
diff -u -d -r1.106 -r1.107
--- onion.c 13 Dec 2003 01:43:21 -0000 1.106
+++ onion.c 13 Dec 2003 07:01:46 -0000 1.107
@@ -152,11 +152,12 @@
return 0;
}
-char **parse_nickname_list(char *list, int *num) {
+#if 0
+static char **parse_nickname_list(char *list, int *num) {
char **out;
char *start,*end;
int i;
-
+
while(isspace(*list)) list++;
i=0, start = list;
@@ -175,11 +176,34 @@
strncpy(out[i],start,end-start);
out[i][end-start] = 0; /* null terminate it */
i++;
- while(*end && isspace(*end)) end++;
+ while(isspace(*end)) end++;
start = end;
}
*num = i;
- return out;
+ return out;
+}
+#endif
+
+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(*list) || *list==',') list++;
+
+ start = list;
+ while(*start) {
+ end=start; while(*end && !isspace(*end) && *end != ',') end++;
+ memcpy(nick,start,end-start);
+ nick[end-start] = 0; /* null terminate it */
+ router = router_get_by_nickname(nick);
+ if(router && router->is_running)
+ smartlist_add(sl,router);
+ else
+ log_fn(LOG_WARN,"Nickname list includes '%s' which isn't a known router.",nick);
+ while(isspace(*end) || *end==',') end++;
+ start = end;
+ }
}
static int new_route_len(double cw, routerinfo_t **rarray, int rarray_len) {
@@ -412,6 +436,28 @@
return num;
}
+/* prototypes for smartlist operations from routerlist.h
+ * they're here to prevent precedence issues with the .h files
+ */
+void router_add_running_routers_to_smartlist(smartlist_t *sl);
+
+static void remove_twins_from_smartlist(smartlist_t *sl, routerinfo_t *twin) {
+ int i;
+ routerinfo_t *r;
+
+ if(twin == NULL)
+ return;
+
+/* XXX abstraction violation: this function reaches inside smartlist :( */
+ for(i=0; i < sl->num_used; i++) {
+ r = sl->list[i];
+ if (!crypto_pk_cmp_keys(r->onion_pkey, twin->onion_pkey)) {
+ sl->list[i] = sl->list[--sl->num_used]; /* swap with the end */
+ i--; /* so we process the new i'th element */
+ }
+ }
+}
+
int onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t *state, routerinfo_t **router_out)
{
int cur_len;
@@ -419,7 +465,7 @@
routerinfo_t *r;
routerinfo_t *choice;
int i;
- int n_failures;
+ smartlist_t *sl;
assert(head_ptr);
assert(router_out);
@@ -437,31 +483,10 @@
state->desired_path_len);
return 1;
}
- log_fn(LOG_DEBUG, "Path is %d long; we want %d", cur_len,
+ log_fn(LOG_DEBUG, "Path is %d long; we want %d", cur_len,
state->desired_path_len);
- n_failures = 0;
- goto start;
- again:
- log_fn(LOG_DEBUG, "Picked an already-selected router for hop %d; retrying.",
- cur_len);
- ++n_failures;
- if (n_failures == 50) {
- /* XXX hack to prevent infinite loop. Ideally we should build a list
- * of acceptable choices and then choose from it. */
- log_fn(LOG_INFO, "Unable to continue generating circuit path");
- return -1;
- }
- start:
- /* 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 = 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 */
+ 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);
if(!choice) {
@@ -469,34 +494,46 @@
state->chosen_exit);
return -1;
}
+ } else if(cur_len == 0) { /* picking first node */
+ /* try the nodes in EntryNodes first */
+ sl = smartlist_create(MAX_ROUTERS_IN_DIR);
+ add_nickname_list_to_smartlist(sl,options.EntryNodes);
+ remove_twins_from_smartlist(sl,router_get_by_nickname(state->chosen_exit));
+ choice = smartlist_choose(sl);
+ smartlist_free(sl);
+ if(!choice) {
+ sl = smartlist_create(MAX_ROUTERS_IN_DIR);
+ router_add_running_routers_to_smartlist(sl);
+ remove_twins_from_smartlist(sl,router_get_by_nickname(state->chosen_exit));
+ choice = smartlist_choose(sl);
+ smartlist_free(sl);
+ }
+ if(!choice) {
+ log_fn(LOG_WARN,"No acceptable routers while picking entry node. Failing.");
+ return -1;
+ }
} else {
log_fn(LOG_DEBUG, "Contemplating intermediate hop: random choice.");
- choice = router_pick_randomly_from_running();
+ sl = smartlist_create(MAX_ROUTERS_IN_DIR);
+ router_add_running_routers_to_smartlist(sl);
+ remove_twins_from_smartlist(sl,router_get_by_nickname(state->chosen_exit));
+ for (i = 0, cpath = *head_ptr; i < cur_len; ++i, cpath=cpath->next) {
+ r = router_get_by_addr_port(cpath->addr, cpath->port);
+ assert(r);
+ remove_twins_from_smartlist(sl,r);
+ }
+ choice = smartlist_choose(sl);
+ smartlist_free(sl);
+
if(!choice) {
- log_fn(LOG_WARN,"No routers are running while picking intermediate node. Failing.");
+ log_fn(LOG_WARN,"No acceptable routers 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);
- if (cur_len != state->desired_path_len-1 &&
- !strcasecmp(choice->nickname, state->chosen_exit)) {
- /* make sure we don't pick the exit for another node in the path */
- goto again;
- }
-
- for (i = 0, cpath = *head_ptr; i < cur_len; ++i, cpath=cpath->next) {
- r = router_get_by_addr_port(cpath->addr, cpath->port);
- assert(r);
- if (!crypto_pk_cmp_keys(r->onion_pkey, choice->onion_pkey))
- goto again; /* same key -- it or a twin is already chosen */
- if (options.ORPort &&
- !(connection_twin_get_by_addr_port(choice->addr, choice->or_port)))
- goto again; /* this node is not connected to us. */
- }
+ log_fn(LOG_DEBUG,"Chose router %s for hop %d (exit is %s)",
+ choice->nickname, cur_len, state->chosen_exit);
- /* Okay, so we haven't used 'choice' before. */
hop = (crypt_path_t *)tor_malloc_zero(sizeof(crypt_path_t));
/* link hop into the cpath, at the end. */
Index: or.h
===================================================================
RCS file: /home/or/cvsroot/src/or/or.h,v
retrieving revision 1.202
retrieving revision 1.203
diff -u -d -r1.202 -r1.203
--- or.h 13 Dec 2003 02:44:02 -0000 1.202
+++ or.h 13 Dec 2003 07:01:46 -0000 1.203
@@ -701,8 +701,6 @@
int onionskin_answer(circuit_t *circ, unsigned char *payload, unsigned char *keys);
-char **parse_nickname_list(char *start, int *num);
-
int onion_extend_cpath(crypt_path_t **head_ptr, cpath_build_state_t *state,
routerinfo_t **router_out);
@@ -743,7 +741,6 @@
/********************************* routerlist.c ***************************/
routerinfo_t *router_pick_directory_server(void);
-routerinfo_t *router_pick_randomly_from_running(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);
Index: routerlist.c
===================================================================
RCS file: /home/or/cvsroot/src/or/routerlist.c,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -d -r1.7 -r1.8
--- routerlist.c 13 Dec 2003 02:44:02 -0000 1.7
+++ routerlist.c 13 Dec 2003 07:01:46 -0000 1.8
@@ -129,23 +129,20 @@
return dirserver;
}
-routerinfo_t *router_pick_randomly_from_running(void) {
- int i;
+void router_add_running_routers_to_smartlist(smartlist_t *sl) {
routerinfo_t *router;
- smartlist_t *sl;
+ int i;
if(!routerlist)
- return NULL;
-
- sl = smartlist_create(MAX_ROUTERS_IN_DIR);
- for(i=0;i<routerlist->n_routers;i++)
- if(routerlist->routers[i]->is_running)
- smartlist_add(sl, routerlist->routers[i]);
+ return;
- router = smartlist_choose(sl);
- smartlist_free(sl);
- log_fn(LOG_DEBUG, "Chose server '%s'", router ? router->nickname : "<none>");
- return router;
+ for(i=0;i<routerlist->n_routers;i++) {
+ router = routerlist->routers[i];
+ if(router->is_running &&
+ (!options.ORPort ||
+ connection_twin_get_by_addr_port(router->addr, router->or_port) ))
+ smartlist_add(sl, router);
+ }
}
routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port) {
Index: test.c
===================================================================
RCS file: /home/or/cvsroot/src/or/test.c,v
retrieving revision 1.53
retrieving revision 1.54
diff -u -d -r1.53 -r1.54
--- test.c 13 Dec 2003 02:44:02 -0000 1.53
+++ test.c 13 Dec 2003 07:01:46 -0000 1.54
@@ -465,6 +465,7 @@
}
void test_onion() {
+#if 0
char **names;
int i,num;
@@ -477,6 +478,7 @@
for(i=0;i<num;i++)
tor_free(names[i]);
tor_free(names);
+#endif
}
void
More information about the tor-commits
mailing list