summaryrefslogtreecommitdiff
path: root/src/or/dirserv.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/dirserv.c')
-rw-r--r--src/or/dirserv.c497
1 files changed, 84 insertions, 413 deletions
diff --git a/src/or/dirserv.c b/src/or/dirserv.c
index b159afed97..e85575e6f9 100644
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@ -36,7 +36,7 @@ static int runningrouters_is_dirty = 1;
static int the_v2_networkstatus_is_dirty = 1;
static void directory_remove_invalid(void);
-static cached_dir_t *dirserv_regenerate_directory(void);
+static int dirserv_regenerate_directory(void);
static char *format_versions_list(config_line_t *ln);
/* Should be static; exposed for testing */
int add_fingerprint_to_dir(const char *nickname, const char *fp,
@@ -51,7 +51,6 @@ dirserv_get_status_impl(const char *fp, const char *nickname,
const char **msg, int should_log);
static int dirserv_thinks_router_is_reachable(routerinfo_t *router,
time_t now);
-static void clear_cached_dir(cached_dir_t *d);
/************** Fingerprint handling code ************/
@@ -122,31 +121,24 @@ dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk)
return 0;
}
-/** Load the nickname-\>fingerprint mappings stored in the approved-routers
- * file. The file format is line-based, with each non-blank holding one
- * nickname, some space, and a fingerprint for that nickname. On success,
- * replace the current fingerprint list with the new list and return 0. On
- * failure, leave the current fingerprint list untouched, and
- * return -1. */
+/** Parse the nickname-\>fingerprint mappings stored in the file named
+ * <b>fname</b>. The file format is line-based, with each non-blank
+ * holding one nickname, some space, and a fingerprint for that
+ * nickname. On success, replace the current fingerprint list with
+ * the contents of <b>fname</b> and return 0. On failure, leave the
+ * current fingerprint list untouched, and return -1. */
int
-dirserv_load_fingerprint_file(void)
+dirserv_parse_fingerprint_file(const char *fname)
{
- char fname[512];
char *cf;
char *nickname, *fingerprint;
smartlist_t *fingerprint_list_new;
int result;
config_line_t *front=NULL, *list;
- or_options_t *options = get_options();
-
- tor_snprintf(fname, sizeof(fname),
- "%s/approved-routers", options->DataDirectory);
- log_info(LD_GENERAL,
- "Reloading approved fingerprints from \"%s\"...", fname);
cf = read_file_to_str(fname, 0);
if (!cf) {
- if (options->NamingAuthoritativeDir) {
+ if (get_options()->NamingAuthoritativeDir) {
log_warn(LD_FS, "Cannot open fingerprint file '%s'. Failing.", fname);
return -1;
} else {
@@ -462,7 +454,6 @@ authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
case FP_INVALID:
ri->is_named = ri->is_valid = 0;
break;
- case FP_REJECT:
default:
tor_assert(0);
}
@@ -489,7 +480,7 @@ dirserv_add_descriptor(const char *desc, const char **msg)
*msg = NULL;
/* Check: is the descriptor syntactically valid? */
- ri = router_parse_entry_from_string(desc, NULL, 1);
+ ri = router_parse_entry_from_string(desc, NULL);
if (!ri) {
log_warn(LD_DIRSERV, "Couldn't parse uploaded server descriptor");
*msg = "Rejected: Couldn't parse server descriptor.";
@@ -665,7 +656,7 @@ list_single_server_status(routerinfo_t *desc, int is_live)
/** Each server needs to have passed a reachability test no more
* than this number of seconds ago, or he is listed as down in
* the directory. */
-#define REACHABLE_TIMEOUT (45*60)
+#define REACHABLE_TIMEOUT (30*60)
/** Treat a router as alive if
* - It's me, and I'm not hibernating.
@@ -769,12 +760,11 @@ live_enough_for_v1_dir(routerinfo_t *ri, time_t now)
/** Generate a new v1 directory and write it into a newly allocated string.
* Point *<b>dir_out</b> to the allocated string. Sign the
* directory with <b>private_key</b>. Return 0 on success, -1 on
- * failure. If <b>complete</b> is set, give us all the descriptors;
- * otherwise leave out non-running and non-valid ones.
+ * failure.
*/
int
dirserv_dump_directory_to_string(char **dir_out,
- crypto_pk_env_t *private_key, int complete)
+ crypto_pk_env_t *private_key)
{
char *cp;
char *router_status;
@@ -808,7 +798,7 @@ dirserv_dump_directory_to_string(char **dir_out,
buf_len = 2048+strlen(recommended_versions)+
strlen(router_status);
SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri,
- if (complete || live_enough_for_v1_dir(ri, now))
+ if (live_enough_for_v1_dir(ri, now))
buf_len += ri->cache_info.signed_descriptor_len+1);
buf = tor_malloc(buf_len);
/* We'll be comparing against buf_len throughout the rest of the
@@ -834,7 +824,7 @@ dirserv_dump_directory_to_string(char **dir_out,
{
size_t len = ri->cache_info.signed_descriptor_len;
const char *body;
- if (!complete && !live_enough_for_v1_dir(ri, now))
+ if (!live_enough_for_v1_dir(ri, now))
continue;
if (cp+len+1 >= buf+buf_len)
goto truncated;
@@ -874,12 +864,12 @@ dirserv_dump_directory_to_string(char **dir_out,
}
/** Most recently generated encoded signed directory. (auth dirservers only.)*/
-static cached_dir_t *the_directory = NULL;
+static cached_dir_t the_directory = { NULL, NULL, 0, 0, 0 };
/* Used only by non-auth dirservers: The directory and runningrouters we'll
* serve when requested. */
-static cached_dir_t *cached_directory = NULL;
-static cached_dir_t cached_runningrouters = { NULL, NULL, 0, 0, 0, -1 };
+static cached_dir_t cached_directory = { NULL, NULL, 0, 0, 0 };
+static cached_dir_t cached_runningrouters = { NULL, NULL, 0, 0, 0 };
/* Used for other dirservers' v2 network statuses. Map from hexdigest to
* cached_dir_t. */
@@ -889,7 +879,7 @@ static digestmap_t *cached_v2_networkstatus = NULL;
* <b>directory</b> published on <b>when</b>, unless <b>when</b> is older than
* the last value, or too far in the future.
*
- * Does not copy <b>directory</b>; frees it if it isn't used.
+ * Does not copy <b>directory</b>; free it if it isn't used.
*/
static void
set_cached_dir(cached_dir_t *d, char *directory, time_t when)
@@ -916,32 +906,6 @@ set_cached_dir(cached_dir_t *d, char *directory, time_t when)
}
}
-/** DOCDOC */
-void
-cached_dir_decref(cached_dir_t *d)
-{
- if (!d || --d->refcnt > 0)
- return;
- clear_cached_dir(d);
- tor_free(d);
-}
-
-/** DOCDOC */
-static cached_dir_t *
-new_cached_dir(char *s, time_t published)
-{
- cached_dir_t *d = tor_malloc_zero(sizeof(cached_dir_t));
- d->refcnt = 1;
- d->dir = s;
- d->dir_len = strlen(s);
- d->published = published;
- if (tor_gzip_compress(&(d->dir_z), &(d->dir_z_len), d->dir, d->dir_len,
- ZLIB_METHOD)) {
- log_warn(LD_BUG, "Error compressing directory");
- }
- return d;
-}
-
/** Remove all storage held in <b>d</b>, but do not free <b>d</b> itself. */
static void
clear_cached_dir(cached_dir_t *d)
@@ -953,10 +917,11 @@ clear_cached_dir(cached_dir_t *d)
/** Free all storage held by the cached_dir_t in <b>d</b>. */
static void
-_free_cached_dir(void *_d)
+free_cached_dir(void *_d)
{
cached_dir_t *d = (cached_dir_t *)_d;
- cached_dir_decref(d);
+ clear_cached_dir(d);
+ tor_free(d);
}
/** If we have no cached directory, or it is older than <b>when</b>, then
@@ -966,12 +931,9 @@ void
dirserv_set_cached_directory(const char *directory, time_t published,
int is_running_routers)
{
- if (is_running_routers) {
- set_cached_dir(&cached_runningrouters, tor_strdup(directory), published);
- } else {
- cached_dir_decref(cached_directory);
- cached_directory = new_cached_dir(tor_strdup(directory), published);
- }
+ cached_dir_t *d;
+ d = is_running_routers ? &cached_runningrouters : &cached_directory;
+ set_cached_dir(d, tor_strdup(directory), published);
}
/** We've just received a v2 network-status for an authoritative directory
@@ -985,30 +947,28 @@ dirserv_set_cached_networkstatus_v2(const char *networkstatus,
const char *identity,
time_t published)
{
- cached_dir_t *d, *old_d;
+ cached_dir_t *d;
smartlist_t *trusted_dirs;
if (!cached_v2_networkstatus)
cached_v2_networkstatus = digestmap_new();
- old_d = digestmap_get(cached_v2_networkstatus, identity);
- if (!old_d && !networkstatus)
- return;
+ if (!(d = digestmap_get(cached_v2_networkstatus, identity))) {
+ if (!networkstatus)
+ return;
+ d = tor_malloc_zero(sizeof(cached_dir_t));
+ digestmap_set(cached_v2_networkstatus, identity, d);
+ }
+ tor_assert(d);
if (networkstatus) {
- if (!old_d || published > old_d->published) {
- d = new_cached_dir(tor_strdup(networkstatus), published);
- digestmap_set(cached_v2_networkstatus, identity, d);
- if (old_d)
- cached_dir_decref(old_d);
+ if (published > d->published) {
+ set_cached_dir(d, tor_strdup(networkstatus), published);
}
} else {
- if (old_d) {
- digestmap_remove(cached_v2_networkstatus, identity);
- cached_dir_decref(old_d);
- }
+ free_cached_dir(d);
+ digestmap_remove(cached_v2_networkstatus, identity);
}
- /* Now purge old entries. */
trusted_dirs = router_get_trusted_dir_servers();
if (digestmap_size(cached_v2_networkstatus) >
smartlist_len(trusted_dirs) + MAX_UNTRUSTED_NETWORKSTATUSES) {
@@ -1033,7 +993,7 @@ dirserv_set_cached_networkstatus_v2(const char *networkstatus,
tor_assert(oldest);
d = digestmap_remove(cached_v2_networkstatus, oldest);
if (d)
- cached_dir_decref(d);
+ free_cached_dir(d);
}
}
@@ -1045,7 +1005,7 @@ dirserv_set_cached_networkstatus_v2(const char *networkstatus,
static cached_dir_t *
dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
cached_dir_t *auth_src,
- time_t dirty, cached_dir_t *(*regenerate)(void),
+ time_t dirty, int (*regenerate)(void),
const char *name,
int is_v1_object)
{
@@ -1058,7 +1018,7 @@ dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
/* We're authoritative. */
if (regenerate != NULL) {
if (dirty && dirty + DIR_REGEN_SLACK_TIME < time(NULL)) {
- if (!(auth_src = regenerate())) {
+ if (regenerate()) {
log_err(LD_BUG, "Couldn't generate %s?", name);
exit(1);
}
@@ -1082,11 +1042,10 @@ dirserv_pick_cached_dir_obj(cached_dir_t *cache_src,
* this kind of object.
**/
static size_t
-dirserv_get_obj(const char **out,
- int compress,
+dirserv_get_obj(const char **out, int compress,
cached_dir_t *cache_src,
cached_dir_t *auth_src,
- time_t dirty, cached_dir_t *(*regenerate)(void),
+ time_t dirty, int (*regenerate)(void),
const char *name,
int is_v1_object)
{
@@ -1105,54 +1064,53 @@ dirserv_get_obj(const char **out,
}
}
-/** Return the most recently generated encoded signed directory, generating a
- * new one as necessary. If not an authoritative directory may return NULL if
- * no directory is yet cached.*/
-cached_dir_t *
-dirserv_get_directory(void)
+/** Set *<b>directory</b> to the most recently generated encoded signed
+ * directory, generating a new one as necessary. If not an authoritative
+ * directory may return 0 if no directory is yet cached.*/
+size_t
+dirserv_get_directory(const char **directory, int compress)
{
- return dirserv_pick_cached_dir_obj(cached_directory, the_directory,
- the_directory_is_dirty,
- dirserv_regenerate_directory,
- "server directory", 1);
+ return dirserv_get_obj(directory, compress,
+ &cached_directory, &the_directory,
+ the_directory_is_dirty,
+ dirserv_regenerate_directory,
+ "server directory", 1);
}
/**
- * Generate a fresh v1 directory (authdirservers only); set the_directory
- * and return a pointer to the new value.
+ * Generate a fresh v1 directory (authdirservers only.)
*/
-static cached_dir_t *
+static int
dirserv_regenerate_directory(void)
{
char *new_directory=NULL;
if (dirserv_dump_directory_to_string(&new_directory,
- get_identity_key(), 0)) {
+ get_identity_key())) {
log_warn(LD_BUG, "Error creating directory.");
tor_free(new_directory);
- return NULL;
+ return -1;
}
- cached_dir_decref(the_directory);
- the_directory = new_cached_dir(new_directory, time(NULL));
+ set_cached_dir(&the_directory, new_directory, time(NULL));
log_info(LD_DIRSERV,"New directory (size %d) has been built.",
- (int)the_directory->dir_len);
+ (int)the_directory.dir_len);
log_debug(LD_DIRSERV,"New directory (size %d):\n%s",
- (int)the_directory->dir_len, the_directory->dir);
+ (int)the_directory.dir_len, the_directory.dir);
the_directory_is_dirty = 0;
/* Save the directory to disk so we re-load it quickly on startup.
*/
- dirserv_set_cached_directory(the_directory->dir, time(NULL), 0);
+ dirserv_set_cached_directory(the_directory.dir, time(NULL), 0);
- return the_directory;
+ return 0;
}
/** For authoritative directories: the current (v1) network status */
-static cached_dir_t the_runningrouters = { NULL, NULL, 0, 0, 0, -1 };
+static cached_dir_t the_runningrouters = { NULL, NULL, 0, 0, 0 };
/** Replace the current running-routers list with a newly generated one. */
-static cached_dir_t *
+static int
generate_runningrouters(void)
{
char *s=NULL;
@@ -1197,11 +1155,11 @@ generate_runningrouters(void)
set_cached_dir(&the_runningrouters, s, time(NULL));
runningrouters_is_dirty = 0;
- return &the_runningrouters;
+ return 0;
err:
tor_free(s);
tor_free(router_status);
- return NULL;
+ return -1;
}
/** Set *<b>rr</b> to the most recently generated encoded signed
@@ -1218,7 +1176,7 @@ dirserv_get_runningrouters(const char **rr, int compress)
}
/** For authoritative directories: the current (v2) network status */
-static cached_dir_t *the_v2_networkstatus = NULL;
+static cached_dir_t the_v2_networkstatus = { NULL, NULL, 0, 0, 0 };
static int
should_generate_v2_networkstatus(void)
@@ -1302,9 +1260,6 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
if (smartlist_len(bandwidths)) {
fast_bandwidth = *(uint32_t*)smartlist_get(bandwidths,
smartlist_len(bandwidths)/8);
- if (fast_bandwidth < ROUTER_REQUIRED_MIN_BANDWIDTH)
- fast_bandwidth = *(uint32_t*)smartlist_get(bandwidths,
- smartlist_len(bandwidths)/4);
guard_bandwidth = *(uint32_t*)smartlist_get(bandwidths,
smartlist_len(bandwidths)/2);
}
@@ -1323,7 +1278,7 @@ dirserv_compute_performance_thresholds(routerlist_t *rl)
/** For authoritative directories only: replace the contents of
* <b>the_v2_networkstatus</b> with a newly generated network status
* object. */
-static cached_dir_t *
+static int
generate_v2_networkstatus(void)
{
#define LONGEST_STATUS_FLAG_NAME_LEN 7
@@ -1335,7 +1290,7 @@ generate_v2_networkstatus(void)
/* second line */ \
(LONGEST_STATUS_FLAG_NAME_LEN+1)*N_STATUS_FLAGS + 2)
- cached_dir_t *r = NULL;
+ int r = -1;
size_t len, identity_pkey_len;
char *status = NULL, *client_versions = NULL, *server_versions = NULL,
*identity_pkey = NULL, *hostname = NULL;
@@ -1355,7 +1310,7 @@ generate_v2_networkstatus(void)
int versioning = options->VersioningAuthoritativeDir;
const char *contact;
- if (resolve_my_address(LOG_WARN, options, &addr, &hostname)<0) {
+ if (resolve_my_address(options, &addr, &hostname)<0) {
log_warn(LD_NET, "Couldn't resolve my hostname");
goto done;
}
@@ -1404,9 +1359,9 @@ generate_v2_networkstatus(void)
naming ? " Names" : "",
versioning ? " Versions" : "",
versioning ? "client-versions " : "",
- versioning ? client_versions : "",
+ client_versions,
versioning ? "\nserver-versions " : "",
- versioning ? server_versions : "",
+ server_versions,
versioning ? "\n" : "",
identity_pkey);
outp = status + strlen(status);
@@ -1497,14 +1452,13 @@ generate_v2_networkstatus(void)
goto done;
}
- if (the_v2_networkstatus)
- cached_dir_decref(the_v2_networkstatus);
- the_v2_networkstatus = new_cached_dir(status, time(NULL));
+ set_cached_dir(&the_v2_networkstatus, status, time(NULL));
status = NULL; /* So it doesn't get double-freed. */
the_v2_networkstatus_is_dirty = 0;
- router_set_networkstatus(the_v2_networkstatus->dir,
- time(NULL), NS_GENERATED, NULL);
- r = the_v2_networkstatus;
+ router_set_networkstatus(the_v2_networkstatus.dir, time(NULL), NS_GENERATED,
+ NULL);
+
+ r = 0;
done:
tor_free(client_versions);
tor_free(server_versions);
@@ -1514,45 +1468,6 @@ generate_v2_networkstatus(void)
return r;
}
-/* DOCDOC */
-void
-dirserv_get_networkstatus_v2_fingerprints(smartlist_t *result,
- const char *key)
-{
- tor_assert(result);
-
- if (!cached_v2_networkstatus)
- cached_v2_networkstatus = digestmap_new();
-
- if (should_generate_v2_networkstatus())
- generate_v2_networkstatus();
-
- if (!strcmp(key,"authority")) {
- if (get_options()->AuthoritativeDir) {
- routerinfo_t *me = router_get_my_routerinfo();
- if (me)
- smartlist_add(result,
- tor_memdup(me->cache_info.identity_digest, DIGEST_LEN));
- }
- } else if (!strcmp(key, "all")) {
- digestmap_iter_t *iter;
- iter = digestmap_iter_init(cached_v2_networkstatus);
- while (!digestmap_iter_done(iter)) {
- const char *ident;
- void *val;
- digestmap_iter_get(iter, &ident, &val);
- smartlist_add(result, tor_memdup(ident, DIGEST_LEN));
- iter = digestmap_iter_next(cached_v2_networkstatus, iter);
- }
- smartlist_sort_digests(result);
- if (smartlist_len(result) == 0)
- log_warn(LD_DIRSERV,
- "Client requested 'all' network status objects; we have none.");
- } else if (!strcmpstart(key, "fp/")) {
- dir_split_resource_into_fingerprints(key+3, result, NULL, 1, 1);
- }
-}
-
/** Look for a network status object as specified by <b>key</b>, which should
* be either "authority" (to find a network status generated by us), a hex
* identity digest (to find a network status generated by given directory), or
@@ -1571,7 +1486,7 @@ dirserv_get_networkstatus_v2(smartlist_t *result,
if (get_options()->AuthoritativeDir) {
cached_dir_t *d =
dirserv_pick_cached_dir_obj(NULL,
- the_v2_networkstatus,
+ &the_v2_networkstatus,
the_v2_networkstatus_is_dirty,
generate_v2_networkstatus,
"network status list", 0);
@@ -1598,7 +1513,7 @@ dirserv_get_networkstatus_v2(smartlist_t *result,
"Client requested 'all' network status objects; we have none.");
} else if (!strcmpstart(key, "fp/")) {
smartlist_t *digests = smartlist_create();
- dir_split_resource_into_fingerprints(key+3, digests, NULL, 1, 1);
+ dir_split_resource_into_fingerprints(key+3, digests, NULL, 1);
SMARTLIST_FOREACH(digests, char *, cp,
{
cached_dir_t *cached;
@@ -1619,44 +1534,6 @@ dirserv_get_networkstatus_v2(smartlist_t *result,
}
}
-/** As dirserv_get_routerdescs(), but instead of getting signed_descriptor_t
- * pointers, adds copies of digests to fps_out. For a /tor/server/d/ request,
- * adds descriptor digests; for other requests, adds identity digests.
- */
-int
-dirserv_get_routerdesc_fingerprints(smartlist_t *fps_out, const char *key,
- const char **msg)
-{
- *msg = NULL;
-
- if (!strcmp(key, "/tor/server/all")) {
- routerlist_t *rl = router_get_routerlist();
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
- smartlist_add(fps_out,
- tor_memdup(r->cache_info.identity_digest, DIGEST_LEN)));
- } else if (!strcmp(key, "/tor/server/authority")) {
- routerinfo_t *ri = router_get_my_routerinfo();
- if (ri)
- smartlist_add(fps_out,
- tor_memdup(ri->cache_info.identity_digest, DIGEST_LEN));
- } else if (!strcmpstart(key, "/tor/server/d/")) {
- key += strlen("/tor/server/d/");
- dir_split_resource_into_fingerprints(key, fps_out, NULL, 1, 1);
- } else if (!strcmpstart(key, "/tor/server/fp/")) {
- key += strlen("/tor/server/fp/");
- dir_split_resource_into_fingerprints(key, fps_out, NULL, 1, 1);
- } else {
- *msg = "Key not recognized";
- return -1;
- }
-
- if (!smartlist_len(fps_out)) {
- *msg = "Servers unavailable";
- return -1;
- }
- return 0;
-}
-
/** Add a signed_descriptor_t to <b>descs_out</b> for each router matching
* <b>key</b>. The key should be either
* - "/tor/server/authority" for our own routerinfo;
@@ -1692,7 +1569,7 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
} else if (!strcmpstart(key, "/tor/server/d/")) {
smartlist_t *digests = smartlist_create();
key += strlen("/tor/server/d/");
- dir_split_resource_into_fingerprints(key, digests, NULL, 1, 1);
+ dir_split_resource_into_fingerprints(key, digests, NULL, 1);
SMARTLIST_FOREACH(digests, const char *, d,
{
signed_descriptor_t *sd = router_get_by_descriptor_digest(d);
@@ -1705,7 +1582,7 @@ dirserv_get_routerdescs(smartlist_t *descs_out, const char *key,
smartlist_t *digests = smartlist_create();
time_t cutoff = time(NULL) - ROUTER_MAX_AGE_TO_PUBLISH;
key += strlen("/tor/server/fp/");
- dir_split_resource_into_fingerprints(key, digests, NULL, 1, 1);
+ dir_split_resource_into_fingerprints(key, digests, NULL, 1);
SMARTLIST_FOREACH(digests, const char *, d,
{
if (router_digest_is_me(d)) {
@@ -1756,7 +1633,6 @@ dirserv_orconn_tls_done(const char *address,
tor_assert(address);
tor_assert(digest_rcvd);
tor_assert(nickname_rcvd);
- (void) as_advertised; // XXXX This should really be implemented. -NM
// XXXXNM We should really have a better solution here than dropping
// XXXXNM whole routers; otherwise, they come back way too easily.
@@ -1795,211 +1671,6 @@ dirserv_orconn_tls_done(const char *address,
}
}
-/** Auth dir server only: if <b>try_all</b> is 1, launch connections to
- * all known routers; else we want to load balance such that we only
- * try a few connections per call.
- *
- * The load balancing is such that if we get called once every ten
- * seconds, we will cycle through all the tests in 1280 seconds (a
- * bit over 20 minutes).
- */
-void
-dirserv_test_reachability(int try_all)
-{
- time_t now = time(NULL);
- routerlist_t *rl = router_get_routerlist();
- static char ctr = 0;
-
- SMARTLIST_FOREACH(rl->routers, routerinfo_t *, router, {
- const char *id_digest = router->cache_info.identity_digest;
- if (router_is_me(router))
- continue;
- if (try_all || (((uint8_t)id_digest[0]) % 128) == ctr) {
- log_debug(LD_OR,"Testing reachability of %s at %s:%u.",
- router->nickname, router->address, router->or_port);
- /* Remember when we started trying to determine reachability */
- if (!router->testing_since)
- router->testing_since = now;
- connection_or_connect(router->addr, router->or_port,
- id_digest);
- }
- });
- if (!try_all) /* increment ctr */
- ctr = (ctr + 1) % 128;
-}
-
-/** When we're spooling data onto our outbuf, add more whenever we dip
- * below this threshold. */
-#define DIRSERV_BUFFER_MIN 16384
-
-static int
-connection_dirserv_finish_spooling(dir_connection_t *conn)
-{
- if (conn->zlib_state) {
- connection_write_to_buf_zlib(conn, "", 0, 1);
- tor_zlib_free(conn->zlib_state);
- conn->zlib_state = NULL;
- }
- conn->dir_spool_src = DIR_SPOOL_NONE;
- return 0;
-}
-
-/** DOCDOC */
-static int
-connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn)
-{
- int by_fp = conn->dir_spool_src == DIR_SPOOL_SERVER_BY_FP;
-
- while (smartlist_len(conn->fingerprint_stack) &&
- buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) {
- const char *body;
- char *fp = smartlist_pop_last(conn->fingerprint_stack);
- signed_descriptor_t *sd = NULL;
- if (by_fp) {
- if (router_digest_is_me(fp)) {
- sd = &(router_get_my_routerinfo()->cache_info);
- } else {
- routerinfo_t *ri = router_get_by_digest(fp);
- if (ri &&
- ri->cache_info.published_on > time(NULL)-ROUTER_MAX_AGE_TO_PUBLISH)
- sd = &ri->cache_info;
- }
- } else
- sd = router_get_by_descriptor_digest(fp);
- tor_free(fp);
- if (!sd)
- continue;
- body = signed_descriptor_get_body(sd);
- if (conn->zlib_state) {
- int last = ! smartlist_len(conn->fingerprint_stack);
- connection_write_to_buf_zlib(conn, body,
- sd->signed_descriptor_len, last);
- if (last) {
- tor_zlib_free(conn->zlib_state);
- conn->zlib_state = NULL;
- }
- } else {
- connection_write_to_buf(body,
- sd->signed_descriptor_len,
- TO_CONN(conn));
- }
- }
-
- if (!smartlist_len(conn->fingerprint_stack)) {
- /* We just wrote the last one; finish up. */
- conn->dir_spool_src = DIR_SPOOL_NONE;
- smartlist_free(conn->fingerprint_stack);
- conn->fingerprint_stack = NULL;
- }
- return 0;
-}
-
-/** DOCDOC */
-static int
-connection_dirserv_add_dir_bytes_to_outbuf(dir_connection_t *conn)
-{
- int bytes, remaining;
-
- bytes = DIRSERV_BUFFER_MIN - buf_datalen(conn->_base.outbuf);
- tor_assert(bytes > 0);
- tor_assert(conn->cached_dir);
- if (bytes < 8192)
- bytes = 8192;
- remaining = conn->cached_dir->dir_z_len - conn->cached_dir_offset;
- if (bytes > remaining)
- bytes = remaining;
-
- if (conn->zlib_state) {
- connection_write_to_buf_zlib(conn,
- conn->cached_dir->dir_z + conn->cached_dir_offset,
- bytes, bytes == remaining);
- } else {
- connection_write_to_buf(conn->cached_dir->dir_z + conn->cached_dir_offset,
- bytes, TO_CONN(conn));
- }
- conn->cached_dir_offset += bytes;
- if (conn->cached_dir_offset == (int)conn->cached_dir->dir_z_len) {
- /* We just wrote the last one; finish up. */
- connection_dirserv_finish_spooling(conn);
- cached_dir_decref(conn->cached_dir);
- conn->cached_dir = NULL;
- }
- return 0;
-}
-
-/* DOCDOC */
-static int
-connection_dirserv_add_networkstatus_bytes_to_outbuf(dir_connection_t *conn)
-{
-
- while (buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) {
- if (conn->cached_dir) {
- int uncompressing = (conn->zlib_state != NULL);
- int r = connection_dirserv_add_dir_bytes_to_outbuf(conn);
- if (conn->dir_spool_src == DIR_SPOOL_NONE) {
- /* add_dir_bytes thinks we're done with the cached_dir. But we
- * may have more cached_dirs! */
- conn->dir_spool_src = DIR_SPOOL_NETWORKSTATUS;
- /* This bit is tricky. If we were uncompressing the last
- * networkstatus, we may need to make a new zlib object to
- * uncompress the next one. */
- if (uncompressing && ! conn->zlib_state &&
- conn->fingerprint_stack &&
- smartlist_len(conn->fingerprint_stack)) {
- conn->zlib_state = tor_zlib_new(0, ZLIB_METHOD);
- }
- }
- if (r) return r;
- } else if (conn->fingerprint_stack &&
- smartlist_len(conn->fingerprint_stack)) {
- /* Add another networkstatus; start serving it. */
- char *fp = smartlist_pop_last(conn->fingerprint_stack);
- cached_dir_t *d;
- if (router_digest_is_me(fp))
- d = the_v2_networkstatus;
- else
- d = digestmap_get(cached_v2_networkstatus, fp);
- tor_free(fp);
- if (d) {
- ++d->refcnt;
- conn->cached_dir = d;
- conn->cached_dir_offset = 0;
- }
- } else {
- connection_dirserv_finish_spooling(conn);
- if (conn->fingerprint_stack)
- smartlist_free(conn->fingerprint_stack);
- conn->fingerprint_stack = NULL;
- return 0;
- }
- }
- return 0;
-}
-
-/** Called whenever we have flushed some directory data in state
- * SERVER_WRITING. */
-int
-connection_dirserv_flushed_some(dir_connection_t *conn)
-{
- tor_assert(conn->_base.state == DIR_CONN_STATE_SERVER_WRITING);
-
- if (buf_datalen(conn->_base.outbuf) >= DIRSERV_BUFFER_MIN)
- return 0;
-
- switch (conn->dir_spool_src) {
- case DIR_SPOOL_SERVER_BY_DIGEST:
- case DIR_SPOOL_SERVER_BY_FP:
- return connection_dirserv_add_servers_to_outbuf(conn);
- case DIR_SPOOL_CACHED_DIR:
- return connection_dirserv_add_dir_bytes_to_outbuf(conn);
- case DIR_SPOOL_NETWORKSTATUS:
- return connection_dirserv_add_networkstatus_bytes_to_outbuf(conn);
- case DIR_SPOOL_NONE:
- default:
- return 0;
- }
-}
-
/** Release all storage used by the directory server. */
void
dirserv_free_all(void)
@@ -2012,13 +1683,13 @@ dirserv_free_all(void)
smartlist_free(fingerprint_list);
fingerprint_list = NULL;
}
- cached_dir_decref(the_directory);
+ clear_cached_dir(&the_directory);
clear_cached_dir(&the_runningrouters);
- cached_dir_decref(the_v2_networkstatus);
- cached_dir_decref(cached_directory);
+ clear_cached_dir(&the_v2_networkstatus);
+ clear_cached_dir(&cached_directory);
clear_cached_dir(&cached_runningrouters);
if (cached_v2_networkstatus) {
- digestmap_free(cached_v2_networkstatus, _free_cached_dir);
+ digestmap_free(cached_v2_networkstatus, free_cached_dir);
cached_v2_networkstatus = NULL;
}
}