[tor-commits] [tor/maint-0.3.5] Merge branch 'ticket29806_034_squashed' into ticket29806_035_squashed_merged
teor at torproject.org
teor at torproject.org
Wed Mar 27 00:03:11 UTC 2019
commit 3adb689fbc28434efa6a3b599163b1d5b6cae3e9
Merge: 41cd05562 4ab2e9a59
Author: teor <teor at torproject.org>
Date: Thu Mar 21 12:04:30 2019 +1000
Merge branch 'ticket29806_034_squashed' into ticket29806_035_squashed_merged
Copy and paste the vote=0 code from the old src/or/dirserv.c
to the new src/feature/dirauth/bwauth.c.
changes/ticket29806 | 7 ++++++
src/feature/dirauth/bwauth.c | 8 ++++++-
src/test/test_dir.c | 57 ++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 71 insertions(+), 1 deletion(-)
diff --cc src/feature/dirauth/bwauth.c
index a31050ff9,000000000..12f9399e9
mode 100644,000000..100644
--- a/src/feature/dirauth/bwauth.c
+++ b/src/feature/dirauth/bwauth.c
@@@ -1,453 -1,0 +1,459 @@@
+/* Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2019, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+/**
+ * \file bwauth.c
+ * \brief Code to read and apply bandwidth authority data.
+ **/
+
+#define BWAUTH_PRIVATE
+#include "core/or/or.h"
+#include "feature/dirauth/bwauth.h"
+
+#include "app/config/config.h"
+#include "feature/nodelist/networkstatus.h"
+#include "feature/nodelist/routerlist.h"
+#include "feature/dirparse/ns_parse.h"
+
+#include "feature/nodelist/routerinfo_st.h"
+#include "feature/nodelist/vote_routerstatus_st.h"
+
+#include "lib/encoding/keyval.h"
+
+/** Total number of routers with measured bandwidth; this is set by
+ * dirserv_count_measured_bs() before the loop in
+ * dirserv_generate_networkstatus_vote_obj() and checked by
+ * dirserv_get_credible_bandwidth() and
+ * dirserv_compute_performance_thresholds() */
+static int routers_with_measured_bw = 0;
+
+/** Look through the routerlist, and using the measured bandwidth cache count
+ * how many measured bandwidths we know. This is used to decide whether we
+ * ever trust advertised bandwidths for purposes of assigning flags. */
+void
+dirserv_count_measured_bws(const smartlist_t *routers)
+{
+ /* Initialize this first */
+ routers_with_measured_bw = 0;
+
+ /* Iterate over the routerlist and count measured bandwidths */
+ SMARTLIST_FOREACH_BEGIN(routers, const routerinfo_t *, ri) {
+ /* Check if we know a measured bandwidth for this one */
+ if (dirserv_has_measured_bw(ri->cache_info.identity_digest)) {
+ ++routers_with_measured_bw;
+ }
+ } SMARTLIST_FOREACH_END(ri);
+}
+
+/** Return the last-computed result from dirserv_count_mesured_bws(). */
+int
+dirserv_get_last_n_measured_bws(void)
+{
+ return routers_with_measured_bw;
+}
+
+/** Measured bandwidth cache entry */
+typedef struct mbw_cache_entry_s {
+ long mbw_kb;
+ time_t as_of;
+} mbw_cache_entry_t;
+
+/** Measured bandwidth cache - keys are identity_digests, values are
+ * mbw_cache_entry_t *. */
+static digestmap_t *mbw_cache = NULL;
+
+/** Store a measured bandwidth cache entry when reading the measured
+ * bandwidths file. */
+STATIC void
+dirserv_cache_measured_bw(const measured_bw_line_t *parsed_line,
+ time_t as_of)
+{
+ mbw_cache_entry_t *e = NULL;
+
+ tor_assert(parsed_line);
+
+ /* Allocate a cache if we need */
+ if (!mbw_cache) mbw_cache = digestmap_new();
+
+ /* Check if we have an existing entry */
+ e = digestmap_get(mbw_cache, parsed_line->node_id);
+ /* If we do, we can re-use it */
+ if (e) {
+ /* Check that we really are newer, and update */
+ if (as_of > e->as_of) {
+ e->mbw_kb = parsed_line->bw_kb;
+ e->as_of = as_of;
+ }
+ } else {
+ /* We'll have to insert a new entry */
+ e = tor_malloc(sizeof(*e));
+ e->mbw_kb = parsed_line->bw_kb;
+ e->as_of = as_of;
+ digestmap_set(mbw_cache, parsed_line->node_id, e);
+ }
+}
+
+/** Clear and free the measured bandwidth cache */
+void
+dirserv_clear_measured_bw_cache(void)
+{
+ if (mbw_cache) {
+ /* Free the map and all entries */
+ digestmap_free(mbw_cache, tor_free_);
+ mbw_cache = NULL;
+ }
+}
+
+/** Scan the measured bandwidth cache and remove expired entries */
+STATIC void
+dirserv_expire_measured_bw_cache(time_t now)
+{
+
+ if (mbw_cache) {
+ /* Iterate through the cache and check each entry */
+ DIGESTMAP_FOREACH_MODIFY(mbw_cache, k, mbw_cache_entry_t *, e) {
+ if (now > e->as_of + MAX_MEASUREMENT_AGE) {
+ tor_free(e);
+ MAP_DEL_CURRENT(k);
+ }
+ } DIGESTMAP_FOREACH_END;
+
+ /* Check if we cleared the whole thing and free if so */
+ if (digestmap_size(mbw_cache) == 0) {
+ digestmap_free(mbw_cache, tor_free_);
+ mbw_cache = 0;
+ }
+ }
+}
+
+/** Query the cache by identity digest, return value indicates whether
+ * we found it. The bw_out and as_of_out pointers receive the cached
+ * bandwidth value and the time it was cached if not NULL. */
+int
+dirserv_query_measured_bw_cache_kb(const char *node_id, long *bw_kb_out,
+ time_t *as_of_out)
+{
+ mbw_cache_entry_t *v = NULL;
+ int rv = 0;
+
+ if (mbw_cache && node_id) {
+ v = digestmap_get(mbw_cache, node_id);
+ if (v) {
+ /* Found something */
+ rv = 1;
+ if (bw_kb_out) *bw_kb_out = v->mbw_kb;
+ if (as_of_out) *as_of_out = v->as_of;
+ }
+ }
+
+ return rv;
+}
+
+/** Predicate wrapper for dirserv_query_measured_bw_cache() */
+int
+dirserv_has_measured_bw(const char *node_id)
+{
+ return dirserv_query_measured_bw_cache_kb(node_id, NULL, NULL);
+}
+
+/** Get the current size of the measured bandwidth cache */
+int
+dirserv_get_measured_bw_cache_size(void)
+{
+ if (mbw_cache) return digestmap_size(mbw_cache);
+ else return 0;
+}
+
+/** Return the bandwidth we believe for assigning flags; prefer measured
+ * over advertised, and if we have above a threshold quantity of measured
+ * bandwidths, we don't want to ever give flags to unmeasured routers, so
+ * return 0. */
+uint32_t
+dirserv_get_credible_bandwidth_kb(const routerinfo_t *ri)
+{
+ int threshold;
+ uint32_t bw_kb = 0;
+ long mbw_kb;
+
+ tor_assert(ri);
+ /* Check if we have a measured bandwidth, and check the threshold if not */
+ if (!(dirserv_query_measured_bw_cache_kb(ri->cache_info.identity_digest,
+ &mbw_kb, NULL))) {
+ threshold = get_options()->MinMeasuredBWsForAuthToIgnoreAdvertised;
+ if (routers_with_measured_bw > threshold) {
+ /* Return zero for unmeasured bandwidth if we are above threshold */
+ bw_kb = 0;
+ } else {
+ /* Return an advertised bandwidth otherwise */
+ bw_kb = router_get_advertised_bandwidth_capped(ri) / 1000;
+ }
+ } else {
+ /* We have the measured bandwidth in mbw */
+ bw_kb = (uint32_t)mbw_kb;
+ }
+
+ return bw_kb;
+}
+
+/**
+ * Read the measured bandwidth list file, apply it to the list of
+ * vote_routerstatus_t and store all the headers in <b>bw_file_headers</b>.
+ * Returns -1 on error, 0 otherwise.
+ */
+int
+dirserv_read_measured_bandwidths(const char *from_file,
+ smartlist_t *routerstatuses,
+ smartlist_t *bw_file_headers)
+{
+ FILE *fp = tor_fopen_cloexec(from_file, "r");
+ int applied_lines = 0;
+ time_t file_time, now;
+ int ok;
+ /* This flag will be 1 only when the first successful bw measurement line
+ * has been encountered, so that measured_bw_line_parse don't give warnings
+ * if there are additional header lines, as introduced in Bandwidth List spec
+ * version 1.1.0 */
+ int line_is_after_headers = 0;
+ int rv = -1;
+ char *line = NULL;
+ size_t n = 0;
+
+ /* Initialise line, so that we can't possibly run off the end. */
+
+ if (fp == NULL) {
+ log_warn(LD_CONFIG, "Can't open bandwidth file at configured location: %s",
+ from_file);
+ goto err;
+ }
+
+ /* If fgets fails, line is either unmodified, or indeterminate. */
+ if (tor_getline(&line,&n,fp) <= 0) {
+ log_warn(LD_DIRSERV, "Empty bandwidth file");
+ goto err;
+ }
+
+ if (!strlen(line) || line[strlen(line)-1] != '\n') {
+ log_warn(LD_DIRSERV, "Long or truncated time in bandwidth file: %s",
+ escaped(line));
+ goto err;
+ }
+
+ line[strlen(line)-1] = '\0';
+ file_time = (time_t)tor_parse_ulong(line, 10, 0, ULONG_MAX, &ok, NULL);
+ if (!ok) {
+ log_warn(LD_DIRSERV, "Non-integer time in bandwidth file: %s",
+ escaped(line));
+ goto err;
+ }
+
+ now = time(NULL);
+ if ((now - file_time) > MAX_MEASUREMENT_AGE) {
+ log_warn(LD_DIRSERV, "Bandwidth measurement file stale. Age: %u",
+ (unsigned)(time(NULL) - file_time));
+ goto err;
+ }
+
+ /* If timestamp was correct and bw_file_headers is not NULL,
+ * add timestamp to bw_file_headers */
+ if (bw_file_headers)
+ smartlist_add_asprintf(bw_file_headers, "timestamp=%lu",
+ (unsigned long)file_time);
+
+ if (routerstatuses)
+ smartlist_sort(routerstatuses, compare_vote_routerstatus_entries);
+
+ while (!feof(fp)) {
+ measured_bw_line_t parsed_line;
+ if (tor_getline(&line, &n, fp) >= 0) {
+ if (measured_bw_line_parse(&parsed_line, line,
+ line_is_after_headers) != -1) {
+ /* This condition will be true when the first complete valid bw line
+ * has been encountered, which means the end of the header lines. */
+ line_is_after_headers = 1;
+ /* Also cache the line for dirserv_get_bandwidth_for_router() */
+ dirserv_cache_measured_bw(&parsed_line, file_time);
+ if (measured_bw_line_apply(&parsed_line, routerstatuses) > 0)
+ applied_lines++;
+ /* if the terminator is found, it is the end of header lines, set the
+ * flag but do not store anything */
+ } else if (strcmp(line, BW_FILE_HEADERS_TERMINATOR) == 0) {
+ line_is_after_headers = 1;
+ /* if the line was not a correct relay line nor the terminator and
+ * the end of the header lines has not been detected yet
+ * and it is key_value and bw_file_headers did not reach the maximum
+ * number of headers,
+ * then assume this line is a header and add it to bw_file_headers */
+ } else if (bw_file_headers &&
+ (line_is_after_headers == 0) &&
+ string_is_key_value(LOG_DEBUG, line) &&
+ !strchr(line, ' ') &&
+ (smartlist_len(bw_file_headers)
+ < MAX_BW_FILE_HEADER_COUNT_IN_VOTE)) {
+ line[strlen(line)-1] = '\0';
+ smartlist_add_strdup(bw_file_headers, line);
+ };
+ }
+ }
+
+ /* Now would be a nice time to clean the cache, too */
+ dirserv_expire_measured_bw_cache(now);
+
+ log_info(LD_DIRSERV,
+ "Bandwidth measurement file successfully read. "
+ "Applied %d measurements.", applied_lines);
+ rv = 0;
+
+ err:
+ if (line) {
+ // we need to raw_free this buffer because we got it from tor_getdelim()
+ raw_free(line);
+ }
+ if (fp)
+ fclose(fp);
+ return rv;
+}
+
+/**
+ * Helper function to parse out a line in the measured bandwidth file
+ * into a measured_bw_line_t output structure.
+ *
+ * If <b>line_is_after_headers</b> is true, then if we encounter an incomplete
+ * bw line, return -1 and warn, since we are after the headers and we should
+ * only parse bw lines. Return 0 otherwise.
+ *
+ * If <b>line_is_after_headers</b> is false then it means that we are not past
+ * the header block yet. If we encounter an incomplete bw line, return -1 but
+ * don't warn since there could be additional header lines coming. If we
+ * encounter a proper bw line, return 0 (and we got past the headers).
+ */
+STATIC int
+measured_bw_line_parse(measured_bw_line_t *out, const char *orig_line,
+ int line_is_after_headers)
+{
+ char *line = tor_strdup(orig_line);
+ char *cp = line;
+ int got_bw = 0;
+ int got_node_id = 0;
+ char *strtok_state; /* lame sauce d'jour */
+
+ if (strlen(line) == 0) {
+ log_warn(LD_DIRSERV, "Empty line in bandwidth file");
+ tor_free(line);
+ return -1;
+ }
+
+ /* Remove end of line character, so that is not part of the token */
+ if (line[strlen(line) - 1] == '\n') {
+ line[strlen(line) - 1] = '\0';
+ }
+
+ cp = tor_strtok_r(cp, " \t", &strtok_state);
+
+ if (!cp) {
+ log_warn(LD_DIRSERV, "Invalid line in bandwidth file: %s",
+ escaped(orig_line));
+ tor_free(line);
+ return -1;
+ }
+
+ if (orig_line[strlen(orig_line)-1] != '\n') {
+ log_warn(LD_DIRSERV, "Incomplete line in bandwidth file: %s",
+ escaped(orig_line));
+ tor_free(line);
+ return -1;
+ }
+
+ do {
- if (strcmpstart(cp, "bw=") == 0) {
++ // If the line contains vote=0, ignore it.
++ if (strcmpstart(cp, "vote=0") == 0) {
++ log_debug(LD_DIRSERV, "Ignoring bandwidth file line that contains "
++ "vote=0: %s",escaped(orig_line));
++ tor_free(line);
++ return -1;
++ } else if (strcmpstart(cp, "bw=") == 0) {
+ int parse_ok = 0;
+ char *endptr;
+ if (got_bw) {
+ log_warn(LD_DIRSERV, "Double bw= in bandwidth file line: %s",
+ escaped(orig_line));
+ tor_free(line);
+ return -1;
+ }
+ cp+=strlen("bw=");
+
+ out->bw_kb = tor_parse_long(cp, 10, 0, LONG_MAX, &parse_ok, &endptr);
+ if (!parse_ok || (*endptr && !TOR_ISSPACE(*endptr))) {
+ log_warn(LD_DIRSERV, "Invalid bandwidth in bandwidth file line: %s",
+ escaped(orig_line));
+ tor_free(line);
+ return -1;
+ }
+ got_bw=1;
+ } else if (strcmpstart(cp, "node_id=$") == 0) {
+ if (got_node_id) {
+ log_warn(LD_DIRSERV, "Double node_id= in bandwidth file line: %s",
+ escaped(orig_line));
+ tor_free(line);
+ return -1;
+ }
+ cp+=strlen("node_id=$");
+
+ if (strlen(cp) != HEX_DIGEST_LEN ||
+ base16_decode(out->node_id, DIGEST_LEN,
+ cp, HEX_DIGEST_LEN) != DIGEST_LEN) {
+ log_warn(LD_DIRSERV, "Invalid node_id in bandwidth file line: %s",
+ escaped(orig_line));
+ tor_free(line);
+ return -1;
+ }
+ strlcpy(out->node_hex, cp, sizeof(out->node_hex));
+ got_node_id=1;
+ }
+ } while ((cp = tor_strtok_r(NULL, " \t", &strtok_state)));
+
+ if (got_bw && got_node_id) {
+ tor_free(line);
+ return 0;
+ } else if (line_is_after_headers == 0) {
+ /* There could be additional header lines, therefore do not give warnings
+ * but returns -1 since it's not a complete bw line. */
+ log_debug(LD_DIRSERV, "Missing bw or node_id in bandwidth file line: %s",
+ escaped(orig_line));
+ tor_free(line);
+ return -1;
+ } else {
+ log_warn(LD_DIRSERV, "Incomplete line in bandwidth file: %s",
+ escaped(orig_line));
+ tor_free(line);
+ return -1;
+ }
+}
+
+/**
+ * Helper function to apply a parsed measurement line to a list
+ * of bandwidth statuses. Returns true if a line is found,
+ * false otherwise.
+ */
+STATIC int
+measured_bw_line_apply(measured_bw_line_t *parsed_line,
+ smartlist_t *routerstatuses)
+{
+ vote_routerstatus_t *rs = NULL;
+ if (!routerstatuses)
+ return 0;
+
+ rs = smartlist_bsearch(routerstatuses, parsed_line->node_id,
+ compare_digest_to_vote_routerstatus_entry);
+
+ if (rs) {
+ rs->has_measured_bw = 1;
+ rs->measured_bw_kb = (uint32_t)parsed_line->bw_kb;
+ } else {
+ log_info(LD_DIRSERV, "Node ID %s not found in routerstatus list",
+ parsed_line->node_hex);
+ }
+
+ return rs != NULL;
+}
diff --cc src/test/test_dir.c
index 9d163872d,52d3ef159..cbb414ed6
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@@ -1708,286 -1677,94 +1727,324 @@@ test_dir_dirserv_read_measured_bandwidt
"pid_error=4.11374090719 pid_error_sum=4.11374090719 "
"pid_bw=57136645 pid_delta=2.12168374577 circ_fail=0.2 "
"scanner=/filepath\n";
-
- tor_asprintf(&content, "%ld\n%s", (long)timestamp, torflow_relay_lines);
+ const char *relay_lines_v110 =
+ "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A27F80 "
+ "master_key_ed25519=YaqV4vbvPYKucElk297eVdNArDz9HtIwUoIeo0+cVIpQ "
+ "bw=760 nick=Test rtt=380 time=2018-05-08T16:13:26\n";
+ const char *relay_lines_bad =
+ "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A\n";
+
+ tor_asprintf(&header_lines_v100, "%ld\n", (long)timestamp);
+ tor_asprintf(&header_lines_v110_no_terminator, "%ld\n%s", (long)timestamp,
+ header_lines_v110_no_terminator_no_timestamp);
+ tor_asprintf(&header_lines_v110, "%s%s",
+ header_lines_v110_no_terminator, BW_FILE_HEADERS_TERMINATOR);
+
+ tor_asprintf(&bw_file_headers_str_v100, "timestamp=%ld",(long)timestamp);
+ tor_asprintf(&bw_file_headers_str_v110, "timestamp=%ld %s",
+ (long)timestamp, bw_file_headers_str_v110_no_timestamp);
+ tor_asprintf(&bw_file_headers_str_bad, "%s "
+ "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A",
+ bw_file_headers_str_v110);
+
+ for (i=0; i<MAX_BW_FILE_HEADER_COUNT_IN_VOTE; i++) {
+ strlcat(header_lines_long, "foo=bar\n",
+ sizeof(header_lines_long));
+ }
+ /* 8 is the number of v110 lines in header_lines_v110 */
+ for (i=0; i<MAX_BW_FILE_HEADER_COUNT_IN_VOTE - 8 - 1; i++) {
+ strlcat(bw_file_headers_str_long, "foo=bar ",
+ sizeof(bw_file_headers_str_long));
+ }
+ strlcat(bw_file_headers_str_long, "foo=bar",
+ sizeof(bw_file_headers_str_long));
+ tor_asprintf(&bw_file_headers_str_extra,
+ "%s %s",
+ bw_file_headers_str_v110,
+ bw_file_headers_str_long);
+
+ /* Test an empty bandwidth file. bw_file_headers will be empty string */
+ write_str_to_file(fname, "", 0);
+ setup_capture_of_logs(LOG_WARN);
+ tt_int_op(-1, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ expect_log_msg("Empty bandwidth file\n");
+ teardown_capture_of_logs();
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op("", OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test bandwidth file with only timestamp.
+ * bw_file_headers will be empty string */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%ld", (long)timestamp);
write_str_to_file(fname, content, 0);
tor_free(content);
- tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
-
- /* Test Torflow complete file including v1.1.0 headers */
- const char *v110_header_lines=
- "version=1.1.0\n"
- "software=sbws\n"
- "software_version=0.1.0\n"
- "generator_started=2018-05-08T16:13:25\n"
- "earliest_bandwidth=2018-05-08T16:13:26\n"
- "====\n";
-
- tor_asprintf(&content, "%ld\n%s%s", (long)timestamp, v110_header_lines,
- torflow_relay_lines);
+ tt_int_op(-1, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op("", OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.0.0 bandwidth file headers */
+ write_str_to_file(fname, header_lines_v100, 0);
+ bw_file_headers = smartlist_new();
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v100, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.0.0 complete bandwidth file */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s", header_lines_v100, relay_lines_v100);
write_str_to_file(fname, content, 0);
tor_free(content);
- tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
-
- /* Test Torflow with additional headers afer a correct bw line */
- tor_asprintf(&content, "%ld\n%s%s", (long)timestamp, torflow_relay_lines,
- v110_header_lines);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v100, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.0.0 complete bandwidth file with NULL bw_file_headers. */
+ tor_asprintf(&content, "%s%s", header_lines_v100, relay_lines_v100);
write_str_to_file(fname, content, 0);
tor_free(content);
- tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL, NULL));
- /* Test Torflow with additional headers afer a correct bw line and more
- * bw lines after the headers. */
- tor_asprintf(&content, "%ld\n%s%s%s", (long)timestamp, torflow_relay_lines,
- v110_header_lines, torflow_relay_lines);
+ /* Test bandwidth file including v1.1.0 bandwidth headers and
+ * v1.0.0 relay lines. bw_file_headers will contain the v1.1.0 headers. */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s%s", header_lines_v100, header_lines_v110,
+ relay_lines_v100);
write_str_to_file(fname, content, 0);
tor_free(content);
- tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
-
- /* Test sbws file */
- const char *sbws_relay_lines=
- "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A27F80 "
- "master_key_ed25519=YaqV4vbvPYKucElk297eVdNArDz9HtIwUoIeo0+cVIpQ "
- "bw=760 nick=Test rtt=380 time=2018-05-08T16:13:26\n";
-
- tor_asprintf(&content, "%ld\n%s%s", (long)timestamp, v110_header_lines,
- sbws_relay_lines);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v110, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.0.0 complete bandwidth file with v1.1.0 headers at the end.
+ * bw_file_headers will contain only v1.0.0 headers and the additional
+ * headers will be interpreted as malformed relay lines. */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s%s", header_lines_v100, relay_lines_v100,
+ header_lines_v110);
write_str_to_file(fname, content, 0);
tor_free(content);
- tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v100, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.0.0 complete bandwidth file, the v1.1.0 headers and more relay
+ * lines. bw_file_headers will contain only v1.0.0 headers, the additional
+ * headers will be interpreted as malformed relay lines and the last relay
+ * lines will be correctly interpreted as relay lines. */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s%s%s", header_lines_v100, relay_lines_v100,
+ header_lines_v110, relay_lines_v100);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v100, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.1.0 bandwidth headers without terminator */
+ bw_file_headers = smartlist_new();
+ write_str_to_file(fname, header_lines_v110_no_terminator, 0);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v110, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.1.0 bandwidth headers with terminator */
+ bw_file_headers = smartlist_new();
+ write_str_to_file(fname, header_lines_v110, 0);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v110, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.1.0 bandwidth file without terminator, then relay lines.
+ * bw_file_headers will contain the v1.1.0 headers. */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s",
+ header_lines_v110_no_terminator, relay_lines_v110);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v110, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.1.0 bandwidth headers with terminator, then relay lines
+ * bw_file_headers will contain the v1.1.0 headers. */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s",
+ header_lines_v110, relay_lines_v110);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v110, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.1.0 bandwidth headers with terminator, then bad relay lines,
+ * then terminator, then relay_lines_bad.
+ * bw_file_headers will contain the v1.1.0 headers. */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s%s%s", header_lines_v110, relay_lines_bad,
+ BW_FILE_HEADERS_TERMINATOR, relay_lines_bad);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_v110, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.1.0 bandwidth headers without terminator, then bad relay lines,
+ * then relay lines. bw_file_headers will contain the v1.1.0 headers and
+ * the bad relay lines. */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s%s",
+ header_lines_v110_no_terminator, relay_lines_bad,
+ relay_lines_v110);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_bad, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.1.0 bandwidth headers without terminator,
+ * then many bad relay lines, then relay lines.
+ * bw_file_headers will contain the v1.1.0 headers and the bad relay lines
+ * to a maximum of MAX_BW_FILE_HEADER_COUNT_IN_VOTE header lines. */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s%s",
+ header_lines_v110_no_terminator, header_lines_long,
+ relay_lines_v110);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ tt_int_op(MAX_BW_FILE_HEADER_COUNT_IN_VOTE, OP_EQ,
+ smartlist_len(bw_file_headers));
+ bw_file_headers_str = smartlist_join_strings(bw_file_headers, " ", 0, NULL);
+ tt_str_op(bw_file_headers_str_extra, OP_EQ, bw_file_headers_str);
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+
+ /* Test v1.1.0 bandwidth headers without terminator,
+ * then many bad relay lines, then relay lines.
+ * bw_file_headers will contain the v1.1.0 headers and the bad relay lines.
+ * Force bw_file_headers to have more than MAX_BW_FILE_HEADER_COUNT_IN_VOTE
+ * This test is needed while there is not dirvote test. */
+ bw_file_headers = smartlist_new();
+ tor_asprintf(&content, "%s%s%s",
+ header_lines_v110_no_terminator, header_lines_long,
+ relay_lines_v110);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL,
+ bw_file_headers));
+ tt_int_op(MAX_BW_FILE_HEADER_COUNT_IN_VOTE, OP_EQ,
+ smartlist_len(bw_file_headers));
+ /* force bw_file_headers to be bigger than
+ * MAX_BW_FILE_HEADER_COUNT_IN_VOTE */
+ char line[8] = "foo=bar\0";
+ smartlist_add_strdup(bw_file_headers, line);
+ tt_int_op(MAX_BW_FILE_HEADER_COUNT_IN_VOTE, OP_LT,
+ smartlist_len(bw_file_headers));
+ SMARTLIST_FOREACH(bw_file_headers, char *, c, tor_free(c));
+ smartlist_free(bw_file_headers);
+ tor_free(bw_file_headers_str);
+ /* Test v1.x.x bandwidth line with vote=0.
+ * It will be ignored it and logged it at debug level. */
+ const char *relay_lines_ignore =
+ "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A27F80 bw=1024 vote=0\n"
+ "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A27F80 bw=1024 vote=0"
+ "unmeasured=1\n"
+ "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A27F80 bw=1024 vote=0"
+ "unmeasured=0\n";
+
+ /* Create the bandwidth file */
+ tor_asprintf(&content, "%ld\n%s", (long)timestamp, relay_lines_ignore);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+
+ /* Read the bandwidth file */
+ setup_full_capture_of_logs(LOG_DEBUG);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
+ expect_log_msg_containing("Ignoring bandwidth file line");
+ teardown_capture_of_logs();
+
+ /* Test v1.x.x bandwidth line with "vote=1" or "unmeasured=1" or
+ * "unmeasured=0".
+ * They will not be ignored. */
+ /* Create the bandwidth file */
+ const char *relay_lines_vote =
+ "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A27F80 bw=1024 vote=1\n"
+ "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A27F80 bw=1024 unmeasured=0\n"
+ "node_id=$68A483E05A2ABDCA6DA5A3EF8DB5177638A27F80 bw=1024 unmeasured=1\n";
+ tor_asprintf(&content, "%ld\n%s", (long)timestamp, relay_lines_vote);
+ write_str_to_file(fname, content, 0);
+ tor_free(content);
+
+ /* Read the bandwidth file */
+ setup_full_capture_of_logs(LOG_DEBUG);
+ tt_int_op(0, OP_EQ, dirserv_read_measured_bandwidths(fname, NULL));
+ expect_log_msg_not_containing("Ignoring bandwidth file line");
+ teardown_capture_of_logs();
+
done:
tor_free(fname);
+ tor_free(header_lines_v100);
+ tor_free(header_lines_v110_no_terminator);
+ tor_free(header_lines_v110);
+ tor_free(bw_file_headers_str_v100);
+ tor_free(bw_file_headers_str_v110);
+ tor_free(bw_file_headers_str_bad);
+ tor_free(bw_file_headers_str_extra);
}
#define MBWC_INIT_TIME 1000
More information about the tor-commits
mailing list