diff options
author | Nick Mathewson <nickm@torproject.org> | 2009-08-11 15:16:16 -0400 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2010-09-27 12:31:13 -0400 |
commit | 4af6887d201d978a46072ead0036e0d16fa5908a (patch) | |
tree | 6d4c6d53f20ac02ef713fd01a211a57ff26c6510 /src/or/main.c | |
parent | b63f6518cbdc4c80b09399bc17d3bec3cac76ad9 (diff) | |
download | tor-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.c | 90 |
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; } |