[tor-commits] [tor/master] Turn all of run_scheduled_events() into a bunch of periodic events

nickm at torproject.org nickm at torproject.org
Tue Nov 17 13:28:57 UTC 2015


commit 9f31908a405acc64a8dbf1910a273190d7e33f48
Author: Nick Mathewson <nickm at torproject.org>
Date:   Mon Nov 2 14:59:29 2015 -0500

    Turn all of run_scheduled_events() into a bunch of periodic events
    
    This patch is designed to look good when you see it through 'diff -b':
    it mostly leaves entries in the same order, and leaves the code unmodified.
---
 src/or/main.c |  749 ++++++++++++++++++++++++++++++++++++++-------------------
 1 file changed, 498 insertions(+), 251 deletions(-)

diff --git a/src/or/main.c b/src/or/main.c
index 0db843f..593bf0c 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -1231,43 +1231,87 @@ get_signewnym_epoch(void)
 /** DOCDOC */
 static int periodic_events_initialized = 0;
 
+#define CALLBACK(name) \
+  static int name ## _callback(time_t, const or_options_t *)
+CALLBACK(rotate_onion_key);
+CALLBACK(check_ed_keys);
+CALLBACK(launch_descriptor_fetches);
+CALLBACK(reset_descriptor_failures);
+CALLBACK(fetch_bridge_descriptors);
+CALLBACK(rotate_x509_certificate);
+CALLBACK(add_entropy);
+CALLBACK(enable_accounting);
+CALLBACK(launch_reachability_tests);
+CALLBACK(downrate_stability);
+CALLBACK(save_stability);
+CALLBACK(check_authority_cert);
+CALLBACK(check_expired_networkstatus);
+CALLBACK(write_stats_file);
+CALLBACK(record_bridge_stats);
+CALLBACK(clean_caches);
+CALLBACK(rend_cache_failure_clean);
+CALLBACK(retry_dns);
+CALLBACK(check_descriptor);
+CALLBACK(check_for_reachability_bw);
+CALLBACK(fetch_networkstatus);
+CALLBACK(dirvote_act);
+CALLBACK(expire_misc);
+CALLBACK(retry_listeners);
+CALLBACK(build_circuits);
+CALLBACK(expire_old_ciruits_serverside);
+CALLBACK(housekeeping);
+CALLBACK(check_dns_honesty);
+CALLBACK(write_bridge_ns);
+CALLBACK(check_fw_helper_app);
+CALLBACK(pt_configuration);
+CALLBACK(heartbeat);
+
+#undef CALLBACK
+#define CALLBACK(name) PERIODIC_EVENT(name)
+
 static periodic_event_item_t periodic_events[] = {
+  CALLBACK(rotate_onion_key),
+  CALLBACK(check_ed_keys),
+  CALLBACK(launch_descriptor_fetches),
+  CALLBACK(reset_descriptor_failures),
+  CALLBACK(fetch_bridge_descriptors),
+  CALLBACK(rotate_x509_certificate),
+  CALLBACK(add_entropy),
+  CALLBACK(enable_accounting),
+  CALLBACK(launch_reachability_tests),
+  CALLBACK(downrate_stability),
+  CALLBACK(save_stability),
+  CALLBACK(check_authority_cert),
+  CALLBACK(check_expired_networkstatus),
+  CALLBACK(write_stats_file),
+  CALLBACK(record_bridge_stats),
+  CALLBACK(clean_caches),
+  CALLBACK(rend_cache_failure_clean),
+  CALLBACK(retry_dns),
+  CALLBACK(check_descriptor),
+  CALLBACK(check_for_reachability_bw),
+  CALLBACK(fetch_networkstatus),
+  CALLBACK(dirvote_act),
+  CALLBACK(expire_misc),
+  CALLBACK(retry_listeners),
+  CALLBACK(build_circuits),
+  CALLBACK(expire_old_ciruits_serverside),
+  CALLBACK(housekeeping),
+  CALLBACK(check_dns_honesty),
+  CALLBACK(write_bridge_ns),
+  CALLBACK(check_fw_helper_app),
+  CALLBACK(pt_configuration),
+  CALLBACK(heartbeat),
   END_OF_PERIODIC_EVENTS
 };
+#undef CALLBACK
 
-typedef struct {
-  time_t last_rotated_x509_certificate;
-  time_t check_v3_certificate;
-  time_t check_listeners;
-  time_t download_networkstatus;
-  time_t try_getting_descriptors;
-  time_t reset_descriptor_failures;
-  time_t add_entropy;
-  time_t write_bridge_status_file;
-  time_t downrate_stability;
-  time_t save_stability;
-  time_t clean_caches;
-  time_t recheck_bandwidth;
-  time_t check_for_expired_networkstatus;
-  time_t write_stats_files;
-  time_t write_bridge_stats;
-  time_t check_port_forwarding;
-  time_t launch_reachability_tests;
-  time_t retry_dns_init;
-  time_t next_heartbeat;
-  time_t check_descriptor;
-  /** When do we next launch DNS wildcarding checks? */
-  time_t check_for_correct_dns;
-  /** When do we next make sure our Ed25519 keys aren't about to expire? */
-  time_t check_ed_keys;
-
-} time_to_t;
-
-static time_to_t time_to = {
-  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
+static periodic_event_item_t *check_descriptor_event=NULL;
+static periodic_event_item_t *fetch_networkstatus_event=NULL;
+static periodic_event_item_t *launch_descriptor_fetches_event=NULL;
+static periodic_event_item_t *check_dns_honesty_event=NULL;
 
-/** Reset all the time_to's so we'll do all our actions again as if we
+/** Reset all the periodic events so we'll do all our actions again as if we
  * just started up.
  * Useful if our clock just moved back a long time from the future,
  * so we don't wait until that future arrives again before acting.
@@ -1276,12 +1320,23 @@ void
 reset_all_main_loop_timers(void)
 {
   int i;
-  memset(&time_to, 0, sizeof(time_to));
   for (i = 0; periodic_events[i].name; ++i) {
     periodic_event_reschedule(&periodic_events[i]);
   }
 }
 
+/**DOCDOC*/
+static periodic_event_item_t *
+find_periodic_event(const char *name)
+{
+  int i;
+  for (i = 0; periodic_events[i].name; ++i) {
+    if (strcmp(name, periodic_events[i].name) == 0)
+      return &periodic_events[i];
+  }
+  return NULL;
+}
+
 /** DOCDOC */
 static void
 initialize_periodic_events_cb(evutil_socket_t fd, short events, void *data)
@@ -1302,6 +1357,14 @@ initialize_periodic_events(void)
   tor_assert(periodic_events_initialized == 0);
   periodic_events_initialized = 1;
 
+#define NAMED_CALLBACK(name) \
+  STMT_BEGIN name ## _event = find_periodic_event( #name ); STMT_END
+
+  NAMED_CALLBACK(check_descriptor);
+  NAMED_CALLBACK(fetch_networkstatus);
+  NAMED_CALLBACK(launch_descriptor_fetches);
+  NAMED_CALLBACK(check_dns_honesty);
+
   struct timeval one_second = { 1, 0 };
   event_base_once(tor_libevent_get_base(), -1, 0,
                   initialize_periodic_events_cb, NULL,
@@ -1325,7 +1388,8 @@ teardown_periodic_events(void)
 void
 reschedule_descriptor_update_check(void)
 {
-  time_to.check_descriptor = 0;
+  tor_assert(check_descriptor_event);
+  periodic_event_reschedule(check_descriptor_event);
 }
 
 /**
@@ -1335,8 +1399,22 @@ reschedule_descriptor_update_check(void)
 void
 reschedule_directory_downloads(void)
 {
-  time_to.download_networkstatus = 0;
-  time_to.try_getting_descriptors = 0;
+  tor_assert(fetch_networkstatus_event);
+  tor_assert(launch_descriptor_fetches_event);
+
+  periodic_event_reschedule(fetch_networkstatus_event);
+  periodic_event_reschedule(launch_descriptor_fetches_event);
+}
+
+static inline int
+safe_timer_diff(time_t now, time_t next)
+{
+  if (next > now) {
+    tor_assert(next - now <= INT_MAX);
+    return (int)(next - now);
+  } else {
+    return 1;
+  }
 }
 
 /** Perform regular maintenance tasks.  This function gets run once per
@@ -1345,13 +1423,6 @@ reschedule_directory_downloads(void)
 static void
 run_scheduled_events(time_t now)
 {
-  static int should_init_bridge_stats = 1;
-  const or_options_t *options = get_options();
-
-  int is_server = server_mode(options);
-  int i;
-  int have_dir_info;
-
   /* 0. See if we've been asked to shut down and our timeout has
    * expired; or if our bandwidth limits are exhausted and we
    * should hibernate; or if it's time to wake up from hibernation.
@@ -1368,13 +1439,21 @@ run_scheduled_events(time_t now)
 
   /* 0c. If we've deferred log messages for the controller, handle them now */
   flush_pending_log_callbacks();
+}
 
+static int
+rotate_onion_key_callback(time_t now, const or_options_t *options)
+{
   /* 1a. Every MIN_ONION_KEY_LIFETIME seconds, rotate the onion keys,
    *  shut down and restart all cpuworkers, and update the directory if
    *  necessary.
    */
-  if (is_server &&
-      get_onion_key_set_at()+MIN_ONION_KEY_LIFETIME < now) {
+  if (server_mode(options)) {
+    time_t rotation_time = get_onion_key_set_at()+MIN_ONION_KEY_LIFETIME;
+    if (rotation_time > now) {
+      return safe_timer_diff(now, rotation_time);
+    }
+
     log_info(LD_GENERAL,"Rotating onion key.");
     rotate_onion_key();
     cpuworkers_rotate_keyinfo();
@@ -1383,9 +1462,15 @@ run_scheduled_events(time_t now)
     }
     if (advertised_server_mode() && !options->DisableNetwork)
       router_upload_dir_desc_to_dirservers(0);
+    return MIN_ONION_KEY_LIFETIME;
   }
+  return -1;
+}
 
-  if (is_server && time_to.check_ed_keys < now) {
+static int
+check_ed_keys_callback(time_t now, const or_options_t *options)
+{
+  if (server_mode(options)) {
     if (should_make_new_ed_keys(options, now)) {
       if (load_ed_keys(options, now) < 0 ||
           generate_ed_link_cert(options, now)) {
@@ -1394,200 +1479,275 @@ run_scheduled_events(time_t now)
         exit(0);
       }
     }
-    time_to.check_ed_keys = now + 30;
+    return 30;
   }
+  return -1;
+}
 
-  if (!should_delay_dir_fetches(options, NULL) &&
-      time_to.try_getting_descriptors < now) {
-    update_all_descriptor_downloads(now);
-    update_extrainfo_downloads(now);
-    if (router_have_minimum_dir_info())
-      time_to.try_getting_descriptors = now + LAZY_DESCRIPTOR_RETRY_INTERVAL;
-    else
-      time_to.try_getting_descriptors = now + GREEDY_DESCRIPTOR_RETRY_INTERVAL;
-  }
+static int
+launch_descriptor_fetches_callback(time_t now, const or_options_t *options)
+{
+  if (should_delay_dir_fetches(options, NULL))
+    return -1;
 
-  if (time_to.reset_descriptor_failures < now) {
-    router_reset_descriptor_download_failures();
-    time_to.reset_descriptor_failures =
-      now + DESCRIPTOR_FAILURE_RESET_INTERVAL;
-  }
+  update_all_descriptor_downloads(now);
+  update_extrainfo_downloads(now);
+  if (router_have_minimum_dir_info())
+    return LAZY_DESCRIPTOR_RETRY_INTERVAL;
+  else
+    return  GREEDY_DESCRIPTOR_RETRY_INTERVAL;
+}
 
-  if (options->UseBridges && !options->DisableNetwork)
+static int
+reset_descriptor_failures_callback(time_t now, const or_options_t *options)
+{
+  (void)now;
+  (void)options;
+  router_reset_descriptor_download_failures();
+  return DESCRIPTOR_FAILURE_RESET_INTERVAL;
+}
+
+static int
+fetch_bridge_descriptors_callback(time_t now, const or_options_t *options)
+{
+  if (options->UseBridges && !options->DisableNetwork) {
     fetch_bridge_descriptors(options, now);
+    return 1;
+  }
+  return -1;
+}
+
+static int
+rotate_x509_certificate_callback(time_t now, const or_options_t *options)
+{
+  static int first = 1;
+  (void)now;
+  (void)options;
+  if (first) {
+    first = 0;
+    return MAX_SSL_KEY_LIFETIME_INTERNAL;
+  }
 
   /* 1b. Every MAX_SSL_KEY_LIFETIME_INTERNAL seconds, we change our
    * TLS context. */
-  if (!time_to.last_rotated_x509_certificate)
-    time_to.last_rotated_x509_certificate = now;
-  if (time_to.last_rotated_x509_certificate +
-      MAX_SSL_KEY_LIFETIME_INTERNAL < now) {
-    log_info(LD_GENERAL,"Rotating tls context.");
-    if (router_initialize_tls_context() < 0) {
-      log_warn(LD_BUG, "Error reinitializing TLS context");
-      /* XXX is it a bug here, that we just keep going? -RD */
-    }
-    time_to.last_rotated_x509_certificate = now;
-    /* We also make sure to rotate the TLS connections themselves if they've
-     * been up for too long -- but that's done via is_bad_for_new_circs in
-     * connection_run_housekeeping() above. */
+  log_info(LD_GENERAL,"Rotating tls context.");
+  if (router_initialize_tls_context() < 0) {
+    log_warn(LD_BUG, "Error reinitializing TLS context");
+    /* XXX is it a bug here, that we just keep going? -RD */
   }
 
-  if (time_to.add_entropy < now) {
-    if (time_to.add_entropy) {
-      /* We already seeded once, so don't die on failure. */
-      crypto_seed_rng();
-    }
-/** How often do we add more entropy to OpenSSL's RNG pool? */
+  /* We also make sure to rotate the TLS connections themselves if they've
+   * been up for too long -- but that's done via is_bad_for_new_circs in
+   * connection_run_housekeeping() above. */
+
+  return MAX_SSL_KEY_LIFETIME_INTERNAL;
+}
+
+static int
+add_entropy_callback(time_t now, const or_options_t *options)
+{
+  (void)now;
+  (void)options;
+  /* We already seeded once, so don't die on failure. */
+  crypto_seed_rng();
+
+  /** How often do we add more entropy to OpenSSL's RNG pool? */
 #define ENTROPY_INTERVAL (60*60)
-    time_to.add_entropy = now + ENTROPY_INTERVAL;
-  }
+  return ENTROPY_INTERVAL;
+}
 
+static int
+enable_accounting_callback(time_t now, const or_options_t *options)
+{
   /* 1c. If we have to change the accounting interval or record
    * bandwidth used in this accounting interval, do so. */
-  if (accounting_is_enabled(options))
+  if (accounting_is_enabled(options)) {
     accounting_run_housekeeping(now);
+    return 1;
+  }
+  return -1;
+}
 
-  if (time_to.launch_reachability_tests < now &&
-      (authdir_mode_tests_reachability(options)) &&
-       !net_is_disabled()) {
-    time_to.launch_reachability_tests = now + REACHABILITY_TEST_INTERVAL;
+static int
+launch_reachability_tests_callback(time_t now, const or_options_t *options)
+{
+  if (authdir_mode_tests_reachability(options) &&
+      !net_is_disabled()) {
     /* try to determine reachability of the other Tor relays */
     dirserv_test_reachability(now);
   }
+  return REACHABILITY_TEST_INTERVAL;
+}
 
+static int
+downrate_stability_callback(time_t now, const or_options_t *options)
+{
+  (void)options;
   /* 1d. Periodically, we discount older stability information so that new
    * stability info counts more, and save the stability information to disk as
    * appropriate. */
-  if (time_to.downrate_stability < now)
-    time_to.downrate_stability = rep_hist_downrate_old_runs(now);
+  time_t next = rep_hist_downrate_old_runs(now);
+  return safe_timer_diff(now, next);
+}
+
+static int
+save_stability_callback(time_t now, const or_options_t *options)
+{
   if (authdir_mode_tests_reachability(options)) {
-    if (time_to.save_stability < now) {
-      if (time_to.save_stability && rep_hist_record_mtbf_data(now, 1)<0) {
-        log_warn(LD_GENERAL, "Couldn't store mtbf data.");
-      }
-#define SAVE_STABILITY_INTERVAL (30*60)
-      time_to.save_stability = now + SAVE_STABILITY_INTERVAL;
+    if (rep_hist_record_mtbf_data(now, 1)<0) {
+      log_warn(LD_GENERAL, "Couldn't store mtbf data.");
     }
   }
+#define SAVE_STABILITY_INTERVAL (30*60)
+  return SAVE_STABILITY_INTERVAL;
+}
 
+static int
+check_authority_cert_callback(time_t now, const or_options_t *options)
+{
+  (void)now;
+  (void)options;
   /* 1e. Periodically, if we're a v3 authority, we check whether our cert is
    * close to expiring and warn the admin if it is. */
-  if (time_to.check_v3_certificate < now) {
-    v3_authority_check_key_expiry();
+  v3_authority_check_key_expiry();
 #define CHECK_V3_CERTIFICATE_INTERVAL (5*60)
-    time_to.check_v3_certificate = now + CHECK_V3_CERTIFICATE_INTERVAL;
-  }
+  return CHECK_V3_CERTIFICATE_INTERVAL;
+}
 
+static int
+check_expired_networkstatus_callback(time_t now, const or_options_t *options)
+{
+  (void)options;
   /* 1f. Check whether our networkstatus has expired.
    */
-  if (time_to.check_for_expired_networkstatus < now) {
-    networkstatus_t *ns = networkstatus_get_latest_consensus();
-    /*XXXX RD: This value needs to be the same as REASONABLY_LIVE_TIME in
-     * networkstatus_get_reasonably_live_consensus(), but that value is way
-     * way too high.  Arma: is the bridge issue there resolved yet? -NM */
+  networkstatus_t *ns = networkstatus_get_latest_consensus();
+  /*XXXX RD: This value needs to be the same as REASONABLY_LIVE_TIME in
+   * networkstatus_get_reasonably_live_consensus(), but that value is way
+   * way too high.  Arma: is the bridge issue there resolved yet? -NM */
 #define NS_EXPIRY_SLOP (24*60*60)
-    if (ns && ns->valid_until < now+NS_EXPIRY_SLOP &&
-        router_have_minimum_dir_info()) {
-      router_dir_info_changed();
-    }
-#define CHECK_EXPIRED_NS_INTERVAL (2*60)
-    time_to.check_for_expired_networkstatus = now + CHECK_EXPIRED_NS_INTERVAL;
+  if (ns && ns->valid_until < now+NS_EXPIRY_SLOP &&
+      router_have_minimum_dir_info()) {
+    router_dir_info_changed();
   }
+#define CHECK_EXPIRED_NS_INTERVAL (2*60)
+  return CHECK_EXPIRED_NS_INTERVAL;
+}
 
+static int
+write_stats_file_callback(time_t now, const or_options_t *options)
+{
   /* 1g. Check whether we should write statistics to disk.
    */
-  if (time_to.write_stats_files < now) {
 #define CHECK_WRITE_STATS_INTERVAL (60*60)
-    time_t next_time_to_write_stats_files = (time_to.write_stats_files > 0 ?
-           time_to.write_stats_files : now) + CHECK_WRITE_STATS_INTERVAL;
-    if (options->CellStatistics) {
-      time_t next_write =
-          rep_hist_buffer_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;
-    }
-    if (options->DirReqStatistics) {
-      time_t next_write = geoip_dirreq_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;
-    }
-    if (options->EntryStatistics) {
-      time_t next_write = geoip_entry_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;
-    }
-    if (options->HiddenServiceStatistics) {
-      time_t next_write = rep_hist_hs_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;
-    }
-    if (options->ExitPortStatistics) {
-      time_t next_write = rep_hist_exit_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;
-    }
-    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;
-    }
-    if (options->BridgeAuthoritativeDir) {
-      time_t next_write = rep_hist_desc_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;
+  time_t next_time_to_write_stats_files = now + CHECK_WRITE_STATS_INTERVAL;
+  if (options->CellStatistics) {
+    time_t next_write =
+      rep_hist_buffer_stats_write(now);
+    if (next_write && next_write < next_time_to_write_stats_files)
+      next_time_to_write_stats_files = next_write;
+  }
+  if (options->DirReqStatistics) {
+    time_t next_write = geoip_dirreq_stats_write(now);
+    if (next_write && next_write < next_time_to_write_stats_files)
+      next_time_to_write_stats_files = next_write;
+  }
+  if (options->EntryStatistics) {
+    time_t next_write = geoip_entry_stats_write(now);
+    if (next_write && next_write < next_time_to_write_stats_files)
+      next_time_to_write_stats_files = next_write;
+  }
+  if (options->HiddenServiceStatistics) {
+    time_t next_write = rep_hist_hs_stats_write(now);
+    if (next_write && next_write < next_time_to_write_stats_files)
+      next_time_to_write_stats_files = next_write;
+  }
+  if (options->ExitPortStatistics) {
+    time_t next_write = rep_hist_exit_stats_write(now);
+    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(now);
+    if (next_write && next_write < next_time_to_write_stats_files)
+      next_time_to_write_stats_files = next_write;
   }
+  if (options->BridgeAuthoritativeDir) {
+    time_t next_write = rep_hist_desc_stats_write(now);
+    if (next_write && next_write < next_time_to_write_stats_files)
+      next_time_to_write_stats_files = next_write;
+  }
+
+  return safe_timer_diff(now, next_time_to_write_stats_files);
+}
+
+static int
+record_bridge_stats_callback(time_t now, const or_options_t *options)
+{
+  static int should_init_bridge_stats = 1;
 
   /* 1h. Check whether we should write bridge statistics to disk.
    */
   if (should_record_bridge_info(options)) {
-    if (time_to.write_bridge_stats < now) {
-      if (should_init_bridge_stats) {
-        /* (Re-)initialize bridge statistics. */
+    if (should_init_bridge_stats) {
+      /* (Re-)initialize bridge statistics. */
         geoip_bridge_stats_init(now);
-        time_to.write_bridge_stats = now + WRITE_STATS_INTERVAL;
         should_init_bridge_stats = 0;
-      } else {
-        /* Possibly write bridge statistics to disk and ask when to write
-         * them next time. */
-        time_to.write_bridge_stats = geoip_bridge_stats_write(
-                                           time_to.write_bridge_stats);
-      }
+        return WRITE_STATS_INTERVAL;
+    } else {
+      /* Possibly write bridge statistics to disk and ask when to write
+       * them next time. */
+      time_t next = geoip_bridge_stats_write(now);
+      return safe_timer_diff(now, next);
     }
   } else if (!should_init_bridge_stats) {
     /* Bridge mode was turned off. Ensure that stats are re-initialized
      * next time bridge mode is turned on. */
     should_init_bridge_stats = 1;
   }
+  return -1;
+}
 
+static int
+clean_caches_callback(time_t now, const or_options_t *options)
+{
   /* Remove old information from rephist and the rend cache. */
-  if (time_to.clean_caches < now) {
-    rep_history_clean(now - options->RephistTrackTime);
-    rend_cache_clean(now, REND_CACHE_TYPE_CLIENT);
-    rend_cache_clean(now, REND_CACHE_TYPE_SERVICE);
-    rend_cache_clean_v2_descs_as_dir(now, 0);
-    microdesc_cache_rebuild(NULL, 0);
+  rep_history_clean(now - options->RephistTrackTime);
+  rend_cache_clean(now, REND_CACHE_TYPE_CLIENT);
+  rend_cache_clean(now, REND_CACHE_TYPE_SERVICE);
+  rend_cache_clean_v2_descs_as_dir(now, 0);
+  microdesc_cache_rebuild(NULL, 0);
 #define CLEAN_CACHES_INTERVAL (30*60)
-    time_to.clean_caches = now + CLEAN_CACHES_INTERVAL;
-  }
+  return CLEAN_CACHES_INTERVAL;
+}
+
+static int
+rend_cache_failure_clean_callback(time_t now, const or_options_t *options)
+{
+  (void)options;
   /* We don't keep entries that are more than five minutes old so we try to
    * clean it as soon as we can since we want to make sure the client waits
    * as little as possible for reachability reasons. */
   rend_cache_failure_clean(now);
+  return 1;
+}
 
+static int
+retry_dns_callback(time_t now, const or_options_t *options)
+{
+  (void)now;
 #define RETRY_DNS_INTERVAL (10*60)
   /* 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 (is_server && has_dns_init_failed())
-      dns_init();
-  }
+  if (server_mode(options) && has_dns_init_failed())
+    dns_init();
+  return RETRY_DNS_INTERVAL;
+}
 
   /* 2. Periodically, we consider force-uploading our descriptor
    * (if we've passed our internal checks). */
 
+static int
+check_descriptor_callback(time_t now, const or_options_t *options)
+{
 /** How often do we check whether part of our router info has changed in a
  * way that would require an upload? That includes checking whether our IP
  * address has changed. */
@@ -1595,60 +1755,91 @@ run_scheduled_events(time_t now)
 
   /* 2b. Once per minute, regenerate and upload the descriptor if the old
    * one is inaccurate. */
-  if (time_to.check_descriptor < now && !options->DisableNetwork) {
-    static int dirport_reachability_count = 0;
-    time_to.check_descriptor = now + CHECK_DESCRIPTOR_INTERVAL;
+  if (!options->DisableNetwork) {
     check_descriptor_bandwidth_changed(now);
     check_descriptor_ipaddress_changed(now);
     mark_my_descriptor_dirty_if_too_old(now);
     consider_publishable_server(0);
-    /* also, check religiously for reachability, if it's within the first
-     * 20 minutes of our uptime. */
-    if (is_server &&
-        (have_completed_a_circuit() || !any_predicted_circuits(now)) &&
-        !we_are_hibernating()) {
-      if (stats_n_seconds_working < TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) {
-        consider_testing_reachability(1, dirport_reachability_count==0);
-        if (++dirport_reachability_count > 5)
-          dirport_reachability_count = 0;
-      } else if (time_to.recheck_bandwidth < now) {
-        /* 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. */
-        const routerinfo_t *me = router_get_my_routerinfo();
-        if (time_to.recheck_bandwidth && me &&
-            me->bandwidthcapacity < me->bandwidthrate &&
-            me->bandwidthcapacity < 51200) {
-          reset_bandwidth_test();
-        }
-#define BANDWIDTH_RECHECK_INTERVAL (12*60*60)
-        time_to.recheck_bandwidth = now + BANDWIDTH_RECHECK_INTERVAL;
-      }
-    }
-
     /* If any networkstatus documents are no longer recent, we need to
      * update all the descriptors' running status. */
     /* Remove dead routers. */
+    /* XXXX This doesn't belong here, but it was here in the pre-
+     * XXXX refactoring code. */
     routerlist_remove_old_routers();
   }
 
+  return CHECK_DESCRIPTOR_INTERVAL;
+}
+
+static int
+check_for_reachability_bw_callback(time_t now, const or_options_t *options)
+{
+  /* XXXX This whole thing was stuck in the middle of what is now
+   * XXXX check_descriptor_callback.  I'm not sure it's right. */
+
+  static int dirport_reachability_count = 0;
+  /* also, check religiously for reachability, if it's within the first
+   * 20 minutes of our uptime. */
+  if (server_mode(options) &&
+      (have_completed_a_circuit() || !any_predicted_circuits(now)) &&
+      !we_are_hibernating()) {
+    if (stats_n_seconds_working < TIMEOUT_UNTIL_UNREACHABILITY_COMPLAINT) {
+      consider_testing_reachability(1, dirport_reachability_count==0);
+      if (++dirport_reachability_count > 5)
+        dirport_reachability_count = 0;
+      return 1;
+    } else {
+      /* 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. */
+      const routerinfo_t *me = router_get_my_routerinfo();
+      static int first_time = 1;
+      if (!first_time && me &&
+          me->bandwidthcapacity < me->bandwidthrate &&
+          me->bandwidthcapacity < 51200) {
+        reset_bandwidth_test();
+      }
+      first_time = 0;
+#define BANDWIDTH_RECHECK_INTERVAL (12*60*60)
+      return BANDWIDTH_RECHECK_INTERVAL;
+    }
+  }
+  return CHECK_DESCRIPTOR_INTERVAL;
+}
+
+static int
+fetch_networkstatus_callback(time_t now, const or_options_t *options)
+{
   /* 2c. Every minute (or every second if TestingTorNetwork), check
    * whether we want to download any networkstatus documents. */
 
-/* How often do we check whether we should download network status
- * documents? */
+  /* How often do we check whether we should download network status
+   * documents? */
 #define networkstatus_dl_check_interval(o) ((o)->TestingTorNetwork ? 1 : 60)
 
-  if (!should_delay_dir_fetches(options, NULL) &&
-      time_to.download_networkstatus < now) {
-    time_to.download_networkstatus =
-      now + networkstatus_dl_check_interval(options);
-    update_networkstatus_downloads(now);
-  }
+  if (should_delay_dir_fetches(options, NULL))
+    return -1;
+
+  update_networkstatus_downloads(now);
+  return networkstatus_dl_check_interval(options);
+}
 
+static int
+dirvote_act_callback(time_t now, const or_options_t *options)
+{
   /* 2c. Let directory voting happen. */
-  if (authdir_mode_v3(options))
+  if (authdir_mode_v3(options)) {
     dirvote_act(options, now);
+    return 1;
+  }
+  return -1;
+}
+
+static int
+expire_misc_callback(time_t now, const or_options_t *options)
+{
+  (void)now;
+  (void)options;
 
   /* 3a. Every second, we examine pending circuits and prune the
    *    ones which have been pending for more than a few seconds.
@@ -1670,28 +1861,54 @@ run_scheduled_events(time_t now)
    */
   connection_expire_held_open();
 
+  return 1;
+}
+
+static int
+retry_listeners_callback(time_t now, const or_options_t *options)
+{
+  (void)now;
+  (void)options;
   /* 3d. And every 60 seconds, we relaunch listeners if any died. */
-  if (!net_is_disabled() && time_to.check_listeners < now) {
+  if (!net_is_disabled()) {
     retry_all_listeners(NULL, NULL, 0);
-    time_to.check_listeners = now+60;
+    return 60;
   }
+  return -1;
+}
 
+static int
+build_circuits_callback(time_t now, const or_options_t *options)
+{
+  (void)options;
   /* 4. Every second, we try a new circuit if there are no valid
    *    circuits. Every NewCircuitPeriod seconds, we expire circuits
    *    that became dirty more than MaxCircuitDirtiness seconds ago,
    *    and we make a new circ if there are no clean circuits.
    */
-  have_dir_info = router_have_minimum_dir_info();
+  const int have_dir_info = router_have_minimum_dir_info();
   if (have_dir_info && !net_is_disabled()) {
     circuit_build_needed_circs(now);
   } else {
     circuit_expire_old_circs_as_needed(now);
   }
+  return 1;
+}
 
-  /* every 10 seconds, but not at the same second as other such events */
-  if (now % 10 == 5)
-    circuit_expire_old_circuits_serverside(now);
+static int
+expire_old_ciruits_serverside_callback(time_t now, const or_options_t *options)
+{
+  (void)options;
+  /* every 11 seconds, so not usually the same second as other such events */
+  circuit_expire_old_circuits_serverside(now);
+  return 11;
+}
 
+static int
+housekeeping_callback(time_t now, const or_options_t *options)
+{
+  (void)options;
+  int i;
   /* 5. We do housekeeping for each connection... */
   connection_or_set_bad_connections(NULL, 0);
   for (i=0;i<smartlist_len(connection_array);i++) {
@@ -1721,59 +1938,88 @@ run_scheduled_events(time_t now)
   channel_run_cleanup();
   channel_listener_run_cleanup();
 
+  return 1;
+}
+
+static int
+check_dns_honesty_callback(time_t now, const or_options_t *options)
+{
+  (void)now;
   /* 9. and if we're an exit node, check whether our DNS is telling stories
    * to us. */
-  if (!net_is_disabled() &&
-      public_server_mode(options) &&
-      time_to.check_for_correct_dns < now &&
-      ! router_my_exit_policy_is_reject_star()) {
-    if (!time_to.check_for_correct_dns) {
-      time_to.check_for_correct_dns =
-        crypto_rand_time_range(now + 60, now + 180);
-    } else {
-      dns_launch_correctness_checks();
-      time_to.check_for_correct_dns = now + 12*3600 +
-        crypto_rand_int(12*3600);
-    }
+  if (net_is_disabled() ||
+      ! public_server_mode(options) ||
+      router_my_exit_policy_is_reject_star())
+    return -1;
+
+  static int first_time = 1;
+  if (first_time) {
+    /* Don't launch right when we start */
+    first_time = 0;
+    return crypto_rand_int_range(60, 180);
   }
 
+  dns_launch_correctness_checks();
+  return 12*3600 + crypto_rand_int(12*3600);
+}
+
+static int
+write_bridge_ns_callback(time_t now, const or_options_t *options)
+{
   /* 10. write bridge networkstatus file to disk */
-  if (options->BridgeAuthoritativeDir &&
-      time_to.write_bridge_status_file < now) {
+  if (options->BridgeAuthoritativeDir) {
     networkstatus_dump_bridge_status_to_file(now);
 #define BRIDGE_STATUSFILE_INTERVAL (30*60)
-    time_to.write_bridge_status_file = now+BRIDGE_STATUSFILE_INTERVAL;
+     return BRIDGE_STATUSFILE_INTERVAL;
   }
+  return -1;
+}
 
+static int
+check_fw_helper_app_callback(time_t now, const or_options_t *options)
+{
+  if (net_is_disabled() ||
+      ! server_mode(options) ||
+      ! options->PortForwarding) {
+    return -1;
+  }
   /* 11. check the port forwarding app */
-  if (!net_is_disabled() &&
-      time_to.check_port_forwarding < now &&
-      options->PortForwarding &&
-      is_server) {
+
 #define PORT_FORWARDING_CHECK_INTERVAL 5
-    smartlist_t *ports_to_forward = get_list_of_ports_to_forward();
-    if (ports_to_forward) {
-      tor_check_port_forwarding(options->PortForwardingHelper,
-                                ports_to_forward,
-                                now);
-
-      SMARTLIST_FOREACH(ports_to_forward, char *, cp, tor_free(cp));
-      smartlist_free(ports_to_forward);
-    }
-    time_to.check_port_forwarding = now+PORT_FORWARDING_CHECK_INTERVAL;
+  smartlist_t *ports_to_forward = get_list_of_ports_to_forward();
+  if (ports_to_forward) {
+    tor_check_port_forwarding(options->PortForwardingHelper,
+                              ports_to_forward,
+                              now);
+
+    SMARTLIST_FOREACH(ports_to_forward, char *, cp, tor_free(cp));
+    smartlist_free(ports_to_forward);
   }
+  return PORT_FORWARDING_CHECK_INTERVAL;
+}
 
+static int
+pt_configuration_callback(time_t now, const or_options_t *options)
+{
+  (void)now;
+  (void)options;
   /* 11b. check pending unconfigured managed proxies */
   if (!net_is_disabled() && pt_proxies_configuration_pending())
     pt_configure_remaining_proxies();
+  return 1;
+}
 
+static int
+heartbeat_callback(time_t now, const or_options_t *options)
+{
+  static int first = 1;
   /* 12. write the heartbeat message */
-  if (options->HeartbeatPeriod &&
-      time_to.next_heartbeat <= now) {
-    if (time_to.next_heartbeat) /* don't log the first heartbeat */
-      log_heartbeat(now);
-    time_to.next_heartbeat = now+options->HeartbeatPeriod;
+  if (first) {
+    first = 0;
+  } else {
+    log_heartbeat(now);
   }
+  return options->HeartbeatPeriod;
 }
 
 /** Timer: used to invoke second_elapsed_callback() once per second. */
@@ -1995,7 +2241,8 @@ dns_servers_relaunch_checks(void)
 {
   if (server_mode(get_options())) {
     dns_reset_correctness_checks();
-    time_to.check_for_correct_dns = 0;
+    tor_assert(check_dns_honesty_event);
+    periodic_event_reschedule(check_dns_honesty_event);
   }
 }
 





More information about the tor-commits mailing list