buffers.c File Reference

Implements a generic interface buffer. Buffers are fairly opaque string holders that can read to or flush from: memory, file descriptors, or TLS connections. More...

#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_tget_freelist (size_t alloc)
static void chunk_free_unchecked (chunk_t *chunk)
static INLINE chunk_tchunk_new_with_alloc_size (size_t alloc)
static INLINE chunk_tchunk_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_tbuf_new_with_capacity (size_t size)
buf_tbuf_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_tbuf_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


Detailed Description

Implements a generic interface buffer. Buffers are fairly opaque string holders that can read to or flush from: memory, file descriptors, or TLS connections.


Define Documentation

#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,
 )     { 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?


Function Documentation

void assert_buf_ok ( buf_t buf  ) 

static void assert_freelist_ok ( chunk_freelist_t fl  )  [static]

static chunk_t* buf_add_chunk_with_capacity ( buf_t buf,
size_t  capacity,
int  capped 
) [static]

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  ) 

size_t buf_datalen ( const buf_t buf  ) 

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().

static void buf_pos_init ( const buf_t buf,
buf_pos_t out 
) [static]

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]

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  ) 

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]

static INLINE chunk_t* chunk_grow ( chunk_t chunk,
size_t  sz 
) [static]

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:

  • strdup headers into *headers_out, and NUL-terminate it.
  • memdup body into *body_out, and NUL-terminate it.
  • Then remove them from buf, and return 1.

  • If headers or body is NULL, discard that part of the buf.
  • If a headers or body doesn't fit in the arg, return -1. (We ensure that the headers or body don't exceed max len, _even if_ we're planning to discard them.)
  • If force_complete is true, then succeed even if not all of the content has arrived.

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

  • socks4: "socksheader username\\0"
  • socks4a: "socksheader username\\0 destaddr\\0"
  • socks5 phase one: "version #methods methods"
  • socks5 phase two: "version command 0 addresstype..." If it's a complete and valid handshake, and destaddr fits in MAX_SOCKS_ADDR_LEN bytes, then pull the handshake off the buf, assign to req, and return 1.

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().

int flush_buf_tls ( tor_tls_t tls,
buf_t buf,
size_t  flushlen,
size_t *  buf_flushlen 
)

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().

int move_buf_to_buf ( buf_t buf_out,
buf_t buf_in,
size_t *  buf_flushlen 
)

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().

int read_to_buf_tls ( tor_tls_t tls,
size_t  at_most,
buf_t 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().


Variable Documentation

Initial value:

 {
  FL(4096, 256, 8), FL(8192, 128, 4), FL(16384, 64, 4), FL(32768, 32, 2),

}
Static array of freelists, sorted by alloc_len, terminated by an entry with alloc_size of 0.

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().


Generated on Tue May 25 00:30:40 2010 for tor by  doxygen 1.5.6