MySQL 8.4.2
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 switch (result) {
216 case Operation::Result::fatal:
218 return result;
219
221 do_token(std::make_error_code(std::errc::broken_pipe), 0);
222 return result;
223
224 case Operation::Result::ok:
226 return result;
227
228 case Operation::Result::want_read: {
229 if (number_bytes_transfered_ && SslIO::is_read_operation()) {
231 return Operation::Result::ok;
232 }
233 return do_read();
234 }
235
236 case Operation::Result::want_write:
237 return do_write();
238 }
239 }
241 return Operation::Result::ok;
242 }
243
244 template <typename HandlerToken>
246 HandlerToken &&token) {
248 std::forward<HandlerToken>(token), NOP_token());
249 }
250
251 template <typename HandlerToken>
253 HandlerToken &&token) {
255 std::forward<HandlerToken>(token), NOP_token());
256 }
257
258 void do_token(const std::error_code &ec, const size_t no_of_bytes) {
259 token_(ec, no_of_bytes);
260 }
261
262 int bio_read_ex(size_t *out_readbytes) {
263 auto bio = tls_layer_.network_bio_.get();
264 *out_readbytes = 0;
265#if OPENSSL_VERSION_NUMBER >= NET_TLS_USE_BACKWARD_COMPATIBLE_OPENSSL
266 auto result = BIO_read_ex(bio, output_.data_free(), output_.size_free(),
267 out_readbytes);
268#else
269 auto result = BIO_read(bio, output_.data_free(), output_.size_free());
270 if (result > 0) *out_readbytes = result;
271#endif
272
273 return result;
274 }
275
276 int bio_write_ex(size_t *out_written) {
277 auto bio = tls_layer_.network_bio_.get();
278 *out_written = 0;
279#if OPENSSL_VERSION_NUMBER >= NET_TLS_USE_BACKWARD_COMPATIBLE_OPENSSL
280 auto result =
281 BIO_write_ex(bio, input_.data_used(), input_.size_used(), out_written);
282#else
283 auto result = BIO_write(bio, input_.data_used(), input_.size_used());
284 if (result > 0) *out_written = result;
285#endif
286
287 return result;
288 }
289
291 if (0 == net::buffer_size(output_)) {
292 size_t readbytes;
293 bio_read_ex(&readbytes);
294 output_.push(readbytes);
295 }
296
297 action_.send(&tls_layer_.lower_layer_, output_,
298 get_write_handler(std::move(*this)));
299
300 return Operation::Result::want_write;
301 }
302
304 if (0 == input_.size_used()) {
305 action_.recv(&tls_layer_.lower_layer_, input_,
306 get_read_handler(std::move(*this)));
307 return Operation::Result::want_read;
308 }
309
310 size_t written;
311 bio_write_ex(&written);
312 input_.pop(written);
313 return do_it();
314 }
315
316 template <typename Type>
317 static const Type *cast_and_increment(const void *ptr, int value) {
318 return static_cast<const Type *>(ptr) + value;
319 }
320
321 template <typename Type>
322 static Type *cast_and_increment(void *ptr, int value) {
323 return static_cast<Type *>(ptr) + value;
324 }
325
327 TlsLayer &tls_layer_;
330 const BufferSequence buffer_;
331 Token token_;
333};
334
335} // namespace tls
336} // namespace net
337
338#endif // ROUTER_SRC_OPENSSL_INCLUDE_TLS_DETAILS_SSL_OPERATION_H_
The handler class is the interface for dynamically loadable storage engines.
Definition: handler.h:4573
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:329
int bio_write_ex(size_t *out_written)
Definition: ssl_io_completion.h:276
static Type * cast_and_increment(void *ptr, int value)
Definition: ssl_io_completion.h:322
LowerLayerReadCompletionToken< HandlerToken, NOP_token > get_read_handler(HandlerToken &&token)
Definition: ssl_io_completion.h:252
Operation::Result handle_read(std::error_code ec, size_t size)
Definition: ssl_io_completion.h:164
FlexibleOutputBuffer & output_
Definition: ssl_io_completion.h:328
int bio_read_ex(size_t *out_readbytes)
Definition: ssl_io_completion.h:262
Action action_
Definition: ssl_io_completion.h:332
Token token_
Definition: ssl_io_completion.h:331
Operation::Result do_write()
Definition: ssl_io_completion.h:290
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:327
const BufferSequence buffer_
Definition: ssl_io_completion.h:330
LowerLayerWriteCompletionToken< HandlerToken > get_write_handler(HandlerToken &&token)
Definition: ssl_io_completion.h:245
size_t number_bytes_transfered_
Definition: ssl_io_completion.h:326
Operation::Result do_read()
Definition: ssl_io_completion.h:303
static const Type * cast_and_increment(const void *ptr, int value)
Definition: ssl_io_completion.h:317
void do_token(const std::error_code &ec, const size_t no_of_bytes)
Definition: ssl_io_completion.h:258
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:284
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