MySQL 8.0.40
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 <vector>
35
36#include <openssl/bio.h>
37
46
47#include "authentication.h"
53
54namespace server_mock {
55
56/** @brief Vector for keeping has_value|string representation of the values
57 * of the single row (ordered by column)
58 **/
59using RowValueType = std::vector<std::optional<std::string>>;
60
61/** @brief Keeps result data for single SQL statement that returns
62 * resultset.
63 **/
65 std::vector<classic_protocol::message::server::ColumnMeta> columns;
66 std::vector<RowValueType> rows;
67};
68
71
73 // how many milliseconds after the client connects this Notice
74 // should be sent to the client
75 std::chrono::milliseconds send_offset_ms;
76 unsigned type;
77 bool is_local; // true = local, false = global
78 std::string payload;
79};
80
82 public:
86
87 ProtocolBase(socket_type client_sock, endpoint_type client_ep,
88 TlsServerContext &tls_ctx);
89
90 ProtocolBase(const ProtocolBase &) = delete;
92
95
96 virtual ~ProtocolBase() = default;
97
98 // throws std::system_error
99 virtual void encode_error(const ErrorResponse &resp) = 0;
100
101 // throws std::system_error
102 virtual void encode_ok(const uint64_t affected_rows = 0,
103 const uint64_t last_insert_id = 0,
104 const uint16_t server_status = 0,
105 const uint16_t warning_count = 0) = 0;
106
107 void encode_ok(const OkResponse &resp) {
108 encode_ok(resp.affected_rows(), resp.last_insert_id(),
109 resp.status_flags().to_ulong(), resp.warning_count());
110 }
111
112 // throws std::system_error
113 virtual void encode_resultset(const ResultsetResponse &response) = 0;
114
116 const net::mutable_buffer &buf);
117
119 const net::const_buffer &buf);
120
122
123 template <class CompletionToken>
124 void async_send_tls(CompletionToken &&token) {
125 net::async_completion<CompletionToken, void(std::error_code, size_t)> init{
126 token};
127
128 const auto write_res = write_ssl(net::buffer(send_buffer_));
129 if (!write_res) {
130 auto write_ec = write_res.error();
131
132 if (write_ec == TlsErrc::kWantRead || write_ec == TlsErrc::kWantWrite) {
133 client_socket_.async_wait(
136 [this, compl_handler = std::move(init.completion_handler)](
137 std::error_code ec) mutable {
138 if (ec) {
139 compl_handler(ec, {});
140 return;
141 }
142
143 async_send(std::move(compl_handler));
144 });
145 } else {
146 net::defer(client_socket_.get_executor(),
147 [compl_handler = std::move(init.completion_handler),
148 ec = write_res.error()]() { compl_handler(ec, {}); });
149 }
150 } else {
151 net::dynamic_buffer(send_buffer_).consume(write_res.value());
152
153 net::defer(client_socket_.get_executor(),
154 [compl_handler = std::move(init.completion_handler),
155 transferred = write_res.value()]() {
156 compl_handler({}, transferred);
157 });
158 }
159
160 return init.result.get();
161 }
162
163 template <class CompletionToken>
164 void async_send(CompletionToken &&token) {
165 if (is_tls()) {
166 async_send_tls(std::forward<CompletionToken>(token));
167 } else {
168 net::async_write(client_socket_, net::dynamic_buffer(send_buffer_),
169 std::forward<CompletionToken>(token));
170 }
171 }
172
173 // TlsErrc to net::stream_errc if needed.
174 static std::error_code map_tls_error_code(std::error_code ec) {
175 return (ec == TlsErrc::kZeroReturn) ? net::stream_errc::eof : ec;
176 }
177
178 template <class CompletionToken>
179 void async_receive_tls(CompletionToken &&token) {
180 net::async_completion<CompletionToken, void(std::error_code, size_t)> init{
181 token};
182
183 auto buf = net::dynamic_buffer(recv_buffer_);
184
185 auto orig_size = buf.size();
186 auto grow_size = 16 * 1024;
187
188 buf.grow(grow_size);
189 size_t transferred{};
190 auto read_res = read_ssl(buf.data(orig_size, grow_size));
191 if (read_res) {
192 transferred = read_res.value();
193 }
194
195 buf.shrink(grow_size - transferred);
196
197 if (!read_res) {
198 const auto read_ec = read_res.error();
199 if (read_ec == TlsErrc::kWantRead || read_ec == TlsErrc::kWantWrite) {
200 client_socket_.async_wait(
203 [this, compl_handler = std::move(init.completion_handler)](
204 std::error_code ec) mutable {
205 if (ec) {
206 compl_handler(ec, {});
207 return;
208 }
209
210 async_receive_tls(std::move(compl_handler));
211 });
212 } else {
213 // as we can't handle the error, forward the error to the
214 // completion handler
215
217 client_socket_.get_executor(),
218 [compl_handler = std::move(init.completion_handler),
219 ec = map_tls_error_code(read_ec)]() { compl_handler(ec, {}); });
220 }
221 } else {
222 // success, forward it to the completion handler
223 net::defer(client_socket_.get_executor(),
224 [compl_handler = std::move(init.completion_handler),
225 transferred]() { compl_handler({}, transferred); });
226 }
227
228 return init.result.get();
229 }
230
231 template <class CompletionToken>
232 void async_receive(CompletionToken &&token) {
233 is_terminated_([&](const bool killed) {
234 if (killed) {
235 net::async_completion<CompletionToken, void(std::error_code, size_t)>
236 init{token};
237
238 net::defer(client_socket_.get_executor(),
239 [compl_handler = std::move(init.completion_handler)]() {
240 compl_handler(
241 make_error_code(std::errc::operation_canceled), 0);
242 });
243 } else if (is_tls()) {
244 return async_receive_tls(std::forward<CompletionToken>(token));
245 } else {
246 return net::async_read(client_socket_,
247 net::dynamic_buffer(recv_buffer_),
248 std::forward<CompletionToken>(token));
249 }
250 });
251 }
252
253 template <class CompletionToken>
254 void async_tls_accept(CompletionToken &&token) {
255 net::async_completion<CompletionToken, void(std::error_code)> init{token};
256
257 // data may already be pending
258 auto res = tls_accept();
259 if (!res) {
260 auto ec = res.error();
261 if (ec == TlsErrc::kWantRead || ec == TlsErrc::kWantWrite) {
264
265 client_socket_.async_wait(
266 wt, [&, compl_handler = std::move(init.completion_handler)](
267 std::error_code ec) mutable {
268 if (ec) {
269 compl_handler(ec);
270 return;
271 }
272
273 // call async accept again.
274 async_tls_accept(std::move(compl_handler));
275 });
276 } else {
277 net::defer(client_socket_.get_executor().context(),
278 [ec, compl_handler = std::move(init.completion_handler)]() {
279 compl_handler(ec);
280 });
281 }
282 } else {
283 net::defer(client_socket_.get_executor().context(),
284 [compl_handler = std::move(init.completion_handler)]() {
285 compl_handler({});
286 });
287 }
288
289 return init.result.get();
290 }
291
292 const std::vector<uint8_t> &send_buffer() const { return send_buffer_; }
293
294 const net::ip::tcp::socket &client_socket() const { return client_socket_; }
295
296 void username(const std::string &username) { username_ = username; }
297
298 std::string username() const { return username_; }
299
300 void auth_method_name(const std::string &auth_method_name) {
301 auth_method_name_ = auth_method_name;
302 }
303
304 std::string auth_method_name() const { return auth_method_name_; }
305
306 void auth_method_data(const std::string &auth_method_data) {
307 auth_method_data_ = auth_method_data;
308 }
309
310 std::string auth_method_data() const { return auth_method_data_; }
311
312 static bool authenticate(const std::string &auth_method_name,
313 const std::string &auth_method_data,
314 const std::string &password,
315 const std::vector<uint8_t> &auth_response);
316
317 void init_tls();
318
319 bool is_tls() { return bool(ssl_); }
320
321 const SSL *ssl() const { return ssl_.get(); }
322
324
325 net::steady_timer &exec_timer() { return exec_timer_; }
326
327 void cancel();
328
329 /**
330 * terminate the current connection.
331 *
332 * sets is_terminated(true) and cancels the current operation.
333 *
334 * may be called from another thread.
335 */
336 void terminate();
337
339 return client_socket_.get_executor().context();
340 }
341
342 private:
343 Monitor<bool> is_terminated_{false};
344
345 protected:
348 net::steady_timer exec_timer_{io_context()};
349
350 std::string username_{};
351 std::string auth_method_name_{};
352 std::string auth_method_data_{};
353
355
357 public:
358 void operator()(SSL *v) { SSL_free(v); }
359 };
360
361 std::unique_ptr<SSL, SSL_Deleter> ssl_;
362
363 std::vector<uint8_t> recv_buffer_;
364 std::vector<uint8_t> send_buffer_;
365};
366
368 public:
370 std::optional<ErrorResponse> error;
371
372 std::optional<std::string> username;
373 std::optional<std::string> password;
374 bool cert_required{false};
375 std::optional<std::string> cert_subject;
376 std::optional<std::string> cert_issuer;
377 };
378
380
383
386
387 virtual ~StatementReaderBase() = default;
388
389 /** @brief Returns the data about the next statement from the
390 * json file. If there is no more statements it returns
391 * empty statement.
392 **/
393 virtual void handle_statement(const std::string &statement,
394 ProtocolBase *protocol) = 0;
395
396 /** @brief Returns the default execution time in microseconds. If
397 * no default execution time is provided in json file, then
398 * 0 microseconds is returned.
399 **/
400 virtual std::chrono::microseconds get_default_exec_time() = 0;
401
402 virtual std::vector<AsyncNotice> get_async_notices() = 0;
403
405 std::error_code>
406 server_greeting(bool with_tls) = 0;
407
409
410 virtual std::chrono::microseconds server_greeting_exec_time() = 0;
411
412 virtual void set_session_ssl_info(const SSL *ssl) = 0;
413};
414
415} // namespace server_mock
416
417#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:46
Definition: executor.h:72
Definition: socket.h:1144
Definition: timer.h:57
Definition: buffer.h:135
io_context & context() const noexcept
Definition: io_context.h:1002
Definition: io_context.h:61
executor_type get_executor() noexcept
Definition: io_context.h:1080
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:356
void operator()(SSL *v)
Definition: statement_reader.h:358
Definition: statement_reader.h:81
std::string username() const
Definition: statement_reader.h:298
virtual ~ProtocolBase()=default
ProtocolBase(ProtocolBase &&)=delete
net::steady_timer & exec_timer()
Definition: statement_reader.h:325
TlsServerContext & tls_ctx_
Definition: statement_reader.h:354
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:74
const std::vector< uint8_t > & send_buffer() const
Definition: statement_reader.h:292
void async_send_tls(CompletionToken &&token)
Definition: statement_reader.h:124
socket_type client_socket_
Definition: statement_reader.h:346
const SSL * ssl() const
Definition: statement_reader.h:321
ProtocolBase & operator=(ProtocolBase &&rhs)=delete
std::string auth_method_data() const
Definition: statement_reader.h:310
virtual void encode_ok(const uint64_t affected_rows=0, const uint64_t last_insert_id=0, const uint16_t server_status=0, const uint16_t warning_count=0)=0
void encode_ok(const OkResponse &resp)
Definition: statement_reader.h:107
void auth_method_name(const std::string &auth_method_name)
Definition: statement_reader.h:300
void async_tls_accept(CompletionToken &&token)
Definition: statement_reader.h:254
virtual void encode_resultset(const ResultsetResponse &response)=0
endpoint_type client_ep_
Definition: statement_reader.h:347
std::vector< uint8_t > recv_buffer_
Definition: statement_reader.h:363
const net::ip::tcp::socket & client_socket() const
Definition: statement_reader.h:294
void async_receive_tls(CompletionToken &&token)
Definition: statement_reader.h:179
void auth_method_data(const std::string &auth_method_data)
Definition: statement_reader.h:306
bool is_tls()
Definition: statement_reader.h:319
void async_receive(CompletionToken &&token)
Definition: statement_reader.h:232
typename protocol_type::endpoint endpoint_type
Definition: statement_reader.h:85
void async_send(CompletionToken &&token)
Definition: statement_reader.h:164
std::string auth_method_name() const
Definition: statement_reader.h:304
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:174
void username(const std::string &username)
Definition: statement_reader.h:296
ProtocolBase & operator=(const ProtocolBase &)=delete
typename protocol_type::socket socket_type
Definition: statement_reader.h:84
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:364
net::io_context & io_context()
Definition: statement_reader.h:338
ProtocolBase(const ProtocolBase &)=delete
std::unique_ptr< SSL, SSL_Deleter > ssl_
Definition: statement_reader.h:361
Definition: statement_reader.h:367
StatementReaderBase & operator=(StatementReaderBase &&)=default
virtual std::vector< AsyncNotice > get_async_notices()=0
virtual stdx::expected< handshake_data, ErrorResponse > handshake()=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.
virtual stdx::expected< classic_protocol::message::server::Greeting, std::error_code > server_greeting(bool with_tls)=0
StatementReaderBase & operator=(const StatementReaderBase &)=default
virtual std::chrono::microseconds server_greeting_exec_time()=0
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:56
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:1399
borrowable::message::server::Greeting< false > Greeting
Definition: classic_protocol_message.h:1401
borrowable::message::server::Ok< false > Ok
Definition: classic_protocol_message.h:1398
bool terminate(THD *thd)
Drop all DD tables in case there is an error while upgrading server.
Definition: upgrade.cc:686
dynamic_vector_buffer< T, Allocator > dynamic_buffer(std::vector< T, Allocator > &vec) noexcept
Definition: buffer.h:663
auto defer(CompletionToken &&token)
Definition: executor.h:804
mutable_buffer buffer(void *p, size_t n) noexcept
Definition: buffer.h:420
std::enable_if_t< is_dynamic_buffer< DynamicBuffer >::value, void > async_read(AsyncReadStream &stream, DynamicBuffer &&b, CompletionCondition completion_condition, CompletionToken &&token)
Definition: buffer.h:928
std::enable_if_t< is_dynamic_buffer< DynamicBuffer >::value, void > async_write(AsyncWriteStream &stream, DynamicBuffer &&b, CompletionCondition cond, CompletionToken &&token)
Definition: buffer.h:1074
Definition: mock_server_component.h:36
classic_protocol::message::server::Ok OkResponse
Definition: statement_reader.h:69
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:59
classic_protocol::message::server::Error ErrorResponse
Definition: statement_reader.h:70
Definition: statement_reader.h:72
std::chrono::milliseconds send_offset_ms
Definition: statement_reader.h:75
bool is_local
Definition: statement_reader.h:77
std::string payload
Definition: statement_reader.h:78
unsigned type
Definition: statement_reader.h:76
Keeps result data for single SQL statement that returns resultset.
Definition: statement_reader.h:64
std::vector< RowValueType > rows
Definition: statement_reader.h:66
std::vector< classic_protocol::message::server::ColumnMeta > columns
Definition: statement_reader.h:65
Definition: statement_reader.h:369
std::optional< std::string > username
Definition: statement_reader.h:372
std::optional< ErrorResponse > error
Definition: statement_reader.h:370
std::optional< std::string > cert_issuer
Definition: statement_reader.h:376
std::optional< std::string > password
Definition: statement_reader.h:373
std::optional< std::string > cert_subject
Definition: statement_reader.h:375
Definition: mysqlslap.cc:217