[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
[or-cvs] r11575: V3 authority work: fetch missing votes and/or signatures as (in tor/trunk: . doc src/or)
Author: nickm
Date: 2007-09-22 02:06:05 -0400 (Sat, 22 Sep 2007)
New Revision: 11575
Modified:
tor/trunk/
tor/trunk/ChangeLog
tor/trunk/doc/TODO
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/routerlist.c
tor/trunk/src/or/routerparse.c
tor/trunk/src/or/test.c
Log:
r15279@catbus: nickm | 2007-09-22 02:00:06 -0400
V3 authority work: fetch missing votes and/or signatures as needed.
Property changes on: tor/trunk
___________________________________________________________________
svk:merge ticket from /tor/trunk [r15279] on 8246c3cf-6607-4228-993b-4d95d33730f1
Modified: tor/trunk/ChangeLog
===================================================================
--- tor/trunk/ChangeLog 2007-09-22 05:46:51 UTC (rev 11574)
+++ tor/trunk/ChangeLog 2007-09-22 06:06:05 UTC (rev 11575)
@@ -1,3 +1,8 @@
+Changes in version 0.2.0.8-alpha - 2007-??-??
+ o Major features (directory authorities):
+ - When an authority is missing votes or signatures, it now tries to fetch
+ them.
+
Changes in version 0.2.0.7-alpha - 2007-09-21
o New directory authorities:
- Set up moria1 and tor26 as the first v3 directory authorities. See
Modified: tor/trunk/doc/TODO
===================================================================
--- tor/trunk/doc/TODO 2007-09-22 05:46:51 UTC (rev 11574)
+++ tor/trunk/doc/TODO 2007-09-22 06:06:05 UTC (rev 11575)
@@ -59,8 +59,8 @@
. Code to retry download.
o Code to generate consensus from a list of votes
o Detect whether votes are really all for the same period.
- . Push/pull documents as appropriate.
- - Pull votes and signatures if we don't get them.
+ o Push/pull documents as appropriate.
+ o Pull votes and signatures if we don't get them.
- Cache votes and signatures on disk?
o Code to keep consensus docs in limbo if they don't have
have enough signatures.
Modified: tor/trunk/src/or/directory.c
===================================================================
--- tor/trunk/src/or/directory.c 2007-09-22 05:46:51 UTC (rev 11574)
+++ tor/trunk/src/or/directory.c 2007-09-22 06:06:05 UTC (rev 11575)
@@ -297,6 +297,8 @@
break;
case DIR_PURPOSE_FETCH_STATUS_VOTE:
case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
+ type = V3_AUTHORITY;
+ break;
case DIR_PURPOSE_FETCH_CONSENSUS:
case DIR_PURPOSE_FETCH_CERTIFICATE:
type = V3_AUTHORITY;
@@ -377,6 +379,32 @@
}
}
+/** As directory_get_from_dirserver, but initiates a request to <i>every</i>
+ * directory authority other than ourself. Only for use by authorities when
+ * searching for missing information while voting. */
+void
+directory_get_from_all_authorities(uint8_t dir_purpose,
+ uint8_t router_purpose,
+ const char *resource)
+{
+ tor_assert(dir_purpose == DIR_PURPOSE_FETCH_STATUS_VOTE ||
+ dir_purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES);
+
+ SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
+ trusted_dir_server_t *, ds,
+ {
+ routerstatus_t *rs;
+ if (router_digest_is_me(ds->digest))
+ continue;
+ if (!(ds->type & V3_AUTHORITY))
+ continue;
+ rs = &ds->fake_status.status;
+ /* XXXX020 should this ever tunnel via tor? */
+ directory_initiate_command_routerstatus(rs, dir_purpose, router_purpose,
+ 0, resource, NULL, 0);
+ });
+}
+
/** Launch a new connection to the directory server <b>status</b> to
* upload or download a server or rendezvous
* descriptor. <b>dir_purpose</b> determines what
@@ -727,7 +755,7 @@
httpcommand = "GET";
len = strlen(resource)+32;
url = tor_malloc(len);
- tor_snprintf(url, len, "/tor/status-vote/next/%s", resource);
+ tor_snprintf(url, len, "/tor/status-vote/next/%s.z", resource);
break;
case DIR_PURPOSE_FETCH_DETACHED_SIGNATURES:
tor_assert(!resource);
@@ -1318,7 +1346,7 @@
/*XXXX020*/;
}
if (conn->_base.purpose == DIR_PURPOSE_FETCH_CERTIFICATE) {
- log_info(LD_DIR,"Received aurhority certificatess (size %d) from server "
+ log_info(LD_DIR,"Received authority certificatess (size %d) from server "
"'%s:%d'",(int) body_len, conn->_base.address, conn->_base.port);
if (status_code != 200) {
log_fn(status_code == 403 ? LOG_INFO : LOG_WARN, LD_DIR,
@@ -1336,10 +1364,38 @@
}
}
if (conn->_base.purpose == DIR_PURPOSE_FETCH_STATUS_VOTE) {
- /*XXXX020*/;
+ const char *msg;
+ int st;
+ log_info(LD_DIR,"Got votes (size %d) from server %s:%d",
+ (int) body_len, conn->_base.address, conn->_base.port);
+ if (status_code != 200) {
+ log_fn(status_code == 403 ? LOG_INFO : LOG_WARN, LD_DIR,
+ "Received http status code %d (%s) from server "
+ "'%s:%d' while fetching \"/tor/status-vote/next/%s.z\".",
+ status_code, escaped(reason), conn->_base.address,
+ conn->_base.port, conn->requested_resource);
+ tor_free(body); tor_free(headers); tor_free(reason);
+ return -1;
+ }
+ if (!dirvote_add_vote(body, &msg, &st)) {
+ log_warn(LD_DIR, "Error adding retrieved vote: %s", msg);
+ } else {
+ log_info(LD_DIR, "Added vote(s) successfully.");
+ }
}
if (conn->_base.purpose == DIR_PURPOSE_FETCH_DETACHED_SIGNATURES) {
- /*XXXX020*/;
+ log_info(LD_DIR,"Got detached signatures (size %d) from server %s:%d",
+ (int) body_len, conn->_base.address, conn->_base.port);
+ if (status_code != 200) {
+ log_fn(status_code == 403 ? LOG_INFO : LOG_WARN, LD_DIR,
+ "Received http status code %d (%s) from server "
+ "'%s:%d' while fetching \"/tor/status-vote/consensus-signatures.z\".",
+ status_code, escaped(reason), conn->_base.address,
+ conn->_base.port);
+ tor_free(body); tor_free(headers); tor_free(reason);
+ return -1;
+ }
+ dirvote_add_signatures(body);
}
if (conn->_base.purpose == DIR_PURPOSE_FETCH_SERVERDESC ||
Modified: tor/trunk/src/or/dirserv.c
===================================================================
--- tor/trunk/src/or/dirserv.c 2007-09-22 05:46:51 UTC (rev 11574)
+++ tor/trunk/src/or/dirserv.c 2007-09-22 06:06:05 UTC (rev 11575)
@@ -2198,7 +2198,7 @@
{
networkstatus_vote_t *v;
- if (!(v = networkstatus_parse_vote_from_string(status, 1))) {
+ if (!(v = networkstatus_parse_vote_from_string(status, NULL, 1))) {
log_err(LD_BUG,"Generated a networkstatus vote we couldn't parse: "
"<<%s>>", status);
goto err;
Modified: tor/trunk/src/or/dirvote.c
===================================================================
--- tor/trunk/src/or/dirvote.c 2007-09-22 05:46:51 UTC (rev 11574)
+++ tor/trunk/src/or/dirvote.c 2007-09-22 06:06:05 UTC (rev 11575)
@@ -17,7 +17,11 @@
const char *detached_signatures_body,
const char **msg_out);
static char *list_v3_auth_ids(void);
+static void dirvote_fetch_missing_votes(void);
+static void dirvote_fetch_missing_signatures(void);
+/* XXXX020 lots of the functions here could be made static. Do so. */
+
/* =====
* Voting and consensus generation
* ===== */
@@ -641,7 +645,7 @@
{
networkstatus_vote_t *c;
- if (!(c = networkstatus_parse_vote_from_string(result, 0))) {
+ if (!(c = networkstatus_parse_vote_from_string(result, NULL, 0))) {
log_err(LD_BUG,"Generated a networkstatus consensus we couldn't "
"parse.");
tor_free(result);
@@ -686,7 +690,8 @@
}
/** Given a v3 networkstatus consensus in <b>consensus</b>, check every
- * as-yet-unchecked signature on <b>consensus</b>. Return 0 if there are
+ * as-yet-unchecked signature on <b>consensus</b>. Return 1 if there is a
+ * signature from every recognized authority on it, 0 if there are
* enough good signatures from recognized authorities on it, -1 if we might
* get enough good signatures by fetching missing certificates, and -2
* otherwise. Log messages at INFO or WARN: if <b>warn</b> is over 1, warn
@@ -701,7 +706,8 @@
int n_bad = 0;
int n_unknown = 0;
int n_no_signature = 0;
- int n_required = get_n_authorities(V3_AUTHORITY)/2 + 1;
+ int n_v3_authorities = get_n_authorities(V3_AUTHORITY);
+ int n_required = n_v3_authorities/2 + 1;
smartlist_t *need_certs_from = smartlist_create();
smartlist_t *unrecognized = smartlist_create();
smartlist_t *missing_authorities = smartlist_create();
@@ -786,7 +792,9 @@
smartlist_free(need_certs_from);
smartlist_free(missing_authorities);
- if (n_good >= n_required)
+ if (n_good == n_v3_authorities)
+ return 1;
+ else if (n_good >= n_required)
return 0;
else if (n_good + n_missing_key >= n_required)
return -1;
@@ -1076,11 +1084,15 @@
/* True iff we have generated and distributed our vote. */
int have_voted;
+ /* DOCDOC */
+ int have_fetched_missing_votes;
/* True iff we have built a consensus and sent the signatures around. */
int have_built_consensus;
+ /* DOCDOC */
+ int have_fetched_missing_signatures;
/* True iff we have published our consensus. */
int have_published_consensus;
-} voting_schedule = {0,0,0,0,0,0,0,0,0};
+} voting_schedule = {0,0,0,0,0,0,0,0,0,0,0};
/** Set voting_schedule to hold the timing for the next vote we should be
* doing. */
@@ -1143,7 +1155,12 @@
dirvote_perform_vote();
voting_schedule.have_voted = 1;
}
- /* XXXX020 after a couple minutes here, start trying to fetch votes. */
+ if (voting_schedule.fetch_missing_votes < now &&
+ !voting_schedule.have_fetched_missing_votes) {
+ log_notice(LD_DIR, "Time to fetch any votes that we're missing.");
+ dirvote_fetch_missing_votes();
+ voting_schedule.have_fetched_missing_votes = 1;
+ }
if (voting_schedule.voting_ends < now &&
!voting_schedule.have_built_consensus) {
log_notice(LD_DIR, "Time to compute a consensus.");
@@ -1152,6 +1169,12 @@
* votes yet. */
voting_schedule.have_built_consensus = 1;
}
+ if (voting_schedule.fetch_missing_signatures < now &&
+ !voting_schedule.have_fetched_missing_signatures) {
+ log_notice(LD_DIR, "Time to fetch any signatures that we're missing.");
+ dirvote_fetch_missing_signatures();
+ voting_schedule.have_fetched_missing_signatures = 1;
+ }
if (voting_schedule.interval_starts < now &&
!voting_schedule.have_published_consensus) {
log_notice(LD_DIR, "Time to publish the consensus.");
@@ -1216,6 +1239,53 @@
log_notice(LD_DIR, "Vote posted.");
}
+/** DOCDOC */
+static void
+dirvote_fetch_missing_votes(void)
+{
+ smartlist_t *missing_fps = smartlist_create();
+ char *resource;
+
+ SMARTLIST_FOREACH(router_get_trusted_dir_servers(),
+ trusted_dir_server_t *, ds,
+ {
+ if ((ds->type & V3_AUTHORITY))
+ continue;
+ if (!dirvote_get_vote(ds->v3_identity_digest)) {
+ char *cp = tor_malloc(HEX_DIGEST_LEN+1);
+ base16_encode(cp, HEX_DIGEST_LEN+1, ds->v3_identity_digest,
+ DIGEST_LEN);
+ smartlist_add(missing_fps, cp);
+ }
+ });
+
+ if (!smartlist_len(missing_fps)) {
+ smartlist_free(missing_fps);
+ return;
+ }
+ log_notice(LOG_NOTICE, "We're missing votes from %d authorities. Asking "
+ "every other authority for a copy.", smartlist_len(missing_fps));
+ resource = smartlist_join_strings(missing_fps, "+", 0, NULL);
+ directory_get_from_all_authorities(DIR_PURPOSE_FETCH_STATUS_VOTE,
+ 0, resource);
+ tor_free(resource);
+ SMARTLIST_FOREACH(missing_fps, char *, cp, tor_free(cp));
+ smartlist_free(missing_fps);
+}
+
+/** DOCDOC */
+static void
+dirvote_fetch_missing_signatures(void)
+{
+ if (!pending_consensus)
+ return;
+ if (networkstatus_check_consensus_signature(pending_consensus, -1) == 1)
+ return; /* we have a signature from everybody. */
+
+ directory_get_from_all_authorities(DIR_PURPOSE_FETCH_DETACHED_SIGNATURES,
+ 0, NULL);
+}
+
/** Drop all currently pending votes, consensus, and detached signatures. */
void
dirvote_clear_pending_votes(void)
@@ -1271,6 +1341,8 @@
networkstatus_voter_info_t *vi;
trusted_dir_server_t *ds;
pending_vote_t *pending_vote = NULL;
+ const char *end_of_vote = NULL;
+ int any_failed = 0;
tor_assert(vote_body);
tor_assert(msg_out);
tor_assert(status_out);
@@ -1280,7 +1352,8 @@
pending_vote_list = smartlist_create();
*msg_out = NULL;
- vote = networkstatus_parse_vote_from_string(vote_body, 1);
+ again:
+ vote = networkstatus_parse_vote_from_string(vote_body, &end_of_vote, 1);
if (!vote) {
*msg_out = "Unable to parse vote";
goto err;
@@ -1325,7 +1398,7 @@
goto err;
}
- /* Now see whether we already have a vote from this authority.*/
+ /* Now see whether we already h<ave a vote from this authority.*/
SMARTLIST_FOREACH(pending_vote_list, pending_vote_t *, v, {
if (! memcmp(v->vote->cert->cache_info.identity_digest,
vote->cert->cache_info.identity_digest,
@@ -1359,17 +1432,29 @@
vote->published);
pending_vote->vote = vote;
smartlist_add(pending_vote_list, pending_vote);
+
+ if (end_of_vote && !strcmpstart(end_of_vote, "network-status-version "))
+ goto again;
+
+ if (any_failed)
+ goto err;
+
if (!*status_out)
*status_out = 200;
*msg_out = "ok";
+
return pending_vote;
err:
+ any_failed = 1;
if (vote)
networkstatus_vote_free(vote);
if (!*msg_out)
*msg_out = "Error adding vote";
if (!*status_out)
*status_out = 400;
+
+ if (end_of_vote && !strcmpstart(end_of_vote, "network-status-version "))
+ goto again;
return NULL;
}
@@ -1414,7 +1499,7 @@
log_warn(LD_DIR, "Couldn't generate a consensus at all!");
goto err;
}
- consensus = networkstatus_parse_vote_from_string(consensus_body, 0);
+ consensus = networkstatus_parse_vote_from_string(consensus_body, NULL, 0);
if (!consensus) {
log_warn(LD_DIR, "Couldn't parse consensus we generated!");
goto err;
@@ -1526,7 +1611,7 @@
ns_detached_signatures_t *sigs =
networkstatus_parse_detached_signatures(new_detached, NULL);
networkstatus_vote_t *v = networkstatus_parse_vote_from_string(
- pending_consensus_body, 0);
+ pending_consensus_body, NULL, 0);
tor_assert(sigs);
ns_detached_signatures_free(sigs);
tor_assert(v);
Modified: tor/trunk/src/or/or.h
===================================================================
--- tor/trunk/src/or/or.h 2007-09-22 05:46:51 UTC (rev 11574)
+++ tor/trunk/src/or/or.h 2007-09-22 06:06:05 UTC (rev 11575)
@@ -2769,6 +2769,9 @@
void directory_get_from_dirserver(uint8_t dir_purpose, uint8_t router_purpose,
const char *resource,
int retry_if_no_servers);
+void directory_get_from_all_authorities(uint8_t dir_purpose,
+ uint8_t router_purpose,
+ const char *resource);
void directory_initiate_command_routerstatus(routerstatus_t *status,
uint8_t dir_purpose,
uint8_t router_purpose,
@@ -3662,7 +3665,8 @@
networkstatus_t *networkstatus_parse_from_string(const char *s);
networkstatus_vote_t *networkstatus_parse_vote_from_string(const char *s,
- int is_vote);
+ const char **eos_out,
+ int is_vote);
ns_detached_signatures_t *networkstatus_parse_detached_signatures(
const char *s, const char *eos);
Modified: tor/trunk/src/or/routerlist.c
===================================================================
--- tor/trunk/src/or/routerlist.c 2007-09-22 05:46:51 UTC (rev 11574)
+++ tor/trunk/src/or/routerlist.c 2007-09-22 06:06:05 UTC (rev 11575)
@@ -284,8 +284,8 @@
trusted_dirs_flush_certs_to_disk();
if (consensus_waiting_for_certs) {
- if (!networkstatus_check_consensus_signature(
- consensus_waiting_for_certs, 0)) {
+ if (networkstatus_check_consensus_signature(
+ consensus_waiting_for_certs, 0)<0) {
if (!networkstatus_set_current_consensus(
consensus_waiting_for_certs_body, 0, 1)) {
tor_free(consensus_waiting_for_certs_body);
@@ -4081,7 +4081,7 @@
networkstatus_vote_t *c;
int r;
/* Make sure it's parseable. */
- c = networkstatus_parse_vote_from_string(consensus, 0);
+ c = networkstatus_parse_vote_from_string(consensus, NULL, 0);
if (!c) {
log_warn(LD_DIR, "Unable to parse networkstatus consensus");
return -1;
Modified: tor/trunk/src/or/routerparse.c
===================================================================
--- tor/trunk/src/or/routerparse.c 2007-09-22 05:46:51 UTC (rev 11574)
+++ tor/trunk/src/or/routerparse.c 2007-09-22 06:06:05 UTC (rev 11575)
@@ -1790,7 +1790,8 @@
* networkstatus consensus (if <b>is_vote</b> is false) from <b>s</b>, and
* return the result. Return NULL on failure. */
networkstatus_vote_t *
-networkstatus_parse_vote_from_string(const char *s, int is_vote)
+networkstatus_parse_vote_from_string(const char *s, const char **eos_out,
+ int is_vote)
{
smartlist_t *tokens = smartlist_create();
smartlist_t *rs_tokens = NULL, *footer_tokens = NULL;
@@ -2026,7 +2027,10 @@
/* Parse footer; check signature. */
footer_tokens = smartlist_create();
- end_of_footer = s + strlen(s);
+ if ((end_of_footer = strstr(s, "\nnetwork-status-version ")))
+ ++end_of_footer;
+ else
+ end_of_footer = s + strlen(s);
if (tokenize_string(s, end_of_footer, footer_tokens,
networkstatus_vote_footer_token_table)) {
log_warn(LD_DIR, "Error tokenizing network-status vote footer.");
@@ -2092,6 +2096,9 @@
/* XXXX020 check dates for plausibility. ??? */
+ if (eos_out)
+ *eos_out = end_of_footer;
+
goto done;
err:
if (ns)
Modified: tor/trunk/src/or/test.c
===================================================================
--- tor/trunk/src/or/test.c 2007-09-22 05:46:51 UTC (rev 11574)
+++ tor/trunk/src/or/test.c 2007-09-22 06:06:05 UTC (rev 11575)
@@ -2520,7 +2520,7 @@
/* dump the vote and try to parse it. */
v1_text = format_networkstatus_vote(sign_skey_1, vote);
test_assert(v1_text);
- v1 = networkstatus_parse_vote_from_string(v1_text, 1);
+ v1 = networkstatus_parse_vote_from_string(v1_text, NULL, 1);
test_assert(v1);
/* Make sure the parsed thing was right. */
@@ -2604,7 +2604,7 @@
/* generate and parse. */
v2_text = format_networkstatus_vote(sign_skey_2, vote);
test_assert(v2_text);
- v2 = networkstatus_parse_vote_from_string(v2_text, 1);
+ v2 = networkstatus_parse_vote_from_string(v2_text, NULL, 1);
test_assert(v2);
/* Check that flags come out right.*/
cp = smartlist_join_strings(v2->known_flags, ":", 0, NULL);
@@ -2639,7 +2639,7 @@
v3_text = format_networkstatus_vote(sign_skey_3, vote);
test_assert(v3_text);
- v3 = networkstatus_parse_vote_from_string(v3_text, 1);
+ v3 = networkstatus_parse_vote_from_string(v3_text, NULL, 1);
test_assert(v3);
/* Compute a consensus as voter 3. */
@@ -2650,7 +2650,7 @@
cert3->identity_key,
sign_skey_3);
test_assert(consensus_text);
- con = networkstatus_parse_vote_from_string(consensus_text, 0);
+ con = networkstatus_parse_vote_from_string(consensus_text, NULL, 0);
test_assert(con);
//log_notice(LD_GENERAL, "<<%s>>\n<<%s>>\n<<%s>>\n",
// v1_text, v2_text, v3_text);
@@ -2759,8 +2759,8 @@
sign_skey_1);
test_assert(consensus_text2);
test_assert(consensus_text3);
- con2 = networkstatus_parse_vote_from_string(consensus_text2, 0);
- con3 = networkstatus_parse_vote_from_string(consensus_text3, 0);
+ con2 = networkstatus_parse_vote_from_string(consensus_text2, NULL, 0);
+ con3 = networkstatus_parse_vote_from_string(consensus_text3, NULL, 0);
test_assert(con2);
test_assert(con3);