summaryrefslogtreecommitdiff
path: root/src/or/main.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/main.c')
-rw-r--r--src/or/main.c105
1 files changed, 91 insertions, 14 deletions
diff --git a/src/or/main.c b/src/or/main.c
index 47275c84f5..b492166f87 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -59,6 +59,7 @@
#include "circuitbuild.h"
#include "circuitlist.h"
#include "circuituse.h"
+#include "circuitmux_ewma.h"
#include "command.h"
#include "compress.h"
#include "config.h"
@@ -72,7 +73,6 @@
#include "crypto_s2k.h"
#include "directory.h"
#include "dirserv.h"
-#include "dirvote.h"
#include "dns.h"
#include "dnsserv.h"
#include "dos.h"
@@ -103,7 +103,7 @@
#include "routerlist.h"
#include "routerparse.h"
#include "scheduler.h"
-#include "shared_random.h"
+#include "dirauth/shared_random.h"
#include "statefile.h"
#include "status.h"
#include "tor_api.h"
@@ -118,6 +118,8 @@
#include <event2/event.h>
+#include "dirauth/dirvote.h"
+
#ifdef HAVE_SYSTEMD
# if defined(__COVERITY__) && !defined(__INCLUDE_LEVEL__)
/* Systemd's use of gcc's __INCLUDE_LEVEL__ extension macro appears to confuse
@@ -1352,6 +1354,7 @@ CALLBACK(check_for_reachability_bw);
CALLBACK(check_onion_keys_expiry_time);
CALLBACK(clean_caches);
CALLBACK(clean_consdiffmgr);
+CALLBACK(dirvote);
CALLBACK(downrate_stability);
CALLBACK(expire_old_ciruits_serverside);
CALLBACK(fetch_networkstatus);
@@ -1367,6 +1370,7 @@ CALLBACK(retry_listeners);
CALLBACK(rotate_onion_key);
CALLBACK(rotate_x509_certificate);
CALLBACK(save_stability);
+CALLBACK(save_state);
CALLBACK(write_bridge_ns);
CALLBACK(write_stats_file);
@@ -1388,6 +1392,7 @@ STATIC periodic_event_item_t periodic_events[] = {
CALLBACK(reset_padding_counts, PERIODIC_EVENT_ROLE_ALL, 0),
CALLBACK(retry_listeners, PERIODIC_EVENT_ROLE_ALL,
PERIODIC_EVENT_FLAG_NEED_NET),
+ CALLBACK(save_state, PERIODIC_EVENT_ROLE_ALL, 0),
CALLBACK(rotate_x509_certificate, PERIODIC_EVENT_ROLE_ALL, 0),
CALLBACK(write_stats_file, PERIODIC_EVENT_ROLE_ALL, 0),
@@ -1398,7 +1403,6 @@ STATIC periodic_event_item_t periodic_events[] = {
CALLBACK(check_for_reachability_bw, PERIODIC_EVENT_ROLE_ROUTER,
PERIODIC_EVENT_FLAG_NEED_NET),
CALLBACK(check_onion_keys_expiry_time, PERIODIC_EVENT_ROLE_ROUTER, 0),
- CALLBACK(clean_consdiffmgr, PERIODIC_EVENT_ROLE_ROUTER, 0),
CALLBACK(expire_old_ciruits_serverside, PERIODIC_EVENT_ROLE_ROUTER,
PERIODIC_EVENT_FLAG_NEED_NET),
CALLBACK(retry_dns, PERIODIC_EVENT_ROLE_ROUTER, 0),
@@ -1412,6 +1416,7 @@ STATIC periodic_event_item_t periodic_events[] = {
/* Directory authority only. */
CALLBACK(check_authority_cert, PERIODIC_EVENT_ROLE_DIRAUTH, 0),
+ CALLBACK(dirvote, PERIODIC_EVENT_ROLE_DIRAUTH, PERIODIC_EVENT_FLAG_NEED_NET),
/* Relay only. */
CALLBACK(check_canonical_channels, PERIODIC_EVENT_ROLE_RELAY,
@@ -1432,6 +1437,9 @@ STATIC periodic_event_item_t periodic_events[] = {
/* Bridge Authority only. */
CALLBACK(write_bridge_ns, PERIODIC_EVENT_ROLE_BRIDGEAUTH, 0),
+ /* Directory server only. */
+ CALLBACK(clean_consdiffmgr, PERIODIC_EVENT_ROLE_DIRSERVER, 0),
+
END_OF_PERIODIC_EVENTS
};
#undef CALLBACK
@@ -1441,9 +1449,11 @@ STATIC periodic_event_item_t periodic_events[] = {
* can access them by name. We also keep them inside periodic_events[]
* so that we can implement "reset all timers" in a reasonable way. */
static periodic_event_item_t *check_descriptor_event=NULL;
+static periodic_event_item_t *dirvote_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;
+static periodic_event_item_t *save_state_event=NULL;
/** Reset all the periodic events so we'll do all our actions again as if we
* just started up.
@@ -1488,6 +1498,7 @@ get_my_roles(const or_options_t *options)
int is_bridgeauth = authdir_mode_bridge(options);
int is_hidden_service = !!hs_service_get_num_services() ||
!!rend_num_services();
+ int is_dirserver = dir_server_mode(options);
if (is_bridge) roles |= PERIODIC_EVENT_ROLE_BRIDGE;
if (is_client) roles |= PERIODIC_EVENT_ROLE_CLIENT;
@@ -1495,6 +1506,7 @@ get_my_roles(const or_options_t *options)
if (is_dirauth) roles |= PERIODIC_EVENT_ROLE_DIRAUTH;
if (is_bridgeauth) roles |= PERIODIC_EVENT_ROLE_BRIDGEAUTH;
if (is_hidden_service) roles |= PERIODIC_EVENT_ROLE_HS_SERVICE;
+ if (is_dirserver) roles |= PERIODIC_EVENT_ROLE_DIRSERVER;
return roles;
}
@@ -1537,9 +1549,11 @@ initialize_periodic_events(void)
STMT_BEGIN name ## _event = find_periodic_event( #name ); STMT_END
NAMED_CALLBACK(check_descriptor);
+ NAMED_CALLBACK(dirvote);
NAMED_CALLBACK(fetch_networkstatus);
NAMED_CALLBACK(launch_descriptor_fetches);
NAMED_CALLBACK(check_dns_honesty);
+ NAMED_CALLBACK(save_state);
struct timeval one_second = { 1, 0 };
initialize_periodic_events_event = tor_evtimer_new(
@@ -1565,6 +1579,13 @@ rescan_periodic_events(const or_options_t *options)
{
tor_assert(options);
+ /* Avoid scanning the event list if we haven't initialized it yet. This is
+ * particularly useful for unit tests in order to avoid initializing main
+ * loop events everytime. */
+ if (!periodic_events_initialized) {
+ return;
+ }
+
int roles = get_my_roles(options);
for (int i = 0; periodic_events[i].name; ++i) {
@@ -1610,8 +1631,9 @@ periodic_events_on_new_options(const or_options_t *options)
void
reschedule_descriptor_update_check(void)
{
- tor_assert(check_descriptor_event);
- periodic_event_reschedule(check_descriptor_event);
+ if (check_descriptor_event) {
+ periodic_event_reschedule(check_descriptor_event);
+ }
}
/**
@@ -1705,10 +1727,6 @@ run_scheduled_events(time_t now)
accounting_run_housekeeping(now);
}
- if (authdir_mode_v3(options)) {
- dirvote_act(options, now);
- }
-
/* 3a. Every second, we examine pending circuits and prune the
* ones which have been pending for more than a few seconds.
* We do this before step 4, so it can try building more if
@@ -1749,10 +1767,6 @@ run_scheduled_events(time_t now)
run_connection_housekeeping(i, now);
}
- /* 8b. And if anything in our state is ready to get flushed to disk, we
- * flush it. */
- or_state_save(now);
-
/* 11b. check pending unconfigured managed proxies */
if (!net_is_disabled() && pt_proxies_configuration_pending())
pt_configure_remaining_proxies();
@@ -1965,6 +1979,40 @@ check_authority_cert_callback(time_t now, const or_options_t *options)
}
/**
+ * Scheduled callback: Run directory-authority voting functionality.
+ *
+ * The schedule is a bit complicated here, so dirvote_act() manages the
+ * schedule itself.
+ **/
+static int
+dirvote_callback(time_t now, const or_options_t *options)
+{
+ if (!authdir_mode_v3(options)) {
+ tor_assert_nonfatal_unreached();
+ return 3600;
+ }
+
+ time_t next = dirvote_act(options, now);
+ if (BUG(next == TIME_MAX)) {
+ /* This shouldn't be returned unless we called dirvote_act() without
+ * being an authority. If it happens, maybe our configuration will
+ * fix itself in an hour or so? */
+ return 3600;
+ }
+ return safe_timer_diff(now, next);
+}
+
+/** Reschedule the directory-authority voting event. Run this whenever the
+ * schedule has changed. */
+void
+reschedule_dirvote(const or_options_t *options)
+{
+ if (periodic_events_initialized && authdir_mode_v3(options)) {
+ periodic_event_reschedule(dirvote_event);
+ }
+}
+
+/**
* Periodic callback: If our consensus is too old, recalculate whether
* we can actually use it.
*/
@@ -1987,6 +2035,34 @@ check_expired_networkstatus_callback(time_t now, const or_options_t *options)
}
/**
+ * Scheduled callback: Save the state file to disk if appropriate.
+ */
+static int
+save_state_callback(time_t now, const or_options_t *options)
+{
+ (void) options;
+ (void) or_state_save(now); // only saves if appropriate
+ const time_t next_write = get_or_state()->next_write;
+ if (next_write == TIME_MAX) {
+ return 86400;
+ }
+ return safe_timer_diff(now, next_write);
+}
+
+/** Reschedule the event for saving the state file.
+ *
+ * Run this when the state becomes dirty. */
+void
+reschedule_or_state_save(void)
+{
+ if (save_state_event == NULL) {
+ /* This can happen early on during startup. */
+ return;
+ }
+ periodic_event_reschedule(save_state_event);
+}
+
+/**
* Periodic callback: Write statistics to disk if appropriate.
*/
static int
@@ -2338,7 +2414,7 @@ static int
clean_consdiffmgr_callback(time_t now, const or_options_t *options)
{
(void)now;
- if (server_mode(options)) {
+ if (dir_server_mode(options)) {
consdiffmgr_cleanup();
}
return CDM_CLEAN_CALLBACK_INTERVAL;
@@ -3529,6 +3605,7 @@ tor_free_all(int postfork)
consdiffmgr_free_all();
hs_free_all();
dos_free_all();
+ circuitmux_ewma_free_all();
if (!postfork) {
config_free_all();
or_state_free_all();