MySQL 8.4.1
Source Code Documentation
channel.h
Go to the documentation of this file.
1/*
2Copyright (c) 2020, 2024, 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
50
51/**
52 * SSL aware socket buffers.
53 *
54 * manages the raw and plaintext socket buffers of connection which may switch
55 * to TLS.
56 *
57 * an external user like a socket class can
58 *
59 * - receive from a socket and store the socket data into the recv_buffer().
60 * - send to a socket from the send_buffer().
61 *
62 * Once init_ssl() is called, the recv_plain() and write_plain() methods
63 * transparently decrypt and encrypt.
64 */
66 public:
67 Channel() = default;
68
70 std::vector<uint8_t, default_init_allocator<uint8_t>>;
71 using recv_view_type = std::span<typename recv_buffer_type::value_type>;
73
74 explicit Channel(Ssl ssl) : ssl_{std::move(ssl)} {}
75
76 /**
77 * clears all buffers.
78 */
79 void clear() {
80 recv_buffer_.clear();
81 recv_plain_buffer_.clear();
82 send_buffer_.clear();
83 send_plain_buffer_.clear();
84
85 payload_buffer_.clear();
86
87 view_sync_plain();
88 view_sync_raw();
89 }
90
91 /**
92 * initialize the SSL session.
93 */
94 void init_ssl(SSL_CTX *ssl_ctx) {
95 ssl_.reset(SSL_new(ssl_ctx));
96 // the BIOs are owned by the SSL
97 SSL_set_bio(ssl_.get(), BIO_new(BIO_s_mem()), BIO_new(BIO_s_mem()));
98 }
99
100 /**
101 * accept a TLS session.
102 *
103 * expects a Tls::ClientHello in the recv_buf.
104 */
106
107 /**
108 * connect a TLS session.
109 *
110 *
111 */
113 bool tls_init_is_finished();
114
115 /**
116 * @return on success, true if shutdown is finished, false if not
117 * @return on failure, an error-code
118 */
120
121 /**
122 * write unencrypted net::dynamic_buffer to the channel.
123 *
124 * if the channel has an ssl session it transparently encrypts before
125 * the data is appended to the send_buf()
126 */
127 template <class DynamicBuffer>
128 typename std::enable_if<net::is_dynamic_buffer<DynamicBuffer>::value,
130 write(DynamicBuffer &dyn_buf) {
131 auto orig_size = dyn_buf.size();
132 size_t transferred{};
133
134 auto write_res = write_plain(dyn_buf.data(0, orig_size));
135 if (!write_res) {
136 return stdx::unexpected(write_res.error());
137 }
138
139 transferred += write_res.value();
140 dyn_buf.consume(write_res.value());
141
142 return transferred;
143 }
144
145 /**
146 * write unencrypted net::const_buffer to the channel.
147 *
148 * if the channel has an ssl session it transparently encrypts before
149 * the data is appended to the send_buf()
150 */
152 return write_plain(b);
153 }
154
155 /**
156 * read unencrypted data from channel to a net::dynamic_buffer.
157 *
158 * if the channel has a ssl session in transparently decrypts before
159 * the data is appending to the recv_plain_buf()
160 */
161 template <class DynamicBuffer>
163 size_t sz) {
164 auto orig_size = dyn_buf.size();
165 auto grow_size = sz;
166 size_t transferred{};
167
168 dyn_buf.grow(grow_size);
169
170 const auto res_res = read_plain(dyn_buf.data(orig_size, grow_size));
171 if (!res_res) {
172 dyn_buf.shrink(grow_size);
173 return stdx::unexpected(res_res.error());
174 }
175
176 transferred += res_res.value();
177 dyn_buf.shrink(grow_size - res_res.value());
178
179 return transferred;
180 }
181
182 stdx::expected<size_t, std::error_code> read_to_plain(size_t sz);
183
184 /**
185 * write unencrypted data from a net::const_buffer to the channel.
186 *
187 * call flush_to_send_buf() ensure data is written to the
188 * send-buffers for the socket.
189 *
190 * @see flush_to_send_buf()
191 */
193 const net::const_buffer &b);
194
195 /**
196 * read plaintext data from recv_plain_buffer() into b.
197 */
199 const net::mutable_buffer &b);
200
201 /**
202 * flush data from receive buffer to recv_plain_buffer().
203 *
204 * if an SSL session is active, flush_to_recv_buf() ensures that data
205 * encrypted data gets decrypted and added to the recv_plain_buffer().
206 *
207 * In case no SSL session is active, it is a no-op.
208 */
209 stdx::expected<size_t, std::error_code> flush_from_recv_buf();
210
211 /**
212 * flush data to the send buffer.
213 *
214 * if write_plain() was used and an SSL session is active,
215 * flush_to_send_buf() ensures that data plaintext data gets encrypted and
216 * added to the send_buf().
217 *
218 * In case no SSL session is active, it is a no-op.
219 */
220 stdx::expected<size_t, std::error_code> flush_to_send_buf();
221
222 /**
223 * bytes wanted.
224 *
225 * signals to the socket layer how many bytes should be at least read into the
226 * buffer.
227 */
228 void want_recv(size_t wanted) { want_recv_ = wanted; }
229
230 /**
231 * bytes wanted.
232 *
233 * @return bytes wanted to be received at least.
234 */
235 size_t want_recv() const { return want_recv_; }
236
237 /**
238 * buffer of data that was received from the socket.
239 */
240 recv_buffer_type &recv_buffer() { return recv_buffer_; }
241
242 /**
243 * buffer of data to be sent to the socket.
244 *
245 * written into by write(), write_plain(), flush_to_send_buf().
246 */
247 recv_buffer_type &send_buffer() { return send_buffer_; }
248
249 /**
250 * unencrypted data to be sent to the socket.
251 */
252 recv_buffer_type &send_plain_buffer();
253
254 /**
255 * buffer of data that was received from the socket.
256 *
257 */
258 const recv_buffer_type &recv_buffer() const { return recv_buffer_; }
259
260 /**
261 * network data after a recv().
262 */
263 const recv_view_type &recv_view() const;
264
265 /**
266 * buffer of data to be sent to the socket.
267 */
268 const recv_buffer_type &send_buffer() const { return send_buffer_; }
269
270 /**
271 * payload buffer for
272 */
273 const recv_buffer_type &payload_buffer() const { return payload_buffer_; }
274
275 recv_buffer_type &payload_buffer() { return payload_buffer_; }
276
277 /**
278 * decrypted data after a recv().
279 */
280 const recv_view_type &recv_plain_view() const;
281
282 // consume count bytes from the recv_buffers.
283 void consume_raw(size_t count);
284
285 // consume count bytes from the recv_plain_buffers.
286 void consume_plain(size_t count);
287
288 // discard the data from the recv-buffer that have been 'consumed'
289 void view_discard_raw();
290
291 // discard the data from the recv-plain-buffer that have been 'consumed'
292 void view_discard_plain();
293
294 // updated the recv-buffer's view with the recv-buffer.
295 void view_sync_raw();
296
297 // updated the recv-plain-buffer's view with the recv-plain-buffer.
298 void view_sync_plain();
299
300 /**
301 * mark channel as containing TLS data in the recv_buffer().
302 *
303 * it is independent of calling init_tls() as the channel
304 * may be used to transfer encrypted data as is without
305 * ever call init_ssl().
306 */
307 void is_tls(bool v) { is_tls_ = v; }
308
309 /**
310 * check if connection switched to TLS.
311 */
312 bool is_tls() const { return is_tls_; }
313
314 /**
315 * get access to the raw SSL handle.
316 *
317 * can be used to call:
318 *
319 * - SSL_get_cipher_name()
320 * - SSL_version()
321 *
322 * @retval nullptr if channel has no SSL initialized.
323 */
324 SSL *ssl() const { return ssl_.get(); }
325
326 /**
327 * release the internal Ssl structure.
328 */
329 Ssl release_ssl();
330
331 private:
332 size_t want_recv_{};
333
338
340
343
344 bool is_tls_{false};
345
346 Ssl ssl_{};
347};
348
349#endif
SSL aware socket buffers.
Definition: channel.h:65
Channel()=default
stdx::expected< size_t, std::error_code > write(const net::const_buffer &b)
write unencrypted net::const_buffer to the channel.
Definition: channel.h:151
recv_buffer_type send_buffer_
Definition: channel.h:342
recv_buffer_type send_plain_buffer_
Definition: channel.h:341
const recv_buffer_type & recv_buffer() const
buffer of data that was received from the socket.
Definition: channel.h:258
void clear()
clears all buffers.
Definition: channel.h:79
size_t want_recv() const
bytes wanted.
Definition: channel.h:235
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:162
const recv_buffer_type & send_buffer() const
buffer of data to be sent to the socket.
Definition: channel.h:268
void init_ssl(SSL_CTX *ssl_ctx)
initialize the SSL session.
Definition: channel.h:94
void is_tls(bool v)
mark channel as containing TLS data in the recv_buffer().
Definition: channel.h:307
void want_recv(size_t wanted)
bytes wanted.
Definition: channel.h:228
recv_buffer_type & payload_buffer()
Definition: channel.h:275
SSL * ssl() const
get access to the raw SSL handle.
Definition: channel.h:324
std::enable_if< net::is_dynamic_buffer< DynamicBuffer >::value, stdx::expected< size_t, std::error_code > >::type write(DynamicBuffer &dyn_buf)
write unencrypted net::dynamic_buffer to the channel.
Definition: channel.h:130
const recv_buffer_type & payload_buffer() const
payload buffer for
Definition: channel.h:273
Channel(Ssl ssl)
Definition: channel.h:74
recv_view_type recv_view_
Definition: channel.h:335
recv_buffer_type recv_buffer_
Definition: channel.h:334
std::span< typename recv_buffer_type::value_type > recv_view_type
Definition: channel.h:71
recv_view_type recv_plain_view_
Definition: channel.h:337
mysql_harness::Ssl Ssl
Definition: channel.h:72
recv_buffer_type & send_buffer()
buffer of data to be sent to the socket.
Definition: channel.h:247
std::vector< uint8_t, default_init_allocator< uint8_t > > recv_buffer_type
Definition: channel.h:70
bool is_tls() const
check if connection switched to TLS.
Definition: channel.h:312
recv_buffer_type & recv_buffer()
buffer of data that was received from the socket.
Definition: channel.h:240
recv_buffer_type payload_buffer_
Definition: channel.h:339
recv_buffer_type recv_plain_buffer_
Definition: channel.h:336
Definition: buffer.h:135
Definition: buffer.h:113
Definition: expected.h:284
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
Definition: gcs_xcom_synode.h:64
unexpected(E) -> unexpected< E >
required string type
Definition: replication_group_member_actions.proto:34
#define ROUTING_CONNECTIONS_EXPORT
Definition: routing_connections_export.h:15