include/boost/corosio/tls_stream.hpp

75.0% Lines (6/8) 100.0% List of functions (4/4) 50.0% Branches (2/4)
f(x) Functions (4)
Line Branch TLA Hits Source Code
1 //
2 // Copyright (c) 2025 Vinnie Falco ([email protected])
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 // Official repository: https://github.com/cppalliance/corosio
8 //
9
10 #ifndef BOOST_COROSIO_TLS_STREAM_HPP
11 #define BOOST_COROSIO_TLS_STREAM_HPP
12
13 #include <boost/corosio/detail/config.hpp>
14 #include <boost/capy/buffers.hpp>
15 #include <boost/capy/buffers/buffer_array.hpp>
16 #include <boost/capy/io/any_stream.hpp>
17 #include <boost/capy/io_task.hpp>
18
19 #include <cstddef>
20 #include <string_view>
21
22 namespace boost::corosio {
23
24 /** Abstract base class for TLS streams.
25
26 This class provides a runtime-polymorphic interface for TLS
27 implementations. Derived classes (openssl_stream, wolfssl_stream)
28 implement the virtual functions to provide backend-specific
29 TLS functionality.
30
31 Unlike @ref io_stream which represents OS-level I/O completed
32 by the kernel, TLS streams are coroutine-based: their operations
33 are implemented as coroutines that orchestrate sub-operations
34 on the underlying stream.
35
36 The non-virtual template wrappers (`read_some`, `write_some`)
37 satisfy the `capy::Stream` concept, enabling TLS streams to
38 be used anywhere a Stream is expected.
39
40 @par Thread Safety
41 Distinct objects: Safe.@n
42 Shared objects: Unsafe.
43
44 @see openssl_stream, wolfssl_stream
45 */
46 class BOOST_COROSIO_DECL tls_stream
47 {
48 public:
49 /// Identify the TLS handshake role.
50 enum handshake_type
51 {
52 client, ///< Perform handshaking as a client.
53 server ///< Perform handshaking as a server.
54 };
55
56 /// Destroy the TLS stream.
57 2175x virtual ~tls_stream() = default;
58
59 tls_stream(tls_stream const&) = delete;
60 tls_stream& operator=(tls_stream const&) = delete;
61
62 /** Initiate an asynchronous read operation.
63
64 Reads decrypted data into the provided buffer sequence. The
65 operation completes when at least one byte has been read,
66 or an error occurs.
67
68 This non-virtual template wrapper satisfies the `capy::Stream`
69 concept by delegating to the virtual `do_read_some`.
70
71 @param buffers The buffer sequence to read data into.
72
73 @return An awaitable yielding `(error_code,std::size_t)`.
74 */
75 template<capy::MutableBufferSequence Buffers>
76 155145x auto read_some(Buffers const& buffers)
77 {
78
1/2
✓ Branch 0 taken 155145 times.
✗ Branch 1 not taken.
155145x return do_read_some(buffers);
79 }
80
81 /** Initiate an asynchronous write operation.
82
83 Encrypts and writes data from the provided buffer sequence.
84 The operation completes when at least one byte has been
85 written, or an error occurs.
86
87 This non-virtual template wrapper satisfies the `capy::Stream`
88 concept by delegating to the virtual `do_write_some`.
89
90 @param buffers The buffer sequence containing data to write.
91
92 @return An awaitable yielding `(error_code,std::size_t)`.
93 */
94 template<capy::ConstBufferSequence Buffers>
95 155148x auto write_some(Buffers const& buffers)
96 {
97
1/2
✓ Branch 0 taken 155148 times.
✗ Branch 1 not taken.
155148x return do_write_some(buffers);
98 }
99
100 /** Perform the TLS handshake asynchronously.
101
102 Initiates the TLS handshake process. For client connections,
103 this sends the ClientHello and processes the server's response.
104 For server connections, this waits for the ClientHello and
105 sends the server's response.
106
107 @param type The type of handshaking to perform (client or server).
108
109 @return An awaitable yielding `(error_code)`.
110 */
111 virtual capy::io_task<> handshake(handshake_type type) = 0;
112
113 /** Perform a graceful TLS shutdown asynchronously.
114
115 Initiates the TLS shutdown sequence by sending a close_notify
116 alert and waiting for the peer's close_notify response.
117
118 @return An awaitable yielding `(error_code)`.
119 */
120 virtual capy::io_task<> shutdown() = 0;
121
122 /** Reset TLS session state for reuse.
123
124 Releases TLS session state including session keys and peer
125 certificates, returning the stream to a state where
126 `handshake()` can be called again. Internal memory
127 allocations (I/O buffers) are preserved.
128
129 Calling `handshake()` on a previously-used stream
130 implicitly performs a reset first, so explicit calls
131 are only needed to eagerly release session state.
132
133 @par Preconditions
134 No TLS operation (handshake, read, write, shutdown) is
135 in progress.
136
137 @par Thread Safety
138 Not thread safe. The caller must ensure no concurrent
139 operations are in progress on this stream.
140
141 @note If called mid-session before `shutdown()`, pending
142 TLS data is discarded and the peer will observe a
143 truncated stream.
144 */
145 virtual void reset() = 0;
146
147 /** Returns a reference to the underlying stream.
148
149 Provides access to the type-erased underlying stream for
150 operations like cancellation or accessing native handles.
151
152 @warning Do not reseat (assign to) the returned reference.
153 The TLS implementation holds internal state bound to
154 the original stream. Replacing it causes undefined
155 behavior.
156
157 @return Reference to the wrapped stream.
158 */
159 virtual capy::any_stream& next_layer() noexcept = 0;
160
161 /** Returns a const reference to the underlying stream.
162
163 @return Const reference to the wrapped stream.
164 */
165 virtual capy::any_stream const& next_layer() const noexcept = 0;
166
167 /** Returns the name of the TLS backend.
168
169 @return A string identifying the TLS implementation,
170 such as "openssl" or "wolfssl".
171 */
172 virtual std::string_view name() const noexcept = 0;
173
174 protected:
175 2175x tls_stream() = default;
176
177 /** Virtual read implementation.
178
179 Derived classes override this to perform TLS decryption
180 and read operations.
181
182 @param buffers Buffer sequence to read into.
183
184 @return An awaitable yielding `(error_code,std::size_t)`.
185 */
186 virtual capy::io_task<std::size_t> do_read_some(
187 capy::mutable_buffer_array<capy::detail::max_iovec_> buffers) = 0;
188
189 /** Virtual write implementation.
190
191 Derived classes override this to perform TLS encryption
192 and write operations.
193
194 @param buffers Buffer sequence to write from.
195
196 @return An awaitable yielding `(error_code,std::size_t)`.
197 */
198 virtual capy::io_task<std::size_t> do_write_some(
199 capy::const_buffer_array<capy::detail::max_iovec_> buffers) = 0;
200 };
201
202 } // namespace boost::corosio
203
204 #endif
205