mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
Document main.c a lot better
This commit is contained in:
parent
172b124006
commit
dc79504e2a
165
src/or/main.c
165
src/or/main.c
@ -8,6 +8,42 @@
|
||||
* \file main.c
|
||||
* \brief Toplevel module. Handles signals, multiplexes between
|
||||
* connections, implements main loop, and drives scheduled events.
|
||||
*
|
||||
* For the main loop itself; see run_main_loop_once(). It invokes the rest of
|
||||
* Tor mostly through Libevent callbacks. Libevent callbacks can happen when
|
||||
* a timer elapses, a signal is received, a socket is ready to read or write,
|
||||
* or an event is manually activated.
|
||||
*
|
||||
* Most events in Tor are driven from these callbacks:
|
||||
* <ul>
|
||||
* <li>conn_read_callback() and conn_write_callback() here, which are
|
||||
* invoked when a socket is ready to read or write respectively.
|
||||
* <li>signal_callback(), which handles incoming signals.
|
||||
* </ul>
|
||||
* Other events are used for specific purposes, or for building more complex
|
||||
* control structures. If you search for usage of tor_libevent_new(), you
|
||||
* will find all the events that we construct in Tor.
|
||||
*
|
||||
* Tor has numerous housekeeping operations that need to happen
|
||||
* regularly. They are handled in different ways:
|
||||
* <ul>
|
||||
* <li>The most frequent operations are handled after every read or write
|
||||
* event, at the end of connection_handle_read() and
|
||||
* connection_handle_write().
|
||||
*
|
||||
* <li>The next most frequent operations happen after each invocation of the
|
||||
* main loop, in run_main_loop_once().
|
||||
*
|
||||
* <li>Once per second, we run all of the operations listed in
|
||||
* second_elapsed_callback(), and in its child, run_scheduled_events().
|
||||
*
|
||||
* <li>Once-a-second operations are handled in second_elapsed_callback().
|
||||
*
|
||||
* <li>More infrequent operations take place based on the periodic event
|
||||
* driver in periodic.c . These are stored in the periodic_events[]
|
||||
* table.
|
||||
* </ul>
|
||||
*
|
||||
**/
|
||||
|
||||
#define MAIN_PRIVATE
|
||||
@ -1408,13 +1444,13 @@ run_scheduled_events(time_t now)
|
||||
pt_configure_remaining_proxies();
|
||||
}
|
||||
|
||||
/* Periodic callback: Every MIN_ONION_KEY_LIFETIME seconds, rotate the onion
|
||||
* keys, shut down and restart all cpuworkers, and update our descriptor if
|
||||
* necessary.
|
||||
*/
|
||||
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 (server_mode(options)) {
|
||||
time_t rotation_time = get_onion_key_set_at()+MIN_ONION_KEY_LIFETIME;
|
||||
if (rotation_time > now) {
|
||||
@ -1434,6 +1470,9 @@ rotate_onion_key_callback(time_t now, const or_options_t *options)
|
||||
return PERIODIC_EVENT_NO_UPDATE;
|
||||
}
|
||||
|
||||
/* Periodic callback: Every 30 seconds, check whether it's time to make new
|
||||
* Ed25519 subkeys.
|
||||
*/
|
||||
static int
|
||||
check_ed_keys_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1451,6 +1490,11 @@ check_ed_keys_callback(time_t now, const or_options_t *options)
|
||||
return PERIODIC_EVENT_NO_UPDATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic callback: Every {LAZY,GREEDY}_DESCRIPTOR_RETRY_INTERVAL,
|
||||
* see about fetching descriptors, microdescriptors, and extrainfo
|
||||
* documents.
|
||||
*/
|
||||
static int
|
||||
launch_descriptor_fetches_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1465,6 +1509,10 @@ launch_descriptor_fetches_callback(time_t now, const or_options_t *options)
|
||||
return GREEDY_DESCRIPTOR_RETRY_INTERVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic event: Rotate our X.509 certificates and TLS keys once every
|
||||
* MAX_SSL_KEY_LIFETIME_INTERNAL.
|
||||
*/
|
||||
static int
|
||||
rotate_x509_certificate_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1490,6 +1538,10 @@ rotate_x509_certificate_callback(time_t now, const or_options_t *options)
|
||||
return MAX_SSL_KEY_LIFETIME_INTERNAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic callback: once an hour, grab some more entropy from the
|
||||
* kernel and feed it to our CSPRNG.
|
||||
**/
|
||||
static int
|
||||
add_entropy_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1506,6 +1558,10 @@ add_entropy_callback(time_t now, const or_options_t *options)
|
||||
return ENTROPY_INTERVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic callback: if we're an authority, make sure we test
|
||||
* the routers on the network for reachability.
|
||||
*/
|
||||
static int
|
||||
launch_reachability_tests_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1517,6 +1573,10 @@ launch_reachability_tests_callback(time_t now, const or_options_t *options)
|
||||
return REACHABILITY_TEST_INTERVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic callback: if we're an authority, discount the stability
|
||||
* information (and other rephist information) that's older.
|
||||
*/
|
||||
static int
|
||||
downrate_stability_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1528,6 +1588,10 @@ downrate_stability_callback(time_t now, const or_options_t *options)
|
||||
return safe_timer_diff(now, next);
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic callback: if we're an authority, record our measured stability
|
||||
* information from rephist in an mtbf file.
|
||||
*/
|
||||
static int
|
||||
save_stability_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1540,6 +1604,10 @@ save_stability_callback(time_t now, const or_options_t *options)
|
||||
return SAVE_STABILITY_INTERVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic callback: if we're an authority, check on our authority
|
||||
* certificate (the one that authenticates our authority signing key).
|
||||
*/
|
||||
static int
|
||||
check_authority_cert_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1552,6 +1620,10 @@ check_authority_cert_callback(time_t now, const or_options_t *options)
|
||||
return CHECK_V3_CERTIFICATE_INTERVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic callback: If our consensus is too old, recalculate whether
|
||||
* we can actually use it.
|
||||
*/
|
||||
static int
|
||||
check_expired_networkstatus_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1571,6 +1643,9 @@ check_expired_networkstatus_callback(time_t now, const or_options_t *options)
|
||||
return CHECK_EXPIRED_NS_INTERVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic callback: Write statistics to disk if appropriate.
|
||||
*/
|
||||
static int
|
||||
write_stats_file_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1618,6 +1693,9 @@ write_stats_file_callback(time_t now, const or_options_t *options)
|
||||
return safe_timer_diff(now, next_time_to_write_stats_files);
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic callback: Write bridge statistics to disk if appropriate.
|
||||
*/
|
||||
static int
|
||||
record_bridge_stats_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1645,6 +1723,9 @@ record_bridge_stats_callback(time_t now, const or_options_t *options)
|
||||
return PERIODIC_EVENT_NO_UPDATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic callback: Clean in-memory caches every once in a while
|
||||
*/
|
||||
static int
|
||||
clean_caches_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1658,6 +1739,10 @@ clean_caches_callback(time_t now, const or_options_t *options)
|
||||
return CLEAN_CACHES_INTERVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic callback: Clean the cache of failed hidden service lookups
|
||||
* frequently frequently.
|
||||
*/
|
||||
static int
|
||||
rend_cache_failure_clean_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1669,20 +1754,21 @@ rend_cache_failure_clean_callback(time_t now, const or_options_t *options)
|
||||
return 30;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic callback: If we're a server and initializing dns failed, retry.
|
||||
*/
|
||||
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 (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). */
|
||||
|
||||
/** Periodic callback: consider rebuilding or and re-uploading our descriptor
|
||||
* (if we've passed our internal checks). */
|
||||
static int
|
||||
check_descriptor_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1709,6 +1795,11 @@ check_descriptor_callback(time_t now, const or_options_t *options)
|
||||
return CHECK_DESCRIPTOR_INTERVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic callback: check whether we're reachable (as a relay), and
|
||||
* whether our bandwidth has changed enough that we need to
|
||||
* publish a new descriptor.
|
||||
*/
|
||||
static int
|
||||
check_for_reachability_bw_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1745,13 +1836,13 @@ check_for_reachability_bw_callback(time_t now, const or_options_t *options)
|
||||
return CHECK_DESCRIPTOR_INTERVAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic event: once a minute, (or every second if TestingTorNetwork, or
|
||||
* during client bootstrap), check whether we want to download any
|
||||
* networkstatus documents. */
|
||||
static int
|
||||
fetch_networkstatus_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
/* 2c. Every minute (or every second if TestingTorNetwork, or during
|
||||
* client bootstrap), check whether we want to download any networkstatus
|
||||
* documents. */
|
||||
|
||||
/* How often do we check whether we should download network status
|
||||
* documents? */
|
||||
const int we_are_bootstrapping = networkstatus_consensus_is_bootstrapping(
|
||||
@ -1773,12 +1864,13 @@ fetch_networkstatus_callback(time_t now, const or_options_t *options)
|
||||
return networkstatus_dl_check_interval;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic callback: Every 60 seconds, we relaunch listeners if any died. */
|
||||
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()) {
|
||||
retry_all_listeners(NULL, NULL, 0);
|
||||
return 60;
|
||||
@ -1786,6 +1878,9 @@ retry_listeners_callback(time_t now, const or_options_t *options)
|
||||
return PERIODIC_EVENT_NO_UPDATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic callback: as a server, see if we have any old unused circuits
|
||||
* that should be expired */
|
||||
static int
|
||||
expire_old_ciruits_serverside_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1795,6 +1890,10 @@ expire_old_ciruits_serverside_callback(time_t now, const or_options_t *options)
|
||||
return 11;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic event: if we're an exit, see if our DNS server is telling us
|
||||
* obvious lies.
|
||||
*/
|
||||
static int
|
||||
check_dns_honesty_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1817,6 +1916,10 @@ check_dns_honesty_callback(time_t now, const or_options_t *options)
|
||||
return 12*3600 + crypto_rand_int(12*3600);
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic callback: if we're the bridge authority, write a networkstatus
|
||||
* file to disk.
|
||||
*/
|
||||
static int
|
||||
write_bridge_ns_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1829,6 +1932,9 @@ write_bridge_ns_callback(time_t now, const or_options_t *options)
|
||||
return PERIODIC_EVENT_NO_UPDATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Periodic callback: poke the tor-fw-helper app if we're using one.
|
||||
*/
|
||||
static int
|
||||
check_fw_helper_app_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -1852,7 +1958,9 @@ check_fw_helper_app_callback(time_t now, const or_options_t *options)
|
||||
return PORT_FORWARDING_CHECK_INTERVAL;
|
||||
}
|
||||
|
||||
/** Callback to write heartbeat message in the logs. */
|
||||
/**
|
||||
* Periodic callback: write the heartbeat message in the logs.
|
||||
*/
|
||||
static int
|
||||
heartbeat_callback(time_t now, const or_options_t *options)
|
||||
{
|
||||
@ -2358,19 +2466,26 @@ run_main_loop_once(void)
|
||||
/* Make it easier to tell whether libevent failure is our fault or not. */
|
||||
errno = 0;
|
||||
#endif
|
||||
/* All active linked conns should get their read events activated. */
|
||||
|
||||
/* All active linked conns should get their read events activated,
|
||||
* so that libevent knows to run their callbacks. */
|
||||
SMARTLIST_FOREACH(active_linked_connection_lst, connection_t *, conn,
|
||||
event_active(conn->read_event, EV_READ, 1));
|
||||
called_loop_once = smartlist_len(active_linked_connection_lst) ? 1 : 0;
|
||||
|
||||
/* Make sure we know (about) what time it is. */
|
||||
update_approx_time(time(NULL));
|
||||
|
||||
/* poll until we have an event, or the second ends, or until we have
|
||||
* some active linked connections to trigger events for. */
|
||||
/* Here it is: the main loop. Here we tell Libevent to poll until we have
|
||||
* an event, or the second ends, or until we have some active linked
|
||||
* connections to trigger events for. Libevent will wait till one
|
||||
* of these happens, then run all the appropriate callbacks. */
|
||||
loop_result = event_base_loop(tor_libevent_get_base(),
|
||||
called_loop_once ? EVLOOP_ONCE : 0);
|
||||
|
||||
/* let catch() handle things like ^c, and otherwise don't worry about it */
|
||||
/* Oh, the loop failed. That might be an error that we need to
|
||||
* catch, but more likely, it's just an interrupted poll() call or something,
|
||||
* and we should try again. */
|
||||
if (loop_result < 0) {
|
||||
int e = tor_socket_errno(-1);
|
||||
/* let the program survive things like ^z */
|
||||
@ -2393,9 +2508,17 @@ run_main_loop_once(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* This will be pretty fast if nothing new is pending. Note that this gets
|
||||
* called once per libevent loop, which will make it happen once per group
|
||||
* of events that fire, or once per second. */
|
||||
/* And here is where we put callbacks that happen "every time the event loop
|
||||
* runs." They must be very fast, or else the whole Tor process will get
|
||||
* slowed down.
|
||||
*
|
||||
* Note that this gets called once per libevent loop, which will make it
|
||||
* happen once per group of events that fire, or once per second. */
|
||||
|
||||
/* If there are any pending client connections, try attaching them to
|
||||
* circuits (if we can.) This will be pretty fast if nothing new is
|
||||
* pending.
|
||||
*/
|
||||
connection_ap_attach_pending(0);
|
||||
|
||||
return 1;
|
||||
|
Loading…
Reference in New Issue
Block a user