summaryrefslogtreecommitdiff
path: root/sample
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2009-10-23 17:40:00 +0000
committerNick Mathewson <nickm@torproject.org>2009-10-23 17:40:00 +0000
commitc119e4a13ff171aafff9e0f27f11f8cae389880e (patch)
tree40a2b3a8f98b9147207053ac9be5dae707530176 /sample
parentfdd11c00bb7a90d2f11a8933baa577ac199f74e3 (diff)
downloadlibevent-c119e4a13ff171aafff9e0f27f11f8cae389880e.tar.gz
Improve the behavior of le-proxy in a few cases.
svn:r1458
Diffstat (limited to 'sample')
-rw-r--r--sample/le-proxy.c53
1 files changed, 47 insertions, 6 deletions
diff --git a/sample/le-proxy.c b/sample/le-proxy.c
index d8355799..348bec39 100644
--- a/sample/le-proxy.c
+++ b/sample/le-proxy.c
@@ -26,25 +26,56 @@ static int use_wrapper = 1;
static SSL_CTX *ssl_ctx = NULL;
+#define MAX_OUTPUT (512*1024)
+
+static void drained_writecb(struct bufferevent *bev, void *ctx);
+static void eventcb(struct bufferevent *bev, short what, void *ctx);
+
static void
readcb(struct bufferevent *bev, void *ctx)
{
struct bufferevent *partner = ctx;
struct evbuffer *src, *dst;
+ size_t len;
src = bufferevent_get_input(bev);
+ len = evbuffer_get_length(src);
if (!partner) {
- evbuffer_drain(src, evbuffer_get_length(src));
+ evbuffer_drain(src, len);
return;
}
dst = bufferevent_get_output(partner);
-
evbuffer_add_buffer(dst, src);
+
+ if (evbuffer_get_length(dst) >= MAX_OUTPUT) {
+ /* We're giving the other side data faster than it can
+ * pass it on. Stop reading here until we have drained the
+ * other side to MAX_OUTPUT/2 bytes. */
+ bufferevent_setcb(partner, readcb, drained_writecb,
+ eventcb, bev);
+ bufferevent_setwatermark(partner, EV_WRITE, MAX_OUTPUT/2,
+ MAX_OUTPUT);
+ bufferevent_disable(bev, EV_READ);
+ }
+}
+
+static void
+drained_writecb(struct bufferevent *bev, void *ctx)
+{
+ struct bufferevent *partner = ctx;
+
+ /* We were choking the other side until we drained our outbuf a bit.
+ * Now it seems drained. */
+ bufferevent_setcb(bev, readcb, NULL, eventcb, partner);
+ bufferevent_setwatermark(bev, EV_WRITE, 0, 0);
+ if (partner)
+ bufferevent_enable(partner, EV_READ);
}
static void
close_on_finished_writecb(struct bufferevent *bev, void *ctx)
{
struct evbuffer *b = bufferevent_get_output(bev);
+
if (evbuffer_get_length(b) == 0) {
bufferevent_free(bev);
}
@@ -63,10 +94,20 @@ eventcb(struct bufferevent *bev, short what, void *ctx)
/* Flush all pending data */
readcb(bev, ctx);
- /* Disconnect this one from the partner. */
- bufferevent_setcb(partner,
- NULL, close_on_finished_writecb,
- eventcb, NULL);
+ if (evbuffer_get_length(
+ bufferevent_get_output(partner))) {
+ /* We still have to flush data from the other
+ * side, but when that's done, close the other
+ * side. */
+ bufferevent_setcb(partner,
+ NULL, close_on_finished_writecb,
+ eventcb, NULL);
+ bufferevent_disable(partner, EV_READ);
+ } else {
+ /* We have nothing left to say to the other
+ * side; close it. */
+ bufferevent_free(partner);
+ }
}
bufferevent_free(bev);
}