aboutsummaryrefslogtreecommitdiff
path: root/src/core/or/connection_or.c
diff options
context:
space:
mode:
authorTaylor Yu <catalyst@torproject.org>2018-12-16 16:05:58 -0600
committerTaylor Yu <catalyst@torproject.org>2018-12-20 18:46:17 -0600
commit271b50f54abac7af44e3e54589ff965d3cdac816 (patch)
treeaef158a07f39a869855b0920f6dcd1241601b68b /src/core/or/connection_or.c
parent308dde0c386158971a66c6e035b3f1ad67019eb5 (diff)
downloadtor-271b50f54abac7af44e3e54589ff965d3cdac816.tar.gz
tor-271b50f54abac7af44e3e54589ff965d3cdac816.zip
Add ORCONN event pubsub system
Add a publish-subscribe subsystem to publish messages about changes to OR connections. connection_or_change_state() in connection_or.c and control_event_or_conn_event() in control.c publish messages to this subsystem via helper functions. Move state constants from connection_or.h to orconn_state.h so that subscribers don't have to include all of connection_or.h to take actions based on changes in OR connection state. Move event constants from control.h for similar reasons. Part of ticket 27167.
Diffstat (limited to 'src/core/or/connection_or.c')
-rw-r--r--src/core/or/connection_or.c73
1 files changed, 62 insertions, 11 deletions
diff --git a/src/core/or/connection_or.c b/src/core/or/connection_or.c
index 04ab4fe4a9..a12ea55c46 100644
--- a/src/core/or/connection_or.c
+++ b/src/core/or/connection_or.c
@@ -29,6 +29,7 @@
*/
#define TOR_CHANNEL_INTERNAL_
#define CONNECTION_OR_PRIVATE
+#define ORCONN_EVENT_PRIVATE
#include "core/or/channel.h"
#include "core/or/channeltls.h"
#include "core/or/circuitbuild.h"
@@ -79,6 +80,8 @@
#include "lib/tls/tortls.h"
#include "lib/tls/x509.h"
+#include "core/or/orconn_event.h"
+
static int connection_tls_finish_handshake(or_connection_t *conn);
static int connection_or_launch_v3_or_handshake(or_connection_t *conn);
static int connection_or_process_cells_from_inbuf(or_connection_t *conn);
@@ -401,6 +404,49 @@ connection_or_report_broken_states(int severity, int domain)
smartlist_free(items);
}
+/**
+ * Helper function to publish an OR connection status event
+ *
+ * Publishes a messages to subscribers of ORCONN messages, and sends
+ * the control event.
+ **/
+void
+connection_or_event_status(or_connection_t *conn, or_conn_status_event_t tp,
+ int reason)
+{
+ orconn_event_msg_t msg;
+
+ msg.type = ORCONN_MSGTYPE_STATUS;
+ msg.u.status.gid = conn->base_.global_identifier;
+ msg.u.status.status = tp;
+ msg.u.status.reason = reason;
+ orconn_event_publish(&msg);
+ control_event_or_conn_status(conn, tp, reason);
+}
+
+/**
+ * Helper function to publish a state change message
+ *
+ * connection_or_change_state() calls this to notify subscribers about
+ * a change of an OR connection state.
+ **/
+static void
+connection_or_state_publish(const or_connection_t *conn, uint8_t state)
+{
+ orconn_event_msg_t msg;
+
+ msg.type = ORCONN_MSGTYPE_STATE;
+ msg.u.state.gid = conn->base_.global_identifier;
+ msg.u.state.proxy_type = conn->proxy_type;
+ msg.u.state.state = state;
+ if (conn->chan) {
+ msg.u.state.chan = TLS_CHAN_TO_BASE(conn->chan)->global_identifier;
+ } else {
+ msg.u.state.chan = 0;
+ }
+ orconn_event_publish(&msg);
+}
+
/** Call this to change or_connection_t states, so the owning channel_tls_t can
* be notified.
*/
@@ -412,6 +458,7 @@ connection_or_change_state(or_connection_t *conn, uint8_t state)
conn->base_.state = state;
+ connection_or_state_publish(conn, state);
if (conn->chan)
channel_tls_handle_state_change_on_orconn(conn->chan, conn, state);
}
@@ -755,8 +802,8 @@ connection_or_about_to_close(or_connection_t *or_conn)
entry_guard_chan_failed(TLS_CHAN_TO_BASE(or_conn->chan));
if (conn->state >= OR_CONN_STATE_TLS_HANDSHAKING) {
int reason = tls_error_to_orconn_end_reason(or_conn->tls_error);
- control_event_or_conn_status(or_conn, OR_CONN_EVENT_FAILED,
- reason);
+ connection_or_event_status(or_conn, OR_CONN_EVENT_FAILED,
+ reason);
if (!authdir_mode_tests_reachability(options))
control_event_bootstrap_prob_or(
orconn_end_reason_to_control_string(reason),
@@ -766,10 +813,10 @@ connection_or_about_to_close(or_connection_t *or_conn)
} else if (conn->hold_open_until_flushed) {
/* We only set hold_open_until_flushed when we're intentionally
* closing a connection. */
- control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED,
+ connection_or_event_status(or_conn, OR_CONN_EVENT_CLOSED,
tls_error_to_orconn_end_reason(or_conn->tls_error));
} else if (!tor_digest_is_zero(or_conn->identity_digest)) {
- control_event_or_conn_status(or_conn, OR_CONN_EVENT_CLOSED,
+ connection_or_event_status(or_conn, OR_CONN_EVENT_CLOSED,
tls_error_to_orconn_end_reason(or_conn->tls_error));
}
}
@@ -1361,7 +1408,7 @@ void
connection_or_connect_failed(or_connection_t *conn,
int reason, const char *msg)
{
- control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED, reason);
+ connection_or_event_status(conn, OR_CONN_EVENT_FAILED, reason);
if (!authdir_mode_tests_reachability(get_options()))
control_event_bootstrap_prob_or(msg, reason, conn);
note_or_connect_failed(conn);
@@ -1468,9 +1515,6 @@ connection_or_connect, (const tor_addr_t *_addr, uint16_t port,
return NULL;
}
- connection_or_change_state(conn, OR_CONN_STATE_CONNECTING);
- control_event_or_conn_status(conn, OR_CONN_EVENT_LAUNCHED, 0);
-
conn->is_outgoing = 1;
/* If we are using a proxy server, find it and use it. */
@@ -1482,7 +1526,14 @@ connection_or_connect, (const tor_addr_t *_addr, uint16_t port,
port = proxy_port;
conn->base_.proxy_state = PROXY_INFANT;
}
+ connection_or_change_state(conn, OR_CONN_STATE_CONNECTING);
+ connection_or_event_status(conn, OR_CONN_EVENT_LAUNCHED, 0);
} else {
+ /* This duplication of state change calls is necessary in case we
+ * run into an error condition below */
+ connection_or_change_state(conn, OR_CONN_STATE_CONNECTING);
+ connection_or_event_status(conn, OR_CONN_EVENT_LAUNCHED, 0);
+
/* get_proxy_addrport() might fail if we have a Bridge line that
references a transport, but no ClientTransportPlugin lines
defining its transport proxy. If this is the case, let's try to
@@ -1978,8 +2029,8 @@ connection_or_client_learned_peer_id(or_connection_t *conn,
/* Tell the new guard API about the channel failure */
entry_guard_chan_failed(TLS_CHAN_TO_BASE(conn->chan));
- control_event_or_conn_status(conn, OR_CONN_EVENT_FAILED,
- END_OR_CONN_REASON_OR_IDENTITY);
+ connection_or_event_status(conn, OR_CONN_EVENT_FAILED,
+ END_OR_CONN_REASON_OR_IDENTITY);
if (!authdir_mode_tests_reachability(options))
control_event_bootstrap_prob_or(
"Unexpected identity in router certificate",
@@ -2219,7 +2270,7 @@ int
connection_or_set_state_open(or_connection_t *conn)
{
connection_or_change_state(conn, OR_CONN_STATE_OPEN);
- control_event_or_conn_status(conn, OR_CONN_EVENT_CONNECTED, 0);
+ connection_or_event_status(conn, OR_CONN_EVENT_CONNECTED, 0);
/* Link protocol 3 appeared in Tor 0.2.3.6-alpha, so any connection
* that uses an earlier link protocol should not be treated as a relay. */