|
@@ -27,7 +27,6 @@
|
|
#include "util.h"
|
|
#include "util.h"
|
|
#include "torint.h"
|
|
#include "torint.h"
|
|
#include "torlog.h"
|
|
#include "torlog.h"
|
|
-#include "tortls.h"
|
|
|
|
#ifdef HAVE_UNISTD_H
|
|
#ifdef HAVE_UNISTD_H
|
|
#include <unistd.h>
|
|
#include <unistd.h>
|
|
#endif
|
|
#endif
|
|
@@ -101,22 +100,6 @@
|
|
} while (0)
|
|
} while (0)
|
|
#endif
|
|
#endif
|
|
|
|
|
|
-
|
|
|
|
- * If the chunk is full, this might be off the end of chunk->mem. */
|
|
|
|
-static inline char *
|
|
|
|
-CHUNK_WRITE_PTR(chunk_t *chunk)
|
|
|
|
-{
|
|
|
|
- return chunk->data + chunk->datalen;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- * running out of space. */
|
|
|
|
-static inline size_t
|
|
|
|
-CHUNK_REMAINING_CAPACITY(const chunk_t *chunk)
|
|
|
|
-{
|
|
|
|
- return (chunk->mem + chunk->memlen) - (chunk->data + chunk->datalen);
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
|
|
|
|
* to free up space at the end. */
|
|
* to free up space at the end. */
|
|
static inline void
|
|
static inline void
|
|
@@ -183,9 +166,6 @@ chunk_grow(chunk_t *chunk, size_t sz)
|
|
return chunk;
|
|
return chunk;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- * just start a new chunk. */
|
|
|
|
-#define MIN_READ_LEN 8
|
|
|
|
|
|
|
|
#define MIN_CHUNK_ALLOC 256
|
|
#define MIN_CHUNK_ALLOC 256
|
|
|
|
|
|
@@ -479,7 +459,7 @@ buf_copy(const buf_t *buf)
|
|
|
|
|
|
* the tail of <b>buf</b>. If <b>capped</b>, don't allocate a chunk bigger
|
|
* the tail of <b>buf</b>. If <b>capped</b>, don't allocate a chunk bigger
|
|
* than MAX_CHUNK_ALLOC. */
|
|
* than MAX_CHUNK_ALLOC. */
|
|
-static chunk_t *
|
|
+chunk_t *
|
|
buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped)
|
|
buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped)
|
|
{
|
|
{
|
|
chunk_t *chunk;
|
|
chunk_t *chunk;
|
|
@@ -564,23 +544,6 @@ read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- * or TLS, and the number of bytes read otherwise. */
|
|
|
|
-static inline int
|
|
|
|
-read_to_chunk_tls(buf_t *buf, chunk_t *chunk, tor_tls_t *tls,
|
|
|
|
- size_t at_most)
|
|
|
|
-{
|
|
|
|
- int read_result;
|
|
|
|
-
|
|
|
|
- tor_assert(CHUNK_REMAINING_CAPACITY(chunk) >= at_most);
|
|
|
|
- read_result = tor_tls_read(tls, CHUNK_WRITE_PTR(chunk), at_most);
|
|
|
|
- if (read_result < 0)
|
|
|
|
- return read_result;
|
|
|
|
- buf->datalen += read_result;
|
|
|
|
- chunk->datalen += read_result;
|
|
|
|
- return read_result;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
|
|
|
|
* <b>at_most</b> bytes, growing the buffer as necessary. If recv() returns 0
|
|
* <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
|
|
* (because of EOF), set *<b>reached_eof</b> to 1 and return 0. Return -1 on
|
|
@@ -633,67 +596,6 @@ read_to_buf(tor_socket_t s, size_t at_most, buf_t *buf, int *reached_eof,
|
|
return (int)total_read;
|
|
return (int)total_read;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- * 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.
|
|
|
|
- */
|
|
|
|
-int
|
|
|
|
-read_to_buf_tls(tor_tls_t *tls, size_t at_most, buf_t *buf)
|
|
|
|
-{
|
|
|
|
- int r = 0;
|
|
|
|
- size_t total_read = 0;
|
|
|
|
-
|
|
|
|
- check_no_tls_errors();
|
|
|
|
-
|
|
|
|
- check();
|
|
|
|
-
|
|
|
|
- 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_tls(buf, chunk, tls, readlen);
|
|
|
|
- check();
|
|
|
|
- if (r < 0)
|
|
|
|
- return r;
|
|
|
|
- tor_assert(total_read+r < INT_MAX);
|
|
|
|
- total_read += r;
|
|
|
|
- if ((size_t)r < readlen)
|
|
|
|
- break;
|
|
|
|
- }
|
|
|
|
- return (int)total_read;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
|
|
|
|
* <b>chunk</b> of buffer <b>buf</b> onto socket <b>s</b>. On success, deduct
|
|
* <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
|
|
* the bytes written from *<b>buf_flushlen</b>. Return the number of bytes
|
|
@@ -728,43 +630,6 @@ flush_chunk(tor_socket_t s, buf_t *buf, chunk_t *chunk, size_t sz,
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- * <b>chunk</b> of buffer <b>buf</b> onto socket <b>s</b>. (Tries to write
|
|
|
|
- * more if there is a forced pending write size.) On success, deduct the
|
|
|
|
- * bytes written from *<b>buf_flushlen</b>. Return the number of bytes
|
|
|
|
- * written on success, and a TOR_TLS error code on failure or blocking.
|
|
|
|
- */
|
|
|
|
-static inline int
|
|
|
|
-flush_chunk_tls(tor_tls_t *tls, buf_t *buf, chunk_t *chunk,
|
|
|
|
- size_t sz, size_t *buf_flushlen)
|
|
|
|
-{
|
|
|
|
- int r;
|
|
|
|
- size_t forced;
|
|
|
|
- char *data;
|
|
|
|
-
|
|
|
|
- forced = tor_tls_get_forced_write_size(tls);
|
|
|
|
- if (forced > sz)
|
|
|
|
- sz = forced;
|
|
|
|
- if (chunk) {
|
|
|
|
- data = chunk->data;
|
|
|
|
- tor_assert(sz <= chunk->datalen);
|
|
|
|
- } else {
|
|
|
|
- data = NULL;
|
|
|
|
- tor_assert(sz == 0);
|
|
|
|
- }
|
|
|
|
- r = tor_tls_write(tls, data, sz);
|
|
|
|
- if (r < 0)
|
|
|
|
- return r;
|
|
|
|
- if (*buf_flushlen > (size_t)r)
|
|
|
|
- *buf_flushlen -= r;
|
|
|
|
- else
|
|
|
|
- *buf_flushlen = 0;
|
|
|
|
- buf_remove_from_front(buf, r);
|
|
|
|
- log_debug(LD_NET,"flushed %d bytes, %d ready to flush, %d remain.",
|
|
|
|
- r,(int)*buf_flushlen,(int)buf->datalen);
|
|
|
|
- return r;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
|
|
|
|
* <b>sz</b> bytes, decrement *<b>buf_flushlen</b> by
|
|
* <b>sz</b> bytes, decrement *<b>buf_flushlen</b> by
|
|
* the number of bytes actually written, and remove the written bytes
|
|
* the number of bytes actually written, and remove the written bytes
|
|
@@ -806,50 +671,6 @@ flush_buf(tor_socket_t s, buf_t *buf, size_t sz, size_t *buf_flushlen)
|
|
return (int)flushed;
|
|
return (int)flushed;
|
|
}
|
|
}
|
|
|
|
|
|
-
|
|
|
|
- * <b>flushlen</b> bytes.
|
|
|
|
- */
|
|
|
|
-int
|
|
|
|
-flush_buf_tls(tor_tls_t *tls, buf_t *buf, size_t flushlen,
|
|
|
|
- size_t *buf_flushlen)
|
|
|
|
-{
|
|
|
|
- int r;
|
|
|
|
- size_t flushed = 0;
|
|
|
|
- ssize_t sz;
|
|
|
|
- tor_assert(buf_flushlen);
|
|
|
|
- tor_assert(*buf_flushlen <= buf->datalen);
|
|
|
|
- tor_assert(flushlen <= *buf_flushlen);
|
|
|
|
- sz = (ssize_t) flushlen;
|
|
|
|
-
|
|
|
|
-
|
|
|
|
- * have a partial record pending */
|
|
|
|
- check_no_tls_errors();
|
|
|
|
-
|
|
|
|
- check();
|
|
|
|
- do {
|
|
|
|
- size_t flushlen0;
|
|
|
|
- if (buf->head) {
|
|
|
|
- if ((ssize_t)buf->head->datalen >= sz)
|
|
|
|
- flushlen0 = sz;
|
|
|
|
- else
|
|
|
|
- flushlen0 = buf->head->datalen;
|
|
|
|
- } else {
|
|
|
|
- flushlen0 = 0;
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- r = flush_chunk_tls(tls, buf, buf->head, flushlen0, buf_flushlen);
|
|
|
|
- check();
|
|
|
|
- if (r < 0)
|
|
|
|
- return r;
|
|
|
|
- flushed += r;
|
|
|
|
- sz -= r;
|
|
|
|
- if (r == 0)
|
|
|
|
- break;
|
|
|
|
- } while (sz > 0);
|
|
|
|
- tor_assert(flushed < INT_MAX);
|
|
|
|
- return (int)flushed;
|
|
|
|
-}
|
|
|
|
-
|
|
|
|
|
|
|
|
* <b>buf</b>.
|
|
* <b>buf</b>.
|
|
*
|
|
*
|