[or-cvs] Big commit: clients start downloading and using network-sta...

Nick Mathewson nickm at seul.org
Wed Sep 14 21:09:27 UTC 2005


Update of /home/or/cvsroot/tor/src/or
In directory moria:/tmp/cvs-serv31572/src/or

Modified Files:
	directory.c main.c or.h routerlist.c routerparse.c 
Log Message:
Big commit: clients start downloading and using network-statuses.

Only caches need to get running-routers; nobody needs to parse, store,
or use it.  Same for the router-status line in the directories.  Add
many #if 0's that can get removed once I'm convinced they don't
contain anything I'm forgetting.

Start all newly-parsed routers as non-running and non-valid; update
them from the list of network statuses.

Update all routers when a new networkstatus comes in.

After 3 tries for a networkstatus, clients give up until they're told
to try again.

     "Let's get those missles ready to **DESTROY THE UNIVERSE**!"
				-TMBG



Index: directory.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/directory.c,v
retrieving revision 1.275
retrieving revision 1.276
diff -u -d -r1.275 -r1.276
--- directory.c	14 Sep 2005 03:49:17 -0000	1.275
+++ directory.c	14 Sep 2005 21:09:25 -0000	1.276
@@ -903,8 +903,6 @@
   }
 
   if (conn->purpose == DIR_PURPOSE_FETCH_RUNNING_LIST) {
-    running_routers_t *rrs;
-    routerlist_t *rl;
     /* just update our list of running routers, if this list is new info */
     log_fn(LOG_INFO,"Received running-routers list (size %d)", (int)body_len);
     if (status_code != 200) {
@@ -913,6 +911,13 @@
       tor_free(body); tor_free(headers); tor_free(reason);
       return -1;
     }
+    if (router_parse_runningrouters(body)<0) {
+      log_fn(LOG_WARN,"Bad running-routers from server '%s:%d'. I'll try again soon.",
+             conn->address, conn->port);
+      tor_free(body); tor_free(headers); tor_free(reason);
+      return -1;
+    }
+#if 0
     if (!(rrs = router_parse_runningrouters(body, 1))) {
       log_fn(LOG_WARN, "Can't parse runningrouters list (server '%s:%d')",
              conn->address, conn->port);
@@ -926,6 +931,7 @@
     } else {
       running_routers_free(rrs);
     }
+#endif
   }
 
   if (conn->purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS) {
@@ -963,6 +969,7 @@
       else
         break;
     }
+    routers_update_all_from_networkstatus();
     if (which) {
       if (smartlist_len(which)) {
         dir_networkstatus_download_failed(which);

Index: main.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/main.c,v
retrieving revision 1.549
retrieving revision 1.550
diff -u -d -r1.549 -r1.550
--- main.c	14 Sep 2005 02:36:29 -0000	1.549
+++ main.c	14 Sep 2005 21:09:25 -0000	1.550
@@ -480,6 +480,7 @@
 directory_all_unreachable(time_t now)
 {
   connection_t *conn;
+  /* XXXX011 NM Update this to reflect new directories? */
 
   has_fetched_directory=0;
   stats_n_seconds_working=0; /* reset it */
@@ -533,6 +534,9 @@
 directory_has_arrived(time_t now, char *identity_digest)
 {
   or_options_t *options = get_options();
+  /* XXXX011 NM Update this to reflect new directories.  In particular, we
+   * can't start building circuits until we have descriptors and networkstatus
+   * docs.*/
 
   log_fn(LOG_INFO, "A directory has arrived.");
 
@@ -710,7 +714,8 @@
     rend_cache_clean();
   }
 
-  if (time_to_fetch_running_routers < now) {
+  /* Caches need to fetch running_routers; directory clients don't. */
+  if (options->DirPort && time_to_fetch_running_routers < now) {
     if (!authdir_mode(options) || !options->V1AuthoritativeDir) {
       directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST, NULL, 1);
     }
@@ -732,12 +737,13 @@
         !we_are_hibernating())
       consider_testing_reachability();
 
+    /* Also, once per minute, check whether we want to download any
+     * networkstatus documents.
+     */
     if (server_mode(options) && options->DirPort)
       update_networkstatus_cache_downloads(now);
-    /* XXXX Disabled until 0.1.1.6 is out: only servers need networkstatus.
     else
       update_networkstatus_client_downloads(now);
-    */
   }
 
   /** 3a. Every second, we examine pending circuits and prune the
@@ -980,6 +986,7 @@
   if (router_reload_router_list()) {
     return -1;
   }
+  /* load the networkstatuses. */
   if (router_reload_networkstatus()) {
     return -1;
   }

Index: or.h
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/or.h,v
retrieving revision 1.680
retrieving revision 1.681
diff -u -d -r1.680 -r1.681
--- or.h	14 Sep 2005 02:36:29 -0000	1.680
+++ or.h	14 Sep 2005 21:09:25 -0000	1.681
@@ -785,12 +785,14 @@
   int num_unreachable_notifications;
 } routerinfo_t;
 
+#if 0
 /** Contents of a running-routers list */
 typedef struct running_routers_t {
   time_t published_on; /**< When was the list marked as published? */
   /** Which ORs are on the list?  Entries may be prefixed with ! and $. */
   smartlist_t *running_routers;
 } running_routers_t;
+#endif
 
 /** Contents of a single per-router entry in a network status object.
  */
@@ -848,9 +850,11 @@
   /** When was the most recent directory that contributed to this list
    * published? */
   time_t published_on;
+#if 0
   time_t running_routers_updated_on;
   /** What is the most recently received running_routers structure? */
   running_routers_t *running_routers;
+#endif
 } routerlist_t;
 
 /** Information on router used when extending a circuit.  (We don't need a
@@ -2100,6 +2104,7 @@
                                           int need_uptime);
 
 int router_exit_policy_rejects_all(routerinfo_t *router);
+#if 0
 void running_routers_free(running_routers_t *rr);
 void routerlist_set_runningrouters(routerlist_t *list, running_routers_t *rr);
 int routers_update_status_from_entry(smartlist_t *routers,
@@ -2108,12 +2113,14 @@
 int router_update_status_from_smartlist(routerinfo_t *r,
                                         time_t list_time,
                                         smartlist_t *running_list);
+#endif
 void add_trusted_dir_server(const char *addr, uint16_t port,
                             const char *digest, int supports_v1);
 void clear_trusted_dir_servers(void);
 networkstatus_t *networkstatus_get_by_digest(const char *digest);
 void update_networkstatus_cache_downloads(time_t now);
 void update_networkstatus_client_downloads(time_t now);
+void routers_update_all_from_networkstatus(void);
 void routers_update_status_from_networkstatus(smartlist_t *routers);
 smartlist_t *router_list_superseded(void);
 
@@ -2147,16 +2154,13 @@
                                    crypto_pk_env_t *private_key);
 int router_parse_list_from_string(const char **s,
                                   routerlist_t **dest,
-                                  smartlist_t *good_nickname_list,
-                                  int rr_format,
                                   time_t published);
 int router_parse_routerlist_from_directory(const char *s,
                                            routerlist_t **dest,
                                            crypto_pk_env_t *pkey,
                                            int check_version,
                                            int write_to_cache);
-running_routers_t *router_parse_runningrouters(const char *str,
-                                               int write_to_cache);
+int router_parse_runningrouters(const char *str);
 routerinfo_t *router_parse_entry_from_string(const char *s, const char *end);
 int router_add_exit_policy_from_string(routerinfo_t *router, const char *s);
 addr_policy_t *router_parse_addr_policy_from_string(const char *s,

Index: routerlist.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/routerlist.c,v
retrieving revision 1.287
retrieving revision 1.288
diff -u -d -r1.287 -r1.288
--- routerlist.c	14 Sep 2005 19:12:35 -0000	1.287
+++ routerlist.c	14 Sep 2005 21:09:25 -0000	1.288
@@ -47,6 +47,11 @@
 /** Global list of all of the current network_status documents that we know
  * about.  This list is kept sorted by published_on. */
 static smartlist_t *networkstatus_list = NULL;
+/** True iff networkstatus_list has changed since the last time we called
+ * routers_update_all_from_networkstatus.  Set by router_set_networkstatus;
+ * cleared by routers_update_all_from_networkstatus.
+ */
+static int networkstatus_list_has_changed = 0;
 
 /**
  * Reload the most recent cached directory (if present).
@@ -116,6 +121,7 @@
         tor_free(s);
       }
     });
+  routers_update_all_from_networkstatus();
   return 0;
 }
 
@@ -437,7 +443,10 @@
   }
   if (trusted_dir_servers) {
     SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, dir,
-                      dir->is_running = 1);
+    {
+      dir->is_running = 1;
+      dir->n_networkstatus_failures = 0;
+    });
   }
 }
 
@@ -971,7 +980,6 @@
   SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
                     routerinfo_free(r));
   smartlist_free(rl->routers);
-  running_routers_free(rl->running_routers);
   tor_free(rl->software_versions);
   tor_free(rl);
 }
@@ -1235,12 +1243,16 @@
     routerinfo_free(ri);
     return 0;
   }
+#if 0
   if (routerlist && routerlist->running_routers) {
     running_routers_t *rr = routerlist->running_routers;
     router_update_status_from_smartlist(ri,
                                         rr->published_on,
                                         rr->running_routers);
   }
+#endif
+  /* XXXX011 update router status from networkstatus!! */
+
   if (router_add_to_routerlist(ri, msg)<0) {
     log_fn(LOG_WARN, "Couldn't add router to list: %s Dropping.",
            *msg?*msg:"(No message).");
@@ -1422,11 +1434,13 @@
                   ns->networkstatus_digest, DIGEST_LEN)) {
         /* Same one we had before. */
         networkstatus_free(ns);
+        log_fn(LOG_NOTICE, "Dropping network-status (%s); already have it.",fp);
         if (old_ns->received_on < arrived_at)
+          /* XXXX We should touch the cache file. NM */
           old_ns->received_on = arrived_at;
         return 0;
       } else if (old_ns->published_on >= ns->published_on) {
-        log_fn(LOG_INFO, "Dropping network-status; we have a newer one for this authority.");
+        log_fn(LOG_NOTICE, "Dropping network-status (%s); we have a newer one for this authority.", fp);
         networkstatus_free(ns);
         return 0;
       } else {
@@ -1441,6 +1455,13 @@
   if (!found)
     smartlist_add(networkstatus_list, ns);
 
+  /*XXXX011 downgrade to INFO NM */
+  log_fn(LOG_NOTICE, "New networkstatus %s (%s).",
+         source == NS_FROM_CACHE?"from our cache":
+         (source==NS_FROM_DIR?"from a directory server":"from this authority"),
+         fp);
+  networkstatus_list_has_changed = 1;
+
   smartlist_sort(networkstatus_list, _compare_networkstatus_published_on);
 
   if (source != NS_FROM_CACHE && !skewed) {
@@ -1561,12 +1582,14 @@
 }
 
 /*XXXX Should these be configurable? NM*/
-/** How old (in seconds) can a network-status be before we stop believing it? */
+/** How old (in seconds) can a network-status be before we try replacing it? */
 #define NETWORKSTATUS_MAX_VALIDITY (48*60*60)
 /** How long (in seconds) does a client wait after getting a network status
  * before downloading the next in sequence? */
 #define NETWORKSTATUS_CLIENT_DL_INTERVAL (30*60)
-
+/* How many times do we allow a networkstatus download to fail before we
+ * assume that the authority isn't publishing? */
+#define NETWORKSTATUS_N_ALLOWABLE_FAILURES 3
 /** We are not a directory cache or authority.  Update our network-status list
  * by launching a new directory fetch for enough network-status documents "as
  * necessary".  See function comments for implementation details.
@@ -1574,7 +1597,7 @@
 void
 update_networkstatus_client_downloads(time_t now)
 {
-  int n_live = 0, needed = 0, n_dirservers, i;
+  int n_live = 0, needed = 0, n_running_dirservers, n_dirservers, i;
   int most_recent_idx = -1;
   trusted_dir_server_t *most_recent = NULL;
   time_t most_recent_received = 0;
@@ -1593,12 +1616,16 @@
    */
   if (!trusted_dir_servers || !smartlist_len(trusted_dir_servers))
     return;
-  n_dirservers = smartlist_len(trusted_dir_servers);
+  n_dirservers = n_running_dirservers = smartlist_len(trusted_dir_servers);
   SMARTLIST_FOREACH(trusted_dir_servers, trusted_dir_server_t *, ds,
      {
        networkstatus_t *ns = networkstatus_get_by_digest(ds->digest);
        if (!ns)
          continue;
+       if (ds->n_networkstatus_failures > NETWORKSTATUS_N_ALLOWABLE_FAILURES) {
+         --n_running_dirservers;
+         continue;
+       }
        if (ns->published_on > now-NETWORKSTATUS_MAX_VALIDITY)
          ++n_live;
        if (!most_recent || ns->received_on > most_recent_received) {
@@ -1613,11 +1640,22 @@
    */
   if (n_live < (n_dirservers/2)+1)
     needed = (n_dirservers/2)+1-n_live;
-  if (needed > n_dirservers)
-    needed = n_dirservers;
+  if (needed > n_running_dirservers)
+    needed = n_running_dirservers;
+
+  if (needed)
+    /* XXXX001 Downgrade to info NM */
+    log_fn(LOG_NOTICE, "For %d/%d running directory servers, we have %d live"
+           " network-status documents. Downloading %d.",
+           n_running_dirservers, n_dirservers, n_live, needed);
+
   /* Also, download at least 1 every NETWORKSTATUS_CLIENT_DL_INTERVAL. */
-  if (most_recent_received < now-NETWORKSTATUS_CLIENT_DL_INTERVAL && needed < 1)
+  if (n_running_dirservers &&
+      most_recent_received < now-NETWORKSTATUS_CLIENT_DL_INTERVAL && needed < 1) {
+    log_fn(LOG_NOTICE, "Our most recent network-status document is %d"
+           " seconds old; downloading another.", (int)(now-most_recent_received));
     needed = 1;
+  }
 
   if (!needed)
     return;
@@ -1637,6 +1675,8 @@
     if (i >= n_dirservers)
       i = 0;
     ds = smartlist_get(trusted_dir_servers, i);
+    if (ds->n_networkstatus_failures > NETWORKSTATUS_N_ALLOWABLE_FAILURES)
+      continue;
     base16_encode(cp, HEX_DIGEST_LEN+1, ds->digest, DIGEST_LEN);
     cp += HEX_DIGEST_LEN;
     --needed;
@@ -1860,6 +1900,7 @@
     == ADDR_POLICY_REJECTED;
 }
 
+#if 0
 /** Release all space held in <b>rr</b>. */
 void
 running_routers_free(running_routers_t *rr)
@@ -2047,6 +2088,7 @@
   smartlist_free(rl);
   return 0;
 }
+#endif
 
 /** Add to the list of authorized directory servers one at
  * <b>address</b>:<b>port</b>, with identity key <b>digest</b>.  If
@@ -2111,6 +2153,40 @@
   return NULL;
 }
 
+/** If the network-status list has changed since the last time we called this
+ * function, update the status of every router from the network-status list.
+ */
+void
+routers_update_all_from_networkstatus(void)
+{
+  static int have_warned_about_unverified_status = 0;
+  routerinfo_t *me;
+  if (!routerlist || !networkstatus_list || !networkstatus_list_has_changed)
+    return;
+
+  routers_update_status_from_networkstatus(routerlist->routers);
+
+  me = router_get_my_routerinfo();
+  if (me) {
+    /* We could be more sophisticated about this whole business.  How many
+     * dirservers list us as named, valid, etc. */
+    smartlist_t *lst = smartlist_create();
+    smartlist_add(lst, me);
+    routers_update_status_from_networkstatus(lst);
+    if (me->is_verified == 0) {
+      log_fn(LOG_WARN, "Many directory servers list us as unverified. Please consider sending your identity fingerprint to the tor-ops.");
+      have_warned_about_unverified_status = 1;
+    } else if (me->is_named == 0) {
+      log_fn(LOG_WARN, "Many directory servers list us as unnamed. Please consider sending your identity fingerprint to the tor-ops.");
+      have_warned_about_unverified_status = 1;
+    }
+  }
+
+  helper_nodes_set_status_from_directory();
+
+  networkstatus_list_has_changed = 0;
+}
+
 /** Allow any network-status newer than this to influence our view of who's
  * running. */
 #define DEFAULT_RUNNING_INTERVAL 60*60
@@ -2127,6 +2203,7 @@
     n_recent;
   int i;
   time_t now = time(NULL);
+  trusted_dir_server_t *ds;
 
   if (authdir_mode(get_options())) {
     /* An authoritative directory should never believer someone else about
@@ -2164,6 +2241,7 @@
 
   SMARTLIST_FOREACH(routers, routerinfo_t *, router,
   {
+    ds = router_get_trusteddirserver_by_digest(router->identity_digest);
     n_listing = n_valid = n_naming = n_named = n_running = 0;
 
     SMARTLIST_FOREACH(networkstatus_list, networkstatus_t *, ns,
@@ -2194,6 +2272,10 @@
     router->is_named = (n_named > n_naming/2);
     router->is_verified = (n_valid > n_statuses/2);
     router->is_running = (n_running > n_recent/2);
+
+    if (router->is_running && ds)
+      /*Hm. What about authorities? When do they reset n_networkstatus_failures?*/
+      ds->n_networkstatus_failures = 0;
   });
 }
 

Index: routerparse.c
===================================================================
RCS file: /home/or/cvsroot/tor/src/or/routerparse.c,v
retrieving revision 1.137
retrieving revision 1.138
diff -u -d -r1.137 -r1.138
--- routerparse.c	13 Sep 2005 21:14:55 -0000	1.137
+++ routerparse.c	14 Sep 2005 21:09:25 -0000	1.138
@@ -419,9 +419,8 @@
   char digest[DIGEST_LEN];
   routerlist_t *new_dir = NULL;
   char *versions = NULL;
-  smartlist_t *good_nickname_list = NULL;
   time_t published_on;
-  int i, r;
+  int r;
   const char *end, *cp;
   smartlist_t *tokens = NULL;
   char dirnickname[MAX_NICKNAME_LEN+1];
@@ -531,42 +530,17 @@
     goto err;
   }
 
-  good_nickname_list = smartlist_create();
-  for (i=0; i<tok->n_args; ++i) {
-    smartlist_add(good_nickname_list, tok->args[i]);
-  }
-  tok->n_args = 0; /* Don't free the strings in good_nickname_list yet. */
-
   /* Read the router list from s, advancing s up past the end of the last
    * router. */
   str = end;
   if (router_parse_list_from_string(&str, &new_dir,
-                                    good_nickname_list,
-                                    tok->tp==K_RUNNING_ROUTERS,
                                     published_on)) {
     log_fn(LOG_WARN, "Error reading routers from directory");
     goto err;
   }
 
-  /* Determine if my routerinfo is considered verified. */
-  {
-    static int have_warned_about_unverified_status = 0;
-    routerinfo_t *me = router_get_my_routerinfo();
-    if (me) {
-      if (router_update_status_from_smartlist(me,
-            published_on, good_nickname_list)==1 &&
-          me->is_verified == 0 && !have_warned_about_unverified_status) {
-        log_fn(LOG_WARN,"Dirserver '%s' lists your server as unverified. Please consider sending your identity fingerprint to the tor-ops.", dirnickname);
-        have_warned_about_unverified_status = 1;
-      }
-    }
-  }
-
   new_dir->software_versions = versions; versions = NULL;
   new_dir->published_on = published_on;
-  new_dir->running_routers = tor_malloc_zero(sizeof(running_routers_t));
-  new_dir->running_routers->published_on = published_on;
-  new_dir->running_routers->running_routers = good_nickname_list;
 
   SMARTLIST_FOREACH(tokens, directory_token_t *, tok, token_free(tok));
   smartlist_free(tokens);
@@ -583,10 +557,6 @@
   if (new_dir)
     routerlist_free(new_dir);
   tor_free(versions);
-  if (good_nickname_list) {
-    SMARTLIST_FOREACH(good_nickname_list, char *, n, tor_free(n));
-    smartlist_free(good_nickname_list);
-  }
  done:
   if (declared_key) crypto_free_pk_env(declared_key);
   if (tokens) {
@@ -596,17 +566,15 @@
   return r;
 }
 
-/** Read a signed router status statement from <b>str</b>.  On
- * success, return it, and cache the original string if
- * <b>write_to_cache</b> is set.  Otherwise, return NULL.  */
-running_routers_t *
-router_parse_runningrouters(const char *str, int write_to_cache)
+/** Read a signed router status statement from <b>str</b>.  If it's well-formed,
+ * return 0.  Otherwise, return -1.  If we're a directory cache, cache it.*/
+int
+router_parse_runningrouters(const char *str)
 {
   char digest[DIGEST_LEN];
-  running_routers_t *new_list = NULL;
   directory_token_t *tok;
   time_t published_on;
-  int i;
+  int r = -1;
   crypto_pk_env_t *declared_key = NULL;
   smartlist_t *tokens = NULL;
 
@@ -637,28 +605,6 @@
   if (parse_iso_time(tok->args[0], &published_on) < 0) {
      goto err;
   }
-
-  /* Now that we know the signature is okay, and we have a
-   * publication time, cache the list. */
-  if (!get_options()->AuthoritativeDir && write_to_cache)
-    dirserv_set_cached_directory(str, published_on, 1);
-
-  if (!(tok = find_first_by_keyword(tokens, K_ROUTER_STATUS))) {
-    if (!(tok = find_first_by_keyword(tokens, K_RUNNING_ROUTERS))) {
-      log_fn(LOG_WARN,
-             "Missing running-routers/router-status line from directory.");
-      goto err;
-    }
-  }
-
-  new_list = tor_malloc_zero(sizeof(running_routers_t));
-  new_list->published_on = published_on;
-  new_list->running_routers = smartlist_create();
-  for (i=0;i<tok->n_args;++i) {
-    smartlist_add(new_list->running_routers, tok->args[i]);
-  }
-  tok->n_args = 0; /* Don't free the elements of tok->args. */
-
   if (!(tok = find_first_by_keyword(tokens, K_DIRECTORY_SIGNATURE))) {
     log_fn(LOG_WARN, "Missing signature on running-routers");
     goto err;
@@ -667,19 +613,19 @@
   if (check_directory_signature(digest, tok, NULL, declared_key, 1) < 0)
     goto err;
 
-  goto done;
+  /* Now that we know the signature is okay, and we have a
+   * publication time, cache the list. */
+  if (get_options()->DirPort && !get_options()->V1AuthoritativeDir)
+    dirserv_set_cached_directory(str, published_on, 1);
+
+  r = 0;
  err:
-  if (new_list) {
-    running_routers_free(new_list);
-    new_list = NULL;
-  }
- done:
   if (declared_key) crypto_free_pk_env(declared_key);
   if (tokens) {
     SMARTLIST_FOREACH(tokens, directory_token_t *, tok, token_free(tok));
     smartlist_free(tokens);
   }
-  return new_list;
+  return r;
 }
 
 /** Given a directory or running-routers string in <b>str</b>, try to
@@ -818,8 +764,7 @@
  */
 int
 router_parse_list_from_string(const char **s, routerlist_t **dest,
-                              smartlist_t *good_nickname_list,
-                              int rr_format, time_t published_on)
+                              time_t published_on)
 {
   routerinfo_t *router;
   smartlist_t *routers;
@@ -850,19 +795,10 @@
       continue;
     }
 
-    if (!good_nickname_list) {
-      router->is_running = 1; /* start out assuming all dirservers are up */
-      router->is_verified = router->is_named = 1;
-      router->status_set_at = time(NULL);
-    }
     smartlist_add(routers, router);
-//    log_fn(LOG_DEBUG,"just added router #%d.",smartlist_len(routers));
   }
 
-  if (good_nickname_list) {
-    SMARTLIST_FOREACH(good_nickname_list, const char *, cp,
-                  routers_update_status_from_entry(routers, published_on, cp));
-  }
+  routers_update_status_from_networkstatus(routers);
 
   if (*dest)
     routerlist_free(*dest);



More information about the tor-commits mailing list