ソースを参照

Merge branch 'bufev_ratelim_and_wm'

Nick Mathewson 12 年 前
コミット
b161674d5d

+ 9 - 0
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.

+ 5 - 0
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.
+

+ 26 - 0
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
 

+ 6 - 0
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

+ 5 - 0
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);

+ 6 - 1
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);

+ 2 - 2
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));