commit d8b34e0886c9fd08fb51e0de4fadca7da82056ff Author: Nick Mathewson nickm@torproject.org Date: Thu Jun 28 16:25:06 2018 -0400
Move buffers into container
Split the network-only and compression-only parts of buffers into the appropriate modules. --- src/common/include.am | 2 - src/lib/compress/.may_include | 1 + src/lib/compress/compress.h | 4 + src/lib/compress/compress_buf.c | 77 ++++++++++ src/lib/compress/include.am | 3 +- src/lib/container/.may_include | 7 +- src/{common => lib/container}/buffers.c | 247 ++------------------------------ src/{common => lib/container}/buffers.h | 14 +- src/lib/container/include.am | 2 + src/lib/net/buffers_net.c | 192 +++++++++++++++++++++++++ src/lib/net/buffers_net.h | 26 ++++ src/lib/net/include.am | 2 + src/lib/tls/buffers_tls.c | 2 +- src/or/connection.c | 2 +- src/or/main.c | 1 + 15 files changed, 327 insertions(+), 255 deletions(-)
diff --git a/src/common/include.am b/src/common/include.am index bb1a3ee42..e68a87b10 100644 --- a/src/common/include.am +++ b/src/common/include.am @@ -25,7 +25,6 @@ endif
LIBOR_A_SRC = \ src/common/address_set.c \ - src/common/buffers.c \ src/common/compat.c \ src/common/util.c \ src/common/token_bucket.c \ @@ -60,7 +59,6 @@ src_common_libor_event_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS)
COMMONHEADERS = \ src/common/address_set.h \ - src/common/buffers.h \ src/common/compat.h \ src/common/compat_libevent.h \ src/common/handles.h \ diff --git a/src/lib/compress/.may_include b/src/lib/compress/.may_include index 036177469..68fe9f1c5 100644 --- a/src/lib/compress/.may_include +++ b/src/lib/compress/.may_include @@ -2,6 +2,7 @@ orconfig.h lib/arch/*.h lib/cc/*.h lib/compress/*.h +lib/container/*.h lib/ctime/*.h lib/intmath/*.h lib/log/*.h diff --git a/src/lib/compress/compress.h b/src/lib/compress/compress.h index f88cf2cb2..ae98e1aae 100644 --- a/src/lib/compress/compress.h +++ b/src/lib/compress/compress.h @@ -92,4 +92,8 @@ size_t tor_compress_state_size(const tor_compress_state_t *state); void tor_compress_init(void); void tor_compress_log_init_warnings(void);
+struct buf_t; +int buf_add_compress(struct buf_t *buf, struct tor_compress_state_t *state, + const char *data, size_t data_len, int done); + #endif /* !defined(TOR_COMPRESS_H) */ diff --git a/src/lib/compress/compress_buf.c b/src/lib/compress/compress_buf.c new file mode 100644 index 000000000..4b8877238 --- /dev/null +++ b/src/lib/compress/compress_buf.c @@ -0,0 +1,77 @@ +/* Copyright (c) 2003, Roger Dingledine + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#define BUFFERS_PRIVATE +#include "lib/cc/compat_compiler.h" +#include "lib/container/buffers.h" +#include "lib/compress/compress.h" +#include "lib/log/util_bug.h" + +#ifdef PARANOIA +/** Helper: If PARANOIA is defined, assert that the buffer in local variable + * <b>buf</b> is well-formed. */ +#define check() STMT_BEGIN buf_assert_ok(buf); STMT_END +#else +#define check() STMT_NIL +#endif /* defined(PARANOIA) */ + +/** Compress or uncompress the <b>data_len</b> bytes in <b>data</b> using the + * compression state <b>state</b>, appending the result to <b>buf</b>. If + * <b>done</b> is true, flush the data in the state and finish the + * compression/uncompression. Return -1 on failure, 0 on success. */ +int +buf_add_compress(buf_t *buf, tor_compress_state_t *state, + const char *data, size_t data_len, + const int done) +{ + char *next; + size_t old_avail, avail; + int over = 0; + + do { + int need_new_chunk = 0; + if (!buf->tail || ! CHUNK_REMAINING_CAPACITY(buf->tail)) { + size_t cap = data_len / 4; + buf_add_chunk_with_capacity(buf, cap, 1); + } + next = CHUNK_WRITE_PTR(buf->tail); + avail = old_avail = CHUNK_REMAINING_CAPACITY(buf->tail); + switch (tor_compress_process(state, &next, &avail, + &data, &data_len, done)) { + case TOR_COMPRESS_DONE: + over = 1; + break; + case TOR_COMPRESS_ERROR: + return -1; + case TOR_COMPRESS_OK: + if (data_len == 0) { + tor_assert_nonfatal(!done); + over = 1; + } + break; + case TOR_COMPRESS_BUFFER_FULL: + if (avail) { + /* The compression module says we need more room + * (TOR_COMPRESS_BUFFER_FULL). Start a new chunk automatically, + * whether were going to or not. */ + need_new_chunk = 1; + } + if (data_len == 0 && !done) { + /* We've consumed all the input data, though, so there's no + * point in forging ahead right now. */ + over = 1; + } + break; + } + buf->datalen += old_avail - avail; + buf->tail->datalen += old_avail - avail; + if (need_new_chunk) { + buf_add_chunk_with_capacity(buf, data_len/4, 1); + } + + } while (!over); + check(); + return 0; +} diff --git a/src/lib/compress/include.am b/src/lib/compress/include.am index eb3a89c35..75c9032bd 100644 --- a/src/lib/compress/include.am +++ b/src/lib/compress/include.am @@ -5,8 +5,9 @@ if UNITTESTS_ENABLED noinst_LIBRARIES += src/lib/libtor-compress-testing.a endif
-src_lib_libtor_compress_a_SOURCES = \ +src_lib_libtor_compress_a_SOURCES = \ src/lib/compress/compress.c \ + src/lib/compress/compress_buf.c \ src/lib/compress/compress_lzma.c \ src/lib/compress/compress_none.c \ src/lib/compress/compress_zlib.c \ diff --git a/src/lib/container/.may_include b/src/lib/container/.may_include index 2eecb503c..90de5eda4 100644 --- a/src/lib/container/.may_include +++ b/src/lib/container/.may_include @@ -9,9 +9,10 @@ lib/smartlist_core/*.h lib/string/*.h lib/testsupport/testsupport.h lib/intmath/*.h +lib/log/*.h + +# XXXX I am unsure about this one. It's only here for buffers.c +lib/time/*.h
ht.h siphash.h - -# XXX I'd like to remove this. -lib/log/util_bug.h diff --git a/src/common/buffers.c b/src/lib/container/buffers.c similarity index 77% rename from src/common/buffers.c rename to src/lib/container/buffers.c index 4e5f56c73..ee1a73e8f 100644 --- a/src/common/buffers.c +++ b/src/lib/container/buffers.c @@ -1,6 +1,6 @@ /* Copyright (c) 2001 Matej Pfajfar. * Copyright (c) 2001-2004, Roger Dingledine. - * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. +n * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. * Copyright (c) 2007-2018, The Tor Project, Inc. */ /* See LICENSE for licensing information */
@@ -21,16 +21,22 @@ #define BUFFERS_PRIVATE #include "orconfig.h" #include <stddef.h> -#include "common/buffers.h" -#include "common/compat.h" -#include "lib/compress/compress.h" -#include "common/util.h" +#include "lib/container/buffers.h" #include "lib/cc/torint.h" #include "lib/log/torlog.h" +#include "lib/log/util_bug.h" +#include "lib/ctime/di_ops.h" +#include "lib/malloc/util_malloc.h" +#include "lib/string/printf.h" +#include "lib/time/compat_time.h" + #ifdef HAVE_UNISTD_H #include <unistd.h> #endif
+#include <stdlib.h> +#include <string.h> + //#define PARANOIA
#ifdef PARANOIA @@ -506,177 +512,6 @@ buf_get_total_allocation(void) return total_bytes_allocated_in_chunks; }
-/** Read up to <b>at_most</b> bytes from the socket <b>fd</b> into - * <b>chunk</b> (which must be on <b>buf</b>). If we get an EOF, set - * *<b>reached_eof</b> to 1. Return -1 on error, 0 on eof or blocking, - * and the number of bytes read otherwise. */ -static inline int -read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most, - int *reached_eof, int *socket_error) -{ - ssize_t read_result; - if (at_most > CHUNK_REMAINING_CAPACITY(chunk)) - at_most = CHUNK_REMAINING_CAPACITY(chunk); - read_result = tor_socket_recv(fd, CHUNK_WRITE_PTR(chunk), at_most, 0); - - if (read_result < 0) { - int e = tor_socket_errno(fd); - if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */ -#ifdef _WIN32 - if (e == WSAENOBUFS) - log_warn(LD_NET,"recv() failed: WSAENOBUFS. Not enough ram?"); -#endif - *socket_error = e; - return -1; - } - return 0; /* would block. */ - } else if (read_result == 0) { - log_debug(LD_NET,"Encountered eof on fd %d", (int)fd); - *reached_eof = 1; - return 0; - } else { /* actually got bytes. */ - buf->datalen += read_result; - chunk->datalen += read_result; - log_debug(LD_NET,"Read %ld bytes. %d on inbuf.", (long)read_result, - (int)buf->datalen); - tor_assert(read_result < INT_MAX); - return (int)read_result; - } -} - -/** Read from socket <b>s</b>, writing onto end of <b>buf</b>. Read at most - * <b>at_most</b> bytes, growing the buffer as necessary. If recv() returns 0 - * (because of EOF), set *<b>reached_eof</b> to 1 and return 0. Return -1 on - * error; else return the number of bytes read. - */ -/* XXXX indicate "read blocked" somehow? */ -int -buf_read_from_socket(buf_t *buf, tor_socket_t s, size_t at_most, - int *reached_eof, - int *socket_error) -{ - /* XXXX It's stupid to overload the return values for these functions: - * "error status" and "number of bytes read" are not mutually exclusive. - */ - int r = 0; - size_t total_read = 0; - - check(); - tor_assert(reached_eof); - tor_assert(SOCKET_OK(s)); - - if (BUG(buf->datalen >= INT_MAX)) - return -1; - if (BUG(buf->datalen >= INT_MAX - at_most)) - return -1; - - while (at_most > total_read) { - size_t readlen = at_most - total_read; - chunk_t *chunk; - if (!buf->tail || CHUNK_REMAINING_CAPACITY(buf->tail) < MIN_READ_LEN) { - chunk = buf_add_chunk_with_capacity(buf, at_most, 1); - if (readlen > chunk->memlen) - readlen = chunk->memlen; - } else { - size_t cap = CHUNK_REMAINING_CAPACITY(buf->tail); - chunk = buf->tail; - if (cap < readlen) - readlen = cap; - } - - r = read_to_chunk(buf, chunk, s, readlen, reached_eof, socket_error); - check(); - if (r < 0) - return r; /* Error */ - tor_assert(total_read+r < INT_MAX); - total_read += r; - if ((size_t)r < readlen) { /* eof, block, or no more to read. */ - break; - } - } - return (int)total_read; -} - -/** Helper for buf_flush_to_socket(): try to write <b>sz</b> bytes from chunk - * <b>chunk</b> of buffer <b>buf</b> onto socket <b>s</b>. On success, deduct - * the bytes written from *<b>buf_flushlen</b>. Return the number of bytes - * written on success, 0 on blocking, -1 on failure. - */ -static inline int -flush_chunk(tor_socket_t s, buf_t *buf, chunk_t *chunk, size_t sz, - size_t *buf_flushlen) -{ - ssize_t write_result; - - if (sz > chunk->datalen) - sz = chunk->datalen; - write_result = tor_socket_send(s, chunk->data, sz, 0); - - if (write_result < 0) { - int e = tor_socket_errno(s); - if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */ -#ifdef _WIN32 - if (e == WSAENOBUFS) - log_warn(LD_NET,"write() failed: WSAENOBUFS. Not enough ram?"); -#endif - return -1; - } - log_debug(LD_NET,"write() would block, returning."); - return 0; - } else { - *buf_flushlen -= write_result; - buf_drain(buf, write_result); - tor_assert(write_result < INT_MAX); - return (int)write_result; - } -} - -/** Write data from <b>buf</b> to the socket <b>s</b>. Write at most - * <b>sz</b> bytes, decrement *<b>buf_flushlen</b> 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. - */ -int -buf_flush_to_socket(buf_t *buf, tor_socket_t s, size_t sz, - size_t *buf_flushlen) -{ - /* XXXX It's stupid to overload the return values for these functions: - * "error status" and "number of bytes flushed" are not mutually exclusive. - */ - int r; - size_t flushed = 0; - tor_assert(buf_flushlen); - tor_assert(SOCKET_OK(s)); - if (BUG(*buf_flushlen > buf->datalen)) { - *buf_flushlen = buf->datalen; - } - if (BUG(sz > *buf_flushlen)) { - sz = *buf_flushlen; - } - - check(); - while (sz) { - size_t flushlen0; - tor_assert(buf->head); - if (buf->head->datalen >= sz) - flushlen0 = sz; - else - flushlen0 = buf->head->datalen; - - r = flush_chunk(s, buf, buf->head, flushlen0, buf_flushlen); - check(); - if (r < 0) - return r; - flushed += r; - sz -= r; - if (r == 0 || (size_t)r < flushlen0) /* can't flush any more now. */ - break; - } - tor_assert(flushed < INT_MAX); - return (int)flushed; -} - /** Append <b>string_len</b> bytes from <b>string</b> to the end of * <b>buf</b>. * @@ -1037,65 +872,6 @@ buf_get_line(buf_t *buf, char *data_out, size_t *data_len) return 1; }
-/** Compress or uncompress the <b>data_len</b> bytes in <b>data</b> using the - * compression state <b>state</b>, appending the result to <b>buf</b>. If - * <b>done</b> is true, flush the data in the state and finish the - * compression/uncompression. Return -1 on failure, 0 on success. */ -int -buf_add_compress(buf_t *buf, tor_compress_state_t *state, - const char *data, size_t data_len, - const int done) -{ - char *next; - size_t old_avail, avail; - int over = 0; - - do { - int need_new_chunk = 0; - if (!buf->tail || ! CHUNK_REMAINING_CAPACITY(buf->tail)) { - size_t cap = data_len / 4; - buf_add_chunk_with_capacity(buf, cap, 1); - } - next = CHUNK_WRITE_PTR(buf->tail); - avail = old_avail = CHUNK_REMAINING_CAPACITY(buf->tail); - switch (tor_compress_process(state, &next, &avail, - &data, &data_len, done)) { - case TOR_COMPRESS_DONE: - over = 1; - break; - case TOR_COMPRESS_ERROR: - return -1; - case TOR_COMPRESS_OK: - if (data_len == 0) { - tor_assert_nonfatal(!done); - over = 1; - } - break; - case TOR_COMPRESS_BUFFER_FULL: - if (avail) { - /* The compression module says we need more room - * (TOR_COMPRESS_BUFFER_FULL). Start a new chunk automatically, - * whether were going to or not. */ - need_new_chunk = 1; - } - if (data_len == 0 && !done) { - /* We've consumed all the input data, though, so there's no - * point in forging ahead right now. */ - over = 1; - } - break; - } - buf->datalen += old_avail - avail; - buf->tail->datalen += old_avail - avail; - if (need_new_chunk) { - buf_add_chunk_with_capacity(buf, data_len/4, 1); - } - - } while (!over); - check(); - return 0; -} - /** Set *<b>output</b> to contain a copy of the data in *<b>input</b> */ int buf_set_to_copy(buf_t **output, @@ -1143,4 +919,3 @@ buf_assert_ok(buf_t *buf) tor_assert(buf->datalen == total); } } - diff --git a/src/common/buffers.h b/src/lib/container/buffers.h similarity index 90% rename from src/common/buffers.h rename to src/lib/container/buffers.h index 80103af77..8b16fb298 100644 --- a/src/common/buffers.h +++ b/src/lib/container/buffers.h @@ -12,10 +12,12 @@ #ifndef TOR_BUFFERS_H #define TOR_BUFFERS_H
-#include "common/compat.h" +#include "lib/cc/compat_compiler.h" #include "lib/cc/torint.h" #include "lib/testsupport/testsupport.h"
+#include <stdarg.h> + typedef struct buf_t buf_t;
struct tor_compress_state_t; @@ -35,21 +37,12 @@ size_t buf_slack(const buf_t *buf); uint32_t buf_get_oldest_chunk_timestamp(const buf_t *buf, uint32_t now); size_t buf_get_total_allocation(void);
-int buf_read_from_socket(buf_t *buf, tor_socket_t s, size_t at_most, - int *reached_eof, - int *socket_error); - -int buf_flush_to_socket(buf_t *buf, tor_socket_t s, size_t sz, - size_t *buf_flushlen); - int buf_add(buf_t *buf, const char *string, size_t string_len); void buf_add_string(buf_t *buf, const char *string); void buf_add_printf(buf_t *buf, const char *format, ...) CHECK_PRINTF(2, 3); void buf_add_vprintf(buf_t *buf, const char *format, va_list args) CHECK_PRINTF(2, 0); -int buf_add_compress(buf_t *buf, struct tor_compress_state_t *state, - const char *data, size_t data_len, int done); int buf_move_to_buf(buf_t *buf_out, buf_t *buf_in, size_t *buf_flushlen); void buf_move_all(buf_t *buf_out, buf_t *buf_in); void buf_peek(const buf_t *buf, char *string, size_t string_len); @@ -128,4 +121,3 @@ CHUNK_WRITE_PTR(chunk_t *chunk) #endif /* defined(BUFFERS_PRIVATE) */
#endif /* !defined(TOR_BUFFERS_H) */ - diff --git a/src/lib/container/include.am b/src/lib/container/include.am index 0e7acdff9..e91ad7d1c 100644 --- a/src/lib/container/include.am +++ b/src/lib/container/include.am @@ -7,6 +7,7 @@ endif
src_lib_libtor_container_a_SOURCES = \ src/lib/container/bloomfilt.c \ + src/lib/container/buffers.c \ src/lib/container/map.c \ src/lib/container/order.c \ src/lib/container/smartlist.c @@ -19,6 +20,7 @@ src_lib_libtor_container_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) noinst_HEADERS += \ src/lib/container/bitarray.h \ src/lib/container/bloomfilt.h \ + src/lib/container/buffers.h \ src/lib/container/map.h \ src/lib/container/order.h \ src/lib/container/smartlist.h diff --git a/src/lib/net/buffers_net.c b/src/lib/net/buffers_net.c new file mode 100644 index 000000000..01be30f5a --- /dev/null +++ b/src/lib/net/buffers_net.c @@ -0,0 +1,192 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +#define BUFFERS_PRIVATE +#include "lib/net/buffers_net.h" +#include "lib/container/buffers.h" +#include "lib/log/torlog.h" +#include "lib/log/util_bug.h" + +#include <stdlib.h> + +#ifdef PARANOIA +/** Helper: If PARANOIA is defined, assert that the buffer in local variable + * <b>buf</b> is well-formed. */ +#define check() STMT_BEGIN buf_assert_ok(buf); STMT_END +#else +#define check() STMT_NIL +#endif /* defined(PARANOIA) */ + +/** Read up to <b>at_most</b> bytes from the socket <b>fd</b> into + * <b>chunk</b> (which must be on <b>buf</b>). If we get an EOF, set + * *<b>reached_eof</b> to 1. Return -1 on error, 0 on eof or blocking, + * and the number of bytes read otherwise. */ +static inline int +read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most, + int *reached_eof, int *socket_error) +{ + ssize_t read_result; + if (at_most > CHUNK_REMAINING_CAPACITY(chunk)) + at_most = CHUNK_REMAINING_CAPACITY(chunk); + read_result = tor_socket_recv(fd, CHUNK_WRITE_PTR(chunk), at_most, 0); + + if (read_result < 0) { + int e = tor_socket_errno(fd); + if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */ +#ifdef _WIN32 + if (e == WSAENOBUFS) + log_warn(LD_NET,"recv() failed: WSAENOBUFS. Not enough ram?"); +#endif + *socket_error = e; + return -1; + } + return 0; /* would block. */ + } else if (read_result == 0) { + log_debug(LD_NET,"Encountered eof on fd %d", (int)fd); + *reached_eof = 1; + return 0; + } else { /* actually got bytes. */ + buf->datalen += read_result; + chunk->datalen += read_result; + log_debug(LD_NET,"Read %ld bytes. %d on inbuf.", (long)read_result, + (int)buf->datalen); + tor_assert(read_result < INT_MAX); + return (int)read_result; + } +} + +/** Read from socket <b>s</b>, writing onto end of <b>buf</b>. Read at most + * <b>at_most</b> bytes, growing the buffer as necessary. If recv() returns 0 + * (because of EOF), set *<b>reached_eof</b> to 1 and return 0. Return -1 on + * error; else return the number of bytes read. + */ +/* XXXX indicate "read blocked" somehow? */ +int +buf_read_from_socket(buf_t *buf, tor_socket_t s, size_t at_most, + int *reached_eof, + int *socket_error) +{ + /* XXXX It's stupid to overload the return values for these functions: + * "error status" and "number of bytes read" are not mutually exclusive. + */ + int r = 0; + size_t total_read = 0; + + check(); + tor_assert(reached_eof); + tor_assert(SOCKET_OK(s)); + + if (BUG(buf->datalen >= INT_MAX)) + return -1; + if (BUG(buf->datalen >= INT_MAX - at_most)) + return -1; + + while (at_most > total_read) { + size_t readlen = at_most - total_read; + chunk_t *chunk; + if (!buf->tail || CHUNK_REMAINING_CAPACITY(buf->tail) < MIN_READ_LEN) { + chunk = buf_add_chunk_with_capacity(buf, at_most, 1); + if (readlen > chunk->memlen) + readlen = chunk->memlen; + } else { + size_t cap = CHUNK_REMAINING_CAPACITY(buf->tail); + chunk = buf->tail; + if (cap < readlen) + readlen = cap; + } + + r = read_to_chunk(buf, chunk, s, readlen, reached_eof, socket_error); + check(); + if (r < 0) + return r; /* Error */ + tor_assert(total_read+r < INT_MAX); + total_read += r; + if ((size_t)r < readlen) { /* eof, block, or no more to read. */ + break; + } + } + return (int)total_read; +} + +/** Helper for buf_flush_to_socket(): try to write <b>sz</b> bytes from chunk + * <b>chunk</b> of buffer <b>buf</b> onto socket <b>s</b>. On success, deduct + * the bytes written from *<b>buf_flushlen</b>. Return the number of bytes + * written on success, 0 on blocking, -1 on failure. + */ +static inline int +flush_chunk(tor_socket_t s, buf_t *buf, chunk_t *chunk, size_t sz, + size_t *buf_flushlen) +{ + ssize_t write_result; + + if (sz > chunk->datalen) + sz = chunk->datalen; + write_result = tor_socket_send(s, chunk->data, sz, 0); + + if (write_result < 0) { + int e = tor_socket_errno(s); + if (!ERRNO_IS_EAGAIN(e)) { /* it's a real error */ +#ifdef _WIN32 + if (e == WSAENOBUFS) + log_warn(LD_NET,"write() failed: WSAENOBUFS. Not enough ram?"); +#endif + return -1; + } + log_debug(LD_NET,"write() would block, returning."); + return 0; + } else { + *buf_flushlen -= write_result; + buf_drain(buf, write_result); + tor_assert(write_result < INT_MAX); + return (int)write_result; + } +} + +/** Write data from <b>buf</b> to the socket <b>s</b>. Write at most + * <b>sz</b> bytes, decrement *<b>buf_flushlen</b> 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. + */ +int +buf_flush_to_socket(buf_t *buf, tor_socket_t s, size_t sz, + size_t *buf_flushlen) +{ + /* XXXX It's stupid to overload the return values for these functions: + * "error status" and "number of bytes flushed" are not mutually exclusive. + */ + int r; + size_t flushed = 0; + tor_assert(buf_flushlen); + tor_assert(SOCKET_OK(s)); + if (BUG(*buf_flushlen > buf->datalen)) { + *buf_flushlen = buf->datalen; + } + if (BUG(sz > *buf_flushlen)) { + sz = *buf_flushlen; + } + + check(); + while (sz) { + size_t flushlen0; + tor_assert(buf->head); + if (buf->head->datalen >= sz) + flushlen0 = sz; + else + flushlen0 = buf->head->datalen; + + r = flush_chunk(s, buf, buf->head, flushlen0, buf_flushlen); + check(); + if (r < 0) + return r; + flushed += r; + sz -= r; + if (r == 0 || (size_t)r < flushlen0) /* can't flush any more now. */ + break; + } + tor_assert(flushed < INT_MAX); + return (int)flushed; +} diff --git a/src/lib/net/buffers_net.h b/src/lib/net/buffers_net.h new file mode 100644 index 000000000..d03b61376 --- /dev/null +++ b/src/lib/net/buffers_net.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2001 Matej Pfajfar. + * Copyright (c) 2001-2004, Roger Dingledine. + * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. + * Copyright (c) 2007-2018, The Tor Project, Inc. */ +/* See LICENSE for licensing information */ + +/** + * \file buffers.h + * \brief Header file for buffers.c. + **/ + +#ifndef TOR_BUFFERS_NET_H +#define TOR_BUFFERS_NET_H + +#include <stddef.h> +#include "lib/net/socket.h" + +struct buf_t; +int buf_read_from_socket(struct buf_t *buf, tor_socket_t s, size_t at_most, + int *reached_eof, + int *socket_error); + +int buf_flush_to_socket(struct buf_t *buf, tor_socket_t s, size_t sz, + size_t *buf_flushlen); + +#endif /* !defined(TOR_BUFFERS_H) */ diff --git a/src/lib/net/include.am b/src/lib/net/include.am index 6f34479db..a375ac8ad 100644 --- a/src/lib/net/include.am +++ b/src/lib/net/include.am @@ -8,6 +8,7 @@ endif src_lib_libtor_net_a_SOURCES = \ src/lib/net/address.c \ src/lib/net/alertsock.c \ + src/lib/net/buffers_net.c \ src/lib/net/gethostname.c \ src/lib/net/ipv4.c \ src/lib/net/ipv6.c \ @@ -22,6 +23,7 @@ src_lib_libtor_net_testing_a_CFLAGS = $(AM_CFLAGS) $(TEST_CFLAGS) noinst_HEADERS += \ src/lib/net/address.h \ src/lib/net/alertsock.h \ + src/lib/net/buffers_net.h \ src/lib/net/gethostname.h \ src/lib/net/ipv4.h \ src/lib/net/ipv6.h \ diff --git a/src/lib/tls/buffers_tls.c b/src/lib/tls/buffers_tls.c index 0f9dd7a4d..243e0eb0b 100644 --- a/src/lib/tls/buffers_tls.c +++ b/src/lib/tls/buffers_tls.c @@ -7,7 +7,7 @@ #define BUFFERS_PRIVATE #include "orconfig.h" #include <stddef.h> -#include "common/buffers.h" +#include "lib/container/buffers.h" #include "lib/tls/buffers_tls.h" #include "lib/cc/torint.h" #include "lib/log/torlog.h" diff --git a/src/or/connection.c b/src/or/connection.c index 01067e94f..974281331 100644 --- a/src/or/connection.c +++ b/src/or/connection.c @@ -103,6 +103,7 @@ #include "or/transports.h" #include "or/routerparse.h" #include "lib/sandbox/sandbox.h" +#include "lib/net/buffers_net.h"
#ifdef HAVE_PWD_H #include <pwd.h> @@ -5315,4 +5316,3 @@ clock_skew_warning, (const connection_t *conn, long apparent_skew, int trusted, tor_free(warn); tor_free(ext_source); } - diff --git a/src/or/main.c b/src/or/main.c index 0ba38658a..67ebc980c 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -113,6 +113,7 @@ #include "lib/memarea/memarea.h" #include "lib/sandbox/sandbox.h" #include "lib/fs/lockfile.h" +#include "lib/net/buffers_net.h"
#include <event2/event.h>
tor-commits@lists.torproject.org