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 */ #define ROUTER_ALLOW_SKEW (60*60*12) /* 12 hours */
/** How many seconds do we wait before regenerating the directory? */ /** How many seconds do we wait before regenerating the directory? */
#define DIR_REGEN_SLACK_TIME 30 #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; extern long stats_n_seconds_working;
@ -984,28 +987,60 @@ dirserv_set_cached_directory(const char *directory, time_t published,
* the cache. * the cache.
*/ */
void void
dirserv_set_cached_networkstatus_v2(const char *directory, dirserv_set_cached_networkstatus_v2(const char *networkstatus,
const char *identity, const char *identity,
time_t published) time_t published)
{ {
cached_dir_t *d; cached_dir_t *d;
smartlist_t *trusted_dirs;
if (!cached_v2_networkstatus) if (!cached_v2_networkstatus)
cached_v2_networkstatus = digestmap_new(); cached_v2_networkstatus = digestmap_new();
if (!(d = digestmap_get(cached_v2_networkstatus, identity))) { if (!(d = digestmap_get(cached_v2_networkstatus, identity))) {
if (!directory) if (!networkstatus)
return; return;
d = tor_malloc_zero(sizeof(cached_dir_t)); d = tor_malloc_zero(sizeof(cached_dir_t));
digestmap_set(cached_v2_networkstatus, identity, d); digestmap_set(cached_v2_networkstatus, identity, d);
} }
tor_assert(d); tor_assert(d);
if (directory) { if (networkstatus) {
set_cached_dir(d, tor_strdup(directory), published); if (published > d->published) {
set_cached_dir(d, tor_strdup(networkstatus), published);
} else {
networkstatus_free(networkstatus);
}
} else { } else {
free_cached_dir(d); free_cached_dir(d);
digestmap_remove(cached_v2_networkstatus, identity); 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 /** 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; 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 /** How far in the future do we allow a network-status to get before removing
* it? (seconds) */ * it? (seconds) */
#define NETWORKSTATUS_ALLOW_SKEW (48*60*60) #define NETWORKSTATUS_ALLOW_SKEW (48*60*60)
@ -1969,7 +1993,8 @@ router_set_networkstatus(const char *s, time_t arrived_at,
int i, found; int i, found;
time_t now; time_t now;
int skewed = 0; 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 fp[HEX_DIGEST_LEN+1];
char published[ISO_TIME_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."); warn(LD_DIR, "Couldn't parse network status.");
return -1; return -1;
} }
base16_encode(fp, HEX_DIGEST_LEN+1, ns->identity_digest, DIGEST_LEN);
if (!(trusted_dir = if (!(trusted_dir =
router_get_trusteddirserver_by_digest(ns->identity_digest))) { router_get_trusteddirserver_by_digest(ns->identity_digest))) {
info(LD_DIR, "Network status was signed, but not by an authoritative " info(LD_DIR, "Network status was signed, but not by an authoritative "
"directory we recognize."); "directory we recognize.");
networkstatus_free(ns); if (!get_options()->DirPort) {
return -1; networkstatus_free(ns);
return 0;
}
source_desc = fp;
} else {
source_desc = trusted_dir->description;
} }
now = time(NULL); now = time(NULL);
if (arrived_at > now) 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) { if (ns->published_on > now + NETWORKSTATUS_ALLOW_SKEW) {
warn(LD_GENERAL, "Network status from %s was published in the future " warn(LD_GENERAL, "Network status from %s was published in the future "
"(%s GMT). Somebody is skewed here: check your clock. Not caching.", "(%s GMT). Somebody is skewed here: check your clock. Not caching.",
trusted_dir->description, published); source_desc, published);
skewed = 1; skewed = 1;
} }
@ -2009,8 +2040,6 @@ router_set_networkstatus(const char *s, time_t arrived_at,
return 0; return 0;
} }
base16_encode(fp, HEX_DIGEST_LEN+1, ns->identity_digest, DIGEST_LEN);
if (requested_fingerprints) { if (requested_fingerprints) {
if (smartlist_string_isin(requested_fingerprints, fp)) { if (smartlist_string_isin(requested_fingerprints, fp)) {
smartlist_string_remove(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; trusted_dir->n_networkstatus_failures = 0;
found = 0; found = 0;
@ -2075,8 +2112,8 @@ router_set_networkstatus(const char *s, time_t arrived_at,
SMARTLIST_FOREACH(ns->entries, routerstatus_t *, rs, SMARTLIST_FOREACH(ns->entries, routerstatus_t *, rs,
{ {
if (!router_get_by_descriptor_digest(rs->descriptor_digest)) if (!router_get_by_descriptor_digest(rs->descriptor_digest))
rs->need_to_mirror = 1; rs->need_to_mirror = 1;
}); });
info(LD_DIR, "Setting networkstatus %s %s (published %s)", 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); smartlist_sort(networkstatus_list, _compare_networkstatus_published_on);
if (source != NS_FROM_CACHE && !skewed) { if (!skewed)
char *fn = networkstatus_get_cache_filename(ns); add_networkstatus_to_cache(s, source, 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);
}
networkstatus_list_update_recent(now); networkstatus_list_update_recent(now);
if (get_options()->DirPort && !skewed)
dirserv_set_cached_networkstatus_v2(s,
ns->identity_digest,
ns->published_on);
return 0; return 0;
} }