MySQL 9.1.0
Source Code Documentation
ssl_io_completion.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2021, 2024, Oracle and/or its affiliates.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is designed to work with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have either included with
14 the program or referenced in the documentation.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
24*/
25
26#ifndef ROUTER_SRC_OPENSSL_INCLUDE_TLS_DETAILS_SSL_OPERATION_H_
27#define ROUTER_SRC_OPENSSL_INCLUDE_TLS_DETAILS_SSL_OPERATION_H_
28
29#include <openssl/bio.h>
30
31#include <utility>
32
37
38namespace net {
39namespace tls {
40
42 const mutable_buffer &b) noexcept {
43 return std::addressof(b);
44}
45
47 const mutable_buffer &b) noexcept {
48 return std::addressof(b) + 1;
49}
50
52 const const_buffer &b) noexcept {
53 return std::addressof(b);
54}
55
57 const const_buffer &b) noexcept {
58 return std::addressof(b) + 1;
59}
60
61template <class C>
62inline auto tls_buffer_sequence_begin(const C &c) noexcept
63 -> decltype(c.begin()) {
64 return c.begin();
65}
66
67template <class C>
68inline auto tls_buffer_sequence_end(const C &c) noexcept -> decltype(c.end()) {
69 return c.end();
70}
71
73 public:
74 template <typename Layer, typename Handler>
75 auto recv(Layer *layer, FlexibleInputBuffer &input, Handler &&handler) {
76 return layer->async_receive(input, handler);
77 }
78
79 template <typename Layer, typename Handler>
80 auto send(Layer *layer, FlexibleOutputBuffer &output, Handler &&handler) {
81 return layer->async_send(output, handler);
82 }
83};
84
86 public:
87 struct Unexpected {};
90
91 template <typename Layer, typename Handler>
92 auto recv(Layer *layer, FlexibleInputBuffer &input, Handler &&) {
93 return read_result_ = layer->read_some(input);
94 }
95
96 template <typename Layer, typename Handler>
97 auto send(Layer *layer, FlexibleOutputBuffer &output, Handler &&) {
98 return write_result_ = layer->write_some(output);
99 }
100
101 template <typename Handler>
103 auto result = write_result_;
104 write_result_ = {};
105 if (result.has_value()) {
106 return handler->handle_write({}, result.value());
107 }
108
109 return handler->handle_write(result.error(), 0);
110 }
111
112 template <typename Handler>
114 auto result = read_result_;
115 read_result_ = {};
116 if (result.has_value()) {
117 return handler->handle_read({}, result.value());
118 }
119
120 return handler->handle_read(result.error(), 0);
121 }
122
125};
126
127template <typename SslIO, typename BufferSequence, typename Token,
128 typename TlsLayer, typename Action = AsyncAction>
130 public:
131 using Token_result = std::decay_t<Token>;
133 std::conditional_t<std::is_same<Token, Token_result>::value,
135
136 template <typename UniToken>
137 SslIoCompletionToken(TlsLayer &tls_layer, const BufferSequence &buffer,
138 UniToken &&token, Action action = Action())
139 : tls_layer_{tls_layer},
143 token_{std::forward<UniToken>(token)},
144 action_{action} {}
145
148 tls_layer_{other.tls_layer_},
151 buffer_{other.buffer_},
152 token_{other.token_},
153 action_{other.action_} {}
154
157 tls_layer_{other.tls_layer_},
160 buffer_{other.buffer_},
161 token_{other.token_},
162 action_{other.action_} {}
163
164 Operation::Result handle_read(std::error_code ec, size_t size) {
165 if (ec) {
166 do_token(ec, 0);
167 return Operation::Result::fatal;
168 }
169
171 return do_read();
172 }
173
174 Operation::Result handle_write(std::error_code ec, size_t size) {
175 if (ec) {
176 do_token(ec, 0);
177 return Operation::Result::fatal;
178 }
179
181 if (0 != net::buffer_size(output_)) {
182 return do_write();
183 }
184
185 return do_it();
186 }
187
190 auto it_next = it;
192
193 ++it_next;
194 size_t page_begin = 0;
195 size_t page_end = it->size();
196
197 while (it != end) {
198 const bool is_last = it_next == end;
199 if (!is_last && number_bytes_transfered_ >= page_end) {
200 it = it_next++;
201 page_begin = page_end;
202 if (it != end) page_end += it->size();
203 continue;
204 }
205
206 auto page_offset = number_bytes_transfered_ - page_begin;
207 size_t number_of_bytes = 0;
208 auto result =
209 SslIO::op(tls_layer_.network_bio_.get(), tls_layer_.ssl_.get(),
210 cast_and_increment<uint8_t>(it->data(), page_offset),
211 it->size() - page_offset, &number_of_bytes);
212
213 number_bytes_transfered_ += number_of_bytes;
214
215 debug_print("do_it - ", (SslIO::is_read_operation() ? "read" : "write"),
216 " - result:", result,
217 " - number_bytes_transfered_:", number_bytes_transfered_);
218 switch (result) {
219 case Operation::Result::fatal:
221 return result;
222
224 do_token(std::make_error_code(std::errc::broken_pipe), 0);
225 return result;
226
227 case Operation::Result::ok:
229 return result;
230
231 case Operation::Result::want_read: {
232 if (number_bytes_transfered_ && SslIO::is_read_operation()) {
234 return Operation::Result::ok;
235 }
236 return do_read();
237 }
238
239 case Operation::Result::want_write:
240 return do_write();
241 }
242 }
244 return Operation::Result::ok;
245 }
246
247 template <typename HandlerToken>
249 HandlerToken &&token) {
251 std::forward<HandlerToken>(token), NOP_token());
252 }
253
254 template <typename HandlerToken>
256 HandlerToken &&token) {
258 std::forward<HandlerToken>(token), NOP_token());
259 }
260
261 void do_token(const std::error_code &ec, const size_t no_of_bytes) {
262 token_(ec, no_of_bytes);
263 }
264
265 int bio_read_ex(size_t *out_readbytes) {
266 auto bio = tls_layer_.network_bio_.get();
267 *out_readbytes = 0;
268#if OPENSSL_VERSION_NUMBER >= NET_TLS_USE_BACKWARD_COMPATIBLE_OPENSSL
269 auto result = BIO_read_ex(bio, output_.data_free(), output_.size_free(),
270 out_readbytes);
271#else
272 auto result = BIO_read(bio, output_.data_free(), output_.size_free());
273 if (result > 0) *out_readbytes = result;
274#endif
275
276 return result;
277 }
278
279 int bio_write_ex(size_t *out_written) {
280 auto bio = tls_layer_.network_bio_.get();
281 *out_written = 0;
282#if OPENSSL_VERSION_NUMBER >= NET_TLS_USE_BACKWARD_COMPATIBLE_OPENSSL
283 auto result =
284 BIO_write_ex(bio, input_.data_used(), input_.size_used(), out_written);
285#else
286 auto result = BIO_write(bio, input_.data_used(), input_.size_used());
287 if (result > 0) *out_written = result;
288#endif
289
290 return result;
291 }
292
294 debug_print("do_write - ", (SslIO::is_read_operation() ? "read" : "write"));
295
296 if (0 == net::buffer_size(output_)) {
297 size_t readbytes;
298 bio_read_ex(&readbytes);
299 output_.push(readbytes);
300 }
301
302 action_.send(&tls_layer_.lower_layer_, output_,
303 get_write_handler(std::move(*this)));
304
305 return Operation::Result::want_write;
306 }
307
309 debug_print("do_read - ", (SslIO::is_read_operation() ? "read" : "write"));
310 if (0 == input_.size_used()) {
311 action_.recv(&tls_layer_.lower_layer_, input_,
312 get_read_handler(std::move(*this)));
313 return Operation::Result::want_read;
314 }
315
316 size_t written;
317 bio_write_ex(&written);
318 input_.pop(written);
319 return do_it();
320 }
321
322 template <typename... Parameters>
323 void debug_print([[maybe_unused]] Parameters &&...parameters) const {
324 // (std::cout << ... << std::forward<Parameters>(parameters));
325 // std::cout << std::endl;
326 }
327
328 template <typename Type>
329 static const Type *cast_and_increment(const void *ptr, int value) {
330 return static_cast<const Type *>(ptr) + value;
331 }
332
333 template <typename Type>
334 static Type *cast_and_increment(void *ptr, int value) {
335 return static_cast<Type *>(ptr) + value;
336 }
337
339 TlsLayer &tls_layer_;
342 const BufferSequence buffer_;
343 Token token_;
345};
346
347} // namespace tls
348} // namespace net
349
350#endif // ROUTER_SRC_OPENSSL_INCLUDE_TLS_DETAILS_SSL_OPERATION_H_
The handler class is the interface for dynamically loadable storage engines.
Definition: handler.h:4583
Definition: buffer.h:135
Definition: buffer.h:113
Definition: ssl_io_completion.h:72
auto send(Layer *layer, FlexibleOutputBuffer &output, Handler &&handler)
Definition: ssl_io_completion.h:80
auto recv(Layer *layer, FlexibleInputBuffer &input, Handler &&handler)
Definition: ssl_io_completion.h:75
size_t size_used() const
Definition: flexible_buffer.h:59
bool pop(size_t v) noexcept
Definition: flexible_buffer.h:67
void * data_free() const
Definition: flexible_buffer.h:57
void * data_used() const noexcept
Definition: flexible_buffer.h:56
bool push(size_t v) noexcept
Definition: flexible_buffer.h:78
size_t size_free() const
Definition: flexible_buffer.h:58
Definition: flexible_buffer.h:105
Definition: flexible_buffer.h:91
Definition: lower_layer_completion.h:40
Definition: lower_layer_completion.h:77
Definition: lower_layer_completion.h:34
Result
Definition: ssl_operation.h:41
Definition: ssl_io_completion.h:129
FlexibleInputBuffer & input_
Definition: ssl_io_completion.h:341
int bio_write_ex(size_t *out_written)
Definition: ssl_io_completion.h:279
static Type * cast_and_increment(void *ptr, int value)
Definition: ssl_io_completion.h:334
LowerLayerReadCompletionToken< HandlerToken, NOP_token > get_read_handler(HandlerToken &&token)
Definition: ssl_io_completion.h:255
Operation::Result handle_read(std::error_code ec, size_t size)
Definition: ssl_io_completion.h:164
FlexibleOutputBuffer & output_
Definition: ssl_io_completion.h:340
int bio_read_ex(size_t *out_readbytes)
Definition: ssl_io_completion.h:265
Action action_
Definition: ssl_io_completion.h:344
Token token_
Definition: ssl_io_completion.h:343
Operation::Result do_write()
Definition: ssl_io_completion.h:293
SslIoCompletionToken(TlsLayer &tls_layer, const BufferSequence &buffer, UniToken &&token, Action action=Action())
Definition: ssl_io_completion.h:137
std::decay_t< Token > Token_result
Definition: ssl_io_completion.h:131
std::conditional_t< std::is_same< Token, Token_result >::value, Token_result &, Token_result > Token_handler
Definition: ssl_io_completion.h:134
Operation::Result handle_write(std::error_code ec, size_t size)
Definition: ssl_io_completion.h:174
SslIoCompletionToken(SslIoCompletionToken &&other)
Definition: ssl_io_completion.h:146
SslIoCompletionToken(const SslIoCompletionToken &other)
Definition: ssl_io_completion.h:155
Operation::Result do_it()
Definition: ssl_io_completion.h:188
TlsLayer & tls_layer_
Definition: ssl_io_completion.h:339
const BufferSequence buffer_
Definition: ssl_io_completion.h:342
LowerLayerWriteCompletionToken< HandlerToken > get_write_handler(HandlerToken &&token)
Definition: ssl_io_completion.h:248
size_t number_bytes_transfered_
Definition: ssl_io_completion.h:338
Operation::Result do_read()
Definition: ssl_io_completion.h:308
void debug_print(Parameters &&...parameters) const
Definition: ssl_io_completion.h:323
static const Type * cast_and_increment(const void *ptr, int value)
Definition: ssl_io_completion.h:329
void do_token(const std::error_code &ec, const size_t no_of_bytes)
Definition: ssl_io_completion.h:261
Definition: ssl_io_completion.h:85
Handler_result handle_write_result(Handler *handler)
Definition: ssl_io_completion.h:102
auto send(Layer *layer, FlexibleOutputBuffer &output, Handler &&)
Definition: ssl_io_completion.h:97
Handler_result handle_read_result(Handler *handler)
Definition: ssl_io_completion.h:113
Handler_arguments write_result_
Definition: ssl_io_completion.h:123
Handler_arguments read_result_
Definition: ssl_io_completion.h:124
auto recv(Layer *layer, FlexibleInputBuffer &input, Handler &&)
Definition: ssl_io_completion.h:92
Definition: expected.h:286
std::error_code make_error_code(DynamicLoaderErrc ec)
make error_code from a DynamicLoaderErrc.
Definition: dynamic_loader.cc:79
size_t size(const char *const c)
Definition: base64.h:46
stdx::expected< void, std::error_code > close(file_handle_type native_handle)
close file handle.
Definition: file.h:239
const mutable_buffer * tls_buffer_sequence_begin(const mutable_buffer &b) noexcept
Definition: ssl_io_completion.h:41
const mutable_buffer * tls_buffer_sequence_end(const mutable_buffer &b) noexcept
Definition: ssl_io_completion.h:46
Definition: buffer.h:45
mutable_buffer buffer(void *p, size_t n) noexcept
Definition: buffer.h:418
size_t buffer_size(const ConstBufferSequence &buffers) noexcept
Definition: buffer.h:313
Type
Definition: resource_group_basic_types.h:33
Definition: gcs_xcom_synode.h:64
Definition: tls_keylog_dumper.h:32
static ulint page_offset(const void *ptr)
Gets the offset within a page.
struct result result
Definition: result.h:34
message Action
Definition: replication_group_member_actions.proto:30
repeated Action action
Definition: replication_group_member_actions.proto:43
Definition: ssl_io_completion.h:87
Definition: result.h:30
HARNESS_TLS_EXPORT std::error_code make_tls_error()
make a std::error_code from ERR_get_error().
Definition: tls_error.cc:100