MySQL 9.1.0
Source Code Documentation
statement_reader.h
Go to the documentation of this file.
1/*
2 Copyright (c) 2018, 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 MYSQLD_MOCK_STATEMENT_READER_INCLUDED
27#define MYSQLD_MOCK_STATEMENT_READER_INCLUDED
28
29#include <chrono>
30#include <memory>
31#include <optional>
32#include <string>
33#include <utility>
34#include <variant>
35#include <vector>
36
37#include <openssl/bio.h>
38
47
48#include "authentication.h"
55
56namespace server_mock {
57
58/** @brief Vector for keeping has_value|string representation of the values
59 * of the single row (ordered by column)
60 **/
61using RowValueType = std::vector<std::optional<std::string>>;
62
70
71std::string encode_session_trackers(
72 const std::vector<session_tracker_field> &trackers);
73
74/** @brief Keeps result data for single SQL statement that returns
75 * resultset.
76 **/
78 std::vector<classic_protocol::message::server::ColumnMeta> columns;
79 std::vector<RowValueType> rows;
80
82};
83
86
88 // how many milliseconds after the client connects this Notice
89 // should be sent to the client
90 std::chrono::milliseconds send_offset_ms;
91 unsigned type;
92 bool is_local; // true = local, false = global
93 std::string payload;
94};
95
97 public:
101
102 ProtocolBase(socket_type client_sock, endpoint_type client_ep,
103 TlsServerContext &tls_ctx);
104
105 ProtocolBase(const ProtocolBase &) = delete;
107
110
111 virtual ~ProtocolBase() = default;
112
113 // throws std::system_error
114 virtual void encode_error(const ErrorResponse &resp) = 0;
115
116 // throws std::system_error
117 virtual void encode_ok(const OkResponse &resp) = 0;
118
119 // throws std::system_error
120 virtual void encode_resultset(const ResultsetResponse &response) = 0;
121
123 const net::mutable_buffer &buf);
124
126 const net::const_buffer &buf);
127
129
130 template <class CompletionToken>
131 void async_send_tls(CompletionToken &&token) {
132 net::async_completion<CompletionToken, void(std::error_code, size_t)> init{
133 token};
134
135 const auto write_res = write_ssl(net::buffer(send_buffer_));
136 if (!write_res) {
137 auto write_ec = write_res.error();
138
139 if (write_ec == TlsErrc::kWantRead || write_ec == TlsErrc::kWantWrite) {
140 client_socket_.async_wait(
143 [this, compl_handler = std::move(init.completion_handler)](
144 std::error_code ec) mutable {
145 if (ec) {
146 compl_handler(ec, {});
147 return;
148 }
149
150 async_send(std::move(compl_handler));
151 });
152 } else {
153 net::defer(client_socket_.get_executor(),
154 [compl_handler = std::move(init.completion_handler),
155 ec = write_res.error()]() { compl_handler(ec, {}); });
156 }
157 } else {
158 net::dynamic_buffer(send_buffer_).consume(write_res.value());
159
160 net::defer(client_socket_.get_executor(),
161 [compl_handler = std::move(init.completion_handler),
162 transferred = write_res.value()]() {
163 compl_handler({}, transferred);
164 });
165 }
166
167 return init.result.get();
168 }
169
170 template <class CompletionToken>
171 void async_send(CompletionToken &&token) {
172 if (is_tls()) {
173 async_send_tls(std::forward<CompletionToken>(token));
174 } else {
175 net::async_write(client_socket_, net::dynamic_buffer(send_buffer_),
176 std::forward<CompletionToken>(token));
177 }
178 }
179
180 // TlsErrc to net::stream_errc if needed.
181 static std::error_code map_tls_error_code(std::error_code ec) {
182 return (ec == TlsErrc::kZeroReturn) ? net::stream_errc::eof : ec;
183 }
184
185 template <class CompletionToken>
186 void async_receive_tls(CompletionToken &&token) {
187 net::async_completion<CompletionToken, void(std::error_code, size_t)> init{
188 token};
189
190 auto buf = net::dynamic_buffer(recv_buffer_);
191
192 auto orig_size = buf.size();
193 auto grow_size = 16 * 1024;
194
195 buf.grow(grow_size);
196 size_t transferred{};
197 auto read_res = read_ssl(buf.data(orig_size, grow_size));
198 if (read_res) {
199 transferred = read_res.value();
200 }
201
202 buf.shrink(grow_size - transferred);
203
204 if (!read_res) {
205 const auto read_ec = read_res.error();
206 if (read_ec == TlsErrc::kWantRead || read_ec == TlsErrc::kWantWrite) {
207 client_socket_.async_wait(
210 [this, compl_handler = std::move(init.completion_handler)](
211 std::error_code ec) mutable {
212 if (ec) {
213 compl_handler(ec, {});
214 return;
215 }
216
217 async_receive_tls(std::move(compl_handler));
218 });
219 } else {
220 // as we can't handle the error, forward the error to the
221 // completion handler
222
224 client_socket_.get_executor(),
225 [compl_handler = std::move(init.completion_handler),
226 ec = map_tls_error_code(read_ec)]() { compl_handler(ec, {}); });
227 }
228 } else {
229 // success, forward it to the completion handler
230 net::defer(client_socket_.get_executor(),
231 [compl_handler = std::move(init.completion_handler),
232 transferred]() { compl_handler({}, transferred); });
233 }
234
235 return init.result.get();
236 }
237
238 template <class CompletionToken>
239 void async_receive(CompletionToken &&token) {
240 is_terminated_([&](const bool killed) {
241 if (killed) {
242 net::async_completion<CompletionToken, void(std::error_code, size_t)>
243 init{token};
244
245 net::defer(client_socket_.get_executor(),
246 [compl_handler = std::move(init.completion_handler)]() {
247 compl_handler(
248 make_error_code(std::errc::operation_canceled), 0);
249 });
250 } else if (is_tls()) {
251 return async_receive_tls(std::forward<CompletionToken>(token));
252 } else {
253 return net::async_read(client_socket_,
254 net::dynamic_buffer(recv_buffer_),
255 std::forward<CompletionToken>(token));
256 }
257 });
258 }
259
260 template <class CompletionToken>
261 void async_tls_accept(CompletionToken &&token) {
262 net::async_completion<CompletionToken, void(std::error_code)> init{token};
263
264 // data may already be pending
265 auto res = tls_accept();
266 if (!res) {
267 auto ec = res.error();
268 if (ec == TlsErrc::kWantRead || ec == TlsErrc::kWantWrite) {
271
272 client_socket_.async_wait(
273 wt, [&, compl_handler = std::move(init.completion_handler)](
274 std::error_code ec) mutable {
275 if (ec) {
276 compl_handler(ec);
277 return;
278 }
279
280 // call async accept again.
281 async_tls_accept(std::move(compl_handler));
282 });
283 } else {
284 net::defer(client_socket_.get_executor().context(),
285 [ec, compl_handler = std::move(init.completion_handler)]() {
286 compl_handler(ec);
287 });
288 }
289 } else {
290 net::defer(client_socket_.get_executor().context(),
291 [compl_handler = std::move(init.completion_handler)]() {
292 compl_handler({});
293 });
294 }
295
296 return init.result.get();
297 }
298
299 const std::vector<uint8_t> &send_buffer() const { return send_buffer_; }
300
301 const net::ip::tcp::socket &client_socket() const { return client_socket_; }
302
303 void username(const std::string &username) { username_ = username; }
304
305 std::string username() const { return username_; }
306
307 void server_auth_method_name(const std::string &auth_method_name) {
308 server_auth_method_name_ = auth_method_name;
309 }
310
311 std::string server_auth_method_name() const {
312 return server_auth_method_name_;
313 }
314
315 void server_auth_method_data(const std::string &auth_method_data) {
316 server_auth_method_data_ = auth_method_data;
317 }
318
319 std::string server_auth_method_data() const {
320 return server_auth_method_data_;
321 }
322
323 void auth_method_name(const std::string &auth_method_name) {
324 auth_method_name_ = auth_method_name;
325 }
326
327 std::string auth_method_name() const { return auth_method_name_; }
328
329 void auth_method_data(const std::string &auth_method_data) {
330 auth_method_data_ = auth_method_data;
331 }
332
333 std::string auth_method_data() const { return auth_method_data_; }
334
335 static bool authenticate(const std::string &auth_method_name,
336 const std::string &auth_method_data,
337 const std::string &password,
338 const std::vector<uint8_t> &auth_response);
339
340 void init_tls();
341
342 bool is_tls() { return bool(ssl_); }
343
344 const SSL *ssl() const { return ssl_.get(); }
345
347
348 net::steady_timer &exec_timer() { return exec_timer_; }
349
350 void cancel();
351
352 /**
353 * terminate the current connection.
354 *
355 * sets is_terminated(true) and cancels the current operation.
356 *
357 * may be called from another thread.
358 */
359 void terminate();
360
362 return client_socket_.get_executor().context();
363 }
364
365 private:
366 Monitor<bool> is_terminated_{false};
367
368 protected:
371 net::steady_timer exec_timer_{io_context()};
372
373 std::string username_{};
374
375 std::string server_auth_method_name_{};
376 std::string server_auth_method_data_{};
377
378 std::string auth_method_name_{};
379 std::string auth_method_data_{};
380
382
384 public:
385 void operator()(SSL *v) { SSL_free(v); }
386 };
387
388 std::unique_ptr<SSL, SSL_Deleter> ssl_;
389
390 std::vector<uint8_t> recv_buffer_;
391 std::vector<uint8_t> send_buffer_;
392};
393
395 public:
398
399 std::optional<std::string> username;
400 std::optional<std::string> password;
401 std::optional<std::string> auth_method_name;
402 bool cert_required{false};
403 std::optional<std::string> cert_subject;
404 std::optional<std::string> cert_issuer;
405
406 std::chrono::microseconds exec_time;
407 };
408
410
413
416
417 virtual ~StatementReaderBase() = default;
418
419 /** @brief Returns the data about the next statement from the
420 * json file. If there is no more statements it returns
421 * empty statement.
422 **/
423 virtual void handle_statement(const std::string &statement,
424 ProtocolBase *protocol) = 0;
425
426 /** @brief Returns the default execution time in microseconds. If
427 * no default execution time is provided in json file, then
428 * 0 microseconds is returned.
429 **/
430 virtual std::chrono::microseconds get_default_exec_time() = 0;
431
432 virtual std::vector<AsyncNotice> get_async_notices() = 0;
433
435 bool is_greeting) = 0;
436
437 virtual void set_session_ssl_info(const SSL *ssl) = 0;
438};
439
440} // namespace server_mock
441
442#endif
static mysql_service_status_t init()
Component initialization.
Definition: audit_api_message_emit.cc:571
Monitor pattern.
Definition: monitor.h:39
TLS Context for the server side.
Definition: tls_server_context.h:51
gtid changed.
Definition: classic_protocol_session_track.h:146
Definition: executor.h:72
Definition: socket.h:1090
Definition: timer.h:57
Definition: buffer.h:135
io_context & context() const noexcept
Definition: io_context.h:1003
Definition: io_context.h:61
executor_type get_executor() noexcept
Definition: io_context.h:1081
TCP protocol.
Definition: internet.h:1155
basic_endpoint< tcp > endpoint
Definition: internet.h:1157
basic_stream_socket< tcp > socket
Definition: internet.h:1159
Definition: buffer.h:113
static constexpr wait_type wait_read
Definition: socket.h:168
static constexpr wait_type wait_write
Definition: socket.h:169
Definition: statement_reader.h:383
void operator()(SSL *v)
Definition: statement_reader.h:385
Definition: statement_reader.h:96
std::string username() const
Definition: statement_reader.h:305
virtual ~ProtocolBase()=default
ProtocolBase(ProtocolBase &&)=delete
std::string server_auth_method_name() const
Definition: statement_reader.h:311
net::steady_timer & exec_timer()
Definition: statement_reader.h:348
TlsServerContext & tls_ctx_
Definition: statement_reader.h:381
ProtocolBase(socket_type client_sock, endpoint_type client_ep, TlsServerContext &tls_ctx)
Definition: protocol_base.cc:36
stdx::expected< size_t, std::error_code > avail_ssl()
Definition: protocol_base.cc:73
const std::vector< uint8_t > & send_buffer() const
Definition: statement_reader.h:299
void async_send_tls(CompletionToken &&token)
Definition: statement_reader.h:131
socket_type client_socket_
Definition: statement_reader.h:369
const SSL * ssl() const
Definition: statement_reader.h:344
std::string server_auth_method_data() const
Definition: statement_reader.h:319
ProtocolBase & operator=(ProtocolBase &&rhs)=delete
std::string auth_method_data() const
Definition: statement_reader.h:333
void auth_method_name(const std::string &auth_method_name)
Definition: statement_reader.h:323
void server_auth_method_data(const std::string &auth_method_data)
Definition: statement_reader.h:315
void async_tls_accept(CompletionToken &&token)
Definition: statement_reader.h:261
virtual void encode_resultset(const ResultsetResponse &response)=0
endpoint_type client_ep_
Definition: statement_reader.h:370
std::vector< uint8_t > recv_buffer_
Definition: statement_reader.h:390
void server_auth_method_name(const std::string &auth_method_name)
Definition: statement_reader.h:307
const net::ip::tcp::socket & client_socket() const
Definition: statement_reader.h:301
void async_receive_tls(CompletionToken &&token)
Definition: statement_reader.h:186
void auth_method_data(const std::string &auth_method_data)
Definition: statement_reader.h:329
bool is_tls()
Definition: statement_reader.h:342
void async_receive(CompletionToken &&token)
Definition: statement_reader.h:239
typename protocol_type::endpoint endpoint_type
Definition: statement_reader.h:100
void async_send(CompletionToken &&token)
Definition: statement_reader.h:171
std::string auth_method_name() const
Definition: statement_reader.h:327
virtual void encode_error(const ErrorResponse &resp)=0
stdx::expected< size_t, std::error_code > read_ssl(const net::mutable_buffer &buf)
Definition: protocol_base.cc:59
static std::error_code map_tls_error_code(std::error_code ec)
Definition: statement_reader.h:181
void username(const std::string &username)
Definition: statement_reader.h:303
ProtocolBase & operator=(const ProtocolBase &)=delete
virtual void encode_ok(const OkResponse &resp)=0
typename protocol_type::socket socket_type
Definition: statement_reader.h:99
stdx::expected< size_t, std::error_code > write_ssl(const net::const_buffer &buf)
Definition: protocol_base.cc:48
std::vector< uint8_t > send_buffer_
Definition: statement_reader.h:391
net::io_context & io_context()
Definition: statement_reader.h:361
ProtocolBase(const ProtocolBase &)=delete
std::unique_ptr< SSL, SSL_Deleter > ssl_
Definition: statement_reader.h:388
Definition: statement_reader.h:394
StatementReaderBase & operator=(StatementReaderBase &&)=default
virtual std::vector< AsyncNotice > get_async_notices()=0
virtual stdx::expected< handshake_data, ErrorResponse > handshake(bool is_greeting)=0
StatementReaderBase(StatementReaderBase &&)=default
virtual ~StatementReaderBase()=default
virtual void set_session_ssl_info(const SSL *ssl)=0
virtual void handle_statement(const std::string &statement, ProtocolBase *protocol)=0
Returns the data about the next statement from the json file.
StatementReaderBase & operator=(const StatementReaderBase &)=default
StatementReaderBase(const StatementReaderBase &)=default
virtual std::chrono::microseconds get_default_exec_time()=0
Returns the default execution time in microseconds.
static char * password
Definition: mysql_secure_installation.cc:58
Definition: buf0block_hint.cc:30
constexpr value_type ssl
Definition: classic_protocol_constants.h:49
borrowable::message::server::Error< false > Error
Definition: classic_protocol_message.h:1411
borrowable::message::server::Greeting< false > Greeting
Definition: classic_protocol_message.h:1413
borrowable::message::server::Eof< false > Eof
Definition: classic_protocol_message.h:1412
borrowable::message::server::Ok< false > Ok
Definition: classic_protocol_message.h:1410
borrowable::session_track::TransactionCharacteristics< false > TransactionCharacteristics
Definition: classic_protocol_session_track.h:297
borrowable::session_track::TransactionState TransactionState
Definition: classic_protocol_session_track.h:298
borrowable::session_track::SystemVariable< false > SystemVariable
Definition: classic_protocol_session_track.h:299
borrowable::session_track::State State
Definition: classic_protocol_session_track.h:301
borrowable::session_track::Schema< false > Schema
Definition: classic_protocol_session_track.h:300
void async_read(AsyncReadStream &stream, DynamicBuffer &&b, CompletionCondition completion_condition, CompletionToken &&token)
Definition: buffer.h:933
dynamic_vector_buffer< T, Allocator > dynamic_buffer(std::vector< T, Allocator > &vec) noexcept
Definition: buffer.h:661
auto defer(CompletionToken &&token)
Definition: executor.h:779
mutable_buffer buffer(void *p, size_t n) noexcept
Definition: buffer.h:418
void async_write(AsyncWriteStream &stream, const ConstBufferSequence &buffers, CompletionCondition cond, CompletionToken &&token)
Definition: buffer.h:1066
Definition: mock_server_component.h:36
std::variant< classic_protocol::session_track::TransactionCharacteristics, classic_protocol::session_track::TransactionState, classic_protocol::session_track::SystemVariable, classic_protocol::session_track::Schema, classic_protocol::session_track::State, classic_protocol::session_track::Gtid > session_tracker_field
Definition: statement_reader.h:69
classic_protocol::message::server::Ok OkResponse
Definition: statement_reader.h:84
std::vector< std::optional< std::string > > RowValueType
Vector for keeping has_value|string representation of the values of the single row (ordered by column...
Definition: statement_reader.h:61
classic_protocol::message::server::Error ErrorResponse
Definition: statement_reader.h:85
std::string encode_session_trackers(const std::vector< session_tracker_field > &trackers)
Definition: duktape_statement_reader.cc:90
Definition: statement_reader.h:87
std::chrono::milliseconds send_offset_ms
Definition: statement_reader.h:90
bool is_local
Definition: statement_reader.h:92
std::string payload
Definition: statement_reader.h:93
unsigned type
Definition: statement_reader.h:91
Keeps result data for single SQL statement that returns resultset.
Definition: statement_reader.h:77
std::vector< RowValueType > rows
Definition: statement_reader.h:79
classic_protocol::message::server::Eof end_of_rows
Definition: statement_reader.h:81
std::vector< classic_protocol::message::server::ColumnMeta > columns
Definition: statement_reader.h:78
Definition: statement_reader.h:396
std::optional< std::string > username
Definition: statement_reader.h:399
std::chrono::microseconds exec_time
Definition: statement_reader.h:406
classic_protocol::message::server::Greeting greeting
Definition: statement_reader.h:397
std::optional< std::string > cert_issuer
Definition: statement_reader.h:404
std::optional< std::string > password
Definition: statement_reader.h:400
std::optional< std::string > cert_subject
Definition: statement_reader.h:403
std::optional< std::string > auth_method_name
Definition: statement_reader.h:401
Definition: mysqlslap.cc:219