[tor-commits] [tor/master] Merge remote branch 'origin/maint-0.2.2'

nickm at torproject.org nickm at torproject.org
Mon Mar 14 19:31:06 UTC 2011


commit f1c365b032e058e7342b632006435ecc175475a3
Merge: d52a99d b639add
Author: Nick Mathewson <nickm at torproject.org>
Date:   Mon Mar 14 15:31:24 2011 -0400

    Merge remote branch 'origin/maint-0.2.2'
    
    Fix trivial add/add conflict in main.c
    
    Conflicts:
    	src/or/main.c

 changes/bug2716  |    5 +++++
 src/or/dirserv.c |   22 ++++++++++++++++------
 src/or/dirserv.h |   12 ++++++++++++
 src/or/main.c    |    7 +++++--
 4 files changed, 38 insertions(+), 8 deletions(-)

diff --combined src/or/dirserv.c
index cbf8c36,18abd18..1796c28
--- a/src/or/dirserv.c
+++ b/src/or/dirserv.c
@@@ -16,7 -16,6 +16,7 @@@
  #include "hibernate.h"
  #include "microdesc.h"
  #include "networkstatus.h"
 +#include "nodelist.h"
  #include "policies.h"
  #include "rephist.h"
  #include "router.h"
@@@ -68,6 -67,8 +68,6 @@@ static char *format_versions_list(confi
  struct authdir_config_t;
  static int add_fingerprint_to_dir(const char *nickname, const char *fp,
                                    struct authdir_config_t *list);
 -static uint32_t dirserv_router_get_status(const routerinfo_t *router,
 -                                          const char **msg);
  static uint32_t
  dirserv_get_status_impl(const char *fp, const char *nickname,
                          const char *address,
@@@ -75,8 -76,7 +75,8 @@@
                          const char *platform, const char *contact,
                          const char **msg, int should_log);
  static void clear_cached_dir(cached_dir_t *d);
 -static signed_descriptor_t *get_signed_descriptor_by_fp(const char *fp,
 +static const signed_descriptor_t *get_signed_descriptor_by_fp(
 +                                                        const char *fp,
                                                          int extrainfo,
                                                          time_t publish_cutoff);
  static int dirserv_add_extrainfo(extrainfo_t *ei, const char **msg);
@@@ -305,7 -305,7 +305,7 @@@ dirserv_load_fingerprint_file(void
   *
   * If the status is 'FP_REJECT' and <b>msg</b> is provided, set
   * *<b>msg</b> to an explanation of why. */
 -static uint32_t
 +uint32_t
  dirserv_router_get_status(const routerinfo_t *router, const char **msg)
  {
    char d[DIGEST_LEN];
@@@ -327,7 -327,7 +327,7 @@@
  /** Return true if there is no point in downloading the router described by
   * <b>rs</b> because this directory would reject it. */
  int
 -dirserv_would_reject_router(routerstatus_t *rs)
 +dirserv_would_reject_router(const routerstatus_t *rs)
  {
    uint32_t res;
  
@@@ -362,7 -362,7 +362,7 @@@ dirserv_get_name_status(const char *id_
    return 0;
  }
  
 -/** Helper: As dirserv_get_router_status, but takes the router fingerprint
 +/** Helper: As dirserv_router_get_status, but takes the router fingerprint
   * (hex, no spaces), nickname, address (used for logging only), IP address, OR
   * port, platform (logging only) and contact info (logging only) as arguments.
   *
@@@ -377,7 -377,7 +377,7 @@@ dirserv_get_status_impl(const char *id_
                          const char **msg, int should_log)
  {
    int reject_unlisted = get_options()->AuthDirRejectUnlisted;
 -  uint32_t result = 0;
 +  uint32_t result;
    router_status_t *status_by_digest;
  
    if (!fingerprint_list)
@@@ -541,7 -541,7 +541,7 @@@ dirserv_router_has_valid_address(router
   */
  int
  authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
 -                               int complain)
 +                               int complain, int *valid_out)
  {
    /* Okay.  Now check whether the fingerprint is recognized. */
    uint32_t status = dirserv_router_get_status(ri, msg);
@@@ -582,24 -582,15 +582,24 @@@
      *msg = "Rejected: Address is not an IP, or IP is a private address.";
      return -1;
    }
 -  /* Okay, looks like we're willing to accept this one. */
 -  ri->is_named = (status & FP_NAMED) ? 1 : 0;
 -  ri->is_valid = (status & FP_INVALID) ? 0 : 1;
 -  ri->is_bad_directory = (status & FP_BADDIR) ? 1 : 0;
 -  ri->is_bad_exit = (status & FP_BADEXIT) ? 1 : 0;
 +
 +  *valid_out = ! (status & FP_INVALID);
  
    return 0;
  }
  
 +/** Update the relevant flags of <b>node</b> based on our opinion as a
 + * directory authority in <b>authstatus</b>, as returned by
 + * dirserv_router_get_status or equivalent.  */
 +void
 +dirserv_set_node_flags_from_authoritative_status(node_t *node,
 +                                                 uint32_t authstatus)
 +{
 +  node->is_valid = (authstatus & FP_INVALID) ? 0 : 1;
 +  node->is_bad_directory = (authstatus & FP_BADDIR) ? 1 : 0;
 +  node->is_bad_exit = (authstatus & FP_BADEXIT) ? 1 : 0;
 +}
 +
  /** True iff <b>a</b> is more severe than <b>b</b>. */
  static int
  WRA_MORE_SEVERE(was_router_added_t a, was_router_added_t b)
@@@ -724,7 -715,7 +724,7 @@@ dirserv_add_descriptor(routerinfo_t *ri
     * from this server.  (We do this here and not in router_add_to_routerlist
     * because we want to be able to accept the newest router descriptor that
     * another authority has, so we all converge on the same one.) */
 -  ri_old = router_get_by_digest(ri->cache_info.identity_digest);
 +  ri_old = router_get_mutable_by_digest(ri->cache_info.identity_digest);
    if (ri_old && ri_old->cache_info.published_on < ri->cache_info.published_on
        && router_differences_are_cosmetic(ri_old, ri)
        && !router_is_me(ri)) {
@@@ -768,7 -759,8 +768,7 @@@
      routerlist_descriptors_added(changed, 0);
      smartlist_free(changed);
      if (!*msg) {
 -      *msg =  ri->is_valid ? "Descriptor for valid server accepted" :
 -        "Descriptor for invalid server accepted";
 +      *msg =  "Descriptor accepted";
      }
      log_info(LD_DIRSERV,
               "Added descriptor from '%s' (source: %s): %s.",
@@@ -783,12 -775,12 +783,12 @@@
  static was_router_added_t
  dirserv_add_extrainfo(extrainfo_t *ei, const char **msg)
  {
 -  routerinfo_t *ri;
 +  const routerinfo_t *ri;
    int r;
    tor_assert(msg);
    *msg = NULL;
  
 -  ri = router_get_by_digest(ei->cache_info.identity_digest);
 +  ri = router_get_by_id_digest(ei->cache_info.identity_digest);
    if (!ri) {
      *msg = "No corresponding router descriptor for extra-info descriptor";
      extrainfo_free(ei);
@@@ -823,65 -815,54 +823,65 @@@
  static void
  directory_remove_invalid(void)
  {
 -  int i;
    int changed = 0;
    routerlist_t *rl = router_get_routerlist();
 +  smartlist_t *nodes = smartlist_create();
 +  smartlist_add_all(nodes, nodelist_get_list());
  
 -  routerlist_assert_ok(rl);
 -
 -  for (i = 0; i < smartlist_len(rl->routers); ++i) {
 +  SMARTLIST_FOREACH_BEGIN(nodes, node_t *, node) {
      const char *msg;
 -    routerinfo_t *ent = smartlist_get(rl->routers, i);
 -    uint32_t r = dirserv_router_get_status(ent, &msg);
 +    routerinfo_t *ent = node->ri;
 +    uint32_t r;
 +    if (!ent)
 +      continue;
 +    r = dirserv_router_get_status(ent, &msg);
      if (r & FP_REJECT) {
        log_info(LD_DIRSERV, "Router '%s' is now rejected: %s",
                 ent->nickname, msg?msg:"");
        routerlist_remove(rl, ent, 0, time(NULL));
        changed = 1;
        continue;
      }
 -    if (bool_neq((r & FP_NAMED), ent->is_named)) {
 +#if 0
 +    if (bool_neq((r & FP_NAMED), ent->auth_says_is_named)) {
        log_info(LD_DIRSERV,
                 "Router '%s' is now %snamed.", ent->nickname,
                 (r&FP_NAMED)?"":"un");
        ent->is_named = (r&FP_NAMED)?1:0;
        changed = 1;
      }
 -    if (bool_neq((r & FP_INVALID), !ent->is_valid)) {
 +    if (bool_neq((r & FP_UNNAMED), ent->auth_says_is_unnamed)) {
 +      log_info(LD_DIRSERV,
 +               "Router '%s' is now %snamed. (FP_UNNAMED)", ent->nickname,
 +               (r&FP_NAMED)?"":"un");
 +      ent->is_named = (r&FP_NUNAMED)?0:1;
 +      changed = 1;
 +    }
 +#endif
 +    if (bool_neq((r & FP_INVALID), !node->is_valid)) {
        log_info(LD_DIRSERV, "Router '%s' is now %svalid.", ent->nickname,
                 (r&FP_INVALID) ? "in" : "");
 -      ent->is_valid = (r&FP_INVALID)?0:1;
 +      node->is_valid = (r&FP_INVALID)?0:1;
        changed = 1;
      }
 -    if (bool_neq((r & FP_BADDIR), ent->is_bad_directory)) {
 +    if (bool_neq((r & FP_BADDIR), node->is_bad_directory)) {
        log_info(LD_DIRSERV, "Router '%s' is now a %s directory", ent->nickname,
                 (r & FP_BADDIR) ? "bad" : "good");
 -      ent->is_bad_directory = (r&FP_BADDIR) ? 1: 0;
 +      node->is_bad_directory = (r&FP_BADDIR) ? 1: 0;
        changed = 1;
      }
 -    if (bool_neq((r & FP_BADEXIT), ent->is_bad_exit)) {
 +    if (bool_neq((r & FP_BADEXIT), node->is_bad_exit)) {
        log_info(LD_DIRSERV, "Router '%s' is now a %s exit", ent->nickname,
                 (r & FP_BADEXIT) ? "bad" : "good");
 -      ent->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
 +      node->is_bad_exit = (r&FP_BADEXIT) ? 1: 0;
        changed = 1;
      }
 -  }
 +  } SMARTLIST_FOREACH_END(node);
    if (changed)
      directory_set_dirty();
  
    routerlist_assert_ok(rl);
 +  smartlist_free(nodes);
  }
  
  /** Mark the directory as <b>dirty</b> -- when we're next asked for a
@@@ -920,11 -901,10 +920,11 @@@ directory_set_dirty(void
   * as running iff <b>is_live</b> is true.
   */
  static char *
 -list_single_server_status(routerinfo_t *desc, int is_live)
 +list_single_server_status(const routerinfo_t *desc, int is_live)
  {
    char buf[MAX_NICKNAME_LEN+HEX_DIGEST_LEN+4]; /* !nickname=$hexdigest\0 */
    char *cp;
 +  const node_t *node;
  
    tor_assert(desc);
  
@@@ -932,8 -912,7 +932,8 @@@
    if (!is_live) {
      *cp++ = '!';
    }
 -  if (desc->is_valid) {
 +  node = node_get_by_id(desc->cache_info.identity_digest);
 +  if (node && node->is_valid) {
      strlcpy(cp, desc->nickname, sizeof(buf)-(cp-buf));
      cp += strlen(cp);
      *cp++ = '=';
@@@ -972,8 -951,6 +972,8 @@@ dirserv_set_router_is_running(routerinf
      unreachable.
     */
    int answer;
 +  node_t *node = node_get_mutable_by_id(router->cache_info.identity_digest);
 +  tor_assert(node);
  
    if (router_is_me(router)) {
      /* We always know if we are down ourselves. */
@@@ -994,11 -971,21 +994,21 @@@
    }
  
    if (!answer && running_long_enough_to_decide_unreachable()) {
-     /* not considered reachable. tell rephist. */
-     rep_hist_note_router_unreachable(router->cache_info.identity_digest, now);
+     /* Not considered reachable. tell rephist about that.
+ 
+        Because we launch a reachability test for each router every
+        REACHABILITY_TEST_CYCLE_PERIOD seconds, then the router has probably
+        been down since at least that time after we last successfully reached
+        it.
+      */
+     time_t when = now;
+     if (router->last_reachable &&
+         router->last_reachable + REACHABILITY_TEST_CYCLE_PERIOD < now)
+       when = router->last_reachable + REACHABILITY_TEST_CYCLE_PERIOD;
+     rep_hist_note_router_unreachable(router->cache_info.identity_digest, when);
    }
  
 -  router->is_running = answer;
 +  node->is_running = answer;
  }
  
  /** Based on the routerinfo_ts in <b>routers</b>, allocate the
@@@ -1026,8 -1013,6 +1036,8 @@@ list_server_status_v1(smartlist_t *rout
    rs_entries = smartlist_create();
  
    SMARTLIST_FOREACH_BEGIN(routers, routerinfo_t *, ri) {
 +    const node_t *node = node_get_by_id(ri->cache_info.identity_digest);
 +    tor_assert(node);
      if (authdir) {
        /* Update router status in routerinfo_t. */
        dirserv_set_router_is_running(ri, now);
@@@ -1035,13 -1020,12 +1045,13 @@@
      if (for_controller) {
        char name_buf[MAX_VERBOSE_NICKNAME_LEN+2];
        char *cp = name_buf;
 -      if (!ri->is_running)
 +      if (!node->is_running)
          *cp++ = '!';
        router_get_verbose_nickname(cp, ri);
        smartlist_add(rs_entries, tor_strdup(name_buf));
      } else if (ri->cache_info.published_on >= cutoff) {
 -      smartlist_add(rs_entries, list_single_server_status(ri, ri->is_running));
 +      smartlist_add(rs_entries, list_single_server_status(ri,
 +                                                          node->is_running));
      }
    } SMARTLIST_FOREACH_END(ri);
  
@@@ -1079,12 -1063,12 +1089,12 @@@ format_versions_list(config_line_t *ln
   * not hibernating, and not too old. Else return 0.
   */
  static int
 -router_is_active(routerinfo_t *ri, time_t now)
 +router_is_active(const routerinfo_t *ri, const node_t *node, time_t now)
  {
    time_t cutoff = now - ROUTER_MAX_AGE_TO_PUBLISH;
    if (ri->cache_info.published_on < cutoff)
      return 0;
 -  if (!ri->is_running || !ri->is_valid || ri->is_hibernating)
 +  if (!node->is_running || !node->is_valid || ri->is_hibernating)
      return 0;
    return 1;
  }
@@@ -1185,7 -1169,7 +1195,7 @@@ dirserv_dump_directory_to_string(char *
  int
  directory_fetches_from_authorities(or_options_t *options)
  {
 -  routerinfo_t *me;
 +  const routerinfo_t *me;
    uint32_t addr;
    int refuseunknown;
    if (options->FetchDirInfoEarly)
@@@ -1297,8 -1281,7 +1307,8 @@@ static cached_dir_t cached_runningroute
   * cached_dir_t. */
  static digestmap_t *cached_v2_networkstatus = NULL;
  
 -/** Map from flavor name to the v3 consensuses that we're currently serving. */
 +/** Map from flavor name to the cached_dir_t for the v3 consensuses that we're
 + * currently serving. */
  static strmap_t *cached_consensuses = NULL;
  
  /** Possibly replace the contents of <b>d</b> with the value of
@@@ -1751,7 -1734,7 +1761,7 @@@ static uint64_t total_exit_bandwidth = 
  /** Helper: estimate the uptime of a router given its stated uptime and the
   * amount of time since it last stated its stated uptime. */
  static INLINE long
 -real_uptime(routerinfo_t *router, time_t now)
 +real_uptime(const routerinfo_t *router, time_t now)
  {
    if (now < router->cache_info.published_on)
      return router->uptime;
@@@ -1802,8 -1785,7 +1812,8 @@@ dirserv_thinks_router_is_unreliable(tim
   * been set.
   */
  static int
 -dirserv_thinks_router_is_hs_dir(routerinfo_t *router, time_t now)
 +dirserv_thinks_router_is_hs_dir(const routerinfo_t *router,
 +                                const node_t *node, time_t now)
  {
  
    long uptime;
@@@ -1828,7 -1810,7 +1838,7 @@@
     * version is too old. */
    return (router->wants_to_be_hs_dir && router->dir_port &&
            uptime > get_options()->MinUptimeHidServDirectoryV2 &&
 -          router->is_running);
 +          node->is_running);
  }
  
  /** Look through the routerlist, the Mean Time Between Failure history, and
@@@ -1876,22 -1858,19 +1886,22 @@@ dirserv_compute_performance_thresholds(
    /* Weighted fractional uptime for each active router. */
    wfus = tor_malloc(sizeof(double)*smartlist_len(rl->routers));
  
 +  nodelist_assert_ok();
 +
    /* Now, fill in the arrays. */
 -  SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
 -    if (router_is_active(ri, now)) {
 +  SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
 +    routerinfo_t *ri = node->ri;
 +    if (ri && router_is_active(ri, node, now)) {
        const char *id = ri->cache_info.identity_digest;
        uint32_t bw;
 -      ri->is_exit = (!router_exit_policy_rejects_all(ri) &&
 -                    exit_policy_is_general_exit(ri->exit_policy));
 +      node->is_exit = (!router_exit_policy_rejects_all(ri) &&
 +                       exit_policy_is_general_exit(ri->exit_policy));
        uptimes[n_active] = (uint32_t)real_uptime(ri, now);
        mtbfs[n_active] = rep_hist_get_stability(id, now);
        tks  [n_active] = rep_hist_get_weighted_time_known(id, now);
        bandwidths[n_active] = bw = router_get_advertised_bandwidth(ri);
        total_bandwidth += bw;
 -      if (ri->is_exit && !ri->is_bad_exit) {
 +      if (node->is_exit && !node->is_bad_exit) {
          total_exit_bandwidth += bw;
        } else {
          bandwidths_excluding_exits[n_active_nonexit] = bw;
@@@ -1899,7 -1878,7 +1909,7 @@@
        }
        ++n_active;
      }
 -  });
 +  } SMARTLIST_FOREACH_END(node);
  
    /* Now, compute thresholds. */
    if (n_active) {
@@@ -1925,17 -1904,15 +1935,17 @@@
    /* Now that we have a time-known that 7/8 routers are known longer than,
     * fill wfus with the wfu of every such "familiar" router. */
    n_familiar = 0;
 -  SMARTLIST_FOREACH(rl->routers, routerinfo_t *, ri, {
 -      if (router_is_active(ri, now)) {
 +
 +  SMARTLIST_FOREACH_BEGIN(nodelist_get_list(), node_t *, node) {
 +      routerinfo_t *ri = node->ri;
 +      if (ri && router_is_active(ri, node, now)) {
          const char *id = ri->cache_info.identity_digest;
          long tk = rep_hist_get_weighted_time_known(id, now);
          if (tk < guard_tk)
            continue;
          wfus[n_familiar++] = rep_hist_get_weighted_fractional_uptime(id, now);
        }
 -    });
 +  } SMARTLIST_FOREACH_END(node);
    if (n_familiar)
      guard_wfu = median_double(wfus, n_familiar);
    if (guard_wfu > WFU_TO_GUARANTEE_GUARD)
@@@ -2006,20 -1983,24 +2016,20 @@@ version_from_platform(const char *platf
   */
  int
  routerstatus_format_entry(char *buf, size_t buf_len,
 -                          routerstatus_t *rs, const char *version,
 +                          const routerstatus_t *rs, const char *version,
                            routerstatus_format_type_t format)
  {
    int r;
 -  struct in_addr in;
    char *cp;
    char *summary;
  
    char published[ISO_TIME_LEN+1];
 -  char ipaddr[INET_NTOA_BUF_LEN];
    char identity64[BASE64_DIGEST_LEN+1];
    char digest64[BASE64_DIGEST_LEN+1];
  
    format_iso_time(published, rs->published_on);
    digest_to_base64(identity64, rs->identity_digest);
    digest_to_base64(digest64, rs->descriptor_digest);
 -  in.s_addr = htonl(rs->addr);
 -  tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr));
  
    r = tor_snprintf(buf, buf_len,
                     "r %s %s %s%s%s %s %d %d\n",
@@@ -2028,7 -2009,7 +2038,7 @@@
                     (format==NS_V3_CONSENSUS_MICRODESC)?"":digest64,
                     (format==NS_V3_CONSENSUS_MICRODESC)?"":" ",
                     published,
 -                   ipaddr,
 +                   fmt_addr32(rs->addr),
                     (int)rs->or_port,
                     (int)rs->dir_port);
    if (r<0) {
@@@ -2056,7 -2037,7 +2066,7 @@@
                     rs->is_possible_guard?" Guard":"",
                     rs->is_hs_dir?" HSDir":"",
                     rs->is_named?" Named":"",
 -                   rs->is_running?" Running":"",
 +                   rs->is_flagged_running?" Running":"",
                     rs->is_stable?" Stable":"",
                     rs->is_unnamed?" Unnamed":"",
                     rs->is_v2_dir?" V2Dir":"",
@@@ -2078,7 -2059,7 +2088,7 @@@
    }
  
    if (format != NS_V2) {
 -    routerinfo_t* desc = router_get_by_digest(rs->identity_digest);
 +    const routerinfo_t* desc = router_get_by_id_digest(rs->identity_digest);
      uint32_t bw;
  
      if (format != NS_CONTROL_PORT) {
@@@ -2174,8 -2155,6 +2184,8 @@@ _compare_routerinfo_by_ip_and_bw(const 
    routerinfo_t *first = *(routerinfo_t **)a, *second = *(routerinfo_t **)b;
    int first_is_auth, second_is_auth;
    uint32_t bw_first, bw_second;
 +  const node_t *node_first, *node_second;
 +  int first_is_running, second_is_running;
  
    /* we return -1 if first should appear before second... that is,
     * if first is a better router. */
@@@ -2198,14 -2177,9 +2208,14 @@@
    else if (!first_is_auth && second_is_auth)
      return 1;
  
 -  else if (first->is_running && !second->is_running)
 +  node_first = node_get_by_id(first->cache_info.identity_digest);
 +  node_second = node_get_by_id(second->cache_info.identity_digest);
 +  first_is_running = node_first && node_first->is_running;
 +  second_is_running = node_second && node_second->is_running;
 +
 +  if (first_is_running && !second_is_running)
      return -1;
 -  else if (!first->is_running && second->is_running)
 +  else if (!first_is_running && second_is_running)
      return 1;
  
    bw_first = router_get_advertised_bandwidth(first);
@@@ -2274,9 -2248,7 +2284,9 @@@ get_possible_sybil_list(const smartlist
   */
  void
  set_routerstatus_from_routerinfo(routerstatus_t *rs,
 -                                 routerinfo_t *ri, time_t now,
 +                                 node_t *node,
 +                                 routerinfo_t *ri,
 +                                 time_t now,
                                   int naming, int listbadexits,
                                   int listbaddirs)
  {
@@@ -2288,46 -2260,48 +2298,46 @@@
      router_digest_is_trusted_dir(ri->cache_info.identity_digest);
  
    /* Already set by compute_performance_thresholds. */
 -  rs->is_exit = ri->is_exit;
 -  rs->is_stable = ri->is_stable =
 -    router_is_active(ri, now) &&
 +  rs->is_exit = node->is_exit;
 +  rs->is_stable = node->is_stable =
 +    router_is_active(ri, node, now) &&
      !dirserv_thinks_router_is_unreliable(now, ri, 1, 0) &&
      !unstable_version;
 -  rs->is_fast = ri->is_fast =
 -    router_is_active(ri, now) &&
 +  rs->is_fast = node->is_fast =
 +    router_is_active(ri, node, now) &&
      !dirserv_thinks_router_is_unreliable(now, ri, 0, 1);
 -  rs->is_running = ri->is_running; /* computed above */
 +  rs->is_flagged_running = node->is_running; /* computed above */
  
    if (naming) {
      uint32_t name_status = dirserv_get_name_status(
 -                         ri->cache_info.identity_digest, ri->nickname);
 +                                              node->identity, ri->nickname);
      rs->is_named = (naming && (name_status & FP_NAMED)) ? 1 : 0;
      rs->is_unnamed = (naming && (name_status & FP_UNNAMED)) ? 1 : 0;
    }
 -  rs->is_valid = ri->is_valid;
 +  rs->is_valid = node->is_valid;
  
 -  if (rs->is_fast &&
 +  if (node->is_fast &&
        (router_get_advertised_bandwidth(ri) >= BANDWIDTH_TO_GUARANTEE_GUARD ||
         router_get_advertised_bandwidth(ri) >=
                                MIN(guard_bandwidth_including_exits,
                                    guard_bandwidth_excluding_exits))) {
 -    long tk = rep_hist_get_weighted_time_known(
 -                                      ri->cache_info.identity_digest, now);
 -    double wfu = rep_hist_get_weighted_fractional_uptime(
 -                                      ri->cache_info.identity_digest, now);
 +    long tk = rep_hist_get_weighted_time_known(node->identity, now);
 +    double wfu = rep_hist_get_weighted_fractional_uptime(node->identity, now);
      rs->is_possible_guard = (wfu >= guard_wfu && tk >= guard_tk) ? 1 : 0;
    } else {
      rs->is_possible_guard = 0;
    }
 -  rs->is_bad_directory = listbaddirs && ri->is_bad_directory;
 -  rs->is_bad_exit = listbadexits && ri->is_bad_exit;
 -  ri->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, now);
 -  rs->is_hs_dir = ri->is_hs_dir;
 +  rs->is_bad_directory = listbaddirs && node->is_bad_directory;
 +  rs->is_bad_exit = listbadexits && node->is_bad_exit;
 +  node->is_hs_dir = dirserv_thinks_router_is_hs_dir(ri, node, now);
 +  rs->is_hs_dir = node->is_hs_dir;
    rs->is_v2_dir = ri->dir_port != 0;
  
    if (!strcasecmp(ri->nickname, UNNAMED_ROUTER_NICKNAME))
      rs->is_named = rs->is_unnamed = 0;
  
    rs->published_on = ri->cache_info.published_on;
 -  memcpy(rs->identity_digest, ri->cache_info.identity_digest, DIGEST_LEN);
 +  memcpy(rs->identity_digest, node->identity, DIGEST_LEN);
    memcpy(rs->descriptor_digest, ri->cache_info.signed_descriptor_digest,
           DIGEST_LEN);
    rs->addr = ri->addr;
@@@ -2344,7 -2318,7 +2354,7 @@@ static voi
  clear_status_flags_on_sybil(routerstatus_t *rs)
  {
    rs->is_authority = rs->is_exit = rs->is_stable = rs->is_fast =
 -    rs->is_running = rs->is_named = rs->is_valid = rs->is_v2_dir =
 +    rs->is_flagged_running = rs->is_named = rs->is_valid = rs->is_v2_dir =
      rs->is_hs_dir = rs->is_possible_guard = rs->is_bad_exit =
      rs->is_bad_directory = 0;
    /* FFFF we might want some mechanism to check later on if we
@@@ -2352,6 -2326,18 +2362,6 @@@
     * forget to add it to this clause. */
  }
  
 -/** Clear all the status flags in routerinfo <b>router</b>. We put this
 - * function here because it's eerily similar to
 - * clear_status_flags_on_sybil() above. One day we should merge them. */
 -void
 -router_clear_status_flags(routerinfo_t *router)
 -{
 -  router->is_valid = router->is_running = router->is_hs_dir =
 -    router->is_fast = router->is_stable =
 -    router->is_possible_guard = router->is_exit =
 -    router->is_bad_exit = router->is_bad_directory = 0;
 -}
 -
  /**
   * Helper function to parse out a line in the measured bandwidth file
   * into a measured_bw_line_t output structure. Returns -1 on failure
@@@ -2469,7 -2455,7 +2479,7 @@@ dirserv_read_measured_bandwidths(const 
                                   smartlist_t *routerstatuses)
  {
    char line[256];
 -  FILE *fp = fopen(from_file, "r");
 +  FILE *fp = tor_fopen_cloexec(from_file, "r");
    int applied_lines = 0;
    time_t file_time;
    int ok;
@@@ -2599,20 -2585,17 +2609,20 @@@ dirserv_generate_networkstatus_vote_obj
        routerstatus_t *rs;
        vote_routerstatus_t *vrs;
        microdesc_t *md;
 +      node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
 +      if (!node)
 +        continue;
  
        vrs = tor_malloc_zero(sizeof(vote_routerstatus_t));
        rs = &vrs->status;
 -      set_routerstatus_from_routerinfo(rs, ri, now,
 +      set_routerstatus_from_routerinfo(rs, node, ri, now,
                                         naming, listbadexits, listbaddirs);
  
        if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
          clear_status_flags_on_sybil(rs);
  
        if (!vote_on_reachability)
 -        rs->is_running = 0;
 +        rs->is_flagged_running = 0;
  
        vrs->version = version_from_platform(ri->platform);
        md = dirvote_create_microdescriptor(ri);
@@@ -2743,8 -2726,10 +2753,8 @@@ generate_v2_networkstatus_opinion(void
    char *outp, *endp;
    or_options_t *options = get_options();
    char fingerprint[FINGERPRINT_LEN+1];
 -  char ipaddr[INET_NTOA_BUF_LEN];
    char published[ISO_TIME_LEN+1];
    char digest[DIGEST_LEN];
 -  struct in_addr in;
    uint32_t addr;
    crypto_pk_env_t *private_key;
    routerlist_t *rl = router_get_routerlist();
@@@ -2765,6 -2750,8 +2775,6 @@@
      log_warn(LD_NET, "Couldn't resolve my hostname");
      goto done;
    }
 -  in.s_addr = htonl(addr);
 -  tor_inet_ntoa(&in, ipaddr, sizeof(ipaddr));
  
    format_iso_time(published, now);
  
@@@ -2810,7 -2797,7 +2820,7 @@@
                 "dir-options%s%s%s%s\n"
                 "%s" /* client version line, server version line. */
                 "dir-signing-key\n%s",
 -               hostname, ipaddr, (int)options->DirPort,
 +               hostname, fmt_addr32(addr), (int)options->DirPort,
                 fingerprint,
                 contact,
                 published,
@@@ -2841,12 -2828,8 +2851,12 @@@
      if (ri->cache_info.published_on >= cutoff) {
        routerstatus_t rs;
        char *version = version_from_platform(ri->platform);
 -
 -      set_routerstatus_from_routerinfo(&rs, ri, now,
 +      node_t *node = node_get_mutable_by_id(ri->cache_info.identity_digest);
 +      if (!node) {
 +        tor_free(version);
 +        continue;
 +      }
 +      set_routerstatus_from_routerinfo(&rs, node, ri, now,
                                         naming, listbadexits, listbaddirs);
  
        if (digestmap_get(omit_as_sybil, ri->cache_info.identity_digest))
@@@ -2929,7 -2912,7 +2939,7 @@@ dirserv_get_networkstatus_v2_fingerprin
  
    if (!strcmp(key,"authority")) {
      if (authdir_mode_v2(get_options())) {
 -      routerinfo_t *me = router_get_my_routerinfo();
 +      const routerinfo_t *me = router_get_my_routerinfo();
        if (me)
          smartlist_add(result,
                        tor_memdup(me->cache_info.identity_digest, DIGEST_LEN));
@@@ -3017,7 -3000,7 +3027,7 @@@ dirserv_get_routerdesc_fingerprints(sma
      /* Treat "all" requests as if they were unencrypted */
      for_unencrypted_conn = 1;
    } else if (!strcmp(key, "authority")) {
 -    routerinfo_t *ri = router_get_my_routerinfo();
 +    const routerinfo_t *ri = router_get_my_routerinfo();
      if (ri)
        smartlist_add(fps_out,
                      tor_memdup(ri->cache_info.identity_digest, DIGEST_LEN));
@@@ -3037,8 -3020,8 +3047,8 @@@
  
    if (for_unencrypted_conn) {
      /* Remove anything that insists it not be sent unencrypted. */
 -    SMARTLIST_FOREACH(fps_out, char *, cp, {
 -        signed_descriptor_t *sd;
 +    SMARTLIST_FOREACH_BEGIN(fps_out, char *, cp) {
 +        const signed_descriptor_t *sd;
          if (by_id)
            sd = get_signed_descriptor_by_fp(cp,is_extrainfo,0);
          else if (is_extrainfo)
@@@ -3049,7 -3032,7 +3059,7 @@@
            tor_free(cp);
            SMARTLIST_DEL_CURRENT(fps_out, cp);
          }
 -      });
 +    } SMARTLIST_FOREACH_END(cp);
    }
  
    if (!smartlist_len(fps_out)) {
@@@ -3088,9 -3071,9 +3098,9 @@@ dirserv_get_routerdescs(smartlist_t *de
      SMARTLIST_FOREACH(rl->routers, routerinfo_t *, r,
                        smartlist_add(descs_out, &(r->cache_info)));
    } else if (!strcmp(key, "/tor/server/authority")) {
 -    routerinfo_t *ri = router_get_my_routerinfo();
 +    const routerinfo_t *ri = router_get_my_routerinfo();
      if (ri)
 -      smartlist_add(descs_out, &(ri->cache_info));
 +      smartlist_add(descs_out, (void*) &(ri->cache_info));
    } else if (!strcmpstart(key, "/tor/server/d/")) {
      smartlist_t *digests = smartlist_create();
      key += strlen("/tor/server/d/");
@@@ -3114,17 -3097,17 +3124,17 @@@
         {
           if (router_digest_is_me(d)) {
             /* make sure desc_routerinfo exists */
 -           routerinfo_t *ri = router_get_my_routerinfo();
 +           const routerinfo_t *ri = router_get_my_routerinfo();
             if (ri)
 -             smartlist_add(descs_out, &(ri->cache_info));
 +             smartlist_add(descs_out, (void*) &(ri->cache_info));
           } else {
 -           routerinfo_t *ri = router_get_by_digest(d);
 +           const routerinfo_t *ri = router_get_by_id_digest(d);
             /* Don't actually serve a descriptor that everyone will think is
              * expired.  This is an (ugly) workaround to keep buggy 0.1.1.10
              * Tors from downloading descriptors that they will throw away.
              */
             if (ri && ri->cache_info.published_on > cutoff)
 -             smartlist_add(descs_out, &(ri->cache_info));
 +             smartlist_add(descs_out, (void*) &(ri->cache_info));
           }
         });
      SMARTLIST_FOREACH(digests, char *, d, tor_free(d));
@@@ -3190,8 -3173,7 +3200,8 @@@ dirserv_orconn_tls_done(const char *add
   * an upload or a download.  Used to decide whether to relaunch reachability
   * testing for the server. */
  int
 -dirserv_should_launch_reachability_test(routerinfo_t *ri, routerinfo_t *ri_old)
 +dirserv_should_launch_reachability_test(const routerinfo_t *ri,
 +                                        const routerinfo_t *ri_old)
  {
    if (!authdir_mode_handles_descs(get_options(), ri->purpose))
      return 0;
@@@ -3232,8 -3214,8 +3242,8 @@@ dirserv_single_reachability_test(time_
   * try a few connections per call.
   *
   * The load balancing is such that if we get called once every ten
-  * seconds, we will cycle through all the tests in 1280 seconds (a
-  * bit over 20 minutes).
+  * seconds, we will cycle through all the tests in
+  * REACHABILITY_TEST_CYCLE_PERIOD seconds (a bit over 20 minutes).
   */
  void
  dirserv_test_reachability(time_t now)
@@@ -3259,11 -3241,11 +3269,11 @@@
        continue; /* bridge authorities only test reachability on bridges */
  //    if (router->cache_info.published_on > cutoff)
  //      continue;
-     if ((((uint8_t)id_digest[0]) % 128) == ctr) {
+     if ((((uint8_t)id_digest[0]) % REACHABILITY_MODULO_PER_TEST) == ctr) {
        dirserv_single_reachability_test(now, router);
      }
    } SMARTLIST_FOREACH_END(router);
-   ctr = (ctr + 1) % 128; /* increment ctr */
+   ctr = (ctr + 1) % REACHABILITY_MODULO_PER_TEST; /* increment ctr */
  }
  
  /** Given a fingerprint <b>fp</b> which is either set if we're looking for a
@@@ -3315,7 -3297,7 +3325,7 @@@ dirserv_remove_old_statuses(smartlist_
   * its extra-info document if <b>extrainfo</b> is true. Return
   * NULL if not found or if the descriptor is older than
   * <b>publish_cutoff</b>. */
 -static signed_descriptor_t *
 +static const signed_descriptor_t *
  get_signed_descriptor_by_fp(const char *fp, int extrainfo,
                              time_t publish_cutoff)
  {
@@@ -3325,7 -3307,7 +3335,7 @@@
      else
        return &(router_get_my_routerinfo()->cache_info);
    } else {
 -    routerinfo_t *ri = router_get_by_digest(fp);
 +    const routerinfo_t *ri = router_get_by_id_digest(fp);
      if (ri &&
          ri->cache_info.published_on > publish_cutoff) {
        if (extrainfo)
@@@ -3393,7 -3375,7 +3403,7 @@@ dirserv_estimate_data_size(smartlist_t 
    tor_assert(fps);
    if (is_serverdescs) {
      int n = smartlist_len(fps);
 -    routerinfo_t *me = router_get_my_routerinfo();
 +    const routerinfo_t *me = router_get_my_routerinfo();
      result = (me?me->cache_info.signed_descriptor_len:2048) * n;
      if (compressed)
        result /= 2; /* observed compressibility is between 35 and 55%. */
@@@ -3457,10 -3439,10 +3467,10 @@@ connection_dirserv_add_servers_to_outbu
    time_t publish_cutoff = time(NULL)-ROUTER_MAX_AGE_TO_PUBLISH;
  
    while (smartlist_len(conn->fingerprint_stack) &&
 -         buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) {
 +         connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) {
      const char *body;
      char *fp = smartlist_pop_last(conn->fingerprint_stack);
 -    signed_descriptor_t *sd = NULL;
 +    const signed_descriptor_t *sd = NULL;
      if (by_fp) {
        sd = get_signed_descriptor_by_fp(fp, extra, publish_cutoff);
      } else {
@@@ -3518,7 -3500,7 +3528,7 @@@ connection_dirserv_add_microdescs_to_ou
  {
    microdesc_cache_t *cache = get_microdesc_cache();
    while (smartlist_len(conn->fingerprint_stack) &&
 -         buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) {
 +         connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) {
      char *fp256 = smartlist_pop_last(conn->fingerprint_stack);
      microdesc_t *md = microdesc_cache_lookup_by_digest256(cache, fp256);
      tor_free(fp256);
@@@ -3557,7 -3539,7 +3567,7 @@@ connection_dirserv_add_dir_bytes_to_out
    ssize_t bytes;
    int64_t remaining;
  
 -  bytes = DIRSERV_BUFFER_MIN - buf_datalen(conn->_base.outbuf);
 +  bytes = DIRSERV_BUFFER_MIN - connection_get_outbuf_len(TO_CONN(conn));
    tor_assert(bytes > 0);
    tor_assert(conn->cached_dir);
    if (bytes < 8192)
@@@ -3596,7 -3578,7 +3606,7 @@@ static in
  connection_dirserv_add_networkstatus_bytes_to_outbuf(dir_connection_t *conn)
  {
  
 -  while (buf_datalen(conn->_base.outbuf) < DIRSERV_BUFFER_MIN) {
 +  while (connection_get_outbuf_len(TO_CONN(conn)) < DIRSERV_BUFFER_MIN) {
      if (conn->cached_dir) {
        int uncompressing = (conn->zlib_state != NULL);
        int r = connection_dirserv_add_dir_bytes_to_outbuf(conn);
@@@ -3642,7 -3624,7 +3652,7 @@@ connection_dirserv_flushed_some(dir_con
  {
    tor_assert(conn->_base.state == DIR_CONN_STATE_SERVER_WRITING);
  
 -  if (buf_datalen(conn->_base.outbuf) >= DIRSERV_BUFFER_MIN)
 +  if (connection_get_outbuf_len(TO_CONN(conn)) >= DIRSERV_BUFFER_MIN)
      return 0;
  
    switch (conn->dir_spool_src) {
diff --combined src/or/dirserv.h
index 0489f3a,569abfc..8bd6d18
--- a/src/or/dirserv.h
+++ b/src/or/dirserv.h
@@@ -12,6 -12,18 +12,18 @@@
  #ifndef _TOR_DIRSERV_H
  #define _TOR_DIRSERV_H
  
+ /** What fraction (1 over this number) of the relay ID space do we
+  * (as a directory authority) launch connections to at each reachability
+  * test? */
+ #define REACHABILITY_MODULO_PER_TEST 128
+ 
+ /** How often (in seconds) do we launch reachability tests? */
+ #define REACHABILITY_TEST_INTERVAL 10
+ 
+ /** How many seconds apart are the reachability tests for a given relay? */
+ #define REACHABILITY_TEST_CYCLE_PERIOD \
+   (REACHABILITY_TEST_INTERVAL*REACHABILITY_MODULO_PER_TEST)
+ 
  /** Maximum length of an exit policy summary. */
  #define MAX_EXITPOLICY_SUMMARY_LEN 1000
  
@@@ -40,6 -52,8 +52,6 @@@
     MAX_V_LINE_LEN                                                       \
     )
  
 -#define UNNAMED_ROUTER_NICKNAME "Unnamed"
 -
  int connection_dirserv_flushed_some(dir_connection_t *conn);
  
  int dirserv_add_own_fingerprint(const char *nickname, crypto_pk_env_t *pk);
@@@ -97,19 -111,13 +109,19 @@@ void dirserv_orconn_tls_done(const cha
                               uint16_t or_port,
                               const char *digest_rcvd,
                               int as_advertised);
 -int dirserv_should_launch_reachability_test(routerinfo_t *ri,
 -                                            routerinfo_t *ri_old);
 +int dirserv_should_launch_reachability_test(const routerinfo_t *ri,
 +                                            const routerinfo_t *ri_old);
  void dirserv_single_reachability_test(time_t now, routerinfo_t *router);
  void dirserv_test_reachability(time_t now);
  int authdir_wants_to_reject_router(routerinfo_t *ri, const char **msg,
 -                                   int complain);
 -int dirserv_would_reject_router(routerstatus_t *rs);
 +                                   int complain,
 +                                   int *valid_out);
 +uint32_t dirserv_router_get_status(const routerinfo_t *router,
 +                                   const char **msg);
 +void dirserv_set_node_flags_from_authoritative_status(node_t *node,
 +                                                      uint32_t authstatus);
 +
 +int dirserv_would_reject_router(const routerstatus_t *rs);
  int dirserv_remove_old_statuses(smartlist_t *fps, time_t cutoff);
  int dirserv_have_any_serverdesc(smartlist_t *fps, int spool_src);
  int dirserv_have_any_microdesc(const smartlist_t *fps);
@@@ -118,7 -126,7 +130,7 @@@ size_t dirserv_estimate_data_size(smart
  size_t dirserv_estimate_microdesc_size(const smartlist_t *fps, int compressed);
  
  int routerstatus_format_entry(char *buf, size_t buf_len,
 -                              routerstatus_t *rs, const char *platform,
 +                              const routerstatus_t *rs, const char *platform,
                                routerstatus_format_type_t format);
  void dirserv_free_all(void);
  void cached_dir_decref(cached_dir_t *d);
diff --combined src/or/main.c
index c1335ff,214a4fa..9c19485
--- a/src/or/main.c
+++ b/src/or/main.c
@@@ -33,7 -33,6 +33,7 @@@
  #include "main.h"
  #include "microdesc.h"
  #include "networkstatus.h"
 +#include "nodelist.h"
  #include "ntmain.h"
  #include "onion.h"
  #include "policies.h"
@@@ -45,7 -44,6 +45,7 @@@
  #include "router.h"
  #include "routerlist.h"
  #include "routerparse.h"
 +#include "status.h"
  #ifdef USE_DMALLOC
  #include <dmalloc.h>
  #include <openssl/crypto.h>
@@@ -58,10 -56,6 +58,10 @@@
  #include <event.h>
  #endif
  
 +#ifdef USE_BUFFEREVENTS
 +#include <event2/bufferevent.h>
 +#endif
 +
  void evdns_shutdown(int);
  
  /********* PROTOTYPES **********/
@@@ -78,7 -72,6 +78,7 @@@ static int connection_should_read_from_
  
  /********* START VARIABLES **********/
  
 +#ifndef USE_BUFFEREVENTS
  int global_read_bucket; /**< Max number of bytes I can read this second. */
  int global_write_bucket; /**< Max number of bytes I can write this second. */
  
@@@ -86,17 -79,13 +86,17 @@@
  int global_relayed_read_bucket;
  /** Max number of relayed (bandwidth class 1) bytes I can write this second. */
  int global_relayed_write_bucket;
 -
  /** What was the read bucket before the last second_elapsed_callback() call?
   * (used to determine how many bytes we've read). */
  static int stats_prev_global_read_bucket;
  /** What was the write bucket before the last second_elapsed_callback() call?
   * (used to determine how many bytes we've written). */
  static int stats_prev_global_write_bucket;
 +#else
 +static uint64_t stats_prev_n_read = 0;
 +static uint64_t stats_prev_n_written = 0;
 +#endif
 +
  /* XXX we might want to keep stats about global_relayed_*_bucket too. Or not.*/
  /** How many bytes have we read since we started the process? */
  static uint64_t stats_n_bytes_read = 0;
@@@ -162,38 -151,12 +162,38 @@@ int can_complete_circuit=0
  *
  ****************************************************************************/
  
 +#if 0 && defined(USE_BUFFEREVENTS)
 +static void
 +free_old_inbuf(connection_t *conn)
 +{
 +  if (! conn->inbuf)
 +    return;
 +
 +  tor_assert(conn->outbuf);
 +  tor_assert(buf_datalen(conn->inbuf) == 0);
 +  tor_assert(buf_datalen(conn->outbuf) == 0);
 +  buf_free(conn->inbuf);
 +  buf_free(conn->outbuf);
 +  conn->inbuf = conn->outbuf = NULL;
 +
 +  if (conn->read_event) {
 +    event_del(conn->read_event);
 +    tor_event_free(conn->read_event);
 +  }
 +  if (conn->write_event) {
 +    event_del(conn->read_event);
 +    tor_event_free(conn->write_event);
 +  }
 +  conn->read_event = conn->write_event = NULL;
 +}
 +#endif
 +
  /** Add <b>conn</b> to the array of connections that we can poll on.  The
   * connection's socket must be set; the connection starts out
   * non-reading and non-writing.
   */
  int
 -connection_add(connection_t *conn)
 +connection_add_impl(connection_t *conn, int is_connecting)
  {
    tor_assert(conn);
    tor_assert(conn->s >= 0 ||
@@@ -205,63 -168,11 +205,63 @@@
    conn->conn_array_index = smartlist_len(connection_array);
    smartlist_add(connection_array, conn);
  
 -  if (conn->s >= 0 || conn->linked) {
 +#ifdef USE_BUFFEREVENTS
 +  if (connection_type_uses_bufferevent(conn)) {
 +    if (conn->s >= 0 && !conn->linked) {
 +      conn->bufev = bufferevent_socket_new(
 +                         tor_libevent_get_base(),
 +                         conn->s,
 +                         BEV_OPT_DEFER_CALLBACKS);
 +      if (!conn->bufev) {
 +        log_warn(LD_BUG, "Unable to create socket bufferevent");
 +        smartlist_del(connection_array, conn->conn_array_index);
 +        conn->conn_array_index = -1;
 +        return -1;
 +      }
 +      if (is_connecting) {
 +        /* Put the bufferevent into a "connecting" state so that we'll get
 +         * a "connected" event callback on successful write. */
 +        bufferevent_socket_connect(conn->bufev, NULL, 0);
 +      }
 +      connection_configure_bufferevent_callbacks(conn);
 +    } else if (conn->linked && conn->linked_conn &&
 +               connection_type_uses_bufferevent(conn->linked_conn)) {
 +      tor_assert(conn->s < 0);
 +      if (!conn->bufev) {
 +        struct bufferevent *pair[2] = { NULL, NULL };
 +        if (bufferevent_pair_new(tor_libevent_get_base(),
 +                                 BEV_OPT_DEFER_CALLBACKS,
 +                                 pair) < 0) {
 +          log_warn(LD_BUG, "Unable to create bufferevent pair");
 +          smartlist_del(connection_array, conn->conn_array_index);
 +          conn->conn_array_index = -1;
 +          return -1;
 +        }
 +        tor_assert(pair[0]);
 +        conn->bufev = pair[0];
 +        conn->linked_conn->bufev = pair[1];
 +      } /* else the other side already was added, and got a bufferevent_pair */
 +      connection_configure_bufferevent_callbacks(conn);
 +    } else {
 +      tor_assert(!conn->linked);
 +    }
 +
 +    if (conn->bufev)
 +      tor_assert(conn->inbuf == NULL);
 +
 +    if (conn->linked_conn && conn->linked_conn->bufev)
 +      tor_assert(conn->linked_conn->inbuf == NULL);
 +  }
 +#else
 +  (void) is_connecting;
 +#endif
 +
 +  if (!HAS_BUFFEREVENT(conn) && (conn->s >= 0 || conn->linked)) {
      conn->read_event = tor_event_new(tor_libevent_get_base(),
           conn->s, EV_READ|EV_PERSIST, conn_read_callback, conn);
      conn->write_event = tor_event_new(tor_libevent_get_base(),
           conn->s, EV_WRITE|EV_PERSIST, conn_write_callback, conn);
 +    /* XXXX CHECK FOR NULL RETURN! */
    }
  
    log_debug(LD_NET,"new conn type %s, socket %d, address %s, n_conns %d.",
@@@ -285,12 -196,6 +285,12 @@@ connection_unregister_events(connection
        log_warn(LD_BUG, "Error removing write event for %d", conn->s);
      tor_free(conn->write_event);
    }
 +#ifdef USE_BUFFEREVENTS
 +  if (conn->bufev) {
 +    bufferevent_free(conn->bufev);
 +    conn->bufev = NULL;
 +  }
 +#endif
    if (conn->dns_server_port) {
      dnsserv_close_listener(conn);
    }
@@@ -399,37 -304,12 +399,37 @@@ get_connection_array(void
    return connection_array;
  }
  
 +/** Provides the traffic read and written over the life of the process. */
 +
 +uint64_t
 +get_bytes_read(void)
 +{
 +  return stats_n_bytes_read;
 +}
 +
 +uint64_t
 +get_bytes_written(void)
 +{
 +  return stats_n_bytes_written;
 +}
 +
  /** Set the event mask on <b>conn</b> to <b>events</b>.  (The event
   * mask is a bitmask whose bits are READ_EVENT and WRITE_EVENT)
   */
  void
  connection_watch_events(connection_t *conn, watchable_events_t events)
  {
 +  IF_HAS_BUFFEREVENT(conn, {
 +      short ev = ((short)events) & (EV_READ|EV_WRITE);
 +      short old_ev = bufferevent_get_enabled(conn->bufev);
 +      if ((ev & ~old_ev) != 0) {
 +        bufferevent_enable(conn->bufev, ev);
 +      }
 +      if ((old_ev & ~ev) != 0) {
 +        bufferevent_disable(conn->bufev, old_ev & ~ev);
 +      }
 +      return;
 +  });
    if (events & READ_EVENT)
      connection_start_reading(conn);
    else
@@@ -447,9 -327,6 +447,9 @@@ connection_is_reading(connection_t *con
  {
    tor_assert(conn);
  
 +  IF_HAS_BUFFEREVENT(conn,
 +    return (bufferevent_get_enabled(conn->bufev) & EV_READ) != 0;
 +  );
    return conn->reading_from_linked_conn ||
      (conn->read_event && event_pending(conn->read_event, EV_READ, NULL));
  }
@@@ -459,12 -336,6 +459,12 @@@ voi
  connection_stop_reading(connection_t *conn)
  {
    tor_assert(conn);
 +
 +  IF_HAS_BUFFEREVENT(conn, {
 +      bufferevent_disable(conn->bufev, EV_READ);
 +      return;
 +  });
 +
    tor_assert(conn->read_event);
  
    if (conn->linked) {
@@@ -484,12 -355,6 +484,12 @@@ voi
  connection_start_reading(connection_t *conn)
  {
    tor_assert(conn);
 +
 +  IF_HAS_BUFFEREVENT(conn, {
 +      bufferevent_enable(conn->bufev, EV_READ);
 +      return;
 +  });
 +
    tor_assert(conn->read_event);
  
    if (conn->linked) {
@@@ -511,10 -376,6 +511,10 @@@ connection_is_writing(connection_t *con
  {
    tor_assert(conn);
  
 +  IF_HAS_BUFFEREVENT(conn,
 +    return (bufferevent_get_enabled(conn->bufev) & EV_WRITE) != 0;
 +  );
 +
    return conn->writing_to_linked_conn ||
      (conn->write_event && event_pending(conn->write_event, EV_WRITE, NULL));
  }
@@@ -524,12 -385,6 +524,12 @@@ voi
  connection_stop_writing(connection_t *conn)
  {
    tor_assert(conn);
 +
 +  IF_HAS_BUFFEREVENT(conn, {
 +      bufferevent_disable(conn->bufev, EV_WRITE);
 +      return;
 +  });
 +
    tor_assert(conn->write_event);
  
    if (conn->linked) {
@@@ -550,12 -405,6 +550,12 @@@ voi
  connection_start_writing(connection_t *conn)
  {
    tor_assert(conn);
 +
 +  IF_HAS_BUFFEREVENT(conn, {
 +      bufferevent_enable(conn->bufev, EV_WRITE);
 +      return;
 +  });
 +
    tor_assert(conn->write_event);
  
    if (conn->linked) {
@@@ -741,23 -590,7 +741,23 @@@ conn_close_if_marked(int i
    assert_connection_ok(conn, now);
    /* assert_all_pending_dns_resolves_ok(); */
  
 +#ifdef USE_BUFFEREVENTS
 +  if (conn->bufev) {
 +    if (conn->hold_open_until_flushed &&
 +        evbuffer_get_length(bufferevent_get_output(conn->bufev))) {
 +      /* don't close yet. */
 +      return 0;
 +    }
 +    if (conn->linked_conn && ! conn->linked_conn->marked_for_close) {
 +      /* We need to do this explicitly so that the linked connection
 +       * notices that there was an EOF. */
 +      bufferevent_flush(conn->bufev, EV_WRITE, BEV_FINISHED);
 +    }
 +  }
 +#endif
 +
    log_debug(LD_NET,"Cleaning up connection (fd %d).",conn->s);
 +  IF_HAS_BUFFEREVENT(conn, goto unlink);
    if ((conn->s >= 0 || conn->linked_conn) && connection_wants_to_flush(conn)) {
      /* s == -1 means it's an incomplete edge connection, or that the socket
       * has already been closed as unflushable. */
@@@ -780,8 -613,8 +780,8 @@@
        }
        log_debug(LD_GENERAL, "Flushed last %d bytes from a linked conn; "
                 "%d left; flushlen %d; wants-to-flush==%d", retval,
 -               (int)buf_datalen(conn->outbuf),
 -               (int)conn->outbuf_flushlen,
 +                (int)connection_get_outbuf_len(conn),
 +                (int)conn->outbuf_flushlen,
                  connection_wants_to_flush(conn));
      } else if (connection_speaks_cells(conn)) {
        if (conn->state == OR_CONN_STATE_OPEN) {
@@@ -818,17 -651,13 +818,17 @@@
               "something is wrong with your network connection, or "
               "something is wrong with theirs. "
               "(fd %d, type %s, state %d, marked at %s:%d).",
 -             (int)buf_datalen(conn->outbuf),
 +             (int)connection_get_outbuf_len(conn),
               escaped_safe_str_client(conn->address),
               conn->s, conn_type_to_string(conn->type), conn->state,
               conn->marked_for_close_file,
               conn->marked_for_close);
      }
    }
 +
 +#ifdef USE_BUFFEREVENTS
 + unlink:
 +#endif
    connection_unlink(conn); /* unlink, remove, free */
    return 1;
  }
@@@ -874,13 -703,10 +874,13 @@@ directory_info_has_arrived(time_t now, 
          "I learned some more directory information, but not enough to "
          "build a circuit: %s", get_dir_info_status_string());
      update_router_descriptor_downloads(now);
 +    update_microdesc_downloads(now);
      return;
    } else {
 -    if (directory_fetches_from_authorities(options))
 +    if (directory_fetches_from_authorities(options)) {
        update_router_descriptor_downloads(now);
 +      update_microdesc_downloads(now);
 +    }
  
      /* if we have enough dir info, then update our guard status with
       * whatever we just learned. */
@@@ -918,8 -744,7 +918,8 @@@ run_connection_housekeeping(int i, time
    int past_keepalive =
      now >= conn->timestamp_lastwritten + options->KeepalivePeriod;
  
 -  if (conn->outbuf && !buf_datalen(conn->outbuf) && conn->type == CONN_TYPE_OR)
 +  if (conn->outbuf && !connection_get_outbuf_len(conn) &&
 +      conn->type == CONN_TYPE_OR)
      TO_OR_CONN(conn)->timestamp_lastempty = now;
  
    if (conn->marked_for_close) {
@@@ -939,7 -764,7 +939,7 @@@
      /* This check is temporary; it's to let us know whether we should consider
       * parsing partial serverdesc responses. */
      if (conn->purpose == DIR_PURPOSE_FETCH_SERVERDESC &&
 -        buf_datalen(conn->inbuf)>=1024) {
 +        connection_get_inbuf_len(conn) >= 1024) {
        log_info(LD_DIR,"Trying to extract information from wedged server desc "
                 "download.");
        connection_dir_reached_eof(TO_DIR_CONN(conn));
@@@ -956,11 -781,7 +956,11 @@@
       the connection or send a keepalive, depending. */
  
    or_conn = TO_OR_CONN(conn);
 +#ifdef USE_BUFFEREVENTS
 +  tor_assert(conn->bufev);
 +#else
    tor_assert(conn->outbuf);
 +#endif
  
    if (or_conn->is_bad_for_new_circs && !or_conn->n_circuits) {
      /* It's bad for new circuits, and has no unmarked circuits on it:
@@@ -972,7 -793,8 +972,7 @@@
        connection_or_connect_failed(TO_OR_CONN(conn),
                                     END_OR_CONN_REASON_TIMEOUT,
                                     "Tor gave up on the connection");
 -    connection_mark_for_close(conn);
 -    conn->hold_open_until_flushed = 1;
 +    connection_mark_and_flush(conn);
    } else if (!connection_state_is_open(conn)) {
      if (past_keepalive) {
        /* We never managed to actually get this connection open and happy. */
@@@ -981,12 -803,13 +981,12 @@@
        connection_mark_for_close(conn);
      }
    } else if (we_are_hibernating() && !or_conn->n_circuits &&
 -             !buf_datalen(conn->outbuf)) {
 +             !connection_get_outbuf_len(conn)) {
      /* We're hibernating, there's no circuits, and nothing to flush.*/
      log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) "
               "[Hibernating or exiting].",
               conn->s,conn->address, conn->port);
 -    connection_mark_for_close(conn);
 -    conn->hold_open_until_flushed = 1;
 +    connection_mark_and_flush(conn);
    } else if (!or_conn->n_circuits &&
               now >= or_conn->timestamp_last_added_nonpadding +
                                           IDLE_OR_CONN_TIMEOUT) {
@@@ -994,6 -817,7 +994,6 @@@
               "[idle %d].", conn->s,conn->address, conn->port,
               (int)(now - or_conn->timestamp_last_added_nonpadding));
      connection_mark_for_close(conn);
 -    conn->hold_open_until_flushed = 1;
    } else if (
        now >= or_conn->timestamp_lastempty + options->KeepalivePeriod*10 &&
        now >= conn->timestamp_lastwritten + options->KeepalivePeriod*10) {
@@@ -1001,10 -825,10 +1001,10 @@@
             "Expiring stuck OR connection to fd %d (%s:%d). (%d bytes to "
             "flush; %d seconds since last write)",
             conn->s, conn->address, conn->port,
 -           (int)buf_datalen(conn->outbuf),
 +           (int)connection_get_outbuf_len(conn),
             (int)(now-conn->timestamp_lastwritten));
      connection_mark_for_close(conn);
 -  } else if (past_keepalive && !buf_datalen(conn->outbuf)) {
 +  } else if (past_keepalive && !connection_get_outbuf_len(conn)) {
      /* send a padding cell */
      log_fn(LOG_DEBUG,LD_OR,"Sending keepalive to (%s:%d)",
             conn->address, conn->port);
@@@ -1048,10 -872,9 +1048,11 @@@ run_scheduled_events(time_t now
    static time_t time_to_check_for_expired_networkstatus = 0;
    static time_t time_to_write_stats_files = 0;
    static time_t time_to_write_bridge_stats = 0;
 +  static time_t time_to_check_port_forwarding = 0;
+   static time_t time_to_launch_reachability_tests = 0;
    static int should_init_bridge_stats = 1;
    static time_t time_to_retry_dns_init = 0;
 +  static time_t time_to_next_heartbeat = 0;
    or_options_t *options = get_options();
    int is_server = server_mode(options);
    int i;
@@@ -1063,16 -886,6 +1064,16 @@@
     */
    consider_hibernation(now);
  
 +#if 0
 +  {
 +    static time_t nl_check_time = 0;
 +    if (nl_check_time <= now) {
 +      nodelist_assert_ok();
 +      nl_check_time = now + 30;
 +    }
 +  }
 +#endif
 +
    /* 0b. If we've deferred a signewnym, make sure it gets handled
     * eventually. */
    if (signewnym_is_pending &&
@@@ -1103,7 -916,6 +1104,7 @@@
    if (time_to_try_getting_descriptors < now) {
      update_router_descriptor_downloads(now);
      update_extrainfo_downloads(now);
 +    update_microdesc_downloads(now);
      if (options->UseBridges)
        fetch_bridge_descriptors(options, now);
      if (router_have_minimum_dir_info())
@@@ -1151,8 -963,10 +1152,10 @@@
    if (accounting_is_enabled(options))
      accounting_run_housekeeping(now);
  
-   if (now % 10 == 0 && (authdir_mode_tests_reachability(options)) &&
-       !we_are_hibernating()) {
+   if (time_to_launch_reachability_tests < now &&
+       (authdir_mode_tests_reachability(options)) &&
+        !we_are_hibernating()) {
+     time_to_launch_reachability_tests = now + REACHABILITY_TEST_INTERVAL;
      /* try to determine reachability of the other Tor relays */
      dirserv_test_reachability(now);
    }
@@@ -1223,11 -1037,6 +1226,11 @@@
        if (next_write && next_write < next_time_to_write_stats_files)
          next_time_to_write_stats_files = next_write;
      }
 +    if (options->ConnDirectionStatistics) {
 +      time_t next_write = rep_hist_conn_stats_write(time_to_write_stats_files);
 +      if (next_write && next_write < next_time_to_write_stats_files)
 +        next_time_to_write_stats_files = next_write;
 +    }
      time_to_write_stats_files = next_time_to_write_stats_files;
    }
  
@@@ -1256,8 -1065,8 +1259,8 @@@
    /* Remove old information from rephist and the rend cache. */
    if (time_to_clean_caches < now) {
      rep_history_clean(now - options->RephistTrackTime);
 -    rend_cache_clean();
 -    rend_cache_clean_v2_descs_as_dir();
 +    rend_cache_clean(now);
 +    rend_cache_clean_v2_descs_as_dir(now);
  #define CLEAN_CACHES_INTERVAL (30*60)
      time_to_clean_caches = now + CLEAN_CACHES_INTERVAL;
    }
@@@ -1266,7 -1075,7 +1269,7 @@@
    /* If we're a server and initializing dns failed, retry periodically. */
    if (time_to_retry_dns_init < now) {
      time_to_retry_dns_init = now + RETRY_DNS_INTERVAL;
 -    if (server_mode(options) && has_dns_init_failed())
 +    if (is_server && has_dns_init_failed())
        dns_init();
    }
  
@@@ -1297,7 -1106,7 +1300,7 @@@
      consider_publishable_server(0);
      /* also, check religiously for reachability, if it's within the first
       * 20 minutes of our uptime. */
 -    if (server_mode(options) &&
 +    if (is_server &&
          (can_complete_circuit || !any_predicted_circuits(now)) &&
          !we_are_hibernating()) {
        if (stats_n_seconds_working < TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) {
@@@ -1308,7 -1117,7 +1311,7 @@@
          /* If we haven't checked for 12 hours and our bandwidth estimate is
           * low, do another bandwidth test. This is especially important for
           * bridges, since they might go long periods without much use. */
 -        routerinfo_t *me = router_get_my_routerinfo();
 +        const routerinfo_t *me = router_get_my_routerinfo();
          if (time_to_recheck_bandwidth && me &&
              me->bandwidthcapacity < me->bandwidthrate &&
              me->bandwidthcapacity < 51200) {
@@@ -1431,24 -1240,6 +1434,24 @@@
  #define BRIDGE_STATUSFILE_INTERVAL (30*60)
      time_to_write_bridge_status_file = now+BRIDGE_STATUSFILE_INTERVAL;
    }
 +
 +  if (time_to_check_port_forwarding < now &&
 +      options->PortForwarding &&
 +      is_server) {
 +#define PORT_FORWARDING_CHECK_INTERVAL 5
 +    tor_check_port_forwarding(options->PortForwardingHelper,
 +                              options->DirPort,
 +                              options->ORPort,
 +                              now);
 +    time_to_check_port_forwarding = now+PORT_FORWARDING_CHECK_INTERVAL;
 +  }
 +
 +  /** 11. write the heartbeat message */
 +  if (options->HeartbeatPeriod &&
 +      time_to_next_heartbeat < now) {
 +    log_heartbeat(now);
 +    time_to_next_heartbeat = now+options->HeartbeatPeriod;
 +  }
  }
  
  /** Timer: used to invoke second_elapsed_callback() once per second. */
@@@ -1468,9 -1259,6 +1471,9 @@@ second_elapsed_callback(periodic_timer_
    size_t bytes_written;
    size_t bytes_read;
    int seconds_elapsed;
 +#ifdef USE_BUFFEREVENTS
 +  uint64_t cur_read,cur_written;
 +#endif
    or_options_t *options = get_options();
    (void)timer;
    (void)arg;
@@@ -1482,15 -1270,9 +1485,15 @@@
    update_approx_time(now);
  
    /* the second has rolled over. check more stuff. */
 +  seconds_elapsed = current_second ? (int)(now - current_second) : 0;
 +#ifdef USE_BUFFEREVENTS
 +  connection_get_rate_limit_totals(&cur_read, &cur_written);
 +  bytes_written = (size_t)(cur_written - stats_prev_n_written);
 +  bytes_read = (size_t)(cur_read - stats_prev_n_read);
 +#else
    bytes_written = stats_prev_global_write_bucket - global_write_bucket;
    bytes_read = stats_prev_global_read_bucket - global_read_bucket;
 -  seconds_elapsed = current_second ? (int)(now - current_second) : 0;
 +#endif
    stats_n_bytes_read += bytes_read;
    stats_n_bytes_written += bytes_written;
    if (accounting_is_enabled(options) && seconds_elapsed >= 0)
@@@ -1500,13 -1282,8 +1503,13 @@@
  
    if (seconds_elapsed > 0)
      connection_bucket_refill(seconds_elapsed, now);
 +#ifdef USE_BUFFEREVENTS
 +  stats_prev_n_written = cur_written;
 +  stats_prev_n_read = cur_read;
 +#else
    stats_prev_global_read_bucket = global_read_bucket;
    stats_prev_global_write_bucket = global_write_bucket;
 +#endif
  
    if (server_mode(options) &&
        !we_are_hibernating() &&
@@@ -1516,7 -1293,7 +1519,7 @@@
        (stats_n_seconds_working+seconds_elapsed) /
          TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) {
      /* every 20 minutes, check and complain if necessary */
 -    routerinfo_t *me = router_get_my_routerinfo();
 +    const routerinfo_t *me = router_get_my_routerinfo();
      if (me && !check_whether_orport_reachable()) {
        log_warn(LD_CONFIG,"Your server (%s:%d) has not managed to confirm that "
                 "its ORPort is reachable. Please check your firewalls, ports, "
@@@ -1707,10 -1484,8 +1710,10 @@@ do_main_loop(void
  
    /* Set up our buckets */
    connection_bucket_init();
 +#ifndef USE_BUFFEREVENTS
    stats_prev_global_read_bucket = global_read_bucket;
    stats_prev_global_write_bucket = global_write_bucket;
 +#endif
  
    /* initialize the bootstrap status events to know we're starting up */
    control_event_bootstrap(BOOTSTRAP_STATUS_STARTING, 0);
@@@ -1871,13 -1646,11 +1874,13 @@@ signal_callback(int fd, short events, v
      case SIGUSR1:
        /* prefer to log it at INFO, but make sure we always see it */
        dumpstats(get_min_log_level()<LOG_INFO ? get_min_log_level() : LOG_INFO);
 +      control_event_signal(sig);
        break;
      case SIGUSR2:
        switch_logs_debug();
        log_debug(LD_GENERAL,"Caught USR2, going to loglevel debug. "
                  "Send HUP to change back.");
 +      control_event_signal(sig);
        break;
      case SIGHUP:
        if (do_hup() < 0) {
@@@ -1885,7 -1658,6 +1888,7 @@@
          tor_cleanup();
          exit(1);
        }
 +      control_event_signal(sig);
        break;
  #ifdef SIGCHLD
      case SIGCHLD:
@@@ -1902,33 -1674,15 +1905,33 @@@
              (int)(MAX_SIGNEWNYM_RATE+time_of_last_signewnym-now));
        } else {
          signewnym_impl(now);
 +        control_event_signal(sig);
        }
        break;
      }
      case SIGCLEARDNSCACHE:
        addressmap_clear_transient();
 +      control_event_signal(sig);
        break;
    }
  }
  
 +/** Returns Tor's uptime. */
 +long
 +get_uptime(void)
 +{
 +  return stats_n_seconds_working;
 +}
 +
 +/** Fills <b>n_read_in</b> with total bytes read and <b>n_written_out</b>
 +    with total bytes written */
 +void
 +get_traffic_stats(uint64_t *n_read_in, uint64_t *n_written_out)
 +{
 +  *n_read_in = stats_n_bytes_read;
 +  *n_written_out = stats_n_bytes_written;
 +}
 +
  extern uint64_t rephist_total_alloc;
  extern uint32_t rephist_total_num;
  
@@@ -1975,13 -1729,13 +1978,13 @@@ dumpstats(int severity
        log(severity,LD_GENERAL,
            "Conn %d: %d bytes waiting on inbuf (len %d, last read %d secs ago)",
            i,
 -          (int)buf_datalen(conn->inbuf),
 +          (int)connection_get_inbuf_len(conn),
            (int)buf_allocation(conn->inbuf),
            (int)(now - conn->timestamp_lastread));
        log(severity,LD_GENERAL,
            "Conn %d: %d bytes waiting on outbuf "
            "(len %d, last written %d secs ago)",i,
 -          (int)buf_datalen(conn->outbuf),
 +          (int)connection_get_outbuf_len(conn),
            (int)buf_allocation(conn->outbuf),
            (int)(now - conn->timestamp_lastwritten));
        if (conn->type == CONN_TYPE_OR) {
@@@ -2278,7 -2032,6 +2281,7 @@@ tor_free_all(int postfork
    connection_free_all();
    buf_shrink_freelists(1);
    memarea_clear_freelist();
 +  nodelist_free_all();
    microdesc_free_all();
    if (!postfork) {
      config_free_all();



More information about the tor-commits mailing list