/* * server/conn_session.h — Per-client connection state machine. * * State: WaitingHello → WaitingAuth → Authenticated → Disconnecting * * Design: ConnSession is a pure state machine. It receives frames via on_frame() * (called from TcpServerConn's strand) and sends via a send_fn set after construction. * The server creates the TcpServerConn first (with callbacks referencing the session), * then calls set_tcp() to give the session its send capability. */ #ifndef VOICECAT_SERVER_CONN_SESSION_H #define VOICECAT_SERVER_CONN_SESSION_H #ifdef VOICECAT_HAS_NET #include #include #include #include #include #include #include #define ASIO_STANDALONE 1 #include #include "crypto/crypto.h" #include "proto/voicecat.pb.h" namespace voicecat { class WorkerPool; } namespace voicecat::server { class Database; class SessionRegistry; class ConnSession : public std::enable_shared_from_this { public: enum class State { WaitingHello, WaitingAuth, Authenticated, Disconnecting }; using SendFn = std::function)>; using CloseFn = std::function; ConnSession(std::shared_ptr db, std::shared_ptr registry, std::shared_ptr workers, const std::array& server_fp, bool allow_guests, uint16_t udp_media_port = 0); void set_io(SendFn send_fn, CloseFn close_fn); void set_session_id(uint64_t id) { session_id_ = id; } void begin(); void on_frame(std::vector frame); void on_disconnect(); void send_envelope(const voicecat::v1::Envelope& env); void close(); // ── M2: media key injection (called from on_tls_ready) ─────────────────── void set_media_crypto(std::unique_ptr send, std::unique_ptr recv); // ── M2: UDP endpoint (set by MediaRelay on UdpBinding) ──────────────────── void set_udp_endpoint(asio::ip::udp::endpoint ep); asio::ip::udp::endpoint udp_endpoint() const; bool has_udp_endpoint() const { return has_udp_ep_.load(); } // ── M2: media crypto access (for SFU relay) ────────────────────────────── voicecat::crypto::SodiumMediaCrypto* send_crypto(); voicecat::crypto::SodiumMediaCrypto* recv_crypto(); // ── M2: UDP token (for binding) ─────────────────────────────────────────── const std::array& udp_token() const { return udp_token_; } // ── Accessors ────────────────────────────────────────────────────────────── State state() const { return state_.load(); } uint64_t session_id() const { return session_id_; } uint32_t user_id() const { return user_id_; } private: void handle_client_hello(uint64_t req_id, const voicecat::v1::ClientHello& msg); void handle_auth_request(uint64_t req_id, const voicecat::v1::AuthRequest& msg); void handle_join_channel(uint64_t req_id, const voicecat::v1::JoinChannelRequest& msg); void handle_text_message(const voicecat::v1::TextMessage& msg); void handle_ping(const voicecat::v1::Ping& msg); void handle_udp_binding(uint64_t req_id, const voicecat::v1::UdpBinding& msg); void handle_stream_announce(uint64_t req_id, const voicecat::v1::StreamAnnounce& msg); void handle_stream_stop(const voicecat::v1::StreamStop& msg); void finish_guest_auth(const voicecat::v1::GuestAuth& guest, uint64_t req_id); void finish_password_auth(const std::string& username, const std::string& password, uint64_t req_id); void send_auth_result_ok(uint64_t req_id, const voicecat::v1::User& user, const voicecat::v1::Permissions* perms = nullptr); void send_state_snapshot(); void broadcast_user_joined(const voicecat::v1::User& user); void send_disconnect_and_close(uint32_t code, const std::string& reason); std::shared_ptr db_; std::shared_ptr registry_; std::shared_ptr workers_; std::array server_fp_; bool allow_guests_; uint16_t udp_media_port_; SendFn send_fn_; CloseFn close_fn_; std::atomic state_{State::WaitingHello}; uint64_t session_id_{0}; std::atomic user_id_{0}; std::atomic closed_{false}; // M2 UDP / media std::array udp_token_{}; mutable std::mutex udp_ep_mu_; asio::ip::udp::endpoint udp_ep_; std::atomic has_udp_ep_{false}; mutable std::mutex crypto_mu_; std::unique_ptr send_crypto_; std::unique_ptr recv_crypto_; // M2: locally-announced stream (single MIC stream per session for now) uint32_t announced_stream_id_{0}; }; } // namespace voicecat::server #endif // VOICECAT_HAS_NET #endif // VOICECAT_SERVER_CONN_SESSION_H