aboutsummaryrefslogtreecommitdiff
path: root/src/or
diff options
context:
space:
mode:
Diffstat (limited to 'src/or')
-rw-r--r--src/or/buffers.c92
-rw-r--r--src/or/buffers.h4
-rw-r--r--src/or/or.h2
3 files changed, 96 insertions, 2 deletions
diff --git a/src/or/buffers.c b/src/or/buffers.c
index 5a34bd2bd..c038ba11e 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -1008,6 +1008,98 @@ fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto)
return 1;
}
+#ifdef USE_BUFFEREVENTS
+static size_t
+inspect_evbuffer(struct evbuffer *buf, char **data, size_t n, int *free_out)
+{
+ 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, NULL, NULL, 0);
+ if (n_vecs <= 0)
+ return -1;
+ if (n_vecs == 1) {
+ struct evbuffer_iovec v;
+ i = evbuffer_peek(buf, n, NULL, &v, 1);
+ tor_assert(i == 1);
+ *data = v.iov_base;
+ *free_out = 0;
+ return v.iov_len;
+ } else {
+ struct evbuffer_iovec *vecs =
+ tor_malloc(sizeof(struct evbuffer_iovec)*n_vecs);
+ size_t copied = 0;
+ i = evbuffer_peek(buf, n, NULL, vecs, n_vecs);
+ tor_assert(i == n_vecs);
+ *data = tor_malloc(n);
+ for (i=0; i < n_vecs; ++i) {
+ size_t copy = n - copied;
+ if (copy > vecs[i].iov_len)
+ copy = vecs[i].iov_len;
+ tor_assert(copied+copy <= n);
+ memcpy(data+copied, vecs[i].iov_base, copy);
+ copied += copy;
+ }
+ *free_out = 0;
+ 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;
+ if (linkproto == 1)
+ return 0;
+
+ *out = NULL;
+ buf_len = evbuffer_get_length(buf);
+ if (buf_len < VAR_CELL_HEADER_SIZE) {
+ result = 0;
+ goto done;
+ }
+ n = inspect_evbuffer(buf, &hdr, VAR_CELL_HEADER_SIZE, &free_hdr);
+ tor_assert(n == VAR_CELL_HEADER_SIZE);
+
+ command = get_uint8(hdr+2);
+ if (!(CELL_COMMAND_IS_VAR_LENGTH(command))) {
+ result = 0;
+ goto done;
+ }
+
+ cell_length = ntohs(get_uint16(hdr+3));
+ if (buf_len < (size_t)(VAR_CELL_HEADER_SIZE+cell_length)) {
+ result = 1; /* Not all here yet. */
+ goto done;
+ }
+
+ cell = var_cell_new(cell_length);
+ cell->command = command;
+ cell->circ_id = ntohs(get_uint16(hdr));
+ evbuffer_drain(buf, VAR_CELL_HEADER_SIZE);
+ 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.
diff --git a/src/or/buffers.h b/src/or/buffers.h
index 8fd403d95..f4174e91a 100644
--- a/src/or/buffers.h
+++ b/src/or/buffers.h
@@ -35,6 +35,10 @@ int write_to_buf(const char *string, size_t string_len, buf_t *buf);
int write_to_buf_zlib(buf_t *buf, tor_zlib_state_t *state,
const char *data, size_t data_len, int done);
int move_buf_to_buf(buf_t *buf_out, buf_t *buf_in, size_t *buf_flushlen);
+#ifdef USE_BUFFEREVENTS
+int fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out,
+ int linkproto);
+#endif
int fetch_from_buf(char *string, size_t string_len, buf_t *buf);
int fetch_var_cell_from_buf(buf_t *buf, var_cell_t **out, int linkproto);
int fetch_from_buf_http(buf_t *buf,
diff --git a/src/or/or.h b/src/or/or.h
index 0246da8ca..e0c259b04 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2974,8 +2974,6 @@ struct socks_request_t {
* every connection. */
};
-/* all the function prototypes go here */
-
/********************************* circuitbuild.c **********************/
/** How many hops does a general-purpose circuit have by default? */