commit 21de9d46e264ceb14f3fe59d17210d82f2499637 Merge: 5dc3c46 da7c60d Author: Nick Mathewson nickm@torproject.org Date: Mon May 30 14:58:26 2011 -0400
Merge remote-tracking branch 'origin/maint-0.2.2'
Conflicts: src/common/compat.c src/or/main.c
changes/bug3270 | 4 ++ src/common/compat.c | 32 +++++++++++---------- src/common/compat.h | 21 ++++++++++---- src/common/compat_libevent.h | 4 ++ src/common/util.c | 8 ++-- src/common/util.h | 4 +- src/or/buffers.c | 8 ++-- src/or/buffers.h | 4 +- src/or/connection.c | 50 +++++++++++++++++--------------- src/or/control.c | 2 +- src/or/cpuworker.c | 10 +++--- src/or/dnsserv.c | 2 +- src/or/eventdns.c | 2 +- src/or/eventdns.h | 2 +- src/or/main.c | 64 +++++++++++++++++++++-------------------- src/or/or.h | 2 +- 16 files changed, 121 insertions(+), 98 deletions(-)
diff --cc src/common/compat.c index 1d00e30,9377959..61a4a6f --- a/src/common/compat.c +++ b/src/common/compat.c @@@ -946,19 -919,11 +948,19 @@@ mark_socket_open(tor_socket_t s /** @} */
/** As socket(), but counts the number of open sockets. */ - int + tor_socket_t tor_open_socket(int domain, int type, int protocol) { - int s; - tor_socket_t s = socket(domain, type, protocol); ++ tor_socket_t s; +#ifdef SOCK_CLOEXEC +#define LINUX_CLOEXEC_OPEN_SOCKET + type |= SOCK_CLOEXEC; +#endif + s = socket(domain, type, protocol); - if (s >= 0) { + if (SOCKET_OK(s)) { +#if !defined(LINUX_CLOEXEC_OPEN_SOCKET) && defined(FD_CLOEXEC) + fcntl(s, F_SETFD, FD_CLOEXEC); +#endif socket_accounting_lock(); ++n_sockets_open; mark_socket_open(s); @@@ -968,20 -933,11 +970,20 @@@ }
/** As socket(), but counts the number of open sockets. */ - int + tor_socket_t tor_accept_socket(int sockfd, struct sockaddr *addr, socklen_t *len) { - int s; - tor_socket_t s = accept(sockfd, addr, len); ++ tor_socket_t s; +#if defined(HAVE_ACCEPT4) && defined(SOCK_CLOEXEC) +#define LINUX_CLOEXEC_ACCEPT + s = accept4(sockfd, addr, len, SOCK_CLOEXEC); +#else + s = accept(sockfd, addr, len); +#endif - if (s >= 0) { + if (SOCKET_OK(s)) { +#if !defined(LINUX_CLOEXEC_ACCEPT) && defined(FD_CLOEXEC) + fcntl(s, F_SETFD, FD_CLOEXEC); +#endif socket_accounting_lock(); ++n_sockets_open; mark_socket_open(s); diff --cc src/common/compat_libevent.h index ecf2580,1decc8d..496544d --- a/src/common/compat_libevent.h +++ b/src/common/compat_libevent.h @@@ -8,10 -8,8 +8,11 @@@
struct event; struct event_base; +#ifdef USE_BUFFEREVENTS +struct bufferevent; +#endif
+ #ifdef HAVE_EVENT2_EVENT_H #include <event2/util.h> #else diff --cc src/or/connection.c index 7faeeb0,6644b4c..364816a --- a/src/or/connection.c +++ b/src/or/connection.c @@@ -1361,10 -1318,11 +1361,11 @@@ in connection_connect(connection_t *conn, const char *address, const tor_addr_t *addr, uint16_t port, int *socket_error) { - int s, inprogress = 0; + tor_socket_t s; + int inprogress = 0; char addrbuf[256]; struct sockaddr *dest_addr; - socklen_t dest_addr_len; + int dest_addr_len; or_options_t *options = get_options(); int protocol_family;
@@@ -3966,18 -3542,11 +3968,18 @@@ assert_connection_ok(connection_t *conn tor_assert(conn->linked); } if (conn->linked) - tor_assert(conn->s < 0); + tor_assert(!SOCKET_OK(conn->s));
if (conn->outbuf_flushlen > 0) { - tor_assert(connection_is_writing(conn) || conn->write_blocked_on_bw || - (CONN_IS_EDGE(conn) && TO_EDGE_CONN(conn)->edge_blocked_on_circ)); + /* With optimistic data, we may have queued data in + * EXIT_CONN_STATE_RESOLVING while the conn is not yet marked to writing. + * */ + tor_assert((conn->type == CONN_TYPE_EXIT && + conn->state == EXIT_CONN_STATE_RESOLVING) || + connection_is_writing(conn) || + conn->write_blocked_on_bw || + (CONN_IS_EDGE(conn) && + TO_EDGE_CONN(conn)->edge_blocked_on_circ)); }
if (conn->hold_open_until_flushed) diff --cc src/or/main.c index 303d506,adbde90..7d9a85a --- a/src/or/main.c +++ b/src/or/main.c @@@ -192,10 -155,10 +192,10 @@@ free_old_inbuf(connection_t *conn * non-reading and non-writing. */ int -connection_add(connection_t *conn) +connection_add_impl(connection_t *conn, int is_connecting) { tor_assert(conn); - tor_assert(conn->s >= 0 || + tor_assert(SOCKET_OK(conn->s) || conn->linked || (conn->type == CONN_TYPE_AP && TO_EDGE_CONN(conn)->is_dns_request)); @@@ -204,58 -167,7 +204,58 @@@ conn->conn_array_index = smartlist_len(connection_array); smartlist_add(connection_array, conn);
- if (SOCKET_OK(conn->s) || conn->linked) { +#ifdef USE_BUFFEREVENTS + if (connection_type_uses_bufferevent(conn)) { - if (conn->s >= 0 && !conn->linked) { ++ if (SOCKET_OK(conn->s) && !conn->linked) { + conn->bufev = bufferevent_socket_new( + tor_libevent_get_base(), + conn->s, + BEV_OPT_DEFER_CALLBACKS); + if (!conn->bufev) { + log_warn(LD_BUG, "Unable to create socket bufferevent"); + smartlist_del(connection_array, conn->conn_array_index); + conn->conn_array_index = -1; + return -1; + } + 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); ++ tor_assert(!(SOCKET_OK(conn->s)); + if (!conn->bufev) { + struct bufferevent *pair[2] = { NULL, NULL }; + if (bufferevent_pair_new(tor_libevent_get_base(), + BEV_OPT_DEFER_CALLBACKS, + pair) < 0) { + log_warn(LD_BUG, "Unable to create bufferevent pair"); + smartlist_del(connection_array, conn->conn_array_index); + conn->conn_array_index = -1; + return -1; + } + 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); + } else { + tor_assert(!conn->linked); + } + + if (conn->bufev) + tor_assert(conn->inbuf == NULL); + + if (conn->linked_conn && conn->linked_conn->bufev) + tor_assert(conn->linked_conn->inbuf == NULL); + } +#else + (void) is_connecting; +#endif + - if (!HAS_BUFFEREVENT(conn) && (conn->s >= 0 || conn->linked)) { ++ if (!HAS_BUFFEREVENT(conn) && (SOCKET_OK(conn->s) || conn->linked)) { conn->read_event = tor_event_new(tor_libevent_get_base(), conn->s, EV_READ|EV_PERSIST, conn_read_callback, conn); conn->write_event = tor_event_new(tor_libevent_get_base(), @@@ -281,15 -192,9 +281,15 @@@ connection_unregister_events(connection } if (conn->write_event) { if (event_del(conn->write_event)) - log_warn(LD_BUG, "Error removing write event for %d", conn->s); + log_warn(LD_BUG, "Error removing write event for %d", (int)conn->s); tor_free(conn->write_event); } +#ifdef USE_BUFFEREVENTS + if (conn->bufev) { + bufferevent_free(conn->bufev); + conn->bufev = NULL; + } +#endif if (conn->dns_server_port) { dnsserv_close_listener(conn); } @@@ -740,24 -590,9 +741,25 @@@ conn_close_if_marked(int i assert_connection_ok(conn, now); /* assert_all_pending_dns_resolves_ok(); */
- log_debug(LD_NET,"Cleaning up connection (fd %d).",(int)conn->s); - if ((SOCKET_OK(conn->s) || conn->linked_conn) - && connection_wants_to_flush(conn)) { +#ifdef USE_BUFFEREVENTS + if (conn->bufev) { + if (conn->hold_open_until_flushed && + evbuffer_get_length(bufferevent_get_output(conn->bufev))) { + /* don't close yet. */ + return 0; + } + if (conn->linked_conn && ! conn->linked_conn->marked_for_close) { + /* 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); + } + } +#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)) { ++ if ((SOCKET_OK(conn->s) || 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. */ ssize_t sz = connection_bucket_write_limit(conn, now); @@@ -817,9 -652,9 +819,9 @@@ "something is wrong with your network connection, or " "something is wrong with theirs. " "(fd %d, type %s, state %d, marked at %s:%d).", - (int)buf_datalen(conn->outbuf), + (int)connection_get_outbuf_len(conn), escaped_safe_str_client(conn->address), - conn->s, conn_type_to_string(conn->type), conn->state, + (int)conn->s, conn_type_to_string(conn->type), conn->state, conn->marked_for_close_file, conn->marked_for_close); } @@@ -982,26 -808,28 +984,26 @@@ run_connection_housekeeping(int i, time /* We're hibernating, there's no circuits, and nothing to flush.*/ log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) " "[Hibernating or exiting].", - conn->s,conn->address, conn->port); + (int)conn->s,conn->address, conn->port); - connection_mark_for_close(conn); - conn->hold_open_until_flushed = 1; + connection_mark_and_flush(conn); } else if (!or_conn->n_circuits && now >= or_conn->timestamp_last_added_nonpadding + IDLE_OR_CONN_TIMEOUT) { log_info(LD_OR,"Expiring non-used OR connection to fd %d (%s:%d) " - "[idle %d].", conn->s,conn->address, conn->port, + "[idle %d].", (int)conn->s,conn->address, conn->port, (int)(now - or_conn->timestamp_last_added_nonpadding)); connection_mark_for_close(conn); - conn->hold_open_until_flushed = 1; } else if ( now >= or_conn->timestamp_lastempty + options->KeepalivePeriod*10 && now >= conn->timestamp_lastwritten + options->KeepalivePeriod*10) { log_fn(LOG_PROTOCOL_WARN,LD_PROTOCOL, "Expiring stuck OR connection to fd %d (%s:%d). (%d bytes to " "flush; %d seconds since last write)", - conn->s, conn->address, conn->port, + (int)conn->s, conn->address, conn->port, - (int)buf_datalen(conn->outbuf), + (int)connection_get_outbuf_len(conn), (int)(now-conn->timestamp_lastwritten)); connection_mark_for_close(conn); - } else if (past_keepalive && !buf_datalen(conn->outbuf)) { + } else if (past_keepalive && !connection_get_outbuf_len(conn)) { /* send a padding cell */ log_fn(LOG_DEBUG,LD_OR,"Sending keepalive to (%s:%d)", conn->address, conn->port); diff --cc src/or/or.h index 4aa1ba2,97fecd1..7daf195 --- a/src/or/or.h +++ b/src/or/or.h @@@ -982,9 -970,8 +982,9 @@@ typedef struct connection_t unsigned int proxy_state:4;
/** Our socket; -1 if this connection is closed, or has no socket. */ - evutil_socket_t s; + tor_socket_t s; int conn_array_index; /**< Index into the global connection array. */ + struct event *read_event; /**< Libevent event structure. */ struct event *write_event; /**< Libevent event structure. */ buf_t *inbuf; /**< Buffer holding data read over this connection. */