Browse Source

r15806@catbus: nickm | 2007-10-15 19:14:57 -0400
Implement v3 networkstatus client code. Remove v2 networkstatus client code, except as needed for caches to fetch and serve v2 networkstatues and the routers they list.


svn:r11957

Nick Mathewson 16 years ago
parent
commit
3ad6dc0e2e
12 changed files with 498 additions and 1217 deletions
  1. 5 0
      ChangeLog
  2. 23 2
      doc/TODO
  3. 18 13
      src/or/control.c
  4. 6 7
      src/or/directory.c
  5. 4 4
      src/or/dirserv.c
  6. 2 0
      src/or/dirvote.c
  7. 0 1
      src/or/hibernate.c
  8. 12 9
      src/or/main.c
  9. 263 760
      src/or/networkstatus.c
  10. 30 51
      src/or/or.h
  11. 130 335
      src/or/routerlist.c
  12. 5 35
      src/or/routerparse.c

+ 5 - 0
ChangeLog

@@ -1,4 +1,9 @@
 Changes in version 0.2.0.9-alpha - 2007-10-??
+  o Major features (v3 directory system):
+    - Clients now download v3 consensus networkstatus documents instead
+      of v2 networkstatus documents.  Clients and caches now their opinions
+      about routers on these consensus documents.  Clients only download
+      router descriptors listed in the consensus.
 
   o Major bugfixes:
     - Stop publishing a new server descriptor just because we HUP or

+ 23 - 2
doc/TODO

@@ -69,8 +69,29 @@ Things we'd like to do in 0.2.0.x:
         - Enable for non-caches
       - Code to use v3 networkstatus documents once clients are
         fetching them
-        - Implement
-        - Enable
+        o Make everybody download v3 networkstatus docs.
+        o Make clients not download v2 networkstatus docs.
+        o Make everybody download routerdescs based on v3 networkstatus
+          docs.
+        o Change definition of "have enough information to build circuits"
+        o Base version sanity check on v3 ns.
+        o Change routerstatus_get_by_* to use v3 networkstatus docs.
+        o Make download_status_get_by_descriptor_digest() use v2
+          networkstatus docs too.
+        o Eliminate routerstatus_list.
+        o Make routers_update_all_from_networkstatus() [or equivalent]
+          get called at the right time.
+        o Make  routersstatus_list_update_from_consensus_networkstatus()
+          get renamed and called.
+        o When setting a new consensus, copy the extra fields out of the
+          old consensus (if any).
+        o Update named-server-map as appropriate.
+        - Fix all XXXX020s.
+        - Sort out need_to_mirror
+        - Work hard to make sure clients never look at v2 networkstatus docs.
+        - Check in old_routers before fetching a router status. You never
+          know if we'll flap...
+
       - Controller support
         - GETINFO to get consensus
         - Event when new consensus arrives

+ 18 - 13
src/or/control.c

@@ -1609,33 +1609,38 @@ getinfo_helper_events(control_connection_t *control_conn,
                    check_whether_orport_reachable() ? 1 : 0,
                    check_whether_dirport_reachable() ? 1 : 0);
     } else if (!strcmpstart(question, "status/version/")) {
-      combined_version_status_t st;
       int is_server = server_mode(get_options());
-      char *recommended;
-      recommended = compute_recommended_versions(time(NULL),
-                                                 !is_server, VERSION, &st);
+      networkstatus_vote_t *c = networkstatus_get_latest_consensus();
+      version_status_t status;
+      const char *recommended;
+      if (c) {
+        recommended = is_server ? c->server_versions : c->client_versions;
+        status = tor_version_is_obsolete(VERSION, recommended);
+      } else {
+        recommended = "?";
+        status = VS_UNKNOWN;
+      }
+
       if (!strcmp(question, "status/version/recommended")) {
-        *answer = recommended;
+        *answer = tor_strdup(recommended);
         return 0;
       }
-      tor_free(recommended);
       if (!strcmp(question, "status/version/current")) {
-        switch (st.consensus)
+        switch (status)
           {
           case VS_RECOMMENDED: *answer = tor_strdup("recommended"); break;
           case VS_OLD: *answer = tor_strdup("obsolete"); break;
           case VS_NEW: *answer = tor_strdup("new"); break;
           case VS_NEW_IN_SERIES: *answer = tor_strdup("new in series"); break;
           case VS_UNRECOMMENDED: *answer = tor_strdup("unrecommended"); break;
+          case VS_UNKNOWN: *answer = tor_strdup("unknown"); break;
           default: tor_fragile_assert();
           }
-      } else if (!strcmp(question, "status/version/num-versioning")) {
-        char s[33];
-        tor_snprintf(s, sizeof(s), "%d", st.n_versioning);
-        *answer = tor_strdup(s);
-      } else if (!strcmp(question, "status/version/num-concurring")) {
+      } else if (!strcmp(question, "status/version/num-versioning") ||
+                 !strcmp(question, "status/version/num-concurring")) {
+        /*XXXX020 deprecate.*/
         char s[33];
-        tor_snprintf(s, sizeof(s), "%d", st.n_concurring);
+        tor_snprintf(s, sizeof(s), "%d", get_n_authorities(V3_AUTHORITY));
         *answer = tor_strdup(s);
       }
     } else {

+ 6 - 7
src/or/directory.c

@@ -178,7 +178,7 @@ router_supports_extrainfo(const char *identity_digest, int is_authority)
       return 1;
   }
   if (is_authority) {
-    routerstatus_t *rs = router_get_combined_status_by_digest(identity_digest);
+    routerstatus_t *rs = router_get_consensus_status_by_id(identity_digest);
     if (rs && rs->version_supports_extrainfo_upload)
       return 1;
   }
@@ -1232,7 +1232,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
              "'%s:%d'. I'll try again soon.",
              status_code, escaped(reason), conn->_base.address,
              conn->_base.port);
-    if ((rs = router_get_combined_status_by_digest(conn->identity_digest)))
+    if ((rs = router_get_consensus_status_by_id(conn->identity_digest)))
       rs->last_dir_503_at = now;
     if ((ds = router_get_trusteddirserver_by_digest(conn->identity_digest)))
       ds->fake_status.last_dir_503_at = now;
@@ -1387,7 +1387,7 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
       if (next)
         next[1] = '\0';
       /* learn from it, and then remove it from 'which' */
-      if (router_set_networkstatus(cp, now, source, which)<0)
+      if (router_set_networkstatus_v2(cp, now, source, which)<0)
         break;
       if (next) {
         next[1] = 'n';
@@ -1426,6 +1426,8 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
       networkstatus_consensus_download_failed(0);
       return -1;
     }
+    routers_update_all_from_networkstatus(now); /*launches router downloads*/
+    directory_info_has_arrived(now, 0);
     log_info(LD_DIR, "Successfully loaded consensus.");
   }
   if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
@@ -2790,10 +2792,7 @@ dir_routerdesc_download_failed(smartlist_t *failed, int status_code,
       if (sd)
         dls = &sd->ei_dl_status;
     } else {
-      routerstatus_t *rs =
-        router_get_combined_status_by_descriptor_digest(digest);
-      if (rs)
-        dls = &rs->dl_status;
+      dls = router_get_dl_status_by_descriptor_digest(digest);
     }
     if (!dls || dls->n_download_failures >= MAX_ROUTERDESC_DOWNLOAD_FAILURES)
       continue;

+ 4 - 4
src/or/dirserv.c

@@ -2380,12 +2380,12 @@ generate_networkstatus_opinion(int v2)
   }
 
   {
-    networkstatus_t *ns;
-    if (!(ns = networkstatus_parse_from_string(status))) {
+    networkstatus_v2_t *ns;
+    if (!(ns = networkstatus_v2_parse_from_string(status))) {
       log_err(LD_BUG,"Generated a networkstatus we couldn't parse.");
       goto done;
     }
-    networkstatus_free(ns);
+    networkstatus_v2_free(ns);
   }
 
   {
@@ -2395,7 +2395,7 @@ generate_networkstatus_opinion(int v2)
     *ns_ptr = new_cached_dir(status, now);
     status = NULL; /* So it doesn't get double-freed. */
     the_v2_networkstatus_is_dirty = 0;
-    router_set_networkstatus((*ns_ptr)->dir, now, NS_GENERATED, NULL);
+    router_set_networkstatus_v2((*ns_ptr)->dir, now, NS_GENERATED, NULL);
     r = *ns_ptr;
   }
 

+ 2 - 0
src/or/dirvote.c

@@ -67,6 +67,8 @@ networkstatus_vote_free(networkstatus_vote_t *ns)
 
     smartlist_free(ns->routerstatus_list);
   }
+  if (ns->desc_digest_map)
+    digestmap_free(ns->desc_digest_map, NULL);
 
   memset(ns, 11, sizeof(*ns));
   tor_free(ns);

+ 0 - 1
src/or/hibernate.c

@@ -547,7 +547,6 @@ accounting_set_wakeup_time(void)
 
 /* This rounds 0 up to 1000, but that's actually a feature. */
 #define ROUND_UP(x) (((x) + 0x3ff) & ~0x3ff)
-#define BW_ACCOUNTING_VERSION 1
 /** Save all our bandwidth tracking information to disk. Return 0 on
  * success, -1 on failure. */
 int

+ 12 - 9
src/or/main.c

@@ -995,9 +995,10 @@ run_scheduled_events(time_t now)
      * update all the descriptors' running status. */
     /* purge obsolete entries */
     routerlist_remove_old_routers();
-    networkstatus_list_clean(now);
-    networkstatus_list_update_recent(now);
-    routers_update_all_from_networkstatus(now);
+    networkstatus_v2_list_clean(now);
+#if 0
+    networkstatus_v2_list_update_recent(now);
+#endif
 
     /* Also, once per minute, check whether we want to download any
      * networkstatus documents.
@@ -1339,6 +1340,14 @@ do_main_loop(void)
   stats_prev_global_read_bucket = global_read_bucket;
   stats_prev_global_write_bucket = global_write_bucket;
 
+  if (trusted_dirs_reload_certs())
+    return -1;
+  if (router_reload_v2_networkstatus()) {
+    return -1;
+  }
+  if (router_reload_consensus_networkstatus()) {
+    return -1;
+  }
   /* load the routers file, or assign the defaults. */
   if (router_reload_router_list()) {
     return -1;
@@ -1346,12 +1355,6 @@ do_main_loop(void)
   /* load the networkstatuses. (This launches a download for new routers as
    * appropriate.)
    */
-  if (router_reload_networkstatus()) {
-    return -1;
-  }
-  if (router_reload_consensus_networkstatus()) {
-    return -1;
-  }
   now = time(NULL);
   directory_info_has_arrived(now, 1);
 

File diff suppressed because it is too large
+ 263 - 760
src/or/networkstatus.c


+ 30 - 51
src/or/or.h

@@ -120,12 +120,6 @@
 #define cell_t tor_cell_t
 #endif
 
-/** Undefine this when it's time to stop generating v1 directories. */
-// #define FULL_V1_DIRECTORIES
-/** Undefine this when it's time to stop includeing bandwidth info in router
- * descriptors. */
-#define INCLUDE_BW_INFO_IN_ROUTERDESCS
-
 /** Length of longest allowable configured nickname. */
 #define MAX_NICKNAME_LEN 19
 /** Length of a router identity encoded as a hexadecimal digest, plus
@@ -172,8 +166,6 @@
 #define ROUTER_MAX_AGE_TO_PUBLISH (60*60*20)
 /** How old do we let a saved descriptor get before force-removing it? */
 #define OLD_ROUTER_DESC_MAX_AGE (60*60*24*5)
-/** How old do we let a networkstatus get before ignoring it? */
-#define NETWORKSTATUS_MAX_AGE (60*60*24)
 
 /** Possible rules for generating circuit IDs on an OR connection. */
 typedef enum {
@@ -342,26 +334,24 @@ typedef enum {
 #define DIR_PURPOSE_UPLOAD_RENDDESC 9
 /** A connection to a directory server: upload a v3 networkstatus vote. */
 #define DIR_PURPOSE_UPLOAD_VOTE 10
-/** A connection to a directory server: fetch a v3 networkstatus vote. */
-#define DIR_PURPOSE_FETCH_VOTE 11
 /** A connection to a directory server: upload a v3 consensus signature */
-#define DIR_PURPOSE_UPLOAD_SIGNATURES 12
+#define DIR_PURPOSE_UPLOAD_SIGNATURES 11
 /** A connection to a directory server: download one or more network-status
  * objects */
-#define DIR_PURPOSE_FETCH_STATUS_VOTE 13
+#define DIR_PURPOSE_FETCH_STATUS_VOTE 12
 /** A connection to a directory server: download one or more network-status
  * objects */
-#define DIR_PURPOSE_FETCH_DETACHED_SIGNATURES 14
+#define DIR_PURPOSE_FETCH_DETACHED_SIGNATURES 13
 /** A connection to a directory server: download one or more network-status
  * objects */
-#define DIR_PURPOSE_FETCH_CONSENSUS 15
+#define DIR_PURPOSE_FETCH_CONSENSUS 14
 /** A connection to a directory server: download one or more network-status
  * objects */
-#define DIR_PURPOSE_FETCH_CERTIFICATE 16
+#define DIR_PURPOSE_FETCH_CERTIFICATE 15
 
 /** Purpose for connection at a directory server. */
-#define DIR_PURPOSE_SERVER 17
-#define _DIR_PURPOSE_MAX 17
+#define DIR_PURPOSE_SERVER 16
+#define _DIR_PURPOSE_MAX 16
 
 #define _EXIT_PURPOSE_MIN 1
 /** This exit stream wants to do an ordinary connect. */
@@ -1274,7 +1264,7 @@ typedef struct routerstatus_t {
 #define MAX_ROUTERDESC_DOWNLOAD_FAILURES 8
 
 /** Contents of a v2 (non-consensus, non-vote) network status object. */
-typedef struct networkstatus_t {
+typedef struct networkstatus_v2_t {
   /** When did we receive the network-status document? */
   time_t received_on;
 
@@ -1312,7 +1302,7 @@ typedef struct networkstatus_t {
 
   smartlist_t *entries; /**< List of routerstatus_t*.   This list is kept
                          * sorted by identity_digest. */
-} networkstatus_t;
+} networkstatus_v2_t;
 
 /** The claim about a single router, make in a vote. */
 typedef struct vote_routerstatus_t {
@@ -1385,6 +1375,10 @@ typedef struct networkstatus_vote_t {
    * the elements are vote_routerstatus_t; for a consensus, the elements
    * are routerstatus_t. */
   smartlist_t *routerstatus_list;
+
+  /** If present, a map from descriptor digest to elements of
+   * routerstatus_list. */
+  digestmap_t *desc_digest_map;
 } networkstatus_vote_t;
 
 /** A set of signatures for a networkstatus consensus.  All fields are as for
@@ -1466,7 +1460,6 @@ typedef struct extend_info_t {
                                           * display. */
   char identity_digest[DIGEST_LEN]; /**< Hash of this router's identity key. */
   uint16_t port; /**< OR port. */
-//  uint8_t router_purpose; /**< General, controller, or bridge. */
   uint32_t addr; /**< IP address in host order. */
   crypto_pk_env_t *onion_key; /**< Current onionskin key. */
 } extend_info_t;
@@ -2310,7 +2303,6 @@ extend_info_t *extend_info_alloc(const char *nickname, const char *digest,
                                  crypto_pk_env_t *onion_key,
                                  uint32_t addr, uint16_t port);
 extend_info_t *extend_info_from_router(routerinfo_t *r);
-//extend_info_t *extend_info_from_routerstatus(routerstatus_t *s);
 extend_info_t *extend_info_dup(extend_info_t *info);
 void extend_info_free(extend_info_t *info);
 routerinfo_t *build_state_get_exit_router(cpath_build_state_t *state);
@@ -3058,52 +3050,43 @@ typedef enum version_status_t {
   VS_NEW_IN_SERIES=3, /**< This version is newer than any recommended version
                        * in its series, but later recommended versions exist.
                        */
-  VS_UNRECOMMENDED=4 /**< This version is not recommended (general case). */
+  VS_UNRECOMMENDED=4, /**< This version is not recommended (general case). */
+  VS_UNKNOWN, /**< We have no idea. */
 } version_status_t;
 
-typedef struct combined_version_status_t {
-  /** How many networkstatuses claim to know about versions? */
-  int n_versioning;
-  /** What do the majority of networkstatuses believe about this version? */
-  enum version_status_t consensus;
-  /** How many networkstatuses constitute the majority? */
-  int n_concurring;
-} combined_version_status_t;
-
 void networkstatus_reset_warnings(void);
-int router_reload_networkstatus(void);
+void networkstatus_reset_download_failures(void);
+int router_reload_v2_networkstatus(void);
 int router_reload_consensus_networkstatus(void);
 void routerstatus_free(routerstatus_t *rs);
-void networkstatus_free(networkstatus_t *ns);
+void networkstatus_v2_free(networkstatus_v2_t *ns);
 char *networkstatus_get_cache_filename(const char *identity_digest);
-int router_set_networkstatus(const char *s, time_t arrived_at,
+int router_set_networkstatus_v2(const char *s, time_t arrived_at,
                              networkstatus_source_t source,
                              smartlist_t *requested_fingerprints);
-void networkstatus_list_clean(time_t now);
-routerstatus_t *networkstatus_find_entry(networkstatus_t *ns,
+void networkstatus_v2_list_clean(time_t now);
+routerstatus_t *networkstatus_v2_find_entry(networkstatus_v2_t *ns,
                                          const char *digest);
+routerstatus_t *networkstatus_vote_find_entry(networkstatus_vote_t *ns,
+                                              const char *digest);
 const smartlist_t *networkstatus_get_v2_list(void);
-const smartlist_t *networkstatus_get_all_statuses(void);
-routerstatus_t *router_get_combined_status_by_digest(const char *digest);
-routerstatus_t *router_get_combined_status_by_descriptor_digest(const char *d);
-routerstatus_t *router_get_combined_status_by_nickname(const char *nickname,
+download_status_t *router_get_dl_status_by_descriptor_digest(const char *d);
+routerstatus_t *router_get_consensus_status_by_id(const char *digest);
+routerstatus_t *router_get_consensus_status_by_descriptor_digest(
+                                                        const char *digest);
+routerstatus_t *router_get_consensus_status_by_nickname(const char *nickname,
                                                        int warn_if_unnamed);
 const char *networkstatus_get_router_digest_by_nickname(const char *nickname);
-routerstatus_t *routerstatus_get_by_hexdigest(const char *hexdigest);
 void networkstatus_consensus_download_failed(int status_code);
 int should_delay_dir_fetches(or_options_t *options);
 void update_networkstatus_downloads(time_t now);
-networkstatus_t *networkstatus_get_by_digest(const char *digest);
+networkstatus_v2_t *networkstatus_v2_get_by_digest(const char *digest);
 networkstatus_vote_t *networkstatus_get_latest_consensus(void);
 networkstatus_vote_t *networkstatus_get_live_consensus(time_t now);
 int networkstatus_set_current_consensus(const char *consensus, int from_cache,
                                         int was_waiting_for_certs);
 void networkstatus_note_certs_arrived(void);
 void routers_update_all_from_networkstatus(time_t now);
-void networkstatus_list_update_recent(time_t now);
-void routerstatus_list_update_from_networkstatus(time_t now);
-void routers_update_status_from_networkstatus(smartlist_t *routers,
-                                              int reset_failures);
 void routerstatus_list_update_from_consensus_networkstatus(time_t now);
 void routers_update_status_from_consensus_networkstatus(smartlist_t *routers,
                                                         int reset_failures);
@@ -3628,9 +3611,6 @@ void add_trusted_dir_server(const char *nickname, const char *address,
                        authority_type_t type);
 void clear_trusted_dir_servers(void);
 int any_trusted_dir_is_v1_authority(void);
-char *compute_recommended_versions(time_t now, int client,
-                                   const char *my_version,
-                                   combined_version_status_t *status_out);
 void update_router_descriptor_downloads(time_t now);
 void update_extrainfo_downloads(time_t now);
 int router_have_minimum_dir_info(void);
@@ -3695,7 +3675,6 @@ addr_policy_t *router_parse_addr_policy_from_string(const char *s,
                                                     int assume_action);
 version_status_t tor_version_is_obsolete(const char *myversion,
                                          const char *versionlist);
-version_status_t version_status_join(version_status_t a, version_status_t b);
 int tor_version_parse(const char *s, tor_version_t *out);
 int tor_version_as_new_as(const char *platform, const char *cutoff);
 int tor_version_compare(tor_version_t *a, tor_version_t *b);
@@ -3703,7 +3682,7 @@ void sort_version_list(smartlist_t *lst, int remove_duplicates);
 void assert_addr_policy_ok(addr_policy_t *t);
 void dump_distinct_digest_count(int severity);
 
-networkstatus_t *networkstatus_parse_from_string(const char *s);
+networkstatus_v2_t *networkstatus_v2_parse_from_string(const char *s);
 networkstatus_vote_t *networkstatus_parse_vote_from_string(const char *s,
                                                           const char **eos_out,
                                                           int is_vote);

+ 130 - 335
src/or/routerlist.c

@@ -468,6 +468,7 @@ router_rebuild_store(int force, desc_store_t *store)
   int r = -1;
   off_t offset = 0;
   smartlist_t *signed_descriptors = NULL;
+  int nocache=0;
 
   if (!force && !router_should_rebuild_store(store))
     return 0;
@@ -506,11 +507,9 @@ router_rebuild_store(int force, desc_store_t *store)
     }
   } else {
     SMARTLIST_FOREACH(routerlist->old_routers, signed_descriptor_t *, sd,
-                      if (desc_get_store(routerlist, sd) == store)
-                        smartlist_add(signed_descriptors, sd));
+                      smartlist_add(signed_descriptors, sd));
     SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, ri,
-                      if (router_get_store(routerlist, ri) == store)
-                        smartlist_add(signed_descriptors, &ri->cache_info));
+                      smartlist_add(signed_descriptors, &ri->cache_info));
   }
 
   smartlist_sort(signed_descriptors, _compare_signed_descriptors_by_age);
@@ -524,8 +523,10 @@ router_rebuild_store(int force, desc_store_t *store)
         log_warn(LD_BUG, "No descriptor available for router.");
         goto done;
       }
-      if (sd->do_not_cache)
+      if (sd->do_not_cache) {
+        ++nocache;
         continue;
+      }
       c = tor_malloc(sizeof(sized_chunk_t));
       c->bytes = body;
       c->len = sd->signed_descriptor_len + sd->annotations_len;
@@ -549,8 +550,10 @@ router_rebuild_store(int force, desc_store_t *store)
   }
 
   store->mmap = tor_mmap_file(fname);
-  if (! store->mmap)
+  if (! store->mmap) {
     log_warn(LD_FS, "Unable to mmap new descriptor file at '%s'.",fname);
+    //tor_assert(0);
+  }
 
   log_info(LD_DIR, "Reconstructing pointers into cache");
 
@@ -688,8 +691,6 @@ router_reload_router_list(void)
     return -1;
   if (router_reload_router_list_impl(&rl->extrainfo_store))
     return -1;
-  if (trusted_dirs_reload_certs())
-    return -1;
   return 0;
 }
 
@@ -844,7 +845,10 @@ router_pick_directory_server_impl(int requireother, int fascistfirewall,
   smartlist_t *trusted_direct, *trusted_tunnel;
   smartlist_t *overloaded_direct, *overloaded_tunnel;
   time_t now = time(NULL);
-  const smartlist_t *routerstatus_list = networkstatus_get_all_statuses();
+  const networkstatus_vote_t *consensus = networkstatus_get_latest_consensus();
+
+  if (!consensus)
+    return NULL;
 
   direct = smartlist_create();
   tunnel = smartlist_create();
@@ -854,7 +858,7 @@ router_pick_directory_server_impl(int requireother, int fascistfirewall,
   overloaded_tunnel = smartlist_create();
 
   /* Find all the running dirservers we know about. */
-  SMARTLIST_FOREACH(routerstatus_list, routerstatus_t *, status,
+  SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, status,
   {
     int is_trusted;
     int is_overloaded = status->last_dir_503_at + DIR_503_TIMEOUT > now;
@@ -997,7 +1001,7 @@ mark_all_trusteddirservers_up(void)
       routerstatus_t *rs;
       dir->is_running = 1;
       download_status_reset(&dir->v2_ns_dl_status);
-      rs = router_get_combined_status_by_digest(dir->digest);
+      rs = router_get_consensus_status_by_id(dir->digest);
       if (rs && !rs->is_running) {
         rs->is_running = 1;
         rs->last_dir_503_at = 0;
@@ -1147,7 +1151,7 @@ add_nickname_list_to_smartlist(smartlist_t *sl, const char *list,
       if (!must_be_running || router->is_running) {
         smartlist_add(sl,router);
       }
-    } else if (!router_get_combined_status_by_nickname(nick,1)) {
+    } else if (!router_get_consensus_status_by_nickname(nick,1)) {
       if (!warned) {
         log_fn(have_dir_info ? LOG_WARN : LOG_INFO, LD_CONFIG,
                "Nickname list includes '%s' which isn't a known router.",nick);
@@ -1714,6 +1718,8 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
     return rimap_get(routerlist->identity_map, named_digest);
   }
 
+  /* If we reach this point, there's no canonical value for the nickname. */
+
   SMARTLIST_FOREACH(routerlist->routers, routerinfo_t *, router,
   {
     if (!strcasecmp(router->nickname, nickname)) {
@@ -1742,7 +1748,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
           char fp[HEX_DIGEST_LEN+1];
           if (strcasecmp(router->nickname, nickname))
             continue;
-          rs = router_get_combined_status_by_digest(
+          rs = router_get_consensus_status_by_id(
                                           router->cache_info.identity_digest);
           if (rs && !rs->name_lookup_warned) {
             rs->name_lookup_warned = 1;
@@ -1768,7 +1774,7 @@ router_get_by_nickname(const char *nickname, int warn_if_unnamed)
       SMARTLIST_FOREACH(fps, char *, cp, tor_free(cp));
       smartlist_free(fps);
     } else if (warn_if_unnamed) {
-      routerstatus_t *rs = router_get_combined_status_by_digest(
+      routerstatus_t *rs = router_get_consensus_status_by_id(
           best_match->cache_info.identity_digest);
       if (rs && !rs->name_lookup_warned) {
         char fp[HEX_DIGEST_LEN+1];
@@ -2134,15 +2140,6 @@ dump_routerlist_mem_usage(int severity)
       smartlist_len(routerlist->old_routers), U64_PRINTF_ARG(olddescs));
 }
 
-/** Return the greatest number of routerdescs we'll hold for any given router.
- */
-static int
-max_descriptors_per_router(void)
-{
-  int n_authorities = get_n_v2_authorities();
-  return (n_authorities < 5) ? 5 : n_authorities;
-}
-
 /** Return non-zero if we have a lot of extra descriptors in our
  * routerlist, and should get rid of some of them. Else return 0.
  *
@@ -2154,8 +2151,12 @@ max_descriptors_per_router(void)
 static INLINE int
 routerlist_is_overfull(routerlist_t *rl)
 {
-  return smartlist_len(rl->old_routers) >
-    smartlist_len(rl->routers)*(max_descriptors_per_router()+1);
+  /*XXXX020 no longer wholly logical.*/
+  if (dirserver_mode(get_options())) {
+    return smartlist_len(rl->old_routers) > smartlist_len(rl->routers)*5;
+  } else {
+    return smartlist_len(rl->old_routers) > smartlist_len(rl->routers)*2;
+  }
 }
 
 static INLINE int
@@ -2541,7 +2542,7 @@ router_set_status(const char *digest, int up)
                "addresses reachable?");
     router->is_running = up;
   }
-  status = router_get_combined_status_by_digest(digest);
+  status = router_get_consensus_status_by_id(digest);
   if (status && status->is_running != up) {
     status->is_running = up;
     control_event_networkstatus_changed_single(status);
@@ -2574,8 +2575,8 @@ router_set_status(const char *digest, int up)
  * server or via the controller.)
  *
  * This function should be called *after*
- * routers_update_status_from_networkstatus; subsequently, you should call
- * router_rebuild_store and routerlist_descriptors_added.
+ * routers_update_status_from_consensus_networkstatus; subsequently, you
+ * should call router_rebuild_store and routerlist_descriptors_added.
  */
 int
 router_add_to_routerlist(routerinfo_t *router, const char **msg,
@@ -2590,7 +2591,9 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
   int authdir_may_warn_about_unreachable_server =
     authdir && !from_cache && !from_fetch &&
     router_have_minimum_dir_info();
-  const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
+  networkstatus_vote_t *consensus = networkstatus_get_latest_consensus();
+  const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
+  int in_consensus = 0;
 
   tor_assert(msg);
 
@@ -2644,15 +2647,37 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
   }
 
   /* We no longer need a router with this descriptor digest. */
-  SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
+  SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
   {
     routerstatus_t *rs =
-      networkstatus_find_entry(ns, router->cache_info.identity_digest);
+      networkstatus_v2_find_entry(ns, router->cache_info.identity_digest);
     if (rs && !memcmp(rs->descriptor_digest,
                       router->cache_info.signed_descriptor_digest,
                       DIGEST_LEN))
       rs->need_to_mirror = 0;
   });
+  if (consensus) {
+    routerstatus_t *rs = networkstatus_vote_find_entry(consensus,
+                                        router->cache_info.identity_digest);
+    if (rs && !memcmp(rs->descriptor_digest,
+                      router->cache_info.signed_descriptor_digest,
+                      DIGEST_LEN)) {
+      in_consensus = 1;
+      rs->need_to_mirror = 0;
+    }
+  }
+
+  /*XXXX020 I had suspicions about whether this was correct, but now I
+   * can't remember why. :( -NM */
+  if (consensus && !in_consensus && !authdir_mode(get_options())) {
+    /* If it's not listed in the consensus, then don't consider replacing
+     * the latest router with it. */
+    if (!from_cache && should_cache_old_descriptors())
+      signed_desc_append_to_journal(&router->cache_info,
+                                    router_get_store(routerlist, router));
+    routerlist_insert_old(routerlist, router);
+    return -1;
+  }
 
   /* If we have a router with the same identity key, choose the newer one. */
   old_router = rimap_get(routerlist->identity_map,
@@ -2802,7 +2827,7 @@ routerlist_remove_old_cached_routers_with_id(time_t cutoff, int lo, int hi,
 
   /* Check whether we need to do anything at all. */
   {
-    int mdpr = max_descriptors_per_router();
+    int mdpr = dirserver_mode(get_options()) ? 5 : 2;
     if (n <= mdpr)
       return;
     n_extra = n - mdpr;
@@ -2874,11 +2899,13 @@ routerlist_remove_old_routers(void)
   routerinfo_t *router;
   signed_descriptor_t *sd;
   digestmap_t *retain;
-  const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
+  int dirserv = dirserver_mode(get_options());
+  const networkstatus_vote_t *consensus = networkstatus_get_latest_consensus();
+  const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
 
   trusted_dirs_remove_old_certs();
 
-  if (!routerlist || !networkstatus_list)
+  if (!routerlist || !consensus)
     return;
 
   routerlist_assert_ok(routerlist);
@@ -2886,7 +2913,8 @@ routerlist_remove_old_routers(void)
   retain = digestmap_new();
   cutoff = now - OLD_ROUTER_DESC_MAX_AGE;
   /* Build a list of all the descriptors that _anybody_ lists. */
-  SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
+  if (dirserv) {
+    SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
     {
       /* XXXX The inner loop here gets pretty expensive, and actually shows up
        * on some profiles.  It may be the reason digestmap_set shows up in
@@ -2900,22 +2928,21 @@ routerlist_remove_old_routers(void)
         if (rs->published_on >= cutoff)
           digestmap_set(retain, rs->descriptor_digest, (void*)1));
     });
+  }
 
-  {
-    /* Retain anything listed in the consensus. */
-    networkstatus_vote_t *ns = networkstatus_get_latest_consensus();
-    if (ns) {
-      SMARTLIST_FOREACH(ns->routerstatus_list, routerstatus_t *, rs,
+  /* Retain anything listed in the consensus. */
+  if (consensus) {
+    SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs,
         if (rs->published_on >= cutoff)
           digestmap_set(retain, rs->descriptor_digest, (void*)1));
-    }
   }
 
   /* If we have a bunch of networkstatuses, we should consider pruning current
    * routers that are too old and that nobody recommends.  (If we don't have
    * enough networkstatuses, then we should get more before we decide to kill
    * routers.) */
-  if (smartlist_len(networkstatus_list) > get_n_v2_authorities() / 2) {
+  if (!dirserv ||
+      smartlist_len(networkstatus_v2_list) > get_n_v2_authorities() / 2) {
     cutoff = now - ROUTER_MAX_AGE;
     /* Remove too-old unrecommended members of routerlist->routers. */
     for (i = 0; i < smartlist_len(routerlist->routers); ++i) {
@@ -2955,7 +2982,7 @@ routerlist_remove_old_routers(void)
    * total number doesn't approach max_descriptors_per_router()*len(router).
    */
   if (smartlist_len(routerlist->old_routers) <
-      smartlist_len(routerlist->routers) * (max_descriptors_per_router() - 1))
+      smartlist_len(routerlist->routers) * (dirserver_mode(get_options())?4:2))
     goto done;
 
   smartlist_sort(routerlist->old_routers, _compare_old_routers_by_identity);
@@ -3040,7 +3067,7 @@ router_load_single_router(const char *s, uint8_t purpose, int cache,
 
   lst = smartlist_create();
   smartlist_add(lst, ri);
-  routers_update_status_from_networkstatus(lst, 0);
+  routers_update_status_from_consensus_networkstatus(lst, 0);
 
   if ((r=router_add_to_routerlist(ri, msg, 0, 0))<0) {
     /* we've already assigned to *msg now, and ri is already freed */
@@ -3086,7 +3113,7 @@ router_load_routers_from_string(const char *s, const char *eos,
   router_parse_list_from_string(&s, eos, routers, saved_location, 0,
                                 allow_annotations, prepend_annotations);
 
-  routers_update_status_from_networkstatus(routers, !from_cache);
+  routers_update_status_from_consensus_networkstatus(routers, !from_cache);
 
   log_info(LD_DIR, "%d elements to add", smartlist_len(routers));
 
@@ -3171,16 +3198,26 @@ static int
 signed_desc_digest_is_recognized(signed_descriptor_t *desc)
 {
   routerstatus_t *rs;
-  const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
+  networkstatus_vote_t *consensus = networkstatus_get_latest_consensus();
+  int dirserv = dirserver_mode(get_options());
+  const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
 
-  SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
-  {
-    if (!(rs = networkstatus_find_entry(ns, desc->identity_digest)))
-      continue;
-    if (!memcmp(rs->descriptor_digest,
-                desc->signed_descriptor_digest, DIGEST_LEN))
+  if (consensus) {
+    rs = networkstatus_vote_find_entry(consensus, desc->identity_digest);
+    if (rs && !memcmp(rs->descriptor_digest,
+                      desc->signed_descriptor_digest, DIGEST_LEN))
       return 1;
-  });
+  }
+  if (dirserv && networkstatus_v2_list) {
+    SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
+    {
+      if (!(rs = networkstatus_v2_find_entry(ns, desc->identity_digest)))
+        continue;
+      if (!memcmp(rs->descriptor_digest,
+                  desc->signed_descriptor_digest, DIGEST_LEN))
+        return 1;
+    });
+  }
   return 0;
 }
 
@@ -3336,103 +3373,6 @@ any_trusted_dir_is_v1_authority(void)
   return 0;
 }
 
-/** Return a newly allocated string naming the versions of Tor recommended by
- * more than half the versioning networkstatuses. */
-char *
-compute_recommended_versions(time_t now, int client,
-                             const char *my_version,
-                             combined_version_status_t *status_out)
-{
-  int n_seen;
-  char *current;
-  smartlist_t *combined, *recommended;
-  int n_versioning, n_recommending;
-  char *result;
-  /** holds the compromise status taken among all non-recommending
-   * authorities */
-  version_status_t consensus = VS_RECOMMENDED;
-  const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
-  (void) now; /* right now, we consider *all* statuses, regardless of age. */
-
-  tor_assert(my_version);
-  tor_assert(status_out);
-
-  memset(status_out, 0, sizeof(combined_version_status_t));
-
-  if (!networkstatus_list)
-    return tor_strdup("<none>");
-
-  combined = smartlist_create();
-  n_versioning = n_recommending = 0;
-  SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
-    {
-      const char *vers;
-      smartlist_t *versions;
-      version_status_t status;
-      if (! ns->recommends_versions)
-        continue;
-      n_versioning++;
-      vers = client ? ns->client_versions : ns->server_versions;
-      if (!vers)
-        continue;
-      versions = smartlist_create();
-      smartlist_split_string(versions, vers, ",",
-                             SPLIT_SKIP_SPACE|SPLIT_IGNORE_BLANK, 0);
-      sort_version_list(versions, 1);
-      smartlist_add_all(combined, versions);
-      smartlist_free(versions);
-
-      /* now, check _our_ version */
-      status = tor_version_is_obsolete(my_version, vers);
-      if (status == VS_RECOMMENDED)
-        n_recommending++;
-      consensus = version_status_join(status, consensus);
-    });
-
-  sort_version_list(combined, 0);
-
-  current = NULL;
-  n_seen = 0;
-  recommended = smartlist_create();
-  SMARTLIST_FOREACH(combined, char *, cp,
-    {
-      if (current && !strcmp(cp, current)) {
-        ++n_seen;
-      } else {
-        if (current)
-          log_info(LD_DIR,"version %s is recommended by %d authorities",
-                    current, n_seen);
-        if (n_seen > n_versioning/2 && current) {
-          smartlist_add(recommended, current);
-        }
-        n_seen = 1;
-        current = cp;
-      }
-    });
-  if (current)
-    log_info(LD_DIR,"version %s is recommended by %d authorities",
-             current, n_seen);
-  if (n_seen > n_versioning/2 && current)
-    smartlist_add(recommended, current);
-
-  result = smartlist_join_strings(recommended, ", ", 0, NULL);
-
-  SMARTLIST_FOREACH(combined, char *, cp, tor_free(cp));
-  smartlist_free(combined);
-  smartlist_free(recommended);
-
-  status_out->n_versioning = n_versioning;
-  if (n_recommending > n_versioning/2) {
-    status_out->consensus = VS_RECOMMENDED;
-    status_out->n_concurring = n_recommending;
-  } else {
-    status_out->consensus = consensus;
-    status_out->n_concurring = n_versioning - n_recommending;
-  }
-
-  return result;
-}
-
 /** DOCDOC */
 static void
 list_pending_downloads(digestmap_t *result,
@@ -3541,128 +3481,26 @@ client_would_use_router(routerstatus_t *rs, time_t now, or_options_t *options)
   return 1;
 }
 
-/** Return new list of ID fingerprints for routers that we (as a client) would
- * like to download.
+/** Max amount of hashes to download per request.
+ * Since squid does not like URLs >= 4096 bytes we limit it to 96.
+ *   4096 - strlen(http://255.255.255.255/tor/server/d/.z) == 4058
+ *   4058/41 (40 for the hash and 1 for the + that separates them) => 98
+ *   So use 96 because it's a nice number.
  */
-static smartlist_t *
-router_list_client_downloadable(void)
-{
-  int n_downloadable = 0;
-  smartlist_t *downloadable = smartlist_create();
-  digestmap_t *downloading;
-  time_t now = time(NULL);
-  /* these are just used for logging */
-  int n_not_ready = 0, n_in_progress = 0, n_uptodate = 0, n_wouldnt_use = 0;
-  or_options_t *options = get_options();
-  const smartlist_t *routerstatus_list = networkstatus_get_all_statuses();
-
-  if (!smartlist_len(routerstatus_list))
-    return downloadable;
-
-  downloading = digestmap_new();
-  list_pending_descriptor_downloads(downloading, 0);
-
-  routerstatus_list_update_from_networkstatus(now);
-  SMARTLIST_FOREACH(routerstatus_list, routerstatus_t *, rs,
-  {
-    routerinfo_t *ri;
-    if (router_get_by_descriptor_digest(rs->descriptor_digest)) {
-      /* We have the 'best' descriptor for this router. */
-      ++n_uptodate;
-    } else if (!client_would_use_router(rs, now, options)) {
-      /* We wouldn't want this descriptor even if we got it. */
-      ++n_wouldnt_use;
-    } else if (digestmap_get(downloading, rs->descriptor_digest)) {
-      /* We're downloading this one now. */
-      ++n_in_progress;
-    } else if ((ri = router_get_by_digest(rs->identity_digest)) &&
-               ri->cache_info.published_on > rs->published_on) {
-      /* Oddly, we have a descriptor more recent than the 'best' one, but it
-         was once best. So that's okay. */
-      ++n_uptodate;
-    } else if (!download_status_is_ready(&rs->dl_status, now,
-                                         MAX_ROUTERDESC_DOWNLOAD_FAILURES)) {
-      /* We failed too recently to try again. */
-      ++n_not_ready;
-    } else {
-      /* Okay, time to try it. */
-      smartlist_add(downloadable, rs->descriptor_digest);
-      ++n_downloadable;
-    }
-  });
-
-#if 0
-  log_info(LD_DIR,
-       "%d router descriptors are downloadable. "
-       "%d are in progress. %d are up-to-date. "
-       "%d are non-useful. %d failed too recently to retry.",
-       n_downloadable, n_in_progress, n_uptodate,
-       n_wouldnt_use, n_not_ready);
-#endif
-
-  digestmap_free(downloading, NULL);
-  return downloadable;
-}
-
-/** Initiate new router downloads as needed, using the strategy for
- * non-directory-servers.
- *
- * We don't launch any downloads if there are fewer than MAX_DL_TO_DELAY
- * descriptors to get and less than MAX_CLIENT_INTERVAL_WITHOUT_REQUEST
- * seconds have passed.
- *
- * Otherwise, we ask for all descriptors that we think are different from what
- * we have, and that we don't currently have an in-progress download attempt
- * for. */
-static void
-update_router_descriptor_client_downloads(time_t now)
-{
-  /** Max amount of hashes to download per request.
-   * Since squid does not like URLs >= 4096 bytes we limit it to 96.
-   *   4096 - strlen(http://255.255.255.255/tor/server/d/.z) == 4058
-   *   4058/41 (40 for the hash and 1 for the + that separates them) => 98
-   *   So use 96 because it's a nice number.
-   */
 #define MAX_DL_PER_REQUEST 96
-  /** Don't split our requests so finely that we are requesting fewer than
-   * this number per server. */
+/** Don't split our requests so finely that we are requesting fewer than
+ * this number per server. */
 #define MIN_DL_PER_REQUEST 4
-  /** To prevent a single screwy cache from confusing us by selective reply,
-   * try to split our requests into at least this this many requests. */
+/** To prevent a single screwy cache from confusing us by selective reply,
+ * try to split our requests into at least this this many requests. */
 #define MIN_REQUESTS 3
-  /** If we want fewer than this many descriptors, wait until we
-   * want more, or until MAX_CLIENT_INTERVAL_WITHOUT_REQUEST has
-   * passed. */
+/** If we want fewer than this many descriptors, wait until we
+ * want more, or until MAX_CLIENT_INTERVAL_WITHOUT_REQUEST has
+ * passed. */
 #define MAX_DL_TO_DELAY 16
-  /** When directory clients have only a few servers to request, they batch
-   * them until they have more, or until this amount of time has passed. */
+/** When directory clients have only a few servers to request, they batch
+ * them until they have more, or until this amount of time has passed. */
 #define MAX_CLIENT_INTERVAL_WITHOUT_REQUEST (10*60)
-  smartlist_t *downloadable = NULL;
-  or_options_t *options = get_options();
-  const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
-
-  if (dirserver_mode(options)) {
-    log_warn(LD_BUG,
-             "Called router_descriptor_client_downloads() on a dir mirror?");
-  }
-
-  if (rep_hist_circbuilding_dormant(now)) {
-//    log_info(LD_CIRC, "Skipping descriptor downloads: we haven't needed "
-//             "any circuits lately.");
-    return;
-  }
-
-  if (networkstatus_list &&
-      smartlist_len(networkstatus_list) <= get_n_v2_authorities()/2) {
-    log_info(LD_DIR,
-             "Not enough networkstatus documents to launch requests.");
-    return;
-  }
-
-  downloadable = router_list_client_downloadable();
-  launch_router_descriptor_downloads(downloadable, now);
-  smartlist_free(downloadable);
-}
 
 /** DOCDOC */
 static void
@@ -3734,18 +3572,18 @@ update_router_descriptor_cache_downloads(time_t now)
   int i, j, n;
   int n_download;
   or_options_t *options = get_options();
-  const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
+  const smartlist_t *networkstatus_v2_list = networkstatus_get_v2_list();
 
   if (! dirserver_mode(options)) {
     log_warn(LD_BUG, "Called update_router_descriptor_cache_downloads() "
              "on a non-dir-mirror?");
   }
 
-  if (!networkstatus_list || !smartlist_len(networkstatus_list))
+  if (!networkstatus_v2_list || !smartlist_len(networkstatus_v2_list))
     return;
 
   map = digestmap_new();
-  n = smartlist_len(networkstatus_list);
+  n = smartlist_len(networkstatus_v2_list);
 
   downloadable = tor_malloc_zero(sizeof(smartlist_t*) * n);
   download_from = tor_malloc_zero(sizeof(smartlist_t*) * n);
@@ -3760,7 +3598,7 @@ update_router_descriptor_cache_downloads(time_t now)
    * descriptor from the corresponding authority.
    */
   n_download = 0;
-  SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
+  SMARTLIST_FOREACH(networkstatus_v2_list, networkstatus_v2_t *, ns,
     {
       trusted_dir_server_t *ds;
       smartlist_t *dl;
@@ -3837,7 +3675,7 @@ update_router_descriptor_cache_downloads(time_t now)
 
   /* Now, we can actually launch our requests. */
   for (i=0; i<n; ++i) {
-    networkstatus_t *ns = smartlist_get(networkstatus_list, i);
+    networkstatus_v2_t *ns = smartlist_get(networkstatus_v2_list, i);
     trusted_dir_server_t *ds =
       router_get_trusteddirserver_by_digest(ns->identity_digest);
     smartlist_t *dl = download_from[i];
@@ -3874,7 +3712,7 @@ update_consensus_router_descriptor_downloads(time_t now)
   smartlist_t *downloadable = smartlist_create();
   int authdir = authdir_mode(options);
   int dirserver = dirserver_mode(options);
-  networkstatus_vote_t *consensus = networkstatus_get_latest_consensus();
+  networkstatus_vote_t *consensus = networkstatus_get_live_consensus(now);
 
   if (!dirserver) {
     if (rep_hist_circbuilding_dormant(now))
@@ -3887,17 +3725,9 @@ update_consensus_router_descriptor_downloads(time_t now)
   list_pending_descriptor_downloads(map, 0);
   SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs,
     {
-      routerstatus_t *lrs;
       if (router_get_by_descriptor_digest(rs->descriptor_digest))
         continue; /* We have it already. */
-
-      /* XXXX020 change this once the real consensus is the canonical place
-       * to go for router information. */
-      lrs = router_get_combined_status_by_digest(rs->identity_digest);
-      if (!lrs ||
-          memcmp(lrs->descriptor_digest, rs->descriptor_digest, DIGEST_LEN))
-        lrs = rs;
-      if (!download_status_is_ready(&lrs->dl_status, now,
+      if (!download_status_is_ready(&rs->dl_status, now,
                                     MAX_ROUTERDESC_DOWNLOAD_FAILURES))
         continue;
 
@@ -3925,10 +3755,8 @@ update_router_descriptor_downloads(time_t now)
     return;
   if (dirserver_mode(options)) {
     update_router_descriptor_cache_downloads(now);
-    update_consensus_router_descriptor_downloads(now); /*XXXX020 clients too*/
-  } else {
-    update_router_descriptor_client_downloads(now);
   }
+  update_consensus_router_descriptor_downloads(now);
 }
 
 /** Return true iff <b>sd</b> is the descriptor for a router descriptor that
@@ -3990,19 +3818,6 @@ update_extrainfo_downloads(time_t now)
   smartlist_free(wanted);
 }
 
-/** Return the number of routerstatus_t in <b>entries</b> that we'd actually
- * use. */
-static int
-routerstatus_count_usable_entries(smartlist_t *entries)
-{
-  int count = 0;
-  time_t now = time(NULL);
-  or_options_t *options = get_options();
-  SMARTLIST_FOREACH(entries, routerstatus_t *, rs,
-                    if (client_would_use_router(rs, now, options)) count++);
-  return count;
-}
-
 /** True iff, the last time we checked whether we had enough directory info
  * to build circuits, the answer was "yes". */
 static int have_min_dir_info = 0;
@@ -4041,20 +3856,18 @@ router_dir_info_changed(void)
 static void
 update_router_have_minimum_dir_info(void)
 {
-  int tot = 0, num_running = 0;
-  int n_ns, n_authorities, res, avg;
+  /*XXX020 call when dirserver_mode() changes. */
+  int num_present = 0, num_usable=0;
   time_t now = time(NULL);
-  const smartlist_t *routerstatus_list = networkstatus_get_all_statuses();
-  const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
+  int res;
+  or_options_t *options = get_options();
+  const networkstatus_vote_t *consensus =
+    networkstatus_get_live_consensus(now);
 
-  if (!routerlist) {
+  if (!consensus) {
     res = 0;
     goto done;
   }
-  /*XXXX020 remove this call. routerlist_remove_old_routers shows up in some
-   * profiles, and this is the biggest caller of that function. */
-  routerlist_remove_old_routers();
-  networkstatus_list_clean(now);
 
   if (should_delay_dir_fetches(get_options())) {
     log_notice(LD_DIR, "no known bridge descriptors running yet; stalling");
@@ -4062,24 +3875,17 @@ update_router_have_minimum_dir_info(void)
     goto done;
   }
 
-  n_authorities = get_n_v2_authorities();
-  n_ns = smartlist_len(networkstatus_list);
-  if (n_ns<=n_authorities/2) {
-    log_info(LD_DIR,
-             "We have %d of %d network statuses, and we want "
-             "more than %d.", n_ns, n_authorities, n_authorities/2);
-    res = 0;
-    goto done;
-  }
-  SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
-                    tot += routerstatus_count_usable_entries(ns->entries));
-  avg = tot / n_ns;
-  SMARTLIST_FOREACH(routerstatus_list, routerstatus_t *, rs,
+  SMARTLIST_FOREACH(consensus->routerstatus_list, routerstatus_t *, rs,
      {
-       if (rs->is_running)
-         num_running++;
+       if (client_would_use_router(rs, now, options)) {
+         ++num_usable;
+         if (router_get_by_digest(rs->identity_digest)) {
+           ++num_present;
+         }
+       }
      });
-  res = smartlist_len(routerlist->routers) >= (avg/4) && num_running > 2;
+  res = num_present >= num_usable/4 && num_usable > 2;
+
  done:
   if (res && !have_min_dir_info) {
     log(LOG_NOTICE, LD_DIR,
@@ -4089,7 +3895,7 @@ update_router_have_minimum_dir_info(void)
   if (!res && have_min_dir_info) {
     log(LOG_NOTICE, LD_DIR,"Our directory information is no longer up-to-date "
         "enough to build circuits.%s",
-        num_running > 2 ? "" : " (Not enough servers seem reachable -- "
+        num_usable > 2 ? "" : " (Not enough servers seem reachable -- "
         "is your network connection down?)");
     control_event_client_status(LOG_NOTICE, "NOT_ENOUGH_DIR_INFO");
   }
@@ -4102,18 +3908,7 @@ update_router_have_minimum_dir_info(void)
 void
 router_reset_descriptor_download_failures(void)
 {
-  const smartlist_t *networkstatus_list = networkstatus_get_v2_list();
-  const smartlist_t *routerstatus_list = networkstatus_get_all_statuses();
-  SMARTLIST_FOREACH(routerstatus_list, routerstatus_t *, rs,
-  {
-    download_status_reset(&rs->dl_status);
-  });
-  SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
-     SMARTLIST_FOREACH(ns->entries, routerstatus_t *, rs,
-       {
-         if (!router_get_by_descriptor_digest(rs->descriptor_digest))
-           rs->need_to_mirror = 1;
-       }));
+  networkstatus_reset_download_failures();
   last_routerdesc_download_attempted = 0;
   if (!routerlist)
     return;

+ 5 - 35
src/or/routerparse.c

@@ -564,36 +564,6 @@ tor_version_is_obsolete(const char *myversion, const char *versionlist)
   return ret;
 }
 
-/** Return the combined status of the current version, given that we know of
- * one set of networkstatuses that give us status <b>a</b>, and another that
- * gives us status <b>b</b>.
- *
- * For example, if one authority thinks that we're NEW, and another thinks
- * we're OLD, we're simply UNRECOMMENDED.
- *
- * This function does not handle calculating whether we're RECOMMENDED; that
- * follows a simple majority rule.  This function simply calculates *why*
- * we're not recommended (if we're not).
- */
-version_status_t
-version_status_join(version_status_t a, version_status_t b)
-{
-  if (a == b)
-    return a;
-  else if (a == VS_UNRECOMMENDED || b == VS_UNRECOMMENDED)
-    return VS_UNRECOMMENDED;
-  else if (a == VS_RECOMMENDED)
-    return b;
-  else if (b == VS_RECOMMENDED)
-    return a;
-  /* Okay.  Neither is 'recommended' or 'unrecommended', and they differ. */
-  else if (a == VS_OLD || b == VS_OLD)
-    return VS_UNRECOMMENDED;
-  /* One is VS_NEW, the other is VS_NEW_IN_SERIES */
-  else
-    return VS_NEW_IN_SERIES;
-}
-
 /** Read a signed directory from <b>str</b>.  If it's well-formed, return 0.
  * Otherwise, return -1.  If we're a directory cache, cache it.
  */
@@ -1722,13 +1692,13 @@ _free_duplicate_routerstatus_entry(void *e)
  * signature of the network status, but do not (yet) check the signing key for
  * authority.
  */
-networkstatus_t *
-networkstatus_parse_from_string(const char *s)
+networkstatus_v2_t *
+networkstatus_v2_parse_from_string(const char *s)
 {
   const char *eos;
   smartlist_t *tokens = smartlist_create();
   smartlist_t *footer_tokens = smartlist_create();
-  networkstatus_t *ns = NULL;
+  networkstatus_v2_t *ns = NULL;
   char ns_digest[DIGEST_LEN];
   char tmp_digest[DIGEST_LEN];
   struct in_addr in;
@@ -1745,7 +1715,7 @@ networkstatus_parse_from_string(const char *s)
     log_warn(LD_DIR, "Error tokenizing network-status header.");
     goto err;
   }
-  ns = tor_malloc_zero(sizeof(networkstatus_t));
+  ns = tor_malloc_zero(sizeof(networkstatus_v2_t));
   memcpy(ns->networkstatus_digest, ns_digest, DIGEST_LEN);
 
   tok = find_first_by_keyword(tokens, K_NETWORK_STATUS_VERSION);
@@ -1876,7 +1846,7 @@ networkstatus_parse_from_string(const char *s)
   goto done;
  err:
   if (ns)
-    networkstatus_free(ns);
+    networkstatus_v2_free(ns);
   ns = NULL;
  done:
   SMARTLIST_FOREACH(tokens, directory_token_t *, t, token_free(t));

Some files were not shown because too many files changed in this diff