mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Move functions for seeing if we know enough nodes into nodelist
This commit is contained in:
parent
725d3a32bd
commit
c2c6d12a81
@ -28,6 +28,7 @@
|
||||
#include "hibernate.h"
|
||||
#include "main.h"
|
||||
#include "networkstatus.h"
|
||||
#include "nodelist.h"
|
||||
#include "policies.h"
|
||||
#include "relay.h"
|
||||
#include "rendclient.h"
|
||||
|
@ -2304,6 +2304,30 @@ networkstatus_parse_flavor_name(const char *flavname)
|
||||
return -1;
|
||||
}
|
||||
|
||||
/** Return 0 if this routerstatus is obsolete, too new, isn't
|
||||
* running, or otherwise not a descriptor that we would make any
|
||||
* use of even if we had it. Else return 1. */
|
||||
int
|
||||
client_would_use_router(const routerstatus_t *rs, time_t now,
|
||||
const or_options_t *options)
|
||||
{
|
||||
if (!rs->is_flagged_running && !options->FetchUselessDescriptors) {
|
||||
/* If we had this router descriptor, we wouldn't even bother using it.
|
||||
* But, if we want to have a complete list, fetch it anyway. */
|
||||
return 0;
|
||||
}
|
||||
if (rs->published_on + options->TestingEstimatedDescriptorPropagationTime
|
||||
> now) {
|
||||
/* Most caches probably don't have this descriptor yet. */
|
||||
return 0;
|
||||
}
|
||||
if (rs->published_on + OLD_ROUTER_DESC_MAX_AGE < now) {
|
||||
/* We'd drop it immediately for being too old. */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** If <b>question</b> is a string beginning with "ns/" in a format the
|
||||
* control interface expects for a GETINFO question, set *<b>answer</b> to a
|
||||
* newly-allocated string containing networkstatus lines for the appropriate
|
||||
|
@ -71,6 +71,8 @@ int should_delay_dir_fetches(const or_options_t *options);
|
||||
void update_networkstatus_downloads(time_t now);
|
||||
void update_certificate_downloads(time_t now);
|
||||
int consensus_is_waiting_for_certs(void);
|
||||
int client_would_use_router(const routerstatus_t *rs, time_t now,
|
||||
const or_options_t *options);
|
||||
networkstatus_v2_t *networkstatus_v2_get_by_digest(const char *digest);
|
||||
networkstatus_t *networkstatus_get_latest_consensus(void);
|
||||
networkstatus_t *networkstatus_get_latest_consensus_by_flavor(
|
||||
|
@ -7,12 +7,15 @@
|
||||
#include "or.h"
|
||||
#include "address.h"
|
||||
#include "config.h"
|
||||
#include "control.h"
|
||||
#include "dirserv.h"
|
||||
#include "geoip.h"
|
||||
#include "main.h"
|
||||
#include "microdesc.h"
|
||||
#include "networkstatus.h"
|
||||
#include "nodelist.h"
|
||||
#include "policies.h"
|
||||
#include "rendservice.h"
|
||||
#include "router.h"
|
||||
#include "routerlist.h"
|
||||
#include "routerset.h"
|
||||
@ -21,6 +24,7 @@
|
||||
|
||||
static void nodelist_drop_node(node_t *node, int remove_from_ht);
|
||||
static void node_free(node_t *node);
|
||||
static void update_router_have_minimum_dir_info(void);
|
||||
|
||||
/** A nodelist_t holds a node_t object for every router we're "willing to use
|
||||
* for something". Specifically, it should hold a node_t for every node that
|
||||
@ -1148,3 +1152,256 @@ router_exit_policy_all_nodes_reject(const tor_addr_t *addr, uint16_t port,
|
||||
return 1; /* all will reject. */
|
||||
}
|
||||
|
||||
/** Mark the router with ID <b>digest</b> as running or non-running
|
||||
* in our routerlist. */
|
||||
void
|
||||
router_set_status(const char *digest, int up)
|
||||
{
|
||||
node_t *node;
|
||||
tor_assert(digest);
|
||||
|
||||
SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
|
||||
trusted_dir_server_t *, d,
|
||||
if (tor_memeq(d->digest, digest, DIGEST_LEN))
|
||||
d->is_running = up);
|
||||
|
||||
node = node_get_mutable_by_id(digest);
|
||||
if (node) {
|
||||
#if 0
|
||||
log_debug(LD_DIR,"Marking router %s as %s.",
|
||||
node_describe(node), up ? "up" : "down");
|
||||
#endif
|
||||
if (!up && node_is_me(node) && !net_is_disabled())
|
||||
log_warn(LD_NET, "We just marked ourself as down. Are your external "
|
||||
"addresses reachable?");
|
||||
node->is_running = up;
|
||||
}
|
||||
|
||||
router_dir_info_changed();
|
||||
}
|
||||
|
||||
/** True iff, the last time we checked whether we had enough directory info
|
||||
* to build circuits, the answer was "yes". */
|
||||
static int have_min_dir_info = 0;
|
||||
/** True iff enough has changed since the last time we checked whether we had
|
||||
* enough directory info to build circuits that our old answer can no longer
|
||||
* be trusted. */
|
||||
static int need_to_update_have_min_dir_info = 1;
|
||||
/** String describing what we're missing before we have enough directory
|
||||
* info. */
|
||||
static char dir_info_status[128] = "";
|
||||
|
||||
/** Return true iff we have enough networkstatus and router information to
|
||||
* start building circuits. Right now, this means "more than half the
|
||||
* networkstatus documents, and at least 1/4 of expected routers." */
|
||||
//XXX should consider whether we have enough exiting nodes here.
|
||||
int
|
||||
router_have_minimum_dir_info(void)
|
||||
{
|
||||
if (PREDICT_UNLIKELY(need_to_update_have_min_dir_info)) {
|
||||
update_router_have_minimum_dir_info();
|
||||
need_to_update_have_min_dir_info = 0;
|
||||
}
|
||||
return have_min_dir_info;
|
||||
}
|
||||
|
||||
/** Called when our internal view of the directory has changed. This can be
|
||||
* when the authorities change, networkstatuses change, the list of routerdescs
|
||||
* changes, or number of running routers changes.
|
||||
*/
|
||||
void
|
||||
router_dir_info_changed(void)
|
||||
{
|
||||
need_to_update_have_min_dir_info = 1;
|
||||
rend_hsdir_routers_changed();
|
||||
}
|
||||
|
||||
/** Return a string describing what we're missing before we have enough
|
||||
* directory info. */
|
||||
const char *
|
||||
get_dir_info_status_string(void)
|
||||
{
|
||||
return dir_info_status;
|
||||
}
|
||||
|
||||
/** 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>. If <b>in_set</b> is non-NULL, only consider those
|
||||
* routers in <b>in_set</b>. If <b>exit_only</b> is true, only consider nodes
|
||||
* with the Exit flag.
|
||||
*/
|
||||
static void
|
||||
count_usable_descriptors(int *num_present, int *num_usable,
|
||||
const networkstatus_t *consensus,
|
||||
const or_options_t *options, time_t now,
|
||||
routerset_t *in_set, int exit_only)
|
||||
{
|
||||
const int md = (consensus->flavor == FLAV_MICRODESC);
|
||||
*num_present = 0, *num_usable=0;
|
||||
|
||||
SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *, rs)
|
||||
{
|
||||
if (exit_only && ! rs->is_exit)
|
||||
continue;
|
||||
if (in_set && ! routerset_contains_routerstatus(in_set, rs, -1))
|
||||
continue;
|
||||
if (client_would_use_router(rs, now, options)) {
|
||||
const char * const digest = rs->descriptor_digest;
|
||||
int present;
|
||||
++*num_usable; /* the consensus says we want it. */
|
||||
if (md)
|
||||
present = NULL != microdesc_cache_lookup_by_digest256(NULL, digest);
|
||||
else
|
||||
present = NULL != router_get_by_descriptor_digest(digest);
|
||||
if (present) {
|
||||
/* we have the descriptor listed in the consensus. */
|
||||
++*num_present;
|
||||
}
|
||||
}
|
||||
}
|
||||
SMARTLIST_FOREACH_END(rs);
|
||||
|
||||
log_debug(LD_DIR, "%d usable, %d present (%s).", *num_usable, *num_present,
|
||||
md ? "microdescs" : "descs");
|
||||
}
|
||||
|
||||
/** We just fetched a new set of descriptors. Compute how far through
|
||||
* the "loading descriptors" bootstrapping phase we are, so we can inform
|
||||
* the controller of our progress. */
|
||||
int
|
||||
count_loading_descriptors_progress(void)
|
||||
{
|
||||
int num_present = 0, num_usable=0;
|
||||
time_t now = time(NULL);
|
||||
const networkstatus_t *consensus =
|
||||
networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor());
|
||||
double fraction;
|
||||
|
||||
if (!consensus)
|
||||
return 0; /* can't count descriptors if we have no list of them */
|
||||
|
||||
count_usable_descriptors(&num_present, &num_usable,
|
||||
consensus, get_options(), now, NULL, 0);
|
||||
|
||||
if (num_usable == 0)
|
||||
return 0; /* don't div by 0 */
|
||||
fraction = num_present / (num_usable/4.);
|
||||
if (fraction > 1.0)
|
||||
return 0; /* it's not the number of descriptors holding us back */
|
||||
return BOOTSTRAP_STATUS_LOADING_DESCRIPTORS + (int)
|
||||
(fraction*(BOOTSTRAP_STATUS_CONN_OR-1 -
|
||||
BOOTSTRAP_STATUS_LOADING_DESCRIPTORS));
|
||||
}
|
||||
|
||||
/** Change the value of have_min_dir_info, setting it true iff we have enough
|
||||
* network and router information to build circuits. Clear the value of
|
||||
* need_to_update_have_min_dir_info. */
|
||||
static void
|
||||
update_router_have_minimum_dir_info(void)
|
||||
{
|
||||
int num_present = 0, num_usable=0;
|
||||
int num_exit_present = 0, num_exit_usable = 0;
|
||||
time_t now = time(NULL);
|
||||
int res;
|
||||
const or_options_t *options = get_options();
|
||||
const networkstatus_t *consensus =
|
||||
networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor());
|
||||
int using_md;
|
||||
|
||||
if (!consensus) {
|
||||
if (!networkstatus_get_latest_consensus())
|
||||
strlcpy(dir_info_status, "We have no usable consensus.",
|
||||
sizeof(dir_info_status));
|
||||
else
|
||||
strlcpy(dir_info_status, "We have no recent usable consensus.",
|
||||
sizeof(dir_info_status));
|
||||
res = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (should_delay_dir_fetches(get_options())) {
|
||||
log_notice(LD_DIR, "no known bridge descriptors running yet; stalling");
|
||||
strlcpy(dir_info_status, "No live bridge descriptors.",
|
||||
sizeof(dir_info_status));
|
||||
res = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
using_md = consensus->flavor == FLAV_MICRODESC;
|
||||
|
||||
count_usable_descriptors(&num_present, &num_usable, consensus, options, now,
|
||||
NULL, 0);
|
||||
count_usable_descriptors(&num_exit_present, &num_exit_usable,
|
||||
consensus, options, now, options->ExitNodes, 1);
|
||||
|
||||
/* What fraction of desired server descriptors do we need before we will
|
||||
* build circuits? */
|
||||
#define FRAC_USABLE_NEEDED .75
|
||||
/* What fraction of desired _exit_ server descriptors do we need before we
|
||||
* will build circuits? */
|
||||
#define FRAC_EXIT_USABLE_NEEDED .5
|
||||
|
||||
if (num_present < num_usable * FRAC_USABLE_NEEDED) {
|
||||
tor_snprintf(dir_info_status, sizeof(dir_info_status),
|
||||
"We have only %d/%d usable %sdescriptors.",
|
||||
num_present, num_usable, using_md ? "micro" : "");
|
||||
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 %sdescriptor%s here and believed reachable!",
|
||||
num_present, using_md ? "micro" : "", num_present ? "" : "s");
|
||||
res = 0;
|
||||
goto done;
|
||||
} else if (num_exit_present < num_exit_usable * FRAC_EXIT_USABLE_NEEDED) {
|
||||
tor_snprintf(dir_info_status, sizeof(dir_info_status),
|
||||
"We have only %d/%d usable exit node descriptors.",
|
||||
num_exit_present, num_exit_usable);
|
||||
res = 0;
|
||||
control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Check for entry nodes. */
|
||||
if (options->EntryNodes) {
|
||||
count_usable_descriptors(&num_present, &num_usable, consensus, options,
|
||||
now, options->EntryNodes, 0);
|
||||
|
||||
if (!num_usable || !num_present) {
|
||||
tor_snprintf(dir_info_status, sizeof(dir_info_status),
|
||||
"We have only %d/%d usable entry node %sdescriptors.",
|
||||
num_present, num_usable, using_md?"micro":"");
|
||||
res = 0;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
res = 1;
|
||||
|
||||
done:
|
||||
if (res && !have_min_dir_info) {
|
||||
log(LOG_NOTICE, LD_DIR,
|
||||
"We now have enough directory information to build circuits.");
|
||||
control_event_client_status(LOG_NOTICE, "ENOUGH_DIR_INFO");
|
||||
control_event_bootstrap(BOOTSTRAP_STATUS_CONN_OR, 0);
|
||||
}
|
||||
if (!res && have_min_dir_info) {
|
||||
int quiet = directory_too_idle_to_fetch_descriptors(options, now);
|
||||
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;
|
||||
need_to_update_have_min_dir_info = 0;
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,11 @@ int node_is_unreliable(const node_t *router, int need_uptime,
|
||||
int need_capacity, int need_guard);
|
||||
int router_exit_policy_all_nodes_reject(const tor_addr_t *addr, uint16_t port,
|
||||
int need_uptime);
|
||||
void router_set_status(const char *digest, int up);
|
||||
int router_have_minimum_dir_info(void);
|
||||
void router_dir_info_changed(void);
|
||||
const char *get_dir_info_status_string(void);
|
||||
int count_loading_descriptors_progress(void);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -50,7 +50,6 @@ static int router_nickname_matches(const routerinfo_t *router,
|
||||
const char *nickname);
|
||||
static void trusted_dir_server_free(trusted_dir_server_t *ds);
|
||||
static int signed_desc_digest_is_recognized(signed_descriptor_t *desc);
|
||||
static void update_router_have_minimum_dir_info(void);
|
||||
static const char *signed_descriptor_get_body_impl(
|
||||
const signed_descriptor_t *desc,
|
||||
int with_annotations);
|
||||
@ -2940,33 +2939,6 @@ routerlist_reset_warnings(void)
|
||||
networkstatus_reset_warnings();
|
||||
}
|
||||
|
||||
/** Mark the router with ID <b>digest</b> as running or non-running
|
||||
* in our routerlist. */
|
||||
void
|
||||
router_set_status(const char *digest, int up)
|
||||
{
|
||||
node_t *node;
|
||||
tor_assert(digest);
|
||||
|
||||
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d,
|
||||
if (tor_memeq(d->digest, digest, DIGEST_LEN))
|
||||
d->is_running = up);
|
||||
|
||||
node = node_get_mutable_by_id(digest);
|
||||
if (node) {
|
||||
#if 0
|
||||
log_debug(LD_DIR,"Marking router %s as %s.",
|
||||
node_describe(node), up ? "up" : "down");
|
||||
#endif
|
||||
if (!up && node_is_me(node) && !net_is_disabled())
|
||||
log_warn(LD_NET, "We just marked ourself as down. Are your external "
|
||||
"addresses reachable?");
|
||||
node->is_running = up;
|
||||
}
|
||||
|
||||
router_dir_info_changed();
|
||||
}
|
||||
|
||||
/** Add <b>router</b> to the routerlist, if we don't already have it. Replace
|
||||
* older entries (if any) with the same key. Note: Callers should not hold
|
||||
* their pointers to <b>router</b> if this function fails; <b>router</b>
|
||||
@ -3993,30 +3965,6 @@ initiate_descriptor_downloads(const routerstatus_t *source,
|
||||
tor_free(resource);
|
||||
}
|
||||
|
||||
/** Return 0 if this routerstatus is obsolete, too new, isn't
|
||||
* running, or otherwise not a descriptor that we would make any
|
||||
* use of even if we had it. Else return 1. */
|
||||
static INLINE int
|
||||
client_would_use_router(const routerstatus_t *rs, time_t now,
|
||||
const or_options_t *options)
|
||||
{
|
||||
if (!rs->is_flagged_running && !options->FetchUselessDescriptors) {
|
||||
/* If we had this router descriptor, we wouldn't even bother using it.
|
||||
* But, if we want to have a complete list, fetch it anyway. */
|
||||
return 0;
|
||||
}
|
||||
if (rs->published_on + options->TestingEstimatedDescriptorPropagationTime
|
||||
> now) {
|
||||
/* Most caches probably don't have this descriptor yet. */
|
||||
return 0;
|
||||
}
|
||||
if (rs->published_on + OLD_ROUTER_DESC_MAX_AGE < now) {
|
||||
/* We'd drop it immediately for being too old. */
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Max amount of hashes to download per request.
|
||||
* Since squid does not like URLs >= 4096 bytes we limit it to 96.
|
||||
* 4096 - strlen(http://255.255.255.255/tor/server/d/.z) == 4058
|
||||
@ -4529,231 +4477,6 @@ update_extrainfo_downloads(time_t now)
|
||||
smartlist_free(wanted);
|
||||
}
|
||||
|
||||
/** True iff, the last time we checked whether we had enough directory info
|
||||
* to build circuits, the answer was "yes". */
|
||||
static int have_min_dir_info = 0;
|
||||
/** True iff enough has changed since the last time we checked whether we had
|
||||
* enough directory info to build circuits that our old answer can no longer
|
||||
* be trusted. */
|
||||
static int need_to_update_have_min_dir_info = 1;
|
||||
/** String describing what we're missing before we have enough directory
|
||||
* info. */
|
||||
static char dir_info_status[128] = "";
|
||||
|
||||
/** Return true iff we have enough networkstatus and router information to
|
||||
* start building circuits. Right now, this means "more than half the
|
||||
* networkstatus documents, and at least 1/4 of expected routers." */
|
||||
//XXX should consider whether we have enough exiting nodes here.
|
||||
int
|
||||
router_have_minimum_dir_info(void)
|
||||
{
|
||||
if (PREDICT_UNLIKELY(need_to_update_have_min_dir_info)) {
|
||||
update_router_have_minimum_dir_info();
|
||||
need_to_update_have_min_dir_info = 0;
|
||||
}
|
||||
return have_min_dir_info;
|
||||
}
|
||||
|
||||
/** Called when our internal view of the directory has changed. This can be
|
||||
* when the authorities change, networkstatuses change, the list of routerdescs
|
||||
* changes, or number of running routers changes.
|
||||
*/
|
||||
void
|
||||
router_dir_info_changed(void)
|
||||
{
|
||||
need_to_update_have_min_dir_info = 1;
|
||||
rend_hsdir_routers_changed();
|
||||
}
|
||||
|
||||
/** Return a string describing what we're missing before we have enough
|
||||
* directory info. */
|
||||
const char *
|
||||
get_dir_info_status_string(void)
|
||||
{
|
||||
return dir_info_status;
|
||||
}
|
||||
|
||||
/** 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>. If <b>in_set</b> is non-NULL, only consider those
|
||||
* routers in <b>in_set</b>. If <b>exit_only</b> is true, only consider nodes
|
||||
* with the Exit flag.
|
||||
*/
|
||||
static void
|
||||
count_usable_descriptors(int *num_present, int *num_usable,
|
||||
const networkstatus_t *consensus,
|
||||
const or_options_t *options, time_t now,
|
||||
routerset_t *in_set, int exit_only)
|
||||
{
|
||||
const int md = (consensus->flavor == FLAV_MICRODESC);
|
||||
*num_present = 0, *num_usable=0;
|
||||
|
||||
SMARTLIST_FOREACH_BEGIN(consensus->routerstatus_list, routerstatus_t *, rs)
|
||||
{
|
||||
if (exit_only && ! rs->is_exit)
|
||||
continue;
|
||||
if (in_set && ! routerset_contains_routerstatus(in_set, rs, -1))
|
||||
continue;
|
||||
if (client_would_use_router(rs, now, options)) {
|
||||
const char * const digest = rs->descriptor_digest;
|
||||
int present;
|
||||
++*num_usable; /* the consensus says we want it. */
|
||||
if (md)
|
||||
present = NULL != microdesc_cache_lookup_by_digest256(NULL, digest);
|
||||
else
|
||||
present = NULL != router_get_by_descriptor_digest(digest);
|
||||
if (present) {
|
||||
/* we have the descriptor listed in the consensus. */
|
||||
++*num_present;
|
||||
}
|
||||
}
|
||||
}
|
||||
SMARTLIST_FOREACH_END(rs);
|
||||
|
||||
log_debug(LD_DIR, "%d usable, %d present (%s).", *num_usable, *num_present,
|
||||
md ? "microdescs" : "descs");
|
||||
}
|
||||
|
||||
/** We just fetched a new set of descriptors. Compute how far through
|
||||
* the "loading descriptors" bootstrapping phase we are, so we can inform
|
||||
* the controller of our progress. */
|
||||
int
|
||||
count_loading_descriptors_progress(void)
|
||||
{
|
||||
int num_present = 0, num_usable=0;
|
||||
time_t now = time(NULL);
|
||||
const networkstatus_t *consensus =
|
||||
networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor());
|
||||
double fraction;
|
||||
|
||||
if (!consensus)
|
||||
return 0; /* can't count descriptors if we have no list of them */
|
||||
|
||||
count_usable_descriptors(&num_present, &num_usable,
|
||||
consensus, get_options(), now, NULL, 0);
|
||||
|
||||
if (num_usable == 0)
|
||||
return 0; /* don't div by 0 */
|
||||
fraction = num_present / (num_usable/4.);
|
||||
if (fraction > 1.0)
|
||||
return 0; /* it's not the number of descriptors holding us back */
|
||||
return BOOTSTRAP_STATUS_LOADING_DESCRIPTORS + (int)
|
||||
(fraction*(BOOTSTRAP_STATUS_CONN_OR-1 -
|
||||
BOOTSTRAP_STATUS_LOADING_DESCRIPTORS));
|
||||
}
|
||||
|
||||
/** Change the value of have_min_dir_info, setting it true iff we have enough
|
||||
* network and router information to build circuits. Clear the value of
|
||||
* need_to_update_have_min_dir_info. */
|
||||
static void
|
||||
update_router_have_minimum_dir_info(void)
|
||||
{
|
||||
int num_present = 0, num_usable=0;
|
||||
int num_exit_present = 0, num_exit_usable = 0;
|
||||
time_t now = time(NULL);
|
||||
int res;
|
||||
const or_options_t *options = get_options();
|
||||
const networkstatus_t *consensus =
|
||||
networkstatus_get_reasonably_live_consensus(now,usable_consensus_flavor());
|
||||
int using_md;
|
||||
|
||||
if (!consensus) {
|
||||
if (!networkstatus_get_latest_consensus())
|
||||
strlcpy(dir_info_status, "We have no usable consensus.",
|
||||
sizeof(dir_info_status));
|
||||
else
|
||||
strlcpy(dir_info_status, "We have no recent usable consensus.",
|
||||
sizeof(dir_info_status));
|
||||
res = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (should_delay_dir_fetches(get_options())) {
|
||||
log_notice(LD_DIR, "no known bridge descriptors running yet; stalling");
|
||||
strlcpy(dir_info_status, "No live bridge descriptors.",
|
||||
sizeof(dir_info_status));
|
||||
res = 0;
|
||||
goto done;
|
||||
}
|
||||
|
||||
using_md = consensus->flavor == FLAV_MICRODESC;
|
||||
|
||||
count_usable_descriptors(&num_present, &num_usable, consensus, options, now,
|
||||
NULL, 0);
|
||||
count_usable_descriptors(&num_exit_present, &num_exit_usable,
|
||||
consensus, options, now, options->ExitNodes, 1);
|
||||
|
||||
/* What fraction of desired server descriptors do we need before we will
|
||||
* build circuits? */
|
||||
#define FRAC_USABLE_NEEDED .75
|
||||
/* What fraction of desired _exit_ server descriptors do we need before we
|
||||
* will build circuits? */
|
||||
#define FRAC_EXIT_USABLE_NEEDED .5
|
||||
|
||||
if (num_present < num_usable * FRAC_USABLE_NEEDED) {
|
||||
tor_snprintf(dir_info_status, sizeof(dir_info_status),
|
||||
"We have only %d/%d usable %sdescriptors.",
|
||||
num_present, num_usable, using_md ? "micro" : "");
|
||||
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 %sdescriptor%s here and believed reachable!",
|
||||
num_present, using_md ? "micro" : "", num_present ? "" : "s");
|
||||
res = 0;
|
||||
goto done;
|
||||
} else if (num_exit_present < num_exit_usable * FRAC_EXIT_USABLE_NEEDED) {
|
||||
tor_snprintf(dir_info_status, sizeof(dir_info_status),
|
||||
"We have only %d/%d usable exit node descriptors.",
|
||||
num_exit_present, num_exit_usable);
|
||||
res = 0;
|
||||
control_event_bootstrap(BOOTSTRAP_STATUS_REQUESTING_DESCRIPTORS, 0);
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Check for entry nodes. */
|
||||
if (options->EntryNodes) {
|
||||
count_usable_descriptors(&num_present, &num_usable, consensus, options,
|
||||
now, options->EntryNodes, 0);
|
||||
|
||||
if (!num_usable || !num_present) {
|
||||
tor_snprintf(dir_info_status, sizeof(dir_info_status),
|
||||
"We have only %d/%d usable entry node %sdescriptors.",
|
||||
num_present, num_usable, using_md?"micro":"");
|
||||
res = 0;
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
res = 1;
|
||||
|
||||
done:
|
||||
if (res && !have_min_dir_info) {
|
||||
log(LOG_NOTICE, LD_DIR,
|
||||
"We now have enough directory information to build circuits.");
|
||||
control_event_client_status(LOG_NOTICE, "ENOUGH_DIR_INFO");
|
||||
control_event_bootstrap(BOOTSTRAP_STATUS_CONN_OR, 0);
|
||||
}
|
||||
if (!res && have_min_dir_info) {
|
||||
int quiet = directory_too_idle_to_fetch_descriptors(options, now);
|
||||
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;
|
||||
need_to_update_have_min_dir_info = 0;
|
||||
}
|
||||
|
||||
/** Reset the descriptor download failure count on all routers, so that we
|
||||
* can retry any long-failed routers immediately.
|
||||
*/
|
||||
|
@ -73,7 +73,6 @@ void routerlist_remove(routerlist_t *rl, routerinfo_t *ri, int make_old,
|
||||
time_t now);
|
||||
void routerlist_free_all(void);
|
||||
void routerlist_reset_warnings(void);
|
||||
void router_set_status(const char *digest, int up);
|
||||
|
||||
static int WRA_WAS_ADDED(was_router_added_t s);
|
||||
static int WRA_WAS_OUTDATED(was_router_added_t s);
|
||||
@ -141,10 +140,6 @@ void update_consensus_router_descriptor_downloads(time_t now, int is_vote,
|
||||
void update_router_descriptor_downloads(time_t now);
|
||||
void update_all_descriptor_downloads(time_t now);
|
||||
void update_extrainfo_downloads(time_t now);
|
||||
int router_have_minimum_dir_info(void);
|
||||
void router_dir_info_changed(void);
|
||||
const char *get_dir_info_status_string(void);
|
||||
int count_loading_descriptors_progress(void);
|
||||
void router_reset_descriptor_download_failures(void);
|
||||
int router_differences_are_cosmetic(const routerinfo_t *r1,
|
||||
const routerinfo_t *r2);
|
||||
|
Loading…
Reference in New Issue
Block a user