/* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. * Copyright (c) 2007-2019, The Tor Project, Inc. */ /* See LICENSE for licensing information */ #include "core/or/or.h" #include "core/mainloop/netstatus.h" #include "core/mainloop/mainloop.h" #include "app/config/config.h" #include "feature/hibernate/hibernate.h" #include "app/config/or_state_st.h" /** Return true iff our network is in some sense disabled or shutting down: * either we're hibernating, entering hibernation, or the network is turned * off with DisableNetwork. */ int net_is_disabled(void) { return get_options()->DisableNetwork || we_are_hibernating(); } /** Return true iff our network is in some sense "completely disabled" either * we're fully hibernating or the network is turned off with * DisableNetwork. */ int net_is_completely_disabled(void) { return get_options()->DisableNetwork || we_are_fully_hibernating(); } /** * The time at which we've last seen "user activity" -- that is, any activity * that should keep us as a participant on the network. * * This is not actually the true time. We will adjust this forward if * our clock jumps, or if Tor is shut down for a while, so that the time * since our last activity remains as it was before the jump or shutdown. */ static time_t last_user_activity_seen = 0; /** * True iff we are currently a "network participant" -- that is, we * are building circuits, fetching directory information, and so on. **/ static bool participating_on_network = false; /** * Record the fact that we have seen "user activity" at the time now. Move * "last activity seen" time forwards, but never backwards. * * If we were previously not participating on the network, set our * participation status to true, and launch periodic events as appropriate. **/ void note_user_activity(time_t now) { last_user_activity_seen = MAX(now, last_user_activity_seen); if (! participating_on_network) { log_notice(LD_GENERAL, "Tor is no longer dormant."); set_network_participation(true); schedule_rescan_periodic_events(); } } /** * Change the time at which "user activitiy" was last seen to now. * * Unlike note_user_actity, this function sets the time without checking * whether it is in the past, and without causing any rescan of periodic events * or change in participation status. */ void reset_user_activity(time_t now) { last_user_activity_seen = now; } /** * Return the most recent time at which we recorded "user activity". **/ time_t get_last_user_activity_time(void) { return last_user_activity_seen; } /** * Set the field that remembers whether we are currently participating on the * network. Does not schedule or un-schedule periodic events. **/ void set_network_participation(bool participation) { participating_on_network = participation; } /** * Return true iff we are currently participating on the network. **/ bool is_participating_on_network(void) { return participating_on_network; } /** * Update 'state' with the last time at which we were active on the network. **/ void netstatus_flush_to_state(or_state_t *state, time_t now) { state->Dormant = ! participating_on_network; if (participating_on_network) { time_t sec_since_activity = MAX(0, now - last_user_activity_seen); state->MinutesSinceUserActivity = (int)(sec_since_activity / 60); } else { state->MinutesSinceUserActivity = 0; } } /** * Update our current view of network participation from an or_state_t object. **/ void netstatus_load_from_state(const or_state_t *state, time_t now) { time_t last_activity; if (state->Dormant == -1) { // Initial setup. if (get_options()->DormantOnFirstStartup) { last_activity = 0; participating_on_network = false; } else { // Start up as active, treat activity as happening now. last_activity = now; participating_on_network = true; } } else if (state->Dormant) { last_activity = 0; participating_on_network = false; } else { last_activity = now - 60 * state->MinutesSinceUserActivity; participating_on_network = true; } reset_user_activity(last_activity); } /** * Adjust the time at which the user was last active by seconds_diff * in response to a clock jump. */ void netstatus_note_clock_jumped(time_t seconds_diff) { time_t last_active = get_last_user_activity_time(); if (last_active) reset_user_activity(last_active + seconds_diff); }