Browse Source

r12414@catbus: nickm | 2007-04-16 17:37:17 -0400
More proposal-104 stuff: actually remember extra-info stuff.


svn:r9975

Nick Mathewson 18 years ago
parent
commit
362fbc79d2
9 changed files with 121 additions and 19 deletions
  1. 9 0
      ChangeLog
  2. 2 1
      doc/TODO
  3. 0 1
      src/common/mempool.c
  4. 5 7
      src/or/dirserv.c
  5. 8 1
      src/or/or.h
  6. 1 1
      src/or/rephist.c
  7. 3 2
      src/or/router.c
  8. 91 4
      src/or/routerlist.c
  9. 2 2
      src/or/routerparse.c

+ 9 - 0
ChangeLog

@@ -30,6 +30,15 @@ Changes in version 0.2.0.1-alpha - 2007-??-??
       message, so when people paste just their logs, we know if it's
       message, so when people paste just their logs, we know if it's
       openbsd or windows or what.
       openbsd or windows or what.
 
 
+  o Minor features (directory system):
+    - Directory authorities accept and serve "extra info" documents for
+      routers.  These documents contain fields from router descriptors that
+      aren't usually needed, and that use a lot of excess bandwidth. Once
+      these fields are removed from router descriptors, the bandwidth savings
+      should be about 60%.  (Limitation: servers do not yet upload extra-info
+      documents; authorities do not yet cache them.)  [Partially implements
+      proposal 104.]
+
   o Minor features (other):
   o Minor features (other):
     - More unit tests.
     - More unit tests.
 
 

+ 2 - 1
doc/TODO

@@ -60,7 +60,8 @@ Things we'd like to do in 0.2.0.x:
       o Have routers generate extra-info documents.
       o Have routers generate extra-info documents.
       . Have have authorities accept them and serve them from specified URLs
       . Have have authorities accept them and serve them from specified URLs
         o Implement directory-protocol side.
         o Implement directory-protocol side.
-        - Implement storage.
+        o Implement storage in memory
+        - Implement cache on disk.
       - Have routers upload extra-info documents.
       - Have routers upload extra-info documents.
       - Implement option to download and cache extra-info documents.
       - Implement option to download and cache extra-info documents.
       - Drop bandwidth history from router-descriptors
       - Drop bandwidth history from router-descriptors

+ 0 - 1
src/common/mempool.c

@@ -140,7 +140,6 @@ struct mp_chunk_t {
   char mem[1]; /**< Storage for this chunk. (Not actual size.) */
   char mem[1]; /**< Storage for this chunk. (Not actual size.) */
 };
 };
 
 
-
 /** Number of extra bytes needed beyond mem_size to allocate a chunk. */
 /** Number of extra bytes needed beyond mem_size to allocate a chunk. */
 #define CHUNK_OVERHEAD (sizeof(mp_chunk_t)-1)
 #define CHUNK_OVERHEAD (sizeof(mp_chunk_t)-1)
 
 

+ 5 - 7
src/or/dirserv.c

@@ -562,9 +562,7 @@ dirserv_add_descriptor(const char *desc, const char **msg)
       extrainfo_free(ei);
       extrainfo_free(ei);
       return -1;
       return -1;
     }
     }
-    /* XXXX020 Eventually, we should store this.  For now, we'll just
-     * discard it. */
-    extrainfo_free(ei);
+    router_add_extrainfo_to_routerlist(ei, msg, 0, 0);
     return 2;
     return 2;
   }
   }
 
 
@@ -2115,11 +2113,11 @@ connection_dirserv_add_servers_to_outbuf(dir_connection_t *conn)
         routerinfo_t *ri = router_get_by_digest(fp);
         routerinfo_t *ri = router_get_by_digest(fp);
         if (ri &&
         if (ri &&
             ri->cache_info.published_on > publish_cutoff) {
             ri->cache_info.published_on > publish_cutoff) {
-          if (extra) {
-            sd = extrainfo_get_by_descriptor_digest(ri->extra_info_digest);
-          } else {
+          if (extra)
+            sd = extrainfo_get_by_descriptor_digest(
+                                         ri->cache_info.extra_info_digest);
+          else
             sd = &ri->cache_info;
             sd = &ri->cache_info;
-          }
         }
         }
       }
       }
     } else {
     } else {

+ 8 - 1
src/or/or.h

@@ -1047,6 +1047,8 @@ typedef struct signed_descriptor_t {
   char identity_digest[DIGEST_LEN];
   char identity_digest[DIGEST_LEN];
   /** Declared publication time of the descriptor */
   /** Declared publication time of the descriptor */
   time_t published_on;
   time_t published_on;
+ /** DOCDOC; routerinfo_t only. */
+  char extra_info_digest[DIGEST_LEN];
   /** Where is the descriptor saved? */
   /** Where is the descriptor saved? */
   saved_location_t saved_location;
   saved_location_t saved_location;
   /** If saved_location is SAVED_IN_CACHE or SAVED_IN_JOURNAL, the offset of
   /** If saved_location is SAVED_IN_CACHE or SAVED_IN_JOURNAL, the offset of
@@ -1081,7 +1083,6 @@ typedef struct {
   smartlist_t *declared_family; /**< Nicknames of router which this router
   smartlist_t *declared_family; /**< Nicknames of router which this router
                                  * claims are its family. */
                                  * claims are its family. */
   char *contact_info; /**< Declared contact info for this router. */
   char *contact_info; /**< Declared contact info for this router. */
-  char extra_info_digest[DIGEST_LEN]; /**< DOCDOC */
   unsigned int is_hibernating:1; /**< Whether the router claims to be
   unsigned int is_hibernating:1; /**< Whether the router claims to be
                                   * hibernating */
                                   * hibernating */
   unsigned int has_old_dnsworkers:1; /**< Whether the router is using
   unsigned int has_old_dnsworkers:1; /**< Whether the router is using
@@ -1128,6 +1129,7 @@ typedef struct {
 typedef struct extrainfo_t {
 typedef struct extrainfo_t {
   signed_descriptor_t cache_info;
   signed_descriptor_t cache_info;
   char nickname[MAX_NICKNAME_LEN+1];
   char nickname[MAX_NICKNAME_LEN+1];
+  unsigned int bad_sig : 1;
   char *pending_sig;
   char *pending_sig;
 } extrainfo_t;
 } extrainfo_t;
 
 
@@ -1245,6 +1247,9 @@ typedef struct {
   /** Map from server descriptor digest to a signed_descriptor_t from
   /** Map from server descriptor digest to a signed_descriptor_t from
    * routers or old_routers. */
    * routers or old_routers. */
   digestmap_t *desc_digest_map;
   digestmap_t *desc_digest_map;
+  /** Map from extra-info digest to a signed_descriptor_t.  Only for
+   * routers in routers or old_routers. */
+  digestmap_t *extra_info_map;
   /** List of routerinfo_t for all currently live routers we know. */
   /** List of routerinfo_t for all currently live routers we know. */
   smartlist_t *routers;
   smartlist_t *routers;
   /** List of signed_descriptor_t for older router descriptors we're
   /** List of signed_descriptor_t for older router descriptors we're
@@ -3016,6 +3021,8 @@ void routerlist_remove_old_routers(void);
 void networkstatus_list_clean(time_t now);
 void networkstatus_list_clean(time_t now);
 int router_add_to_routerlist(routerinfo_t *router, const char **msg,
 int router_add_to_routerlist(routerinfo_t *router, const char **msg,
                              int from_cache, int from_fetch);
                              int from_cache, int from_fetch);
+void router_add_extrainfo_to_routerlist(extrainfo_t *ei, const char **msg,
+                                        int from_cache, int from_fetch);
 int router_load_single_router(const char *s, uint8_t purpose,
 int router_load_single_router(const char *s, uint8_t purpose,
                               const char **msg);
                               const char **msg);
 void router_load_routers_from_string(const char *s,
 void router_load_routers_from_string(const char *s,

+ 1 - 1
src/or/rephist.c

@@ -630,7 +630,7 @@ rep_hist_get_bandwidth_lines(int for_extrainfo)
     tor_assert(b);
     tor_assert(b);
     format_iso_time(t, b->next_period-NUM_SECS_BW_SUM_INTERVAL);
     format_iso_time(t, b->next_period-NUM_SECS_BW_SUM_INTERVAL);
     tor_snprintf(cp, len-(cp-buf), "%s%s %s (%d s) ",
     tor_snprintf(cp, len-(cp-buf), "%s%s %s (%d s) ",
-                 for_extrainfo ? "" : "opt ", 
+                 for_extrainfo ? "" : "opt ",
                  r ? "read-history" : "write-history", t,
                  r ? "read-history" : "write-history", t,
                  NUM_SECS_BW_SUM_INTERVAL);
                  NUM_SECS_BW_SUM_INTERVAL);
     cp += strlen(cp);
     cp += strlen(cp);

+ 3 - 2
src/or/router.c

@@ -980,7 +980,8 @@ router_rebuild_descriptor(int force)
                             ei->cache_info.signed_descriptor_digest);
                             ei->cache_info.signed_descriptor_digest);
 
 
   /* Now finish the router descriptor. */
   /* Now finish the router descriptor. */
-  memcpy(ri->extra_info_digest, ei->cache_info.signed_descriptor_digest,
+  memcpy(ri->cache_info.extra_info_digest,
+         ei->cache_info.signed_descriptor_digest,
          DIGEST_LEN);
          DIGEST_LEN);
   ri->cache_info.signed_descriptor_body = tor_malloc(8192);
   ri->cache_info.signed_descriptor_body = tor_malloc(8192);
   if (router_dump_router_to_string(ri->cache_info.signed_descriptor_body, 8192,
   if (router_dump_router_to_string(ri->cache_info.signed_descriptor_body, 8192,
@@ -1258,7 +1259,7 @@ router_dump_router_to_string(char *s, size_t maxlen, routerinfo_t *router,
   }
   }
 
 
   base16_encode(extra_info_digest, sizeof(extra_info_digest),
   base16_encode(extra_info_digest, sizeof(extra_info_digest),
-                router->extra_info_digest, DIGEST_LEN);
+                router->cache_info.extra_info_digest, DIGEST_LEN);
 
 
   /* Generate the easy portion of the router descriptor. */
   /* Generate the easy portion of the router descriptor. */
   result = tor_snprintf(s, maxlen,
   result = tor_snprintf(s, maxlen,

+ 91 - 4
src/or/routerlist.c

@@ -1446,9 +1446,11 @@ router_get_by_descriptor_digest(const char *digest)
 signed_descriptor_t *
 signed_descriptor_t *
 extrainfo_get_by_descriptor_digest(const char *digest)
 extrainfo_get_by_descriptor_digest(const char *digest)
 {
 {
-  /* XXXX020 implement me. */
-  (void)digest;
-  return NULL;
+  extrainfo_t *ei;
+  tor_assert(digest);
+  if (!routerlist) return NULL;
+  ei = digestmap_get(routerlist->extra_info_map, digest);
+  return ei ? &ei->cache_info : NULL;
 }
 }
 
 
 /** Return a pointer to the signed textual representation of a descriptor.
 /** Return a pointer to the signed textual representation of a descriptor.
@@ -1487,6 +1489,7 @@ router_get_routerlist(void)
     routerlist->old_routers = smartlist_create();
     routerlist->old_routers = smartlist_create();
     routerlist->identity_map = digestmap_new();
     routerlist->identity_map = digestmap_new();
     routerlist->desc_digest_map = digestmap_new();
     routerlist->desc_digest_map = digestmap_new();
+    routerlist->extra_info_map = digestmap_new();
   }
   }
   return routerlist;
   return routerlist;
 }
 }
@@ -1546,6 +1549,13 @@ signed_descriptor_from_routerinfo(routerinfo_t *ri)
   return sd;
   return sd;
 }
 }
 
 
+/** DOCDOC */
+static void
+_extrainfo_free(void *e)
+{
+  extrainfo_free(e);
+}
+
 /** Free all storage held by a routerlist <b>rl</b> */
 /** Free all storage held by a routerlist <b>rl</b> */
 void
 void
 routerlist_free(routerlist_t *rl)
 routerlist_free(routerlist_t *rl)
@@ -1553,6 +1563,7 @@ routerlist_free(routerlist_t *rl)
   tor_assert(rl);
   tor_assert(rl);
   digestmap_free(rl->identity_map, NULL);
   digestmap_free(rl->identity_map, NULL);
   digestmap_free(rl->desc_digest_map, NULL);
   digestmap_free(rl->desc_digest_map, NULL);
+  digestmap_free(rl->extra_info_map, _extrainfo_free);
   SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
   SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
                     routerinfo_free(r));
                     routerinfo_free(r));
   SMARTLIST_FOREACH(rl->old_routers, signed_descriptor_t *, sd,
   SMARTLIST_FOREACH(rl->old_routers, signed_descriptor_t *, sd,
@@ -1642,6 +1653,44 @@ routerlist_insert(routerlist_t *rl, routerinfo_t *ri)
   // routerlist_assert_ok(rl);
   // routerlist_assert_ok(rl);
 }
 }
 
 
+/**DOCDOC*/
+static void
+extrainfo_insert(routerlist_t *rl, extrainfo_t *ei)
+{
+  routerinfo_t *ri = digestmap_get(rl->identity_map,
+                                   ei->cache_info.identity_digest);
+  extrainfo_t *ei_tmp;
+  if (!ri || routerinfo_incompatible_with_extrainfo(ri,ei)) {
+    int found = 0;
+    if (ei->pending_sig || ei->bad_sig) {
+      extrainfo_free(ei);
+      return;
+    }
+    /* The signature checks out; let's see if one of the old routers
+     * matches. */
+    SMARTLIST_FOREACH(rl->old_routers, signed_descriptor_t *, sd, {
+        if (!memcmp(ei->cache_info.identity_digest,
+                    sd->identity_digest, DIGEST_LEN) &&
+            !memcmp(ei->cache_info.signed_descriptor_digest,
+                    sd->extra_info_digest, DIGEST_LEN) &&
+            sd->published_on == ei->cache_info.published_on) {
+          found = 1;
+          break;
+        }
+      });
+    if (!found) {
+      extrainfo_free(ei);
+      return;
+    }
+  }
+
+  ei_tmp = digestmap_set(rl->extra_info_map,
+                         ei->cache_info.signed_descriptor_digest,
+                         ei);
+  if (ei_tmp)
+    extrainfo_free(ei_tmp);
+}
+
 /** If we're a directory cache and routerlist <b>rl</b> doesn't have
 /** If we're a directory cache and routerlist <b>rl</b> doesn't have
  * a copy of router <b>ri</b> yet, add it to the list of old (not
  * a copy of router <b>ri</b> yet, add it to the list of old (not
  * recommended but still served) descriptors. Else free it. */
  * recommended but still served) descriptors. Else free it. */
@@ -1673,6 +1722,7 @@ void
 routerlist_remove(routerlist_t *rl, routerinfo_t *ri, int idx, int make_old)
 routerlist_remove(routerlist_t *rl, routerinfo_t *ri, int idx, int make_old)
 {
 {
   routerinfo_t *ri_tmp;
   routerinfo_t *ri_tmp;
+  extrainfo_t *ei_tmp;
   idx = _routerlist_find_elt(rl->routers, ri, idx);
   idx = _routerlist_find_elt(rl->routers, ri, idx);
   if (idx < 0)
   if (idx < 0)
     return;
     return;
@@ -1686,6 +1736,7 @@ routerlist_remove(routerlist_t *rl, routerinfo_t *ri, int idx, int make_old)
   ri_tmp = digestmap_remove(rl->identity_map, ri->cache_info.identity_digest);
   ri_tmp = digestmap_remove(rl->identity_map, ri->cache_info.identity_digest);
   router_dir_info_changed();
   router_dir_info_changed();
   tor_assert(ri_tmp == ri);
   tor_assert(ri_tmp == ri);
+
   if (make_old && get_options()->DirPort &&
   if (make_old && get_options()->DirPort &&
       ri->purpose == ROUTER_PURPOSE_GENERAL) {
       ri->purpose == ROUTER_PURPOSE_GENERAL) {
     signed_descriptor_t *sd;
     signed_descriptor_t *sd;
@@ -1698,6 +1749,10 @@ routerlist_remove(routerlist_t *rl, routerinfo_t *ri, int idx, int make_old)
     tor_assert(ri_tmp == ri);
     tor_assert(ri_tmp == ri);
     router_bytes_dropped += ri->cache_info.signed_descriptor_len;
     router_bytes_dropped += ri->cache_info.signed_descriptor_len;
     routerinfo_free(ri);
     routerinfo_free(ri);
+    ei_tmp = digestmap_remove(rl->extra_info_map,
+                              ri->cache_info.extra_info_digest);
+    if (ei_tmp)
+      extrainfo_free(ei_tmp);
   }
   }
   // routerlist_assert_ok(rl);
   // routerlist_assert_ok(rl);
 }
 }
@@ -1706,6 +1761,7 @@ static void
 routerlist_remove_old(routerlist_t *rl, signed_descriptor_t *sd, int idx)
 routerlist_remove_old(routerlist_t *rl, signed_descriptor_t *sd, int idx)
 {
 {
   signed_descriptor_t *sd_tmp;
   signed_descriptor_t *sd_tmp;
+  extrainfo_t *ei_tmp;
   idx = _routerlist_find_elt(rl->old_routers, sd, idx);
   idx = _routerlist_find_elt(rl->old_routers, sd, idx);
   if (idx < 0)
   if (idx < 0)
     return;
     return;
@@ -1715,6 +1771,12 @@ routerlist_remove_old(routerlist_t *rl, signed_descriptor_t *sd, int idx)
   tor_assert(sd_tmp == sd);
   tor_assert(sd_tmp == sd);
   router_bytes_dropped += sd->signed_descriptor_len;
   router_bytes_dropped += sd->signed_descriptor_len;
   signed_descriptor_free(sd);
   signed_descriptor_free(sd);
+
+  ei_tmp = digestmap_remove(rl->extra_info_map,
+                            sd->extra_info_digest);
+  if (ei_tmp)
+    extrainfo_free(ei_tmp);
+
   // routerlist_assert_ok(rl);
   // routerlist_assert_ok(rl);
 }
 }
 
 
@@ -1731,6 +1793,7 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old,
                    routerinfo_t *ri_new, int idx, int make_old)
                    routerinfo_t *ri_new, int idx, int make_old)
 {
 {
   routerinfo_t *ri_tmp;
   routerinfo_t *ri_tmp;
+  extrainfo_t *ei_tmp;
   tor_assert(ri_old != ri_new);
   tor_assert(ri_old != ri_new);
   idx = _routerlist_find_elt(rl->routers, ri_old, idx);
   idx = _routerlist_find_elt(rl->routers, ri_old, idx);
   router_dir_info_changed();
   router_dir_info_changed();
@@ -1766,6 +1829,12 @@ routerlist_replace(routerlist_t *rl, routerinfo_t *ri_old,
       /* digests don't match; digestmap_set didn't replace */
       /* digests don't match; digestmap_set didn't replace */
       digestmap_remove(rl->desc_digest_map,
       digestmap_remove(rl->desc_digest_map,
                        ri_old->cache_info.signed_descriptor_digest);
                        ri_old->cache_info.signed_descriptor_digest);
+
+      ei_tmp = digestmap_remove(rl->extra_info_map,
+                                ri_old->cache_info.extra_info_digest);
+      if (ei_tmp) {
+        extrainfo_free(ei_tmp);
+      }
     }
     }
     routerinfo_free(ri_old);
     routerinfo_free(ri_old);
   }
   }
@@ -2067,6 +2136,18 @@ router_add_to_routerlist(routerinfo_t *router, const char **msg,
   return 0;
   return 0;
 }
 }
 
 
+/** DOCDOC */
+void
+router_add_extrainfo_to_routerlist(extrainfo_t *ei, const char **msg,
+                                   int from_cache, int from_fetch)
+{
+  /* XXXX020 cache on disk */
+  (void)from_cache;
+  (void)from_fetch;
+  (void)msg;
+  extrainfo_insert(router_get_routerlist(), ei);
+}
+
 /** Sorting helper: return &lt;0, 0, or &gt;0 depending on whether the
 /** Sorting helper: return &lt;0, 0, or &gt;0 depending on whether the
  * signed_descriptor_t* in *<b>a</b> has an identity digest preceding, equal
  * signed_descriptor_t* in *<b>a</b> has an identity digest preceding, equal
  * to, or later than that of *<b>b</b>. */
  * to, or later than that of *<b>b</b>. */
@@ -4438,6 +4519,9 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei)
   tor_assert(ri);
   tor_assert(ri);
   tor_assert(ei);
   tor_assert(ei);
 
 
+  if (ei->bad_sig)
+    return 1;
+
   if (strcmp(ri->nickname, ei->nickname) ||
   if (strcmp(ri->nickname, ei->nickname) ||
       memcmp(ri->cache_info.identity_digest, ei->cache_info.identity_digest,
       memcmp(ri->cache_info.identity_digest, ei->cache_info.identity_digest,
              DIGEST_LEN))
              DIGEST_LEN))
@@ -4448,8 +4532,11 @@ routerinfo_incompatible_with_extrainfo(routerinfo_t *ri, extrainfo_t *ei)
     if (crypto_pk_public_checksig(ri->identity_pkey, signed_digest,
     if (crypto_pk_public_checksig(ri->identity_pkey, signed_digest,
                                   ei->pending_sig, 128) != 20 ||
                                   ei->pending_sig, 128) != 20 ||
         memcmp(signed_digest, ei->cache_info.signed_descriptor_digest,
         memcmp(signed_digest, ei->cache_info.signed_descriptor_digest,
-               DIGEST_LEN))
+               DIGEST_LEN)) {
+      ei->bad_sig = 1;
+      tor_free(ei->pending_sig);
       return 1; /* Bad signature, or no match. */
       return 1; /* Bad signature, or no match. */
+    }
 
 
     tor_free(ei->pending_sig);
     tor_free(ei->pending_sig);
   }
   }

+ 2 - 2
src/or/routerparse.c

@@ -967,8 +967,8 @@ router_parse_entry_from_string(const char *s, const char *end,
   if ((tok = find_first_by_keyword(tokens, K_EXTRA_INFO_DIGEST))) {
   if ((tok = find_first_by_keyword(tokens, K_EXTRA_INFO_DIGEST))) {
     tor_assert(tok->n_args >= 1);
     tor_assert(tok->n_args >= 1);
     if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
     if (strlen(tok->args[0]) == HEX_DIGEST_LEN) {
-      base16_decode(router->extra_info_digest, DIGEST_LEN, tok->args[0],
-                    HEX_DIGEST_LEN);
+      base16_decode(router->cache_info.extra_info_digest,
+                    DIGEST_LEN, tok->args[0], HEX_DIGEST_LEN);
     } else {
     } else {
       log_warn(LD_DIR, "Invalid extra info digest %s", escaped(tok->args[0]));
       log_warn(LD_DIR, "Invalid extra info digest %s", escaped(tok->args[0]));
     }
     }