#pragma once #include #include #include #include #include "event.hpp" struct Connection; class SaslMechanism { public: virtual ~SaslMechanism() {} virtual auto mechanism_name() const -> std::string = 0; virtual auto step(std::string_view msg) -> std::optional = 0; virtual auto is_complete() const -> bool = 0; }; class SaslPlain final : public SaslMechanism { std::string authcid_; std::string authzid_; std::string password_; bool complete_; public: SaslPlain(std::string username, std::string password) : authcid_{std::move(username)} , password_{std::move(password)} , complete_{false} {} auto mechanism_name() const -> std::string override { return "PLAIN"; } auto step(std::string_view msg) -> std::optional override { if (complete_) { return {}; } else { std::string reply; reply += authzid_; reply += '\0'; reply += authcid_; reply += '\0'; reply += password_; complete_ = true; return {std::move(reply)}; } } auto is_complete() const -> bool override { return complete_; } }; struct SaslComplete : Event { bool success; }; struct SaslMessage : Event { SaslMessage(std::string message) : message{std::move(message)} {} std::string message; }; class SaslThread { Connection& connection_; std::string buffer_; const std::size_t MAX_BUFFER = 1024; public: SaslThread(Connection& connection) : connection_{connection} {} static auto start(Connection& connection) -> std::shared_ptr; auto on_authenticate(std::string_view) -> void; };