diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 1dc1498fc7..ad126e6fc1 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -397,7 +397,10 @@ dirserv_add_descriptor(const char **desc, const char **msg) } /* We don't already have a newer one; we'll update this one. */ log_fn(LOG_INFO,"Dirserv updating desc for server %s (nickname '%s')",hex_digest,ri->nickname); - ri->last_reachable = ri_old->last_reachable; /* this carries over */ + if (ri->addr == ri_old->addr && ri->or_port == ri_old->or_port) { + ri->last_reachable = ri_old->last_reachable; /* these carry over */ + ri->testing_since = ri_old->testing_since; + } *msg = verified?"Verified server updated":"Unverified server updated. (Have you sent us your key fingerprint?)"; routerinfo_free(ri_old); smartlist_del_keeporder(descriptor_list, found); @@ -581,13 +584,7 @@ list_server_status(smartlist_t *routers, char **router_status_out) if (router_is_me(ri) && !we_are_hibernating()) { is_live = 1; } else if (conn && conn->state == OR_CONN_STATE_OPEN) { - if (now < ri->last_reachable + REACHABLE_TIMEOUT) { - is_live = 1; - } else { - log_fn(stats_n_seconds_working>REACHABLE_TIMEOUT ? LOG_NOTICE : LOG_INFO, - "Router %s (%s:%d) is connected to us but not reachable by us.", - ri->nickname, ri->address, ri->or_port); - } + is_live = now < ri->last_reachable + REACHABLE_TIMEOUT; } } else { is_live = ri->is_running; @@ -603,6 +600,42 @@ list_server_status(smartlist_t *routers, char **router_status_out) return 0; } +/** Log complaints about each server that is connected to us and has + * been found unreachable for the past several testing periods. + */ +void +dirserv_log_unreachable_servers(time_t now) { + + SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri, + { + connection_t *conn; + conn = connection_get_by_identity_digest( + ri->identity_digest, CONN_TYPE_OR); + if (conn && conn->state == OR_CONN_STATE_OPEN && + now >= ri->last_reachable + 2*REACHABLE_TIMEOUT && + ri->testing_since && + now >= ri->testing_since + 2*REACHABLE_TIMEOUT) { + log_fn(LOG_NOTICE, + "Router %s (%s:%d) is connected to us but not reachable by us.", + ri->nickname, ri->address, ri->or_port); + } + }); +} + +/** Record the fact that we've started trying to determine reachability + * for the router with identity digest. + * (This function can go away when we merge descriptor-list and router-list.) + */ +void +dirserv_router_has_begun_reachability_testing(char *digest, time_t now) { + SMARTLIST_FOREACH(descriptor_list, routerinfo_t *, ri, + { + if (!memcmp(ri->identity_digest, digest, DIGEST_LEN)) + if (!ri->testing_since) + ri->testing_since = now; + }); +} + /** Remove any descriptors from the directory that are more than age * seconds old. */ diff --git a/src/or/main.c b/src/or/main.c index 3b22c27283..6791ef377d 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -694,6 +694,7 @@ run_scheduled_events(time_t now) if (authdir_mode(options)) { /* Dump any old descriptors. */ dirserv_remove_old_servers(ROUTER_MAX_AGE); + dirserv_log_unreachable_servers(now); if (!we_are_hibernating()) { /* try to determine reachability */ router_retry_connections(1); } diff --git a/src/or/or.h b/src/or/or.h index 4e35ba8655..35c883eda6 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -738,6 +738,7 @@ typedef struct { int is_running; /**< As far as we know, is this OR currently running? */ time_t status_set_at; /**< When did we last update is_running? */ time_t last_reachable; /**< When was the last time we could reach this OR? */ + time_t testing_since; /**< When did we start testing reachability for this OR? */ int is_verified; /**< Has a trusted dirserver validated this OR? */ smartlist_t *declared_family; /**< Nicknames of router which this router @@ -1624,6 +1625,8 @@ char *dirserver_getinfo_unregistered(const char *question); int dirserv_load_from_directory_string(const char *dir); void dirserv_free_descriptors(void); int list_server_status(smartlist_t *routers, char **router_status_out); +void dirserv_log_unreachable_servers(time_t now); +void dirserv_router_has_begun_reachability_testing(char *digest, time_t now); void dirserv_remove_old_servers(int age); int dirserv_dump_directory_to_string(char **dir_out, crypto_pk_env_t *private_key); diff --git a/src/or/router.c b/src/or/router.c index bbb43db67f..1244e9e3df 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -577,6 +577,7 @@ void router_retry_connections(int force) { int i; + time_t now = time(NULL); routerinfo_t *router; routerlist_t *rl; or_options_t *options = get_options(); @@ -597,6 +598,7 @@ router_retry_connections(int force) log_fn(LOG_INFO,"%sconnecting to %s at %s:%u.", clique_mode(options) ? "(forced) " : "", router->nickname, router->address, router->or_port); + dirserv_router_has_begun_reachability_testing(router->identity_digest, now); connection_or_connect(router->addr, router->or_port, router->identity_digest); } }