diff options
-rw-r--r-- | changes/bug3804 | 9 | ||||
-rw-r--r-- | changes/bug3805 | 5 | ||||
-rw-r--r-- | src/common/compat_libevent.c | 26 | ||||
-rw-r--r-- | src/common/compat_libevent.h | 6 | ||||
-rw-r--r-- | src/common/tortls.c | 5 | ||||
-rw-r--r-- | src/or/connection.c | 7 | ||||
-rw-r--r-- | src/or/connection_or.c | 4 |
7 files changed, 59 insertions, 3 deletions
diff --git a/changes/bug3804 b/changes/bug3804 new file mode 100644 index 0000000000..7ad091c172 --- /dev/null +++ b/changes/bug3804 @@ -0,0 +1,9 @@ + o Major bugfixes (bufferevents): + - Apply rate-limiting only at the bottom of a chain of filtering + bufferevents. This prevents us from filling up internal read + buffers and violating rate-limits when filtering bufferevents + are enabled. Bugfix on 0.2.3.1-alpha; fixes part of bug 3804. + - Add high-watermarks to the output buffers for filtered + bufferevents. This prevents us from filling up internal write + buffers and wasting CPU cycles when filtering bufferevents are + enabled. Bugfix on 0.2.3.1-alpha; fixes part of bug 3804. diff --git a/changes/bug3805 b/changes/bug3805 new file mode 100644 index 0000000000..9d12b8146e --- /dev/null +++ b/changes/bug3805 @@ -0,0 +1,5 @@ + o Major bugfixes (bufferevents): + - Correctly notice when data has been written from a bufferevent + without flushing it completely. Bugfix on 0.2.3.1-alpha; fixes + bug 3805. + diff --git a/src/common/compat_libevent.c b/src/common/compat_libevent.c index 595742f961..beae9502da 100644 --- a/src/common/compat_libevent.c +++ b/src/common/compat_libevent.c @@ -20,6 +20,9 @@ #ifdef HAVE_EVENT2_EVENT_H #include <event2/event.h> #include <event2/thread.h> +#ifdef USE_BUFFEREVENTS +#include <event2/bufferevent.h> +#endif #else #include <event.h> #endif @@ -614,5 +617,28 @@ tor_libevent_get_one_tick_timeout(void) } return one_tick; } + +static struct bufferevent * +tor_get_root_bufferevent(struct bufferevent *bev) +{ + struct bufferevent *u; + while ((u = bufferevent_get_underlying(bev)) != NULL) + bev = u; + return bev; +} + +int +tor_set_bufferevent_rate_limit(struct bufferevent *bev, + struct ev_token_bucket_cfg *cfg) +{ + return bufferevent_set_rate_limit(tor_get_root_bufferevent(bev), cfg); +} + +int +tor_add_bufferevent_to_rate_limit_group(struct bufferevent *bev, + struct bufferevent_rate_limit_group *g) +{ + return bufferevent_add_to_rate_limit_group(tor_get_root_bufferevent(bev), g); +} #endif diff --git a/src/common/compat_libevent.h b/src/common/compat_libevent.h index bbe105bf40..15b0fc273b 100644 --- a/src/common/compat_libevent.h +++ b/src/common/compat_libevent.h @@ -10,6 +10,8 @@ struct event; struct event_base; #ifdef USE_BUFFEREVENTS struct bufferevent; +struct ev_token_bucket_cfg; +struct bufferevent_rate_limit_group; #endif #ifdef HAVE_EVENT2_EVENT_H @@ -74,6 +76,10 @@ const char *tor_libevent_get_version_str(void); #define TOR_LIBEVENT_TICKS_PER_SECOND 3 const struct timeval *tor_libevent_get_one_tick_timeout(void); int tor_libevent_using_iocp_bufferevents(void); +int tor_set_bufferevent_rate_limit(struct bufferevent *bev, + struct ev_token_bucket_cfg *cfg); +int tor_add_bufferevent_to_rate_limit_group(struct bufferevent *bev, + struct bufferevent_rate_limit_group *g); #endif #endif diff --git a/src/common/tortls.c b/src/common/tortls.c index 2aaa2c49b5..1bb9c74efa 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -51,6 +51,7 @@ #ifdef USE_BUFFEREVENTS #include <event2/bufferevent_ssl.h> #include <event2/buffer.h> +#include <event2/event.h> #include "compat_libevent.h" #endif @@ -1905,6 +1906,10 @@ tor_tls_init_bufferevent(tor_tls_t *tls, struct bufferevent *bufev_in, state, BEV_OPT_DEFER_CALLBACKS| BEV_OPT_CLOSE_ON_FREE); + /* Tell the underlying bufferevent when to accept more data from the SSL + filter (only when it's got less than 32K to write), and when to notify + the SSL filter that it could write more (when it drops under 24K). */ + bufferevent_setwatermark(bufev_in, EV_WRITE, 24*1024, 32*1024); } else { if (bufev_in) { evutil_socket_t s = bufferevent_getfd(bufev_in); diff --git a/src/or/connection.c b/src/or/connection.c index f8f82a30dd..dc804ddcec 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -2509,7 +2509,7 @@ connection_enable_rate_limiting(connection_t *conn) if (conn->bufev) { if (!global_rate_limit) connection_bucket_init(); - bufferevent_add_to_rate_limit_group(conn->bufev, global_rate_limit); + tor_add_bufferevent_to_rate_limit_group(conn->bufev, global_rate_limit); } } @@ -2947,6 +2947,11 @@ connection_configure_bufferevent_callbacks(connection_t *conn) connection_handle_write_cb, connection_handle_event_cb, conn); + /* Set a fairly high write low-watermark so that we get the write callback + called whenever data is written to bring us under 128K. Leave the + high-watermark at 0. + */ + bufferevent_setwatermark(bufev, EV_WRITE, 128*1024, 0); input = bufferevent_get_input(bufev); output = bufferevent_get_output(bufev); diff --git a/src/or/connection_or.c b/src/or/connection_or.c index e66d36a2f3..a75444e1ed 100644 --- a/src/or/connection_or.c +++ b/src/or/connection_or.c @@ -585,7 +585,7 @@ connection_or_update_token_buckets_helper(or_connection_t *conn, int reset, burst, tick); old_cfg = conn->bucket_cfg; if (conn->_base.bufev) - bufferevent_set_rate_limit(conn->_base.bufev, cfg); + tor_set_bufferevent_rate_limit(conn->_base.bufev, cfg); if (old_cfg) ev_token_bucket_cfg_free(old_cfg); conn->bucket_cfg = cfg; @@ -1102,7 +1102,7 @@ connection_tls_start_handshake(or_connection_t *conn, int receiving) } conn->_base.bufev = b; if (conn->bucket_cfg) - bufferevent_set_rate_limit(conn->_base.bufev, conn->bucket_cfg); + tor_set_bufferevent_rate_limit(conn->_base.bufev, conn->bucket_cfg); connection_enable_rate_limiting(TO_CONN(conn)); connection_configure_bufferevent_callbacks(TO_CONN(conn)); |