#pragma once #include #include #include #include #include #include #include #include #include #include #include #include #include "VoiceClient.h" #include "protocol/AcknowledgeManager.h" #include #include "./PacketStatistics.h" #include "./PacketDecoder.h" #include "./PacketEncoder.h" #include "./ServerCommandExecutor.h" #include "CryptSetupHandler.h" #include "PingHandler.h" //#define LOG_ACK_SYSTEM #ifdef LOG_ACK_SYSTEM #define LOG_AUTO_ACK_REQUEST #define LOG_AUTO_ACK_RESPONSE #define LOG_PKT_RESEND #endif //#define PKT_LOG_PING namespace ts { namespace server { class VoiceClient; class VoiceServer; class POWHandler; } namespace connection { class VoiceClientConnection { friend class AcknowledgeManager; friend class server::VoiceServer; friend class server::VoiceClient; friend class server::POWHandler; using PacketDecoder = server::server::udp::PacketDecoder; using PacketEncoder = server::server::udp::PacketEncoder; using PingHandler = server::server::udp::PingHandler; using CryptSetupHandler = server::server::udp::CryptSetupHandler; using ReassembledCommand = server::server::udp::ReassembledCommand; using StatisticsCategory = stats::ConnectionStatistics::category; public: explicit VoiceClientConnection(server::VoiceClient*); virtual ~VoiceClientConnection(); void send_packet(protocol::PacketType /* type */, protocol::PacketFlag::PacketFlags /* flags */, const void* /* payload */, size_t /* payload length */); void send_command(const std::string_view& /* build command command */, bool /* command low */, std::unique_ptr> /* acknowledge listener */); CryptHandler* getCryptHandler(){ return &crypt_handler; } std::shared_ptr getCurrentClient(); bool wait_empty_write_and_prepare_queue(std::chrono::time_point until = std::chrono::time_point()); void reset(); void reset_remote_address(); [[nodiscard]] std::string log_prefix(); [[nodiscard]] inline auto virtual_server_id() const { return this->virtual_server_id_; } [[nodiscard]] inline const auto& remote_address() const { return this->remote_address_; } [[nodiscard]] inline const auto& socket_id() const { return this->socket_id_; } [[nodiscard]] inline auto& packet_statistics() { return this->packet_statistics_; } [[nodiscard]] inline auto& packet_decoder() { return this->packet_decoder_; } [[nodiscard]] inline auto& packet_encoder() { return this->packet_encoder_; } [[nodiscard]] inline auto& ping_handler() { return this->ping_handler_; } [[nodiscard]] inline auto& crypt_setup_handler() { return this->crypt_setup_handler_; } protected: void handle_incoming_datagram(const pipes::buffer_view &buffer); bool verify_encryption(const pipes::buffer_view& /* full packet */); void triggerWrite(); private: ServerId virtual_server_id_; server::VoiceClient* current_client; int socket_id_{0}; sockaddr_storage remote_address_{}; server::udp::pktinfo_storage remote_address_info_{}; CryptHandler crypt_handler; /* access to CryptHandler is thread save */ server::client::PacketStatistics packet_statistics_{}; PacketDecoder packet_decoder_; PacketEncoder packet_encoder_; CryptSetupHandler crypt_setup_handler_; PingHandler ping_handler_{}; static void callback_packet_decoded(void*, const protocol::ClientPacketParser&); static void callback_command_decoded(void*, ReassembledCommand*&); static void callback_send_acknowledge(void*, uint16_t, bool); static void callback_request_write(void*); static void callback_encode_crypt_error(void*, const PacketEncoder::CryptError&, const std::string&); static void callback_resend_failed(void*, const std::shared_ptr&); static void callback_resend_statistics(void*, size_t); static void callback_outgoing_connection_statistics(void*, StatisticsCategory::value, size_t /* bytes */); static void callback_ping_send(void*, uint16_t&); static void callback_ping_send_recovery(void*); static void callback_ping_timeout(void*); /* Attention: All packet callbacks are called from the IO threads and are not thread save! */ void handlePacketCommand(ReassembledCommand* /* command */); /* The ownership will be transferred */ void handlePacketAck(const protocol::ClientPacketParser&); void handlePacketAckLow(const protocol::ClientPacketParser&); void handlePacketVoice(const protocol::ClientPacketParser&); void handlePacketVoiceWhisper(const protocol::ClientPacketParser&); void handlePacketPing(const protocol::ClientPacketParser&); void handlePacketPong(const protocol::ClientPacketParser&); }; } }