aboutsummaryrefslogtreecommitdiff
path: root/src/or/networkstatus.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2016-05-19 08:25:12 -0400
committerNick Mathewson <nickm@torproject.org>2016-05-19 08:25:12 -0400
commitd718c717a67051cb1da2a1f80c70401d0d10b374 (patch)
tree8a5fdc8466bc79e54d6b0f07d0e98bcdbf946119 /src/or/networkstatus.c
parent159ea7a88f31aee2f84cf964c0d0000a5bd98970 (diff)
parent9f217c83b0d91508af0d63f04216fa78cdbfbe1b (diff)
downloadtor-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.c189
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