|
@@ -116,7 +116,8 @@ static void dir_routerdesc_download_failed(smartlist_t *failed,
|
|
|
int was_extrainfo,
|
|
|
int was_descriptor_digests);
|
|
|
static void dir_microdesc_download_failed(smartlist_t *failed,
|
|
|
- int status_code);
|
|
|
+ int status_code,
|
|
|
+ const char *dir_id);
|
|
|
static int client_likes_consensus(const struct consensus_cache_entry_t *ent,
|
|
|
const char *want_url);
|
|
|
|
|
@@ -469,7 +470,7 @@ directory_pick_generic_dirserver(dirinfo_type_t type, int pds_flags,
|
|
|
log_warn(LD_BUG, "Called when we have UseBridges set.");
|
|
|
|
|
|
if (should_use_directory_guards(options)) {
|
|
|
- const node_t *node = guards_choose_dirguard(guard_state_out);
|
|
|
+ const node_t *node = guards_choose_dirguard(dir_purpose, guard_state_out);
|
|
|
if (node)
|
|
|
rs = node->rs;
|
|
|
} else {
|
|
@@ -603,7 +604,7 @@ directory_get_from_dirserver,(
|
|
|
* sort of dir fetch we'll be doing, so it won't return a bridge
|
|
|
* that can't answer our question.
|
|
|
*/
|
|
|
- const node_t *node = guards_choose_dirguard(&guard_state);
|
|
|
+ const node_t *node = guards_choose_dirguard(dir_purpose, &guard_state);
|
|
|
if (node && node->ri) {
|
|
|
/* every bridge has a routerinfo. */
|
|
|
routerinfo_t *ri = node->ri;
|
|
@@ -2247,8 +2248,6 @@ static int handle_response_fetch_detached_signatures(dir_connection_t *,
|
|
|
const response_handler_args_t *);
|
|
|
static int handle_response_fetch_desc(dir_connection_t *,
|
|
|
const response_handler_args_t *);
|
|
|
-static int handle_response_fetch_microdesc(dir_connection_t *,
|
|
|
- const response_handler_args_t *);
|
|
|
static int handle_response_upload_dir(dir_connection_t *,
|
|
|
const response_handler_args_t *);
|
|
|
static int handle_response_upload_vote(dir_connection_t *,
|
|
@@ -2916,7 +2915,7 @@ handle_response_fetch_desc(dir_connection_t *conn,
|
|
|
* Handler function: processes a response to a request for a group of
|
|
|
* microdescriptors
|
|
|
**/
|
|
|
-static int
|
|
|
+STATIC int
|
|
|
handle_response_fetch_microdesc(dir_connection_t *conn,
|
|
|
const response_handler_args_t *args)
|
|
|
{
|
|
@@ -2933,6 +2932,7 @@ handle_response_fetch_microdesc(dir_connection_t *conn,
|
|
|
conn->base_.port);
|
|
|
tor_assert(conn->requested_resource &&
|
|
|
!strcmpstart(conn->requested_resource, "d/"));
|
|
|
+ tor_assert_nonfatal(!tor_mem_is_zero(conn->identity_digest, DIGEST_LEN));
|
|
|
which = smartlist_new();
|
|
|
dir_split_resource_into_fingerprints(conn->requested_resource+2,
|
|
|
which, NULL,
|
|
@@ -2943,7 +2943,7 @@ handle_response_fetch_microdesc(dir_connection_t *conn,
|
|
|
"soon.",
|
|
|
status_code, escaped(reason), conn->base_.address,
|
|
|
(int)conn->base_.port, conn->requested_resource);
|
|
|
- dir_microdesc_download_failed(which, status_code);
|
|
|
+ dir_microdesc_download_failed(which, status_code, conn->identity_digest);
|
|
|
SMARTLIST_FOREACH(which, char *, cp, tor_free(cp));
|
|
|
smartlist_free(which);
|
|
|
return 0;
|
|
@@ -2955,7 +2955,7 @@ handle_response_fetch_microdesc(dir_connection_t *conn,
|
|
|
now, which);
|
|
|
if (smartlist_len(which)) {
|
|
|
/* Mark remaining ones as failed. */
|
|
|
- dir_microdesc_download_failed(which, status_code);
|
|
|
+ dir_microdesc_download_failed(which, status_code, conn->identity_digest);
|
|
|
}
|
|
|
if (mds && smartlist_len(mds)) {
|
|
|
control_event_bootstrap(BOOTSTRAP_STATUS_LOADING_DESCRIPTORS,
|
|
@@ -5812,13 +5812,14 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
|
|
|
* every 10 or 60 seconds (FOO_DESCRIPTOR_RETRY_INTERVAL) in main.c. */
|
|
|
}
|
|
|
|
|
|
-/** Called when a connection to download microdescriptors has failed in whole
|
|
|
- * or in part. <b>failed</b> is a list of every microdesc digest we didn't
|
|
|
- * get. <b>status_code</b> is the http status code we received. Reschedule the
|
|
|
- * microdesc downloads as appropriate. */
|
|
|
+/** Called when a connection to download microdescriptors from relay with
|
|
|
+ * <b>dir_id</b> has failed in whole or in part. <b>failed</b> is a list
|
|
|
+ * of every microdesc digest we didn't get. <b>status_code</b> is the http
|
|
|
+ * status code we received. Reschedule the microdesc downloads as
|
|
|
+ * appropriate. */
|
|
|
static void
|
|
|
dir_microdesc_download_failed(smartlist_t *failed,
|
|
|
- int status_code)
|
|
|
+ int status_code, const char *dir_id)
|
|
|
{
|
|
|
networkstatus_t *consensus
|
|
|
= networkstatus_get_latest_consensus_by_flavor(FLAV_MICRODESC);
|
|
@@ -5829,17 +5830,26 @@ dir_microdesc_download_failed(smartlist_t *failed,
|
|
|
|
|
|
if (! consensus)
|
|
|
return;
|
|
|
+
|
|
|
+ /* We failed to fetch a microdescriptor from 'dir_id', note it down
|
|
|
+ * so that we don't try the same relay next time... */
|
|
|
+ microdesc_note_outdated_dirserver(dir_id);
|
|
|
+
|
|
|
SMARTLIST_FOREACH_BEGIN(failed, const char *, d) {
|
|
|
rs = router_get_mutable_consensus_status_by_descriptor_digest(consensus,d);
|
|
|
if (!rs)
|
|
|
continue;
|
|
|
dls = &rs->dl_status;
|
|
|
if (dls->n_download_failures >=
|
|
|
- get_options()->TestingMicrodescMaxDownloadTries)
|
|
|
+ get_options()->TestingMicrodescMaxDownloadTries) {
|
|
|
continue;
|
|
|
- {
|
|
|
+ }
|
|
|
+
|
|
|
+ { /* Increment the failure count for this md fetch */
|
|
|
char buf[BASE64_DIGEST256_LEN+1];
|
|
|
digest256_to_base64(buf, d);
|
|
|
+ log_info(LD_DIR, "Failed to download md %s from %s",
|
|
|
+ buf, hex_str(dir_id, DIGEST_LEN));
|
|
|
download_status_increment_failure(dls, status_code, buf,
|
|
|
server, now);
|
|
|
}
|