Get zlib compression working with bufferevents.

This commit is contained in:
Nick Mathewson 2009-08-26 15:33:19 -04:00
parent 9796b9bfa6
commit 0c9b64d449
3 changed files with 71 additions and 5 deletions

View File

@ -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

View File

@ -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);

View File

@ -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);