Fix bug 236: caches should cache up to 16 unrecognized network-status docs.

svn:r5754
This commit is contained in:
Nick Mathewson 2006-01-08 21:26:33 +00:00
parent 1616cb9297
commit e30516f33f
2 changed files with 87 additions and 25 deletions

View File

@ -17,6 +17,9 @@ const char dirserv_c_id[] =
#define ROUTER_ALLOW_SKEW (60*60*12) /* 12 hours */
/** How many seconds do we wait before regenerating the directory? */
#define DIR_REGEN_SLACK_TIME 30
/** If we're a cache, keep this many networkstatuses around from non-trusted
* directory authorities. */
#define MAX_UNTRUSTED_NETWORKSTATUSES 16
extern long stats_n_seconds_working;
@ -984,28 +987,60 @@ dirserv_set_cached_directory(const char *directory, time_t published,
* the cache.
*/
void
dirserv_set_cached_networkstatus_v2(const char *directory,
dirserv_set_cached_networkstatus_v2(const char *networkstatus,
const char *identity,
time_t published)
{
cached_dir_t *d;
smartlist_t *trusted_dirs;
if (!cached_v2_networkstatus)
cached_v2_networkstatus = digestmap_new();
if (!(d = digestmap_get(cached_v2_networkstatus, identity))) {
if (!directory)
if (!networkstatus)
return;
d = tor_malloc_zero(sizeof(cached_dir_t));
digestmap_set(cached_v2_networkstatus, identity, d);
}
tor_assert(d);
if (directory) {
set_cached_dir(d, tor_strdup(directory), published);
if (networkstatus) {
if (published > d->published) {
set_cached_dir(d, tor_strdup(networkstatus), published);
} else {
networkstatus_free(networkstatus);
}
} else {
free_cached_dir(d);
digestmap_remove(cached_v2_networkstatus, identity);
}
router_get_trusted_dir_servers(&trusted_dirs);
if (digestmap_size(cached_v2_networkstatus) >
smartlist_len(trusted_dirs) + MAX_UNTRUSTED_NETWORKSTATUSES) {
/* We need to remove the oldest untrusted networkstatus. */
const char *oldest = NULL;
time_t oldest_published = TIME_MAX;
digestmap_iter_t *iter;
for (iter = digestmap_iter_init(cached_v2_networkstatus);
!digestmap_iter_done(iter);
iter = digestmap_iter_next(cached_v2_networkstatus, iter)) {
const char *ident;
void *val;
digestmap_iter_get(iter, &ident, &val);
d = val;
if (d->published < oldest_published &&
!router_get_trusteddirserver_by_digest(ident)) {
oldest = ident;
oldest_published = d->published;
}
}
tor_assert(oldest);
d = digestmap_remove(cached_v2_networkstatus, oldest);
if (d)
free_cached_dir(d);
}
}
/** Helper: If we're an authority for the right directory version (the

View File

@ -1938,6 +1938,30 @@ _compare_networkstatus_published_on(const void **_a, const void **_b)
return 0;
}
/** Add the parsed neworkstatus in <b>ns</b> (with original document in
* <b>s</b> to the disk cache (and the in-memory directory server cache) as
* appropriate. */
static int
add_networkstatus_to_cache(const char *s,
networkstatus_source_t source,
networkstatus_t *ns)
{
if (source != NS_FROM_CACHE) {
char *fn = networkstatus_get_cache_filename(ns);
if (write_str_to_file(fn, s, 0)<0) {
notice(LD_FS, "Couldn't write cached network status to \"%s\"", fn);
}
tor_free(fn);
}
if (get_options()->DirPort)
dirserv_set_cached_networkstatus_v2(s,
ns->identity_digest,
ns->published_on);
return 0;
}
/** How far in the future do we allow a network-status to get before removing
* it? (seconds) */
#define NETWORKSTATUS_ALLOW_SKEW (48*60*60)
@ -1969,7 +1993,8 @@ router_set_networkstatus(const char *s, time_t arrived_at,
int i, found;
time_t now;
int skewed = 0;
trusted_dir_server_t *trusted_dir;
trusted_dir_server_t *trusted_dir = NULL;
const char *source_desc = NULL;
char fp[HEX_DIGEST_LEN+1];
char published[ISO_TIME_LEN+1];
@ -1978,12 +2003,18 @@ router_set_networkstatus(const char *s, time_t arrived_at,
warn(LD_DIR, "Couldn't parse network status.");
return -1;
}
base16_encode(fp, HEX_DIGEST_LEN+1, ns->identity_digest, DIGEST_LEN);
if (!(trusted_dir =
router_get_trusteddirserver_by_digest(ns->identity_digest))) {
info(LD_DIR, "Network status was signed, but not by an authoritative "
"directory we recognize.");
networkstatus_free(ns);
return -1;
if (!get_options()->DirPort) {
networkstatus_free(ns);
return 0;
}
source_desc = fp;
} else {
source_desc = trusted_dir->description;
}
now = time(NULL);
if (arrived_at > now)
@ -1996,7 +2027,7 @@ router_set_networkstatus(const char *s, time_t arrived_at,
if (ns->published_on > now + NETWORKSTATUS_ALLOW_SKEW) {
warn(LD_GENERAL, "Network status from %s was published in the future "
"(%s GMT). Somebody is skewed here: check your clock. Not caching.",
trusted_dir->description, published);
source_desc, published);
skewed = 1;
}
@ -2009,8 +2040,6 @@ router_set_networkstatus(const char *s, time_t arrived_at,
return 0;
}
base16_encode(fp, HEX_DIGEST_LEN+1, ns->identity_digest, DIGEST_LEN);
if (requested_fingerprints) {
if (smartlist_string_isin(requested_fingerprints, fp)) {
smartlist_string_remove(requested_fingerprints, fp);
@ -2025,7 +2054,15 @@ router_set_networkstatus(const char *s, time_t arrived_at,
}
}
if (source != NS_FROM_CACHE)
if (!trusted_dir) {
if (!skewed && get_options()->DirPort) {
add_networkstatus_to_cache(s, source, ns);
networkstatus_free(ns);
}
return 0;
}
if (source != NS_FROM_CACHE && trusted_dir)
trusted_dir->n_networkstatus_failures = 0;
found = 0;
@ -2075,8 +2112,8 @@ router_set_networkstatus(const char *s, time_t arrived_at,
SMARTLIST_FOREACH(ns->entries, routerstatus_t *, rs,
{
if (!router_get_by_descriptor_digest(rs->descriptor_digest))
rs->need_to_mirror = 1;
if (!router_get_by_descriptor_digest(rs->descriptor_digest))
rs->need_to_mirror = 1;
});
info(LD_DIR, "Setting networkstatus %s %s (published %s)",
@ -2087,21 +2124,11 @@ router_set_networkstatus(const char *s, time_t arrived_at,
smartlist_sort(networkstatus_list, _compare_networkstatus_published_on);
if (source != NS_FROM_CACHE && !skewed) {
char *fn = networkstatus_get_cache_filename(ns);
if (write_str_to_file(fn, s, 0)<0) {
notice(LD_FS, "Couldn't write cached network status to \"%s\"", fn);
}
tor_free(fn);
}
if (!skewed)
add_networkstatus_to_cache(s, source, ns);
networkstatus_list_update_recent(now);
if (get_options()->DirPort && !skewed)
dirserv_set_cached_networkstatus_v2(s,
ns->identity_digest,
ns->published_on);
return 0;
}