|
@@ -1,3 +1,4 @@
|
|
|
+
|
|
|
/* Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
|
|
|
* Copyright (c) 2007-2017, The Tor Project, Inc. */
|
|
|
/* See LICENSE for licensing information */
|
|
@@ -112,6 +113,10 @@ static int disable_log_messages = 0;
|
|
|
#define EVENT_IS_INTERESTING(e) \
|
|
|
(!! (global_event_mask & EVENT_MASK_(e)))
|
|
|
|
|
|
+/** Macro: true if any event from the bitfield 'e' is interesting. */
|
|
|
+#define ANY_EVENT_IS_INTERESTING(e) \
|
|
|
+ EVENT_IS_INTERESTING(e)
|
|
|
+
|
|
|
/** If we're using cookie-type authentication, how long should our cookies be?
|
|
|
*/
|
|
|
#define AUTHENTICATION_COOKIE_LEN 32
|
|
@@ -219,6 +224,7 @@ static void set_cached_network_liveness(int liveness);
|
|
|
static void flush_queued_events_cb(mainloop_event_t *event, void *arg);
|
|
|
|
|
|
static char * download_status_to_string(const download_status_t *dl);
|
|
|
+static void control_get_bytes_rw_last_sec(uint64_t *r, uint64_t *w);
|
|
|
|
|
|
/** Given a control event code for a message event, return the corresponding
|
|
|
* log severity. */
|
|
@@ -271,6 +277,7 @@ control_update_global_event_mask(void)
|
|
|
smartlist_t *conns = get_connection_array();
|
|
|
event_mask_t old_mask, new_mask;
|
|
|
old_mask = global_event_mask;
|
|
|
+ int any_old_per_sec_events = control_any_per_second_event_enabled();
|
|
|
|
|
|
global_event_mask = 0;
|
|
|
SMARTLIST_FOREACH(conns, connection_t *, _conn,
|
|
@@ -288,10 +295,13 @@ control_update_global_event_mask(void)
|
|
|
* we want to hear...*/
|
|
|
control_adjust_event_log_severity();
|
|
|
|
|
|
+ /* Macro: true if ev was false before and is true now. */
|
|
|
+#define NEWLY_ENABLED(ev) \
|
|
|
+ (! (old_mask & (ev)) && (new_mask & (ev)))
|
|
|
+
|
|
|
/* ...then, if we've started logging stream or circ bw, clear the
|
|
|
* appropriate fields. */
|
|
|
- if (! (old_mask & EVENT_STREAM_BANDWIDTH_USED) &&
|
|
|
- (new_mask & EVENT_STREAM_BANDWIDTH_USED)) {
|
|
|
+ if (NEWLY_ENABLED(EVENT_STREAM_BANDWIDTH_USED)) {
|
|
|
SMARTLIST_FOREACH(conns, connection_t *, conn,
|
|
|
{
|
|
|
if (conn->type == CONN_TYPE_AP) {
|
|
@@ -300,10 +310,18 @@ control_update_global_event_mask(void)
|
|
|
}
|
|
|
});
|
|
|
}
|
|
|
- if (! (old_mask & EVENT_CIRC_BANDWIDTH_USED) &&
|
|
|
- (new_mask & EVENT_CIRC_BANDWIDTH_USED)) {
|
|
|
+ if (NEWLY_ENABLED(EVENT_CIRC_BANDWIDTH_USED)) {
|
|
|
clear_circ_bw_fields();
|
|
|
}
|
|
|
+ if (NEWLY_ENABLED(EVENT_BANDWIDTH_USED)) {
|
|
|
+ uint64_t r, w;
|
|
|
+ control_get_bytes_rw_last_sec(&r, &w);
|
|
|
+ }
|
|
|
+ if (any_old_per_sec_events != control_any_per_second_event_enabled()) {
|
|
|
+ reschedule_per_second_timer();
|
|
|
+ }
|
|
|
+
|
|
|
+#undef NEWLY_ENABLED
|
|
|
}
|
|
|
|
|
|
/** Adjust the log severities that result in control_event_logmsg being called
|
|
@@ -352,6 +370,65 @@ control_event_is_interesting(int event)
|
|
|
return EVENT_IS_INTERESTING(event);
|
|
|
}
|
|
|
|
|
|
+/** Return true if any event that needs to fire once a second is enabled. */
|
|
|
+int
|
|
|
+control_any_per_second_event_enabled(void)
|
|
|
+{
|
|
|
+ return ANY_EVENT_IS_INTERESTING(
|
|
|
+ EVENT_BANDWIDTH_USED |
|
|
|
+ EVENT_CELL_STATS |
|
|
|
+ EVENT_CIRC_BANDWIDTH_USED |
|
|
|
+ EVENT_CONN_BW |
|
|
|
+ EVENT_STREAM_BANDWIDTH_USED
|
|
|
+ );
|
|
|
+}
|
|
|
+
|
|
|
+/* The value of 'get_bytes_read()' the previous time that
|
|
|
+ * control_get_bytes_rw_last_sec() as called. */
|
|
|
+static uint64_t stats_prev_n_read = 0;
|
|
|
+/* The value of 'get_bytes_written()' the previous time that
|
|
|
+ * control_get_bytes_rw_last_sec() as called. */
|
|
|
+static uint64_t stats_prev_n_written = 0;
|
|
|
+
|
|
|
+/**
|
|
|
+ * Set <b>n_read</b> and <b>n_written</b> to the total number of bytes read
|
|
|
+ * and written by Tor since the last call to this function.
|
|
|
+ *
|
|
|
+ * Call this only from the main thread.
|
|
|
+ */
|
|
|
+static void
|
|
|
+control_get_bytes_rw_last_sec(uint64_t *n_read,
|
|
|
+ uint64_t *n_written)
|
|
|
+{
|
|
|
+ const uint64_t stats_n_bytes_read = get_bytes_read();
|
|
|
+ const uint64_t stats_n_bytes_written = get_bytes_written();
|
|
|
+
|
|
|
+ *n_read = stats_n_bytes_read - stats_prev_n_read;
|
|
|
+ *n_written = stats_n_bytes_written - stats_prev_n_written;
|
|
|
+ stats_prev_n_read = stats_n_bytes_read;
|
|
|
+ stats_prev_n_written = stats_n_bytes_written;
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * Run all the controller events (if any) that are scheduled to trigger once
|
|
|
+ * per second.
|
|
|
+ */
|
|
|
+void
|
|
|
+control_per_second_events(void)
|
|
|
+{
|
|
|
+ if (!control_any_per_second_event_enabled())
|
|
|
+ return;
|
|
|
+
|
|
|
+ uint64_t bytes_read, bytes_written;
|
|
|
+ control_get_bytes_rw_last_sec(&bytes_read, &bytes_written);
|
|
|
+ control_event_bandwidth_used((uint32_t)bytes_read,(uint32_t)bytes_written);
|
|
|
+
|
|
|
+ control_event_stream_bandwidth_used();
|
|
|
+ control_event_conn_bandwidth_used();
|
|
|
+ control_event_circ_bandwidth_used();
|
|
|
+ control_event_circuit_cell_stats();
|
|
|
+}
|
|
|
+
|
|
|
/** Append a NUL-terminated string <b>s</b> to the end of
|
|
|
* <b>conn</b>-\>outbuf.
|
|
|
*/
|
|
@@ -7035,6 +7112,8 @@ control_event_bootstrap_problem(const char *warn, const char *reason,
|
|
|
if (bootstrap_problems >= BOOTSTRAP_PROBLEM_THRESHOLD)
|
|
|
dowarn = 1;
|
|
|
|
|
|
+ /* Don't warn about our bootstrapping status if we are hibernating or
|
|
|
+ * shutting down. */
|
|
|
if (we_are_hibernating())
|
|
|
dowarn = 0;
|
|
|
|
|
@@ -7606,6 +7685,8 @@ control_free_all(void)
|
|
|
{
|
|
|
smartlist_t *queued_events = NULL;
|
|
|
|
|
|
+ stats_prev_n_read = stats_prev_n_written = 0;
|
|
|
+
|
|
|
if (authentication_cookie) /* Free the auth cookie */
|
|
|
tor_free(authentication_cookie);
|
|
|
if (detached_onion_services) { /* Free the detached onion services */
|