message_parser.hpp 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  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_MESSAGE_PARSER_HPP
  8. #define BHO_MYSQL_IMPL_INTERNAL_CHANNEL_MESSAGE_PARSER_HPP
  9. #include <asio2/bho/mysql/detail/config.hpp>
  10. #include <asio2/bho/mysql/impl/internal/channel/read_buffer.hpp>
  11. #include <asio2/bho/mysql/impl/internal/protocol/constants.hpp>
  12. #include <cstddef>
  13. #include <cstdint>
  14. namespace bho {
  15. namespace mysql {
  16. namespace detail {
  17. class message_parser
  18. {
  19. struct state_t
  20. {
  21. bool is_first_frame{true};
  22. std::uint8_t seqnum_first{};
  23. std::uint8_t seqnum_last{};
  24. bool reading_header{true};
  25. std::size_t remaining_bytes{0};
  26. bool more_frames_follow{false};
  27. bool has_seqnum_mismatch{false};
  28. };
  29. std::size_t max_frame_size_;
  30. state_t state_;
  31. public:
  32. struct result
  33. {
  34. // whether it has a message or not
  35. bool has_message{false};
  36. // if !has_message, number of bytes required to parse the current message
  37. std::size_t required_size{0};
  38. // if has_message, the actual parsed message
  39. struct message_t
  40. {
  41. std::uint8_t seqnum_first;
  42. std::uint8_t seqnum_last;
  43. std::size_t size;
  44. bool has_seqnum_mismatch; // for multi-frame messages, set to true if an error mismatch
  45. // happened
  46. } message{};
  47. void set_required_size(std::size_t size) noexcept
  48. {
  49. has_message = false;
  50. required_size = size;
  51. }
  52. void set_message(const message_t& msg) noexcept
  53. {
  54. has_message = true;
  55. message = msg;
  56. }
  57. };
  58. // max_frame_size is configurable so tests run faster
  59. message_parser(std::size_t max_frame_size = MAX_PACKET_SIZE) noexcept : max_frame_size_(max_frame_size){};
  60. // Attempts to process a message from buff and puts it into msg.
  61. // If a message is read, res.has_message == true, and res.message will be populated.
  62. // Otherwise, res.required_size will contain
  63. // the number of bytes needed to complete the message part we're parsing.
  64. // Doesn't cause buffer reallocations, and doesn't change the contents
  65. // of buff's reserved area.
  66. BHO_MYSQL_DECL
  67. void parse_message(read_buffer& buff, result& res) noexcept;
  68. };
  69. } // namespace detail
  70. } // namespace mysql
  71. } // namespace bho
  72. #ifdef BHO_MYSQL_HEADER_ONLY
  73. #include <asio2/bho/mysql/impl/internal/channel/message_parser.ipp>
  74. #endif
  75. #endif