//----------------------------------------------------------------------------- // ___ __ _ _ // / _ \__ _ _ __ ___ ___ / /(_)_ __ | | __ // / /_)/ _` | '__/ __|/ _ \/ / | | '_ \| |/ / // / ___/ (_| | | \__ \ __/ /__| | | | | < // \/ \__,_|_| |___/\___\____/_|_| |_|_|\_\ . // //----------------------------------------------------------------------------- // Author: Kurt Sassenrath // Module: Proto // // Message type definitions for the parselink protocol. // // Copyright (c) 2023 Kurt Sassenrath. // // License TBD. //----------------------------------------------------------------------------- #ifndef message_0c61530748b9f966 #define message_0c61530748b9f966 #include #include #include #include #include namespace parselink { namespace proto { // Parselink messages are encoded with MessagePack and take the form of: // | magic | size | content | // - [magic] is the string "prs", in "fixstr" format. // - [size] is the size of the message, not including this header. // - [content] is [size] bytes of MessagePack data, including the // specific type of message presented. // This may be revised in the future. The header could remain as msgpack, or // switch to something hand-crafted for saving bits. struct error_message { std::uint32_t code; // An error code std::string_view what; // A string }; // C->S: Request to (re)connect. struct connect_message { std::uint32_t user_id; // The user id. std::uint32_t version; // The version of the client. std::span session_token; // An optional existing session token. }; // S->C: Challenge to authenticate client as user_id struct challenge_message { std::uint32_t version; std::span challenge; }; // C->S: Calculated response to a challenge. struct response_message { std::span response; }; // S->C: Session token. struct session_established_message { std::span session_token; }; struct parser_data_message { std::string_view opts; std::span payload; }; using message = std::variant< error_message, connect_message, challenge_message, response_message, session_established_message, parser_data_message>; enum class error { bad_magic, // Did not get the message magic expected too_large, // The message size was too large. unknown_type, // The message type is not known }; // This class is responsible for consuming buffer data and yielding a message // instance when complete. Will throw an error if data is incorrect. // class builder { public: // For now, builders don't manage any buffers themselves. Later, that // may change. builder() = default; // Reset the builder to its initial state. This means any partially-decoded // message data will be lost. void reset() noexcept; // How many bytes are needed to perform a meaningful amount of work. std::size_t bytes_needed() noexcept; // Process data from a buffer, building messages. Returns the number of // bytes read from the buffer for the caller's bookkeeping. May yield a // message in addition. std::size_t process(std::span buffer) noexcept; private: enum class state { magic, size, payload }; state state_{state::magic}; std::size_t payload_size_{}; std::size_t payload_remaining_{}; }; } // namespace message } // namespace parselink #endif // message_0c61530748b9f966