Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-16 09:58:23

0001 //
0002 // Copyright (c) 2019-2025 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 
0008 #ifndef BOOST_MYSQL_IMPL_INTERNAL_SANSIO_CONNECTION_STATE_DATA_HPP
0009 #define BOOST_MYSQL_IMPL_INTERNAL_SANSIO_CONNECTION_STATE_DATA_HPP
0010 
0011 #include <boost/mysql/character_set.hpp>
0012 #include <boost/mysql/client_errc.hpp>
0013 #include <boost/mysql/diagnostics.hpp>
0014 #include <boost/mysql/error_code.hpp>
0015 #include <boost/mysql/field_view.hpp>
0016 #include <boost/mysql/metadata_mode.hpp>
0017 
0018 #include <boost/mysql/detail/next_action.hpp>
0019 #include <boost/mysql/detail/pipeline.hpp>
0020 
0021 #include <boost/mysql/impl/internal/protocol/capabilities.hpp>
0022 #include <boost/mysql/impl/internal/protocol/db_flavor.hpp>
0023 #include <boost/mysql/impl/internal/protocol/serialization.hpp>
0024 #include <boost/mysql/impl/internal/sansio/message_reader.hpp>
0025 
0026 #include <boost/assert.hpp>
0027 
0028 #include <array>
0029 #include <cstddef>
0030 #include <cstdint>
0031 #include <vector>
0032 
0033 namespace boost {
0034 namespace mysql {
0035 namespace detail {
0036 
0037 enum class connection_status
0038 {
0039     // Never connected or closed
0040     not_connected,
0041 
0042     // Connected and ready for a command
0043     ready,
0044 
0045     // In the middle of a multi-function operation
0046     engaged_in_multi_function,
0047 };
0048 
0049 struct connection_state_data
0050 {
0051     // Are we connected? In the middle of a multi-function operation?
0052     connection_status status{connection_status::not_connected};
0053 
0054     // Are we currently executing an operation?
0055     // Prevent the user from running concurrent operations
0056     bool op_in_progress{false};
0057 
0058     // Are we talking to MySQL or MariaDB?
0059     db_flavor flavor{db_flavor::mysql};
0060 
0061     // What are the connection's capabilities?
0062     capabilities current_capabilities;
0063 
0064     // The current connection ID. Supplied by handshake, can be used in KILL statements
0065     std::uint32_t connection_id{};
0066 
0067     // Used by async ops without output diagnostics params, to avoid allocations
0068     diagnostics shared_diag;
0069 
0070     // Temporary field storage, re-used by several ops
0071     std::vector<field_view> shared_fields;
0072 
0073     // Temporary pipeline stage storage, re-used by several ops
0074     std::array<pipeline_request_stage, 2> shared_pipeline_stages;
0075 
0076     // Do we want to retain metadata strings or not? Used to save allocations
0077     metadata_mode meta_mode{metadata_mode::minimal};
0078 
0079     // Is TLS supported for the current connection?
0080     bool tls_supported;
0081 
0082     // Is TLS enabled for the current connection?
0083     bool tls_active{false};
0084 
0085     // Do backslashes represent escape sequences? By default they do, but they can
0086     // be disabled using a variable. OK packets include a flag with this info.
0087     bool backslash_escapes{true};
0088 
0089     // The current character set, or a default-constructed character set (will all nullptrs) if unknown
0090     character_set current_charset{};
0091 
0092     // The write buffer
0093     std::vector<std::uint8_t> write_buffer;
0094 
0095     // Reader
0096     message_reader reader;
0097 
0098     std::size_t max_buffer_size() const { return reader.max_buffer_size(); }
0099 
0100     connection_state_data(
0101         std::size_t read_buffer_size,
0102         std::size_t max_buff_size = static_cast<std::size_t>(-1),
0103         bool transport_supports_ssl = false
0104     )
0105         : tls_supported(transport_supports_ssl), reader(read_buffer_size, max_buff_size)
0106     {
0107     }
0108 
0109     void reset()
0110     {
0111         status = connection_status::not_connected;
0112         flavor = db_flavor::mysql;
0113         current_capabilities = capabilities();
0114         // Metadata mode does not get reset on handshake
0115         reader.reset();
0116         // Writer does not need reset, since every write clears previous state
0117         tls_active = false;
0118         backslash_escapes = true;
0119         current_charset = character_set{};
0120     }
0121 
0122     // Reads an OK packet from the reader. This operation is repeated in several places.
0123     error_code deserialize_ok(diagnostics& diag)
0124     {
0125         return deserialize_ok_response(reader.message(), flavor, diag, backslash_escapes);
0126     }
0127 
0128     // Helpers for sans-io algorithms
0129     next_action read(std::uint8_t& seqnum, bool keep_parsing_state = false)
0130     {
0131         // buffer is attached by top_level_algo
0132         reader.prepare_read(seqnum, keep_parsing_state);
0133         return next_action::read({});
0134     }
0135 
0136     template <class Serializable>
0137     next_action write(const Serializable& msg, std::uint8_t& seqnum)
0138     {
0139         // use_ssl is attached by top_level_algo
0140         write_buffer.clear();
0141         auto res = serialize_top_level(msg, write_buffer, seqnum, max_buffer_size());
0142         if (res.err)
0143             return res.err;
0144         seqnum = res.seqnum;
0145         return next_action::write({write_buffer, false});
0146     }
0147 
0148     // Helpers to implement connection status in algorithms
0149     error_code check_status_ready() const
0150     {
0151         switch (status)
0152         {
0153         case connection_status::not_connected: return client_errc::not_connected;
0154         case connection_status::engaged_in_multi_function: return client_errc::engaged_in_multi_function;
0155         default: BOOST_ASSERT(status == connection_status::ready); return error_code();
0156         }
0157     }
0158 
0159     error_code check_status_multi_function() const
0160     {
0161         switch (status)
0162         {
0163         case connection_status::not_connected: return client_errc::not_connected;
0164         case connection_status::ready: return client_errc::not_engaged_in_multi_function;
0165         default: BOOST_ASSERT(status == connection_status::engaged_in_multi_function); return error_code();
0166         }
0167     }
0168 };
0169 
0170 }  // namespace detail
0171 }  // namespace mysql
0172 }  // namespace boost
0173 
0174 #endif