[or-cvs] r10927: Some dirvote code to handle generating votes and slinging th (in tor/trunk: . src/or)

nickm at seul.org nickm at seul.org
Wed Jul 25 22:56:46 UTC 2007


Author: nickm
Date: 2007-07-25 18:56:44 -0400 (Wed, 25 Jul 2007)
New Revision: 10927

Modified:
   tor/trunk/
   tor/trunk/src/or/directory.c
   tor/trunk/src/or/dirserv.c
   tor/trunk/src/or/dirvote.c
   tor/trunk/src/or/or.h
   tor/trunk/src/or/router.c
Log:
 r13902 at catbus:  nickm | 2007-07-25 17:43:52 -0400
 Some dirvote code to handle generating votes and slinging them around.  More code is still needed.



Property changes on: tor/trunk
___________________________________________________________________
 svk:merge ticket from /tor/trunk [r13902] on 8246c3cf-6607-4228-993b-4d95d33730f1

Modified: tor/trunk/src/or/directory.c
===================================================================
--- tor/trunk/src/or/directory.c	2007-07-25 22:56:40 UTC (rev 10926)
+++ tor/trunk/src/or/directory.c	2007-07-25 22:56:44 UTC (rev 10927)
@@ -78,6 +78,7 @@
     return 1; /* if we have to ask, better make it anonymous */
   if (dir_purpose == DIR_PURPOSE_FETCH_DIR ||
       dir_purpose == DIR_PURPOSE_UPLOAD_DIR ||
+      dir_purpose == DIR_PURPOSE_UPLOAD_VOTE ||
       dir_purpose == DIR_PURPOSE_FETCH_RUNNING_LIST ||
       dir_purpose == DIR_PURPOSE_FETCH_NETWORKSTATUS ||
       dir_purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
@@ -501,6 +502,9 @@
     case DIR_PURPOSE_UPLOAD_RENDDESC:
       log_debug(LD_REND,"initiating hidden-service descriptor upload");
       break;
+    case DIR_PURPOSE_UPLOAD_VOTE:
+      log_debug(LD_OR,"initiating server vote upload");
+      break;
     case DIR_PURPOSE_FETCH_RUNNING_LIST:
       log_debug(LD_DIR,"initiating running-routers fetch");
       break;
@@ -685,6 +689,12 @@
       httpcommand = "POST";
       url = tor_strdup("/tor/");
       break;
+    case DIR_PURPOSE_UPLOAD_VOTE:
+      tor_assert(!resource);
+      tor_assert(payload);
+      httpcommand = "POST";
+      url = tor_strdup("/tor/post/vote");
+      break;
     case DIR_PURPOSE_FETCH_RENDDESC:
       tor_assert(resource);
       tor_assert(!payload);
@@ -1367,6 +1377,30 @@
      * dirservers down just because they don't like us. */
   }
 
+  if (conn->_base.purpose == DIR_PURPOSE_UPLOAD_VOTE) {
+    switch (status_code) {
+      case 200: {
+        log_notice(LD_DIR,"Uploaded a vote to dirserver %s:%d",
+                   conn->_base.address, conn->_base.port);
+        }
+        break;
+      case 400:
+        log_warn(LD_GENERAL,"http status 400 (%s) response after uploading "
+                 "vote to dirserver '%s:%d'. Please correct.",
+                 escaped(reason), conn->_base.address, conn->_base.port);
+        break;
+      default:
+        log_warn(LD_GENERAL,
+             "http status %d (%s) reason unexpected while uploading "
+             "vote to server '%s:%d').",
+             status_code, escaped(reason), conn->_base.address,
+             conn->_base.port);
+        break;
+    }
+    /* return 0 in all cases, since we don't want to mark any
+     * dirservers down just because they don't like us. */
+  }
+
   if (conn->_base.purpose == DIR_PURPOSE_FETCH_RENDDESC) {
     log_info(LD_REND,"Received rendezvous descriptor (size %d, status %d "
              "(%s))",
@@ -2075,6 +2109,18 @@
     goto done;
   }
 
+  if (authdir_mode_v3(options) &&
+      !strcmp(url,"/tor/post/vote")) { /* server descriptor post */
+    const char *msg = "OK";
+    if (dirserv_add_vote(body, &msg)) {
+      write_http_status_line(conn, 200, "Vote stored");
+    } else {
+      tor_assert(msg);
+      write_http_status_line(conn, 400, msg);
+    }
+    goto done;
+  }
+
   /* we didn't recognize the url */
   write_http_status_line(conn, 404, "Not found");
 

Modified: tor/trunk/src/or/dirserv.c
===================================================================
--- tor/trunk/src/or/dirserv.c	2007-07-25 22:56:40 UTC (rev 10926)
+++ tor/trunk/src/or/dirserv.c	2007-07-25 22:56:44 UTC (rev 10927)
@@ -1116,7 +1116,7 @@
 
 /** Allocate and return a new cached_dir_t containing the string <b>s</b>,
  * published at <b>published</b>. */
-static cached_dir_t *
+cached_dir_t *
 new_cached_dir(char *s, time_t published)
 {
   cached_dir_t *d = tor_malloc_zero(sizeof(cached_dir_t));
@@ -2075,7 +2075,9 @@
   return status;
 }
 
-static cached_dir_t *
+/** DOCDOC */
+/* XXXX020 possibly rename and relocate to dirvote.c? */
+cached_dir_t *
 generate_v3_networkstatus(void)
 {
   crypto_pk_env_t *key = get_my_v3_authority_signing_key();

Modified: tor/trunk/src/or/dirvote.c
===================================================================
--- tor/trunk/src/or/dirvote.c	2007-07-25 22:56:40 UTC (rev 10926)
+++ tor/trunk/src/or/dirvote.c	2007-07-25 22:56:44 UTC (rev 10927)
@@ -866,3 +866,157 @@
   voting_schedule.voting_starts = start - vote_delay - dist_delay;
 }
 
+/** DOCDOC */
+typedef struct pending_vote_t {
+  cached_dir_t *vote_body;
+  networkstatus_vote_t *vote;
+} pending_vote_t;
+
+/** DOCDOC */
+static smartlist_t *pending_vote_list = NULL;
+/** DOCDOC */
+static char *pending_consensus_body = NULL;
+
+/** DOCDOC */
+void
+dirvote_perform_vote(void)
+{
+  cached_dir_t *new_vote = generate_v3_networkstatus();
+  pending_vote_t *pending_vote;
+  const char *msg = "";
+
+  if ((pending_vote = dirvote_add_vote(tor_memdup(new_vote->dir,
+                                                  new_vote->dir_len), &msg))) {
+    log_warn(LD_DIR, "Couldn't store my own vote! (I told myself, '%s'.)",
+             msg);
+    return;
+  }
+
+  directory_post_to_dirservers(DIR_PURPOSE_UPLOAD_VOTE,
+                               ROUTER_PURPOSE_GENERAL,
+                               V3_AUTHORITY,
+                               pending_vote->vote_body->dir,
+                               pending_vote->vote_body->dir_len, 0);
+}
+
+/** DOCDOC */
+void
+dirvote_clear_pending_votes(void)
+{
+  if (!pending_vote_list)
+    return;
+  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);
+}
+
+/** DOCDOC */
+pending_vote_t *
+dirvote_add_vote(char *vote_body, const char **msg_out)
+{
+  networkstatus_vote_t *vote;
+  networkstatus_voter_info_t *vi;
+  trusted_dir_server_t *ds;
+  pending_vote_t *pending_vote = NULL;
+  tor_assert(vote_body);
+  tor_assert(msg_out);
+
+  if (!pending_vote_list)
+    pending_vote_list = smartlist_create();
+  *msg_out = NULL;
+
+  vote = networkstatus_parse_vote_from_string(vote_body, 1);
+  if (!vote) {
+    *msg_out = "Unable to parse vote";
+    goto err;
+  }
+  tor_assert(smartlist_len(vote->voters) == 1);
+  vi = smartlist_get(vote->voters, 0);
+  tor_assert(vi->good_signature == 1);
+  ds = trusteddirserver_get_by_v3_auth_digest(vi->identity_digest);
+  if (!ds || !(ds->type & V3_AUTHORITY)) {
+    *msg_out = "Vote not from a recognized v3 authority";
+    goto err;
+  }
+  /* XXXX020 check times; make sure epochs match. */
+
+  SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, {
+      if (! memcmp(v->vote->cert->cache_info.identity_digest,
+                   vote->cert->cache_info.identity_digest,
+                   DIGEST_LEN)) {
+        log_notice(LD_DIR, "We already have a pending vote from this dir");
+        if (v->vote->published < vote->published) {
+          cached_dir_decref(v->vote_body);
+          networkstatus_vote_free(v->vote);
+          v->vote_body = new_cached_dir(vote_body, vote->published);
+          v->vote = vote;
+          *msg_out = "ok";
+          return v;
+        } else {
+          *msg_out = "Already have a newer pending vote";
+          goto err;
+        }
+      }
+    });
+
+  pending_vote = tor_malloc_zero(sizeof(pending_vote_t));
+  pending_vote->vote_body = new_cached_dir(vote_body, vote->published);
+  pending_vote->vote = vote;
+  smartlist_add(pending_vote_list, pending_vote);
+
+  *msg_out = "ok";
+  return pending_vote;
+ err:
+  tor_free(vote_body);
+  if (vote)
+    networkstatus_vote_free(vote);
+  if (!*msg_out)
+    *msg_out = "Error adding vote";
+  /*XXXX020 free other fields */
+  return NULL;
+}
+
+/** DOCDOC */
+int
+dirvote_compute_consensus(void)
+{
+  /* Have we got enough votes to try? */
+  int n_votes, n_voters;
+  smartlist_t *votes = NULL;
+  char *consensus_body = NULL;
+  authority_cert_t *my_cert;
+
+  if (!pending_vote_list)
+    pending_vote_list = smartlist_create();
+
+  n_voters = get_n_authorities(V3_AUTHORITY);
+  n_votes = smartlist_len(pending_vote_list);
+  /* XXXX020 see if there are enough to go ahead. */
+
+  if (!(my_cert = get_my_v3_authority_cert())) {
+    log_warn(LD_DIR, "Can't generate consensus without a certificate.");
+    goto err;
+  }
+
+  votes = smartlist_create();
+  SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v,
+                    smartlist_add(votes, v->vote));
+
+  consensus_body = networkstatus_compute_consensus(
+        votes, n_voters,
+        my_cert->identity_key,
+        get_my_v3_authority_signing_key());
+
+  tor_free(pending_consensus_body);
+  pending_consensus_body = consensus_body;
+
+  return 0;
+ err:
+  if (votes)
+    smartlist_free(votes);
+  return -1;
+}

Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h	2007-07-25 22:56:40 UTC (rev 10926)
+++ tor/trunk/src/or/or.h	2007-07-25 22:56:44 UTC (rev 10927)
@@ -368,9 +368,14 @@
 /** A connection to a directory server: upload a rendezvous
  * descriptor. */
 #define DIR_PURPOSE_UPLOAD_RENDDESC 9
+/** A connection to a directory server: upload a v3 networkstatus vote. */
+#define DIR_PURPOSE_UPLOAD_VOTE 10
+/** A connection to a directory server: fetch a v3 networkstatus vote. */
+#define DIR_PURPOSE_FETCH_VOTE 11
+
 /** Purpose for connection at a directory server. */
-#define DIR_PURPOSE_SERVER 10
-#define _DIR_PURPOSE_MAX 10
+#define DIR_PURPOSE_SERVER 12
+#define _DIR_PURPOSE_MAX 12
 
 #define _EXIT_PURPOSE_MIN 1
 /** This exit stream wants to do an ordinary connect. */
@@ -2765,7 +2770,10 @@
                               int first_line_only);
 void dirserv_free_all(void);
 void cached_dir_decref(cached_dir_t *d);
+cached_dir_t *new_cached_dir(char *s, time_t published);
 
+cached_dir_t *generate_v3_networkstatus(void);
+
 #ifdef DIRSERV_PRIVATE
 char *
 format_networkstatus_vote(crypto_pk_env_t *private_key,
@@ -2774,6 +2782,7 @@
 
 /********************************* dirvote.c ************************/
 
+/* vote manipulation */
 void networkstatus_vote_free(networkstatus_vote_t *ns);
 char *networkstatus_compute_consensus(smartlist_t *votes,
                                       int total_authorities,
@@ -2784,6 +2793,7 @@
                                        const char *identity);
 int networkstatus_check_consensus_signature(networkstatus_vote_t *consensus);
 
+/* cert manipulation */
 void authority_cert_free(authority_cert_t *cert);
 authority_cert_t *authority_cert_dup(authority_cert_t *cert);
 
@@ -2794,10 +2804,17 @@
   int vote_delay;
   int dist_delay;
 } vote_timing_t;
+/* vote scheduling */
 void dirvote_get_preferred_voting_intervals(vote_timing_t *timing_out);
 time_t dirvote_get_start_of_next_interval(time_t now, int interval);
 void dirvote_recalculate_timing(time_t now);
 
+/* invoked on timers and by outside triggers. */
+void dirvote_perform_vote(void);
+void dirvote_clear_pending_votes(void);
+struct pending_vote_t * dirvote_add_vote(char *vote_body,const char **msg_out);
+int dirvote_compute_consensus(void);
+
 #ifdef DIRVOTE_PRIVATE
 int networkstatus_check_voter_signature(networkstatus_vote_t *consensus,
                                         networkstatus_voter_info_t *voter,
@@ -3187,6 +3204,7 @@
 int authdir_mode(or_options_t *options);
 int authdir_mode_v1(or_options_t *options);
 int authdir_mode_v2(or_options_t *options);
+int authdir_mode_v3(or_options_t *options);
 int authdir_mode_handles_descs(or_options_t *options);
 int authdir_mode_publishes_statuses(or_options_t *options);
 int authdir_mode_tests_reachability(or_options_t *options);

Modified: tor/trunk/src/or/router.c
===================================================================
--- tor/trunk/src/or/router.c	2007-07-25 22:56:40 UTC (rev 10926)
+++ tor/trunk/src/or/router.c	2007-07-25 22:56:44 UTC (rev 10927)
@@ -714,6 +714,14 @@
 {
   return authdir_mode(options) && options->V2AuthoritativeDir != 0;
 }
+/** Return true iff we believe ourselves to be a v3 authoritative
+ * directory server.
+ */
+int
+authdir_mode_v3(or_options_t *options)
+{
+  return authdir_mode(options) && options->V3AuthoritativeDir != 0;
+}
 /** Return true iff we are an authoritative directory server that
  * is willing to receive or serve descriptors on its dirport.
  */



More information about the tor-commits mailing list