Loading src/or/buffers.c +0 −415 Original line number Diff line number Diff line Loading @@ -914,97 +914,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. Loading Loading @@ -1247,94 +1156,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). */ Loading Loading @@ -1454,86 +1275,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 Loading Loading @@ -1564,34 +1305,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>. */ Loading Loading @@ -2036,34 +1749,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, Loading Loading @@ -2194,27 +1879,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 Loading Loading @@ -2312,93 +1976,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) { #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; } Loading src/or/buffers.h +0 −30 Original line number Diff line number Diff line Loading @@ -56,35 +56,6 @@ int peek_buf_has_control0_command(buf_t *buf); int fetch_ext_or_command_from_buf(buf_t *buf, ext_or_cmd_t **out); #ifdef USE_BUFFEREVENTS int fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out, int linkproto); int fetch_from_evbuffer_socks(struct evbuffer *buf, socks_request_t *req, int log_sockstype, int safe_socks); int fetch_from_evbuffer_socks_client(struct evbuffer *buf, int state, char **reason); 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); 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); int fetch_ext_or_command_from_evbuffer(struct evbuffer *buf, ext_or_cmd_t **out); #endif #ifdef USE_BUFFEREVENTS #define generic_buffer_new() evbuffer_new() #define generic_buffer_len(b) evbuffer_get_length((b)) #define generic_buffer_add(b,dat,len) evbuffer_add((b),(dat),(len)) #define generic_buffer_get(b,buf,buflen) evbuffer_remove((b),(buf),(buflen)) #define generic_buffer_clear(b) evbuffer_drain((b), evbuffer_get_length((b))) #define generic_buffer_free(b) evbuffer_free((b)) #define generic_buffer_fetch_ext_or_cmd(b, out) \ fetch_ext_or_command_from_evbuffer((b), (out)) #else #define generic_buffer_new() buf_new() #define generic_buffer_len(b) buf_datalen((b)) #define generic_buffer_add(b,dat,len) write_to_buf((dat),(len),(b)) Loading @@ -93,7 +64,6 @@ int fetch_ext_or_command_from_evbuffer(struct evbuffer *buf, #define generic_buffer_free(b) buf_free((b)) #define generic_buffer_fetch_ext_or_cmd(b, out) \ fetch_ext_or_command_from_buf((b), (out)) #endif int generic_buffer_set_to_copy(generic_buffer_t **output, const generic_buffer_t *input); Loading src/or/config.c +0 −11 Original line number Diff line number Diff line Loading @@ -1674,17 +1674,6 @@ options_act(const or_options_t *old_options) if (accounting_is_enabled(options)) configure_accounting(time(NULL)); #ifdef USE_BUFFEREVENTS /* If we're using the bufferevents implementation and our rate limits * changed, we need to tell the rate-limiting system about it. */ if (!old_options || old_options->BandwidthRate != options->BandwidthRate || old_options->BandwidthBurst != options->BandwidthBurst || old_options->RelayBandwidthRate != options->RelayBandwidthRate || old_options->RelayBandwidthBurst != options->RelayBandwidthBurst) connection_bucket_init(); #endif old_ewma_enabled = cell_ewma_enabled(); /* Change the cell EWMA settings */ cell_ewma_set_scale_factor(options, networkstatus_get_latest_consensus()); Loading src/or/connection.c +0 −340 File changed.Preview size limit exceeded, changes collapsed. Show changes src/or/connection.h +0 −12 Original line number Diff line number Diff line Loading @@ -257,19 +257,7 @@ void clock_skew_warning(const connection_t *conn, long apparent_skew, int trusted, log_domain_mask_t domain, const char *received, const char *source); #ifdef USE_BUFFEREVENTS int connection_type_uses_bufferevent(connection_t *conn); void connection_configure_bufferevent_callbacks(connection_t *conn); void connection_handle_read_cb(struct bufferevent *bufev, void *arg); void connection_handle_write_cb(struct bufferevent *bufev, void *arg); void connection_handle_event_cb(struct bufferevent *bufev, short event, void *arg); void connection_get_rate_limit_totals(uint64_t *read_out, uint64_t *written_out); void connection_enable_rate_limiting(connection_t *conn); #else #define connection_type_uses_bufferevent(c) (0) #endif #ifdef CONNECTION_PRIVATE STATIC void connection_free_(connection_t *conn); Loading Loading
src/or/buffers.c +0 −415 Original line number Diff line number Diff line Loading @@ -914,97 +914,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. Loading Loading @@ -1247,94 +1156,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). */ Loading Loading @@ -1454,86 +1275,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 Loading Loading @@ -1564,34 +1305,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>. */ Loading Loading @@ -2036,34 +1749,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, Loading Loading @@ -2194,27 +1879,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 Loading Loading @@ -2312,93 +1976,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) { #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; } Loading
src/or/buffers.h +0 −30 Original line number Diff line number Diff line Loading @@ -56,35 +56,6 @@ int peek_buf_has_control0_command(buf_t *buf); int fetch_ext_or_command_from_buf(buf_t *buf, ext_or_cmd_t **out); #ifdef USE_BUFFEREVENTS int fetch_var_cell_from_evbuffer(struct evbuffer *buf, var_cell_t **out, int linkproto); int fetch_from_evbuffer_socks(struct evbuffer *buf, socks_request_t *req, int log_sockstype, int safe_socks); int fetch_from_evbuffer_socks_client(struct evbuffer *buf, int state, char **reason); 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); 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); int fetch_ext_or_command_from_evbuffer(struct evbuffer *buf, ext_or_cmd_t **out); #endif #ifdef USE_BUFFEREVENTS #define generic_buffer_new() evbuffer_new() #define generic_buffer_len(b) evbuffer_get_length((b)) #define generic_buffer_add(b,dat,len) evbuffer_add((b),(dat),(len)) #define generic_buffer_get(b,buf,buflen) evbuffer_remove((b),(buf),(buflen)) #define generic_buffer_clear(b) evbuffer_drain((b), evbuffer_get_length((b))) #define generic_buffer_free(b) evbuffer_free((b)) #define generic_buffer_fetch_ext_or_cmd(b, out) \ fetch_ext_or_command_from_evbuffer((b), (out)) #else #define generic_buffer_new() buf_new() #define generic_buffer_len(b) buf_datalen((b)) #define generic_buffer_add(b,dat,len) write_to_buf((dat),(len),(b)) Loading @@ -93,7 +64,6 @@ int fetch_ext_or_command_from_evbuffer(struct evbuffer *buf, #define generic_buffer_free(b) buf_free((b)) #define generic_buffer_fetch_ext_or_cmd(b, out) \ fetch_ext_or_command_from_buf((b), (out)) #endif int generic_buffer_set_to_copy(generic_buffer_t **output, const generic_buffer_t *input); Loading
src/or/config.c +0 −11 Original line number Diff line number Diff line Loading @@ -1674,17 +1674,6 @@ options_act(const or_options_t *old_options) if (accounting_is_enabled(options)) configure_accounting(time(NULL)); #ifdef USE_BUFFEREVENTS /* If we're using the bufferevents implementation and our rate limits * changed, we need to tell the rate-limiting system about it. */ if (!old_options || old_options->BandwidthRate != options->BandwidthRate || old_options->BandwidthBurst != options->BandwidthBurst || old_options->RelayBandwidthRate != options->RelayBandwidthRate || old_options->RelayBandwidthBurst != options->RelayBandwidthBurst) connection_bucket_init(); #endif old_ewma_enabled = cell_ewma_enabled(); /* Change the cell EWMA settings */ cell_ewma_set_scale_factor(options, networkstatus_get_latest_consensus()); Loading
src/or/connection.c +0 −340 File changed.Preview size limit exceeded, changes collapsed. Show changes
src/or/connection.h +0 −12 Original line number Diff line number Diff line Loading @@ -257,19 +257,7 @@ void clock_skew_warning(const connection_t *conn, long apparent_skew, int trusted, log_domain_mask_t domain, const char *received, const char *source); #ifdef USE_BUFFEREVENTS int connection_type_uses_bufferevent(connection_t *conn); void connection_configure_bufferevent_callbacks(connection_t *conn); void connection_handle_read_cb(struct bufferevent *bufev, void *arg); void connection_handle_write_cb(struct bufferevent *bufev, void *arg); void connection_handle_event_cb(struct bufferevent *bufev, short event, void *arg); void connection_get_rate_limit_totals(uint64_t *read_out, uint64_t *written_out); void connection_enable_rate_limiting(connection_t *conn); #else #define connection_type_uses_bufferevent(c) (0) #endif #ifdef CONNECTION_PRIVATE STATIC void connection_free_(connection_t *conn); Loading