summaryrefslogtreecommitdiff
path: root/src/or/main.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2009-08-11 15:16:16 -0400
committerNick Mathewson <nickm@torproject.org>2010-09-27 12:31:13 -0400
commit4af6887d201d978a46072ead0036e0d16fa5908a (patch)
tree6d4c6d53f20ac02ef713fd01a211a57ff26c6510 /src/or/main.c
parentb63f6518cbdc4c80b09399bc17d3bec3cac76ad9 (diff)
downloadtor-4af6887d201d978a46072ead0036e0d16fa5908a.tar.gz
tor-4af6887d201d978a46072ead0036e0d16fa5908a.zip
Add support for linked connections with bufferevent_pair.
Also, set directory connections (linked and otherwise) to use bufferevents. Also, stop using outbuf_flushlen anywhere except for OR connections.
Diffstat (limited to 'src/or/main.c')
-rw-r--r--src/or/main.c90
1 files changed, 74 insertions, 16 deletions
diff --git a/src/or/main.c b/src/or/main.c
index 976d805e13..cba98a8849 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -155,6 +155,32 @@ int can_complete_circuit=0;
*
****************************************************************************/
+#ifdef USE_BUFFEREVENTS
+static void
+free_old_inbuf(connection_t *conn)
+{
+ if (! conn->inbuf)
+ return;
+
+ tor_assert(conn->outbuf);
+ tor_assert(buf_datalen(conn->inbuf) == 0);
+ tor_assert(buf_datalen(conn->outbuf) == 0);
+ buf_free(conn->inbuf);
+ buf_free(conn->outbuf);
+ conn->inbuf = conn->outbuf = NULL;
+
+ if (conn->read_event) {
+ event_del(conn->read_event);
+ tor_event_free(conn->read_event);
+ }
+ if (conn->write_event) {
+ event_del(conn->read_event);
+ tor_event_free(conn->write_event);
+ }
+ conn->read_event = conn->write_event = NULL;
+}
+#endif
+
/** Add <b>conn</b> to the array of connections that we can poll on. The
* connection's socket must be set; the connection starts out
* non-reading and non-writing.
@@ -173,28 +199,47 @@ connection_add_impl(connection_t *conn, int is_connecting)
smartlist_add(connection_array, conn);
#ifdef USE_BUFFEREVENTS
- if (connection_type_uses_bufferevent(conn) &&
- conn->s >= 0 && !conn->linked) {
- conn->bufev = bufferevent_socket_new(
+ if (connection_type_uses_bufferevent(conn)) {
+ if (conn->s >= 0 && !conn->linked) {
+ conn->bufev = bufferevent_socket_new(
tor_libevent_get_base(),
conn->s,
BEV_OPT_DEFER_CALLBACKS);
- if (conn->inbuf) {
+ /* XXXX CHECK FOR NULL RETURN! */
+ if (is_connecting) {
+ /* Put the bufferevent into a "connecting" state so that we'll get
+ * a "connected" event callback on successful write. */
+ bufferevent_socket_connect(conn->bufev, NULL, 0);
+ }
+ connection_configure_bufferevent_callbacks(conn);
+ } else if (conn->linked && conn->linked_conn &&
+ connection_type_uses_bufferevent(conn->linked_conn)) {
+ tor_assert(conn->s < 0);
+ if (!conn->bufev) {
+ struct bufferevent *pair[2] = { NULL, NULL };
+ /* XXXX CHECK FOR ERROR RETURN! */
+ bufferevent_pair_new(tor_libevent_get_base(),
+ BEV_OPT_DEFER_CALLBACKS,
+ pair);
+ tor_assert(pair[0]);
+ conn->bufev = pair[0];
+ conn->linked_conn->bufev = pair[1];
+ } /* else the other side already was added, and got a bufferevent_pair */
+ connection_configure_bufferevent_callbacks(conn);
+ }
+
+ if (conn->bufev && conn->inbuf) {
/* XXX Instead we should assert that there is no inbuf, once we
* have linked connections using bufferevents. */
- tor_assert(conn->outbuf);
- tor_assert(buf_datalen(conn->inbuf) == 0);
- tor_assert(buf_datalen(conn->outbuf) == 0);
- buf_free(conn->inbuf);
- buf_free(conn->outbuf);
- conn->inbuf = conn->outbuf = NULL;
+ free_old_inbuf(conn);
}
- if (is_connecting) {
- /* Put the bufferevent into a "connecting" state so that we'll get
- * a "connected" event callback on successful write. */
- bufferevent_socket_connect(conn->bufev, NULL, 0);
+
+ if (conn->linked_conn && conn->linked_conn->bufev &&
+ conn->linked_conn->inbuf) {
+ /* XXX Instead we should assert that there is no inbuf, once we
+ * have linked connections using bufferevents. */
+ free_old_inbuf(conn->linked_conn);
}
- connection_configure_bufferevent_callbacks(conn);
}
#else
(void) is_connecting;
@@ -205,6 +250,7 @@ connection_add_impl(connection_t *conn, int is_connecting)
conn->s, EV_READ|EV_PERSIST, conn_read_callback, conn);
conn->write_event = tor_event_new(tor_libevent_get_base(),
conn->s, EV_WRITE|EV_PERSIST, conn_write_callback, conn);
+ /* XXXX CHECK FOR NULL RETURN! */
}
log_debug(LD_NET,"new conn type %s, socket %d, address %s, n_conns %d.",
@@ -671,11 +717,19 @@ conn_close_if_marked(int i)
/* assert_all_pending_dns_resolves_ok(); */
#ifdef USE_BUFFEREVENTS
- if (conn->bufev && conn->hold_open_until_flushed)
+ if (conn->bufev && conn->hold_open_until_flushed) {
+ if (conn->linked) {
+ /* 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;
+ }
#endif
log_debug(LD_NET,"Cleaning up connection (fd %d).",conn->s);
+ IF_HAS_BUFFEREVENT(conn, goto unlink);
if ((conn->s >= 0 || conn->linked_conn) && connection_wants_to_flush(conn)) {
/* s == -1 means it's an incomplete edge connection, or that the socket
* has already been closed as unflushable. */
@@ -743,6 +797,10 @@ conn_close_if_marked(int i)
conn->marked_for_close);
}
}
+
+#ifdef USE_BUFFEREVENTS
+ unlink:
+#endif
connection_unlink(conn); /* unlink, remove, free */
return 1;
}