[tor-commits] [tor/master] Move the tls parts of buffers.c into buffers_tls.c

nickm at torproject.org nickm at torproject.org
Tue Sep 5 18:18:13 UTC 2017


commit 150089cbd7445f76a5d29df7d33c15c3a1ada034
Author: Nick Mathewson <nickm at torproject.org>
Date:   Tue Aug 8 15:06:40 2017 -0400

    Move the tls parts of buffers.c into buffers_tls.c
---
 src/or/buffers.c        | 181 +-----------------------------------------------
 src/or/buffers.h        |  27 ++++++--
 src/or/buffers_tls.c    | 175 ++++++++++++++++++++++++++++++++++++++++++++++
 src/or/buffers_tls.h    |  19 +++++
 src/or/connection.c     |   1 +
 src/or/include.am       |   2 +
 src/or/main.c           |   1 +
 src/test/test_buffers.c |   1 +
 8 files changed, 222 insertions(+), 185 deletions(-)

diff --git a/src/or/buffers.c b/src/or/buffers.c
index ee888b42a..1a9144e14 100644
--- a/src/or/buffers.c
+++ b/src/or/buffers.c
@@ -27,7 +27,6 @@
 #include "util.h"
 #include "torint.h"
 #include "torlog.h"
-#include "tortls.h"
 #ifdef HAVE_UNISTD_H
 #include <unistd.h>
 #endif
@@ -101,22 +100,6 @@
   } while (0)
 #endif
 
-/** Return the next character in <b>chunk</b> onto which data can be appended.
- * 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;
-}
-
-/** Return the number of bytes that can be written onto <b>chunk</b> without
- * running out of space. */
-static inline size_t
-CHUNK_REMAINING_CAPACITY(const chunk_t *chunk)
-{
-  return (chunk->mem + chunk->memlen) - (chunk->data + chunk->datalen);
-}
-
 /** Move all bytes stored in <b>chunk</b> to the front of <b>chunk</b>->mem,
  * to free up space at the end. */
 static inline void
@@ -183,9 +166,6 @@ chunk_grow(chunk_t *chunk, size_t sz)
   return chunk;
 }
 
-/** If a read onto the end of a chunk would be smaller than this number, then
- * just start a new chunk. */
-#define MIN_READ_LEN 8
 /** Every chunk should take up at least this many bytes. */
 #define MIN_CHUNK_ALLOC 256
 /** No chunk should take up more than this many bytes. */
@@ -479,7 +459,7 @@ buf_copy(const buf_t *buf)
 /** Append a new chunk with enough capacity to hold <b>capacity</b> bytes to
  * the tail of <b>buf</b>.  If <b>capped</b>, don't allocate a chunk bigger
  * than MAX_CHUNK_ALLOC. */
-static chunk_t *
+chunk_t *
 buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped)
 {
   chunk_t *chunk;
@@ -564,23 +544,6 @@ read_to_chunk(buf_t *buf, chunk_t *chunk, tor_socket_t fd, size_t at_most,
   }
 }
 
-/** As read_to_chunk(), but return (negative) error code on error, blocking,
- * 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;
-}
-
 /** 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
@@ -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;
 }
 
-/** 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.
- */
-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; /* 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 flush_buf(): 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
@@ -728,43 +630,6 @@ flush_chunk(tor_socket_t s, buf_t *buf, chunk_t *chunk, size_t sz,
   }
 }
 
-/** Helper for flush_buf_tls(): try to write <b>sz</b> bytes from chunk
- * <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;
-}
-
 /** 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
@@ -806,50 +671,6 @@ flush_buf(tor_socket_t s, buf_t *buf, size_t sz, size_t *buf_flushlen)
   return (int)flushed;
 }
 
-/** As flush_buf(), but writes data to a TLS connection.  Can write more than
- * <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;
-
-  /* we want to let tls write even if flushlen is zero, because it might
-   * 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) /* Can't flush any more now. */
-      break;
-  } while (sz > 0);
-  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>.
  *
diff --git a/src/or/buffers.h b/src/or/buffers.h
index 35fa46593..77cc9ce0f 100644
--- a/src/or/buffers.h
+++ b/src/or/buffers.h
@@ -19,9 +19,7 @@
 
 typedef struct buf_t buf_t;
 
-struct tor_tls_t;
 struct tor_compress_state_t;
-struct ext_or_cmd_t;
 
 buf_t *buf_new(void);
 buf_t *buf_new_with_capacity(size_t size);
@@ -39,11 +37,8 @@ size_t buf_get_total_allocation(void);
 
 int read_to_buf(tor_socket_t s, size_t at_most, buf_t *buf, int *reached_eof,
                 int *socket_error);
-int read_to_buf_tls(struct tor_tls_t *tls, size_t at_most, buf_t *buf);
 
 int flush_buf(tor_socket_t s, buf_t *buf, size_t sz, size_t *buf_flushlen);
-int flush_buf_tls(struct tor_tls_t *tls, buf_t *buf, size_t sz,
-                  size_t *buf_flushlen);
 
 int write_to_buf(const char *string, size_t string_len, buf_t *buf);
 int write_to_buf_compress(buf_t *buf, struct tor_compress_state_t *state,
@@ -100,6 +95,28 @@ struct buf_t {
   chunk_t *head; /**< First chunk in the list, or NULL for none. */
   chunk_t *tail; /**< Last chunk in the list, or NULL for none. */
 };
+
+chunk_t *buf_add_chunk_with_capacity(buf_t *buf, size_t capacity, int capped);
+/** If a read onto the end of a chunk would be smaller than this number, then
+ * just start a new chunk. */
+#define MIN_READ_LEN 8
+
+/** Return the number of bytes that can be written onto <b>chunk</b> without
+ * running out of space. */
+static inline size_t
+CHUNK_REMAINING_CAPACITY(const chunk_t *chunk)
+{
+  return (chunk->mem + chunk->memlen) - (chunk->data + chunk->datalen);
+}
+
+/** Return the next character in <b>chunk</b> onto which data can be appended.
+ * 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;
+}
+
 #endif
 
 #endif
diff --git a/src/or/buffers_tls.c b/src/or/buffers_tls.c
new file mode 100644
index 000000000..e47073869
--- /dev/null
+++ b/src/or/buffers_tls.c
@@ -0,0 +1,175 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#define BUFFERS_PRIVATE
+#include "orconfig.h"
+#include <stddef.h>
+#include "buffers.h"
+#include "buffers_tls.h"
+#include "compat.h"
+#include "compress.h"
+#include "util.h"
+#include "torint.h"
+#include "torlog.h"
+#include "tortls.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+/** As read_to_chunk(), but return (negative) error code on error, blocking,
+ * 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;
+}
+
+/** 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.
+ */
+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();
+
+  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);
+    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 flush_buf_tls(): try to write <b>sz</b> bytes from chunk
+ * <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;
+}
+
+/** As flush_buf(), but writes data to a TLS connection.  Can write more than
+ * <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;
+
+  /* we want to let tls write even if flushlen is zero, because it might
+   * have a partial record pending */
+  check_no_tls_errors();
+
+  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);
+    if (r < 0)
+      return r;
+    flushed += r;
+    sz -= r;
+    if (r == 0) /* Can't flush any more now. */
+      break;
+  } while (sz > 0);
+  tor_assert(flushed < INT_MAX);
+  return (int)flushed;
+}
+
diff --git a/src/or/buffers_tls.h b/src/or/buffers_tls.h
new file mode 100644
index 000000000..4fce6c113
--- /dev/null
+++ b/src/or/buffers_tls.h
@@ -0,0 +1,19 @@
+/* Copyright (c) 2001 Matej Pfajfar.
+ * Copyright (c) 2001-2004, Roger Dingledine.
+ * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
+ * Copyright (c) 2007-2017, The Tor Project, Inc. */
+/* See LICENSE for licensing information */
+
+#ifndef TOR_BUFFERS_TLS_H
+#define TOR_BUFFERS_TLS_H
+
+struct buf_t;
+struct tor_tls_t;
+
+int read_to_buf_tls(struct tor_tls_t *tls, size_t at_most,
+                    struct buf_t *buf);
+int flush_buf_tls(struct tor_tls_t *tls, struct buf_t *buf, size_t sz,
+                  size_t *buf_flushlen);
+
+#endif
+
diff --git a/src/or/connection.c b/src/or/connection.c
index 637b38cec..866ce5e0b 100644
--- a/src/or/connection.c
+++ b/src/or/connection.c
@@ -58,6 +58,7 @@
 #include "or.h"
 #include "bridges.h"
 #include "buffers.h"
+#include "buffers_tls.h"
 /*
  * Define this so we get channel internal functions, since we're implementing
  * part of a subclass (channel_tls_t).
diff --git a/src/or/include.am b/src/or/include.am
index fe860339f..6dc43749b 100644
--- a/src/or/include.am
+++ b/src/or/include.am
@@ -21,6 +21,7 @@ LIBTOR_A_SOURCES = \
 	src/or/addressmap.c				\
 	src/or/bridges.c				\
 	src/or/buffers.c				\
+	src/or/buffers_tls.c				\
 	src/or/channel.c				\
 	src/or/channelpadding.c				\
 	src/or/channeltls.c				\
@@ -156,6 +157,7 @@ ORHEADERS = \
 	src/or/addressmap.h				\
 	src/or/bridges.h				\
 	src/or/buffers.h				\
+	src/or/buffers_tls.h				\
 	src/or/channel.h				\
 	src/or/channelpadding.h				\
 	src/or/channeltls.h				\
diff --git a/src/or/main.c b/src/or/main.c
index 7939f1984..a9d4bdb6e 100644
--- a/src/or/main.c
+++ b/src/or/main.c
@@ -52,6 +52,7 @@
 #include "backtrace.h"
 #include "bridges.h"
 #include "buffers.h"
+#include "buffers_tls.h"
 #include "channel.h"
 #include "channeltls.h"
 #include "channelpadding.h"
diff --git a/src/test/test_buffers.c b/src/test/test_buffers.c
index 26c062597..d2d1223f3 100644
--- a/src/test/test_buffers.c
+++ b/src/test/test_buffers.c
@@ -7,6 +7,7 @@
 #define PROTO_HTTP_PRIVATE
 #include "or.h"
 #include "buffers.h"
+#include "buffers_tls.h"
 #include "ext_orport.h"
 #include "proto_cell.h"
 #include "proto_ext_or.h"





More information about the tor-commits mailing list