channel.hpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150
  1. //
  2. // Copyright (c) 2019-2023 Ruben Perez Hidalgo (rubenperez038 at gmail dot com)
  3. //
  4. // Distributed under the Boost Software License, Version 1.0. (See accompanying
  5. // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
  6. //
  7. #ifndef BHO_MYSQL_IMPL_INTERNAL_CHANNEL_CHANNEL_HPP
  8. #define BHO_MYSQL_IMPL_INTERNAL_CHANNEL_CHANNEL_HPP
  9. #include <asio2/bho/mysql/diagnostics.hpp>
  10. #include <asio2/bho/mysql/error_code.hpp>
  11. #include <asio2/bho/mysql/field_view.hpp>
  12. #include <asio2/bho/mysql/metadata_mode.hpp>
  13. #include <asio2/bho/mysql/detail/any_stream.hpp>
  14. #include <asio2/bho/mysql/impl/internal/channel/message_reader.hpp>
  15. #include <asio2/bho/mysql/impl/internal/channel/message_writer.hpp>
  16. #include <asio2/bho/mysql/impl/internal/channel/write_message.hpp>
  17. #include <asio2/bho/mysql/impl/internal/protocol/capabilities.hpp>
  18. #include <asio2/bho/mysql/impl/internal/protocol/db_flavor.hpp>
  19. #include <asio/any_io_executor.hpp>
  20. #include <asio/async_result.hpp>
  21. #include <cstddef>
  22. #include <memory>
  23. #include <utility>
  24. #include <vector>
  25. namespace bho {
  26. namespace mysql {
  27. namespace detail {
  28. // Implements the message layer of the MySQL protocol
  29. class channel
  30. {
  31. db_flavor flavor_{db_flavor::mysql};
  32. capabilities current_caps_;
  33. std::uint8_t shared_sequence_number_{};
  34. diagnostics shared_diag_; // for async ops
  35. std::vector<field_view> shared_fields_;
  36. metadata_mode meta_mode_{metadata_mode::minimal};
  37. message_reader reader_;
  38. message_writer writer_;
  39. std::unique_ptr<any_stream> stream_;
  40. public:
  41. channel(std::size_t read_buffer_size, std::unique_ptr<any_stream> stream)
  42. : reader_(read_buffer_size), stream_(std::move(stream))
  43. {
  44. }
  45. // Executor
  46. using executor_type = asio::any_io_executor;
  47. executor_type get_executor() { return stream_->get_executor(); }
  48. // Reading
  49. bool has_read_messages() const noexcept { return reader_.has_message(); }
  50. span<const std::uint8_t> next_read_message(std::uint8_t& seqnum, error_code& err) noexcept
  51. {
  52. return reader_.get_next_message(seqnum, err);
  53. }
  54. void read_some(error_code& code) { read_some_messages(*stream_, reader_, code); }
  55. template <ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken>
  56. ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  57. async_read_some(CompletionToken&& token)
  58. {
  59. return async_read_some_messages(*stream_, reader_, std::forward<CompletionToken>(token));
  60. }
  61. span<const std::uint8_t> read_one(std::uint8_t& seqnum, error_code& ec)
  62. {
  63. return read_one_message(*stream_, reader_, seqnum, ec);
  64. }
  65. template <ASIO_COMPLETION_TOKEN_FOR(void(error_code, span<const std::uint8_t>)) CompletionToken>
  66. ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code, span<const std::uint8_t>))
  67. async_read_one(std::uint8_t& seqnum, CompletionToken&& token)
  68. {
  69. return async_read_one_message(*stream_, reader_, seqnum, std::forward<CompletionToken>(token));
  70. }
  71. // Exposed for the sake of testing
  72. std::size_t read_buffer_size() const noexcept { return reader_.buffer().size(); }
  73. // Writing. serialize() gets all the required data into the write buffers so it can be written
  74. template <class Serializable>
  75. void serialize(const Serializable& message, std::uint8_t& sequence_number)
  76. {
  77. std::size_t size = message.get_size();
  78. auto buff = writer_.prepare_buffer(size, sequence_number);
  79. message.serialize(buff);
  80. }
  81. // Writes what has been set up by serialize()
  82. void write(error_code& code) { write_message(*stream_, writer_, code); }
  83. template <ASIO_COMPLETION_TOKEN_FOR(void(error_code)) CompletionToken>
  84. ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(error_code))
  85. async_write(CompletionToken&& token)
  86. {
  87. return async_write_message(*stream_, writer_, std::forward<CompletionToken>(token));
  88. }
  89. // Capabilities
  90. capabilities current_capabilities() const noexcept { return current_caps_; }
  91. void set_current_capabilities(capabilities value) noexcept { current_caps_ = value; }
  92. // DB flavor
  93. db_flavor flavor() const noexcept { return flavor_; }
  94. void set_flavor(db_flavor v) noexcept { flavor_ = v; }
  95. void reset()
  96. {
  97. flavor_ = db_flavor::mysql;
  98. current_caps_ = capabilities();
  99. reset_sequence_number();
  100. stream_->reset_ssl_active();
  101. // Metadata mode does not get reset on handshake
  102. }
  103. // Internal buffer, diagnostics and sequence_number to help async ops
  104. diagnostics& shared_diag() noexcept { return shared_diag_; }
  105. std::uint8_t& shared_sequence_number() noexcept { return shared_sequence_number_; }
  106. std::uint8_t& reset_sequence_number() noexcept { return shared_sequence_number_ = 0; }
  107. std::vector<field_view>& shared_fields() noexcept { return shared_fields_; }
  108. const std::vector<field_view>& shared_fields() const noexcept { return shared_fields_; }
  109. // Metadata mode
  110. metadata_mode meta_mode() const noexcept { return meta_mode_; }
  111. void set_meta_mode(metadata_mode v) noexcept { meta_mode_ = v; }
  112. // SSL
  113. bool ssl_active() const noexcept { return stream_->ssl_active(); }
  114. // Getting the underlying stream
  115. any_stream& stream() noexcept { return *stream_; }
  116. const any_stream& stream() const noexcept { return *stream_; }
  117. };
  118. } // namespace detail
  119. } // namespace mysql
  120. } // namespace bho
  121. #endif