diff --git a/doc/TODO b/doc/TODO index b2daf9defd..041b4e0a8d 100644 --- a/doc/TODO +++ b/doc/TODO @@ -90,7 +90,8 @@ Things we'd like to do in 0.2.0.x: - Fix all XXXX020s in vote code . Code to generate consensus from a list of votes * Detect whether votes are really all for the same period. - - Push/pull documents as appropriate. + . Push/pull documents as appropriate. + o Serve interim votes and signatures. - Pull votes and signatures if we don't get them. o Store consensuses - Cache votes and signatures on disk. diff --git a/src/or/directory.c b/src/or/directory.c index 76e6c99ac5..0847f23fd3 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -1935,6 +1935,85 @@ directory_handle_command_get(dir_connection_t *conn, const char *headers, return 0; } + if (!strcmpstart(url,"/tor/status-vote/current/") || + !strcmpstart(url,"/tor/status-vote/next/")) { + char *url_mem = url; + size_t url_len = strlen(url); + int deflated = !strcmp(url+url_len-2, ".z"); + int current = 1; + ssize_t body_len = 0; + smartlist_t *items = smartlist_create(); + smartlist_t *dir_items = smartlist_create(); + int lifetime = 60; /* XXXX020 should actually use vote intervals. */ + if (deflated) + url[url_len-2] = '\0'; + url += strlen("/tor/status-vote/"); + current = !strcmpstart(url, "current/"); + url = strchr(url, '/'); + tor_assert(url); + ++url; + if (!strcmp(url, "consensus")) { + const char *item; + tor_assert(!current); /* we handle current consensus specially above, + * since it wants to be spooled. */ + if ((item = dirvote_get_pending_consensus())) + smartlist_add(items, (char*)item); + } else if (current && !strcmp(url, "consensus-signatures")) { + /* XXXX020 the spec says that we should implement + * currrent/consensus-signatures too. Why? */ + const char *item; + if ((item=dirvote_get_pending_detached_signatures())) + smartlist_add(items, (char*)item); + } else if (current && !strcmp(url, "authority")) { + const cached_dir_t *d; + if ((d=dirvote_get_vote(NULL))) + smartlist_add(dir_items, (cached_dir_t*)d); + } else if (current) { + const cached_dir_t *d; + smartlist_t *fps = smartlist_create(); + dir_split_resource_into_fingerprints(url, fps, NULL, 1, 1); + SMARTLIST_FOREACH(fps, char *, fp, { + if ((d = dirvote_get_vote(fp))) + smartlist_add(dir_items, (cached_dir_t*)d); + tor_free(fp); + }); + smartlist_free(fps); + } + if (!smartlist_len(dir_items) && !smartlist_len(items)) { + write_http_status_line(conn, 404, "Not found"); + tor_free(url_mem); + return 0; + } + SMARTLIST_FOREACH(items, const char *, item, + if (!deflated) + body_len += strlen(item)); + SMARTLIST_FOREACH(dir_items, cached_dir_t *, d, + body_len += deflated ? d->dir_z_len : d->dir_len); + write_http_response_header(conn, body_len ? body_len : -1, + deflated?"application/octet_stream":"text/plain", + deflated?"deflate":NULL, + lifetime); + + if (smartlist_len(items)) { + if (deflated) { + conn->zlib_state = tor_zlib_new(1, ZLIB_METHOD); + SMARTLIST_FOREACH(items, const char *, c, + connection_write_to_buf_zlib(c, strlen(c), conn, 0)); + connection_write_to_buf_zlib("", 0, conn, 1); + } else { + SMARTLIST_FOREACH(items, const char *, c, + connection_write_to_buf(c, strlen(c), TO_CONN(conn))); + } + } else { + SMARTLIST_FOREACH(dir_items, cached_dir_t *, d, + connection_write_to_buf(deflated ? d->dir_z : d->dir, + deflated ? d->dir_z_len : d->dir_len, + TO_CONN(conn))); + } + tor_free(url_mem); + return 0; + } + if (!strcmpstart(url,"/tor/server/") || !strcmpstart(url,"/tor/extra/")) { char *url_mem = url; diff --git a/src/or/dirvote.c b/src/or/dirvote.c index 5d04713754..2c88b07c9a 100644 --- a/src/or/dirvote.c +++ b/src/or/dirvote.c @@ -1096,7 +1096,6 @@ dirvote_recalculate_timing(time_t now) memset(&voting_schedule, 0, sizeof(voting_schedule)); if (consensus) { - /* XXXX020 sanity-check these somewhere! */ interval = consensus->fresh_until - consensus->valid_after; vote_delay = consensus->vote_seconds; dist_delay = consensus->dist_seconds; @@ -1605,3 +1604,40 @@ dirvote_free_all(void) } } +/* ==== + * Access to pending items. + * ==== */ + +/** DOCDOC */ +const char * +dirvote_get_pending_consensus(void) +{ + return pending_consensus_body; +} + +/** DOCDOC */ +const char * +dirvote_get_pending_detached_signatures(void) +{ + return pending_consensus_signatures; +} + +/** DOCDOC */ +const cached_dir_t * +dirvote_get_vote(const char *id) +{ + if (!pending_vote_list) + return NULL; + if (id == NULL) { + authority_cert_t *c = get_my_v3_authority_cert(); + if (c) + id = c->cache_info.identity_digest; + 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); + return NULL; +} + diff --git a/src/or/or.h b/src/or/or.h index 4d04a7f02e..a0d9b087e7 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2881,6 +2881,11 @@ int dirvote_compute_consensus(void); int dirvote_add_signatures(const char *detached_signatures_body); 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); + #ifdef DIRVOTE_PRIVATE time_t median_time(smartlist_t *times); int median_int(smartlist_t *times);