aboutsummaryrefslogtreecommitdiff
path: root/src/or/control.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/or/control.c')
-rw-r--r--src/or/control.c138
1 files changed, 86 insertions, 52 deletions
diff --git a/src/or/control.c b/src/or/control.c
index fa62e9dbde..93b204f9a3 100644
--- a/src/or/control.c
+++ b/src/or/control.c
@@ -52,6 +52,8 @@
#include "connection_edge.h"
#include "connection_or.h"
#include "control.h"
+#include "crypto_rand.h"
+#include "crypto_util.h"
#include "directory.h"
#include "dirserv.h"
#include "dnsserv.h"
@@ -76,15 +78,13 @@
#include "router.h"
#include "routerlist.h"
#include "routerparse.h"
-#include "shared_random.h"
+#include "shared_random_client.h"
#ifndef _WIN32
#include <pwd.h>
#include <sys/resource.h>
#endif
-#include <event2/event.h>
-
#include "crypto_s2k.h"
#include "procmon.h"
@@ -216,7 +216,7 @@ static void orconn_target_get_name(char *buf, size_t len,
static int get_cached_network_liveness(void);
static void set_cached_network_liveness(int liveness);
-static void flush_queued_events_cb(evutil_socket_t fd, short what, void *arg);
+static void flush_queued_events_cb(mainloop_event_t *event, void *arg);
static char * download_status_to_string(const download_status_t *dl);
@@ -691,7 +691,7 @@ static tor_mutex_t *queued_control_events_lock = NULL;
/** An event that should fire in order to flush the contents of
* queued_control_events. */
-static struct event *flush_queued_events_event = NULL;
+static mainloop_event_t *flush_queued_events_event = NULL;
void
control_initialize_event_queue(void)
@@ -703,9 +703,8 @@ control_initialize_event_queue(void)
if (flush_queued_events_event == NULL) {
struct event_base *b = tor_libevent_get_base();
if (b) {
- flush_queued_events_event = tor_event_new(b,
- -1, 0, flush_queued_events_cb,
- NULL);
+ flush_queued_events_event =
+ mainloop_event_new(flush_queued_events_cb, NULL);
tor_assert(flush_queued_events_event);
}
}
@@ -781,7 +780,7 @@ queue_control_event_string,(uint16_t event, char *msg))
*/
if (activate_event) {
tor_assert(flush_queued_events_event);
- event_active(flush_queued_events_event, EV_READ, 1);
+ mainloop_event_activate(flush_queued_events_event);
}
}
@@ -806,6 +805,9 @@ queued_event_free_(queued_event_t *ev)
static void
queued_events_flush_all(int force)
{
+ /* Make sure that we get all the pending log events, if there are any. */
+ flush_pending_log_callbacks();
+
if (PREDICT_UNLIKELY(queued_control_events == NULL)) {
return;
}
@@ -863,10 +865,9 @@ queued_events_flush_all(int force)
/** Libevent callback: Flushes pending events to controllers that are
* interested in them. */
static void
-flush_queued_events_cb(evutil_socket_t fd, short what, void *arg)
+flush_queued_events_cb(mainloop_event_t *event, void *arg)
{
- (void) fd;
- (void) what;
+ (void) event;
(void) arg;
queued_events_flush_all(0);
}
@@ -1218,7 +1219,6 @@ static const struct control_event_t control_event_table[] = {
{ EVENT_CONF_CHANGED, "CONF_CHANGED"},
{ EVENT_CONN_BW, "CONN_BW" },
{ EVENT_CELL_STATS, "CELL_STATS" },
- { EVENT_TB_EMPTY, "TB_EMPTY" },
{ EVENT_CIRC_BANDWIDTH_USED, "CIRC_BW" },
{ EVENT_TRANSPORT_LAUNCHED, "TRANSPORT_LAUNCHED" },
{ EVENT_HS_DESC, "HS_DESC" },
@@ -1936,6 +1936,31 @@ getinfo_helper_listeners(control_connection_t *control_conn,
return 0;
}
+/** Implementation helper for GETINFO: answers requests for information about
+ * the current time in both local and UTF forms. */
+STATIC int
+getinfo_helper_current_time(control_connection_t *control_conn,
+ const char *question,
+ char **answer, const char **errmsg)
+{
+ (void)control_conn;
+ (void)errmsg;
+
+ struct timeval now;
+ tor_gettimeofday(&now);
+ char timebuf[ISO_TIME_LEN+1];
+
+ if (!strcmp(question, "current-time/local"))
+ format_local_iso_time_nospace(timebuf, (time_t)now.tv_sec);
+ else if (!strcmp(question, "current-time/utc"))
+ format_iso_time_nospace(timebuf, (time_t)now.tv_sec);
+ else
+ return 0;
+
+ *answer = tor_strdup(timebuf);
+ return 0;
+}
+
/** Implementation helper for GETINFO: knows the answers for questions about
* directory information. */
STATIC int
@@ -3078,6 +3103,9 @@ static const getinfo_item_t getinfo_items[] = {
DOC("config/defaults",
"List of default values for configuration options. "
"See also config/names"),
+ PREFIX("current-time/", current_time, "Current time."),
+ DOC("current-time/local", "Current time on the local system."),
+ DOC("current-time/utc", "Current UTC time."),
PREFIX("downloads/networkstatus/", downloads,
"Download statuses for networkstatus objects"),
DOC("downloads/networkstatus/ns",
@@ -3492,17 +3520,19 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
smartlist_free(args);
nodes = smartlist_new();
+ int first_node = zero_circ;
SMARTLIST_FOREACH_BEGIN(router_nicknames, const char *, n) {
const node_t *node = node_get_by_nickname(n, 0);
if (!node) {
connection_printf_to_buf(conn, "552 No such router \"%s\"\r\n", n);
goto done;
}
- if (!node_has_descriptor(node)) {
+ if (!node_has_preferred_descriptor(node, first_node)) {
connection_printf_to_buf(conn, "552 No descriptor for \"%s\"\r\n", n);
goto done;
}
smartlist_add(nodes, (void*)node);
+ first_node = 0;
} SMARTLIST_FOREACH_END(n);
if (!smartlist_len(nodes)) {
connection_write_str_to_buf("512 No router names provided\r\n", conn);
@@ -3515,14 +3545,15 @@ handle_control_extendcircuit(control_connection_t *conn, uint32_t len,
}
/* now circ refers to something that is ready to be extended */
- int first_node = zero_circ;
+ first_node = zero_circ;
SMARTLIST_FOREACH(nodes, const node_t *, node,
{
extend_info_t *info = extend_info_from_node(node, first_node);
if (!info) {
tor_assert_nonfatal(first_node);
log_warn(LD_CONTROL,
- "controller tried to connect to a node that doesn't have any "
+ "controller tried to connect to a node that lacks a suitable "
+ "descriptor, or which doesn't have any "
"addresses that are allowed by the firewall configuration; "
"circuit marked for closing.");
circuit_mark_for_close(TO_CIRCUIT(circ), -END_CIRC_REASON_CONNECTFAILED);
@@ -5805,8 +5836,6 @@ control_event_or_conn_status(or_connection_t *conn, or_conn_status_event_t tp,
int
control_event_stream_bandwidth(edge_connection_t *edge_conn)
{
- circuit_t *circ;
- origin_circuit_t *ocirc;
struct timeval now;
char tbuf[ISO_TIME_USEC_LEN+1];
if (EVENT_IS_INTERESTING(EVENT_STREAM_BANDWIDTH_USED)) {
@@ -5822,12 +5851,6 @@ control_event_stream_bandwidth(edge_connection_t *edge_conn)
(unsigned long)edge_conn->n_written,
tbuf);
- circ = circuit_get_by_edge_conn(edge_conn);
- if (circ && CIRCUIT_IS_ORIGIN(circ)) {
- ocirc = TO_ORIGIN_CIRCUIT(circ);
- ocirc->n_read_circ_bw += edge_conn->n_read;
- ocirc->n_written_circ_bw += edge_conn->n_written;
- }
edge_conn->n_written = edge_conn->n_read = 0;
}
@@ -6081,28 +6104,6 @@ control_event_circuit_cell_stats(void)
return 0;
}
-/** Tokens in <b>bucket</b> have been refilled: the read bucket was empty
- * for <b>read_empty_time</b> millis, the write bucket was empty for
- * <b>write_empty_time</b> millis, and buckets were last refilled
- * <b>milliseconds_elapsed</b> millis ago. Only emit TB_EMPTY event if
- * either read or write bucket have been empty before. */
-int
-control_event_tb_empty(const char *bucket, uint32_t read_empty_time,
- uint32_t write_empty_time,
- int milliseconds_elapsed)
-{
- if (get_options()->TestingEnableTbEmptyEvent &&
- EVENT_IS_INTERESTING(EVENT_TB_EMPTY) &&
- (read_empty_time > 0 || write_empty_time > 0)) {
- send_control_event(EVENT_TB_EMPTY,
- "650 TB_EMPTY %s READ=%d WRITTEN=%d "
- "LAST=%d\r\n",
- bucket, read_empty_time, write_empty_time,
- milliseconds_elapsed);
- }
- return 0;
-}
-
/* about 5 minutes worth. */
#define N_BW_EVENTS_TO_CACHE 300
/* Index into cached_bw_events to next write. */
@@ -6190,7 +6191,7 @@ control_event_logmsg(int severity, uint32_t domain, const char *msg)
int event;
/* Don't even think of trying to add stuff to a buffer from a cpuworker
- * thread. */
+ * thread. (See #25987 for plan to fix.) */
if (! in_main_thread())
return;
@@ -6236,6 +6237,23 @@ control_event_logmsg(int severity, uint32_t domain, const char *msg)
}
}
+/**
+ * Logging callback: called when there is a queued pending log callback.
+ */
+void
+control_event_logmsg_pending(void)
+{
+ if (! in_main_thread()) {
+ /* We can't handle this case yet, since we're using a
+ * mainloop_event_t to invoke queued_events_flush_all. We ought to
+ * use a different mechanism instead: see #25987.
+ **/
+ return;
+ }
+ tor_assert(flush_queued_events_event);
+ mainloop_event_activate(flush_queued_events_event);
+}
+
/** Called whenever we receive new router descriptors: tell any
* interested control connections. <b>routers</b> is a list of
* routerinfo_t's.
@@ -7586,22 +7604,38 @@ control_event_hs_descriptor_upload_failed(const char *id_digest,
void
control_free_all(void)
{
+ smartlist_t *queued_events = NULL;
+
if (authentication_cookie) /* Free the auth cookie */
tor_free(authentication_cookie);
if (detached_onion_services) { /* Free the detached onion services */
SMARTLIST_FOREACH(detached_onion_services, char *, cp, tor_free(cp));
smartlist_free(detached_onion_services);
}
- if (queued_control_events) {
- SMARTLIST_FOREACH(queued_control_events, queued_event_t *, ev,
- queued_event_free(ev));
- smartlist_free(queued_control_events);
+
+ if (queued_control_events_lock) {
+ tor_mutex_acquire(queued_control_events_lock);
+ flush_queued_event_pending = 0;
+ queued_events = queued_control_events;
queued_control_events = NULL;
+ tor_mutex_release(queued_control_events_lock);
+ }
+ if (queued_events) {
+ SMARTLIST_FOREACH(queued_events, queued_event_t *, ev,
+ queued_event_free(ev));
+ smartlist_free(queued_events);
}
if (flush_queued_events_event) {
- tor_event_free(flush_queued_events_event);
+ mainloop_event_free(flush_queued_events_event);
flush_queued_events_event = NULL;
}
+ bootstrap_percent = BOOTSTRAP_STATUS_UNDEF;
+ notice_bootstrap_percent = 0;
+ bootstrap_problems = 0;
+ authentication_cookie_is_set = 0;
+ global_event_mask = 0;
+ disable_log_messages = 0;
+ memset(last_sent_bootstrap_message, 0, sizeof(last_sent_bootstrap_message));
}
#ifdef TOR_UNIT_TESTS