#pragma once #include #include #include #include #include #include #include #include #include #include "../SpeakingClient.h" #include "../ConnectedClient.h" #include "protocol/CryptHandler.h" #include "VoiceClientConnection.h" #include "PrecomputedPuzzles.h" #include "../../lincense/TeamSpeakLicense.h" //#define LOG_INCOMPING_PACKET_FRAGMENTS //#define LOG_AUTO_ACK_AUTORESPONSE //#define LOG_AUTO_ACK_REQUEST //#define LOG_AUTO_ACK_RESPONSE //#define LOG_PKT_RESEND #define PKT_LOG_CMD //#define PKT_LOG_VOICE //#define PKT_LOG_WHISPER //#define PKT_LOG_PING //For CLion #ifndef CLIENT_LOG_PREFIX #define CLIENT_LOG_PREFIX "Undefined CLIENT_LOG_PREFIX" #endif namespace ts { namespace connection { class VoiceClientConnection; } namespace server { class VirtualServer; class VoiceClient : public SpeakingClient { friend class VirtualServer; friend class VoiceServer; friend class POWHandler; friend class ts::connection::VoiceClientConnection; friend class ConnectedClient; friend class io::IOServerHandler; public: VoiceClient(const std::shared_ptr& server,const sockaddr_storage*); ~VoiceClient(); bool close_connection(const std::chrono::system_clock::time_point &timeout) override; bool disconnect(const std::string&) override; bool disconnect(ViewReasonId /* reason type */, const std::string& /* reason */, const std::shared_ptr& /* invoker */, bool /* notify viewer */); virtual void sendCommand(const ts::Command &command, bool low = false) { return this->sendCommand0(command.build(), low); } virtual void sendCommand(const ts::command_builder &command, bool low) { return this->sendCommand0(command.build(), low); } /* Note: Order is only guaranteed if progressDirectly is on! */ virtual void sendCommand0(const std::string_view& /* data */, bool low = false, bool progressDirectly = false, std::unique_ptr> listener = nullptr); virtual void sendAcknowledge(uint16_t packetId, bool low = false); connection::VoiceClientConnection* getConnection(){ return connection; } std::shared_ptr getVoiceServer(){ return voice_server; } std::chrono::milliseconds calculatePing(){ return ping; } private: connection::VoiceClientConnection* connection; protected: std::shared_ptr voice_server; void initialize(); virtual void tick(const std::chrono::system_clock::time_point &time) override; void handlePacketCommand(const pipes::buffer_view&); void handlePacketAck(const protocol::IncomingClientPacketParser&); void handlePacketVoice(const protocol::IncomingClientPacketParser&); void handlePacketPing(const protocol::IncomingClientPacketParser&); void handlePacketInit(const protocol::IncomingClientPacketParser&); //Handshake helpers public: void send_voice_packet(const pipes::buffer_view &packet, const VoicePacketFlags &flags) override; void send_voice_whisper_packet(const pipes::buffer_view &packet, const VoicePacketFlags &flags) override; protected: virtual command_result handleCommand(Command &command) override; //Some helper method void sendPingRequest(); //Ping/pong uint16_t lastPingId = 0; std::chrono::milliseconds ping = std::chrono::milliseconds(0); std::chrono::system_clock::time_point lastPingResponse; std::chrono::system_clock::time_point lastPingRequest; std::chrono::system_clock::time_point last_packet_handshake; private: int socket = 0; io::pktinfo_storage address_info; void finalDisconnect(); bool final_disconnected = false; //General TS3 manager commands command_result handleCommandClientInitIv(Command&); command_result handleCommandClientEk(Command&); command_result handleCommandClientInit(Command&) override; command_result handleCommandClientDisconnect(Command&); //Locked by finalDisconnect, disconnect and close connection std::shared_ptr flushing_thread; struct { bool client_init = false; bool new_protocol = false; bool protocol_encrypted = false; uint32_t client_time = 0; std::string alpha; std::string beta; std::shared_ptr chain_data; std::shared_ptr remote_key; } crypto; std::shared_ptr> event_handle_packet; void execute_handle_packet(const std::chrono::system_clock::time_point& /* scheduled */); }; } }