aboutsummaryrefslogtreecommitdiff
path: root/src/or/routerlist.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/routerlist.c')
-rw-r--r--src/or/routerlist.c93
1 files changed, 73 insertions, 20 deletions
diff --git a/src/or/routerlist.c b/src/or/routerlist.c
index 8808f56db..5fb4fe13c 100644
--- a/src/or/routerlist.c
+++ b/src/or/routerlist.c
@@ -440,6 +440,23 @@ authority_cert_dl_failed(const char *id_digest, int status)
download_status_failed(&cl->dl_status, status);
}
+/** Return true iff when we've been getting enough failures when trying to
+ * download the certificate with ID digest <b>id_digest</b> that we're willing
+ * to start bugging the user about it. */
+int
+authority_cert_dl_looks_uncertain(const char *id_digest)
+{
+#define N_AUTH_CERT_DL_FAILURES_TO_BUG_USER 2
+ cert_list_t *cl;
+ int n_failures;
+ if (!trusted_dir_certs ||
+ !(cl = digestmap_get(trusted_dir_certs, id_digest)))
+ return 0;
+
+ n_failures = download_status_get_n_failures(&cl->dl_status);
+ return n_failures >= N_AUTH_CERT_DL_FAILURES_TO_BUG_USER;
+}
+
/** How many times will we try to fetch a certificate before giving up? */
#define MAX_CERT_DL_FAILURES 8
@@ -1257,6 +1274,13 @@ mark_all_trusteddirservers_up(void)
router_dir_info_changed();
}
+/** Return true iff r1 and r2 have the same address and OR port. */
+int
+routers_have_same_or_addr(const routerinfo_t *r1, const routerinfo_t *r2)
+{
+ return r1->addr == r2->addr && r1->or_port == r2->or_port;
+}
+
/** Reset all internal variables used to count failed downloads of network
* status objects. */
void
@@ -3159,8 +3183,10 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
/* If we have this descriptor already and the new descriptor is a bridge
* descriptor, replace it. If we had a bridge descriptor before and the
* new one is not a bridge descriptor, don't replace it. */
- if (old_router && (!routerinfo_is_a_configured_bridge(router) ||
- routerinfo_is_a_configured_bridge(old_router))) {
+ tor_assert(old_router);
+ if (! (routerinfo_is_a_configured_bridge(router) &&
+ (router->purpose == ROUTER_PURPOSE_BRIDGE ||
+ old_router->purpose != ROUTER_PURPOSE_BRIDGE))) {
log_info(LD_DIR,
"Dropping descriptor that we already have for router '%s'",
router->nickname);
@@ -3251,8 +3277,7 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
log_debug(LD_DIR, "Replacing entry for router '%s/%s' [%s]",
router->nickname, old_router->nickname,
hex_str(id_digest,DIGEST_LEN));
- if (router->addr == old_router->addr &&
- router->or_port == old_router->or_port) {
+ if (routers_have_same_or_addr(router, old_router)) {
/* these carry over when the address and orport are unchanged. */
router->last_reachable = old_router->last_reachable;
router->testing_since = old_router->testing_since;
@@ -3281,11 +3306,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);
}
@@ -3605,15 +3625,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);
}
/**
@@ -4196,7 +4220,7 @@ launch_router_descriptor_downloads(smartlist_t *downloadable,
pds_flags |= PDS_NO_EXISTING_SERVERDESC_FETCH;
}
- n_per_request = (n_downloadable+MIN_REQUESTS-1) / MIN_REQUESTS;
+ n_per_request = CEIL_DIV(n_downloadable, MIN_REQUESTS);
if (n_per_request > MAX_DL_PER_REQUEST)
n_per_request = MAX_DL_PER_REQUEST;
if (n_per_request < MIN_DL_PER_REQUEST)
@@ -4209,7 +4233,7 @@ launch_router_descriptor_downloads(smartlist_t *downloadable,
log_info(LD_DIR,
"Launching %d request%s for %d router%s, %d at a time",
- (n_downloadable+n_per_request-1)/n_per_request,
+ CEIL_DIV(n_downloadable, n_per_request),
req_plural, n_downloadable, rtr_plural, n_per_request);
smartlist_sort_digests(downloadable);
for (i=0; i < n_downloadable; i += n_per_request) {
@@ -4649,16 +4673,21 @@ get_dir_info_status_string(void)
/** Iterate over the servers listed in <b>consensus</b>, and count how many of
* them seem like ones we'd use, and how many of <em>those</em> we have
* descriptors for. Store the former in *<b>num_usable</b> and the latter in
- * *<b>num_present</b>. */
+ * *<b>num_present</b>. If <b>in_set</b> is non-NULL, only consider those
+ * routers in <b>in_set</b>.
+ */
static void
count_usable_descriptors(int *num_present, int *num_usable,
const networkstatus_t *consensus,
- or_options_t *options, time_t now)
+ or_options_t *options, time_t now,
+ routerset_t *in_set)
{
*num_present = 0, *num_usable=0;
SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs,
{
+ if (in_set && ! routerset_contains_routerstatus(in_set, rs))
+ continue;
if (client_would_use_router(rs, now, options)) {
++*num_usable; /* the consensus says we want it. */
if (router_get_by_descriptor_digest(rs->descriptor_digest)) {
@@ -4687,7 +4716,7 @@ count_loading_descriptors_progress(void)
return 0; /* can't count descriptors if we have no list of them */
count_usable_descriptors(&num_present, &num_usable,
- consensus, get_options(), now);
+ consensus, get_options(), now, NULL);
if (num_usable == 0)
return 0; /* don't div by 0 */
@@ -4731,22 +4760,39 @@ update_router_have_minimum_dir_info(void)
goto done;
}
- count_usable_descriptors(&num_present, &num_usable, consensus, options, now);
+ count_usable_descriptors(&num_present, &num_usable, consensus, options, now,
+ NULL);
if (num_present < num_usable/4) {
tor_snprintf(dir_info_status, sizeof(dir_info_status),
"We have only %d/%d usable descriptors.", num_present, num_usable);
res = 0;
control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0);
+ goto done;
} else if (num_present < 2) {
tor_snprintf(dir_info_status, sizeof(dir_info_status),
"Only %d descriptor%s here and believed reachable!",
num_present, num_present ? "" : "s");
res = 0;
- } else {
- res = 1;
+ goto done;
}
+ /* Check for entry nodes. */
+ if (options->EntryNodes) {
+ count_usable_descriptors(&num_present, &num_usable, consensus, options,
+ now, options->EntryNodes);
+
+ if (num_usable && (num_present == 0)) {
+ tor_snprintf(dir_info_status, sizeof(dir_info_status),
+ "We have only %d/%d usable entry node descriptors.",
+ num_present, num_usable);
+ res = 0;
+ goto done;
+ }
+ }
+
+ res = 1;
+
done:
if (res && !have_min_dir_info) {
log(LOG_NOTICE, LD_DIR,
@@ -4759,6 +4805,13 @@ update_router_have_minimum_dir_info(void)
log(quiet ? LOG_INFO : LOG_NOTICE, LD_DIR,
"Our directory information is no longer up-to-date "
"enough to build circuits: %s", dir_info_status);
+
+ /* a) make us log when we next complete a circuit, so we know when Tor
+ * is back up and usable, and b) disable some activities that Tor
+ * should only do while circuits are working, like reachability tests
+ * and fetching bridge descriptors only over circuits. */
+ can_complete_circuit = 0;
+
control_event_client_status(LOG_NOTICE, "NOT_ENOUGH_DIR_INFO");
}
have_min_dir_info = res;