diff options
Diffstat (limited to 'src/or/routerlist.c')
-rw-r--r-- | src/or/routerlist.c | 90 |
1 files changed, 53 insertions, 37 deletions
diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 282572d8f..2ecb1aaab 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -19,7 +19,9 @@ extern or_options_t options; /**< command-line and config-file options */ /* ********************************************************************** */ /* static function prototypes */ -static routerinfo_t *router_pick_directory_server_impl(void); +static routerinfo_t * +router_pick_directory_server_impl(int requireauth, int preferothers); +static void mark_all_authdirservers_up(void); static int router_resolve_routerlist(routerlist_t *dir); /****************************************************************************/ @@ -35,32 +37,46 @@ static routerlist_t *routerlist = NULL; extern int has_fetched_directory; /**< from main.c */ -/** Try to find a running dirserver. If there are no running dirservers - * in our routerlist, reload the routerlist and try again. */ -routerinfo_t *router_pick_directory_server(void) { +/** Try to find a running dirserver. If there are no running dirservers + * in our routerlist, set all the authoritative ones as running again, + * and pick one. If there are no dirservers at all in our routerlist, + * reload the routerlist and try one last time. */ +routerinfo_t *router_pick_directory_server(int requireauth, int requireothers) { routerinfo_t *choice; - choice = router_pick_directory_server_impl(); - if(!choice) { - log_fn(LOG_WARN,"No dirservers known. Reloading and trying again."); - has_fetched_directory=0; /* reset it */ - routerlist_clear_trusted_directories(); - if(options.RouterFile) { - if(router_load_routerlist_from_file(options.RouterFile, 1) < 0) - return NULL; - } else { - if(config_assign_default_dirservers() < 0) - return NULL; - } - /* give it another try */ - choice = router_pick_directory_server_impl(); + choice = router_pick_directory_server_impl(requireauth, requireothers); + if(choice) + return choice; + + log_fn(LOG_INFO,"No dirservers are reachable. Trying them all again."); + /* mark all authdirservers are up again */ + mark_all_authdirservers_up(); + /* try again */ + choice = router_pick_directory_server_impl(requireauth, requireothers); + if(choice) + return choice; + + log_fn(LOG_WARN,"No dirservers known. Reloading and trying again."); + has_fetched_directory=0; /* reset it */ + routerlist_clear_trusted_directories(); + if(options.RouterFile) { + if(router_load_routerlist_from_file(options.RouterFile, 1) < 0) + return NULL; + } else { + if(config_assign_default_dirservers() < 0) + return NULL; } + /* give it one last try */ + choice = router_pick_directory_server_impl(requireauth, requireothers); return choice; } -/** Pick a random running router that's a trusted dirserver from our - * routerlist. */ -static routerinfo_t *router_pick_directory_server_impl(void) { +/** Pick a random running router from our routerlist. If requireauth, + * it has to be a trusted server. If requireothers, it cannot be us. + */ +static routerinfo_t * +router_pick_directory_server_impl(int requireauth, int requireothers) +{ int i; routerinfo_t *router; smartlist_t *sl; @@ -72,36 +88,36 @@ static routerinfo_t *router_pick_directory_server_impl(void) { sl = smartlist_create(); for(i=0;i< smartlist_len(routerlist->routers); i++) { router = smartlist_get(routerlist->routers, i); - if(router->is_running && router->is_trusted_dir) { - tor_assert(router->dir_port > 0); - smartlist_add(sl, router); - } + if(!router->is_running || !router->dir_port) + continue; + if(requireauth && !router->is_trusted_dir) + continue; + if(requireothers && router_is_me(router)) + continue; + smartlist_add(sl, router); } router = smartlist_choose(sl); smartlist_free(sl); + return router; +} - if(router) - return router; - log_fn(LOG_INFO,"No dirservers are reachable. Trying them all again."); +/** Go through and mark the auth dirservers as up */ +static void mark_all_authdirservers_up(void) { + int i; + routerinfo_t *router; + + if(!routerlist) + return; - /* No running dir servers found? go through and mark them all as up, - * so we cycle through the list again. */ - sl = smartlist_create(); for(i=0; i < smartlist_len(routerlist->routers); i++) { router = smartlist_get(routerlist->routers, i); if(router->is_trusted_dir) { tor_assert(router->dir_port > 0); router->is_running = 1; router->status_set_at = time(NULL); - smartlist_add(sl, router); } } - router = smartlist_choose(sl); - smartlist_free(sl); - if(!router) - log_fn(LOG_WARN,"No dirservers in directory! Returning NULL."); - return router; } /** Return 0 if \exists an authoritative dirserver that's currently |