[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