Browse Source

r11694@Kushana: nickm | 2006-12-23 23:09:20 -0500
Add a version entry to networkstatus documents; have this entry get parsed and used to calculate whether begin_dir is supported.


svn:r9181

Nick Mathewson 19 years ago
parent
commit
2e538d9918
6 changed files with 51 additions and 10 deletions
  1. 5 0
      ChangeLog
  2. 9 9
      doc/TODO
  3. 11 0
      src/or/dirserv.c
  4. 7 0
      src/or/or.h
  5. 8 0
      src/or/routerlist.c
  6. 11 1
      src/or/routerparse.c

+ 5 - 0
ChangeLog

@@ -7,6 +7,11 @@ Changes in version 0.1.2.5-xxxx - 200?-??-??
     - Enable write limiting as well as read limiting. Now we sacrifice
     - Enable write limiting as well as read limiting. Now we sacrifice
       capacity if we're pushing out lots of directory traffic, rather
       capacity if we're pushing out lots of directory traffic, rather
       than overrunning the user's intended bandwidth limits.
       than overrunning the user's intended bandwidth limits.
+    - Authorities now include server versions in networkstatus. This adds
+      about 2% to the side of compressed networkstatus docs, and allows
+      clients to tell which servers support BEGIN_DIR and which don't.
+      The implementation is forward-compatible with a proposed future
+      protocol version scheme not tied to Tor versions.
 
 
   o Minor features:
   o Minor features:
     - Start using the state file to store bandwidth accounting data:
     - Start using the state file to store bandwidth accounting data:

+ 9 - 9
doc/TODO

@@ -55,14 +55,14 @@ R   - turn the received socks addr:port into a digest for setting .exit
 R     - handle connect-dir streams that don't have a chosen_exit_name set.
 R     - handle connect-dir streams that don't have a chosen_exit_name set.
       o include ORPort in DirServers lines so we can know where to connect.
       o include ORPort in DirServers lines so we can know where to connect.
         list the orport as 0 if it can't handle begin_dir.
         list the orport as 0 if it can't handle begin_dir.
-N     - list versions in status page
-        a new line in the status entry. "Tor 0.1.2.2-alpha". If it's
-        a version, treat it like one. If it's something else, assume
-        it's at least 0.1.2.x.
-        maybe we could have it be a new 'v' line in the status, with
-        key=value syntax. so we could have a 'tor' version, but we
-        could also have a 'conn' version, a 'dir' version, etc down
-        the road. and one day maybe the 'tor' key would be deprecated.
+      o List versions in status page
+        o A new line in the status entry. "Tor 0.1.2.2-alpha". If it's
+          a version, treat it like one. If it's something else, assume
+          it's at least 0.1.2.x.
+        D maybe we could have it be a new 'v' line in the status, with
+          key=value syntax. so we could have a 'tor' version, but we
+          could also have a 'conn' version, a 'dir' version, etc down
+          the road. and one day maybe the 'tor' key would be deprecated.
 
 
   o Document .noconnect addresses...
   o Document .noconnect addresses...
     A new file 'address-spec.txt' that describes .exit, .onion,
     A new file 'address-spec.txt' that describes .exit, .onion,
@@ -193,7 +193,7 @@ R   - "bandwidth classes", for incoming vs initiated-here conns,
       - separate config options for read vs write limiting
       - separate config options for read vs write limiting
 
 
   - Forward compatibility fixes
   - Forward compatibility fixes
-    - Stop requiring "opt" to ignore options in descriptors, networkstatuses,
+    o Stop requiring "opt" to ignore options in descriptors, networkstatuses,
       and so on.
       and so on.
     - Caches should start trying to cache consensus docs?
     - Caches should start trying to cache consensus docs?
     - Start uploading short and long descriptors; authorities should support
     - Start uploading short and long descriptors; authorities should support

+ 11 - 0
src/or/dirserv.c

@@ -1561,6 +1561,17 @@ generate_v2_networkstatus(void)
         goto done;
         goto done;
       }
       }
       outp += strlen(outp);
       outp += strlen(outp);
+      if (ri->platform && !strcmpstart(ri->platform, "Tor ")) {
+        const char *eos = find_whitespace(ri->platform+4);
+        char *platform = tor_strndup(ri->platform+4, eos-(ri->platform+4));
+        if (tor_snprintf(outp, endp-outp,
+                         "opt v %s\n", platform)) {
+          log_warn(LD_BUG, "Unable to print router version.");
+          goto done;
+        }
+        tor_free(platform);
+        outp += strlen(outp);
+      }
     }
     }
   });
   });
 
 

+ 7 - 0
src/or/or.h

@@ -1013,6 +1013,13 @@ typedef struct routerstatus_t {
   unsigned int is_bad_exit:1; /**< True iff this node is a bad choice for
   unsigned int is_bad_exit:1; /**< True iff this node is a bad choice for
                                * an exit node. */
                                * an exit node. */
 
 
+  /** True iff we know version info for this router. (i.e., a "v" entry was
+   * included.)  We'll replace all these with a big tor_vesion_t or a char[]
+   * if the number of traits we care about ever becomes incredibly big. */
+  unsigned int version_known:1;
+  /** True iff this router is a version that supports BEGIN_DIR cells. */
+  unsigned int version_supports_begindir:1;
+
   /** True if we, as a directory mirror, want to download the corresponding
   /** True if we, as a directory mirror, want to download the corresponding
    * routerinfo from the authority who gave us this routerstatus.  (That is,
    * routerinfo from the authority who gave us this routerstatus.  (That is,
    * if we don't have the routerinfo, and if we haven't already tried to get it
    * if we don't have the routerinfo, and if we haven't already tried to get it

+ 8 - 0
src/or/routerlist.c

@@ -3345,6 +3345,7 @@ routerstatus_list_update_from_networkstatus(time_t now)
   while (1) {
   while (1) {
     int n_running=0, n_named=0, n_valid=0, n_listing=0;
     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, n_guard=0, n_bad_exit=0;
     int n_v2_dir=0, n_fast=0, n_stable=0, n_exit=0, n_guard=0, n_bad_exit=0;
+    int n_version_known=0, n_supports_begindir=0;
     int n_desc_digests=0, highest_count=0;
     int n_desc_digests=0, highest_count=0;
     const char *the_name = NULL;
     const char *the_name = NULL;
     local_routerstatus_t *rs_out, *rs_old;
     local_routerstatus_t *rs_out, *rs_old;
@@ -3432,6 +3433,10 @@ routerstatus_list_update_from_networkstatus(time_t now)
         ++n_v2_dir;
         ++n_v2_dir;
       if (rs->is_bad_exit)
       if (rs->is_bad_exit)
         ++n_bad_exit;
         ++n_bad_exit;
+      if (rs->version_known)
+        ++n_version_known;
+      if (rs->version_supports_begindir)
+        ++n_supports_begindir;
     }
     }
     /* Go over the descriptor digests and figure out which descriptor we
     /* Go over the descriptor digests and figure out which descriptor we
      * want. */
      * want. */
@@ -3482,6 +3487,9 @@ routerstatus_list_update_from_networkstatus(time_t now)
     rs_out->status.is_stable = n_stable > 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;
     rs_out->status.is_v2_dir = n_v2_dir > n_statuses/2;
     rs_out->status.is_bad_exit = n_bad_exit > n_listing_bad_exits/2;
     rs_out->status.is_bad_exit = n_bad_exit > n_listing_bad_exits/2;
+    rs_out->status.version_known = n_version_known > 0;
+    rs_out->status.version_supports_begindir =
+      n_supports_begindir > n_version_known/2;
     if (!rs_old || memcmp(rs_old, rs_out, sizeof(local_routerstatus_t)))
     if (!rs_old || memcmp(rs_old, rs_out, sizeof(local_routerstatus_t)))
       smartlist_add(changed_list, rs_out);
       smartlist_add(changed_list, rs_out);
   }
   }

+ 11 - 1
src/or/routerparse.c

@@ -54,6 +54,7 @@ typedef enum {
   K_SERVER_VERSIONS,
   K_SERVER_VERSIONS,
   K_R,
   K_R,
   K_S,
   K_S,
+  K_V,
   K_EVENTDNS,
   K_EVENTDNS,
   _UNRECOGNIZED,
   _UNRECOGNIZED,
   _ERR,
   _ERR,
@@ -117,6 +118,7 @@ static struct {
                                                            DIR|NETSTATUS},
                                                            DIR|NETSTATUS},
   { "r",                   K_R,                   ARGS,    NO_OBJ, RTRSTATUS },
   { "r",                   K_R,                   ARGS,    NO_OBJ, RTRSTATUS },
   { "s",                   K_S,                   ARGS,    NO_OBJ, RTRSTATUS },
   { "s",                   K_S,                   ARGS,    NO_OBJ, RTRSTATUS },
+  { "v",                   K_V,               CONCAT_ARGS, NO_OBJ, RTRSTATUS },
   { "reject",              K_REJECT,              ARGS,    NO_OBJ,  RTR },
   { "reject",              K_REJECT,              ARGS,    NO_OBJ,  RTR },
   { "router",              K_ROUTER,              ARGS,    NO_OBJ,  RTR },
   { "router",              K_ROUTER,              ARGS,    NO_OBJ,  RTR },
   { "recommended-software",K_RECOMMENDED_SOFTWARE,ARGS,    NO_OBJ,  DIR },
   { "recommended-software",K_RECOMMENDED_SOFTWARE,ARGS,    NO_OBJ,  DIR },
@@ -1075,7 +1077,15 @@ routerstatus_parse_entry_from_string(const char **s, smartlist_t *tokens)
         rs->is_possible_guard = 1;
         rs->is_possible_guard = 1;
       else if (!strcmp(tok->args[i], "BadExit"))
       else if (!strcmp(tok->args[i], "BadExit"))
         rs->is_bad_exit = 1;
         rs->is_bad_exit = 1;
-
+    }
+  }
+  if ((tok = find_first_by_keyword(tokens, K_V))) {
+    rs->version_known = 1;
+    if (strcmpstart(tok->args[0], "Tor ")) {
+      rs->version_supports_begindir = 1;
+    } else {
+      rs->version_supports_begindir =
+        tor_version_as_new_as(tok->args[0], "0.1.2.2-alpha");
     }
     }
   }
   }