mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 04:13:28 +01:00
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.
This commit is contained in:
parent
2f06345db3
commit
dcc533fb13
@ -32,6 +32,15 @@
|
|||||||
/* The valid-after time for a consensus (or for the target consensus of a
|
/* The valid-after time for a consensus (or for the target consensus of a
|
||||||
* diff), encoded as ISO UTC. */
|
* diff), encoded as ISO UTC. */
|
||||||
#define LABEL_VALID_AFTER "consensus-valid-after"
|
#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) */
|
/* A hex encoded SHA3 digest of the object, as compressed (if any) */
|
||||||
#define LABEL_SHA3_DIGEST "sha3-digest"
|
#define LABEL_SHA3_DIGEST "sha3-digest"
|
||||||
/* A hex encoded SHA3 digest of the object before compression. */
|
/* A hex encoded SHA3 digest of the object before compression. */
|
||||||
@ -1729,54 +1738,53 @@ consdiffmgr_enable_background_compression(void)
|
|||||||
background_compression = 1;
|
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
|
int
|
||||||
consensus_cache_entry_get_lifetime(const consensus_cache_entry_t *ent,
|
consensus_cache_entry_get_voter_id_digests(const consensus_cache_entry_t *ent,
|
||||||
long *lifetime)
|
smartlist_t *out)
|
||||||
{
|
{
|
||||||
tor_assert(lifetime);
|
tor_assert(ent);
|
||||||
|
tor_assert(out);
|
||||||
// FIXME(ahf): Fill out.
|
const char *s;
|
||||||
*lifetime = 0;
|
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 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Return non-zero if the cache object found in <b>ent</b> is
|
/** Read the fresh-until time of cached object <b>ent</b> into *<b>out</b>
|
||||||
* reasonably live, otherwise return 0. Use <b>now</b> to pass the
|
* and return 0, or return -1 if no such time was recorded. */
|
||||||
* timestamp used for comparison. */
|
|
||||||
int
|
int
|
||||||
consensus_cache_entry_is_reasonably_live(const consensus_cache_entry_t *ent,
|
consensus_cache_entry_get_fresh_until(const consensus_cache_entry_t *ent,
|
||||||
time_t now)
|
time_t *out)
|
||||||
{
|
{
|
||||||
// FIXME(ahf): Fill out.
|
tor_assert(ent);
|
||||||
(void)now;
|
tor_assert(out);
|
||||||
|
const char *s;
|
||||||
return 1;
|
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 set of voters 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
|
int
|
||||||
consensus_cache_entry_get_voters(const consensus_cache_entry_t *ent,
|
consensus_cache_entry_get_valid_until(const consensus_cache_entry_t *ent,
|
||||||
smartlist_t *out)
|
time_t *out)
|
||||||
{
|
|
||||||
// FIXME(ahf): Fill out.
|
|
||||||
(void)out;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Read the valid until timestamp from the cached object <b>ent</b>
|
|
||||||
* into <b>out</b>. */
|
|
||||||
int
|
|
||||||
consensus_cache_entry_valid_until(const consensus_cache_entry_t *ent,
|
|
||||||
time_t *out)
|
|
||||||
{
|
{
|
||||||
|
tor_assert(ent);
|
||||||
tor_assert(out);
|
tor_assert(out);
|
||||||
|
|
||||||
// FIXME(ahf): Fill out.
|
const char *s;
|
||||||
*out = time(NULL);
|
s = consensus_cache_entry_get_value(ent, LABEL_VALID_UNTIL);
|
||||||
|
if (s == NULL || parse_iso_time_nospace(s, out) < 0)
|
||||||
return 0;
|
return -1;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -36,16 +36,13 @@ consdiff_status_t consdiffmgr_find_diff_from(
|
|||||||
size_t digestlen,
|
size_t digestlen,
|
||||||
compress_method_t method);
|
compress_method_t method);
|
||||||
|
|
||||||
int consensus_cache_entry_get_lifetime(
|
int consensus_cache_entry_get_voter_id_digests(
|
||||||
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(
|
|
||||||
const struct consensus_cache_entry_t *ent,
|
const struct consensus_cache_entry_t *ent,
|
||||||
smartlist_t *out);
|
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,
|
const struct consensus_cache_entry_t *ent,
|
||||||
time_t *out);
|
time_t *out);
|
||||||
|
|
||||||
|
@ -3382,47 +3382,35 @@ int
|
|||||||
client_likes_consensus(const struct consensus_cache_entry_t *ent,
|
client_likes_consensus(const struct consensus_cache_entry_t *ent,
|
||||||
const char *want_url)
|
const char *want_url)
|
||||||
{
|
{
|
||||||
smartlist_t *want_authorities = smartlist_new();
|
|
||||||
smartlist_t *voters = smartlist_new();
|
smartlist_t *voters = smartlist_new();
|
||||||
int need_at_least;
|
int need_at_least;
|
||||||
int have = 0;
|
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);
|
dir_split_resource_into_fingerprints(want_url, want_authorities, NULL, 0);
|
||||||
need_at_least = smartlist_len(want_authorities)/2+1;
|
need_at_least = smartlist_len(want_authorities)/2+1;
|
||||||
|
|
||||||
if (consensus_cache_entry_get_voters(ent, voters) != 0)
|
SMARTLIST_FOREACH_BEGIN(want_authorities, const char *, want_digest) {
|
||||||
goto done;
|
|
||||||
|
|
||||||
SMARTLIST_FOREACH_BEGIN(want_authorities, const char *, d) {
|
SMARTLIST_FOREACH_BEGIN(voters, const char *, digest) {
|
||||||
char want_digest[DIGEST_LEN];
|
if (!strcasecmpstart(digest, want_digest)) {
|
||||||
size_t want_len = strlen(d)/2;
|
|
||||||
if (want_len > DIGEST_LEN)
|
|
||||||
want_len = DIGEST_LEN;
|
|
||||||
|
|
||||||
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)) {
|
|
||||||
have++;
|
have++;
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
} SMARTLIST_FOREACH_END(vi);
|
} SMARTLIST_FOREACH_END(digest);
|
||||||
|
|
||||||
/* early exit, if we already have enough */
|
/* early exit, if we already have enough */
|
||||||
if (have >= need_at_least)
|
if (have >= need_at_least)
|
||||||
break;
|
break;
|
||||||
} SMARTLIST_FOREACH_END(d);
|
} SMARTLIST_FOREACH_END(want_digest);
|
||||||
|
|
||||||
done:
|
|
||||||
SMARTLIST_FOREACH(want_authorities, char *, d, tor_free(d));
|
SMARTLIST_FOREACH(want_authorities, char *, d, tor_free(d));
|
||||||
smartlist_free(want_authorities);
|
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);
|
smartlist_free(voters);
|
||||||
return (have >= need_at_least);
|
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;
|
time_t valid_until;
|
||||||
char *dupes;
|
char *dupes;
|
||||||
|
|
||||||
if (consensus_cache_entry_valid_until(cached_consensus, &valid_until))
|
if (consensus_cache_entry_get_valid_until(cached_consensus, &valid_until))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if ((dupes = rate_limit_log(&warned, now))) {
|
if ((dupes = rate_limit_log(&warned, now))) {
|
||||||
@ -3832,9 +3820,17 @@ handle_get_current_consensus(dir_connection_t *conn,
|
|||||||
args->compression_supported,
|
args->compression_supported,
|
||||||
&compression_used);
|
&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 &&
|
if (cached_consensus && have_valid_until &&
|
||||||
!consensus_cache_entry_is_reasonably_live(cached_consensus, now)) {
|
!networkstatus_valid_until_is_reasonably_live(valid_until, now)) {
|
||||||
write_http_status_line(conn, 404, "Consensus is too old");
|
write_http_status_line(conn, 404, "Consensus is too old");
|
||||||
warn_consensus_is_too_old(cached_consensus, flavor, now);
|
warn_consensus_is_too_old(cached_consensus, flavor, now);
|
||||||
geoip_note_ns_response(GEOIP_REJECT_NOT_FOUND);
|
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);
|
smartlist_add(conn->spool, spooled);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (cached_consensus &&
|
lifetime = (have_fresh_until && fresh_until > now) ? fresh_until - now : 0;
|
||||||
consensus_cache_entry_get_lifetime(cached_consensus,
|
|
||||||
&lifetime) != 0) {
|
|
||||||
lifetime = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!smartlist_len(conn->spool)) { /* we failed to create/cache cp */
|
if (!smartlist_len(conn->spool)) { /* we failed to create/cache cp */
|
||||||
write_http_status_line(conn, 503, "Network status object unavailable");
|
write_http_status_line(conn, 503, "Network status object unavailable");
|
||||||
|
@ -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.
|
* Return 1 if the consensus is reasonably live, or 0 if it is too old.
|
||||||
*/
|
*/
|
||||||
int
|
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))
|
if (BUG(!consensus))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (now <= consensus->valid_until + REASONABLY_LIVE_TIME)
|
return networkstatus_valid_until_is_reasonably_live(consensus->valid_until,
|
||||||
return 1;
|
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,
|
/* XXXX remove this in favor of get_live_consensus. But actually,
|
||||||
|
@ -81,8 +81,10 @@ MOCK_DECL(networkstatus_t *,networkstatus_get_latest_consensus,(void));
|
|||||||
MOCK_DECL(networkstatus_t *,networkstatus_get_latest_consensus_by_flavor,
|
MOCK_DECL(networkstatus_t *,networkstatus_get_latest_consensus_by_flavor,
|
||||||
(consensus_flavor_t f));
|
(consensus_flavor_t f));
|
||||||
MOCK_DECL(networkstatus_t *, networkstatus_get_live_consensus,(time_t now));
|
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);
|
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,
|
networkstatus_t *networkstatus_get_reasonably_live_consensus(time_t now,
|
||||||
int flavor);
|
int flavor);
|
||||||
MOCK_DECL(int, networkstatus_consensus_is_bootstrapping,(time_t now));
|
MOCK_DECL(int, networkstatus_consensus_is_bootstrapping,(time_t now));
|
||||||
|
Loading…
Reference in New Issue
Block a user