aboutsummaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2009-08-14 14:34:16 -0400
committerNick Mathewson <nickm@torproject.org>2010-09-27 12:31:14 -0400
commitbd3612cd2b4c49fd9f9aec68b6268973e43f2b63 (patch)
treeec5e092ec63d687a326618e805066731abac637b /src/or
parentfc4ddafab81d5ca229436eeb0c460634e03cb2ca (diff)
downloadtor-bd3612cd2b4c49fd9f9aec68b6268973e43f2b63.tar.gz
tor-bd3612cd2b4c49fd9f9aec68b6268973e43f2b63.zip
Get SSL connections and linked connections working with bufferevents.
Clients are now verified to work and build circuits correctly. There are still a few warnings given here and there that I need to look into.
Diffstat (limited to 'src/or')
-rw-r--r--src/or/Makefile.am4
-rw-r--r--src/or/buffers.c2
-rw-r--r--src/or/connection.c22
-rw-r--r--src/or/connection.h4
-rw-r--r--src/or/connection_or.c91
-rw-r--r--src/or/main.c4
6 files changed, 115 insertions, 12 deletions
diff --git a/src/or/Makefile.am b/src/or/Makefile.am
index a9ac3cdee1..b1add7cb64 100644
--- a/src/or/Makefile.am
+++ b/src/or/Makefile.am
@@ -45,6 +45,10 @@ tor_LDADD = ./libtor.a ../common/libor.a ../common/libor-crypto.a \
../common/libor-event.a \
@TOR_ZLIB_LIBS@ -lm @TOR_LIBEVENT_LIBS@ @TOR_OPENSSL_LIBS@ @TOR_LIB_WS32@ @TOR_LIB_GDI@
+if USE_BUFFEREVENTS
+tor_LDADD += -levent_openssl
+endif
+
noinst_HEADERS = buffers.h circuitbuild.h circuitlist.h circuituse.h \
command.h config.h connection_edge.h connection.h connection_or.h \
control.h cpuworker.h directory.h dirserv.h dirvote.h dns.h \
diff --git a/src/or/buffers.c b/src/or/buffers.c
index b750a0540c..ffdbcd3b4f 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -1083,7 +1083,7 @@ fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out,
goto done;
}
n = inspect_evbuffer(buf, &hdr, VAR_CELL_HEADER_SIZE, &free_hdr, NULL);
- tor_assert(n == VAR_CELL_HEADER_SIZE);
+ tor_assert(n >= VAR_CELL_HEADER_SIZE);
command = get_uint8(hdr+2);
if (!(CELL_COMMAND_IS_VAR_LENGTH(command))) {
diff --git a/src/or/connection.c b/src/or/connection.c
index 570eceeef0..b39763055c 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -36,6 +36,10 @@
#include "router.h"
#include "routerparse.h"
+#ifdef USE_BUFFEREVENTS
+#include <event2/event.h>
+#endif
+
static connection_t *connection_create_listener(
struct sockaddr *listensockaddr,
socklen_t listensocklen, int type,
@@ -194,6 +198,7 @@ connection_type_uses_bufferevent(connection_t *conn)
case CONN_TYPE_EXIT:
case CONN_TYPE_DIR:
case CONN_TYPE_CONTROL:
+ case CONN_TYPE_OR:
return 1;
default:
return 0;
@@ -2648,6 +2653,7 @@ evbuffer_inbuf_callback(struct evbuffer *buf,
}
}
+/** DOCDOC */
static void
evbuffer_outbuf_callback(struct evbuffer *buf,
const struct evbuffer_cb_info *info, void *arg)
@@ -2667,7 +2673,8 @@ evbuffer_outbuf_callback(struct evbuffer *buf,
}
}
-static void
+/** DOCDOC */
+void
connection_handle_read_cb(struct bufferevent *bufev, void *arg)
{
connection_t *conn = arg;
@@ -2677,7 +2684,8 @@ connection_handle_read_cb(struct bufferevent *bufev, void *arg)
connection_mark_for_close(conn);
}
-static void
+/** DOCDOC */
+void
connection_handle_write_cb(struct bufferevent *bufev, void *arg)
{
connection_t *conn = arg;
@@ -2690,12 +2698,18 @@ connection_handle_write_cb(struct bufferevent *bufev, void *arg)
output = bufferevent_get_output(bufev);
if (!evbuffer_get_length(output)) {
connection_finished_flushing(conn);
- if (conn->marked_for_close && conn->hold_open_until_flushed)
+ if (conn->marked_for_close && conn->hold_open_until_flushed) {
conn->hold_open_until_flushed = 0;
+ if (conn->linked) {
+ /* send eof */
+ bufferevent_flush(conn->bufev, EV_WRITE, BEV_FINISHED);
+ }
+ }
}
}
-static void
+/** DOCDOC */
+void
connection_handle_event_cb(struct bufferevent *bufev, short event, void *arg)
{
connection_t *conn = arg;
diff --git a/src/or/connection.h b/src/or/connection.h
index adf79f1391..83aec0ef00 100644
--- a/src/or/connection.h
+++ b/src/or/connection.h
@@ -140,6 +140,10 @@ void remove_file_if_very_old(const char *fname, time_t now);
#ifdef USE_BUFFEREVENTS
int connection_type_uses_bufferevent(connection_t *conn);
void connection_configure_bufferevent_callbacks(connection_t *conn);
+void connection_handle_read_cb(struct bufferevent *bufev, void *arg);
+void connection_handle_write_cb(struct bufferevent *bufev, void *arg);
+void connection_handle_event_cb(struct bufferevent *bufev, short event,
+ void *arg);
#else
#define connection_type_uses_bufferevent(c) (0)
#endif
diff --git a/src/or/connection_or.c b/src/or/connection_or.c
index a2eb868d95..2fbc230bcd 100644
--- a/src/or/connection_or.c
+++ b/src/or/connection_or.c
@@ -28,6 +28,10 @@
#include "router.h"
#include "routerlist.h"
+#ifdef USE_BUFFEREVENTS
+#include <event2/bufferevent_ssl.h>
+#endif
+
static int connection_tls_finish_handshake(or_connection_t *conn);
static int connection_or_process_cells_from_inbuf(or_connection_t *conn);
static int connection_or_send_versions(or_connection_t *conn);
@@ -37,6 +41,12 @@ static int connection_or_check_valid_tls_handshake(or_connection_t *conn,
int started_here,
char *digest_rcvd_out);
+#ifdef USE_BUFFEREVENTS
+static void connection_or_handle_event_cb(struct bufferevent *bufev,
+ short event, void *arg);
+#include <event2/buffer.h>/*XXXX REMOVE */
+#endif
+
/**************************************************************/
/** Map from identity digest of connected OR or desired OR to a connection_t
@@ -851,6 +861,7 @@ int
connection_tls_start_handshake(or_connection_t *conn, int receiving)
{
conn->_base.state = OR_CONN_STATE_TLS_HANDSHAKING;
+ tor_assert(!conn->tls);
conn->tls = tor_tls_new(conn->_base.s, receiving);
tor_tls_set_logged_address(conn->tls, // XXX client and relay?
escaped_safe_str(conn->_base.address));
@@ -858,12 +869,31 @@ connection_tls_start_handshake(or_connection_t *conn, int receiving)
log_warn(LD_BUG,"tor_tls_new failed. Closing.");
return -1;
}
+#ifdef USE_BUFFEREVENTS
+ if (connection_type_uses_bufferevent(TO_CONN(conn))) {
+ struct bufferevent *b =
+ tor_tls_init_bufferevent(conn->tls, conn->_base.bufev, conn->_base.s,
+ receiving);
+ if (!b) {
+ log_warn(LD_BUG,"tor_tls_init_bufferevent failed. Closing.");
+ return -1;
+ }
+ conn->_base.bufev = b;
+ bufferevent_setcb(b, connection_handle_read_cb,
+ connection_handle_write_cb,
+ connection_or_handle_event_cb,
+ TO_CONN(conn));
+ }
+#endif
connection_start_reading(TO_CONN(conn));
log_debug(LD_HANDSHAKE,"starting TLS handshake on fd %d", conn->_base.s);
note_crypto_pk_op(receiving ? TLS_HANDSHAKE_S : TLS_HANDSHAKE_C);
- if (connection_tls_continue_handshake(conn) < 0) {
- return -1;
+ IF_HAS_BUFFEREVENT(TO_CONN(conn), {
+ /* ???? */;
+ }) ELSE_IF_NO_BUFFEREVENT {
+ if (connection_tls_continue_handshake(conn) < 0)
+ return -1;
}
return 0;
}
@@ -948,6 +978,53 @@ connection_tls_continue_handshake(or_connection_t *conn)
return 0;
}
+#ifdef USE_BUFFEREVENTS
+static void
+connection_or_handle_event_cb(struct bufferevent *bufev, short event,
+ void *arg)
+{
+ struct or_connection_t *conn = TO_OR_CONN(arg);
+
+ /* XXXX cut-and-paste code; should become a function. */
+ if (event & BEV_EVENT_CONNECTED) {
+ if (conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) {
+ if (tor_tls_finish_handshake(conn->tls) < 0) {
+ log_warn(LD_OR, "Problem finishing handshake");
+ connection_mark_for_close(TO_CONN(conn));
+ return;
+ }
+ }
+
+ if (! tor_tls_used_v1_handshake(conn->tls)) {
+ if (!tor_tls_is_server(conn->tls)) {
+ if (conn->_base.state == OR_CONN_STATE_TLS_HANDSHAKING) {
+ conn->_base.state = OR_CONN_STATE_TLS_CLIENT_RENEGOTIATING;
+ if (bufferevent_ssl_renegotiate(conn->_base.bufev)<0) {
+ log_warn(LD_OR, "Start_renegotiating went badly.");
+ connection_mark_for_close(TO_CONN(conn));
+ }
+ return; /* ???? */
+ }
+ } else {
+ /* improved handshake, but not a client. */
+ tor_tls_set_renegotiate_callback(conn->tls,
+ connection_or_tls_renegotiated_cb,
+ conn);
+ conn->_base.state = OR_CONN_STATE_TLS_SERVER_RENEGOTIATING;
+ /* return 0; */
+ return; /* ???? */
+ }
+ }
+ connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
+ if (connection_tls_finish_handshake(conn) < 0)
+ connection_mark_for_close(TO_CONN(conn)); /* ???? */
+ return;
+ }
+
+ connection_handle_event_cb(bufev, event, arg);
+}
+#endif
+
/** Return 1 if we initiated this connection, or 0 if it started
* out as an incoming connection.
*/
@@ -1208,8 +1285,12 @@ connection_or_set_state_open(or_connection_t *conn)
or_handshake_state_free(conn->handshake_state);
conn->handshake_state = NULL;
+ IF_HAS_BUFFEREVENT(TO_CONN(conn), {
+ connection_watch_events(TO_CONN(conn), READ_EVENT|WRITE_EVENT);
+ }) ELSE_IF_NO_BUFFEREVENT {
+ connection_start_reading(TO_CONN(conn));
+ }
- connection_start_reading(TO_CONN(conn));
circuit_n_conn_done(conn, 1); /* send the pending creates, if any. */
return 0;
@@ -1260,8 +1341,8 @@ connection_fetch_var_cell_from_buf(or_connection_t *or_conn, var_cell_t **out)
{
connection_t *conn = TO_CONN(or_conn);
IF_HAS_BUFFEREVENT(conn, {
- struct evbuffer *input = bufferevent_get_input(conn->bufev);
- return fetch_var_cell_from_evbuffer(input, out, or_conn->link_proto);
+ struct evbuffer *input = bufferevent_get_input(conn->bufev);
+ return fetch_var_cell_from_evbuffer(input, out, or_conn->link_proto);
}) ELSE_IF_NO_BUFFEREVENT {
return fetch_var_cell_from_buf(conn->inbuf, out, or_conn->link_proto);
}
diff --git a/src/or/main.c b/src/or/main.c
index cba98a8849..263103662c 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -722,9 +722,9 @@ conn_close_if_marked(int i)
/* We need to do this explicitly so that the linked connection
* notices that there was an EOF. */
bufferevent_flush(conn->bufev, EV_WRITE, BEV_FINISHED);
- /* XXXX Now can we free it? */
}
- return 0;
+ if (evbuffer_get_length(bufferevent_get_output(conn->bufev)))
+ return 0;
}
#endif