aboutsummaryrefslogtreecommitdiff
path: root/src/or/buffers.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2009-08-11 17:44:43 -0400
committerNick Mathewson <nickm@torproject.org>2010-09-27 12:31:13 -0400
commit44375d4eb8d9336c074d7e224cb118f1ad7e6f54 (patch)
treed24784374e4da12b2d6e590ea26d70abc396d905 /src/or/buffers.c
parentf6899f3a74fafb6eef814832830c11d5bc6e9c33 (diff)
downloadtor-44375d4eb8d9336c074d7e224cb118f1ad7e6f54.tar
tor-44375d4eb8d9336c074d7e224cb118f1ad7e6f54.tar.gz
Add a 0-pullup version of fetch_from_evbuffer_socks
Diffstat (limited to 'src/or/buffers.c')
-rw-r--r--src/or/buffers.c44
1 files changed, 34 insertions, 10 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 9d667d4b4..b750a0540 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -1498,7 +1498,7 @@ int
fetch_from_evbuffer_socks(struct evbuffer *buf, socks_request_t *req,
int log_sockstype, int safe_socks)
{
- const char *data;
+ char *data;
ssize_t n_drain;
size_t datalen, buflen, want_length;
int res;
@@ -1507,27 +1507,51 @@ fetch_from_evbuffer_socks(struct evbuffer *buf, socks_request_t *req,
if (buflen < 2)
return 0;
- want_length = evbuffer_get_contiguous_space(buf);
+ {
+ struct evbuffer_iovec v;
+ int i;
+ want_length = evbuffer_get_contiguous_space(buf);
+ n_drain = 0;
+ i = evbuffer_peek(buf, want_length, NULL, &v, 1);
+ tor_assert(i == i);
+ data = v.iov_base;
+ datalen = v.iov_len;
- do {
+ 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;
+ }
+
+ while (evbuffer_get_length(buf) > datalen) {
+ int free_data = 0;
n_drain = 0;
- data = (const char*) evbuffer_pullup(buf, want_length);
- datalen = evbuffer_get_contiguous_space(buf);
- want_length = 0;
+ data = NULL;
+ datalen = inspect_evbuffer(buf, &data, want_length, &free_data, NULL);
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);
- datalen = evbuffer_get_contiguous_space(buf);
- buflen = evbuffer_get_length(buf);
+ if (res)
+ return res;
- } while (res == 0 &&
- want_length > datalen && buflen > datalen);
+ if (want_length <= datalen)
+ break;
+ }
return res;
}