[or-cvs] Choose directory servers from routerstatus list, not from r...
Nick Mathewson
nickm at seul.org
Wed Dec 14 22:01:00 UTC 2005
Update of /home/or/cvsroot/tor/src/or
In directory moria:/tmp/cvs-serv16688/src/or
Modified Files:
directory.c or.h relay.c routerlist.c
Log Message:
Choose directory servers from routerstatus list, not from routerinfo list. This way, as soon was we have a networkstatus, we can ask a cache to give us routers, rather than needing to ask the directories.
Index: directory.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/directory.c,v
retrieving revision 1.325
retrieving revision 1.326
diff -u -d -r1.325 -r1.326
--- directory.c 14 Dec 2005 20:40:40 -0000 1.325
+++ directory.c 14 Dec 2005 22:00:58 -0000 1.326
@@ -31,11 +31,6 @@
* connection_finished_connecting() in connection.c
*/
static void
-directory_initiate_command_trusted_dir(trusted_dir_server_t *dirserv,
- uint8_t purpose, int private_connection,
- const char *resource,
- const char *payload, size_t payload_len);
-static void
directory_initiate_command(const char *address, uint32_t addr, uint16_t port,
const char *platform,
const char *digest, uint8_t purpose,
@@ -143,10 +138,11 @@
*/
SMARTLIST_FOREACH(dirservers, trusted_dir_server_t *, ds,
{
+ routerstatus_t *rs = &(ds->fake_status);
post_via_tor = purpose_is_private(purpose) ||
!fascist_firewall_allows_address(ds->addr,ds->dir_port);
- directory_initiate_command_trusted_dir(ds, purpose, post_via_tor,
- NULL, payload, payload_len);
+ directory_initiate_command_routerstatus(rs, purpose, post_via_tor,
+ NULL, payload, payload_len);
});
}
@@ -159,8 +155,7 @@
directory_get_from_dirserver(uint8_t purpose, const char *resource,
int retry_if_no_servers)
{
- routerinfo_t *r = NULL;
- trusted_dir_server_t *ds = NULL;
+ routerstatus_t *rs = NULL;
or_options_t *options = get_options();
int fetch_fresh_first = server_mode(options) && options->DirPort != 0;
int directconn = !purpose_is_private(purpose);
@@ -175,19 +170,21 @@
!strcmpstart(resource,"fp/") && strlen(resource) == HEX_DIGEST_LEN+3) {
/* Try to ask the actual dirserver its opinion. */
char digest[DIGEST_LEN];
+ trusted_dir_server_t *ds;
base16_decode(digest, DIGEST_LEN, resource+3, HEX_DIGEST_LEN);
ds = router_get_trusteddirserver_by_digest(digest);
+ rs = &(ds->fake_status);
}
- if (!ds && fetch_fresh_first) {
+ if (!rs && fetch_fresh_first) {
/* only ask authdirservers, and don't ask myself */
- ds = router_pick_trusteddirserver(need_v1_support, 1, 1,
+ rs = router_pick_trusteddirserver(need_v1_support, 1, 1,
retry_if_no_servers);
}
- if (!ds) {
+ if (!rs) {
/* anybody with a non-zero dirport will do */
- r = router_pick_directory_server(1, 1, need_v2_support,
- retry_if_no_servers);
- if (!r) {
+ rs = router_pick_directory_server(1, 1, need_v2_support,
+ retry_if_no_servers);
+ if (!rs) {
const char *which;
if (purpose == DIR_PURPOSE_FETCH_DIR)
which = "directory";
@@ -199,9 +196,9 @@
which = "server descriptors";
info(LD_DIR,
"No router found for %s; falling back to dirserver list", which);
- ds = router_pick_trusteddirserver(1, 1, 1,
+ rs = router_pick_trusteddirserver(1, 1, 1,
retry_if_no_servers);
- if (!ds)
+ if (!rs)
directconn = 0; /* last resort: try routing it via Tor */
}
}
@@ -210,20 +207,18 @@
/* Never use fascistfirewall; we're going via Tor. */
if (purpose == DIR_PURPOSE_FETCH_RENDDESC) {
/* only ask authdirservers, any of them will do */
- ds = router_pick_trusteddirserver(0, 0, 0, retry_if_no_servers);
+ rs = router_pick_trusteddirserver(0, 0, 0, retry_if_no_servers);
} else {
/* anybody with a non-zero dirport will do. Disregard firewalls. */
- r = router_pick_directory_server(1, 0, need_v2_support,
- retry_if_no_servers);
+ rs = router_pick_directory_server(1, 0, need_v2_support,
+ retry_if_no_servers);
+ /* XXXX If no rs, fall back to trusted dir servers? -NM */
}
}
- if (r)
- directory_initiate_command_router(r, purpose, !directconn,
- resource, NULL, 0);
- else if (ds)
- directory_initiate_command_trusted_dir(ds, purpose, !directconn,
- resource, NULL, 0);
+ if (rs)
+ directory_initiate_command_routerstatus(rs, purpose, !directconn,
+ resource, NULL, 0);
else {
notice(LD_DIR,
"No running dirservers known. Will try again later. (purpose %d)",
@@ -247,28 +242,56 @@
* want to fetch.
*/
void
-directory_initiate_command_router(routerinfo_t *router, uint8_t purpose,
- int private_connection, const char *resource,
- const char *payload, size_t payload_len)
+directory_initiate_command_router(routerinfo_t *router,
+ uint8_t purpose,
+ int private_connection,
+ const char *resource,
+ const char *payload,
+ size_t payload_len)
{
directory_initiate_command(router->address, router->addr, router->dir_port,
- router->platform, router->cache_info.identity_digest,
- purpose, private_connection, resource,
- payload, payload_len);
+ router->platform,
+ router->cache_info.identity_digest,
+ purpose, private_connection, resource,
+ payload, payload_len);
}
-/** As directory_initiate_command_router, but send the command to a trusted
- * directory server <b>dirserv</b>. **/
-static void
-directory_initiate_command_trusted_dir(trusted_dir_server_t *dirserv,
- uint8_t purpose, int private_connection,
- const char *resource,
- const char *payload, size_t payload_len)
+/** Launch a new connection to the directory server <b>status</b> to upload or
+ * download a service or rendezvous descriptor. <b>purpose</b> determines what
+ * kind of directory connection we're launching, and must be one of
+ * DIR_PURPOSE_{FETCH|UPLOAD}_{DIR|RENDDESC}.
+ *
+ * When uploading, <b>payload</b> and <b>payload_len</b> determine the content
+ * of the HTTP post. Otherwise, <b>payload</b> should be NULL.
+ *
+ * When fetching a rendezvous descriptor, <b>resource</b> is the service ID we
+ * want to fetch.
+ */
+void
+directory_initiate_command_routerstatus(routerstatus_t *status,
+ uint8_t purpose,
+ int private_connection,
+ const char *resource,
+ const char *payload,
+ size_t payload_len)
{
- directory_initiate_command(dirserv->address, dirserv->addr,
- dirserv->dir_port, NULL, dirserv->digest, purpose,
- private_connection, resource,
- payload, payload_len);
+ const char *platform = NULL;
+ routerinfo_t *router;
+ char address_buf[INET_NTOA_BUF_LEN];
+ struct in_addr in;
+ const char *address;
+ if ((router = router_get_by_digest(status->identity_digest))) {
+ platform = router->platform;
+ address = router->address;
+ } else {
+ in.s_addr = htonl(status->addr);
+ tor_inet_ntoa(&in, address_buf, sizeof(address_buf));
+ address = address_buf;
+ }
+ directory_initiate_command(address, status->addr, status->dir_port,
+ platform, status->identity_digest,
+ purpose, private_connection, resource,
+ payload, payload_len);
}
/** Called when we are unable to complete the client's request to a
Index: or.h
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/or.h,v
retrieving revision 1.756
retrieving revision 1.757
diff -u -d -r1.756 -r1.757
--- or.h 14 Dec 2005 21:03:51 -0000 1.756
+++ or.h 14 Dec 2005 22:00:58 -0000 1.757
@@ -1822,6 +1822,12 @@
const char *resource,
const char *payload,
size_t payload_len);
+void directory_initiate_command_routerstatus(routerstatus_t *status,
+ uint8_t purpose,
+ int private_connection,
+ const char *resource,
+ const char *payload,
+ size_t payload_len);
int parse_http_response(const char *headers, int *code, time_t *date,
int *compression, char **response);
@@ -2183,24 +2189,26 @@
uint16_t dir_port; /**< Directory port */
char digest[DIGEST_LEN]; /**< Digest of identity key */
unsigned int is_running:1; /**< True iff we think this server is running. */
- unsigned int supports_v1_protocol:1; /**< True iff this server is an
- * authority for the older ("v1")
- * directory protocol.*/
+ unsigned int is_v1_authority:1; /**< True iff this server is an
+ * authority for the older ("v1")
+ * directory protocol.*/
int n_networkstatus_failures; /**< How many times have we asked for this
* server's network-status unsuccessfully? */
+ routerstatus_t fake_status; /**< Used when we need to pass this trusted
+ * dir_server_t as a routerstatus_t. */
} trusted_dir_server_t;
int router_reload_router_list(void);
int router_reload_networkstatus(void);
void router_get_trusted_dir_servers(smartlist_t **outp);
-routerinfo_t *router_pick_directory_server(int requireother,
- int fascistfirewall,
- int for_v2_directory,
- int retry_if_no_servers);
-trusted_dir_server_t *router_pick_trusteddirserver(int need_v1_support,
- int requireother,
- int fascistfirewall,
- int retry_if_no_servers);
+routerstatus_t *router_pick_directory_server(int requireother,
+ int fascistfirewall,
+ int for_v2_directory,
+ int retry_if_no_servers);
+routerstatus_t *router_pick_trusteddirserver(int need_v1_authority,
+ int requireother,
+ int fascistfirewall,
+ int retry_if_no_servers);
trusted_dir_server_t *router_get_trusteddirserver_by_digest(
const char *digest);
int all_trusted_directory_servers_down(void);
Index: relay.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/relay.c,v
retrieving revision 1.93
retrieving revision 1.94
diff -u -d -r1.93 -r1.94
--- relay.c 14 Dec 2005 20:40:40 -0000 1.93
+++ relay.c 14 Dec 2005 22:00:58 -0000 1.94
@@ -3,7 +3,8 @@
* Copyright 2004-2005 Roger Dingledine, Nick Mathewson. */
/* See LICENSE for licensing information */
/* $Id$ */
-const char relay_c_id[] = "$Id$";
+const char relay_c_id[] =
+ "$Id$";
/**
* \file relay.c
Index: routerlist.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/routerlist.c,v
retrieving revision 1.390
retrieving revision 1.391
diff -u -d -r1.390 -r1.391
--- routerlist.c 14 Dec 2005 20:40:40 -0000 1.390
+++ routerlist.c 14 Dec 2005 22:00:58 -0000 1.391
@@ -18,11 +18,11 @@
/****************************************************************************/
/* static function prototypes */
-static routerinfo_t *router_pick_directory_server_impl(int requireother,
- int fascistfirewall,
- int for_v2_directory);
-static trusted_dir_server_t *router_pick_trusteddirserver_impl(
- int need_v1_support, int requireother, int fascistfirewall);
+static routerstatus_t *router_pick_directory_server_impl(int requireother,
+ int fascistfirewall,
+ int for_v2_directory);
+static routerstatus_t *router_pick_trusteddirserver_impl(
+ int need_v1_authority, int requireother, int fascistfirewall);
static void mark_all_trusteddirservers_up(void);
static int router_nickname_is_in_list(routerinfo_t *router, const char *list);
static int router_nickname_matches(routerinfo_t *router, const char *nickname);
@@ -321,13 +321,13 @@
* (that is, a trusted dirserver, or one running 0.0.9rc5-cvs or later).
* Other args are as in router_pick_directory_server_impl().
*/
-routerinfo_t *
+routerstatus_t *
router_pick_directory_server(int requireother,
int fascistfirewall,
int for_v2_directory,
int retry_if_no_servers)
{
- routerinfo_t *choice;
+ routerstatus_t *choice;
if (!routerlist)
return NULL;
@@ -358,6 +358,9 @@
return choice;
}
+/** Return the trusted_dir_server_t for the directory authority whose identity
+ * key hashes to <b>digest</b>, or NULL if no such authority is known.
+ */
trusted_dir_server_t *
router_get_trusteddirserver_by_digest(const char *digest)
{
@@ -376,24 +379,26 @@
/** Try to find a running trusted dirserver. If there are no running
* trusted dirservers and <b>retry_if_no_servers</b> is non-zero,
* set them all as running again, and try again.
+ * If <b>need_v1_authority</b> is set, return only trusted servers
+ * that are authorities for the V1 directory protocol.
* Other args are as in router_pick_trusteddirserver_impl().
*/
-trusted_dir_server_t *
-router_pick_trusteddirserver(int need_v1_support,
+routerstatus_t *
+router_pick_trusteddirserver(int need_v1_authority,
int requireother,
int fascistfirewall,
int retry_if_no_servers)
{
- trusted_dir_server_t *choice;
+ routerstatus_t *choice;
- choice = router_pick_trusteddirserver_impl(need_v1_support,
+ choice = router_pick_trusteddirserver_impl(need_v1_authority,
requireother, fascistfirewall);
if (choice || !retry_if_no_servers)
return choice;
info(LD_DIR,"No trusted dirservers are reachable. Trying them all again.");
mark_all_trusteddirservers_up();
- return router_pick_trusteddirserver_impl(need_v1_support,
+ return router_pick_trusteddirserver_impl(need_v1_authority,
requireother, fascistfirewall);
}
@@ -405,37 +410,34 @@
* choose a directory server new enough to support the v2 directory
* functionality.
*/
-static routerinfo_t *
+static routerstatus_t *
router_pick_directory_server_impl(int requireother, int fascistfirewall,
int for_v2_directory)
{
- routerinfo_t *result;
+ routerstatus_t *result;
smartlist_t *sl;
- if (!routerlist)
+ if (!routerstatus_list)
return NULL;
/* Find all the running dirservers we know about. */
sl = smartlist_create();
- SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
+ SMARTLIST_FOREACH(routerstatus_list, local_routerstatus_t *, _local_status,
{
- if (!router->is_running || !router->dir_port || !router->is_verified)
+ routerstatus_t *status = &(_local_status->status);
+ if (!status->is_running || !status->dir_port || !status->is_valid)
continue;
- if (requireother && router_is_me(router))
+ if (requireother && router_digest_is_me(status->identity_digest))
continue;
if (fascistfirewall) {
- if (!fascist_firewall_allows_address(router->addr, router->dir_port))
+ if (!fascist_firewall_allows_address(status->addr, status->dir_port))
continue;
}
- /* Before 0.1.1.6-alpha, only trusted dirservers served status info.
- * Before 0.1.1.7-alpha, retrieving nonexistent server IDs could bork
- * the directory server.
- */
if (for_v2_directory &&
- !(tor_version_as_new_as(router->platform,"0.1.1.7-alpha") ||
- router_digest_is_trusted_dir(router->cache_info.identity_digest)))
+ !(status->is_v2_dir ||
+ router_digest_is_trusted_dir(status->identity_digest)))
continue;
- smartlist_add(sl, router);
+ smartlist_add(sl, status);
});
result = smartlist_choose(sl);
@@ -443,19 +445,19 @@
return result;
}
-/** Choose randomly from among the trusted dirservers that are up.
- * If <b>fascistfirewall</b>,
- * make sure the port we pick is allowed by our firewall options.
- * If <b>requireother</b>, it cannot be us. If <b>need_v1_support</b>, choose
- * a trusted authority for the v1 directory system.
+/** Choose randomly from among the trusted dirservers that are up. If
+ * <b>fascistfirewall</b>, make sure the port we pick is allowed by our
+ * firewall options. If <b>requireother</b>, it cannot be us. If
+ * <b>need_v1_authority</b>, choose a trusted authority for the v1 directory
+ * system.
*/
-static trusted_dir_server_t *
-router_pick_trusteddirserver_impl(int need_v1_support,
+static routerstatus_t *
+router_pick_trusteddirserver_impl(int need_v1_authority,
int requireother, int fascistfirewall)
{
smartlist_t *sl;
routerinfo_t *me;
- trusted_dir_server_t *ds;
+ routerstatus_t *rs;
sl = smartlist_create();
me = router_get_my_routerinfo();
@@ -465,7 +467,7 @@
SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, d,
{
if (!d->is_running) continue;
- if (need_v1_support && !d->supports_v1_protocol)
+ if (need_v1_authority && !d->is_v1_authority)
continue;
if (requireother && me && router_digest_is_me(d->digest))
continue;
@@ -473,12 +475,12 @@
if (!fascist_firewall_allows_address(d->addr, d->dir_port))
continue;
}
- smartlist_add(sl, d);
+ smartlist_add(sl, &d->fake_status);
});
- ds = smartlist_choose(sl);
+ rs = smartlist_choose(sl);
smartlist_free(sl);
- return ds;
+ return rs;
}
/** Go through and mark the authoritative dirservers as up. */
@@ -2526,7 +2528,7 @@
ent->addr = a;
ent->dir_port = port;
ent->is_running = 1;
- ent->supports_v1_protocol = supports_v1;
+ ent->is_v1_authority = supports_v1;
memcpy(ent->digest, digest, DIGEST_LEN);
dlen = 64 + strlen(hostname) + (nickname?strlen(nickname):0);
@@ -2538,6 +2540,16 @@
tor_snprintf(ent->description, dlen, "directory server at %s:%d",
hostname, (int)port);
+ ent->fake_status.addr = ent->addr;
+ memcpy(ent->fake_status.identity_digest, digest, DIGEST_LEN);
+ strlcpy(ent->fake_status.nickname, nickname,
+ sizeof(ent->fake_status.nickname));
+ ent->fake_status.dir_port = ent->dir_port;
+ ent->fake_status.is_running = 1;
+ ent->fake_status.is_named = 1;
+ ent->fake_status.is_valid = 1;
+ ent->fake_status.is_v2_dir = 1;
+
smartlist_add(trusted_dir_servers, ent);
}
@@ -2848,6 +2860,7 @@
*/
while (1) {
int n_running=0, n_named=0, n_valid=0, n_listing=0;
+ int n_v2_dir=0, n_fast=0, n_stable=0, n_exit=0;
const char *the_name = NULL;
local_routerstatus_t *rs_out, *rs_old;
routerstatus_t *rs, *most_recent;
@@ -2902,6 +2915,14 @@
++n_valid;
if (rs->is_running && ns->is_recent)
++n_running;
+ if (rs->is_exit)
+ ++n_exit;
+ if (rs->is_fast)
+ ++n_fast;
+ if (rs->is_stable)
+ ++n_stable;
+ if (rs->is_v2_dir)
+ ++n_v2_dir;
}
rs_out = tor_malloc_zero(sizeof(local_routerstatus_t));
memcpy(&rs_out->status, most_recent, sizeof(routerstatus_t));
@@ -2930,6 +2951,10 @@
sizeof(rs_out->status.nickname));
rs_out->status.is_valid = n_valid > n_statuses/2;
rs_out->status.is_running = n_running > n_recent/2;
+ rs_out->status.is_exit = n_exit > n_statuses/2;
+ rs_out->status.is_fast = n_fast > n_statuses/2;
+ rs_out->status.is_stable = n_stable > n_statuses/2;
+ rs_out->status.is_v2_dir = n_v2_dir > n_statuses/2;
}
SMARTLIST_FOREACH(routerstatus_list, local_routerstatus_t *, rs,
local_routerstatus_free(rs));
More information about the tor-commits
mailing list