MySQL 26.10.0
Source Code Documentation
channel.h
Go to the documentation of this file.
1/*
2Copyright (c) 2020, 2026, Oracle and/or its affiliates.
3
4This program is free software; you can redistribute it and/or modify
5it under the terms of the GNU General Public License, version 2.0,
6as published by the Free Software Foundation.
7
8This program is designed to work with certain software (including
9but not limited to OpenSSL) that is licensed under separate terms,
10as designated in a particular file or component or in included license
11documentation. The authors of MySQL hereby grant you an additional
12permission to link the program and your derivative works with the
13separately licensed software that they have either included with
14the program or referenced in the documentation.
15
16This program is distributed in the hope that it will be useful,
17but WITHOUT ANY WARRANTY; without even the implied warranty of
18MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19GNU General Public License for more details.
20
21You should have received a copy of the GNU General Public License
22along with this program; if not, write to the Free Software
23Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24*/
25
26#ifndef MYSQL_ROUTER_CHANNEL_INCLUDED
27#define MYSQL_ROUTER_CHANNEL_INCLUDED
28
30
31#include <memory>
32#include <system_error>
33#include <type_traits>
34#include <vector>
35
36#ifdef _WIN32
37// include winsock2.h before openssl/ssl.h
38#include <windows.h>
39#include <winsock2.h>
40#include <ws2tcpip.h>
41#endif
42
43#include <openssl/ssl.h>
44
51
52/**
53 * SSL aware socket buffers.
54 *
55 * manages the raw and plaintext socket buffers of connection which may switch
56 * to TLS.
57 *
58 * an external user like a socket class can
59 *
60 * - receive from a socket and store the socket data into the recv_buffer().
61 * - send to a socket from the send_buffer().
62 *
63 * Once init_ssl() is called, the recv_plain() and write_plain() methods
64 * transparently decrypt and encrypt.
65 */
67 public:
68 Channel() = default;
69
71 std::vector<uint8_t, default_init_allocator<uint8_t>>;
72 using recv_view_type = std::span<typename recv_buffer_type::value_type>;
74
75 explicit Channel(Ssl ssl) : ssl_{std::move(ssl)} {}
76
77 /**
78 * clears all buffers.
79 */
80 void clear() {
81 recv_buffer_.clear();
82 recv_plain_buffer_.clear();
83 send_buffer_.clear();
84 send_plain_buffer_.clear();
85
86 payload_buffer_.clear();
87
88 view_sync_plain();
89 view_sync_raw();
90 }
91
92 /**
93 * initialize the SSL session.
94 */
95 void init_ssl(SSL_CTX *ssl_ctx) {
96 tls_context_.reset();
97 init_ssl_impl(ssl_ctx);
98 }
99
100 void init_ssl(std::shared_ptr<TlsContext> ssl_ctx) {
101 tls_context_ = std::move(ssl_ctx);
102 init_ssl_impl(tls_context_->get());
103 }
104
105 /**
106 * accept a TLS session.
107 *
108 * expects a Tls::ClientHello in the recv_buf.
109 */
111
112 /**
113 * connect a TLS session.
114 *
115 *
116 */
118 bool tls_init_is_finished();
119
120 /**
121 * @return on success, true if shutdown is finished, false if not
122 * @return on failure, an error-code
123 */
125
126 /**
127 * write unencrypted net::dynamic_buffer to the channel.
128 *
129 * if the channel has an ssl session it transparently encrypts before
130 * the data is appended to the send_buf()
131 */
132 template <class DynamicBuffer>
134 requires(net::is_dynamic_buffer_v<DynamicBuffer>)
135 {
136 auto orig_size = dyn_buf.size();
137 size_t transferred{};
138
139 auto write_res = write_plain(dyn_buf.data(0, orig_size));
140 if (!write_res) {
141 return stdx::unexpected(write_res.error());
142 }
143
144 transferred += write_res.value();
145 dyn_buf.consume(write_res.value());
146
147 return transferred;
148 }
149
150 /**
151 * write unencrypted net::const_buffer to the channel.
152 *
153 * if the channel has an ssl session it transparently encrypts before
154 * the data is appended to the send_buf()
155 */
157 return write_plain(b);
158 }
159
160 /**
161 * read unencrypted data from channel to a net::dynamic_buffer.
162 *
163 * if the channel has a ssl session in transparently decrypts before
164 * the data is appending to the recv_plain_buf()
165 */
166 template <class DynamicBuffer>
168 size_t sz) {
169 auto orig_size = dyn_buf.size();
170 auto grow_size = sz;
171 size_t transferred{};
172
173 dyn_buf.grow(grow_size);
174
175 const auto res_res = read_plain(dyn_buf.data(orig_size, grow_size));
176 if (!res_res) {
177 dyn_buf.shrink(grow_size);
178 return stdx::unexpected(res_res.error());
179 }
180
181 transferred += res_res.value();
182 dyn_buf.shrink(grow_size - res_res.value());
183
184 return transferred;
185 }
186
187 stdx::expected<size_t, std::error_code> read_to_plain(size_t sz);
188
189 /**
190 * write unencrypted data from a net::const_buffer to the channel.
191 *
192 * call flush_to_send_buf() ensure data is written to the
193 * send-buffers for the socket.
194 *
195 * @see flush_to_send_buf()
196 */
198 const net::const_buffer &b);
199
200 /**
201 * read plaintext data from recv_plain_buffer() into b.
202 */
204 const net::mutable_buffer &b);
205
206 /**
207 * flush data from receive buffer to recv_plain_buffer().
208 *
209 * if an SSL session is active, flush_to_recv_buf() ensures that data
210 * encrypted data gets decrypted and added to the recv_plain_buffer().
211 *
212 * In case no SSL session is active, it is a no-op.
213 */
214 stdx::expected<size_t, std::error_code> flush_from_recv_buf();
215
216 /**
217 * flush data to the send buffer.
218 *
219 * if write_plain() was used and an SSL session is active,
220 * flush_to_send_buf() ensures that data plaintext data gets encrypted and
221 * added to the send_buf().
222 *
223 * In case no SSL session is active, it is a no-op.
224 */
225 stdx::expected<size_t, std::error_code> flush_to_send_buf();
226
227 /**
228 * bytes wanted.
229 *
230 * signals to the socket layer how many bytes should be at least read into the
231 * buffer.
232 */
233 void want_recv(size_t wanted) { want_recv_ = wanted; }
234
235 /**
236 * bytes wanted.
237 *
238 * @return bytes wanted to be received at least.
239 */
240 size_t want_recv() const { return want_recv_; }
241
242 /**
243 * buffer of data that was received from the socket.
244 */
245 recv_buffer_type &recv_buffer() { return recv_buffer_; }
246
247 /**
248 * buffer of data to be sent to the socket.
249 *
250 * written into by write(), write_plain(), flush_to_send_buf().
251 */
252 recv_buffer_type &send_buffer() { return send_buffer_; }
253
254 /**
255 * unencrypted data to be sent to the socket.
256 */
257 recv_buffer_type &send_plain_buffer();
258
259 /**
260 * buffer of data that was received from the socket.
261 *
262 */
263 const recv_buffer_type &recv_buffer() const { return recv_buffer_; }
264
265 /**
266 * network data after a recv().
267 */
268 const recv_view_type &recv_view() const;
269
270 /**
271 * buffer of data to be sent to the socket.
272 */
273 const recv_buffer_type &send_buffer() const { return send_buffer_; }
274
275 /**
276 * payload buffer for
277 */
278 const recv_buffer_type &payload_buffer() const { return payload_buffer_; }
279
280 recv_buffer_type &payload_buffer() { return payload_buffer_; }
281
282 /**
283 * decrypted data after a recv().
284 */
285 const recv_view_type &recv_plain_view() const;
286
287 // consume count bytes from the recv_buffers.
288 void consume_raw(size_t count);
289
290 // consume count bytes from the recv_plain_buffers.
291 void consume_plain(size_t count);
292
293 // discard the data from the recv-buffer that have been 'consumed'
294 void view_discard_raw();
295
296 // discard the data from the recv-plain-buffer that have been 'consumed'
297 void view_discard_plain();
298
299 // updated the recv-buffer's view with the recv-buffer.
300 void view_sync_raw();
301
302 // updated the recv-plain-buffer's view with the recv-plain-buffer.
303 void view_sync_plain();
304
305 /**
306 * mark channel as containing TLS data in the recv_buffer().
307 *
308 * it is independent of calling init_tls() as the channel
309 * may be used to transfer encrypted data as is without
310 * ever call init_ssl().
311 */
312 void is_tls(bool v) { is_tls_ = v; }
313
314 /**
315 * check if connection switched to TLS.
316 */
317 bool is_tls() const { return is_tls_; }
318
319 /**
320 * get access to the raw SSL handle.
321 *
322 * can be used to call:
323 *
324 * - SSL_get_cipher_name()
325 * - SSL_version()
326 *
327 * @retval nullptr if channel has no SSL initialized.
328 */
329 SSL *ssl() const { return ssl_.get(); }
330
331 /**
332 * release the internal Ssl structure.
333 */
334 Ssl release_ssl();
335
336 private:
337 void init_ssl_impl(SSL_CTX *ssl_ctx) {
338 ssl_.reset(SSL_new(ssl_ctx));
339 // the BIOs are owned by the SSL
340 SSL_set_bio(ssl_.get(), BIO_new(BIO_s_mem()), BIO_new(BIO_s_mem()));
341 }
342
343 size_t want_recv_{};
344
349
351
354
355 bool is_tls_{false};
356
357 Ssl ssl_{};
358 std::shared_ptr<TlsContext> tls_context_;
359};
360
361#endif
SSL aware socket buffers.
Definition: channel.h:66
Channel()=default
std::shared_ptr< TlsContext > tls_context_
Definition: channel.h:358
void init_ssl(std::shared_ptr< TlsContext > ssl_ctx)
Definition: channel.h:100
stdx::expected< size_t, std::error_code > write(const net::const_buffer &b)
write unencrypted net::const_buffer to the channel.
Definition: channel.h:156
recv_buffer_type send_buffer_
Definition: channel.h:353
recv_buffer_type send_plain_buffer_
Definition: channel.h:352
const recv_buffer_type & recv_buffer() const
buffer of data that was received from the socket.
Definition: channel.h:263
void clear()
clears all buffers.
Definition: channel.h:80
size_t want_recv() const
bytes wanted.
Definition: channel.h:240
stdx::expected< size_t, std::error_code > read(DynamicBuffer &dyn_buf, size_t sz)
read unencrypted data from channel to a net::dynamic_buffer.
Definition: channel.h:167
const recv_buffer_type & send_buffer() const
buffer of data to be sent to the socket.
Definition: channel.h:273
void init_ssl(SSL_CTX *ssl_ctx)
initialize the SSL session.
Definition: channel.h:95
void is_tls(bool v)
mark channel as containing TLS data in the recv_buffer().
Definition: channel.h:312
stdx::expected< size_t, std::error_code > write(DynamicBuffer &dyn_buf)
write unencrypted net::dynamic_buffer to the channel.
Definition: channel.h:133
void want_recv(size_t wanted)
bytes wanted.
Definition: channel.h:233
recv_buffer_type & payload_buffer()
Definition: channel.h:280
SSL * ssl() const
get access to the raw SSL handle.
Definition: channel.h:329
const recv_buffer_type & payload_buffer() const
payload buffer for
Definition: channel.h:278
Channel(Ssl ssl)
Definition: channel.h:75
void init_ssl_impl(SSL_CTX *ssl_ctx)
Definition: channel.h:337
recv_view_type recv_view_
Definition: channel.h:346
recv_buffer_type recv_buffer_
Definition: channel.h:345
std::span< typename recv_buffer_type::value_type > recv_view_type
Definition: channel.h:72
recv_view_type recv_plain_view_
Definition: channel.h:348
mysql_harness::Ssl Ssl
Definition: channel.h:73
recv_buffer_type & send_buffer()
buffer of data to be sent to the socket.
Definition: channel.h:252
std::vector< uint8_t, default_init_allocator< uint8_t > > recv_buffer_type
Definition: channel.h:71
bool is_tls() const
check if connection switched to TLS.
Definition: channel.h:317
recv_buffer_type & recv_buffer()
buffer of data that was received from the socket.
Definition: channel.h:245
recv_buffer_type payload_buffer_
Definition: channel.h:350
recv_buffer_type recv_plain_buffer_
Definition: channel.h:347
Definition: buffer.h:135
Definition: buffer.h:113
Definition: expected.h:286
static int count
Definition: myisam_ftdump.cc:45
constexpr value_type ssl
Definition: classic_protocol_constants.h:49
std::unique_ptr< SSL, mysql_harness::impl::Deleter_SSL > Ssl
Definition: tls_types.h:48
Define std::hash<Gtid>.
Definition: gtid.h:355
unexpected(E) -> unexpected< E >
#define ROUTING_CONNECTIONS_EXPORT
Definition: routing_connections_export.h:15