mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Make buf_pullup() expose the pulled-up data.
This lets us drop the testing-only function buf_get_first_chunk_data(), and lets us implement proto_http and proto_socks without looking at buf_t internals.
This commit is contained in:
parent
cddac959e7
commit
f28e314b0d
@ -203,22 +203,33 @@ preferred_chunk_size(size_t target)
|
||||
/** Collapse data from the first N chunks from <b>buf</b> into buf->head,
|
||||
* growing it as necessary, until buf->head has the first <b>bytes</b> bytes
|
||||
* of data from the buffer, or until buf->head has all the data in <b>buf</b>.
|
||||
*
|
||||
* Set *<b>head_out</b> to point to the first byte of available data, and
|
||||
* *<b>len_out</b> to the number of bytes of data available at
|
||||
* *<b>head_out</b>. Note that *<b>len_out</b> may be more or less than
|
||||
* <b>bytes</b>, depending on the number of bytes available.
|
||||
*/
|
||||
void
|
||||
buf_pullup(buf_t *buf, size_t bytes)
|
||||
buf_pullup(buf_t *buf, size_t bytes, const char **head_out, size_t *len_out)
|
||||
{
|
||||
chunk_t *dest, *src;
|
||||
size_t capacity;
|
||||
if (!buf->head)
|
||||
if (!buf->head) {
|
||||
*head_out = NULL;
|
||||
*len_out = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
check();
|
||||
if (buf->datalen < bytes)
|
||||
bytes = buf->datalen;
|
||||
|
||||
capacity = bytes;
|
||||
if (buf->head->datalen >= bytes)
|
||||
if (buf->head->datalen >= bytes) {
|
||||
*head_out = buf->head->data;
|
||||
*len_out = buf->head->datalen;
|
||||
return;
|
||||
}
|
||||
|
||||
if (buf->head->memlen >= capacity) {
|
||||
/* We don't need to grow the first chunk, but we might need to repack it.*/
|
||||
@ -263,22 +274,11 @@ buf_pullup(buf_t *buf, size_t bytes)
|
||||
}
|
||||
|
||||
check();
|
||||
*head_out = buf->head->data;
|
||||
*len_out = buf->head->datalen;
|
||||
}
|
||||
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
/* Return the data from the first chunk of buf in cp, and its length in sz. */
|
||||
void
|
||||
buf_get_first_chunk_data(const buf_t *buf, const char **cp, size_t *sz)
|
||||
{
|
||||
if (!buf || !buf->head) {
|
||||
*cp = NULL;
|
||||
*sz = 0;
|
||||
} else {
|
||||
*cp = buf->head->data;
|
||||
*sz = buf->head->datalen;
|
||||
}
|
||||
}
|
||||
|
||||
/* Write sz bytes from cp into a newly allocated buffer buf.
|
||||
* Returns NULL when passed a NULL cp or zero sz.
|
||||
* Asserts on failure: only for use in unit tests.
|
||||
|
@ -55,11 +55,11 @@ int buf_set_to_copy(buf_t **output,
|
||||
void assert_buf_ok(buf_t *buf);
|
||||
|
||||
int buf_find_string_offset(const buf_t *buf, const char *s, size_t n);
|
||||
void buf_pullup(buf_t *buf, size_t bytes);
|
||||
void buf_pullup(buf_t *buf, size_t bytes,
|
||||
const char **head_out, size_t *len_out);
|
||||
|
||||
#ifdef BUFFERS_PRIVATE
|
||||
#ifdef TOR_UNIT_TESTS
|
||||
void buf_get_first_chunk_data(const buf_t *buf, const char **cp, size_t *sz);
|
||||
buf_t *buf_new_with_data(const char *cp, size_t sz);
|
||||
#endif
|
||||
ATTR_UNUSED STATIC size_t preferred_chunk_size(size_t target);
|
||||
|
@ -4,7 +4,6 @@
|
||||
* Copyright (c) 2007-2017, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
#define BUFFERS_PRIVATE // XXXX remove.
|
||||
#define PROTO_HTTP_PRIVATE
|
||||
#include "or.h"
|
||||
#include "buffers.h"
|
||||
@ -48,12 +47,12 @@ fetch_from_buf_http(buf_t *buf,
|
||||
char **body_out, size_t *body_used, size_t max_bodylen,
|
||||
int force_complete)
|
||||
{
|
||||
char *headers;
|
||||
const char *headers;
|
||||
size_t headerlen, bodylen, contentlen=0;
|
||||
int crlf_offset;
|
||||
int r;
|
||||
|
||||
if (!buf->head)
|
||||
if (buf_datalen(buf) == 0)
|
||||
return 0;
|
||||
|
||||
crlf_offset = buf_find_string_offset(buf, "\r\n\r\n", 4);
|
||||
@ -67,11 +66,10 @@ fetch_from_buf_http(buf_t *buf,
|
||||
}
|
||||
/* Okay, we have a full header. Make sure it all appears in the first
|
||||
* chunk. */
|
||||
if ((int)buf->head->datalen < crlf_offset + 4)
|
||||
buf_pullup(buf, crlf_offset+4);
|
||||
headerlen = crlf_offset + 4;
|
||||
size_t headers_in_chunk = 0;
|
||||
buf_pullup(buf, headerlen, &headers, &headers_in_chunk);
|
||||
|
||||
headers = buf->head->data;
|
||||
bodylen = buf_datalen(buf) - headerlen;
|
||||
log_debug(LD_HTTP,"headerlen %d, bodylen %d.", (int)headerlen, (int)bodylen);
|
||||
|
||||
|
@ -4,7 +4,6 @@
|
||||
* Copyright (c) 2007-2017, The Tor Project, Inc. */
|
||||
/* See LICENSE for licensing information */
|
||||
|
||||
#define BUFFERS_PRIVATE // XXXX remove.
|
||||
#include "or.h"
|
||||
#include "addressmap.h"
|
||||
#include "buffers.h"
|
||||
@ -115,17 +114,19 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
|
||||
int res;
|
||||
ssize_t n_drain;
|
||||
size_t want_length = 128;
|
||||
const char *head = NULL;
|
||||
size_t datalen = 0;
|
||||
|
||||
if (buf_datalen(buf) < 2) /* version and another byte */
|
||||
return 0;
|
||||
|
||||
do {
|
||||
n_drain = 0;
|
||||
buf_pullup(buf, want_length);
|
||||
tor_assert(buf->head && buf->head->datalen >= 2);
|
||||
buf_pullup(buf, want_length, &head, &datalen);
|
||||
tor_assert(head && datalen >= 2);
|
||||
want_length = 0;
|
||||
|
||||
res = parse_socks(buf->head->data, buf->head->datalen, req, log_sockstype,
|
||||
res = parse_socks(head, datalen, req, log_sockstype,
|
||||
safe_socks, &n_drain, &want_length);
|
||||
|
||||
if (n_drain < 0)
|
||||
@ -133,7 +134,7 @@ fetch_from_buf_socks(buf_t *buf, socks_request_t *req,
|
||||
else if (n_drain > 0)
|
||||
buf_remove_from_front(buf, n_drain);
|
||||
|
||||
} while (res == 0 && buf->head && want_length < buf_datalen(buf) &&
|
||||
} while (res == 0 && head && want_length < buf_datalen(buf) &&
|
||||
buf_datalen(buf) >= 2);
|
||||
|
||||
return res;
|
||||
@ -591,13 +592,16 @@ fetch_from_buf_socks_client(buf_t *buf, int state, char **reason)
|
||||
{
|
||||
ssize_t drain = 0;
|
||||
int r;
|
||||
const char *head = NULL;
|
||||
size_t datalen = 0;
|
||||
|
||||
if (buf_datalen(buf) < 2)
|
||||
return 0;
|
||||
|
||||
buf_pullup(buf, MAX_SOCKS_MESSAGE_LEN);
|
||||
tor_assert(buf->head && buf->head->datalen >= 2);
|
||||
buf_pullup(buf, MAX_SOCKS_MESSAGE_LEN, &head, &datalen);
|
||||
tor_assert(head && datalen >= 2);
|
||||
|
||||
r = parse_socks_client((uint8_t*)buf->head->data, buf->head->datalen,
|
||||
r = parse_socks_client((uint8_t*)head, datalen,
|
||||
state, reason, &drain);
|
||||
if (drain > 0)
|
||||
buf_remove_from_front(buf, drain);
|
||||
|
@ -220,8 +220,7 @@ test_buffer_pullup(void *arg)
|
||||
|
||||
/* There are a bunch of cases for pullup. One is the trivial case. Let's
|
||||
mess around with an empty buffer. */
|
||||
buf_pullup(buf, 16);
|
||||
buf_get_first_chunk_data(buf, &cp, &sz);
|
||||
buf_pullup(buf, 16, &cp, &sz);
|
||||
tt_ptr_op(cp, OP_EQ, NULL);
|
||||
tt_uint_op(sz, OP_EQ, 0);
|
||||
|
||||
@ -234,7 +233,7 @@ test_buffer_pullup(void *arg)
|
||||
crypto_rand(stuff, 16384);
|
||||
write_to_buf(stuff, 3000, buf);
|
||||
write_to_buf(stuff+3000, 3000, buf);
|
||||
buf_get_first_chunk_data(buf, &cp, &sz);
|
||||
buf_pullup(buf, 0, &cp, &sz);
|
||||
tt_ptr_op(cp, OP_NE, NULL);
|
||||
tt_int_op(sz, OP_LE, 4096);
|
||||
|
||||
@ -242,9 +241,8 @@ test_buffer_pullup(void *arg)
|
||||
* can get tested. */
|
||||
tt_int_op(fetch_from_buf(tmp, 3000, buf), OP_EQ, 3000);
|
||||
tt_mem_op(tmp,OP_EQ, stuff, 3000);
|
||||
buf_pullup(buf, 2048);
|
||||
buf_pullup(buf, 2048, &cp, &sz);
|
||||
assert_buf_ok(buf);
|
||||
buf_get_first_chunk_data(buf, &cp, &sz);
|
||||
tt_ptr_op(cp, OP_NE, NULL);
|
||||
tt_int_op(sz, OP_GE, 2048);
|
||||
tt_mem_op(cp,OP_EQ, stuff+3000, 2048);
|
||||
@ -261,13 +259,12 @@ test_buffer_pullup(void *arg)
|
||||
write_to_buf(stuff+8000, 4000, buf);
|
||||
write_to_buf(stuff+12000, 4000, buf);
|
||||
tt_int_op(buf_datalen(buf), OP_EQ, 16000);
|
||||
buf_get_first_chunk_data(buf, &cp, &sz);
|
||||
buf_pullup(buf, 0, &cp, &sz);
|
||||
tt_ptr_op(cp, OP_NE, NULL);
|
||||
tt_int_op(sz, OP_LE, 4096);
|
||||
|
||||
buf_pullup(buf, 12500);
|
||||
buf_pullup(buf, 12500, &cp, &sz);
|
||||
assert_buf_ok(buf);
|
||||
buf_get_first_chunk_data(buf, &cp, &sz);
|
||||
tt_ptr_op(cp, OP_NE, NULL);
|
||||
tt_int_op(sz, OP_GE, 12500);
|
||||
tt_mem_op(cp,OP_EQ, stuff, 12500);
|
||||
@ -288,9 +285,8 @@ test_buffer_pullup(void *arg)
|
||||
write_to_buf(stuff, 4000, buf);
|
||||
write_to_buf(stuff+4000, 4000, buf);
|
||||
fetch_from_buf(tmp, 100, buf); /* dump 100 bytes from first chunk */
|
||||
buf_pullup(buf, 16000); /* Way too much. */
|
||||
buf_pullup(buf, 16000, &cp, &sz);
|
||||
assert_buf_ok(buf);
|
||||
buf_get_first_chunk_data(buf, &cp, &sz);
|
||||
tt_ptr_op(cp, OP_NE, NULL);
|
||||
tt_int_op(sz, OP_EQ, 7900);
|
||||
tt_mem_op(cp,OP_EQ, stuff+100, 7900);
|
||||
|
Loading…
Reference in New Issue
Block a user