Browse Source

Merge remote-tracking branch 'public/bug8158'

Nick Mathewson 11 years ago
parent
commit
01184f164f
4 changed files with 91 additions and 32 deletions
  1. 3 0
      changes/bug8158
  2. 2 32
      src/or/dirserv.c
  3. 81 0
      src/or/dirvote.c
  4. 5 0
      src/or/dirvote.h

+ 3 - 0
changes/bug8158

@@ -0,0 +1,3 @@
+  o Minor bugfixes:
+    - Use less space when formatting identical microdescriptor lines in
+      directory votes. Fixes bug 8158; bugfix on 0.2.4.1-alpha.

+ 2 - 32
src/or/dirserv.c

@@ -66,19 +66,6 @@ static cached_dir_t *the_directory = NULL;
 /** For authoritative directories: the current (v1) network status. */
 static cached_dir_t the_runningrouters;
 
-/** Array of start and end of consensus methods used for supported
-    microdescriptor formats. */
-static const struct consensus_method_range_t {
-  int low;
-  int high;
-} microdesc_consensus_methods[] = {
-  {MIN_METHOD_FOR_MICRODESC, MIN_METHOD_FOR_A_LINES - 1},
-  {MIN_METHOD_FOR_A_LINES, MIN_METHOD_FOR_P6_LINES - 1},
-  {MIN_METHOD_FOR_P6_LINES, MIN_METHOD_FOR_NTOR_KEY - 1},
-  {MIN_METHOD_FOR_NTOR_KEY, MAX_SUPPORTED_CONSENSUS_METHOD},
-  {-1, -1}
-};
-
 static void directory_remove_invalid(void);
 static cached_dir_t *dirserv_regenerate_directory(void);
 static char *format_versions_list(config_line_t *ln);
@@ -2811,11 +2798,9 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
   microdescriptors = smartlist_new();
 
   SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) {
-    const struct consensus_method_range_t *cmr = NULL;
     if (ri->cache_info.published_on >= cutoff) {
       routerstatus_t *rs;
       vote_routerstatus_t *vrs;
-      microdesc_t *md;
       node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
       if (!node)
         continue;
@@ -2833,23 +2818,8 @@ dirserv_generate_networkstatus_vote_obj(crypto_pk_t *private_key,
         rs->is_flagged_running = 0;
 
       vrs->version = version_from_platform(ri->platform);
-      for (cmr = microdesc_consensus_methods;
-           cmr->low != -1 && cmr->high != -1;
-           cmr++) {
-        md = dirvote_create_microdescriptor(ri, cmr->low);
-        if (md) {
-          char buf[128];
-          vote_microdesc_hash_t *h;
-          dirvote_format_microdesc_vote_line(buf, sizeof(buf), md,
-                                             cmr->low, cmr->high);
-          h = tor_malloc_zero(sizeof(vote_microdesc_hash_t));
-          h->microdesc_hash_line = tor_strdup(buf);
-          h->next = vrs->microdesc;
-          vrs->microdesc = h;
-          md->last_listed = now;
-          smartlist_add(microdescriptors, md);
-        }
-      }
+      vrs->microdesc = dirvote_format_all_microdesc_vote_lines(ri, now,
+                                                        microdescriptors);
 
       smartlist_add(routerstatuses, vrs);
     }

+ 81 - 0
src/or/dirvote.c

@@ -3651,6 +3651,87 @@ dirvote_format_microdesc_vote_line(char *out_buf, size_t out_buf_len,
   return ret;
 }
 
+/** Array of start and end of consensus methods used for supported
+    microdescriptor formats. */
+static const struct consensus_method_range_t {
+  int low;
+  int high;
+} microdesc_consensus_methods[] = {
+  {MIN_METHOD_FOR_MICRODESC, MIN_METHOD_FOR_A_LINES - 1},
+  {MIN_METHOD_FOR_A_LINES, MIN_METHOD_FOR_P6_LINES - 1},
+  {MIN_METHOD_FOR_P6_LINES, MIN_METHOD_FOR_NTOR_KEY - 1},
+  {MIN_METHOD_FOR_NTOR_KEY, MAX_SUPPORTED_CONSENSUS_METHOD},
+  {-1, -1}
+};
+
+/** Helper type used when generating the microdescriptor lines in a directory
+ * vote. */
+typedef struct microdesc_vote_line_t {
+  int low;
+  int high;
+  microdesc_t *md;
+  struct microdesc_vote_line_t *next;
+} microdesc_vote_line_t;
+
+/** Generate and return a linked list of all the lines that should appear to
+ * describe a router's microdescriptor versions in a directory vote.
+ * Add the generated microdescriptors to <b>microdescriptors_out</b>. */
+vote_microdesc_hash_t *
+dirvote_format_all_microdesc_vote_lines(const routerinfo_t *ri, time_t now,
+                                        smartlist_t *microdescriptors_out)
+{
+  const struct consensus_method_range_t *cmr;
+  microdesc_vote_line_t *entries = NULL, *ep;
+  vote_microdesc_hash_t *result = NULL;
+
+  /* Generate the microdescriptors. */
+  for (cmr = microdesc_consensus_methods;
+       cmr->low != -1 && cmr->high != -1;
+       cmr++) {
+    microdesc_t *md = dirvote_create_microdescriptor(ri, cmr->low);
+    if (md) {
+      microdesc_vote_line_t *e =
+        tor_malloc_zero(sizeof(microdesc_vote_line_t));
+      e->md = md;
+      e->low = cmr->low;
+      e->high = cmr->high;
+      e->next = entries;
+      entries = e;
+    }
+  }
+
+  /* Compress adjacent identical ones */
+  for (ep = entries; ep; ep = ep->next) {
+    while (ep->next &&
+           fast_memeq(ep->md->digest, ep->next->md->digest, DIGEST256_LEN) &&
+           ep->low == ep->next->high + 1) {
+      microdesc_vote_line_t *next = ep->next;
+      ep->low = next->low;
+      microdesc_free(next->md);
+      ep->next = next->next;
+      tor_free(next);
+    }
+  }
+
+  /* Format them into vote_microdesc_hash_t, and add to microdescriptors_out.*/
+  while ((ep = entries)) {
+    char buf[128];
+    vote_microdesc_hash_t *h;
+    dirvote_format_microdesc_vote_line(buf, sizeof(buf), ep->md,
+                                       ep->low, ep->high);
+    h = tor_malloc_zero(sizeof(vote_microdesc_hash_t));
+    h->microdesc_hash_line = tor_strdup(buf);
+    h->next = result;
+    result = h;
+    ep->md->last_listed = now;
+    smartlist_add(microdescriptors_out, ep->md);
+    entries = ep->next;
+    tor_free(ep);
+  }
+
+  return result;
+}
+
 /** If <b>vrs</b> has a hash made for the consensus method <b>method</b> with
  * the digest algorithm <b>alg</b>, decode it and copy it into
  * <b>digest256_out</b> and return 0.  Otherwise return -1. */

+ 5 - 0
src/or/dirvote.h

@@ -109,6 +109,11 @@ ssize_t dirvote_format_microdesc_vote_line(char *out, size_t out_len,
                                            const microdesc_t *md,
                                            int consensus_method_low,
                                            int consensus_method_high);
+vote_microdesc_hash_t *dirvote_format_all_microdesc_vote_lines(
+                                        const routerinfo_t *ri,
+                                        time_t now,
+                                        smartlist_t *microdescriptors_out);
+
 int vote_routerstatus_find_microdesc_hash(char *digest256_out,
                                           const vote_routerstatus_t *vrs,
                                           int method,