📄 main.c
字号:
} else {
or_connection_t *best =
connection_or_get_by_identity_digest(or_conn->identity_digest);
if (best && best != or_conn &&
(conn->state == OR_CONN_STATE_OPEN ||
now > conn->timestamp_created + TLS_HANDSHAKE_TIMEOUT)) {
/* We only mark as obsolete connections that already are in
* OR_CONN_STATE_OPEN, i.e. that have finished their TLS handshaking.
* This is necessary because authorities judge whether a router is
* reachable based on whether they were able to TLS handshake with it
* recently. Without this check we would expire connections too
* early for router->last_reachable to be updated.
*/
log_info(LD_OR,
"Marking duplicate conn to %s:%d obsolete "
"(fd %d, %d secs old).",
conn->address, conn->port, conn->s,
(int)(now - conn->timestamp_created));
conn->or_is_obsolete = 1;
}
}
}
if (conn->or_is_obsolete && !or_conn->n_circuits) {
/* no unmarked circs -- mark it now */
log_info(LD_OR,
"Expiring non-used OR connection to fd %d (%s:%d) [Obsolete].",
conn->s, conn->address, conn->port);
connection_mark_for_close(conn);
conn->hold_open_until_flushed = 1;
return;
}
/* If we haven't written to an OR connection for a while, then either nuke
the connection or send a keepalive, depending. */
if (now >= conn->timestamp_lastwritten + options->KeepalivePeriod) {
routerinfo_t *router = router_get_by_digest(or_conn->identity_digest);
int maxCircuitlessPeriod = options->MaxCircuitDirtiness*3/2;
if (!connection_state_is_open(conn)) {
/* We never managed to actually get this connection open and happy. */
log_info(LD_OR,"Expiring non-open OR connection to fd %d (%s:%d).",
conn->s,conn->address, conn->port);
connection_mark_for_close(conn);
conn->hold_open_until_flushed = 1;
} else if (we_are_hibernating() && !or_conn->n_circuits &&
!buf_datalen(conn->outbuf)) {
/* 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;
} else if (!clique_mode(options) && !or_conn->n_circuits &&
now >= or_conn->timestamp_last_added_nonpadding +
maxCircuitlessPeriod &&
(!router || !server_mode(options) ||
!router_is_clique_mode(router))) {
log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) "
"[Not in clique mode].",
conn->s,conn->address, conn->port);
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) {
log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL,
"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)(now-conn->timestamp_lastwritten));
connection_mark_for_close(conn);
} else if (!buf_datalen(conn->outbuf)) {
/* either in clique mode, or we've got a circuit. send a padding cell. */
log_fn(LOG_DEBUG,LD_OR,"Sending keepalive to (%s:%d)",
conn->address, conn->port);
memset(&cell,0,sizeof(cell_t));
cell.command = CELL_PADDING;
connection_or_write_cell_to_buf(&cell, or_conn);
}
}
}
/** Honor a NEWNYM request: make future requests unlinkability to past
* requests. */
static void
signewnym_impl(time_t now)
{
circuit_expire_all_dirty_circs();
addressmap_clear_transient();
time_of_last_signewnym = now;
signewnym_is_pending = 0;
}
/** Perform regular maintenance tasks. This function gets run once per
* second by prepare_for_poll.
*/
static void
run_scheduled_events(time_t now)
{
static time_t time_to_fetch_directory = 0;
static time_t time_to_fetch_running_routers = 0;
static time_t last_rotated_x509_certificate = 0;
static time_t time_to_check_v3_certificate = 0;
static time_t time_to_check_listeners = 0;
static time_t time_to_check_descriptor = 0;
static time_t time_to_check_ipaddress = 0;
static time_t time_to_shrink_memory = 0;
static time_t time_to_try_getting_descriptors = 0;
static time_t time_to_reset_descriptor_failures = 0;
static time_t time_to_add_entropy = 0;
static time_t time_to_write_hs_statistics = 0;
static time_t time_to_write_bridge_status_file = 0;
static time_t time_to_downrate_stability = 0;
static time_t time_to_save_stability = 0;
static time_t time_to_clean_caches = 0;
static time_t time_to_recheck_bandwidth = 0;
static time_t time_to_check_for_expired_networkstatus = 0;
or_options_t *options = get_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.
*/
consider_hibernation(now);
/* 0b. If we've deferred a signewnym, make sure it gets handled
* eventually. */
if (signewnym_is_pending &&
time_of_last_signewnym + MAX_SIGNEWNYM_RATE <= now) {
log(LOG_INFO, LD_CONTROL, "Honoring delayed NEWNYM request");
signewnym_impl(now);
}
/** 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) &&
get_onion_key_set_at()+MIN_ONION_KEY_LIFETIME < now) {
log_info(LD_GENERAL,"Rotating onion key.");
rotate_onion_key();
cpuworkers_rotate();
if (router_rebuild_descriptor(1)<0) {
log_info(LD_CONFIG, "Couldn't rebuild router descriptor");
}
if (advertised_server_mode())
router_upload_dir_desc_to_dirservers(0);
}
if (time_to_try_getting_descriptors < now) {
update_router_descriptor_downloads(now);
update_extrainfo_downloads(now);
if (options->UseBridges)
fetch_bridge_descriptors(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;
}
if (time_to_reset_descriptor_failures < now) {
router_reset_descriptor_download_failures();
time_to_reset_descriptor_failures =
now + DESCRIPTOR_FAILURE_RESET_INTERVAL;
}
/** 1b. Every MAX_SSL_KEY_LIFETIME seconds, we change our TLS context. */
if (!last_rotated_x509_certificate)
last_rotated_x509_certificate = now;
if (last_rotated_x509_certificate+MAX_SSL_KEY_LIFETIME < now) {
log_info(LD_GENERAL,"Rotating tls context.");
if (tor_tls_context_new(get_identity_key(), MAX_SSL_KEY_LIFETIME) < 0) {
log_warn(LD_BUG, "Error reinitializing TLS context");
/* XXX is it a bug here, that we just keep going? -RD */
}
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 or_is_obsolete in
* connection_run_housekeeping() above. */
}
if (time_to_add_entropy < now) {
if (time_to_add_entropy) {
/* We already seeded once, so don't die on failure. */
crypto_seed_rng(0);
}
/** How often do we add more entropy to OpenSSL's RNG pool? */
#define ENTROPY_INTERVAL (60*60)
time_to_add_entropy = now + ENTROPY_INTERVAL;
}
/** 1c. If we have to change the accounting interval or record
* bandwidth used in this accounting interval, do so. */
if (accounting_is_enabled(options))
accounting_run_housekeeping(now);
if (now % 10 == 0 && (authdir_mode_tests_reachability(options)) &&
!we_are_hibernating()) {
/* try to determine reachability of the other Tor relays */
dirserv_test_reachability(now, 0);
}
/** 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);
if (authdir_mode_tests_reachability(options)) {
if (time_to_save_stability < now) {
if (time_to_save_stability && rep_hist_record_mtbf_data()<0) {
log_warn(LD_GENERAL, "Couldn't store mtbf data.");
}
#define SAVE_STABILITY_INTERVAL (30*60)
time_to_save_stability = now + SAVE_STABILITY_INTERVAL;
}
}
/* 1e. Periodicaly, 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();
#define CHECK_V3_CERTIFICATE_INTERVAL (5*60)
time_to_check_v3_certificate = now + CHECK_V3_CERTIFICATE_INTERVAL;
}
/* 1f. Check whether our networkstatus has expired.
*/
if (time_to_check_for_expired_networkstatus < now) {
networkstatus_t *ns = networkstatus_get_latest_consensus();
/*XXXX020 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;
}
/** 2. Periodically, we consider getting a new directory, getting a
* new running-routers list, and/or force-uploading our descriptor
* (if we've passed our internal checks). */
if (time_to_fetch_directory < now) {
/* Only caches actually need to fetch v1 directories now. */
if (directory_fetches_dir_info_early(options) &&
!authdir_mode_v1(options) && any_trusted_dir_is_v1_authority() &&
!should_delay_dir_fetches(options))
directory_get_from_dirserver(DIR_PURPOSE_FETCH_DIR,
ROUTER_PURPOSE_GENERAL, NULL, 1);
/** How often do we (as a cache) fetch a new V1 directory? */
#define V1_DIR_FETCH_PERIOD (12*60*60)
time_to_fetch_directory = now + V1_DIR_FETCH_PERIOD;
}
/* Caches need to fetch running_routers; directory clients don't. */
if (time_to_fetch_running_routers < now) {
if (directory_fetches_dir_info_early(options) &&
!authdir_mode_v1(options) && any_trusted_dir_is_v1_authority() &&
!should_delay_dir_fetches(options))
directory_get_from_dirserver(DIR_PURPOSE_FETCH_RUNNING_LIST,
ROUTER_PURPOSE_GENERAL, NULL, 1);
/** How often do we (as a cache) fetch a new V1 runningrouters document? */
#define V1_RUNNINGROUTERS_FETCH_PERIOD (12*60*60)
time_to_fetch_running_routers = now + V1_RUNNINGROUTERS_FETCH_PERIOD;
}
/* 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();
#define CLEAN_CACHES_INTERVAL (30*60)
time_to_clean_caches = now + CLEAN_CACHES_INTERVAL;
}
/** How often do we check whether part of our router info has changed in a way
* that would require an upload? */
#define CHECK_DESCRIPTOR_INTERVAL (60)
/** How often do we (as a router) check whether our IP address has changed? */
#define CHECK_IPADDRESS_INTERVAL (15*60)
/* 2b. Once per minute, regenerate and upload the descriptor if the old
* one is inaccurate. */
if (time_to_check_descriptor < now) {
static int dirport_reachability_count = 0;
time_to_check_descriptor = now + CHECK_DESCRIPTOR_INTERVAL;
check_descriptor_bandwidth_changed(now);
if (time_to_check_ipaddress < now) {
time_to_check_ipaddress = now + CHECK_IPADDRESS_INTERVAL;
check_descriptor_ipaddress_changed(now);
}
/** If our router descriptor ever goes this long without being regenerated
* because something changed, we force an immediate regenerate-and-upload. */
#define FORCE_REGENERATE_DESCRIPTOR_INTERVAL (18*60*60)
mark_my_descriptor_dirty_if_older_than(
now - FORCE_REGENERATE_DESCRIPTOR_INTERVAL);
consider_publishable_server(0);
/* also, check religiously for reachability, if it's within the first
* 20 minutes of our uptime. */
if (server_mode(options) &&
(has_completed_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. */
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. */
/* purge obsolete entries */
networkstatus_v2_list_clean(now);
/* Remove dead routers. */
routerlist_remove_old_routers();
/* Also, once per minute, check whether we want to download any
* networkstatus documents.
*/
update_networkstatus_downloads(now);
}
/** 2c. Let directory voting happen. */
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
* it's not comfortable with the number of available circuits.
*/
circuit_expire_building(now);
/** 3b. Also look at pending streams and prune the ones that 'began'
* a long time ago but haven't gotten a 'connected' yet.
* Do this before step 4, so we can put them back into pending
* state to be picked up by the new circuit.
*/
connection_ap_expire_beginning();
/** 3c. And expire connections that we've held open for too long.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -