diff options
author | Nick Mathewson <nickm@torproject.org> | 2016-05-19 08:25:12 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2016-05-19 08:25:12 -0400 |
commit | d718c717a67051cb1da2a1f80c70401d0d10b374 (patch) | |
tree | 8a5fdc8466bc79e54d6b0f07d0e98bcdbf946119 /src/or/networkstatus.c | |
parent | 159ea7a88f31aee2f84cf964c0d0000a5bd98970 (diff) | |
parent | 9f217c83b0d91508af0d63f04216fa78cdbfbe1b (diff) | |
download | tor-d718c717a67051cb1da2a1f80c70401d0d10b374.tar.gz tor-d718c717a67051cb1da2a1f80c70401d0d10b374.zip |
Merge branch 'maint-0.2.8'
Diffstat (limited to 'src/or/networkstatus.c')
-rw-r--r-- | src/or/networkstatus.c | 189 |
1 files changed, 70 insertions, 119 deletions
diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index 1c6afe49b9..0fba0e3036 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -121,8 +121,7 @@ static int have_warned_about_new_version = 0; static void routerstatus_list_update_named_server_map(void); static void update_consensus_bootstrap_multiple_downloads( time_t now, - const or_options_t *options, - int we_are_bootstrapping); + const or_options_t *options); /** Forget that we've warned about anything networkstatus-related, so we will * give fresh warnings if the same behavior happens again. */ @@ -793,26 +792,6 @@ check_consensus_waiting_for_certs(int flavor, time_t now, return 0; } -/* Return the maximum download tries for a consensus, based on options and - * whether we_are_bootstrapping. */ -static int -consensus_max_download_tries(const or_options_t *options, - int we_are_bootstrapping) -{ - int use_fallbacks = networkstatus_consensus_can_use_extra_fallbacks(options); - - if (we_are_bootstrapping) { - if (use_fallbacks) { - return options->ClientBootstrapConsensusMaxDownloadTries; - } else { - return - options->ClientBootstrapConsensusAuthorityOnlyMaxDownloadTries; - } - } - - return options->TestingConsensusMaxDownloadTries; -} - /** If we want to download a fresh consensus, launch a new download as * appropriate. */ static void @@ -866,29 +845,14 @@ update_consensus_networkstatus_downloads(time_t now) && i == usable_consensus_flavor()) { /* Check if we're already downloading a usable consensus */ - int consens_conn_count = - connection_dir_count_by_purpose_and_resource( - DIR_PURPOSE_FETCH_CONSENSUS, - resource); - int connect_consens_conn_count = - connection_dir_count_by_purpose_resource_and_state( - DIR_PURPOSE_FETCH_CONSENSUS, - resource, - DIR_CONN_STATE_CONNECTING); - - /* If not all connections are "connecting", then some are - * downloading. We want to have at most one downloading at a time. */ - if (connect_consens_conn_count < consens_conn_count) { + if (networkstatus_consensus_is_already_downloading(resource)) continue; - } /* Make multiple connections for a bootstrap consensus download. */ - update_consensus_bootstrap_multiple_downloads(now, options, - we_are_bootstrapping); + update_consensus_bootstrap_multiple_downloads(now, options); } else { /* Check if we failed downloading a consensus too recently */ - int max_dl_tries = consensus_max_download_tries(options, - we_are_bootstrapping); + int max_dl_tries = options->TestingConsensusMaxDownloadTries; /* Let's make sure we remembered to update consensus_dl_status */ tor_assert(consensus_dl_status[i].schedule == DL_SCHED_CONSENSUS); @@ -923,12 +887,16 @@ static void update_consensus_bootstrap_attempt_downloads( time_t now, const or_options_t *options, - int we_are_bootstrapping, download_status_t *dls, download_want_authority_t want_authority) { - int max_dl_tries = consensus_max_download_tries(options, - we_are_bootstrapping); + int use_fallbacks = networkstatus_consensus_can_use_extra_fallbacks(options); + int max_dl_tries = options->ClientBootstrapConsensusMaxDownloadTries; + if (!use_fallbacks) { + max_dl_tries = + options->ClientBootstrapConsensusAuthorityOnlyMaxDownloadTries; + } + const char *resource = networkstatus_get_flavor_name( usable_consensus_flavor()); @@ -961,8 +929,7 @@ update_consensus_bootstrap_attempt_downloads( */ static void update_consensus_bootstrap_multiple_downloads(time_t now, - const or_options_t *options, - int we_are_bootstrapping) + const or_options_t *options) { const int usable_flavor = usable_consensus_flavor(); @@ -971,12 +938,6 @@ update_consensus_bootstrap_multiple_downloads(time_t now, return; } - /* If we've managed to validate a usable consensus, don't make additional - * connections. */ - if (!we_are_bootstrapping) { - return; - } - /* Launch concurrent consensus download attempt(s) based on the mirror and * authority schedules. Try the mirror first - this makes it slightly more * likely that we'll connect to the fallback first, and then end the @@ -995,8 +956,7 @@ update_consensus_bootstrap_multiple_downloads(time_t now, if (!check_consensus_waiting_for_certs(usable_flavor, now, dls_f)) { /* During bootstrap, DL_WANT_ANY_DIRSERVER means "use fallbacks". */ - update_consensus_bootstrap_attempt_downloads(now, options, - we_are_bootstrapping, dls_f, + update_consensus_bootstrap_attempt_downloads(now, options, dls_f, DL_WANT_ANY_DIRSERVER); } } @@ -1006,8 +966,7 @@ update_consensus_bootstrap_multiple_downloads(time_t now, &consensus_bootstrap_dl_status[CONSENSUS_BOOTSTRAP_SOURCE_AUTHORITY]; if (!check_consensus_waiting_for_certs(usable_flavor, now, dls_a)) { - update_consensus_bootstrap_attempt_downloads(now, options, - we_are_bootstrapping, dls_a, + update_consensus_bootstrap_attempt_downloads(now, options, dls_a, DL_WANT_AUTHORITY); } } @@ -1275,16 +1234,30 @@ networkstatus_get_reasonably_live_consensus(time_t now, int flavor) return NULL; } -/** Check if we're bootstrapping a consensus download. This means that we are - * only using the authorities and fallback directory mirrors to download the - * consensus flavour we'll use. */ -int -networkstatus_consensus_is_bootstrapping(time_t now) +/** Check if we need to download a consensus during tor's bootstrap phase. + * If we have no consensus, or our consensus is unusably old, return 1. + * As soon as we have received a consensus, return 0, even if we don't have + * enough certificates to validate it. */ +MOCK_IMPL(int, +networkstatus_consensus_is_bootstrapping,(time_t now)) { - /* If we don't have a consensus, we must still be bootstrapping */ - return !networkstatus_get_reasonably_live_consensus( - now, - usable_consensus_flavor()); + /* If we have a validated, reasonably live consensus, we're not + * bootstrapping a consensus at all. */ + if (networkstatus_get_reasonably_live_consensus( + now, + usable_consensus_flavor())) { + return 0; + } + + /* If we have a consensus, but we're waiting for certificates, + * we're not waiting for a consensus download while bootstrapping. */ + if (consensus_is_waiting_for_certs()) { + return 0; + } + + /* If we have no consensus, or our consensus is very old, we are + * bootstrapping, and we need to download a consensus. */ + return 1; } /** Check if we can use multiple directories for a consensus download. @@ -1301,8 +1274,8 @@ networkstatus_consensus_can_use_multiple_directories( /** Check if we can use fallback directory mirrors for a consensus download. * If we have fallbacks and don't want to fetch from the authorities, * we can use them. */ -int -networkstatus_consensus_can_use_extra_fallbacks(const or_options_t *options) +MOCK_IMPL(int, +networkstatus_consensus_can_use_extra_fallbacks,(const or_options_t *options)) { /* The list length comparisons are a quick way to check if we have any * non-authority fallback directories. If we ever have any authorities that @@ -1316,61 +1289,39 @@ networkstatus_consensus_can_use_extra_fallbacks(const or_options_t *options) > smartlist_len(router_get_trusted_dir_servers()))); } -/* Check if there is more than 1 consensus connection retrieving the usable - * consensus flavor. If so, return 1, if not, return 0. - * - * During normal operation, Tor only makes one consensus download - * connection. But clients can make multiple simultaneous consensus - * connections to improve bootstrap speed and reliability. - * - * If there is more than one connection, we must have connections left - * over from bootstrapping. However, some of the connections may have - * completed and been cleaned up, so it is not sufficient to check the - * return value of this function to see if a client could make multiple - * bootstrap connections. Use - * networkstatus_consensus_can_use_multiple_directories() - * and networkstatus_consensus_is_bootstrapping(). */ -int -networkstatus_consensus_has_excess_connections(void) -{ - const char *usable_resource = networkstatus_get_flavor_name( - usable_consensus_flavor()); - const int consens_conn_usable_count = - connection_dir_count_by_purpose_and_resource( - DIR_PURPOSE_FETCH_CONSENSUS, - usable_resource); - /* The maximum number of connections we want downloading a usable consensus - * Always 1, whether bootstrapping or not. */ - const int max_expected_consens_conn_usable_count = 1; - - if (consens_conn_usable_count > max_expected_consens_conn_usable_count) { - return 1; - } - - return 0; -} - -/* Is tor currently downloading a consensus of the usable flavor? */ +/* Is there a consensus fetch for flavor <b>resource</b> that's far + * enough along to be attached to a circuit? */ int -networkstatus_consensus_is_downloading_usable_flavor(void) -{ - const char *usable_resource = networkstatus_get_flavor_name( - usable_consensus_flavor()); - const int consens_conn_usable_count = - connection_dir_count_by_purpose_and_resource( - DIR_PURPOSE_FETCH_CONSENSUS, - usable_resource); - - const int connect_consens_conn_usable_count = - connection_dir_count_by_purpose_resource_and_state( - DIR_PURPOSE_FETCH_CONSENSUS, - usable_resource, - DIR_CONN_STATE_CONNECTING); - if (connect_consens_conn_usable_count < consens_conn_usable_count) { - return 1; - } +networkstatus_consensus_is_already_downloading(const char *resource) +{ + int answer = 0; + + /* First, get a list of all the dir conns that are fetching a consensus, + * fetching *this* consensus, and are in state "reading" (meaning they + * have already flushed their request onto the socks connection). */ + smartlist_t *fetching_conns = + connection_dir_list_by_purpose_resource_and_state( + DIR_PURPOSE_FETCH_CONSENSUS, resource, DIR_CONN_STATE_CLIENT_READING); + + /* Then, walk through each conn, to see if its linked socks connection + * is in an attached state. We have to check this separately, since with + * the optimistic data feature, fetches can send their request to the + * socks connection and go into state 'reading', even before they're + * attached to any circuit. */ + SMARTLIST_FOREACH_BEGIN(fetching_conns, dir_connection_t *, dirconn) { + /* Do any of these other dir conns have a linked socks conn that is + * attached to a circuit already? */ + connection_t *base = TO_CONN(dirconn); + if (base->linked_conn && + base->linked_conn->type == CONN_TYPE_AP && + !AP_CONN_STATE_IS_UNATTACHED(base->linked_conn->state)) { + answer = 1; + break; /* stop looping, because we know the answer will be yes */ + } + } SMARTLIST_FOREACH_END(dirconn); + smartlist_free(fetching_conns); - return 0; + return answer; } /** Given two router status entries for the same router identity, return 1 if |