mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 04:13:28 +01:00
Request (and try to use) consensus diffs.
This commit is contained in:
parent
912b0641e9
commit
c12d2cb2dc
@ -1401,3 +1401,12 @@ consensus_diff_apply(const char *consensus,
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Return true iff, based on its header, <b>document</b> is likely
|
||||
* to be a consensus diff. */
|
||||
int
|
||||
looks_like_a_consensus_diff(const char *document, size_t len)
|
||||
{
|
||||
return (len >= strlen(ns_diff_version) &&
|
||||
fast_memeq(document, ns_diff_version, strlen(ns_diff_version)));
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,8 @@ char *consensus_diff_generate(const char *cons1,
|
||||
char *consensus_diff_apply(const char *consensus,
|
||||
const char *diff);
|
||||
|
||||
int looks_like_a_consensus_diff(const char *document, size_t len);
|
||||
|
||||
#ifdef CONSDIFF_PRIVATE
|
||||
struct memarea_t;
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "config.h"
|
||||
#include "connection.h"
|
||||
#include "connection_edge.h"
|
||||
#include "consdiff.h"
|
||||
#include "consdiffmgr.h"
|
||||
#include "control.h"
|
||||
#include "compat.h"
|
||||
@ -2417,6 +2418,10 @@ handle_response_fetch_consensus(dir_connection_t *conn,
|
||||
const char *reason = args->reason;
|
||||
const time_t now = approx_time();
|
||||
|
||||
const char *consensus;
|
||||
char *new_consensus = NULL;
|
||||
const char *sourcename;
|
||||
|
||||
int r;
|
||||
const char *flavname = conn->requested_resource;
|
||||
if (status_code != 200) {
|
||||
@ -2429,15 +2434,57 @@ handle_response_fetch_consensus(dir_connection_t *conn,
|
||||
networkstatus_consensus_download_failed(status_code, flavname);
|
||||
return -1;
|
||||
}
|
||||
log_info(LD_DIR,"Received consensus directory (body size %d) from server "
|
||||
"'%s:%d'", (int)body_len, conn->base_.address, conn->base_.port);
|
||||
if ((r=networkstatus_set_current_consensus(body, flavname, 0,
|
||||
|
||||
if (looks_like_a_consensus_diff(body, body_len)) {
|
||||
/* First find our previous consensus. Maybe it's in ram, maybe not. */
|
||||
cached_dir_t *cd = dirserv_get_consensus(flavname);
|
||||
const char *consensus_body;
|
||||
char *owned_consensus = NULL;
|
||||
if (cd) {
|
||||
consensus_body = cd->dir;
|
||||
} else {
|
||||
owned_consensus = networkstatus_read_cached_consensus(flavname);
|
||||
consensus_body = owned_consensus;
|
||||
}
|
||||
if (!consensus_body) {
|
||||
log_warn(LD_DIR, "Received a consensus diff, but we can't find "
|
||||
"any %s-flavored consensus in our current cache.",flavname);
|
||||
networkstatus_consensus_download_failed(0, flavname);
|
||||
// XXXX if this happens too much, see below
|
||||
return -1;
|
||||
}
|
||||
|
||||
new_consensus = consensus_diff_apply(consensus_body, body);
|
||||
tor_free(owned_consensus);
|
||||
if (new_consensus == NULL) {
|
||||
log_warn(LD_DIR, "Could not apply consensus diff received from server "
|
||||
"'%s:%d'", conn->base_.address, conn->base_.port);
|
||||
// XXXX If this happens too many times, we should maybe not use
|
||||
// XXXX this directory for diffs any more?
|
||||
networkstatus_consensus_download_failed(0, flavname);
|
||||
return -1;
|
||||
}
|
||||
log_info(LD_DIR, "Applied consensus diff (body size %d) from server "
|
||||
"'%s:%d' resulted in a new consensus document (size %d).",
|
||||
(int)body_len, conn->base_.address, conn->base_.port,
|
||||
(int)strlen(new_consensus));
|
||||
consensus = new_consensus;
|
||||
sourcename = "generated based on a diff";
|
||||
} else {
|
||||
log_info(LD_DIR,"Received consensus directory (body size %d) from server "
|
||||
"'%s:%d'", (int)body_len, conn->base_.address, conn->base_.port);
|
||||
consensus = body;
|
||||
sourcename = "downloaded";
|
||||
}
|
||||
|
||||
if ((r=networkstatus_set_current_consensus(consensus, flavname, 0,
|
||||
conn->identity_digest))<0) {
|
||||
log_fn(r<-1?LOG_WARN:LOG_INFO, LD_DIR,
|
||||
"Unable to load %s consensus directory downloaded from "
|
||||
"Unable to load %s consensus directory %s from "
|
||||
"server '%s:%d'. I'll try again soon.",
|
||||
flavname, conn->base_.address, conn->base_.port);
|
||||
flavname, sourcename, conn->base_.address, conn->base_.port);
|
||||
networkstatus_consensus_download_failed(0, flavname);
|
||||
tor_free(new_consensus);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -2455,6 +2502,7 @@ handle_response_fetch_consensus(dir_connection_t *conn,
|
||||
}
|
||||
log_info(LD_DIR, "Successfully loaded consensus.");
|
||||
|
||||
tor_free(new_consensus);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -179,53 +179,74 @@ networkstatus_reset_download_failures(void)
|
||||
download_status_reset(&consensus_bootstrap_dl_status[i]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and and return the cached consensus of type <b>flavorname</b>. If
|
||||
* <b>unverified</b> is false, get the one we haven't verified. Return NULL if
|
||||
* the file isn't there. */
|
||||
static char *
|
||||
networkstatus_read_cached_consensus_impl(int flav,
|
||||
const char *flavorname,
|
||||
int unverified_consensus)
|
||||
{
|
||||
char buf[128];
|
||||
const char *prefix;
|
||||
if (unverified_consensus) {
|
||||
prefix = "unverified";
|
||||
} else {
|
||||
prefix = "cached";
|
||||
}
|
||||
if (flav == FLAV_NS) {
|
||||
tor_snprintf(buf, sizeof(buf), "%s-consensus", prefix);
|
||||
} else {
|
||||
tor_snprintf(buf, sizeof(buf), "%s-%s-consensus", prefix, flavorname);
|
||||
}
|
||||
|
||||
char *filename = get_datadir_fname(buf);
|
||||
char *result = read_file_to_str(filename, RFTS_IGNORE_MISSING, NULL);
|
||||
tor_free(filename);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Return a new string containing the current cached consensus of flavor
|
||||
* <b>flavorname</b>. */
|
||||
char *
|
||||
networkstatus_read_cached_consensus(const char *flavorname)
|
||||
{
|
||||
int flav = networkstatus_parse_flavor_name(flavorname);
|
||||
if (flav < 0)
|
||||
return NULL;
|
||||
return networkstatus_read_cached_consensus_impl(flav, flavorname, 0);
|
||||
}
|
||||
|
||||
/** Read every cached v3 consensus networkstatus from the disk. */
|
||||
int
|
||||
router_reload_consensus_networkstatus(void)
|
||||
{
|
||||
char *filename;
|
||||
char *s;
|
||||
const unsigned int flags = NSSET_FROM_CACHE | NSSET_DONT_DOWNLOAD_CERTS;
|
||||
int flav;
|
||||
|
||||
/* FFFF Suppress warnings if cached consensus is bad? */
|
||||
for (flav = 0; flav < N_CONSENSUS_FLAVORS; ++flav) {
|
||||
char buf[128];
|
||||
const char *flavor = networkstatus_get_flavor_name(flav);
|
||||
if (flav == FLAV_NS) {
|
||||
filename = get_datadir_fname("cached-consensus");
|
||||
} else {
|
||||
tor_snprintf(buf, sizeof(buf), "cached-%s-consensus", flavor);
|
||||
filename = get_datadir_fname(buf);
|
||||
}
|
||||
s = read_file_to_str(filename, RFTS_IGNORE_MISSING, NULL);
|
||||
char *s = networkstatus_read_cached_consensus_impl(flav, flavor, 0);
|
||||
if (s) {
|
||||
if (networkstatus_set_current_consensus(s, flavor, flags, NULL) < -1) {
|
||||
log_warn(LD_FS, "Couldn't load consensus %s networkstatus from \"%s\"",
|
||||
flavor, filename);
|
||||
log_warn(LD_FS, "Couldn't load consensus %s networkstatus from cache",
|
||||
flavor);
|
||||
}
|
||||
tor_free(s);
|
||||
}
|
||||
tor_free(filename);
|
||||
|
||||
if (flav == FLAV_NS) {
|
||||
filename = get_datadir_fname("unverified-consensus");
|
||||
} else {
|
||||
tor_snprintf(buf, sizeof(buf), "unverified-%s-consensus", flavor);
|
||||
filename = get_datadir_fname(buf);
|
||||
}
|
||||
|
||||
s = read_file_to_str(filename, RFTS_IGNORE_MISSING, NULL);
|
||||
s = networkstatus_read_cached_consensus_impl(flav, flavor, 1);
|
||||
if (s) {
|
||||
if (networkstatus_set_current_consensus(s, flavor,
|
||||
flags|NSSET_WAS_WAITING_FOR_CERTS,
|
||||
NULL)) {
|
||||
log_info(LD_FS, "Couldn't load consensus %s networkstatus from \"%s\"",
|
||||
flavor, filename);
|
||||
}
|
||||
log_info(LD_FS, "Couldn't load unverified consensus %s networkstatus "
|
||||
"from cache", flavor);
|
||||
}
|
||||
tor_free(s);
|
||||
}
|
||||
tor_free(filename);
|
||||
}
|
||||
|
||||
if (!networkstatus_get_latest_consensus()) {
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
void networkstatus_reset_warnings(void);
|
||||
void networkstatus_reset_download_failures(void);
|
||||
char *networkstatus_read_cached_consensus(const char *flavorname);
|
||||
int router_reload_consensus_networkstatus(void);
|
||||
void routerstatus_free(routerstatus_t *rs);
|
||||
void networkstatus_vote_free(networkstatus_t *ns);
|
||||
|
Loading…
Reference in New Issue
Block a user