commit dcc533fb133646d81c2fa6632d6fb7f05f99f650 Author: Nick Mathewson nickm@torproject.org Date: Sun May 14 19:43:41 2017 -0400
Implement functions to expose valid/fresh-until and voters
These still won't do anything till I get the values to be filled in.
Also, I changed the API a little (with corresponding changes in directory.c) to match things that it's easier to store. --- src/or/consdiffmgr.c | 80 +++++++++++++++++++++++++++----------------------- src/or/consdiffmgr.h | 13 ++++---- src/or/directory.c | 54 +++++++++++++++------------------- src/or/networkstatus.c | 18 ++++++++---- src/or/networkstatus.h | 4 ++- 5 files changed, 88 insertions(+), 81 deletions(-)
diff --git a/src/or/consdiffmgr.c b/src/or/consdiffmgr.c index c208865..d117acd 100644 --- a/src/or/consdiffmgr.c +++ b/src/or/consdiffmgr.c @@ -32,6 +32,15 @@ /* The valid-after time for a consensus (or for the target consensus of a * diff), encoded as ISO UTC. */ #define LABEL_VALID_AFTER "consensus-valid-after" +/* The fresh-until time for a consensus (or for the target consensus of a + * diff), encoded as ISO UTC. */ +#define LABEL_FRESH_UNTIL "consensus-fresh-until" +/* The valid-until time for a consensus (or for the target consensus of a + * diff), encoded as ISO UTC. */ +#define LABEL_VALID_UNTIL "consensus-valid-until" +/* Comma-separated list of hex-encoded identity digests for the voting + * authorities. */ +#define LABEL_SIGNATORIES "consensus-signatories" /* A hex encoded SHA3 digest of the object, as compressed (if any) */ #define LABEL_SHA3_DIGEST "sha3-digest" /* A hex encoded SHA3 digest of the object before compression. */ @@ -1729,54 +1738,53 @@ consdiffmgr_enable_background_compression(void) background_compression = 1; }
-/** Read the lifetime of cached object <b>ent</b> into <b>lifetime</b>. */ +/** Read the set of voters from the cached object <b>ent</b> into + * <b>out</b>, as a list of hex-encoded digests. Return 0 on success, + * -1 if no signatories were recorded. */ int -consensus_cache_entry_get_lifetime(const consensus_cache_entry_t *ent, - long *lifetime) +consensus_cache_entry_get_voter_id_digests(const consensus_cache_entry_t *ent, + smartlist_t *out) { - tor_assert(lifetime); - - // FIXME(ahf): Fill out. - *lifetime = 0; - + tor_assert(ent); + tor_assert(out); + const char *s; + s = consensus_cache_entry_get_value(ent, LABEL_SIGNATORIES); + if (s == NULL) + return -1; + smartlist_split_string(out, s, ",", SPLIT_SKIP_SPACE|SPLIT_STRIP_SPACE, 0); return 0; }
-/** Return non-zero if the cache object found in <b>ent</b> is - * reasonably live, otherwise return 0. Use <b>now</b> to pass the - * timestamp used for comparison. */ -int -consensus_cache_entry_is_reasonably_live(const consensus_cache_entry_t *ent, - time_t now) -{ - // FIXME(ahf): Fill out. - (void)now; - - return 1; -} - -/** Read the set of voters from the cached object <b>ent</b> into <b>out</b>. */ +/** Read the fresh-until time of cached object <b>ent</b> into *<b>out</b> + * and return 0, or return -1 if no such time was recorded. */ int -consensus_cache_entry_get_voters(const consensus_cache_entry_t *ent, - smartlist_t *out) +consensus_cache_entry_get_fresh_until(const consensus_cache_entry_t *ent, + time_t *out) { - // FIXME(ahf): Fill out. - (void)out; - - return 0; + tor_assert(ent); + tor_assert(out); + const char *s; + s = consensus_cache_entry_get_value(ent, LABEL_FRESH_UNTIL); + if (s == NULL || parse_iso_time_nospace(s, out) < 0) + return -1; + else + return 0; }
-/** Read the valid until timestamp from the cached object <b>ent</b> - * into <b>out</b>. */ +/** Read the valid until timestamp from the cached object <b>ent</b> into + * *<b>out</b> and return 0, or return -1 if no such time was recorded. */ int -consensus_cache_entry_valid_until(const consensus_cache_entry_t *ent, - time_t *out) +consensus_cache_entry_get_valid_until(const consensus_cache_entry_t *ent, + time_t *out) { + tor_assert(ent); tor_assert(out);
- // FIXME(ahf): Fill out. - *out = time(NULL); - - return 0; + const char *s; + s = consensus_cache_entry_get_value(ent, LABEL_VALID_UNTIL); + if (s == NULL || parse_iso_time_nospace(s, out) < 0) + return -1; + else + return 0; }
diff --git a/src/or/consdiffmgr.h b/src/or/consdiffmgr.h index a8111dd..0325a00 100644 --- a/src/or/consdiffmgr.h +++ b/src/or/consdiffmgr.h @@ -36,16 +36,13 @@ consdiff_status_t consdiffmgr_find_diff_from( size_t digestlen, compress_method_t method);
-int consensus_cache_entry_get_lifetime( - const struct consensus_cache_entry_t *ent, - long *lifetime); -int consensus_cache_entry_is_reasonably_live( - const struct consensus_cache_entry_t *ent, - time_t now); -int consensus_cache_entry_get_voters( +int consensus_cache_entry_get_voter_id_digests( const struct consensus_cache_entry_t *ent, smartlist_t *out); -int consensus_cache_entry_valid_until( +int consensus_cache_entry_get_fresh_until( + const struct consensus_cache_entry_t *ent, + time_t *out); +int consensus_cache_entry_get_valid_until( const struct consensus_cache_entry_t *ent, time_t *out);
diff --git a/src/or/directory.c b/src/or/directory.c index 946792b..4fa4b3c 100644 --- a/src/or/directory.c +++ b/src/or/directory.c @@ -3382,47 +3382,35 @@ int client_likes_consensus(const struct consensus_cache_entry_t *ent, const char *want_url) { - smartlist_t *want_authorities = smartlist_new(); smartlist_t *voters = smartlist_new(); int need_at_least; int have = 0;
+ if (consensus_cache_entry_get_voter_id_digests(ent, voters) != 0) { + return 1; // We don't know the voters; assume the client won't mind. */ + } + + smartlist_t *want_authorities = smartlist_new(); dir_split_resource_into_fingerprints(want_url, want_authorities, NULL, 0); need_at_least = smartlist_len(want_authorities)/2+1;
- if (consensus_cache_entry_get_voters(ent, voters) != 0) - goto done; - - SMARTLIST_FOREACH_BEGIN(want_authorities, const char *, d) { - char want_digest[DIGEST_LEN]; - size_t want_len = strlen(d)/2; - if (want_len > DIGEST_LEN) - want_len = DIGEST_LEN; + SMARTLIST_FOREACH_BEGIN(want_authorities, const char *, want_digest) {
- if (base16_decode(want_digest, DIGEST_LEN, d, want_len*2) - != (int) want_len) { - log_fn(LOG_PROTOCOL_WARN, LD_DIR, - "Failed to decode requested authority digest %s.", escaped(d)); - continue; - }; - - SMARTLIST_FOREACH_BEGIN(voters, networkstatus_voter_info_t *, vi) { - if (smartlist_len(vi->sigs) && - tor_memeq(vi->identity_digest, want_digest, want_len)) { + SMARTLIST_FOREACH_BEGIN(voters, const char *, digest) { + if (!strcasecmpstart(digest, want_digest)) { have++; break; }; - } SMARTLIST_FOREACH_END(vi); + } SMARTLIST_FOREACH_END(digest);
/* early exit, if we already have enough */ if (have >= need_at_least) break; - } SMARTLIST_FOREACH_END(d); + } SMARTLIST_FOREACH_END(want_digest);
- done: SMARTLIST_FOREACH(want_authorities, char *, d, tor_free(d)); smartlist_free(want_authorities); - SMARTLIST_FOREACH(voters, networkstatus_voter_info_t *, v, tor_free(v)); + SMARTLIST_FOREACH(voters, char *, cp, tor_free(cp)); smartlist_free(voters); return (have >= need_at_least); } @@ -3644,7 +3632,7 @@ warn_consensus_is_too_old(const struct consensus_cache_entry_t *cached_consensus time_t valid_until; char *dupes;
- if (consensus_cache_entry_valid_until(cached_consensus, &valid_until)) + if (consensus_cache_entry_get_valid_until(cached_consensus, &valid_until)) return;
if ((dupes = rate_limit_log(&warned, now))) { @@ -3832,9 +3820,17 @@ handle_get_current_consensus(dir_connection_t *conn, args->compression_supported, &compression_used); } + time_t fresh_until, valid_until; + int have_fresh_until = 0, have_valid_until = 0; + if (cached_consensus) { + have_fresh_until = + !consensus_cache_entry_get_fresh_until(cached_consensus, &fresh_until); + have_valid_until = + !consensus_cache_entry_get_valid_until(cached_consensus, &valid_until); + }
- if (cached_consensus && - !consensus_cache_entry_is_reasonably_live(cached_consensus, now)) { + if (cached_consensus && have_valid_until && + !networkstatus_valid_until_is_reasonably_live(valid_until, now)) { write_http_status_line(conn, 404, "Consensus is too old"); warn_consensus_is_too_old(cached_consensus, flavor, now); geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND); @@ -3870,11 +3866,7 @@ handle_get_current_consensus(dir_connection_t *conn, smartlist_add(conn->spool, spooled); }
- if (cached_consensus && - consensus_cache_entry_get_lifetime(cached_consensus, - &lifetime) != 0) { - lifetime = 0; - } + lifetime = (have_fresh_until && fresh_until > now) ? fresh_until - now : 0;
if (!smartlist_len(conn->spool)) { /* we failed to create/cache cp */ write_http_status_line(conn, 503, "Network status object unavailable"); diff --git a/src/or/networkstatus.c b/src/or/networkstatus.c index bd106fd..fffd107 100644 --- a/src/or/networkstatus.c +++ b/src/or/networkstatus.c @@ -1407,16 +1407,24 @@ networkstatus_get_live_consensus,(time_t now)) * Return 1 if the consensus is reasonably live, or 0 if it is too old. */ int -networkstatus_consensus_reasonably_live(networkstatus_t *consensus, time_t now) +networkstatus_consensus_reasonably_live(const networkstatus_t *consensus, + time_t now) { -#define REASONABLY_LIVE_TIME (24*60*60) if (BUG(!consensus)) return 0;
- if (now <= consensus->valid_until + REASONABLY_LIVE_TIME) - return 1; + return networkstatus_valid_until_is_reasonably_live(consensus->valid_until, + now); +}
- return 0; +/** As networkstatus_consensus_reasonably_live, but takes a valid_until + * time rather than an entire consensus. */ +int +networkstatus_valid_until_is_reasonably_live(time_t valid_until, + time_t now) +{ +#define REASONABLY_LIVE_TIME (24*60*60) + return (now <= valid_until + REASONABLY_LIVE_TIME); }
/* XXXX remove this in favor of get_live_consensus. But actually, diff --git a/src/or/networkstatus.h b/src/or/networkstatus.h index 37a5a3b..e774c4d 100644 --- a/src/or/networkstatus.h +++ b/src/or/networkstatus.h @@ -81,8 +81,10 @@ MOCK_DECL(networkstatus_t *,networkstatus_get_latest_consensus,(void)); MOCK_DECL(networkstatus_t *,networkstatus_get_latest_consensus_by_flavor, (consensus_flavor_t f)); MOCK_DECL(networkstatus_t *, networkstatus_get_live_consensus,(time_t now)); -int networkstatus_consensus_reasonably_live(networkstatus_t *consensus, +int networkstatus_consensus_reasonably_live(const networkstatus_t *consensus, time_t now); +int networkstatus_valid_until_is_reasonably_live(time_t valid_until, + time_t now); networkstatus_t *networkstatus_get_reasonably_live_consensus(time_t now, int flavor); MOCK_DECL(int, networkstatus_consensus_is_bootstrapping,(time_t now));