#ifndef _PROTOCOL_ #define _PROTOCOL_ #include #include #include #include #include namespace protocol { struct message_t { std::string input; token::pattern_t pattern; }; class protocol_t; using handler_t = std::function; using handler_map_t = std::map; struct session_key_t { std::string session; std::string token; }; bool operator==(const session_key_t& l, const session_key_t& r); session_key_t session_key_from(const token::list_t& tokens); session_key_t session_key_from(const message_t& message); class protocol_t { public: void set_handlers(const handler_map_t handlers); void absorb(const std::string& input); void send(const token::list_t& tokens); // TODO: Move these methods to a separate session_t class! void send_result(const session_key_t& session_key, token::list_t tokens); void proceed(const session_key_t& session_key); void junk(const session_key_t& session_key); void fail(const session_key_t& session_key); void submit_message(const session_key_t& session_key, const std::vector& header, const std::vector& body); protected: virtual void emit(const std::string& output) { }; private: handler_map_t handlers; size_t max_pattern_length; std::string version; void send_data_line(const session_key_t& session_key, const std::string& data_line); }; class ios_protocol_t : public protocol_t { public: ios_protocol_t(std::istream& in, std::ostream& out); void run(); protected: virtual void emit(const std::string& output); private: std::istream& in; std::ostream& out; }; } namespace std { template<> struct hash { std::size_t operator()(protocol::session_key_t const& session) const noexcept { auto session_hash = std::hash{}(session.session); auto token_hash = std::hash{}(session.token); return session_hash ^ (token_hash << 1); } }; } #endif