|
@@ -38,6 +38,8 @@ static networkstatus_vote_t *current_consensus = NULL;
|
|
|
* have enough certificates to be happy about. */
|
|
|
static networkstatus_vote_t *consensus_waiting_for_certs = NULL;
|
|
|
static char *consensus_waiting_for_certs_body = NULL;
|
|
|
+static time_t consensus_waiting_for_certs_set_at = 0;
|
|
|
+static int consensus_waiting_for_certs_dl_failed = 0;
|
|
|
|
|
|
|
|
|
* use this to rate-limit download attempts for directory caches (including
|
|
@@ -951,6 +953,8 @@ update_v2_networkstatus_cache_downloads(time_t now)
|
|
|
|
|
|
|
|
|
#define CONSENSUS_NETWORKSTATUS_MAX_DL_TRIES 8
|
|
|
+
|
|
|
+#define DELAY_WHILE_FETCHING_CERTS (20*60)
|
|
|
|
|
|
|
|
|
* appropriate. */
|
|
@@ -971,6 +975,17 @@ update_consensus_networkstatus_downloads(time_t now)
|
|
|
DIR_PURPOSE_FETCH_CONSENSUS))
|
|
|
return;
|
|
|
|
|
|
+ if (consensus_waiting_for_certs) {
|
|
|
+ if (consensus_waiting_for_certs_set_at + DELAY_WHILE_FETCHING_CERTS > now)
|
|
|
+ return;
|
|
|
+ else {
|
|
|
+ if (!consensus_waiting_for_certs_dl_failed) {
|
|
|
+ download_status_failed(&consensus_dl_status, 0);
|
|
|
+ consensus_waiting_for_certs_dl_failed=1;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
directory_get_from_dirserver(DIR_PURPOSE_FETCH_CONSENSUS,
|
|
|
ROUTER_PURPOSE_GENERAL, NULL, 1);
|
|
|
}
|
|
@@ -1153,7 +1168,9 @@ networkstatus_copy_old_consensus_info(networkstatus_vote_t *new_c,
|
|
|
* <b>consensus</b>. If we don't have enough certificates to validate it,
|
|
|
* store it in consensus_waiting_for_certs and launch a certificate fetch.
|
|
|
*
|
|
|
- * Return 0 on success, -1 on failure. */
|
|
|
+ * Return 0 on success, -1 on failure. On -1, caller should increment
|
|
|
+ * the failure count as appropriate.
|
|
|
+ */
|
|
|
int
|
|
|
networkstatus_set_current_consensus(const char *consensus, int from_cache,
|
|
|
int was_waiting_for_certs)
|
|
@@ -1170,6 +1187,20 @@ networkstatus_set_current_consensus(const char *consensus, int from_cache,
|
|
|
goto done;
|
|
|
}
|
|
|
|
|
|
+ if (current_consensus &&
|
|
|
+ !memcmp(c->networkstatus_digest, current_consensus->networkstatus_digest,
|
|
|
+ DIGEST_LEN)) {
|
|
|
+
|
|
|
+ log_info(LD_DIR, "Got a consensus we already have");
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (current_consensus && c->valid_after <= current_consensus->valid_after) {
|
|
|
+
|
|
|
+ log_info(LD_DIR, "Got a consensus at least as old as the one we have");
|
|
|
+ goto done;
|
|
|
+ }
|
|
|
+
|
|
|
consensus_fname = get_datadir_fname("cached-consensus");
|
|
|
unverified_fname = get_datadir_fname("unverified-consensus");
|
|
|
|
|
@@ -1187,34 +1218,33 @@ networkstatus_set_current_consensus(const char *consensus, int from_cache,
|
|
|
tor_free(consensus_waiting_for_certs_body);
|
|
|
consensus_waiting_for_certs = c;
|
|
|
consensus_waiting_for_certs_body = tor_strdup(consensus);
|
|
|
-
|
|
|
+ consensus_waiting_for_certs_set_at = now;
|
|
|
+ consensus_waiting_for_certs_dl_failed = 0;
|
|
|
if (!from_cache) {
|
|
|
write_str_to_file(unverified_fname, consensus, 0);
|
|
|
}
|
|
|
authority_certs_fetch_missing(c, now);
|
|
|
+
|
|
|
+ * or fail to get the certs. */
|
|
|
+ result = 0;
|
|
|
} else {
|
|
|
|
|
|
* latest consensus. */
|
|
|
if (was_waiting_for_certs && from_cache)
|
|
|
unlink(unverified_fname);
|
|
|
}
|
|
|
- download_status_reset(&consensus_dl_status);
|
|
|
- result = 0;
|
|
|
goto done;
|
|
|
- } else {
|
|
|
-
|
|
|
+ } else {
|
|
|
+
|
|
|
if (!was_waiting_for_certs)
|
|
|
log_warn(LD_DIR, "Not enough good signatures on networkstatus "
|
|
|
"consensus");
|
|
|
- if (was_waiting_for_certs && from_cache)
|
|
|
+ if (was_waiting_for_certs && (r < -1) && from_cache)
|
|
|
unlink(unverified_fname);
|
|
|
- networkstatus_vote_free(c);
|
|
|
goto done;
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- download_status_reset(&consensus_dl_status);
|
|
|
-
|
|
|
|
|
|
* valid-after date is very far in the future. */
|
|
|
|
|
@@ -1233,10 +1263,21 @@ networkstatus_set_current_consensus(const char *consensus, int from_cache,
|
|
|
consensus_waiting_for_certs = NULL;
|
|
|
if (consensus != consensus_waiting_for_certs_body)
|
|
|
tor_free(consensus_waiting_for_certs_body);
|
|
|
+ consensus_waiting_for_certs_set_at = 0;
|
|
|
+ consensus_waiting_for_certs_dl_failed = 0;
|
|
|
unlink(unverified_fname);
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ if (c->valid_after <= now && now <= c->valid_until) {
|
|
|
+ download_status_reset(&consensus_dl_status);
|
|
|
+ } else {
|
|
|
+ if (!from_cache)
|
|
|
+ download_status_failed(&consensus_dl_status, 0);
|
|
|
+ }
|
|
|
+
|
|
|
current_consensus = c;
|
|
|
+ c = NULL;
|
|
|
|
|
|
update_consensus_networkstatus_fetch_time(now);
|
|
|
dirvote_recalculate_timing(get_options(), now);
|
|
@@ -1253,6 +1294,8 @@ networkstatus_set_current_consensus(const char *consensus, int from_cache,
|
|
|
|
|
|
result = 0;
|
|
|
done:
|
|
|
+ if (c)
|
|
|
+ networkstatus_vote_free(c);
|
|
|
tor_free(consensus_fname);
|
|
|
tor_free(unverified_fname);
|
|
|
return result;
|