mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-23 20:03:31 +01:00
r15806@catbus: nickm | 2007-10-15 19:14:57 -0400
Implement v3 networkstatus client code. Remove v2 networkstatus client code, except as needed for caches to fetch and serve v2 networkstatues and the routers they list. svn:r11957
This commit is contained in:
parent
95f6265a79
commit
3ad6dc0e2e
@ -1,4 +1,9 @@
|
||||
Changes in version 0.2.0.9-alpha - 2007-10-??
|
||||
o Major features (v3 directory system):
|
||||
- Clients now download v3 consensus networkstatus documents instead
|
||||
of v2 networkstatus documents. Clients and caches now their opinions
|
||||
about routers on these consensus documents. Clients only download
|
||||
router descriptors listed in the consensus.
|
||||
|
||||
o Major bugfixes:
|
||||
- Stop publishing a new server descriptor just because we HUP or
|
||||
|
25
doc/TODO
25
doc/TODO
@ -69,8 +69,29 @@ Things we'd like to do in 0.2.0.x:
|
||||
- Enable for non-caches
|
||||
- Code to use v3 networkstatus documents once clients are
|
||||
fetching them
|
||||
- Implement
|
||||
- Enable
|
||||
o Make everybody download v3 networkstatus docs.
|
||||
o Make clients not download v2 networkstatus docs.
|
||||
o Make everybody download routerdescs based on v3 networkstatus
|
||||
docs.
|
||||
o Change definition of "have enough information to build circuits"
|
||||
o Base version sanity check on v3 ns.
|
||||
o Change routerstatus_get_by_* to use v3 networkstatus docs.
|
||||
o Make download_status_get_by_descriptor_digest() use v2
|
||||
networkstatus docs too.
|
||||
o Eliminate routerstatus_list.
|
||||
o Make routers_update_all_from_networkstatus() [or equivalent]
|
||||
get called at the right time.
|
||||
o Make routersstatus_list_update_from_consensus_networkstatus()
|
||||
get renamed and called.
|
||||
o When setting a new consensus, copy the extra fields out of the
|
||||
old consensus (if any).
|
||||
o Update named-server-map as appropriate.
|
||||
- Fix all XXXX020s.
|
||||
- Sort out need_to_mirror
|
||||
- Work hard to make sure clients never look at v2 networkstatus docs.
|
||||
- Check in old_routers before fetching a router status. You never
|
||||
know if we'll flap...
|
||||
|
||||
- Controller support
|
||||
- GETINFO to get consensus
|
||||
- Event when new consensus arrives
|
||||
|
@ -1609,33 +1609,38 @@ getinfo_helper_events(control_connection_t *control_conn,
|
||||
check_whether_orport_reachable() ? 1 : 0,
|
||||
check_whether_dirport_reachable() ? 1 : 0);
|
||||
} else if (!strcmpstart(question, "status/version/")) {
|
||||
combined_version_status_t st;
|
||||
int is_server = server_mode(get_options());
|
||||
char *recommended;
|
||||
recommended = compute_recommended_versions(time(NULL),
|
||||
!is_server, VERSION, &st);
|
||||
networkstatus_vote_t *c = networkstatus_get_latest_consensus();
|
||||
version_status_t status;
|
||||
const char *recommended;
|
||||
if (c) {
|
||||
recommended = is_server ? c->server_versions : c->client_versions;
|
||||
status = tor_version_is_obsolete(VERSION, recommended);
|
||||
} else {
|
||||
recommended = "?";
|
||||
status = VS_UNKNOWN;
|
||||
}
|
||||
|
||||
if (!strcmp(question, "status/version/recommended")) {
|
||||
*answer = recommended;
|
||||
*answer = tor_strdup(recommended);
|
||||
return 0;
|
||||
}
|
||||
tor_free(recommended);
|
||||
if (!strcmp(question, "status/version/current")) {
|
||||
switch (st.consensus)
|
||||
switch (status)
|
||||
{
|
||||
case VS_RECOMMENDED: *answer = tor_strdup("recommended"); break;
|
||||
case VS_OLD: *answer = tor_strdup("obsolete"); break;
|
||||
case VS_NEW: *answer = tor_strdup("new"); break;
|
||||
case VS_NEW_IN_SERIES: *answer = tor_strdup("new in series"); break;
|
||||
case VS_UNRECOMMENDED: *answer = tor_strdup("unrecommended"); break;
|
||||
case VS_UNKNOWN: *answer = tor_strdup("unknown"); break;
|
||||
default: tor_fragile_assert();
|
||||
}
|
||||
} else if (!strcmp(question, "status/version/num-versioning")) {
|
||||
} else if (!strcmp(question, "status/version/num-versioning") ||
|
||||
!strcmp(question, "status/version/num-concurring")) {
|
||||
/*XXXX020 deprecate.*/
|
||||
char s[33];
|
||||
tor_snprintf(s, sizeof(s), "%d", st.n_versioning);
|
||||
*answer = tor_strdup(s);
|
||||
} else if (!strcmp(question, "status/version/num-concurring")) {
|
||||
char s[33];
|
||||
tor_snprintf(s, sizeof(s), "%d", st.n_concurring);
|
||||
tor_snprintf(s, sizeof(s), "%d", get_n_authorities(V3_AUTHORITY));
|
||||
*answer = tor_strdup(s);
|
||||
}
|
||||
} else {
|
||||
|
@ -178,7 +178,7 @@ router_supports_extrainfo(const char *identity_digest, int is_authority)
|
||||
return 1;
|
||||
}
|
||||
if (is_authority) {
|
||||
routerstatus_t *rs = router_get_combined_status_by_digest(identity_digest);
|
||||
routerstatus_t *rs = router_get_consensus_status_by_id(identity_digest);
|
||||
if (rs && rs->version_supports_extrainfo_upload)
|
||||
return 1;
|
||||
}
|
||||
@ -1232,7 +1232,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
|
||||
"'%s:%d'. I'll try again soon.",
|
||||
status_code, escaped(reason), conn->_base.address,
|
||||
conn->_base.port);
|
||||
if ((rs = router_get_combined_status_by_digest(conn->identity_digest)))
|
||||
if ((rs = router_get_consensus_status_by_id(conn->identity_digest)))
|
||||
rs->last_dir_503_at = now;
|
||||
if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
|
||||
ds->fake_status.last_dir_503_at = now;
|
||||
@ -1387,7 +1387,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
|
||||
if (next)
|
||||
next[1] = '\0';
|
||||
/* learn from it, and then remove it from 'which' */
|
||||
if (router_set_networkstatus(cp, now, source, which)<0)
|
||||
if (router_set_networkstatus_v2(cp, now, source, which)<0)
|
||||
break;
|
||||
if (next) {
|
||||
next[1] = 'n';
|
||||
@ -1426,6 +1426,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
|
||||
networkstatus_consensus_download_failed(0);
|
||||
return -1;
|
||||
}
|
||||
routers_update_all_from_networkstatus(now); /*launches router downloads*/
|
||||
directory_info_has_arrived(now, 0);
|
||||
log_info(LD_DIR, "Successfully loaded consensus.");
|
||||
}
|
||||
if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
|
||||
@ -2790,10 +2792,7 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
|
||||
if (sd)
|
||||
dls = &sd->ei_dl_status;
|
||||
} else {
|
||||
routerstatus_t *rs =
|
||||
router_get_combined_status_by_descriptor_digest(digest);
|
||||
if (rs)
|
||||
dls = &rs->dl_status;
|
||||
dls = router_get_dl_status_by_descriptor_digest(digest);
|
||||
}
|
||||
if (!dls || dls->n_download_failures >= MAX_ROUTERDESC_DOWNLOAD_FAILURES)
|
||||
continue;
|
||||
|
@ -2380,12 +2380,12 @@ generate_networkstatus_opinion(int v2)
|
||||
}
|
||||
|
||||
{
|
||||
networkstatus_t *ns;
|
||||
if (!(ns = networkstatus_parse_from_string(status))) {
|
||||
networkstatus_v2_t *ns;
|
||||
if (!(ns = networkstatus_v2_parse_from_string(status))) {
|
||||
log_err(LD_BUG,"Generated a networkstatus we couldn't parse.");
|
||||
goto done;
|
||||
}
|
||||
networkstatus_free(ns);
|
||||
networkstatus_v2_free(ns);
|
||||
}
|
||||
|
||||
{
|
||||
@ -2395,7 +2395,7 @@ generate_networkstatus_opinion(int v2)
|
||||
*ns_ptr = new_cached_dir(status, now);
|
||||
status = NULL; /* So it doesn't get double-freed. */
|
||||
the_v2_networkstatus_is_dirty = 0;
|
||||
router_set_networkstatus((*ns_ptr)->dir, now, NS_GENERATED, NULL);
|
||||
router_set_networkstatus_v2((*ns_ptr)->dir, now, NS_GENERATED, NULL);
|
||||
r = *ns_ptr;
|
||||
}
|
||||
|
||||
|
@ -67,6 +67,8 @@ networkstatus_vote_free(networkstatus_vote_t *ns)
|
||||
|
||||
smartlist_free(ns->routerstatus_list);
|
||||
}
|
||||
if (ns->desc_digest_map)
|
||||
digestmap_free(ns->desc_digest_map, NULL);
|
||||
|
||||
memset(ns, 11, sizeof(*ns));
|
||||
tor_free(ns);
|
||||
|
@ -547,7 +547,6 @@ accounting_set_wakeup_time(void)
|
||||
|
||||
/* This rounds 0 up to 1000, but that's actually a feature. */
|
||||
#define ROUND_UP(x) (((x) + 0x3ff) & ~0x3ff)
|
||||
#define BW_ACCOUNTING_VERSION 1
|
||||
/** Save all our bandwidth tracking information to disk. Return 0 on
|
||||
* success, -1 on failure. */
|
||||
int
|
||||
|
@ -995,9 +995,10 @@ run_scheduled_events(time_t now)
|
||||
* update all the descriptors' running status. */
|
||||
/* purge obsolete entries */
|
||||
routerlist_remove_old_routers();
|
||||
networkstatus_list_clean(now);
|
||||
networkstatus_list_update_recent(now);
|
||||
routers_update_all_from_networkstatus(now);
|
||||
networkstatus_v2_list_clean(now);
|
||||
#if 0
|
||||
networkstatus_v2_list_update_recent(now);
|
||||
#endif
|
||||
|
||||
/* Also, once per minute, check whether we want to download any
|
||||
* networkstatus documents.
|
||||
@ -1339,6 +1340,14 @@ do_main_loop(void)
|
||||
stats_prev_global_read_bucket = global_read_bucket;
|
||||
stats_prev_global_write_bucket = global_write_bucket;
|
||||
|
||||
if (trusted_dirs_reload_certs())
|
||||
return -1;
|
||||
if (router_reload_v2_networkstatus()) {
|
||||
return -1;
|
||||
}
|
||||
if (router_reload_consensus_networkstatus()) {
|
||||
return -1;
|
||||
}
|
||||
/* load the routers file, or assign the defaults. */
|
||||
if (router_reload_router_list()) {
|
||||
return -1;
|
||||
@ -1346,12 +1355,6 @@ do_main_loop(void)
|
||||
/* load the networkstatuses. (This launches a download for new routers as
|
||||
* appropriate.)
|
||||
*/
|
||||
if (router_reload_networkstatus()) {
|
||||
return -1;
|
||||
}
|
||||
if (router_reload_consensus_networkstatus()) {
|
||||
return -1;
|
||||
}
|
||||
now = time(NULL);
|
||||
directory_info_has_arrived(now, 1);
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
81
src/or/or.h
81
src/or/or.h
@ -120,12 +120,6 @@
|
||||
#define cell_t tor_cell_t
|
||||
#endif
|
||||
|
||||
/** Undefine this when it's time to stop generating v1 directories. */
|
||||
// #define FULL_V1_DIRECTORIES
|
||||
/** Undefine this when it's time to stop includeing bandwidth info in router
|
||||
* descriptors. */
|
||||
#define INCLUDE_BW_INFO_IN_ROUTERDESCS
|
||||
|
||||
/** Length of longest allowable configured nickname. */
|
||||
#define MAX_NICKNAME_LEN 19
|
||||
/** Length of a router identity encoded as a hexadecimal digest, plus
|
||||
@ -172,8 +166,6 @@
|
||||
#define ROUTER_MAX_AGE_TO_PUBLISH (60*60*20)
|
||||
/** How old do we let a saved descriptor get before force-removing it? */
|
||||
#define OLD_ROUTER_DESC_MAX_AGE (60*60*24*5)
|
||||
/** How old do we let a networkstatus get before ignoring it? */
|
||||
#define NETWORKSTATUS_MAX_AGE (60*60*24)
|
||||
|
||||
/** Possible rules for generating circuit IDs on an OR connection. */
|
||||
typedef enum {
|
||||
@ -342,26 +334,24 @@ typedef enum {
|
||||
#define DIR_PURPOSE_UPLOAD_RENDDESC 9
|
||||
/** A connection to a directory server: upload a v3 networkstatus vote. */
|
||||
#define DIR_PURPOSE_UPLOAD_VOTE 10
|
||||
/** A connection to a directory server: fetch a v3 networkstatus vote. */
|
||||
#define DIR_PURPOSE_FETCH_VOTE 11
|
||||
/** A connection to a directory server: upload a v3 consensus signature */
|
||||
#define DIR_PURPOSE_UPLOAD_SIGNATURES 12
|
||||
#define DIR_PURPOSE_UPLOAD_SIGNATURES 11
|
||||
/** A connection to a directory server: download one or more network-status
|
||||
* objects */
|
||||
#define DIR_PURPOSE_FETCH_STATUS_VOTE 13
|
||||
#define DIR_PURPOSE_FETCH_STATUS_VOTE 12
|
||||
/** A connection to a directory server: download one or more network-status
|
||||
* objects */
|
||||
#define DIR_PURPOSE_FETCH_DETACHED_SIGNATURES 14
|
||||
#define DIR_PURPOSE_FETCH_DETACHED_SIGNATURES 13
|
||||
/** A connection to a directory server: download one or more network-status
|
||||
* objects */
|
||||
#define DIR_PURPOSE_FETCH_CONSENSUS 15
|
||||
#define DIR_PURPOSE_FETCH_CONSENSUS 14
|
||||
/** A connection to a directory server: download one or more network-status
|
||||
* objects */
|
||||
#define DIR_PURPOSE_FETCH_CERTIFICATE 16
|
||||
#define DIR_PURPOSE_FETCH_CERTIFICATE 15
|
||||
|
||||
/** Purpose for connection at a directory server. */
|
||||
#define DIR_PURPOSE_SERVER 17
|
||||
#define _DIR_PURPOSE_MAX 17
|
||||
#define DIR_PURPOSE_SERVER 16
|
||||
#define _DIR_PURPOSE_MAX 16
|
||||
|
||||
#define _EXIT_PURPOSE_MIN 1
|
||||
/** This exit stream wants to do an ordinary connect. */
|
||||
@ -1274,7 +1264,7 @@ typedef struct routerstatus_t {
|
||||
#define MAX_ROUTERDESC_DOWNLOAD_FAILURES 8
|
||||
|
||||
/** Contents of a v2 (non-consensus, non-vote) network status object. */
|
||||
typedef struct networkstatus_t {
|
||||
typedef struct networkstatus_v2_t {
|
||||
/** When did we receive the network-status document? */
|
||||
time_t received_on;
|
||||
|
||||
@ -1312,7 +1302,7 @@ typedef struct networkstatus_t {
|
||||
|
||||
smartlist_t *entries; /**< List of routerstatus_t*. This list is kept
|
||||
* sorted by identity_digest. */
|
||||
} networkstatus_t;
|
||||
} networkstatus_v2_t;
|
||||
|
||||
/** The claim about a single router, make in a vote. */
|
||||
typedef struct vote_routerstatus_t {
|
||||
@ -1385,6 +1375,10 @@ typedef struct networkstatus_vote_t {
|
||||
* the elements are vote_routerstatus_t; for a consensus, the elements
|
||||
* are routerstatus_t. */
|
||||
smartlist_t *routerstatus_list;
|
||||
|
||||
/** If present, a map from descriptor digest to elements of
|
||||
* routerstatus_list. */
|
||||
digestmap_t *desc_digest_map;
|
||||
} networkstatus_vote_t;
|
||||
|
||||
/** A set of signatures for a networkstatus consensus. All fields are as for
|
||||
@ -1466,7 +1460,6 @@ typedef struct extend_info_t {
|
||||
* display. */
|
||||
char identity_digest[DIGEST_LEN]; /**< Hash of this router's identity key. */
|
||||
uint16_t port; /**< OR port. */
|
||||
// uint8_t router_purpose; /**< General, controller, or bridge. */
|
||||
uint32_t addr; /**< IP address in host order. */
|
||||
crypto_pk_env_t *onion_key; /**< Current onionskin key. */
|
||||
} extend_info_t;
|
||||
@ -2310,7 +2303,6 @@ extend_info_t *extend_info_alloc(const char *nickname, const char *digest,
|
||||
crypto_pk_env_t *onion_key,
|
||||
uint32_t addr, uint16_t port);
|
||||
extend_info_t *extend_info_from_router(routerinfo_t *r);
|
||||
//extend_info_t *extend_info_from_routerstatus(routerstatus_t *s);
|
||||
extend_info_t *extend_info_dup(extend_info_t *info);
|
||||
void extend_info_free(extend_info_t *info);
|
||||
routerinfo_t *build_state_get_exit_router(cpath_build_state_t *state);
|
||||
@ -3058,52 +3050,43 @@ typedef enum version_status_t {
|
||||
VS_NEW_IN_SERIES=3, /**< This version is newer than any recommended version
|
||||
* in its series, but later recommended versions exist.
|
||||
*/
|
||||
VS_UNRECOMMENDED=4 /**< This version is not recommended (general case). */
|
||||
VS_UNRECOMMENDED=4, /**< This version is not recommended (general case). */
|
||||
VS_UNKNOWN, /**< We have no idea. */
|
||||
} version_status_t;
|
||||
|
||||
typedef struct combined_version_status_t {
|
||||
/** How many networkstatuses claim to know about versions? */
|
||||
int n_versioning;
|
||||
/** What do the majority of networkstatuses believe about this version? */
|
||||
enum version_status_t consensus;
|
||||
/** How many networkstatuses constitute the majority? */
|
||||
int n_concurring;
|
||||
} combined_version_status_t;
|
||||
|
||||
void networkstatus_reset_warnings(void);
|
||||
int router_reload_networkstatus(void);
|
||||
void networkstatus_reset_download_failures(void);
|
||||
int router_reload_v2_networkstatus(void);
|
||||
int router_reload_consensus_networkstatus(void);
|
||||
void routerstatus_free(routerstatus_t *rs);
|
||||
void networkstatus_free(networkstatus_t *ns);
|
||||
void networkstatus_v2_free(networkstatus_v2_t *ns);
|
||||
char *networkstatus_get_cache_filename(const char *identity_digest);
|
||||
int router_set_networkstatus(const char *s, time_t arrived_at,
|
||||
int router_set_networkstatus_v2(const char *s, time_t arrived_at,
|
||||
networkstatus_source_t source,
|
||||
smartlist_t *requested_fingerprints);
|
||||
void networkstatus_list_clean(time_t now);
|
||||
routerstatus_t *networkstatus_find_entry(networkstatus_t *ns,
|
||||
void networkstatus_v2_list_clean(time_t now);
|
||||
routerstatus_t *networkstatus_v2_find_entry(networkstatus_v2_t *ns,
|
||||
const char *digest);
|
||||
routerstatus_t *networkstatus_vote_find_entry(networkstatus_vote_t *ns,
|
||||
const char *digest);
|
||||
const smartlist_t *networkstatus_get_v2_list(void);
|
||||
const smartlist_t *networkstatus_get_all_statuses(void);
|
||||
routerstatus_t *router_get_combined_status_by_digest(const char *digest);
|
||||
routerstatus_t *router_get_combined_status_by_descriptor_digest(const char *d);
|
||||
routerstatus_t *router_get_combined_status_by_nickname(const char *nickname,
|
||||
download_status_t *router_get_dl_status_by_descriptor_digest(const char *d);
|
||||
routerstatus_t *router_get_consensus_status_by_id(const char *digest);
|
||||
routerstatus_t *router_get_consensus_status_by_descriptor_digest(
|
||||
const char *digest);
|
||||
routerstatus_t *router_get_consensus_status_by_nickname(const char *nickname,
|
||||
int warn_if_unnamed);
|
||||
const char *networkstatus_get_router_digest_by_nickname(const char *nickname);
|
||||
routerstatus_t *routerstatus_get_by_hexdigest(const char *hexdigest);
|
||||
void networkstatus_consensus_download_failed(int status_code);
|
||||
int should_delay_dir_fetches(or_options_t *options);
|
||||
void update_networkstatus_downloads(time_t now);
|
||||
networkstatus_t *networkstatus_get_by_digest(const char *digest);
|
||||
networkstatus_v2_t *networkstatus_v2_get_by_digest(const char *digest);
|
||||
networkstatus_vote_t *networkstatus_get_latest_consensus(void);
|
||||
networkstatus_vote_t *networkstatus_get_live_consensus(time_t now);
|
||||
int networkstatus_set_current_consensus(const char *consensus, int from_cache,
|
||||
int was_waiting_for_certs);
|
||||
void networkstatus_note_certs_arrived(void);
|
||||
void routers_update_all_from_networkstatus(time_t now);
|
||||
void networkstatus_list_update_recent(time_t now);
|
||||
void routerstatus_list_update_from_networkstatus(time_t now);
|
||||
void routers_update_status_from_networkstatus(smartlist_t *routers,
|
||||
int reset_failures);
|
||||
void routerstatus_list_update_from_consensus_networkstatus(time_t now);
|
||||
void routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
|
||||
int reset_failures);
|
||||
@ -3628,9 +3611,6 @@ void add_trusted_dir_server(const char *nickname, const char *address,
|
||||
authority_type_t type);
|
||||
void clear_trusted_dir_servers(void);
|
||||
int any_trusted_dir_is_v1_authority(void);
|
||||
char *compute_recommended_versions(time_t now, int client,
|
||||
const char *my_version,
|
||||
combined_version_status_t *status_out);
|
||||
void update_router_descriptor_downloads(time_t now);
|
||||
void update_extrainfo_downloads(time_t now);
|
||||
int router_have_minimum_dir_info(void);
|
||||
@ -3695,7 +3675,6 @@ addr_policy_t *router_parse_addr_policy_from_string(const char *s,
|
||||
int assume_action);
|
||||
version_status_t tor_version_is_obsolete(const char *myversion,
|
||||
const char *versionlist);
|
||||
version_status_t version_status_join(version_status_t a, version_status_t b);
|
||||
int tor_version_parse(const char *s, tor_version_t *out);
|
||||
int tor_version_as_new_as(const char *platform, const char *cutoff);
|
||||
int tor_version_compare(tor_version_t *a, tor_version_t *b);
|
||||
@ -3703,7 +3682,7 @@ void sort_version_list(smartlist_t *lst, int remove_duplicates);
|
||||
void assert_addr_policy_ok(addr_policy_t *t);
|
||||
void dump_distinct_digest_count(int severity);
|
||||
|
||||
networkstatus_t *networkstatus_parse_from_string(const char *s);
|
||||
networkstatus_v2_t *networkstatus_v2_parse_from_string(const char *s);
|
||||
networkstatus_vote_t *networkstatus_parse_vote_from_string(const char *s,
|
||||
const char **eos_out,
|
||||
int is_vote);
|
||||
|
@ -468,6 +468,7 @@ router_rebuild_store(int force, desc_store_t *store)
|
||||
int r = -1;
|
||||
off_t offset = 0;
|
||||
smartlist_t *signed_descriptors = NULL;
|
||||
int nocache=0;
|
||||
|
||||
if (!force && !router_should_rebuild_store(store))
|
||||
return 0;
|
||||
@ -506,11 +507,9 @@ router_rebuild_store(int force, desc_store_t *store)
|
||||
}
|
||||
} else {
|
||||
SMARTLIST_FOREACH(routerlist->old_routers, signed_descriptor_t *, sd,
|
||||
if (desc_get_store(routerlist, sd) == store)
|
||||
smartlist_add(signed_descriptors, sd));
|
||||
smartlist_add(signed_descriptors, sd));
|
||||
SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri,
|
||||
if (router_get_store(routerlist, ri) == store)
|
||||
smartlist_add(signed_descriptors, &ri->cache_info));
|
||||
smartlist_add(signed_descriptors, &ri->cache_info));
|
||||
}
|
||||
|
||||
smartlist_sort(signed_descriptors, _compare_signed_descriptors_by_age);
|
||||
@ -524,8 +523,10 @@ router_rebuild_store(int force, desc_store_t *store)
|
||||
log_warn(LD_BUG, "No descriptor available for router.");
|
||||
goto done;
|
||||
}
|
||||
if (sd->do_not_cache)
|
||||
if (sd->do_not_cache) {
|
||||
++nocache;
|
||||
continue;
|
||||
}
|
||||
c = tor_malloc(sizeof(sized_chunk_t));
|
||||
c->bytes = body;
|
||||
c->len = sd->signed_descriptor_len + sd->annotations_len;
|
||||
@ -549,8 +550,10 @@ router_rebuild_store(int force, desc_store_t *store)
|
||||
}
|
||||
|
||||
store->mmap = tor_mmap_file(fname);
|
||||
if (! store->mmap)
|
||||
if (! store->mmap) {
|
||||
log_warn(LD_FS, "Unable to mmap new descriptor file at '%s'.",fname);
|
||||
//tor_assert(0);
|
||||
}
|
||||
|
||||
log_info(LD_DIR, "Reconstructing pointers into cache");
|
||||
|
||||
@ -688,8 +691,6 @@ router_reload_router_list(void)
|
||||
return -1;
|
||||
if (router_reload_router_list_impl(&rl->extrainfo_store))
|
||||
return -1;
|
||||
if (trusted_dirs_reload_certs())
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -844,7 +845,10 @@ router_pick_directory_server_impl(int requireother, int fascistfirewall,
|
||||
smartlist_t *trusted_direct, *trusted_tunnel;
|
||||
smartlist_t *overloaded_direct, *overloaded_tunnel;
|
||||
time_t now = time(NULL);
|
||||
const smartlist_t *routerstatus_list = networkstatus_get_all_statuses();
|
||||
const networkstatus_vote_t *consensus = networkstatus_get_latest_consensus();
|
||||
|
||||
if (!consensus)
|
||||
return NULL;
|
||||
|
||||
direct = smartlist_create();
|
||||
tunnel = smartlist_create();
|
||||
@ -854,7 +858,7 @@ router_pick_directory_server_impl(int requireother, int fascistfirewall,
|
||||
overloaded_tunnel = smartlist_create();
|
||||
|
||||
/* Find all the running dirservers we know about. */
|
||||
SMARTLIST_FOREACH(routerstatus_list, routerstatus_t *, status,
|
||||
SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, status,
|
||||
{
|
||||
int is_trusted;
|
||||
int is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now;
|
||||
@ -997,7 +1001,7 @@ mark_all_trusteddirservers_up(void)
|
||||
routerstatus_t *rs;
|
||||
dir->is_running = 1;
|
||||
download_status_reset(&dir->v2_ns_dl_status);
|
||||
rs = router_get_combined_status_by_digest(dir->digest);
|
||||
rs = router_get_consensus_status_by_id(dir->digest);
|
||||
if (rs && !rs->is_running) {
|
||||
rs->is_running = 1;
|
||||
rs->last_dir_503_at = 0;
|
||||
@ -1147,7 +1151,7 @@ add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
|
||||
if (!must_be_running || router->is_running) {
|
||||
smartlist_add(sl,router);
|
||||
}
|
||||
} else if (!router_get_combined_status_by_nickname(nick,1)) {
|
||||
} else if (!router_get_consensus_status_by_nickname(nick,1)) {
|
||||
if (!warned) {
|
||||
log_fn(have_dir_info ? LOG_WARN : LOG_INFO, LD_CONFIG,
|
||||
"Nickname list includes '%s' which isn't a known router.",nick);
|
||||
@ -1714,6 +1718,8 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
|
||||
return rimap_get(routerlist->identity_map, named_digest);
|
||||
}
|
||||
|
||||
/* If we reach this point, there's no canonical value for the nickname. */
|
||||
|
||||
SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
|
||||
{
|
||||
if (!strcasecmp(router->nickname, nickname)) {
|
||||
@ -1742,7 +1748,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
|
||||
char fp[HEX_DIGEST_LEN+1];
|
||||
if (strcasecmp(router->nickname, nickname))
|
||||
continue;
|
||||
rs = router_get_combined_status_by_digest(
|
||||
rs = router_get_consensus_status_by_id(
|
||||
router->cache_info.identity_digest);
|
||||
if (rs && !rs->name_lookup_warned) {
|
||||
rs->name_lookup_warned = 1;
|
||||
@ -1768,7 +1774,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
|
||||
SMARTLIST_FOREACH(fps, char *, cp, tor_free(cp));
|
||||
smartlist_free(fps);
|
||||
} else if (warn_if_unnamed) {
|
||||
routerstatus_t *rs = router_get_combined_status_by_digest(
|
||||
routerstatus_t *rs = router_get_consensus_status_by_id(
|
||||
best_match->cache_info.identity_digest);
|
||||
if (rs && !rs->name_lookup_warned) {
|
||||
char fp[HEX_DIGEST_LEN+1];
|
||||
@ -2134,15 +2140,6 @@ dump_routerlist_mem_usage(int severity)
|
||||
smartlist_len(routerlist->old_routers), U64_PRINTF_ARG(olddescs));
|
||||
}
|
||||
|
||||
/** Return the greatest number of routerdescs we'll hold for any given router.
|
||||
*/
|
||||
static int
|
||||
max_descriptors_per_router(void)
|
||||
{
|
||||
int n_authorities = get_n_v2_authorities();
|
||||
return (n_authorities < 5) ? 5 : n_authorities;
|
||||
}
|
||||
|
||||
/** Return non-zero if we have a lot of extra descriptors in our
|
||||
* routerlist, and should get rid of some of them. Else return 0.
|
||||
*
|
||||
@ -2154,8 +2151,12 @@ max_descriptors_per_router(void)
|
||||
static INLINE int
|
||||
routerlist_is_overfull(routerlist_t *rl)
|
||||
{
|
||||
return smartlist_len(rl->old_routers) >
|
||||
smartlist_len(rl->routers)*(max_descriptors_per_router()+1);
|
||||
/*XXXX020 no longer wholly logical.*/
|
||||
if (dirserver_mode(get_options())) {
|
||||
return smartlist_len(rl->old_routers) > smartlist_len(rl->routers)*5;
|
||||
} else {
|
||||
return smartlist_len(rl->old_routers) > smartlist_len(rl->routers)*2;
|
||||
}
|
||||
}
|
||||
|
||||
static INLINE int
|
||||
@ -2541,7 +2542,7 @@ router_set_status(const char *digest, int up)
|
||||
"addresses reachable?");
|
||||
router->is_running = up;
|
||||
}
|
||||
status = router_get_combined_status_by_digest(digest);
|
||||
status = router_get_consensus_status_by_id(digest);
|
||||
if (status && status->is_running != up) {
|
||||
status->is_running = up;
|
||||
control_event_networkstatus_changed_single(status);
|
||||
@ -2574,8 +2575,8 @@ router_set_status(const char *digest, int up)
|
||||
* server or via the controller.)
|
||||
*
|
||||
* This function should be called *after*
|
||||
* routers_update_status_from_networkstatus; subsequently, you should call
|
||||
* router_rebuild_store and routerlist_descriptors_added.
|
||||
* routers_update_status_from_consensus_networkstatus; subsequently, you
|
||||
* should call router_rebuild_store and routerlist_descriptors_added.
|
||||
*/
|
||||
int
|
||||
router_add_to_routerlist(routerinfo_t *router, const char **msg,
|
||||
@ -2590,7 +2591,9 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
|
||||
int authdir_may_warn_about_unreachable_server =
|
||||
authdir && !from_cache && !from_fetch &&
|
||||
router_have_minimum_dir_info();
|
||||
const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
|
||||
networkstatus_vote_t *consensus = networkstatus_get_latest_consensus();
|
||||
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
|
||||
int in_consensus = 0;
|
||||
|
||||
tor_assert(msg);
|
||||
|
||||
@ -2644,15 +2647,37 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
|
||||
}
|
||||
|
||||
/* We no longer need a router with this descriptor digest. */
|
||||
SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
|
||||
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
|
||||
{
|
||||
routerstatus_t *rs =
|
||||
networkstatus_find_entry(ns, router->cache_info.identity_digest);
|
||||
networkstatus_v2_find_entry(ns, router->cache_info.identity_digest);
|
||||
if (rs && !memcmp(rs->descriptor_digest,
|
||||
router->cache_info.signed_descriptor_digest,
|
||||
DIGEST_LEN))
|
||||
rs->need_to_mirror = 0;
|
||||
});
|
||||
if (consensus) {
|
||||
routerstatus_t *rs = networkstatus_vote_find_entry(consensus,
|
||||
router->cache_info.identity_digest);
|
||||
if (rs && !memcmp(rs->descriptor_digest,
|
||||
router->cache_info.signed_descriptor_digest,
|
||||
DIGEST_LEN)) {
|
||||
in_consensus = 1;
|
||||
rs->need_to_mirror = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*XXXX020 I had suspicions about whether this was correct, but now I
|
||||
* can't remember why. :( -NM */
|
||||
if (consensus && !in_consensus && !authdir_mode(get_options())) {
|
||||
/* If it's not listed in the consensus, then don't consider replacing
|
||||
* the latest router with it. */
|
||||
if (!from_cache && should_cache_old_descriptors())
|
||||
signed_desc_append_to_journal(&router->cache_info,
|
||||
router_get_store(routerlist, router));
|
||||
routerlist_insert_old(routerlist, router);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* If we have a router with the same identity key, choose the newer one. */
|
||||
old_router = rimap_get(routerlist->identity_map,
|
||||
@ -2802,7 +2827,7 @@ routerlist_remove_old_cached_routers_with_id(time_t cutoff, int lo, int hi,
|
||||
|
||||
/* Check whether we need to do anything at all. */
|
||||
{
|
||||
int mdpr = max_descriptors_per_router();
|
||||
int mdpr = dirserver_mode(get_options()) ? 5 : 2;
|
||||
if (n <= mdpr)
|
||||
return;
|
||||
n_extra = n - mdpr;
|
||||
@ -2874,11 +2899,13 @@ routerlist_remove_old_routers(void)
|
||||
routerinfo_t *router;
|
||||
signed_descriptor_t *sd;
|
||||
digestmap_t *retain;
|
||||
const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
|
||||
int dirserv = dirserver_mode(get_options());
|
||||
const networkstatus_vote_t *consensus = networkstatus_get_latest_consensus();
|
||||
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
|
||||
|
||||
trusted_dirs_remove_old_certs();
|
||||
|
||||
if (!routerlist || !networkstatus_list)
|
||||
if (!routerlist || !consensus)
|
||||
return;
|
||||
|
||||
routerlist_assert_ok(routerlist);
|
||||
@ -2886,7 +2913,8 @@ routerlist_remove_old_routers(void)
|
||||
retain = digestmap_new();
|
||||
cutoff = now - OLD_ROUTER_DESC_MAX_AGE;
|
||||
/* Build a list of all the descriptors that _anybody_ lists. */
|
||||
SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
|
||||
if (dirserv) {
|
||||
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
|
||||
{
|
||||
/* XXXX The inner loop here gets pretty expensive, and actually shows up
|
||||
* on some profiles. It may be the reason digestmap_set shows up in
|
||||
@ -2900,22 +2928,21 @@ routerlist_remove_old_routers(void)
|
||||
if (rs->published_on >= cutoff)
|
||||
digestmap_set(retain, rs->descriptor_digest, (void*)1));
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
/* Retain anything listed in the consensus. */
|
||||
networkstatus_vote_t *ns = networkstatus_get_latest_consensus();
|
||||
if (ns) {
|
||||
SMARTLIST_FOREACH(ns->routerstatus_list, routerstatus_t *, rs,
|
||||
/* Retain anything listed in the consensus. */
|
||||
if (consensus) {
|
||||
SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs,
|
||||
if (rs->published_on >= cutoff)
|
||||
digestmap_set(retain, rs->descriptor_digest, (void*)1));
|
||||
}
|
||||
}
|
||||
|
||||
/* If we have a bunch of networkstatuses, we should consider pruning current
|
||||
* routers that are too old and that nobody recommends. (If we don't have
|
||||
* enough networkstatuses, then we should get more before we decide to kill
|
||||
* routers.) */
|
||||
if (smartlist_len(networkstatus_list) > get_n_v2_authorities() / 2) {
|
||||
if (!dirserv ||
|
||||
smartlist_len(networkstatus_v2_list) > get_n_v2_authorities() / 2) {
|
||||
cutoff = now - ROUTER_MAX_AGE;
|
||||
/* Remove too-old unrecommended members of routerlist->routers. */
|
||||
for (i = 0; i < smartlist_len(routerlist->routers); ++i) {
|
||||
@ -2955,7 +2982,7 @@ routerlist_remove_old_routers(void)
|
||||
* total number doesn't approach max_descriptors_per_router()*len(router).
|
||||
*/
|
||||
if (smartlist_len(routerlist->old_routers) <
|
||||
smartlist_len(routerlist->routers) * (max_descriptors_per_router() - 1))
|
||||
smartlist_len(routerlist->routers) * (dirserver_mode(get_options())?4:2))
|
||||
goto done;
|
||||
|
||||
smartlist_sort(routerlist->old_routers, _compare_old_routers_by_identity);
|
||||
@ -3040,7 +3067,7 @@ router_load_single_router(const char *s, uint8_t purpose, int cache,
|
||||
|
||||
lst = smartlist_create();
|
||||
smartlist_add(lst, ri);
|
||||
routers_update_status_from_networkstatus(lst, 0);
|
||||
routers_update_status_from_consensus_networkstatus(lst, 0);
|
||||
|
||||
if ((r=router_add_to_routerlist(ri, msg, 0, 0))<0) {
|
||||
/* we've already assigned to *msg now, and ri is already freed */
|
||||
@ -3086,7 +3113,7 @@ router_load_routers_from_string(const char *s, const char *eos,
|
||||
router_parse_list_from_string(&s, eos, routers, saved_location, 0,
|
||||
allow_annotations, prepend_annotations);
|
||||
|
||||
routers_update_status_from_networkstatus(routers, !from_cache);
|
||||
routers_update_status_from_consensus_networkstatus(routers, !from_cache);
|
||||
|
||||
log_info(LD_DIR, "%d elements to add", smartlist_len(routers));
|
||||
|
||||
@ -3171,16 +3198,26 @@ static int
|
||||
signed_desc_digest_is_recognized(signed_descriptor_t *desc)
|
||||
{
|
||||
routerstatus_t *rs;
|
||||
const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
|
||||
networkstatus_vote_t *consensus = networkstatus_get_latest_consensus();
|
||||
int dirserv = dirserver_mode(get_options());
|
||||
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
|
||||
|
||||
SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
|
||||
{
|
||||
if (!(rs = networkstatus_find_entry(ns, desc->identity_digest)))
|
||||
continue;
|
||||
if (!memcmp(rs->descriptor_digest,
|
||||
desc->signed_descriptor_digest, DIGEST_LEN))
|
||||
if (consensus) {
|
||||
rs = networkstatus_vote_find_entry(consensus, desc->identity_digest);
|
||||
if (rs && !memcmp(rs->descriptor_digest,
|
||||
desc->signed_descriptor_digest, DIGEST_LEN))
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
if (dirserv && networkstatus_v2_list) {
|
||||
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
|
||||
{
|
||||
if (!(rs = networkstatus_v2_find_entry(ns, desc->identity_digest)))
|
||||
continue;
|
||||
if (!memcmp(rs->descriptor_digest,
|
||||
desc->signed_descriptor_digest, DIGEST_LEN))
|
||||
return 1;
|
||||
});
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -3336,103 +3373,6 @@ any_trusted_dir_is_v1_authority(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Return a newly allocated string naming the versions of Tor recommended by
|
||||
* more than half the versioning networkstatuses. */
|
||||
char *
|
||||
compute_recommended_versions(time_t now, int client,
|
||||
const char *my_version,
|
||||
combined_version_status_t *status_out)
|
||||
{
|
||||
int n_seen;
|
||||
char *current;
|
||||
smartlist_t *combined, *recommended;
|
||||
int n_versioning, n_recommending;
|
||||
char *result;
|
||||
/** holds the compromise status taken among all non-recommending
|
||||
* authorities */
|
||||
version_status_t consensus = VS_RECOMMENDED;
|
||||
const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
|
||||
(void) now; /* right now, we consider *all* statuses, regardless of age. */
|
||||
|
||||
tor_assert(my_version);
|
||||
tor_assert(status_out);
|
||||
|
||||
memset(status_out, 0, sizeof(combined_version_status_t));
|
||||
|
||||
if (!networkstatus_list)
|
||||
return tor_strdup("<none>");
|
||||
|
||||
combined = smartlist_create();
|
||||
n_versioning = n_recommending = 0;
|
||||
SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
|
||||
{
|
||||
const char *vers;
|
||||
smartlist_t *versions;
|
||||
version_status_t status;
|
||||
if (! ns->recommends_versions)
|
||||
continue;
|
||||
n_versioning++;
|
||||
vers = client ? ns->client_versions : ns->server_versions;
|
||||
if (!vers)
|
||||
continue;
|
||||
versions = smartlist_create();
|
||||
smartlist_split_string(versions, vers, ",",
|
||||
SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
|
||||
sort_version_list(versions, 1);
|
||||
smartlist_add_all(combined, versions);
|
||||
smartlist_free(versions);
|
||||
|
||||
/* now, check _our_ version */
|
||||
status = tor_version_is_obsolete(my_version, vers);
|
||||
if (status == VS_RECOMMENDED)
|
||||
n_recommending++;
|
||||
consensus = version_status_join(status, consensus);
|
||||
});
|
||||
|
||||
sort_version_list(combined, 0);
|
||||
|
||||
current = NULL;
|
||||
n_seen = 0;
|
||||
recommended = smartlist_create();
|
||||
SMARTLIST_FOREACH(combined, char *, cp,
|
||||
{
|
||||
if (current && !strcmp(cp, current)) {
|
||||
++n_seen;
|
||||
} else {
|
||||
if (current)
|
||||
log_info(LD_DIR,"version %s is recommended by %d authorities",
|
||||
current, n_seen);
|
||||
if (n_seen > n_versioning/2 && current) {
|
||||
smartlist_add(recommended, current);
|
||||
}
|
||||
n_seen = 1;
|
||||
current = cp;
|
||||
}
|
||||
});
|
||||
if (current)
|
||||
log_info(LD_DIR,"version %s is recommended by %d authorities",
|
||||
current, n_seen);
|
||||
if (n_seen > n_versioning/2 && current)
|
||||
smartlist_add(recommended, current);
|
||||
|
||||
result = smartlist_join_strings(recommended, ", ", 0, NULL);
|
||||
|
||||
SMARTLIST_FOREACH(combined, char *, cp, tor_free(cp));
|
||||
smartlist_free(combined);
|
||||
smartlist_free(recommended);
|
||||
|
||||
status_out->n_versioning = n_versioning;
|
||||
if (n_recommending > n_versioning/2) {
|
||||
status_out->consensus = VS_RECOMMENDED;
|
||||
status_out->n_concurring = n_recommending;
|
||||
} else {
|
||||
status_out->consensus = consensus;
|
||||
status_out->n_concurring = n_versioning - n_recommending;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
static void
|
||||
list_pending_downloads(digestmap_t *result,
|
||||
@ -3541,128 +3481,26 @@ client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options)
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Return new list of ID fingerprints for routers that we (as a client) would
|
||||
* like to download.
|
||||
/** 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
|
||||
* 4058/41 (40 for the hash and 1 for the + that separates them) => 98
|
||||
* So use 96 because it's a nice number.
|
||||
*/
|
||||
static smartlist_t *
|
||||
router_list_client_downloadable(void)
|
||||
{
|
||||
int n_downloadable = 0;
|
||||
smartlist_t *downloadable = smartlist_create();
|
||||
digestmap_t *downloading;
|
||||
time_t now = time(NULL);
|
||||
/* these are just used for logging */
|
||||
int n_not_ready = 0, n_in_progress = 0, n_uptodate = 0, n_wouldnt_use = 0;
|
||||
or_options_t *options = get_options();
|
||||
const smartlist_t *routerstatus_list = networkstatus_get_all_statuses();
|
||||
|
||||
if (!smartlist_len(routerstatus_list))
|
||||
return downloadable;
|
||||
|
||||
downloading = digestmap_new();
|
||||
list_pending_descriptor_downloads(downloading, 0);
|
||||
|
||||
routerstatus_list_update_from_networkstatus(now);
|
||||
SMARTLIST_FOREACH(routerstatus_list, routerstatus_t *, rs,
|
||||
{
|
||||
routerinfo_t *ri;
|
||||
if (router_get_by_descriptor_digest(rs->descriptor_digest)) {
|
||||
/* We have the 'best' descriptor for this router. */
|
||||
++n_uptodate;
|
||||
} else if (!client_would_use_router(rs, now, options)) {
|
||||
/* We wouldn't want this descriptor even if we got it. */
|
||||
++n_wouldnt_use;
|
||||
} else if (digestmap_get(downloading, rs->descriptor_digest)) {
|
||||
/* We're downloading this one now. */
|
||||
++n_in_progress;
|
||||
} else if ((ri = router_get_by_digest(rs->identity_digest)) &&
|
||||
ri->cache_info.published_on > rs->published_on) {
|
||||
/* Oddly, we have a descriptor more recent than the 'best' one, but it
|
||||
was once best. So that's okay. */
|
||||
++n_uptodate;
|
||||
} else if (!download_status_is_ready(&rs->dl_status, now,
|
||||
MAX_ROUTERDESC_DOWNLOAD_FAILURES)) {
|
||||
/* We failed too recently to try again. */
|
||||
++n_not_ready;
|
||||
} else {
|
||||
/* Okay, time to try it. */
|
||||
smartlist_add(downloadable, rs->descriptor_digest);
|
||||
++n_downloadable;
|
||||
}
|
||||
});
|
||||
|
||||
#if 0
|
||||
log_info(LD_DIR,
|
||||
"%d router descriptors are downloadable. "
|
||||
"%d are in progress. %d are up-to-date. "
|
||||
"%d are non-useful. %d failed too recently to retry.",
|
||||
n_downloadable, n_in_progress, n_uptodate,
|
||||
n_wouldnt_use, n_not_ready);
|
||||
#endif
|
||||
|
||||
digestmap_free(downloading, NULL);
|
||||
return downloadable;
|
||||
}
|
||||
|
||||
/** Initiate new router downloads as needed, using the strategy for
|
||||
* non-directory-servers.
|
||||
*
|
||||
* We don't launch any downloads if there are fewer than MAX_DL_TO_DELAY
|
||||
* descriptors to get and less than MAX_CLIENT_INTERVAL_WITHOUT_REQUEST
|
||||
* seconds have passed.
|
||||
*
|
||||
* Otherwise, we ask for all descriptors that we think are different from what
|
||||
* we have, and that we don't currently have an in-progress download attempt
|
||||
* for. */
|
||||
static void
|
||||
update_router_descriptor_client_downloads(time_t now)
|
||||
{
|
||||
/** 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
|
||||
* 4058/41 (40 for the hash and 1 for the + that separates them) => 98
|
||||
* So use 96 because it's a nice number.
|
||||
*/
|
||||
#define MAX_DL_PER_REQUEST 96
|
||||
/** Don't split our requests so finely that we are requesting fewer than
|
||||
* this number per server. */
|
||||
/** Don't split our requests so finely that we are requesting fewer than
|
||||
* this number per server. */
|
||||
#define MIN_DL_PER_REQUEST 4
|
||||
/** To prevent a single screwy cache from confusing us by selective reply,
|
||||
* try to split our requests into at least this this many requests. */
|
||||
/** To prevent a single screwy cache from confusing us by selective reply,
|
||||
* try to split our requests into at least this this many requests. */
|
||||
#define MIN_REQUESTS 3
|
||||
/** If we want fewer than this many descriptors, wait until we
|
||||
* want more, or until MAX_CLIENT_INTERVAL_WITHOUT_REQUEST has
|
||||
* passed. */
|
||||
/** If we want fewer than this many descriptors, wait until we
|
||||
* want more, or until MAX_CLIENT_INTERVAL_WITHOUT_REQUEST has
|
||||
* passed. */
|
||||
#define MAX_DL_TO_DELAY 16
|
||||
/** When directory clients have only a few servers to request, they batch
|
||||
* them until they have more, or until this amount of time has passed. */
|
||||
/** When directory clients have only a few servers to request, they batch
|
||||
* them until they have more, or until this amount of time has passed. */
|
||||
#define MAX_CLIENT_INTERVAL_WITHOUT_REQUEST (10*60)
|
||||
smartlist_t *downloadable = NULL;
|
||||
or_options_t *options = get_options();
|
||||
const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
|
||||
|
||||
if (dirserver_mode(options)) {
|
||||
log_warn(LD_BUG,
|
||||
"Called router_descriptor_client_downloads() on a dir mirror?");
|
||||
}
|
||||
|
||||
if (rep_hist_circbuilding_dormant(now)) {
|
||||
// log_info(LD_CIRC, "Skipping descriptor downloads: we haven't needed "
|
||||
// "any circuits lately.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (networkstatus_list &&
|
||||
smartlist_len(networkstatus_list) <= get_n_v2_authorities()/2) {
|
||||
log_info(LD_DIR,
|
||||
"Not enough networkstatus documents to launch requests.");
|
||||
return;
|
||||
}
|
||||
|
||||
downloadable = router_list_client_downloadable();
|
||||
launch_router_descriptor_downloads(downloadable, now);
|
||||
smartlist_free(downloadable);
|
||||
}
|
||||
|
||||
/** DOCDOC */
|
||||
static void
|
||||
@ -3734,18 +3572,18 @@ update_router_descriptor_cache_downloads(time_t now)
|
||||
int i, j, n;
|
||||
int n_download;
|
||||
or_options_t *options = get_options();
|
||||
const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
|
||||
const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
|
||||
|
||||
if (! dirserver_mode(options)) {
|
||||
log_warn(LD_BUG, "Called update_router_descriptor_cache_downloads() "
|
||||
"on a non-dir-mirror?");
|
||||
}
|
||||
|
||||
if (!networkstatus_list || !smartlist_len(networkstatus_list))
|
||||
if (!networkstatus_v2_list || !smartlist_len(networkstatus_v2_list))
|
||||
return;
|
||||
|
||||
map = digestmap_new();
|
||||
n = smartlist_len(networkstatus_list);
|
||||
n = smartlist_len(networkstatus_v2_list);
|
||||
|
||||
downloadable = tor_malloc_zero(sizeof(smartlist_t*) * n);
|
||||
download_from = tor_malloc_zero(sizeof(smartlist_t*) * n);
|
||||
@ -3760,7 +3598,7 @@ update_router_descriptor_cache_downloads(time_t now)
|
||||
* descriptor from the corresponding authority.
|
||||
*/
|
||||
n_download = 0;
|
||||
SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
|
||||
SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
|
||||
{
|
||||
trusted_dir_server_t *ds;
|
||||
smartlist_t *dl;
|
||||
@ -3837,7 +3675,7 @@ update_router_descriptor_cache_downloads(time_t now)
|
||||
|
||||
/* Now, we can actually launch our requests. */
|
||||
for (i=0; i<n; ++i) {
|
||||
networkstatus_t *ns = smartlist_get(networkstatus_list, i);
|
||||
networkstatus_v2_t *ns = smartlist_get(networkstatus_v2_list, i);
|
||||
trusted_dir_server_t *ds =
|
||||
router_get_trusteddirserver_by_digest(ns->identity_digest);
|
||||
smartlist_t *dl = download_from[i];
|
||||
@ -3874,7 +3712,7 @@ update_consensus_router_descriptor_downloads(time_t now)
|
||||
smartlist_t *downloadable = smartlist_create();
|
||||
int authdir = authdir_mode(options);
|
||||
int dirserver = dirserver_mode(options);
|
||||
networkstatus_vote_t *consensus = networkstatus_get_latest_consensus();
|
||||
networkstatus_vote_t *consensus = networkstatus_get_live_consensus(now);
|
||||
|
||||
if (!dirserver) {
|
||||
if (rep_hist_circbuilding_dormant(now))
|
||||
@ -3887,17 +3725,9 @@ update_consensus_router_descriptor_downloads(time_t now)
|
||||
list_pending_descriptor_downloads(map, 0);
|
||||
SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs,
|
||||
{
|
||||
routerstatus_t *lrs;
|
||||
if (router_get_by_descriptor_digest(rs->descriptor_digest))
|
||||
continue; /* We have it already. */
|
||||
|
||||
/* XXXX020 change this once the real consensus is the canonical place
|
||||
* to go for router information. */
|
||||
lrs = router_get_combined_status_by_digest(rs->identity_digest);
|
||||
if (!lrs ||
|
||||
memcmp(lrs->descriptor_digest, rs->descriptor_digest, DIGEST_LEN))
|
||||
lrs = rs;
|
||||
if (!download_status_is_ready(&lrs->dl_status, now,
|
||||
if (!download_status_is_ready(&rs->dl_status, now,
|
||||
MAX_ROUTERDESC_DOWNLOAD_FAILURES))
|
||||
continue;
|
||||
|
||||
@ -3925,10 +3755,8 @@ update_router_descriptor_downloads(time_t now)
|
||||
return;
|
||||
if (dirserver_mode(options)) {
|
||||
update_router_descriptor_cache_downloads(now);
|
||||
update_consensus_router_descriptor_downloads(now); /*XXXX020 clients too*/
|
||||
} else {
|
||||
update_router_descriptor_client_downloads(now);
|
||||
}
|
||||
update_consensus_router_descriptor_downloads(now);
|
||||
}
|
||||
|
||||
/** Return true iff <b>sd</b> is the descriptor for a router descriptor that
|
||||
@ -3990,19 +3818,6 @@ update_extrainfo_downloads(time_t now)
|
||||
smartlist_free(wanted);
|
||||
}
|
||||
|
||||
/** Return the number of routerstatus_t in <b>entries</b> that we'd actually
|
||||
* use. */
|
||||
static int
|
||||
routerstatus_count_usable_entries(smartlist_t *entries)
|
||||
{
|
||||
int count = 0;
|
||||
time_t now = time(NULL);
|
||||
or_options_t *options = get_options();
|
||||
SMARTLIST_FOREACH(entries, routerstatus_t *, rs,
|
||||
if (client_would_use_router(rs, now, options)) count++);
|
||||
return count;
|
||||
}
|
||||
|
||||
/** 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;
|
||||
@ -4041,20 +3856,18 @@ router_dir_info_changed(void)
|
||||
static void
|
||||
update_router_have_minimum_dir_info(void)
|
||||
{
|
||||
int tot = 0, num_running = 0;
|
||||
int n_ns, n_authorities, res, avg;
|
||||
/*XXX020 call when dirserver_mode() changes. */
|
||||
int num_present = 0, num_usable=0;
|
||||
time_t now = time(NULL);
|
||||
const smartlist_t *routerstatus_list = networkstatus_get_all_statuses();
|
||||
const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
|
||||
int res;
|
||||
or_options_t *options = get_options();
|
||||
const networkstatus_vote_t *consensus =
|
||||
networkstatus_get_live_consensus(now);
|
||||
|
||||
if (!routerlist) {
|
||||
if (!consensus) {
|
||||
res = 0;
|
||||
goto done;
|
||||
}
|
||||
/*XXXX020 remove this call. routerlist_remove_old_routers shows up in some
|
||||
* profiles, and this is the biggest caller of that function. */
|
||||
routerlist_remove_old_routers();
|
||||
networkstatus_list_clean(now);
|
||||
|
||||
if (should_delay_dir_fetches(get_options())) {
|
||||
log_notice(LD_DIR, "no known bridge descriptors running yet; stalling");
|
||||
@ -4062,24 +3875,17 @@ update_router_have_minimum_dir_info(void)
|
||||
goto done;
|
||||
}
|
||||
|
||||
n_authorities = get_n_v2_authorities();
|
||||
n_ns = smartlist_len(networkstatus_list);
|
||||
if (n_ns<=n_authorities/2) {
|
||||
log_info(LD_DIR,
|
||||
"We have %d of %d network statuses, and we want "
|
||||
"more than %d.", n_ns, n_authorities, n_authorities/2);
|
||||
res = 0;
|
||||
goto done;
|
||||
}
|
||||
SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
|
||||
tot += routerstatus_count_usable_entries(ns->entries));
|
||||
avg = tot / n_ns;
|
||||
SMARTLIST_FOREACH(routerstatus_list, routerstatus_t *, rs,
|
||||
SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs,
|
||||
{
|
||||
if (rs->is_running)
|
||||
num_running++;
|
||||
if (client_would_use_router(rs, now, options)) {
|
||||
++num_usable;
|
||||
if (router_get_by_digest(rs->identity_digest)) {
|
||||
++num_present;
|
||||
}
|
||||
}
|
||||
});
|
||||
res = smartlist_len(routerlist->routers) >= (avg/4) && num_running > 2;
|
||||
res = num_present >= num_usable/4 && num_usable > 2;
|
||||
|
||||
done:
|
||||
if (res && !have_min_dir_info) {
|
||||
log(LOG_NOTICE, LD_DIR,
|
||||
@ -4089,7 +3895,7 @@ update_router_have_minimum_dir_info(void)
|
||||
if (!res && have_min_dir_info) {
|
||||
log(LOG_NOTICE, LD_DIR,"Our directory information is no longer up-to-date "
|
||||
"enough to build circuits.%s",
|
||||
num_running > 2 ? "" : " (Not enough servers seem reachable -- "
|
||||
num_usable > 2 ? "" : " (Not enough servers seem reachable -- "
|
||||
"is your network connection down?)");
|
||||
control_event_client_status(LOG_NOTICE, "NOT_ENOUGH_DIR_INFO");
|
||||
}
|
||||
@ -4102,18 +3908,7 @@ update_router_have_minimum_dir_info(void)
|
||||
void
|
||||
router_reset_descriptor_download_failures(void)
|
||||
{
|
||||
const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
|
||||
const smartlist_t *routerstatus_list = networkstatus_get_all_statuses();
|
||||
SMARTLIST_FOREACH(routerstatus_list, routerstatus_t *, rs,
|
||||
{
|
||||
download_status_reset(&rs->dl_status);
|
||||
});
|
||||
SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
|
||||
SMARTLIST_FOREACH(ns->entries, routerstatus_t *, rs,
|
||||
{
|
||||
if (!router_get_by_descriptor_digest(rs->descriptor_digest))
|
||||
rs->need_to_mirror = 1;
|
||||
}));
|
||||
networkstatus_reset_download_failures();
|
||||
last_routerdesc_download_attempted = 0;
|
||||
if (!routerlist)
|
||||
return;
|
||||
|
@ -564,36 +564,6 @@ tor_version_is_obsolete(const char *myversion, const char *versionlist)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** Return the combined status of the current version, given that we know of
|
||||
* one set of networkstatuses that give us status <b>a</b>, and another that
|
||||
* gives us status <b>b</b>.
|
||||
*
|
||||
* For example, if one authority thinks that we're NEW, and another thinks
|
||||
* we're OLD, we're simply UNRECOMMENDED.
|
||||
*
|
||||
* This function does not handle calculating whether we're RECOMMENDED; that
|
||||
* follows a simple majority rule. This function simply calculates *why*
|
||||
* we're not recommended (if we're not).
|
||||
*/
|
||||
version_status_t
|
||||
version_status_join(version_status_t a, version_status_t b)
|
||||
{
|
||||
if (a == b)
|
||||
return a;
|
||||
else if (a == VS_UNRECOMMENDED || b == VS_UNRECOMMENDED)
|
||||
return VS_UNRECOMMENDED;
|
||||
else if (a == VS_RECOMMENDED)
|
||||
return b;
|
||||
else if (b == VS_RECOMMENDED)
|
||||
return a;
|
||||
/* Okay. Neither is 'recommended' or 'unrecommended', and they differ. */
|
||||
else if (a == VS_OLD || b == VS_OLD)
|
||||
return VS_UNRECOMMENDED;
|
||||
/* One is VS_NEW, the other is VS_NEW_IN_SERIES */
|
||||
else
|
||||
return VS_NEW_IN_SERIES;
|
||||
}
|
||||
|
||||
/** Read a signed directory from <b>str</b>. If it's well-formed, return 0.
|
||||
* Otherwise, return -1. If we're a directory cache, cache it.
|
||||
*/
|
||||
@ -1722,13 +1692,13 @@ _free_duplicate_routerstatus_entry(void *e)
|
||||
* signature of the network status, but do not (yet) check the signing key for
|
||||
* authority.
|
||||
*/
|
||||
networkstatus_t *
|
||||
networkstatus_parse_from_string(const char *s)
|
||||
networkstatus_v2_t *
|
||||
networkstatus_v2_parse_from_string(const char *s)
|
||||
{
|
||||
const char *eos;
|
||||
smartlist_t *tokens = smartlist_create();
|
||||
smartlist_t *footer_tokens = smartlist_create();
|
||||
networkstatus_t *ns = NULL;
|
||||
networkstatus_v2_t *ns = NULL;
|
||||
char ns_digest[DIGEST_LEN];
|
||||
char tmp_digest[DIGEST_LEN];
|
||||
struct in_addr in;
|
||||
@ -1745,7 +1715,7 @@ networkstatus_parse_from_string(const char *s)
|
||||
log_warn(LD_DIR, "Error tokenizing network-status header.");
|
||||
goto err;
|
||||
}
|
||||
ns = tor_malloc_zero(sizeof(networkstatus_t));
|
||||
ns = tor_malloc_zero(sizeof(networkstatus_v2_t));
|
||||
memcpy(ns->networkstatus_digest, ns_digest, DIGEST_LEN);
|
||||
|
||||
tok = find_first_by_keyword(tokens, K_NETWORK_STATUS_VERSION);
|
||||
@ -1876,7 +1846,7 @@ networkstatus_parse_from_string(const char *s)
|
||||
goto done;
|
||||
err:
|
||||
if (ns)
|
||||
networkstatus_free(ns);
|
||||
networkstatus_v2_free(ns);
|
||||
ns = NULL;
|
||||
done:
|
||||
SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));
|
||||
|
Loading…
Reference in New Issue
Block a user