diff --git a/src/or/directory.c b/src/or/directory.c index c89b2125ce..43d9d58e97 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -143,9 +143,12 @@ directory_post_to_dirservers(uint8_t purpose, const char *payload, * connection purpose 'purpose' requesting 'resource'. The purpose * should be one of 'DIR_PURPOSE_FETCH_DIR', * 'DIR_PURPOSE_FETCH_RENDDESC', 'DIR_PURPOSE_FETCH_RUNNING_LIST.' + * If retry_if_no_servers, then if all the possible servers seem + * down, mark them up and try again. */ void -directory_get_from_dirserver(uint8_t purpose, const char *resource) +directory_get_from_dirserver(uint8_t purpose, const char *resource, + int retry_if_no_servers) { routerinfo_t *r = NULL; trusted_dir_server_t *ds = NULL; @@ -155,30 +158,34 @@ directory_get_from_dirserver(uint8_t purpose, const char *resource) purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) { if (advertised_server_mode()) { /* only ask authdirservers, and don't ask myself */ - ds = router_pick_trusteddirserver(1, fascistfirewall); + ds = router_pick_trusteddirserver(1, fascistfirewall, + retry_if_no_servers); } else { /* anybody with a non-zero dirport will do */ r = router_pick_directory_server(1, fascistfirewall, - purpose==DIR_PURPOSE_FETCH_RUNNING_LIST); + purpose==DIR_PURPOSE_FETCH_RUNNING_LIST, + retry_if_no_servers); if (!r) { log_fn(LOG_INFO, "No router found for %s; falling back to dirserver list", purpose == DIR_PURPOSE_FETCH_RUNNING_LIST ? "status list" : "directory"); - ds = router_pick_trusteddirserver(1, fascistfirewall); + ds = router_pick_trusteddirserver(1, fascistfirewall, + retry_if_no_servers); } } } else { // (purpose == DIR_PURPOSE_FETCH_RENDDESC) /* only ask authdirservers, any of them will do */ /* Never use fascistfirewall; we're going via Tor. */ - ds = router_pick_trusteddirserver(0, 0); + ds = router_pick_trusteddirserver(0, 0, retry_if_no_servers); } if (r) directory_initiate_command_router(r, purpose, resource, NULL, 0); else if (ds) directory_initiate_command_trusted_dir(ds, purpose, resource, NULL, 0); - else + else { log_fn(LOG_WARN,"No running dirservers known. Not trying. (purpose %d)", purpose); + } } /** Launch a new connection to the directory server router to upload or @@ -222,16 +229,9 @@ connection_dir_connect_failed(connection_t *conn) router_mark_as_down(conn->identity_digest); /* don't try him again */ if (conn->purpose == DIR_PURPOSE_FETCH_DIR || conn->purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) { - /* XXX This should possibly take into account that - * !advertised_server_mode() allows us to use more directory - * servers, and fascistfirewall allows us to use less. - */ - if (!all_trusted_directory_servers_down()) { - log_fn(LOG_INFO,"Giving up on dirserver '%s'; trying another.", conn->address); - directory_get_from_dirserver(conn->purpose, NULL); - } else { - log_fn(LOG_INFO,"Giving up on dirserver '%s'; no more to try.", conn->address); - } + log_fn(LOG_INFO, "Giving up on directory server at '%s'; retrying"); + directory_get_from_dirserver(conn->purpose, NULL, + 0 /* don't retry_if_no_servers */); } } diff --git a/src/or/main.c b/src/or/main.c index 37568ff3a3..b65bc3a535 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -605,7 +605,7 @@ static void run_scheduled_events(time_t now) { router_retry_connections(); } - directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR, NULL); + directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR, NULL, 1); time_to_fetch_directory = now + options->DirFetchPeriod; if (time_to_fetch_running_routers < now + options->StatusFetchPeriod) { time_to_fetch_running_routers = now + options->StatusFetchPeriod; @@ -617,7 +617,7 @@ static void run_scheduled_events(time_t now) { if (time_to_fetch_running_routers < now) { if (!authdir_mode(options)) { - directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST, NULL); + directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST, NULL, 1); } time_to_fetch_running_routers = now + options->StatusFetchPeriod; } @@ -779,7 +779,7 @@ static int do_hup(void) { } } /* Fetch a new directory. Even authdirservers do this. */ - directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR, NULL); + directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR, NULL, 1); if (server_mode(options)) { /* Restart cpuworker and dnsworker processes, so they get up-to-date * configuration options. */ diff --git a/src/or/or.h b/src/or/or.h index 770d321d58..3d7c47fbeb 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1313,12 +1313,13 @@ int assign_to_cpuworker(connection_t *cpuworker, unsigned char question_type, int dir_policy_permits_address(uint32_t addr); void directory_post_to_dirservers(uint8_t purpose, const char *payload, size_t payload_len); -void directory_get_from_dirserver(uint8_t purpose, const char *resource); +void directory_get_from_dirserver(uint8_t purpose, const char *resource, + int retry_if_no_servers); int connection_dir_reached_eof(connection_t *conn); int connection_dir_process_inbuf(connection_t *conn); int connection_dir_finished_flushing(connection_t *conn); int connection_dir_finished_connecting(connection_t *conn); -int connection_dir_failed(connection_t *conn); +int connection_dir_connect_failed(connection_t *conn); void parse_dir_policy(void); /********************************* dirserv.c ***************************/ @@ -1571,8 +1572,13 @@ typedef struct trusted_dir_server_t { int router_reload_router_list(void); void router_get_trusted_dir_servers(smartlist_t **outp); -routerinfo_t *router_pick_directory_server(int requireothers, int fascistfirewall, int for_running_routers); -trusted_dir_server_t *router_pick_trusteddirserver(int requireothers, int fascistfirewall); +routerinfo_t *router_pick_directory_server(int requireothers, + int fascistfirewall, + int for_running_routers, + int retry_if_no_servers); +trusted_dir_server_t *router_pick_trusteddirserver(int requireothers, + int fascistfirewall, + int retry_if_no_servers); int all_trusted_directory_servers_down(void); struct smartlist_t; void routerlist_add_family(struct smartlist_t *sl, routerinfo_t *router); diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 96c25159e9..cf16eb7337 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -250,7 +250,7 @@ rend_client_refetch_renddesc(const char *query) log_fn(LOG_INFO,"Would fetch a new renddesc here (for %s), but one is already in progress.", query); } else { /* not one already; initiate a dir rend desc lookup */ - directory_get_from_dirserver(DIR_PURPOSE_FETCH_RENDDESC, query); + directory_get_from_dirserver(DIR_PURPOSE_FETCH_RENDDESC, query, 1); } } diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 6a68bb96e8..cef59634b0 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -95,7 +95,8 @@ void router_get_trusted_dir_servers(smartlist_t **outp) */ routerinfo_t *router_pick_directory_server(int requireothers, int fascistfirewall, - int for_runningrouters) { + int for_runningrouters, + int retry_if_no_servers) { routerinfo_t *choice; if (!routerlist) @@ -103,7 +104,7 @@ routerinfo_t *router_pick_directory_server(int requireothers, choice = router_pick_directory_server_impl(requireothers, fascistfirewall, for_runningrouters); - if (choice) + if (choice || !retry_if_no_servers) return choice; log_fn(LOG_INFO,"No reachable router entries for dirservers. Trying them all again."); @@ -128,11 +129,12 @@ routerinfo_t *router_pick_directory_server(int requireothers, } trusted_dir_server_t *router_pick_trusteddirserver(int requireothers, - int fascistfirewall) { + int fascistfirewall, + int retry_if_no_servers) { trusted_dir_server_t *choice; choice = router_pick_trusteddirserver_impl(requireothers, fascistfirewall); - if (choice) + if (choice || !retry_if_no_servers) return choice; log_fn(LOG_INFO,"No trusted dirservers are reachable. Trying them all again.");