#include "or.h"
#include "../common/util.h"
#include "../common/log.h"
#include <unistd.h>
#include <sys/uio.h>
Data Structures | |
struct | chunk_t |
struct | chunk_freelist_t |
struct | buf_t |
struct | buf_pos_t |
Defines | |
#define | BUFFERS_PRIVATE |
#define | check() STMT_NIL |
#define | CHUNK_HEADER_LEN STRUCT_OFFSET(chunk_t, mem[0]) |
#define | CHUNK_ALLOC_SIZE(memlen) (CHUNK_HEADER_LEN + (memlen)) |
#define | CHUNK_SIZE_WITH_ALLOC(memlen) ((memlen) - CHUNK_HEADER_LEN) |
#define | FL(a, m, s) { a, m, s, 0, 0, 0, 0, 0, NULL } |
#define | MIN_READ_LEN 8 |
#define | MIN_CHUNK_ALLOC 256 |
#define | MAX_CHUNK_ALLOC 65536 |
#define | BUFFER_MAGIC 0xB0FFF312u |
#define | N_IOV 3 |
#define | CONTENT_LENGTH "\r\nContent-Length: " |
Functions | |
static INLINE char * | CHUNK_WRITE_PTR (chunk_t *chunk) |
static INLINE size_t | CHUNK_REMAINING_CAPACITY (const chunk_t *chunk) |
static INLINE void | chunk_repack (chunk_t *chunk) |
static void | assert_freelist_ok (chunk_freelist_t *fl) |
static INLINE chunk_freelist_t * | get_freelist (size_t alloc) |
static void | chunk_free_unchecked (chunk_t *chunk) |
static INLINE chunk_t * | chunk_new_with_alloc_size (size_t alloc) |
static INLINE chunk_t * | chunk_grow (chunk_t *chunk, size_t sz) |
static INLINE size_t | preferred_chunk_size (size_t target) |
void | buf_shrink_freelists (int free_all) |
void | buf_dump_freelist_sizes (int severity) |
static void | buf_pullup (buf_t *buf, size_t bytes, int nulterminate) |
void | buf_shrink (buf_t *buf) |
static INLINE void | buf_remove_from_front (buf_t *buf, size_t n) |
buf_t * | buf_new_with_capacity (size_t size) |
buf_t * | buf_new (void) |
void | buf_clear (buf_t *buf) |
size_t | buf_datalen (const buf_t *buf) |
size_t | buf_allocation (const buf_t *buf) |
size_t | buf_slack (const buf_t *buf) |
void | buf_free (buf_t *buf) |
static chunk_t * | buf_add_chunk_with_capacity (buf_t *buf, size_t capacity, int capped) |
static INLINE int | read_to_chunk (buf_t *buf, chunk_t *chunk, int fd, size_t at_most, int *reached_eof, int *socket_error) |
static INLINE int | read_to_chunk_tls (buf_t *buf, chunk_t *chunk, tor_tls_t *tls, size_t at_most) |
int | read_to_buf (int s, size_t at_most, buf_t *buf, int *reached_eof, int *socket_error) |
int | read_to_buf_tls (tor_tls_t *tls, size_t at_most, buf_t *buf) |
static INLINE int | flush_chunk (int s, buf_t *buf, chunk_t *chunk, size_t sz, size_t *buf_flushlen) |
static INLINE int | flush_chunk_tls (tor_tls_t *tls, buf_t *buf, chunk_t *chunk, size_t sz, size_t *buf_flushlen) |
int | flush_buf (int s, buf_t *buf, size_t sz, size_t *buf_flushlen) |
int | flush_buf_tls (tor_tls_t *tls, buf_t *buf, size_t flushlen, size_t *buf_flushlen) |
int | write_to_buf (const char *string, size_t string_len, buf_t *buf) |
static INLINE void | peek_from_buf (char *string, size_t string_len, const buf_t *buf) |
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 | move_buf_to_buf (buf_t *buf_out, buf_t *buf_in, size_t *buf_flushlen) |
static void | buf_pos_init (const buf_t *buf, buf_pos_t *out) |
static off_t | buf_find_pos_of_char (char ch, buf_pos_t *out) |
static INLINE int | buf_pos_inc (buf_pos_t *pos) |
static int | buf_matches_at_pos (const buf_pos_t *pos, const char *s, size_t n) |
int | buf_find_string_offset (const buf_t *buf, const char *s, size_t n) |
int | fetch_from_buf_http (buf_t *buf, char **headers_out, size_t max_headerlen, char **body_out, size_t *body_used, size_t max_bodylen, int force_complete) |
int | fetch_from_buf_socks (buf_t *buf, socks_request_t *req, int log_sockstype, int safe_socks) |
int | fetch_from_buf_socks_client (buf_t *buf, int state, char **reason) |
int | peek_buf_has_control0_command (buf_t *buf) |
static off_t | buf_find_offset_of_char (buf_t *buf, char ch) |
int | fetch_from_buf_line (buf_t *buf, char *data_out, size_t *data_len) |
int | write_to_buf_zlib (buf_t *buf, tor_zlib_state_t *state, const char *data, size_t data_len, int done) |
void | assert_buf_ok (buf_t *buf) |
Variables | |
static chunk_freelist_t | freelists [] |
static uint64_t | n_freelist_miss = 0 |
#define BUFFER_MAGIC 0xB0FFF312u |
Magic value for buf_t.magic, to catch pointer errors.
Referenced by assert_buf_ok(), and buf_new().
#define CHUNK_ALLOC_SIZE | ( | memlen | ) | (CHUNK_HEADER_LEN + (memlen)) |
Return the number of bytes needed to allocate a chunk to hold memlen bytes.
Referenced by assert_freelist_ok(), buf_add_chunk_with_capacity(), chunk_free_unchecked(), and chunk_grow().
#define CHUNK_SIZE_WITH_ALLOC | ( | memlen | ) | ((memlen) - CHUNK_HEADER_LEN) |
Return the number of usable bytes in a chunk allocated with malloc(memlen).
Referenced by buf_pullup(), chunk_new_with_alloc_size(), and preferred_chunk_size().
#define FL | ( | a, | |||
m, | |||||
s | ) | { a, m, s, 0, 0, 0, 0, 0, NULL } |
Macro to help define freelists.
#define MAX_CHUNK_ALLOC 65536 |
No chunk should take up more than this many bytes.
Referenced by buf_add_chunk_with_capacity().
#define MIN_CHUNK_ALLOC 256 |
Every chunk should take up at least this many bytes.
Referenced by preferred_chunk_size().
#define MIN_READ_LEN 8 |
If a read onto the end of a chunk would be smaller than this number, then just start a new chunk.
Referenced by read_to_buf(), and read_to_buf_tls().
#define N_IOV 3 |
If we're using readv and writev, how many chunks are we willing to read/write at a time?
void assert_buf_ok | ( | buf_t * | buf | ) |
Log an error and exit if buf is corrupted.
References BUFFER_MAGIC, chunk_t::data, chunk_t::datalen, buf_t::datalen, buf_t::head, buf_t::magic, chunk_t::mem, chunk_t::memlen, chunk_t::next, buf_t::tail, and tor_assert.
Referenced by assert_connection_ok().
static void assert_freelist_ok | ( | chunk_freelist_t * | fl | ) | [static] |
Log an error and exit if fl is corrupted.
References chunk_freelist_t::alloc_size, CHUNK_ALLOC_SIZE, chunk_freelist_t::cur_length, chunk_freelist_t::head, chunk_freelist_t::lowest_length, chunk_t::memlen, chunk_t::next, and tor_assert.
Referenced by buf_shrink_freelists().
Append a new chunk with enough capacity to hold capacity bytes to the tail of buf. If capped, don't allocate a chunk bigger than MAX_CHUNK_ALLOC.
References CHUNK_ALLOC_SIZE, chunk_new_with_alloc_size(), buf_t::default_chunk_size, buf_t::head, MAX_CHUNK_ALLOC, chunk_t::next, preferred_chunk_size(), buf_t::tail, and tor_assert.
Referenced by read_to_buf(), read_to_buf_tls(), write_to_buf(), and write_to_buf_zlib().
size_t buf_allocation | ( | const buf_t * | buf | ) |
Return the total length of all chunks used in buf.
References buf_t::head, chunk_t::memlen, and chunk_t::next.
Referenced by connection_dump_buffer_mem_stats(), and dumpstats().
void buf_clear | ( | buf_t * | buf | ) |
Remove all data from buf.
References chunk_free_unchecked(), buf_t::datalen, buf_t::head, chunk_t::next, and buf_t::tail.
Referenced by buf_free(), connection_close_immediate(), fetch_from_buf_socks(), and fetch_from_buf_socks_client().
size_t buf_datalen | ( | const buf_t * | buf | ) |
Return the number of bytes stored in buf
References buf_t::datalen.
Referenced by _connection_free(), _connection_write_to_buf_impl(), append_cell_to_circuit_queue(), conn_close_if_marked(), connection_cpu_process_inbuf(), connection_dir_process_inbuf(), connection_dirserv_add_dir_bytes_to_outbuf(), connection_dirserv_add_microdescs_to_outbuf(), connection_dirserv_add_networkstatus_bytes_to_outbuf(), connection_dirserv_add_servers_to_outbuf(), connection_dirserv_flushed_some(), connection_dump_buffer_mem_stats(), connection_edge_package_raw_inbuf(), connection_edge_reached_eof(), connection_handle_read_impl(), connection_handle_write_impl(), connection_or_flushed_some(), connection_or_process_cells_from_inbuf(), connection_read_to_buf(), connection_should_read_from_linked_conn(), dumpstats(), and run_connection_housekeeping().
void buf_dump_freelist_sizes | ( | int | severity | ) |
Describe the current status of the freelists at log level severity.
References chunk_freelist_t::alloc_size, LD_MM, and n_freelist_miss.
Referenced by dumpmemusage().
static off_t buf_find_offset_of_char | ( | buf_t * | buf, | |
char | ch | |||
) | [static] |
Return the index within buf at which ch first appears, or -1 if ch does not appear on buf.
References chunk_t::data, chunk_t::datalen, buf_t::head, and chunk_t::next.
Referenced by fetch_from_buf_line().
static off_t buf_find_pos_of_char | ( | char | ch, | |
buf_pos_t * | out | |||
) | [static] |
Advance out to the first appearance of ch at the current position of out, or later. Return -1 if no instances are found; otherwise returns the absolute position of the character.
References buf_pos_t::chunk, buf_pos_t::chunk_pos, chunk_t::data, chunk_t::datalen, chunk_t::next, buf_pos_t::pos, and tor_assert.
Referenced by buf_find_string_offset().
int buf_find_string_offset | ( | const buf_t * | buf, | |
const char * | s, | |||
size_t | n | |||
) |
Return the first position in buf at which the n-character string s occurs, or -1 if it does not occur.
References buf_find_pos_of_char(), buf_matches_at_pos(), buf_pos_inc(), buf_pos_init(), buf_pos_t::chunk_pos, buf_pos_t::pos, and tor_assert.
Referenced by fetch_from_buf_http().
void buf_free | ( | buf_t * | buf | ) |
Release storage held by buf.
References buf_clear(), buf_t::magic, and tor_free.
Referenced by _connection_free().
static int buf_matches_at_pos | ( | const buf_pos_t * | pos, | |
const char * | s, | |||
size_t | n | |||
) | [static] |
Return true iff the n-character string in s appears (verbatim) at pos.
References buf_pos_inc(), buf_pos_t::chunk, chunk_t::data, and buf_pos_t::pos.
Referenced by buf_find_string_offset().
buf_t* buf_new | ( | void | ) |
Allocate and return a new buffer with default capacity.
References BUFFER_MAGIC, buf_t::default_chunk_size, and buf_t::magic.
Referenced by buf_new_with_capacity(), and connection_init().
buf_t* buf_new_with_capacity | ( | size_t | size | ) |
Create and return a new buf with default chunk capacity size.
References buf_new(), buf_t::default_chunk_size, and preferred_chunk_size().
static INLINE int buf_pos_inc | ( | buf_pos_t * | pos | ) | [static] |
Advance pos by a single character, if there are any more characters in the buffer. Returns 0 on success, -1 on failure.
References buf_pos_t::chunk, buf_pos_t::chunk_pos, chunk_t::datalen, chunk_t::next, and buf_pos_t::pos.
Referenced by buf_find_string_offset(), and buf_matches_at_pos().
Initialize out to point to the first character of buf.
References buf_pos_t::chunk, buf_pos_t::chunk_pos, buf_t::head, and buf_pos_t::pos.
Referenced by buf_find_string_offset().
static void buf_pullup | ( | buf_t * | buf, | |
size_t | bytes, | |||
int | nulterminate | |||
) | [static] |
Collapse data from the first N chunks from buf into buf->head, growing it as necessary, until buf->head has the first bytes bytes of data from the buffer, or until buf->head has all the data in buf.
If nulterminate is true, ensure that there is a 0 byte in buf->head->mem right after all the data.
References chunk_free_unchecked(), chunk_grow(), CHUNK_REMAINING_CAPACITY(), chunk_repack(), CHUNK_SIZE_WITH_ALLOC, CHUNK_WRITE_PTR(), chunk_t::data, chunk_t::datalen, buf_t::datalen, buf_t::head, chunk_t::memlen, chunk_t::next, preferred_chunk_size(), buf_t::tail, and tor_assert.
Referenced by fetch_from_buf_http(), fetch_from_buf_socks(), and fetch_from_buf_socks_client().
static INLINE void buf_remove_from_front | ( | buf_t * | buf, | |
size_t | n | |||
) | [static] |
Remove the first n bytes from buf.
References chunk_free_unchecked(), chunk_t::data, chunk_t::datalen, buf_t::datalen, buf_t::head, chunk_t::next, buf_t::tail, and tor_assert.
Referenced by fetch_from_buf(), fetch_from_buf_socks(), fetch_from_buf_socks_client(), fetch_var_cell_from_buf(), flush_chunk(), and flush_chunk_tls().
void buf_shrink | ( | buf_t * | buf | ) |
Resize buf so it won't hold extra memory that we haven't been using lately.
Referenced by run_scheduled_events().
void buf_shrink_freelists | ( | int | free_all | ) |
Remove from the freelists most chunks that have not been used since the last call to buf_shrink_freelists().
References chunk_freelist_t::alloc_size, assert_freelist_ok(), chunk_freelist_t::cur_length, chunk_freelist_t::head, LD_BUG, LD_MM, chunk_freelist_t::lowest_length, chunk_freelist_t::n_free, chunk_t::next, chunk_freelist_t::slack, tor_assert, and tor_free.
Referenced by run_scheduled_events(), and tor_free_all().
size_t buf_slack | ( | const buf_t * | buf | ) |
Return the number of bytes that can be added to buf without performing any additional allocation.
References CHUNK_REMAINING_CAPACITY(), and buf_t::tail.
Referenced by connection_read_to_buf().
static void chunk_free_unchecked | ( | chunk_t * | chunk | ) | [static] |
Deallocate a chunk or put it on a freelist
References CHUNK_ALLOC_SIZE, chunk_freelist_t::cur_length, freelist, get_freelist(), chunk_freelist_t::head, chunk_freelist_t::max_length, chunk_t::memlen, chunk_freelist_t::n_free, chunk_t::next, and tor_free.
Expand chunk until it can hold sz bytes, and return a new pointer to chunk. Old pointers are no longer valid.
References CHUNK_ALLOC_SIZE, chunk_t::data, chunk_t::mem, chunk_t::memlen, and tor_assert.
Referenced by buf_pullup().
static INLINE chunk_t* chunk_new_with_alloc_size | ( | size_t | alloc | ) | [static] |
Allocate a new chunk with a given allocation size, or get one from the freelist. Note that a chunk with allocation size A can actually hold only CHUNK_SIZE_WITH_ALLOC(A) bytes in its mem field.
References CHUNK_SIZE_WITH_ALLOC, chunk_freelist_t::cur_length, chunk_t::data, chunk_t::datalen, freelist, get_freelist(), chunk_freelist_t::head, chunk_freelist_t::lowest_length, chunk_t::mem, chunk_t::memlen, chunk_freelist_t::n_alloc, n_freelist_miss, chunk_freelist_t::n_hit, chunk_t::next, and tor_assert.
Referenced by buf_add_chunk_with_capacity().
static INLINE size_t CHUNK_REMAINING_CAPACITY | ( | const chunk_t * | chunk | ) | [static] |
Return the number of bytes that can be written onto chunk without running out of space.
References chunk_t::data, chunk_t::datalen, chunk_t::mem, and chunk_t::memlen.
Referenced by buf_pullup(), buf_slack(), read_to_buf(), read_to_buf_tls(), read_to_chunk(), read_to_chunk_tls(), write_to_buf(), and write_to_buf_zlib().
static INLINE void chunk_repack | ( | chunk_t * | chunk | ) | [static] |
Move all bytes stored in chunk to the front of chunk->mem, to free up space at the end.
References chunk_t::data, chunk_t::datalen, and chunk_t::mem.
Referenced by buf_pullup().
static INLINE char* CHUNK_WRITE_PTR | ( | chunk_t * | chunk | ) | [static] |
Return the next character in chunk onto which data can be appended. If the chunk is full, this might be off the end of chunk->mem.
References chunk_t::data, and chunk_t::datalen.
Referenced by buf_pullup(), fetch_from_buf_socks(), read_to_chunk(), read_to_chunk_tls(), write_to_buf(), and write_to_buf_zlib().
int fetch_from_buf | ( | char * | string, | |
size_t | string_len, | |||
buf_t * | buf | |||
) |
Remove string_len bytes from the front of buf, and store them into string. Return the new buffer size. string_len must be <= the number of bytes on the buffer.
References buf_remove_from_front(), buf_t::datalen, peek_from_buf(), and tor_assert.
Referenced by connection_fetch_from_buf(), fetch_from_buf_http(), fetch_from_buf_line(), and move_buf_to_buf().
int fetch_from_buf_http | ( | buf_t * | buf, | |
char ** | headers_out, | |||
size_t | max_headerlen, | |||
char ** | body_out, | |||
size_t * | body_used, | |||
size_t | max_bodylen, | |||
int | force_complete | |||
) |
There is a (possibly incomplete) http statement on buf, of the form "\%s\\r\\n\\r\\n\%s", headers, body. (body may contain NULs.) If a) the headers include a Content-Length field and all bytes in the body are present, or b) there's no Content-Length field and all headers are present, then:
Else, change nothing and return 0.
References buf_find_string_offset(), buf_pullup(), chunk_t::data, buf_t::datalen, chunk_t::datalen, fetch_from_buf(), buf_t::head, LD_HTTP, LD_PROTOCOL, and tor_assert.
Referenced by connection_dir_client_reached_eof(), connection_read_https_proxy_response(), and directory_handle_command().
int fetch_from_buf_line | ( | buf_t * | buf, | |
char * | data_out, | |||
size_t * | data_len | |||
) |
Try to read a single LF-terminated line from buf, and write it, NUL-terminated, into the *data_len byte buffer at data_out. Set *data_len to the number of bytes in the line, not counting the terminating NUL. Return 1 if we read a whole line, return 0 if we don't have a whole line yet, and return -1 if the line length exceeds *data_len.
References buf_find_offset_of_char(), fetch_from_buf(), and buf_t::head.
Referenced by connection_ap_process_natd(), and connection_control_process_inbuf().
int fetch_from_buf_socks | ( | buf_t * | buf, | |
socks_request_t * | req, | |||
int | log_sockstype, | |||
int | safe_socks | |||
) |
There is a (possibly incomplete) socks handshake on buf, of one of the forms
If it's invalid or too big, return -1.
Else it's not all there yet, leave buf alone and return 0.
If you want to specify the socks reply, write it into req->reply and set req->replylen, else leave req->replylen alone.
If log_sockstype is non-zero, then do a notice-level log of whether the connection is possibly leaking DNS requests locally or not.
If safe_socks is true, then reject unsafe socks protocols.
If returning 0 or -1, req->address and req->port are undefined.
References socks_request_t::address, addressmap_have_mapping(), buf_clear(), buf_pullup(), buf_remove_from_front(), CHUNK_WRITE_PTR(), socks_request_t::command, control_event_client_status(), chunk_t::data, chunk_t::datalen, buf_t::datalen, escaped(), get_uint16(), get_uint32(), buf_t::head, LD_APP, LD_PROTOCOL, socks_request_t::port, socks_request_t::reply, socks_request_t::replylen, safe_str_client(), SOCKS4_NETWORK_LEN, SOCKS_COMMAND_CONNECT, SOCKS_COMMAND_RESOLVE, SOCKS_COMMAND_RESOLVE_PTR, socks_request_t::socks_version, tor_addr_from_ipv4n(), tor_addr_from_ipv6_bytes(), tor_addr_to_str(), tor_assert, tor_free, tor_inet_ntoa(), and tor_strisprint().
Referenced by connection_ap_handshake_process_socks().
int fetch_from_buf_socks_client | ( | buf_t * | buf, | |
int | state, | |||
char ** | reason | |||
) |
Inspect a reply from SOCKS server stored in buf according to state, removing the protocol data upon success. Return 0 on incomplete response, 1 on success and -1 on error, in which case reason is set to a descriptive message (free() when finished with it).
As a special case, 2 is returned when user/pass is required during SOCKS5 handshake and user/pass is configured.
References buf_clear(), buf_pullup(), buf_remove_from_front(), chunk_t::data, chunk_t::datalen, buf_t::datalen, buf_t::head, LD_NET, socks4_response_code_to_string(), socks5_response_code_to_string(), and tor_assert.
Referenced by connection_read_proxy_handshake().
int fetch_var_cell_from_buf | ( | buf_t * | buf, | |
var_cell_t ** | out, | |||
int | linkproto | |||
) |
Check buf for a variable-length cell according to the rules of link protocol version linkproto. If one is found, pull it off the buffer and assign a newly allocated var_cell_t to *out, and return 1. Return 0 if whatever is on the start of buf_t is not a variable-length cell. Return 1 and set *out to NULL if there seems to be the start of a variable-length cell on buf, but the whole thing isn't there yet.
References buf_remove_from_front(), CELL_COMMAND_IS_VAR_LENGTH, var_cell_t::circ_id, var_cell_t::command, buf_t::datalen, get_uint16(), var_cell_t::payload, peek_from_buf(), VAR_CELL_HEADER_SIZE, and var_cell_new().
Referenced by connection_fetch_var_cell_from_buf().
int flush_buf | ( | int | s, | |
buf_t * | buf, | |||
size_t | sz, | |||
size_t * | buf_flushlen | |||
) |
Write data from buf to the socket s. Write at most sz bytes, decrement *buf_flushlen by the number of bytes actually written, and remove the written bytes from the buffer. Return the number of bytes written on success, -1 on failure. Return 0 if write() would block.
References chunk_t::datalen, flush_chunk(), buf_t::head, and tor_assert.
Referenced by conn_close_if_marked(), and connection_handle_write_impl().
As flush_buf(), but writes data to a TLS connection. Can write more than flushlen bytes.
References chunk_t::datalen, flush_chunk_tls(), buf_t::head, and tor_assert.
Referenced by conn_close_if_marked(), and connection_handle_write_impl().
static INLINE int flush_chunk | ( | int | s, | |
buf_t * | buf, | |||
chunk_t * | chunk, | |||
size_t | sz, | |||
size_t * | buf_flushlen | |||
) | [static] |
Helper for flush_buf(): try to write sz bytes from chunk chunk of buffer buf onto socket s. On success, deduct the bytes written from *buf_flushlen. Return the number of bytes written on success, 0 on blocking, -1 on failure.
References buf_remove_from_front(), chunk_t::data, chunk_t::datalen, LD_NET, chunk_t::next, and tor_assert.
Referenced by flush_buf().
static INLINE int flush_chunk_tls | ( | tor_tls_t * | tls, | |
buf_t * | buf, | |||
chunk_t * | chunk, | |||
size_t | sz, | |||
size_t * | buf_flushlen | |||
) | [static] |
Helper for flush_buf_tls(): try to write sz bytes from chunk chunk of buffer buf onto socket s. (Tries to write more if there is a forced pending write size.) On success, deduct the bytes written from *buf_flushlen. Return the number of bytes written on success, and a TOR_TLS error code on failure or blocking.
References buf_remove_from_front(), chunk_t::data, buf_t::datalen, LD_NET, tor_assert, tor_tls_get_forced_write_size(), and tor_tls_write().
Referenced by flush_buf_tls().
static INLINE chunk_freelist_t* get_freelist | ( | size_t | alloc | ) | [static] |
Return the freelist to hold chunks of size alloc, or NULL if no freelist exists for that size.
References chunk_freelist_t::alloc_size.
Referenced by chunk_free_unchecked(), and chunk_new_with_alloc_size().
Move up to *buf_flushlen bytes from buf_in to buf_out, and modify *buf_flushlen appropriately. Return the number of bytes actually copied.
References buf_t::datalen, fetch_from_buf(), tor_assert, and write_to_buf().
Referenced by conn_close_if_marked(), and connection_read_to_buf().
int peek_buf_has_control0_command | ( | buf_t * | buf | ) |
Return 1 iff buf looks more like it has an (obsolete) v0 controller command on it than any valid v1 controller command.
References buf_t::datalen, get_uint16(), and peek_from_buf().
Referenced by connection_control_process_inbuf().
static INLINE void peek_from_buf | ( | char * | string, | |
size_t | string_len, | |||
const buf_t * | buf | |||
) | [static] |
Helper: copy the first string_len bytes from buf onto string.
References chunk_t::data, chunk_t::datalen, buf_t::head, chunk_t::next, and tor_assert.
Referenced by fetch_from_buf(), fetch_var_cell_from_buf(), and peek_buf_has_control0_command().
static INLINE size_t preferred_chunk_size | ( | size_t | target | ) | [static] |
Return the allocation size we'd like to use to hold target bytes.
References CHUNK_SIZE_WITH_ALLOC, and MIN_CHUNK_ALLOC.
Referenced by buf_add_chunk_with_capacity(), buf_new_with_capacity(), and buf_pullup().
int read_to_buf | ( | int | s, | |
size_t | at_most, | |||
buf_t * | buf, | |||
int * | reached_eof, | |||
int * | socket_error | |||
) |
Read from socket s, writing onto end of buf. Read at most at_most bytes, growing the buffer as necessary. If recv() returns 0 (because of EOF), set *reached_eof to 1 and return 0. Return -1 on error; else return the number of bytes read.
References buf_add_chunk_with_capacity(), CHUNK_REMAINING_CAPACITY(), chunk_t::memlen, MIN_READ_LEN, read_to_chunk(), buf_t::tail, and tor_assert.
Referenced by connection_read_to_buf().
As read_to_buf, but reads from a TLS connection, and returns a TLS status value rather than the number of bytes read.
Using TLS on OR connections complicates matters in two ways.
First, a TLS stream has its own read buffer independent of the connection's read buffer. (TLS needs to read an entire frame from the network before it can decrypt any data. Thus, trying to read 1 byte from TLS can require that several KB be read from the network and decrypted. The extra data is stored in TLS's decrypt buffer.) Because the data hasn't been read by Tor (it's still inside the TLS), this means that sometimes a connection "has stuff to read" even when poll() didn't return POLLIN. The tor_tls_get_pending_bytes function is used in connection.c to detect TLS objects with non-empty internal buffers and read from them again.
Second, the TLS stream's events do not correspond directly to network events: sometimes, before a TLS stream can read, the network must be ready to write -- or vice versa.
References buf_add_chunk_with_capacity(), CHUNK_REMAINING_CAPACITY(), chunk_t::memlen, MIN_READ_LEN, read_to_chunk_tls(), buf_t::tail, and tor_assert.
Referenced by connection_read_to_buf().
static INLINE int read_to_chunk | ( | buf_t * | buf, | |
chunk_t * | chunk, | |||
int | fd, | |||
size_t | at_most, | |||
int * | reached_eof, | |||
int * | socket_error | |||
) | [static] |
Read up to at_most bytes from the socket fd into chunk (which must be on buf). If we get an EOF, set *reached_eof to 1. Return -1 on error, 0 on eof or blocking, and the number of bytes read otherwise.
References CHUNK_REMAINING_CAPACITY(), CHUNK_WRITE_PTR(), chunk_t::datalen, buf_t::datalen, LD_NET, chunk_t::next, and tor_assert.
Referenced by read_to_buf().
static INLINE int read_to_chunk_tls | ( | buf_t * | buf, | |
chunk_t * | chunk, | |||
tor_tls_t * | tls, | |||
size_t | at_most | |||
) | [static] |
As read_to_chunk(), but return (negative) error code on error, blocking, or TLS, and the number of bytes read otherwise.
References CHUNK_REMAINING_CAPACITY(), CHUNK_WRITE_PTR(), chunk_t::datalen, buf_t::datalen, tor_assert, and tor_tls_read().
Referenced by read_to_buf_tls().
int write_to_buf | ( | const char * | string, | |
size_t | string_len, | |||
buf_t * | buf | |||
) |
Append string_len bytes from string to the end of buf.
Return the new length of the buffer on success, -1 on failure.
References buf_add_chunk_with_capacity(), CHUNK_REMAINING_CAPACITY(), CHUNK_WRITE_PTR(), chunk_t::datalen, buf_t::datalen, buf_t::tail, and tor_assert.
Referenced by _connection_write_to_buf_impl(), and move_buf_to_buf().
int write_to_buf_zlib | ( | buf_t * | buf, | |
tor_zlib_state_t * | state, | |||
const char * | data, | |||
size_t | data_len, | |||
int | done | |||
) |
Compress on uncompress the data_len bytes in data using the zlib state state, appending the result to buf. If done is true, flush the data in the state and finish the compression/uncompression. Return -1 on failure, 0 on success.
References buf_add_chunk_with_capacity(), CHUNK_REMAINING_CAPACITY(), CHUNK_WRITE_PTR(), chunk_t::datalen, buf_t::datalen, buf_t::tail, and tor_zlib_process().
Referenced by _connection_write_to_buf_impl().
chunk_freelist_t freelists[] [static] |
uint64_t n_freelist_miss = 0 [static] |
How many times have we looked for a chunk of a size that no freelist could help with?
Referenced by buf_dump_freelist_sizes(), and chunk_new_with_alloc_size().