diff options
author | Nick Mathewson <nickm@torproject.org> | 2010-09-14 22:19:22 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2010-09-14 22:19:22 -0400 |
commit | e2b71d884139af902fc9b9222f5b55fe5a7a91ec (patch) | |
tree | f56bfffb62b21fa9dae69d1ebd4dd8bb509c4f8c | |
parent | a445daf0cf7e7828aefacae1a11df5e76efacafa (diff) | |
parent | d9e05505606046afa8b346acac5f1e379e6f6e6d (diff) | |
download | tor-e2b71d884139af902fc9b9222f5b55fe5a7a91ec.tar.gz tor-e2b71d884139af902fc9b9222f5b55fe5a7a91ec.zip |
Merge branch 'bug911'
-rw-r--r-- | changes/bug911_hibernate_precludes_Running | 6 | ||||
-rw-r--r-- | src/or/dirserv.c | 51 | ||||
-rw-r--r-- | src/or/dirserv.h | 2 | ||||
-rw-r--r-- | src/or/networkstatus.c | 9 | ||||
-rw-r--r-- | src/or/or.h | 3 | ||||
-rw-r--r-- | src/or/routerlist.c | 15 | ||||
-rw-r--r-- | src/or/routerlist.h | 1 |
7 files changed, 74 insertions, 13 deletions
diff --git a/changes/bug911_hibernate_precludes_Running b/changes/bug911_hibernate_precludes_Running new file mode 100644 index 0000000000..5e0168d545 --- /dev/null +++ b/changes/bug911_hibernate_precludes_Running @@ -0,0 +1,6 @@ + o Minor bugfixes: + - Never vote for a server as "Running" if we have a descriptor for it + claiming to be hibernating, and that descriptor was published more + recently than our last contact with the server. Bugfix on + 0.2.0.3-alpha; fixes bug 911. + diff --git a/src/or/dirserv.c b/src/or/dirserv.c index 86cd186111..8523335ec4 100644 --- a/src/or/dirserv.c +++ b/src/or/dirserv.c @@ -730,6 +730,10 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source) desc = tor_strndup(ri->cache_info.signed_descriptor_body, desclen); nickname = tor_strdup(ri->nickname); + /* Tell if we're about to need to launch a test if we add this. */ + ri->needs_retest_if_added = + dirserv_should_launch_reachability_test(ri, ri_old); + r = router_add_to_routerlist(ri, msg, 0, 0); if (!WRA_WAS_ADDED(r)) { /* unless the routerinfo was fine, just out-of-date */ @@ -744,7 +748,7 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source) changed = smartlist_create(); smartlist_add(changed, ri); - control_event_descriptors_changed(changed); + routerlist_descriptors_added(changed, 0); smartlist_free(changed); if (!*msg) { *msg = ri->is_valid ? "Descriptor for valid server accepted" : @@ -923,6 +927,11 @@ running_long_enough_to_decide_unreachable(void) * the directory. */ #define REACHABLE_TIMEOUT (45*60) +/** If we tested a router and found it reachable _at least this long_ after it + * declared itself hibernating, it is probably done hibernating and we just + * missed a descriptor from it. */ +#define HIBERNATION_PUBLICATION_SKEW (60*60) + /** Treat a router as alive if * - It's me, and I'm not hibernating. * or - We've found it reachable recently. */ @@ -935,11 +944,23 @@ dirserv_set_router_is_running(routerinfo_t *router, time_t now) */ int answer; - if (router_is_me(router) && !we_are_hibernating()) + if (router_is_me(router)) { + /* We always know if we are down ourselves. */ + answer = ! we_are_hibernating(); + } else if (router->is_hibernating && + (router->cache_info.published_on + + HIBERNATION_PUBLICATION_SKEW) > router->last_reachable) { + /* A hibernating router is down unless we (somehow) had contact with it + * since it declared itself to be hibernating. */ + answer = 0; + } else if (get_options()->AssumeReachable) { + /* If AssumeReachable, everybody is up unless they say they are down! */ answer = 1; - else - answer = get_options()->AssumeReachable || - now < router->last_reachable + REACHABLE_TIMEOUT; + } else { + /* Otherwise, a router counts as up if we found it reachable in the last + REACHABLE_TIMEOUT seconds. */ + answer = (now < router->last_reachable + REACHABLE_TIMEOUT); + } if (!answer && running_long_enough_to_decide_unreachable()) { /* not considered reachable. tell rephist. */ @@ -3098,6 +3119,26 @@ dirserv_orconn_tls_done(const char *address, * skip testing. */ } +/** Called when we, as an authority, receive a new router descriptor either as + * an upload or a download. Used to decide whether to relaunch reachability + * testing for the server. */ +int +dirserv_should_launch_reachability_test(routerinfo_t *ri, routerinfo_t *ri_old) +{ + if (!authdir_mode_handles_descs(get_options(), ri->purpose)) + return 0; + if (!ri_old) { + /* New router: Launch an immediate reachability test, so we will have an + * opinion soon in case we're generating a consensus soon */ + return 1; + } + if (ri_old->is_hibernating && !ri->is_hibernating) { + /* It just came out of hibernation; launch a reachability test */ + return 1; + } + return 0; +} + /** Helper function for dirserv_test_reachability(). Start a TLS * connection to <b>router</b>, and annotate it with when we started * the test. */ diff --git a/src/or/dirserv.h b/src/or/dirserv.h index 5ebcb8b2b0..94e4e811d6 100644 --- a/src/or/dirserv.h +++ b/src/or/dirserv.h @@ -99,6 +99,8 @@ void dirserv_orconn_tls_done(const char *address, uint16_t or_port, const char *digest_rcvd, int as_advertised); +int dirserv_should_launch_reachability_test(routerinfo_t *ri, + routerinfo_t *ri_old); void dirserv_single_reachability_test(time_t now, routerinfo_t *router); void dirserv_test_reachability(time_t now); int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg, diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 3ac7b805a0..9bb5546d97 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -1981,6 +1981,15 @@ routers_update_status_from_consensus_networkstatus(smartlist_t *routers, router->is_bad_directory = rs->is_bad_directory; router->is_bad_exit = rs->is_bad_exit; router->is_hs_dir = rs->is_hs_dir; + } else { + /* If we _are_ an authority, we should check whether this router + * is one that will cause us to need a reachability test. */ + routerinfo_t *old_router = + router_get_by_digest(router->cache_info.identity_digest); + if (old_router != router) { + router->needs_retest_if_added = + dirserv_should_launch_reachability_test(router, old_router); + } } if (router->is_running && ds) { download_status_reset(&ds->v2_ns_dl_status); diff --git a/src/or/or.h b/src/or/or.h index 48641c8115..3c109738d7 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -1456,6 +1456,9 @@ typedef struct { * directory according to the authorities. */ unsigned int policy_is_reject_star:1; /**< True iff the exit policy for this * router rejects everything. */ + /** True if, after we have added this router, we should re-launch + * tests for it. */ + unsigned int needs_retest_if_added:1; /** Tor can use this router for general positions in circuits. */ #define ROUTER_PURPOSE_GENERAL 0 diff --git a/src/or/routerlist.c b/src/or/routerlist.c index ca16456a8c..402e98599e 100644 --- a/src/or/routerlist.c +++ b/src/or/routerlist.c @@ -3300,11 +3300,6 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg, * the list. */ routerlist_insert(routerlist, router); if (!from_cache) { - if (authdir) { - /* launch an immediate reachability test, so we will have an opinion - * soon in case we're generating a consensus soon */ - dirserv_single_reachability_test(time(NULL), router); - } signed_desc_append_to_journal(&router->cache_info, &routerlist->desc_store); } @@ -3624,15 +3619,19 @@ routerlist_remove_old_routers(void) /** We just added a new set of descriptors. Take whatever extra steps * we need. */ -static void +void routerlist_descriptors_added(smartlist_t *sl, int from_cache) { tor_assert(sl); control_event_descriptors_changed(sl); - SMARTLIST_FOREACH(sl, routerinfo_t *, ri, + SMARTLIST_FOREACH_BEGIN(sl, routerinfo_t *, ri) { if (ri->purpose == ROUTER_PURPOSE_BRIDGE) learned_bridge_descriptor(ri, from_cache); - ); + if (ri->needs_retest_if_added) { + ri->needs_retest_if_added = 0; + dirserv_single_reachability_test(approx_time(), ri); + } + } SMARTLIST_FOREACH_END(ri); } /** diff --git a/src/or/routerlist.h b/src/or/routerlist.h index e3e9ddd778..b53997ae8f 100644 --- a/src/or/routerlist.h +++ b/src/or/routerlist.h @@ -116,6 +116,7 @@ was_router_added_t router_add_to_routerlist(routerinfo_t *router, was_router_added_t router_add_extrainfo_to_routerlist( extrainfo_t *ei, const char **msg, int from_cache, int from_fetch); +void routerlist_descriptors_added(smartlist_t *sl, int from_cache); void routerlist_remove_old_routers(void); int router_load_single_router(const char *s, uint8_t purpose, int cache, const char **msg); |