[or-cvs] [tor/master 27/38] Get zlib compression working with bufferevents.

nickm at torproject.org nickm at torproject.org
Mon Sep 27 20:51:00 UTC 2010


Author: Nick Mathewson <nickm at torproject.org>
Date: Wed, 26 Aug 2009 15:33:19 -0400
Subject: Get zlib compression working with bufferevents.
Commit: 0c9b64d449a725dc2f9f043d174b581e3a5d9cb2

---
 src/or/buffers.c    |   55 +++++++++++++++++++++++++++++++++++++++++++++++++++
 src/or/buffers.h    |    3 ++
 src/or/connection.c |   18 ++++++++++++----
 3 files changed, 71 insertions(+), 5 deletions(-)

diff --git a/src/or/buffers.c b/src/or/buffers.c
index b9e1c53..eaa7427 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -2190,6 +2190,61 @@ write_to_buf_zlib(buf_t *buf, tor_zlib_state_t *state,
   return 0;
 }
 
+#ifdef USE_BUFFEREVENTS
+int
+write_to_evbuffer_zlib(struct evbuffer *buf, tor_zlib_state_t *state,
+                       const char *data, size_t data_len,
+                       int done)
+{
+  char *next;
+  size_t old_avail, avail;
+  int over = 0, n;
+  struct evbuffer_iovec vec[1];
+  do {
+    int need_new_chunk = 0;
+    {
+      size_t cap = data_len / 4;
+      if (cap < 128)
+        cap = 128;
+      /* XXXX NM this strategy is fragmentation-prone. We should really have
+       * two iovecs, and write first into the one, and then into the
+       * second if the first gets full. */
+      n = evbuffer_reserve_space(buf, cap, vec, 1);
+      tor_assert(n == 1);
+    }
+
+    next = vec[0].iov_base;
+    avail = old_avail = vec[0].iov_len;
+
+    switch (tor_zlib_process(state, &next, &avail, &data, &data_len, done)) {
+      case TOR_ZLIB_DONE:
+        over = 1;
+        break;
+      case TOR_ZLIB_ERR:
+        return -1;
+      case TOR_ZLIB_OK:
+        if (data_len == 0)
+          over = 1;
+        break;
+      case TOR_ZLIB_BUF_FULL:
+        if (avail) {
+          /* Zlib says we need more room (ZLIB_BUF_FULL).  Start a new chunk
+           * automatically, whether were going to or not. */
+          need_new_chunk = 1;
+        }
+        break;
+    }
+
+    /* XXXX possible infinite loop on BUF_FULL. */
+    vec[0].iov_len = old_avail - avail;
+    evbuffer_commit_space(buf, vec, 1);
+
+  } while (!over);
+  check();
+  return 0;
+}
+#endif
+
 /** Log an error and exit if <b>buf</b> is corrupted.
  */
 void
diff --git a/src/or/buffers.h b/src/or/buffers.h
index 64e1f55..35c1dd2 100644
--- a/src/or/buffers.h
+++ b/src/or/buffers.h
@@ -60,6 +60,9 @@ int fetch_from_evbuffer_http(struct evbuffer *buf,
                         char **body_out, size_t *body_used, size_t max_bodylen,
                         int force_complete);
 int peek_evbuffer_has_control0_command(struct evbuffer *buf);
+int write_to_evbuffer_zlib(struct evbuffer *buf, tor_zlib_state_t *state,
+                           const char *data, size_t data_len,
+                           int done);
 #endif
 
 void assert_buf_ok(buf_t *buf);
diff --git a/src/or/connection.c b/src/or/connection.c
index e688f4c..b5496d7 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -3088,11 +3088,19 @@ _connection_write_to_buf_impl(const char *string, size_t len,
     return;
 
   IF_HAS_BUFFEREVENT(conn, {
-      if (bufferevent_write(conn->bufev, string, len)<0) {
-        /* XXXX mark for close? */
-        log_warn(LD_NET, "bufferevent_write failed! That shouldn't happen.");
-      }
-      return;
+    if (zlib) {
+      int done = zlib < 0;
+      r = write_to_evbuffer_zlib(bufferevent_get_output(conn->bufev),
+                                 TO_DIR_CONN(conn)->zlib_state,
+                                 string, len, done);
+    } else {
+      r = bufferevent_write(conn->bufev, string, len);
+    }
+    if (r < 0) {
+      /* XXXX mark for close? */
+      log_warn(LD_NET, "bufferevent_write failed! That shouldn't happen.");
+    }
+    return;
   });
 
   old_datalen = buf_datalen(conn->outbuf);
-- 
1.7.1




More information about the tor-commits mailing list