#pragma once #include #include #include #include "Address.hpp" #include "message_protocol/MessageEndpoint.hpp" #include "message_protocol/MessageConnection.hpp" #include "message_protocol/MessageError.hpp" #include namespace tw::net { /** * Status of a server connection attempt or established connection. */ enum class ConnectionStatus { Idle, Connecting, Connected, Failed }; /** * Encapsulates a connection to a game server. * * Owns the endpoint and connection, managing the state of the connection * attempt and providing non-blocking access to send/receive. */ class ServerConnection { using Clock = std::chrono::steady_clock; std::unique_ptr m_endpoint; msg::MessageConnection* m_server = nullptr; Address m_address; ConnectionStatus m_status = ConnectionStatus::Idle; std::string m_error; Clock::time_point m_started_at; static constexpr std::chrono::seconds CONNECT_TIMEOUT{5}; public: /** * Constructs a connection object for the given address, without starting I/O. */ explicit ServerConnection(Address address); /** * Starts the connection process by creating an endpoint and connecting to * the server. Returns an error if the endpoint cannot be created. */ tl::expected start(); /** * Updates the connection state: pumps the endpoint, and checks for timeout * or successful connection. Must be called regularly. */ void update(); ConnectionStatus status() const; const std::string& error() const; const Address& address() const; msg::MessageEndpoint* endpoint() const; msg::MessageConnection* server() const; }; }