Put ourself in router list; act accordingly.

svn:r1521
This commit is contained in:
Nick Mathewson 2004-04-07 19:46:27 +00:00
parent 4a9587a486
commit 75c19716a8
8 changed files with 151 additions and 84 deletions

View File

@ -293,10 +293,39 @@ void *smartlist_del(smartlist_t *sl, int idx)
sl->list[idx] = sl->list[--sl->num_used];
return old;
}
void *smartlist_del_keeporder(smartlist_t *sl, int idx)
{
void *old;
assert(sl && idx>=0 && idx < sl->num_used);
old = sl->list[idx];
--sl->num_used;
if (idx < sl->num_used)
memmove(sl->list+idx, sl->list+idx+1, sizeof(void*)*(sl->num_used-idx));
return old;
}
int smartlist_len(smartlist_t *sl)
{
return sl->num_used;
}
void smartlist_insert(smartlist_t *sl, int idx, void *val)
{
assert(sl && idx >= 0 && idx <= sl->num_used);
if (idx == sl->num_used) {
smartlist_add(sl, val);
} else {
/* Ensure sufficient capacity */
if (sl->num_used >= sl->capacity) {
sl->capacity *= 2;
sl->list = tor_realloc(sl->list, sizeof(void*)*sl->capacity);
}
/* Move other elements away */
if (idx < sl->num_used)
memmove(sl->list + idx + 1, sl->list + idx,
sizeof(void*)*(sl->num_used-idx));
sl->num_used++;
sl->list[idx] = val;
}
}
/*
* Splay-tree implementation of string-to-void* map

View File

@ -113,6 +113,8 @@ void *smartlist_choose(smartlist_t *sl);
void *smartlist_get(smartlist_t *sl, int idx);
void *smartlist_set(smartlist_t *sl, int idx, void *val);
void *smartlist_del(smartlist_t *sl, int idx);
void *smartlist_del_keeporder(smartlist_t *sl, int idx);
void smartlist_insert(smartlist_t *sl, int idx, void *val);
int smartlist_len(smartlist_t *sl);
#define SMARTLIST_FOREACH(sl, type, var, cmd) \
do { \

View File

@ -96,7 +96,7 @@ connection_t *connection_or_connect(routerinfo_t *router) {
assert(router);
if(options.Nickname && !strcmp(router->nickname,options.Nickname)) {
if(router_is_me(router)) {
log_fn(LOG_WARN,"You asked me to connect to myself! Failing.");
return NULL;
}

View File

@ -12,7 +12,7 @@ void add_nickname_list_to_smartlist(smartlist_t *sl, char *list);
extern or_options_t options; /* command-line and config-file options */
static int count_acceptable_routers(routerinfo_t **rarray, int rarray_len);
static int count_acceptable_routers(smartlist_t *routers);
int decide_circ_id_type(char *local_nick, char *remote_nick) {
int result;
@ -160,11 +160,11 @@ int onionskin_answer(circuit_t *circ, unsigned char *payload, unsigned char *key
extern int has_fetched_directory;
static int new_route_len(double cw, routerinfo_t **rarray, int rarray_len) {
static int new_route_len(double cw, smartlist_t *routers) {
int num_acceptable_routers;
int routelen;
assert((cw >= 0) && (cw < 1) && rarray); /* valid parameters */
assert((cw >= 0) && (cw < 1) && routers); /* valid parameters */
#ifdef TOR_PERF
routelen = 2;
@ -177,9 +177,10 @@ static int new_route_len(double cw, routerinfo_t **rarray, int rarray_len) {
break;
}
#endif
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,
smartlist_len(routers));
num_acceptable_routers = count_acceptable_routers(rarray, rarray_len);
num_acceptable_routers = count_acceptable_routers(routers);
if(num_acceptable_routers < 2) {
log_fn(LOG_INFO,"Not enough acceptable routers (%d). Discarding this circuit.",
@ -227,18 +228,19 @@ static routerinfo_t *choose_good_exit_server_general(routerlist_t *dir)
* router (n_supported[i]). (We can't be sure about cases where we
* don't know the IP address of the pending connection.)
*/
n_supported = tor_malloc(sizeof(int)*dir->n_routers);
for (i = 0; i < dir->n_routers; ++i) { /* iterate over routers */
if(!dir->routers[i]->is_running) {
n_supported = tor_malloc(sizeof(int)*smartlist_len(dir->routers));
for (i = 0; i < smartlist_len(dir->routers); ++i) { /* iterate over routers */
router = smartlist_get(dir->routers, i);
if(!router->is_running) {
n_supported[i] = -1;
log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- directory says it's not running.",
dir->routers[i]->nickname, i);
router->nickname, i);
continue; /* skip routers that are known to be down */
}
if(router_exit_policy_rejects_all(dir->routers[i])) {
if(router_exit_policy_rejects_all(router)) {
n_supported[i] = -1;
log_fn(LOG_DEBUG,"Skipping node %s (index %d) -- it rejects all.",
dir->routers[i]->nickname, i);
router->nickname, i);
continue; /* skip routers that reject all */
}
n_supported[i] = 0;
@ -248,17 +250,17 @@ static routerinfo_t *choose_good_exit_server_general(routerlist_t *dir)
carray[j]->marked_for_close ||
circuit_stream_is_being_handled(carray[j]))
continue; /* Skip everything but APs in CIRCUIT_WAIT */
switch (connection_ap_can_use_exit(carray[j], dir->routers[i]))
switch (connection_ap_can_use_exit(carray[j], router))
{
case ADDR_POLICY_REJECTED:
log_fn(LOG_DEBUG,"%s (index %d) would reject this stream.",
dir->routers[i]->nickname, i);
router->nickname, i);
break; /* would be rejected; try next connection */
case ADDR_POLICY_ACCEPTED:
case ADDR_POLICY_UNKNOWN:
++n_supported[i];
log_fn(LOG_DEBUG,"%s is supported. n_supported[%d] now %d.",
dir->routers[i]->nickname, i, n_supported[i]);
router->nickname, i, n_supported[i]);
}
} /* End looping over connections. */
if (n_supported[i] > best_support) {
@ -266,7 +268,7 @@ static routerinfo_t *choose_good_exit_server_general(routerlist_t *dir)
* and goodness, and start counting how many routers are this good. */
best_support = n_supported[i]; n_best_support=1;
log_fn(LOG_DEBUG,"%s is new best supported option so far.",
dir->routers[i]->nickname);
router->nickname);
} else if (n_supported[i] == best_support) {
/* If this router is _as good_ as the best one, just increment the
* count of equally good routers.*/
@ -287,9 +289,9 @@ static routerinfo_t *choose_good_exit_server_general(routerlist_t *dir)
/* If any routers definitely support any pending connections, choose one
* at random. */
if (best_support > 0) {
for (i = 0; i < dir->n_routers; i++)
for (i = 0; i < smartlist_len(dir->routers); i++)
if (n_supported[i] == best_support)
smartlist_add(sl, dir->routers[i]);
smartlist_add(sl, smartlist_get(dir->routers, i));
smartlist_subtract(sl,excludedexits);
if (smartlist_overlap(sl,preferredexits))
@ -301,9 +303,9 @@ static routerinfo_t *choose_good_exit_server_general(routerlist_t *dir)
if (best_support == -1) {
log(LOG_WARN, "All routers are down or middleman -- choosing a doomed exit at random.");
}
for(i = 0; i < dir->n_routers; i++)
for(i = 0; i < smartlist_len(dir->routers); i++)
if(n_supported[i] != -1)
smartlist_add(sl, dir->routers[i]);
smartlist_add(sl, smartlist_get(dir->routers, i));
smartlist_subtract(sl,excludedexits);
if (smartlist_overlap(sl,preferredexits))
@ -339,7 +341,7 @@ cpath_build_state_t *onion_new_cpath_build_state(uint8_t purpose,
routerinfo_t *exit;
router_get_routerlist(&rl);
r = new_route_len(options.PathlenCoinWeight, rl->routers, rl->n_routers);
r = new_route_len(options.PathlenCoinWeight, rl->routers);
if (r < 0)
return NULL;
info = tor_malloc_zero(sizeof(cpath_build_state_t));
@ -359,26 +361,30 @@ cpath_build_state_t *onion_new_cpath_build_state(uint8_t purpose,
return info;
}
static int count_acceptable_routers(routerinfo_t **rarray, int rarray_len) {
int i, j;
static int count_acceptable_routers(smartlist_t *routers) {
int i, j, n;
int num=0;
connection_t *conn;
routerinfo_t *r, *r2;
for(i=0;i<rarray_len;i++) {
n = smartlist_len(routers);
for(i=0;i<n;i++) {
log_fn(LOG_DEBUG,"Contemplating whether router %d is a new option...",i);
if(rarray[i]->is_running == 0) {
r = smartlist_get(routers, i);
if(r->is_running == 0) {
log_fn(LOG_DEBUG,"Nope, the directory says %d is not running.",i);
goto next_i_loop;
}
if(options.ORPort) {
conn = connection_exact_get_by_addr_port(rarray[i]->addr, rarray[i]->or_port);
conn = connection_exact_get_by_addr_port(r->addr, r->or_port);
if(!conn || conn->type != CONN_TYPE_OR || conn->state != OR_CONN_STATE_OPEN) {
log_fn(LOG_DEBUG,"Nope, %d is not connected.",i);
goto next_i_loop;
}
}
for(j=0;j<i;j++) {
if(!crypto_pk_cmp_keys(rarray[i]->onion_pkey, rarray[j]->onion_pkey)) {
r2 = smartlist_get(routers, j);
if(!crypto_pk_cmp_keys(r->onion_pkey, r2->onion_pkey)) {
/* these guys are twins. so we've already counted him. */
log_fn(LOG_DEBUG,"Nope, %d is a twin of %d.",i,j);
goto next_i_loop;

View File

@ -469,8 +469,7 @@ typedef struct {
#define MAX_ROUTERS_IN_DIR 1024
typedef struct {
routerinfo_t **routers;
int n_routers;
smartlist_t *routers;
char *software_versions;
time_t published_on;
} routerlist_t;
@ -980,6 +979,7 @@ void router_post_to_dirservers(uint8_t purpose, const char *payload, int payload
int router_compare_to_my_exit_policy(connection_t *conn);
routerinfo_t *router_get_my_routerinfo(void);
const char *router_get_my_descriptor(void);
int router_is_me(routerinfo_t *router);
int router_rebuild_descriptor(void);
int router_dump_router_to_string(char *s, int maxlen, routerinfo_t *router,
crypto_pk_env_t *ident_key);

View File

@ -226,8 +226,10 @@ void router_retry_connections(void) {
routerlist_t *rl;
router_get_routerlist(&rl);
for (i=0;i<rl->n_routers;i++) {
router = rl->routers[i];
for (i=0;i < smartlist_len(rl->routers);i++) {
router = smartlist_get(rl->routers, i);
if(router_is_me(router))
continue;
if(!connection_exact_get_by_addr_port(router->addr,router->or_port)) {
/* not in the list */
log_fn(LOG_DEBUG,"connecting to OR %s:%u.",router->address,router->or_port);
@ -256,8 +258,8 @@ void router_post_to_dirservers(uint8_t purpose, const char *payload, int payload
if(!rl)
return;
for(i=0;i<rl->n_routers;i++) {
router = rl->routers[i];
for(i=0; i < smartlist_len(rl->routers); i++) {
router = smartlist_get(rl->routers, i);
if(router->dir_port > 0)
directory_initiate_command(router, purpose, payload, payload_len);
}
@ -310,16 +312,23 @@ static void router_add_exit_policy_from_config(routerinfo_t *router) {
/* Return false if my exit policy says to allow connection to conn.
* Else return true.
*/
int router_compare_to_my_exit_policy(connection_t *conn) {
int router_compare_to_my_exit_policy(connection_t *conn)
{
assert(desc_routerinfo);
assert(conn->addr); /* make sure it's resolved to something. this
way we can't get a 'maybe' below. */
return router_compare_addr_to_exit_policy(conn->addr, conn->port,
return router_compare_addr_to_exit_policy(conn->addr, conn->port,
desc_routerinfo->exit_policy);
}
int router_is_me(routerinfo_t *router)
{
assert(router);
return options.Nickname && !strcasecmp(router->nickname, options.Nickname);
}
routerinfo_t *router_get_my_routerinfo(void)
{
if (!options.ORPort)

View File

@ -98,7 +98,7 @@ static struct {
{ "ports", K_PORTS, ARGS, NO_OBJ, RTR_ONLY },
{ "bandwidth", K_BANDWIDTH, ARGS, NO_OBJ, RTR_ONLY },
{ "opt", K_OPT, CONCAT_ARGS, OBJ_OK, ANY },
{ NULL, -1 }
};
@ -165,8 +165,8 @@ static routerinfo_t *router_pick_directory_server_impl(void) {
return NULL;
sl = smartlist_create();
for(i=0;i<routerlist->n_routers;i++) {
router = routerlist->routers[i];
for(i=0;i< smartlist_len(routerlist->routers); i++) {
router = smartlist_get(routerlist->routers, i);
if(router->dir_port > 0 && router->is_running)
smartlist_add(sl, router);
}
@ -179,8 +179,8 @@ static routerinfo_t *router_pick_directory_server_impl(void) {
log_fn(LOG_INFO,"No dirservers are reachable. Trying them all again.");
/* no running dir servers found? go through and mark them all as up,
* and we'll cycle through the list again. */
for(i=0;i<routerlist->n_routers;i++) {
router = routerlist->routers[i];
for(i=0; i < smartlist_len(routerlist->routers); i++) {
router = smartlist_get(routerlist->routers, i);
if(router->dir_port > 0) {
router->is_running = 1;
dirserver = router;
@ -227,8 +227,8 @@ void router_add_running_routers_to_smartlist(smartlist_t *sl) {
if(!routerlist)
return;
for(i=0;i<routerlist->n_routers;i++) {
router = routerlist->routers[i];
for(i=0;i<smartlist_len(routerlist->routers);i++) {
router = smartlist_get(routerlist->routers, i);
if(router->is_running &&
(!options.ORPort ||
connection_twin_get_by_addr_port(router->addr, router->or_port) ))
@ -279,8 +279,8 @@ routerinfo_t *router_get_by_addr_port(uint32_t addr, uint16_t port) {
assert(routerlist);
for(i=0;i<routerlist->n_routers;i++) {
router = routerlist->routers[i];
for(i=0;i<smartlist_len(routerlist->routers);i++) {
router = smartlist_get(routerlist->routers, i);
if ((router->addr == addr) && (router->or_port == port))
return router;
}
@ -294,8 +294,8 @@ routerinfo_t *router_get_by_link_pk(crypto_pk_env_t *pk)
assert(routerlist);
for(i=0;i<routerlist->n_routers;i++) {
router = routerlist->routers[i];
for(i=0;i<smartlist_len(routerlist->routers);i++) {
router = smartlist_get(routerlist->routers, i);
if (0 == crypto_pk_cmp_keys(router->link_pkey, pk))
return router;
}
@ -309,14 +309,11 @@ routerinfo_t *router_get_by_nickname(char *nickname)
assert(routerlist);
for(i=0;i<routerlist->n_routers;i++) {
router = routerlist->routers[i];
for(i=0;i<smartlist_len(routerlist->routers);i++) {
router = smartlist_get(routerlist->routers, i);
if (0 == strcasecmp(router->nickname, nickname))
return router;
}
router = router_get_my_routerinfo();
if (router && 0 == strcasecmp(router->nickname, nickname))
return router;
return NULL;
}
@ -353,12 +350,12 @@ void routerinfo_free(routerinfo_t *router)
static void routerlist_free(routerlist_t *rl)
{
int i;
for (i = 0; i < rl->n_routers; ++i)
routerinfo_free(rl->routers[i]);
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
routerinfo_free(r));
smartlist_free(rl->routers);
tor_free(rl->routers);
tor_free(rl->software_versions);
free(rl);
tor_free(rl);
}
void router_mark_as_down(char *nickname) {
@ -494,30 +491,35 @@ router_resolve(routerinfo_t *router)
return 0;
}
/* Helper function: resolve every router in rl. */
/* Helper function: resolve every router in rl, and ensure that our own
* routerinfo is at the front.
*/
static int
router_resolve_routerlist(routerlist_t *rl)
{
int i, max, remove;
int i, remove;
routerinfo_t *r;
if (!rl)
rl = routerlist;
max = rl->n_routers;
for (i = 0; i < max; ++i) {
i = 0;
if ((r = router_get_my_routerinfo())) {
smartlist_insert(rl->routers, 0, r);
++i;
}
for ( ; i < smartlist_len(rl->routers); ++i) {
remove = 0;
if (router_resolve(rl->routers[i])) {
log_fn(LOG_WARN, "Couldn't resolve router %s; not using",
rl->routers[i]->address);
r = smartlist_get(rl->routers,i);
if (router_is_me(r)) {
remove = 1;
} else if (options.Nickname &&
!strcmp(rl->routers[i]->nickname, options.Nickname)) {
} else if (router_resolve(r)) {
log_fn(LOG_WARN, "Couldn't resolve router %s; not using", r->address);
remove = 1;
}
if (remove) {
routerinfo_free(rl->routers[i]);
rl->routers[i] = rl->routers[--max];
--rl->n_routers;
--i;
routerinfo_free(r);
smartlist_del_keeporder(rl->routers, i--);
}
}
@ -595,8 +597,8 @@ int router_exit_policy_all_routers_reject(uint32_t addr, uint16_t port) {
int i;
routerinfo_t *router;
for (i=0;i<routerlist->n_routers;i++) {
router = routerlist->routers[i];
for (i=0;i<smartlist_len(routerlist->routers);i++) {
router = smartlist_get(routerlist->routers, i);
if (router->is_running && router_compare_addr_to_exit_policy(
addr, port, router->exit_policy) != ADDR_POLICY_REJECTED)
return 0; /* this one could be ok. good enough. */
@ -801,15 +803,14 @@ router_get_list_from_string_impl(const char **s, routerlist_t **dest,
const char **good_nickname_lst)
{
routerinfo_t *router;
routerinfo_t **rarray;
smartlist_t *routers;
int rarray_len = 0;
int i;
const char *end;
assert(s && *s);
rarray = (routerinfo_t **)
tor_malloc((sizeof(routerinfo_t *))*MAX_ROUTERS_IN_DIR);
routers = smartlist_create();
while (1) {
*s = eat_whitespace(*s);
@ -842,15 +843,14 @@ router_get_list_from_string_impl(const char **s, routerlist_t **dest,
} else {
router->is_running = 1; /* start out assuming all dirservers are up */
}
rarray[rarray_len++] = router;
smartlist_add(routers, router);
log_fn(LOG_DEBUG,"just added router #%d.",rarray_len);
}
if (*dest)
routerlist_free(*dest);
*dest = (routerlist_t *)tor_malloc(sizeof(routerlist_t));
(*dest)->routers = rarray;
(*dest)->n_routers = rarray_len;
*dest = tor_malloc(sizeof(routerlist_t));
(*dest)->routers = routers;
(*dest)->software_versions = NULL;
return 0;
}
@ -860,7 +860,7 @@ router_get_list_from_string_impl(const char **s, routerlist_t **dest,
* *s so it points to just after the router it just read.
* mallocs a new router and returns it if all goes well, else returns
* NULL.
*
*
* DOCDOC
*/
routerinfo_t *router_get_entry_from_string(const char *s,
@ -1288,7 +1288,7 @@ get_next_token(const char **s, where_syntax where) {
i = 0;
done = (*next == '\n');
allocated = 32;
tok->args = (char**)tor_malloc(sizeof(char*)*32);
tok->args = tor_malloc(sizeof(char*)*32);
*s = eat_whitespace_no_nl(next);
while (**s != '\n' && !done) {
next = find_whitespace(*s);
@ -1296,7 +1296,7 @@ get_next_token(const char **s, where_syntax where) {
done = 1;
if (i == allocated) {
allocated *= 2;
tok->args = (char**)tor_realloc(tok->args,sizeof(char*)*allocated);
tok->args = tor_realloc(tok->args,sizeof(char*)*allocated);
}
tok->args[i++] = tor_strndup(*s,next-*s);
*s = eat_whitespace_no_nl(next+1);
@ -1308,7 +1308,7 @@ get_next_token(const char **s, where_syntax where) {
next = strchr(*s, '\n');
if (!next)
RET_ERR("Unexpected EOF");
tok->args = (char**) tor_malloc(sizeof(char*));
tok->args = tor_malloc(sizeof(char*));
tok->args[0] = tor_strndup(*s,next-*s);
tok->n_args = 1;
*s = eat_whitespace_no_nl(next+1);
@ -1330,8 +1330,8 @@ get_next_token(const char **s, where_syntax where) {
next = strchr(*s, '\n');
if (!next) {
RET_ERR("Unexpected EOF");
}
tok->args = (char**) tor_malloc(sizeof(char*));
}
tok->args = tor_malloc(sizeof(char*));
tok->args[0] = tor_strndup(*s,next-*s);
tok->n_args = 1;
*s = next+1;

View File

@ -456,6 +456,7 @@ void
test_util() {
struct timeval start, end;
struct tm a_time;
smartlist_t *sl;
start.tv_sec = 5;
start.tv_usec = 5000;
@ -495,6 +496,26 @@ test_util() {
a_time.tm_mon = 1; /* Try a leap year, in feb. */
a_time.tm_mday = 10;
test_eq((time_t) 1076393695UL, tor_timegm(&a_time));
/* Test smartlist */
sl = smartlist_create();
smartlist_add(sl, (void*)1);
smartlist_add(sl, (void*)2);
smartlist_add(sl, (void*)3);
smartlist_add(sl, (void*)4);
test_eq(2, (int)smartlist_del_keeporder(sl, 1));
smartlist_insert(sl, 1, (void*)22);
smartlist_insert(sl, 0, (void*)0);
smartlist_insert(sl, 5, (void*)555);
test_eq(0, (int)smartlist_get(sl,0));
test_eq(1, (int)smartlist_get(sl,1));
test_eq(22, (int)smartlist_get(sl,2));
test_eq(3, (int)smartlist_get(sl,3));
test_eq(4, (int)smartlist_get(sl,4));
test_eq(555, (int)smartlist_get(sl,5));
/* XXXX test older functions. */
smartlist_free(sl);
}
static void* _squareAndRemoveK4(const char *key, void*val, void *data)
@ -790,7 +811,7 @@ test_dir_format()
test_assert(!dirserv_dump_directory_to_string(buf,8192,pk3));
cp = buf;
test_assert(!router_get_routerlist_from_directory_impl(buf, &dir1, pk3));
test_eq(2, dir1->n_routers);
test_eq(2, smartlist_len(dir1->routers));
dirserv_free_fingerprint_list();
tor_free(pk1_str);