// // Copyright (c) 2019-2025 Ruben Perez Hidalgo (rubenperez038 at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // #ifndef BOOST_MYSQL_IMPL_INTERNAL_SANSIO_CONNECTION_STATE_DATA_HPP #define BOOST_MYSQL_IMPL_INTERNAL_SANSIO_CONNECTION_STATE_DATA_HPP #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace boost { namespace mysql { namespace detail { enum class connection_status { // Never connected or closed not_connected, // Connected and ready for a command ready, // In the middle of a multi-function operation engaged_in_multi_function, }; struct connection_state_data { // Are we connected? In the middle of a multi-function operation? connection_status status{connection_status::not_connected}; // Are we currently executing an operation? // Prevent the user from running concurrent operations bool op_in_progress{false}; // Are we talking to MySQL or MariaDB? db_flavor flavor{db_flavor::mysql}; // What are the connection's capabilities? capabilities current_capabilities{}; // The current connection ID. Supplied by handshake, can be used in KILL statements std::uint32_t connection_id{}; // Used by async ops without output diagnostics params, to avoid allocations diagnostics shared_diag; // Temporary field storage, re-used by several ops std::vector shared_fields; // Temporary pipeline stage storage, re-used by several ops std::array shared_pipeline_stages; // Do we want to retain metadata strings or not? Used to save allocations metadata_mode meta_mode{metadata_mode::minimal}; // Is TLS supported for the current connection? bool tls_supported; // Is TLS enabled for the current connection? bool tls_active{false}; // Do backslashes represent escape sequences? By default they do, but they can // be disabled using a variable. OK packets include a flag with this info. bool backslash_escapes{true}; // The current character set, or a default-constructed character set (will all nullptrs) if unknown character_set current_charset{}; // The write buffer std::vector write_buffer; // Reader message_reader reader; std::size_t max_buffer_size() const { return reader.max_buffer_size(); } connection_state_data( std::size_t read_buffer_size, std::size_t max_buff_size = static_cast(-1), bool transport_supports_ssl = false ) : tls_supported(transport_supports_ssl), reader(read_buffer_size, max_buff_size) { } void reset() { status = connection_status::not_connected; flavor = db_flavor::mysql; current_capabilities = capabilities{}; connection_id = 0u; // Metadata mode does not get reset on handshake reader.reset(); // Writer does not need reset, since every write clears previous state tls_active = false; backslash_escapes = true; current_charset = character_set{}; } // Reads an OK packet from the reader. This operation is repeated in several places. error_code deserialize_ok(diagnostics& diag) { return deserialize_ok_response(reader.message(), flavor, diag, backslash_escapes); } // Helpers for sans-io algorithms next_action read(std::uint8_t& seqnum, bool keep_parsing_state = false) { // buffer is attached by top_level_algo reader.prepare_read(seqnum, keep_parsing_state); return next_action::read({}); } template next_action write(const Serializable& msg, std::uint8_t& seqnum) { // use_ssl is attached by top_level_algo write_buffer.clear(); auto res = serialize_top_level(msg, write_buffer, seqnum, max_buffer_size()); if (res.err) return res.err; seqnum = res.seqnum; return next_action::write({write_buffer, false}); } // Helpers to implement connection status in algorithms error_code check_status_ready() const { switch (status) { case connection_status::not_connected: return client_errc::not_connected; case connection_status::engaged_in_multi_function: return client_errc::engaged_in_multi_function; default: BOOST_ASSERT(status == connection_status::ready); return error_code(); } } error_code check_status_multi_function() const { switch (status) { case connection_status::not_connected: return client_errc::not_connected; case connection_status::ready: return client_errc::not_engaged_in_multi_function; default: BOOST_ASSERT(status == connection_status::engaged_in_multi_function); return error_code(); } } }; } // namespace detail } // namespace mysql } // namespace boost #endif