aboutsummaryrefslogtreecommitdiff
path: root/src/or/buffers.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2016-08-12 16:11:28 -0400
committerNick Mathewson <nickm@torproject.org>2016-08-12 16:11:28 -0400
commit7f145b54afb2cb1d9390a65bf31e2dddeb5b87da (patch)
treef184f7c342e95e36a6b80e2c7fddde7f76c3aa7e /src/or/buffers.c
parent14d58bbb4a9f08d51a58ea0a75d5535a05bfc9e8 (diff)
parentbbc9cbd95839380a45ec9ff11a7f7b99bbe923b0 (diff)
downloadtor-7f145b54afb2cb1d9390a65bf31e2dddeb5b87da.tar.gz
tor-7f145b54afb2cb1d9390a65bf31e2dddeb5b87da.zip
Merge remote-tracking branch 'public/Fix_19450'
Diffstat (limited to 'src/or/buffers.c')
-rw-r--r--src/or/buffers.c419
1 files changed, 2 insertions, 417 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 970d17ee41..3198572392 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -913,97 +913,6 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto)
return 1;
}
-#ifdef USE_BUFFEREVENTS
-/** Try to read <b>n</b> bytes from <b>buf</b> at <b>pos</b> (which may be
- * NULL for the start of the buffer), copying the data only if necessary. Set
- * *<b>data_out</b> to a pointer to the desired bytes. Set <b>free_out</b>
- * to 1 if we needed to malloc *<b>data</b> because the original bytes were
- * noncontiguous; 0 otherwise. Return the number of bytes actually available
- * at *<b>data_out</b>.
- */
-static ssize_t
-inspect_evbuffer(struct evbuffer *buf, char **data_out, size_t n,
- int *free_out, struct evbuffer_ptr *pos)
-{
- int n_vecs, i;
-
- if (evbuffer_get_length(buf) < n)
- n = evbuffer_get_length(buf);
- if (n == 0)
- return 0;
- n_vecs = evbuffer_peek(buf, n, pos, NULL, 0);
- tor_assert(n_vecs > 0);
- if (n_vecs == 1) {
- struct evbuffer_iovec v;
- i = evbuffer_peek(buf, n, pos, &v, 1);
- tor_assert(i == 1);
- *data_out = v.iov_base;
- *free_out = 0;
- return v.iov_len;
- } else {
- ev_ssize_t copied;
- *data_out = tor_malloc(n);
- *free_out = 1;
- copied = evbuffer_copyout(buf, *data_out, n);
- tor_assert(copied >= 0 && (size_t)copied == n);
- return copied;
- }
-}
-
-/** As fetch_var_cell_from_buf, buf works on an evbuffer. */
-int
-fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out,
- int linkproto)
-{
- char *hdr = NULL;
- int free_hdr = 0;
- size_t n;
- size_t buf_len;
- uint8_t command;
- uint16_t cell_length;
- var_cell_t *cell;
- int result = 0;
- const int wide_circ_ids = linkproto >= MIN_LINK_PROTO_FOR_WIDE_CIRC_IDS;
- const int circ_id_len = get_circ_id_size(wide_circ_ids);
- const unsigned header_len = get_var_cell_header_size(wide_circ_ids);
-
- *out = NULL;
- buf_len = evbuffer_get_length(buf);
- if (buf_len < header_len)
- return 0;
-
- n = inspect_evbuffer(buf, &hdr, header_len, &free_hdr, NULL);
- tor_assert(n >= header_len);
-
- command = get_uint8(hdr + circ_id_len);
- if (!(cell_command_is_var_length(command, linkproto))) {
- goto done;
- }
-
- cell_length = ntohs(get_uint16(hdr + circ_id_len + 1));
- if (buf_len < (size_t)(header_len+cell_length)) {
- result = 1; /* Not all here yet. */
- goto done;
- }
-
- cell = var_cell_new(cell_length);
- cell->command = command;
- if (wide_circ_ids)
- cell->circ_id = ntohl(get_uint32(hdr));
- else
- cell->circ_id = ntohs(get_uint16(hdr));
- evbuffer_drain(buf, header_len);
- evbuffer_remove(buf, cell->payload, cell_length);
- *out = cell;
- result = 1;
-
- done:
- if (free_hdr && hdr)
- tor_free(hdr);
- return result;
-}
-#endif
-
/** Move up to *<b>buf_flushlen</b> bytes from <b>buf_in</b> to
* <b>buf_out</b>, and modify *<b>buf_flushlen</b> appropriately.
* Return the number of bytes actually copied.
@@ -1246,94 +1155,6 @@ fetch_from_buf_http(buf_t *buf,
return 1;
}
-#ifdef USE_BUFFEREVENTS
-/** As fetch_from_buf_http, buf works on an evbuffer. */
-int
-fetch_from_evbuffer_http(struct evbuffer *buf,
- char **headers_out, size_t max_headerlen,
- char **body_out, size_t *body_used, size_t max_bodylen,
- int force_complete)
-{
- struct evbuffer_ptr crlf, content_length;
- size_t headerlen, bodylen, contentlen;
-
- /* Find the first \r\n\r\n in the buffer */
- crlf = evbuffer_search(buf, "\r\n\r\n", 4, NULL);
- if (crlf.pos < 0) {
- /* We didn't find one. */
- if (evbuffer_get_length(buf) > max_headerlen)
- return -1; /* Headers too long. */
- return 0; /* Headers not here yet. */
- } else if (crlf.pos > (int)max_headerlen) {
- return -1; /* Headers too long. */
- }
-
- headerlen = crlf.pos + 4; /* Skip over the \r\n\r\n */
- bodylen = evbuffer_get_length(buf) - headerlen;
- if (bodylen > max_bodylen)
- return -1; /* body too long */
-
- /* Look for the first occurrence of CONTENT_LENGTH insize buf before the
- * crlfcrlf */
- content_length = evbuffer_search_range(buf, CONTENT_LENGTH,
- strlen(CONTENT_LENGTH), NULL, &crlf);
-
- if (content_length.pos >= 0) {
- /* We found a content_length: parse it and figure out if the body is here
- * yet. */
- struct evbuffer_ptr eol;
- char *data = NULL;
- int free_data = 0;
- int n, i;
- n = evbuffer_ptr_set(buf, &content_length, strlen(CONTENT_LENGTH),
- EVBUFFER_PTR_ADD);
- tor_assert(n == 0);
- eol = evbuffer_search_eol(buf, &content_length, NULL, EVBUFFER_EOL_CRLF);
- tor_assert(eol.pos > content_length.pos);
- tor_assert(eol.pos <= crlf.pos);
- inspect_evbuffer(buf, &data, eol.pos - content_length.pos, &free_data,
- &content_length);
-
- i = atoi(data);
- if (free_data)
- tor_free(data);
- if (i < 0) {
- log_warn(LD_PROTOCOL, "Content-Length is less than zero; it looks like "
- "someone is trying to crash us.");
- return -1;
- }
- contentlen = i;
- /* if content-length is malformed, then our body length is 0. fine. */
- log_debug(LD_HTTP,"Got a contentlen of %d.",(int)contentlen);
- if (bodylen < contentlen) {
- if (!force_complete) {
- log_debug(LD_HTTP,"body not all here yet.");
- return 0; /* not all there yet */
- }
- }
- if (bodylen > contentlen) {
- bodylen = contentlen;
- log_debug(LD_HTTP,"bodylen reduced to %d.",(int)bodylen);
- }
- }
-
- if (headers_out) {
- *headers_out = tor_malloc(headerlen+1);
- evbuffer_remove(buf, *headers_out, headerlen);
- (*headers_out)[headerlen] = '\0';
- }
- if (body_out) {
- tor_assert(headers_out);
- tor_assert(body_used);
- *body_used = bodylen;
- *body_out = tor_malloc(bodylen+1);
- evbuffer_remove(buf, *body_out, bodylen);
- (*body_out)[bodylen] = '\0';
- }
- return 1;
-}
-#endif
-
/**
* Wait this many seconds before warning the user about using SOCKS unsafely
* again (requires that WarnUnsafeSocks is turned on). */
@@ -1453,86 +1274,6 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
return res;
}
-#ifdef USE_BUFFEREVENTS
-/* As fetch_from_buf_socks(), but targets an evbuffer instead. */
-int
-fetch_from_evbuffer_socks(struct evbuffer *buf, socks_request_t *req,
- int log_sockstype, int safe_socks)
-{
- char *data;
- ssize_t n_drain;
- size_t datalen, buflen, want_length;
- int res;
-
- buflen = evbuffer_get_length(buf);
- if (buflen < 2)
- return 0;
-
- {
- /* See if we can find the socks request in the first chunk of the buffer.
- */
- struct evbuffer_iovec v;
- int i;
- n_drain = 0;
- i = evbuffer_peek(buf, -1, NULL, &v, 1);
- tor_assert(i == 1);
- data = v.iov_base;
- datalen = v.iov_len;
- want_length = 0;
-
- res = parse_socks(data, datalen, req, log_sockstype,
- safe_socks, &n_drain, &want_length);
-
- if (n_drain < 0)
- evbuffer_drain(buf, evbuffer_get_length(buf));
- else if (n_drain > 0)
- evbuffer_drain(buf, n_drain);
-
- if (res)
- return res;
- }
-
- /* Okay, the first chunk of the buffer didn't have a complete socks request.
- * That means that either we don't have a whole socks request at all, or
- * it's gotten split up. We're going to try passing parse_socks() bigger
- * and bigger chunks until either it says "Okay, I got it", or it says it
- * will need more data than we currently have. */
-
- /* Loop while we have more data that we haven't given parse_socks() yet. */
- do {
- int free_data = 0;
- const size_t last_wanted = want_length;
- n_drain = 0;
- data = NULL;
- datalen = inspect_evbuffer(buf, &data, want_length, &free_data, NULL);
-
- want_length = 0;
- res = parse_socks(data, datalen, req, log_sockstype,
- safe_socks, &n_drain, &want_length);
-
- if (free_data)
- tor_free(data);
-
- if (n_drain < 0)
- evbuffer_drain(buf, evbuffer_get_length(buf));
- else if (n_drain > 0)
- evbuffer_drain(buf, n_drain);
-
- if (res == 0 && n_drain == 0 && want_length <= last_wanted) {
- /* If we drained nothing, and we didn't ask for more than last time,
- * then we probably wanted more data than the buffer actually had,
- * and we're finding out that we're not satisified with it. It's
- * time to break until we have more data. */
- break;
- }
-
- buflen = evbuffer_get_length(buf);
- } while (res == 0 && want_length <= buflen && buflen >= 2);
-
- return res;
-}
-#endif
-
/** The size of the header of an Extended ORPort message: 2 bytes for
* COMMAND, 2 bytes for BODYLEN */
#define EXT_OR_CMD_HEADER_SIZE 4
@@ -1563,34 +1304,6 @@ fetch_ext_or_command_from_buf(buf_t *buf, ext_or_cmd_t **out)
return 1;
}
-#ifdef USE_BUFFEREVENTS
-/** Read <b>buf</b>, which should contain an Extended ORPort message
- * from a transport proxy. If well-formed, create and populate
- * <b>out</b> with the Extended ORport message. Return 0 if the
- * buffer was incomplete, 1 if it was well-formed and -1 if we
- * encountered an error while parsing it. */
-int
-fetch_ext_or_command_from_evbuffer(struct evbuffer *buf, ext_or_cmd_t **out)
-{
- char hdr[EXT_OR_CMD_HEADER_SIZE];
- uint16_t len;
- size_t buf_len = evbuffer_get_length(buf);
-
- if (buf_len < EXT_OR_CMD_HEADER_SIZE)
- return 0;
- evbuffer_copyout(buf, hdr, EXT_OR_CMD_HEADER_SIZE);
- len = ntohs(get_uint16(hdr+2));
- if (buf_len < (unsigned)len + EXT_OR_CMD_HEADER_SIZE)
- return 0;
- *out = ext_or_cmd_new(len);
- (*out)->cmd = ntohs(get_uint16(hdr));
- (*out)->len = len;
- evbuffer_drain(buf, EXT_OR_CMD_HEADER_SIZE);
- evbuffer_remove(buf, (*out)->body, len);
- return 1;
-}
-#endif
-
/** Create a SOCKS5 reply message with <b>reason</b> in its REP field and
* have Tor send it as error response to <b>req</b>.
*/
@@ -2035,34 +1748,6 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
return r;
}
-#ifdef USE_BUFFEREVENTS
-/** As fetch_from_buf_socks_client, buf works on an evbuffer */
-int
-fetch_from_evbuffer_socks_client(struct evbuffer *buf, int state,
- char **reason)
-{
- ssize_t drain = 0;
- uint8_t *data;
- size_t datalen;
- int r;
-
- /* Linearize the SOCKS response in the buffer, up to 128 bytes.
- * (parse_socks_client shouldn't need to see anything beyond that.) */
- datalen = evbuffer_get_length(buf);
- if (datalen > MAX_SOCKS_MESSAGE_LEN)
- datalen = MAX_SOCKS_MESSAGE_LEN;
- data = evbuffer_pullup(buf, datalen);
-
- r = parse_socks_client(data, datalen, state, reason, &drain);
- if (drain > 0)
- evbuffer_drain(buf, drain);
- else if (drain < 0)
- evbuffer_drain(buf, evbuffer_get_length(buf));
-
- return r;
-}
-#endif
-
/** Implementation logic for fetch_from_*_socks_client. */
static int
parse_socks_client(const uint8_t *data, size_t datalen,
@@ -2193,27 +1878,6 @@ peek_buf_has_control0_command(buf_t *buf)
return 0;
}
-#ifdef USE_BUFFEREVENTS
-int
-peek_evbuffer_has_control0_command(struct evbuffer *buf)
-{
- int result = 0;
- if (evbuffer_get_length(buf) >= 4) {
- int free_out = 0;
- char *data = NULL;
- size_t n = inspect_evbuffer(buf, &data, 4, &free_out, NULL);
- uint16_t cmd;
- tor_assert(n >= 4);
- cmd = ntohs(get_uint16(data+2));
- if (cmd <= 0x14)
- result = 1;
- if (free_out)
- tor_free(data);
- }
- return result;
-}
-#endif
-
/** Return the index within <b>buf</b> at which <b>ch</b> first appears,
* or -1 if <b>ch</b> does not appear on buf. */
static off_t
@@ -2311,93 +1975,14 @@ 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 {
- {
- 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. */
- }
- 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
-
/** Set *<b>output</b> to contain a copy of the data in *<b>input</b> */
int
-generic_buffer_set_to_copy(generic_buffer_t **output,
- const generic_buffer_t *input)
+buf_set_to_copy(buf_t **output,
+ const buf_t *input)
{
-#ifdef USE_BUFFEREVENTS
- struct evbuffer_ptr ptr;
- size_t remaining = evbuffer_get_length(input);
- if (*output) {
- evbuffer_drain(*output, evbuffer_get_length(*output));
- } else {
- if (!(*output = evbuffer_new()))
- return -1;
- }
- evbuffer_ptr_set((struct evbuffer*)input, &ptr, 0, EVBUFFER_PTR_SET);
- while (remaining) {
- struct evbuffer_iovec v[4];
- int n_used, i;
- n_used = evbuffer_peek((struct evbuffer*)input, -1, &ptr, v, 4);
- if (n_used < 0)
- return -1;
- for (i=0;i<n_used;++i) {
- evbuffer_add(*output, v[i].iov_base, v[i].iov_len);
- tor_assert(v[i].iov_len <= remaining);
- remaining -= v[i].iov_len;
- evbuffer_ptr_set((struct evbuffer*)input,
- &ptr, v[i].iov_len, EVBUFFER_PTR_ADD);
- }
- }
-#else
if (*output)
buf_free(*output);
*output = buf_copy(input);
-#endif
return 0;
}