[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[or-cvs] Choose directory servers from routerstatus list, not from r...



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));