Browse Source

r15510@catbus: nickm | 2007-10-02 16:14:42 -0400
Add support for more vote URLs that weasel wanted. Weasel: please test this before I inflict it on anybody else. :)


svn:r11749

Nick Mathewson 17 years ago
parent
commit
f4f780b526
5 changed files with 102 additions and 30 deletions
  1. 4 0
      ChangeLog
  2. 9 0
      doc/spec/dir-spec.txt
  3. 15 4
      src/or/directory.c
  4. 70 24
      src/or/dirvote.c
  5. 4 2
      src/or/or.h

+ 4 - 0
ChangeLog

@@ -12,6 +12,10 @@ Changes in version 0.2.0.8-alpha - 2007-??-??
     - Use annotations to record the source for each descriptor.
     - Use annotations to record the purpose of each descriptor.
 
+  o Minor features (v3 authority system):
+    - Add more ways for tools to download the votes that lead to the current
+      consensus.
+
   o Major bugfixes (performance):
     - Fix really bad O(n^2) performance when parsing a long list of routers:
       Instead of searching the entire list for an "extra-info " string which

+ 9 - 0
doc/spec/dir-spec.txt

@@ -1152,6 +1152,9 @@ $Id$
    at
       http://<hostname>/tor/status-vote/next/<fp>.z
    where <fp> is the fingerprint of the other authority's identity key.
+   And at
+      http://<hostname>/tor/status-vote/next/d/<d>.z
+   where <d> is the digest of the vote document.
 
    The consensus status, along with as many signatures as the server
    currently knows, should be available at
@@ -1166,6 +1169,12 @@ $Id$
    and
       http://<hostname>/tor/status-vote/current/consensus-signatures.z
 
+   The other vote documents are analogously made available under
+     http://<hostname>/tor/status-vote/current/authority.z
+     http://<hostname>/tor/status-vote/current/<fp>.z
+     http://<hostname>/tor/status-vote/current/d/<d>.z
+   once the consensus is complete.
+
    Once an authority has computed and signed a consensus network status, it
    should send its detached signature to each other authority in an HTTP POST
    request to the URL:

+ 15 - 4
src/or/directory.c

@@ -2124,16 +2124,27 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers,
       const char *item;
       if ((item=dirvote_get_pending_detached_signatures()))
         smartlist_add(items, (char*)item);
-    } else if (!current && !strcmp(url, "authority")) {
+    } else if (!strcmp(url, "authority")) {
       const cached_dir_t *d;
-      if ((d=dirvote_get_vote(NULL)))
+      if ((d=dirvote_get_vote(NULL, 1, current, !current)))
         smartlist_add(dir_items, (cached_dir_t*)d);
-    } else if (!current) {
+    } else {
       const cached_dir_t *d;
       smartlist_t *fps = smartlist_create();
+      int by_id, include_pending, include_previous;
+      if (!strcmpstart(url, "d/")) {
+        url += 2;
+        by_id = 0;
+        include_pending = include_previous = 1;
+      } else {
+        by_id = 1;
+        include_pending = current;
+        include_previous = !current;
+      }
       dir_split_resource_into_fingerprints(url, fps, NULL, 1, 1);
       SMARTLIST_FOREACH(fps, char *, fp, {
-          if ((d = dirvote_get_vote(fp)))
+          if ((d = dirvote_get_vote(fp, by_id,
+                                    include_pending, include_previous)))
             smartlist_add(dir_items, (cached_dir_t*)d);
           tor_free(fp);
         });

+ 70 - 24
src/or/dirvote.c

@@ -1133,8 +1133,7 @@ dirvote_recalculate_timing(time_t now)
   voting_schedule.fetch_missing_votes = start - dist_delay - (vote_delay/2);
   voting_schedule.voting_starts = start - dist_delay - vote_delay;
 
-  voting_schedule.discard_old_votes = start +
-    ((end-start) - vote_delay - dist_delay)/2 ;
+  voting_schedule.discard_old_votes = start;
 }
 
 /** Entry point: Take whatever voting actions are pending as of <b>now</b>. */
@@ -1185,7 +1184,7 @@ dirvote_act(time_t now)
   }
   if (voting_schedule.discard_old_votes < now) {
     log_notice(LD_DIR, "Time to discard old votes.");
-    dirvote_clear_pending_votes();
+    dirvote_clear_votes(0);
     dirvote_recalculate_timing(now);
   }
 }
@@ -1198,8 +1197,12 @@ typedef struct pending_vote_t {
   networkstatus_vote_t *vote;
 } pending_vote_t;
 
-/** List of pending_vote_t for the current vote. */
+/** List of pending_vote_t for the current vote.  Before we've used them to
+ * build a consensus, the votes go here. */
 static smartlist_t *pending_vote_list = NULL;
+/** List of pending_vote_t for the previous vote.  After we've used them to
+ * build a consensus, the votes go here for the next period. */
+static smartlist_t *previous_vote_list = NULL;
 /** The body of the consensus that we're currently building.  Once we
  * have it built, it goes into dirserv.c */
 static char *pending_consensus_body = NULL;
@@ -1251,7 +1254,7 @@ dirvote_fetch_missing_votes(void)
     {
       if (!(ds->type & V3_AUTHORITY))
         continue;
-      if (!dirvote_get_vote(ds->v3_identity_digest)) {
+      if (!dirvote_get_vote(ds->v3_identity_digest, 1, 1, 0)) {
         char *cp = tor_malloc(HEX_DIGEST_LEN+1);
         base16_encode(cp, HEX_DIGEST_LEN+1, ds->v3_identity_digest,
                       DIGEST_LEN);
@@ -1288,17 +1291,36 @@ dirvote_fetch_missing_signatures(void)
 
 /** Drop all currently pending votes, consensus, and detached signatures. */
 void
-dirvote_clear_pending_votes(void)
+dirvote_clear_votes(int all_votes)
 {
-  if (pending_vote_list) {
+  if (!previous_vote_list)
+    previous_vote_list = smartlist_create();
+  if (!pending_vote_list)
+    pending_vote_list = smartlist_create();
+
+  /* All "previous" votes are now junk. */
+  SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, v, {
+      cached_dir_decref(v->vote_body);
+      v->vote_body = NULL;
+      networkstatus_vote_free(v->vote);
+      tor_free(v);
+    });
+  smartlist_clear(previous_vote_list);
+
+  if (all_votes) {
+    /* If we're dumping all the votes, we delete the pending ones. */
     SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, {
         cached_dir_decref(v->vote_body);
         v->vote_body = NULL;
         networkstatus_vote_free(v->vote);
         tor_free(v);
       });
-    smartlist_clear(pending_vote_list);
+  } else {
+    /* Otherwise, we move them into "previous". */
+    smartlist_add_all(previous_vote_list, pending_vote_list);
   }
+  smartlist_clear(pending_vote_list);
+
   if (pending_consensus_signature_list) {
     SMARTLIST_FOREACH(pending_consensus_signature_list, char *, cp,
                       tor_free(cp));
@@ -1685,12 +1707,13 @@ dirvote_publish_consensus(void)
 void
 dirvote_free_all(void)
 {
-  dirvote_clear_pending_votes();
-  if (pending_vote_list) {
-    /* now empty as a result of clear_pending_votes. */
-    smartlist_free(pending_vote_list);
-    pending_vote_list = NULL;
-  }
+  dirvote_clear_votes(1);
+  /* now empty as a result of clear_pending_votes. */
+  smartlist_free(pending_vote_list);
+  pending_vote_list = NULL;
+  smartlist_free(previous_vote_list);
+  previous_vote_list = NULL;
+
   tor_free(pending_consensus_body);
   tor_free(pending_consensus_signatures);
   if (pending_consensus) {
@@ -1725,22 +1748,45 @@ dirvote_get_pending_detached_signatures(void)
 
 /** Return the vote for the authority with the v3 authority identity key
  * digest <b>id</b>.  If <b>id</b> is NULL, return our own vote. May return
- * NULL if we have no vote for the authority in question. */
+ * NULL if we have no vote for the authority in question.
+ * DOCDOC args */
 const cached_dir_t *
-dirvote_get_vote(const char *id)
+dirvote_get_vote(const char *fp, int by_id, int include_previous,
+                 int include_pending)
 {
-  if (!pending_vote_list)
+  if (!pending_vote_list && !previous_vote_list)
     return NULL;
-  if (id == NULL) {
+  if (fp == NULL) {
     authority_cert_t *c = get_my_v3_authority_cert();
-    if (c)
-      id = c->cache_info.identity_digest;
-    else
+    if (c) {
+      fp = c->cache_info.identity_digest;
+      by_id = 1;
+    } else
       return NULL;
   }
-  SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, pv,
-       if (!memcmp(get_voter(pv->vote)->identity_digest, id, DIGEST_LEN))
-         return pv->vote_body);
+  if (by_id) {
+    if (pending_vote_list && include_pending) {
+      SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, pv,
+        if (!memcmp(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN))
+          return pv->vote_body);
+    }
+    if (previous_vote_list && include_previous) {
+      SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, pv,
+        if (!memcmp(get_voter(pv->vote)->identity_digest, fp, DIGEST_LEN))
+          return pv->vote_body);
+    }
+  } else {
+    if (pending_vote_list && include_pending) {
+      SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, pv,
+        if (!memcmp(pv->vote->networkstatus_digest, fp, DIGEST_LEN))
+          return pv->vote_body);
+    }
+    if (previous_vote_list && include_previous) {
+      SMARTLIST_FOREACH(previous_vote_list, pending_vote_t *, pv,
+        if (!memcmp(pv->vote->networkstatus_digest, fp, DIGEST_LEN))
+          return pv->vote_body);
+    }
+  }
   return NULL;
 }
 

+ 4 - 2
src/or/or.h

@@ -2887,7 +2887,7 @@ void dirvote_act(time_t now);
 
 /* invoked on timers and by outside triggers. */
 void dirvote_perform_vote(void);
-void dirvote_clear_pending_votes(void);
+void dirvote_clear_votes(int all_votes);
 struct pending_vote_t * dirvote_add_vote(const char *vote_body,
                                          const char **msg_out,
                                          int *status_out);
@@ -2898,7 +2898,9 @@ int dirvote_publish_consensus(void);
 /* Item access */
 const char *dirvote_get_pending_consensus(void);
 const char *dirvote_get_pending_detached_signatures(void);
-const cached_dir_t *dirvote_get_vote(const char *id);
+const cached_dir_t *dirvote_get_vote(const char *fp, int by_id,
+                                     int include_pending,
+                                     int include_previous);
 
 #ifdef DIRVOTE_PRIVATE
 int networkstatus_check_voter_signature(networkstatus_vote_t *consensus,