diff options
Diffstat (limited to 'src/or/onion.c')
-rw-r--r-- | src/or/onion.c | 104 |
1 files changed, 64 insertions, 40 deletions
diff --git a/src/or/onion.c b/src/or/onion.c index 12971d098..ed8198019 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -95,60 +95,84 @@ int chooselen(double cw) unsigned int *new_route(double cw, routerinfo_t **rarray, size_t rarray_len, size_t *rlen) { int routelen = 0; - int i = 0; + int i, j; + int num_acceptable_routers = 0; int retval = 0; unsigned int *route = NULL; unsigned int oldchoice, choice; assert((cw >= 0) && (cw < 1) && (rarray) && (rlen) ); /* valid parameters */ - routelen = chooselen(cw); - if (routelen == -1) - { - log(LOG_ERR,"Choosing route length failed."); - return NULL; + routelen = chooselen(cw); + if (routelen == -1) { + log(LOG_ERR,"Choosing route length failed."); + return NULL; + } + log(LOG_DEBUG,"new_route(): Chosen route length %d.",routelen); + + for(i=0;i<rarray_len;i++) { + log(LOG_DEBUG,"Contemplating whether router %d is any good...",i); + if(!connection_exact_get_by_addr_port(rarray[i]->addr, rarray[i]->or_port)) { + log(LOG_DEBUG,"Nope, %d is not connected.",i); + goto next_i_loop; + } + for(j=0;j<i;j++) { + if(!pkey_cmp(rarray[i]->pkey, rarray[j]->pkey)) { + /* these guys are twins. so we've already counted him. */ + log(LOG_DEBUG,"Nope, %d is a twin of %d.",i,j); + goto next_i_loop; + } } - log(LOG_DEBUG,"new_route(): Chosen route length %u.",routelen); + num_acceptable_routers++; + log(LOG_DEBUG,"I like %d. num_acceptable_routers now %d.",i, num_acceptable_routers); + next_i_loop: + } + + if(num_acceptable_routers < routelen) { + log(LOG_DEBUG,"new_route(): Cutting routelen from %d to %d.",routelen, num_acceptable_routers); + routelen = num_acceptable_routers; + } - /* FIXME need to figure out how many routers we can actually choose from. - * We can get into an infinite loop if there are too few. */ - - /* allocate memory for the new route */ - route = (unsigned int *)malloc(routelen * sizeof(unsigned int)); - if (!route) - { - log(LOG_ERR,"Memory allocation failed."); + if(routelen < 1) { + log(LOG_ERR,"new_route(): Didn't find any acceptable routers. Failing."); + return NULL; + } + + /* allocate memory for the new route */ + route = (unsigned int *)malloc(routelen * sizeof(unsigned int)); + if (!route) { + log(LOG_ERR,"Memory allocation failed."); + return NULL; + } + + oldchoice = rarray_len; + for(i=0;i<routelen;i++) { + log(LOG_DEBUG,"new_route(): Choosing hop %u.",i); + retval = crypto_pseudo_rand(sizeof(unsigned int),(unsigned char *)&choice); + if (retval) { + free((void *)route); return NULL; } - - oldchoice = rarray_len; - for(i=0;i<routelen;i++) - { - log(LOG_DEBUG,"new_route() : Choosing hop %u.",i); - retval = crypto_pseudo_rand(sizeof(unsigned int),(unsigned char *)&choice); - if (retval) - { - free((void *)route); - return NULL; - } + choice = choice % (rarray_len); + log(LOG_DEBUG,"new_route(): Contemplating router %u.",choice); + while(choice == oldchoice || + (oldchoice < rarray_len && !pkey_cmp(rarray[choice]->pkey, rarray[oldchoice]->pkey)) || + !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(LOG_DEBUG,"new_route(): Picked a router %d that won't work as next hop.",choice); + choice++; choice = choice % (rarray_len); - log(LOG_DEBUG,"new_route() : Chosen router %u.",choice); - if (choice == oldchoice || - (oldchoice < rarray_len && !pkey_cmp(rarray[choice]->pkey, rarray[oldchoice]->pkey)) || - !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. */ - i--; - continue; - } - oldchoice = choice; - route[i] = choice; } + log(LOG_DEBUG,"new_route(): Chosen router %u for hop %u.",choice,i); + oldchoice = choice; + route[i] = choice; + } - *rlen = routelen; - return route; + *rlen = routelen; + return route; } /* creates a new onion from route, stores it and its length into bufp and lenp respectively */ |