1 /* Copyright (c) 2001 Matej Pfajfar.
2 * Copyright (c) 2001-2004, Roger Dingledine.
3 * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson.
4 * Copyright (c) 2007-2019, The Tor Project, Inc. */
5 /* See LICENSE for licensing information */
9 * \brief Read and write data on a tor_tls_t connection from a buf_t object.
12 #define BUFFERS_PRIVATE
15 #include "lib/buf/buffers.h"
16 #include "lib/tls/buffers_tls.h"
17 #include "lib/cc/torint.h"
18 #include "lib/log/log.h"
19 #include "lib/log/util_bug.h"
20 #include "lib/tls/tortls.h"
26 /** As read_to_chunk(), but return (negative) error code on error, blocking,
27 * or TLS, and the number of bytes read otherwise. */
29 read_to_chunk_tls(buf_t
*buf
, chunk_t
*chunk
, tor_tls_t
*tls
,
34 tor_assert(CHUNK_REMAINING_CAPACITY(chunk
) >= at_most
);
35 read_result
= tor_tls_read(tls
, CHUNK_WRITE_PTR(chunk
), at_most
);
38 buf
->datalen
+= read_result
;
39 chunk
->datalen
+= read_result
;
43 /** As read_to_buf, but reads from a TLS connection, and returns a TLS
44 * status value rather than the number of bytes read.
46 * Using TLS on OR connections complicates matters in two ways.
48 * First, a TLS stream has its own read buffer independent of the
49 * connection's read buffer. (TLS needs to read an entire frame from
50 * the network before it can decrypt any data. Thus, trying to read 1
51 * byte from TLS can require that several KB be read from the network
52 * and decrypted. The extra data is stored in TLS's decrypt buffer.)
53 * Because the data hasn't been read by Tor (it's still inside the TLS),
54 * this means that sometimes a connection "has stuff to read" even when
55 * poll() didn't return POLLIN. The tor_tls_get_pending_bytes function is
56 * used in connection.c to detect TLS objects with non-empty internal
57 * buffers and read from them again.
59 * Second, the TLS stream's events do not correspond directly to network
60 * events: sometimes, before a TLS stream can read, the network must be
61 * ready to write -- or vice versa.
64 buf_read_from_tls(buf_t
*buf
, tor_tls_t
*tls
, size_t at_most
)
67 size_t total_read
= 0;
69 check_no_tls_errors();
71 IF_BUG_ONCE(buf
->datalen
>= INT_MAX
)
73 IF_BUG_ONCE(buf
->datalen
>= INT_MAX
- at_most
)
76 while (at_most
> total_read
) {
77 size_t readlen
= at_most
- total_read
;
79 if (!buf
->tail
|| CHUNK_REMAINING_CAPACITY(buf
->tail
) < MIN_READ_LEN
) {
80 chunk
= buf_add_chunk_with_capacity(buf
, at_most
, 1);
81 if (readlen
> chunk
->memlen
)
82 readlen
= chunk
->memlen
;
84 size_t cap
= CHUNK_REMAINING_CAPACITY(buf
->tail
);
90 r
= read_to_chunk_tls(buf
, chunk
, tls
, readlen
);
93 tor_assert(total_read
+r
< INT_MAX
);
95 if ((size_t)r
< readlen
) /* eof, block, or no more to read. */
98 return (int)total_read
;
101 /** Helper for buf_flush_to_tls(): try to write <b>sz</b> bytes from chunk
102 * <b>chunk</b> of buffer <b>buf</b> onto socket <b>s</b>. (Tries to write
103 * more if there is a forced pending write size.) On success, deduct the
104 * bytes written from *<b>buf_flushlen</b>. Return the number of bytes
105 * written on success, and a TOR_TLS error code on failure or blocking.
108 flush_chunk_tls(tor_tls_t
*tls
, buf_t
*buf
, chunk_t
*chunk
,
109 size_t sz
, size_t *buf_flushlen
)
115 forced
= tor_tls_get_forced_write_size(tls
);
120 tor_assert(sz
<= chunk
->datalen
);
125 r
= tor_tls_write(tls
, data
, sz
);
128 if (*buf_flushlen
> (size_t)r
)
133 log_debug(LD_NET
,"flushed %d bytes, %d ready to flush, %d remain.",
134 r
,(int)*buf_flushlen
,(int)buf
->datalen
);
138 /** As buf_flush_to_socket(), but writes data to a TLS connection. Can write
139 * more than <b>flushlen</b> bytes.
142 buf_flush_to_tls(buf_t
*buf
, tor_tls_t
*tls
, size_t flushlen
,
143 size_t *buf_flushlen
)
148 tor_assert(buf_flushlen
);
149 IF_BUG_ONCE(*buf_flushlen
> buf
->datalen
) {
150 *buf_flushlen
= buf
->datalen
;
152 IF_BUG_ONCE(flushlen
> *buf_flushlen
) {
153 flushlen
= *buf_flushlen
;
155 sz
= (ssize_t
) flushlen
;
157 /* we want to let tls write even if flushlen is zero, because it might
158 * have a partial record pending */
159 check_no_tls_errors();
164 if ((ssize_t
)buf
->head
->datalen
>= sz
)
167 flushlen0
= buf
->head
->datalen
;
172 r
= flush_chunk_tls(tls
, buf
, buf
->head
, flushlen0
, buf_flushlen
);
177 if (r
== 0) /* Can't flush any more now. */
180 tor_assert(flushed
< INT_MAX
);