Procházet zdrojové kódy

Get zlib compression working with bufferevents.

Nick Mathewson před 14 roky
rodič
revize
0c9b64d449
3 změnil soubory, kde provedl 71 přidání a 5 odebrání
  1. 55 0
      src/or/buffers.c
  2. 3 0
      src/or/buffers.h
  3. 13 5
      src/or/connection.c

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

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

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