aboutsummaryrefslogtreecommitdiff
path: root/src/or/dirserv.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2005-09-07 16:42:53 +0000
committerNick Mathewson <nickm@torproject.org>2005-09-07 16:42:53 +0000
commit5c6c88e76d65c4817cd44048ad5803a4b0c1cb9e (patch)
tree1455921cbbfa0d2f52577a93cd7565ace01d9434 /src/or/dirserv.c
parentf7256b700766ba7195e8c34c07fcd966201eb71f (diff)
downloadtor-5c6c88e76d65c4817cd44048ad5803a4b0c1cb9e.tar
tor-5c6c88e76d65c4817cd44048ad5803a4b0c1cb9e.tar.gz
More stuff for new directories.
- Distinguish v1 authorities (all currently trusted directories) from v2 authorities (all trusted directories). - Add configuration option for which dirs are v1 authories. - Add configuration option for whether to be a v1 authority. - Make trusted dirserver selection functions take options to choose which functionality we need. - Remove option when getting directory cache to see whether they support running-routers; they all do now. Replace it with one to see whether caches support v2 stuff. - Parse, cache, and serve network-status objects properly. - Serve compressed groups of router descriptors. The compression logic here could be more memory-efficient. - svn:r4911
Diffstat (limited to 'src/or/dirserv.c')
-rw-r--r--src/or/dirserv.c125
1 files changed, 70 insertions, 55 deletions
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index 91a4ae28d..e3fabb04f 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -669,16 +669,6 @@ dirserv_dump_directory_to_string(char **dir_out,
return -1;
}
-/** A cached_dir_t represents a cacheable directory object, along with its
- * compressed form. */
-typedef struct cached_dir_t {
- char *dir; /**< Contents of this object */
- char *dir_z; /**< Compressed contents of this object. */
- size_t dir_len; /**< Length of <b>dir</b> */
- size_t dir_z_len; /**< Length of <b>dir_z</b> */
- time_t published; /**< When was this object published */
-} cached_dir_t;
-
/** Most recently generated encoded signed directory. (auth dirservers only.)*/
static cached_dir_t the_directory = { NULL, NULL, 0, 0, 0 };
@@ -768,7 +758,6 @@ dirserv_set_cached_networkstatus_v2(const char *directory, const char *fp,
time_t published)
{
cached_dir_t *d;
- char fname[512];
if (!cached_v2_networkstatus)
cached_v2_networkstatus = strmap_new();
@@ -781,14 +770,33 @@ dirserv_set_cached_networkstatus_v2(const char *directory, const char *fp,
tor_assert(d);
set_cached_dir(d, tor_strdup(directory), published);
+}
- if (!d->dir)
- return;
+static cached_dir_t *
+dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
+ cached_dir_t *auth_src,
+ time_t dirty, int (*regenerate)(void),
+ const char *name,
+ int is_v1_object)
+{
+ int authority = get_options()->AuthoritativeDir &&
+ (!is_v1_object || get_options()->V1AuthoritativeDir);
- tor_snprintf(fname,sizeof(fname), "%s/cached-status/%s",
- get_options()->DataDirectory, fp);
- if (write_str_to_file(fname, d->dir, 0)<0) {
- log_fn(LOG_NOTICE, "Couldn't write cached network status to disk. Ignoring.");
+ if (!authority) {
+ return cache_src;
+ } else {
+ /* We're authoritative. */
+ if (regenerate != NULL) {
+ if (dirty && dirty + DIR_REGEN_SLACK_TIME < time(NULL)) {
+ if (regenerate()) {
+ log_fn(LOG_ERR, "Couldn't generate %s?", name);
+ exit(1);
+ }
+ } else {
+ log_fn(LOG_INFO, "The %s is still clean; reusing.", name);
+ }
+ }
+ return auth_src ? auth_src : cache_src;
}
}
@@ -798,30 +806,22 @@ dirserv_set_cached_networkstatus_v2(const char *directory, const char *fp,
* DIR_REGEN_SLACK_TIME seconds, call <b>regenerate</b>() to make a fresh one.
* Yields the compressed version of the directory object if <b>compress</b> is
* set; otherwise return the uncompressed version. (In either case, sets
- * *<b>out</b> and returns the size of the buffer in *<b>out</b>. */
+ * *<b>out</b> and returns the size of the buffer in *<b>out</b>.
+ *
+ * DOCDOC is_v1_object
+ **/
static size_t
dirserv_get_obj(const char **out, int compress,
cached_dir_t *cache_src,
cached_dir_t *auth_src,
time_t dirty, int (*regenerate)(void),
- const char *name)
+ const char *name,
+ int is_v1_object)
{
- cached_dir_t *d;
- if (!get_options()->AuthoritativeDir || !auth_src) {
- d = cache_src;
- } else {
- if (regenerate != NULL) {
- if (dirty && dirty + DIR_REGEN_SLACK_TIME < time(NULL)) {
- if (regenerate()) {
- log_fn(LOG_ERR, "Couldn't generate %s?", name);
- exit(1);
- }
- } else {
- log_fn(LOG_INFO, "The %s is still clean; reusing.", name);
- }
- }
- d = auth_src;
- }
+ cached_dir_t *d = dirserv_pick_cached_dir_obj(
+ cache_src, auth_src,
+ dirty, regenerate, name, is_v1_object);
+
if (!d)
return 0;
*out = compress ? d->dir_z : d->dir;
@@ -843,7 +843,7 @@ dirserv_get_directory(const char **directory, int compress)
&cached_directory, &the_directory,
the_directory_is_dirty,
dirserv_regenerate_directory,
- "server directory");
+ "server directory", 1);
}
/**
@@ -938,7 +938,7 @@ dirserv_get_runningrouters(const char **rr, int compress)
&cached_runningrouters, &the_runningrouters,
runningrouters_is_dirty,
generate_runningrouters,
- "v1 network status list");
+ "v1 network status list", 1);
}
/** Return true iff <b>ri</b> is "useful as an exit node." */
@@ -1132,8 +1132,7 @@ generate_v2_networkstatus(void)
set_cached_dir(&the_v2_networkstatus, status, time(NULL));
status = NULL; /* So it doesn't get double-freed. */
the_v2_networkstatus_is_dirty = 0;
- dirserv_set_cached_networkstatus_v2(the_v2_networkstatus.dir,
- fingerprint, time(NULL));
+ router_set_networkstatus(the_v2_networkstatus.dir, time(NULL), 0);
r = 0;
done:
@@ -1153,27 +1152,43 @@ generate_v2_networkstatus(void)
* nothing was found; otherwise set *<b>directory</b> to the matching network
* status and return its length.
*/
-size_t
-dirserv_get_networkstatus_v2(const char **directory, const char *key,
- int compress)
+int
+dirserv_get_networkstatus_v2(smartlist_t *result,
+ const char *key)
{
- *directory = NULL;
+ tor_assert(result);
+
if (!(strcmp(key,"authority"))) {
if (get_options()->AuthoritativeDir) {
- return dirserv_get_obj(directory, compress, NULL,
- &the_v2_networkstatus,
- the_v2_networkstatus_is_dirty,
- generate_v2_networkstatus,
- "network status list");
+ cached_dir_t *d =
+ dirserv_pick_cached_dir_obj(NULL,
+ &the_v2_networkstatus,
+ the_v2_networkstatus_is_dirty,
+ generate_v2_networkstatus,
+ "network status list", 0);
+ if (d)
+ smartlist_add(result, d);
}
} else if (!strcmp(key, "all")) {
- // XXXX NM
- return dirserv_get_networkstatus_v2(directory, "authority", compress);
- } else if (strlen(key)==HEX_DIGEST_LEN) {
- cached_dir_t *cached = strmap_get(cached_v2_networkstatus, key);
- if (cached)
- return dirserv_get_obj(directory, compress, cached, NULL, 0, NULL,
- "cached network status");
+ strmap_iter_t *iter = strmap_iter_init(cached_v2_networkstatus);
+ while (!strmap_iter_done(iter)) {
+ const char *fp;
+ void *val;
+ strmap_iter_get(iter, &fp, &val);
+ smartlist_add(result, val);
+ }
+ } else if (!strcmpstart(key, "fp/")) {
+ smartlist_t *hexdigests = smartlist_create();
+ smartlist_split_string(hexdigests, key+3, "+", 0, 0);
+ SMARTLIST_FOREACH(hexdigests, char *, cp,
+ {
+ cached_dir_t *cached;
+ tor_strlower(cp);
+ /* XXXX special-case own key? */
+ cached = strmap_get(cached_v2_networkstatus, cp);
+ if (cached)
+ smartlist_add(result, cached);
+ });
}
return 0;
}