#pragma once #include "ConnectedClient.h" #include #include namespace ts::server { class VirtualServer; class SpeakingClient : public ConnectedClient { public: struct VoicePacketFlags { bool encrypted : 1; bool head : 1; bool fragmented : 1; /* used by MONO. IDK What this is */ bool new_protocol : 1; char _unused : 4; VoicePacketFlags() : encrypted{false}, head{false}, fragmented{false}, new_protocol{false}, _unused{0} { } }; static_assert(sizeof(VoicePacketFlags) == 1); enum HandshakeState { BEGIN, IDENTITY_PROOF, SUCCEEDED }; enum IdentityType : uint8_t { TEASPEAK_FORUM, TEAMSPEAK, NICKNAME, UNSET = 0xff }; SpeakingClient(sql::SqlManager* a, const std::shared_ptr& b); ~SpeakingClient() override; //Voice virtual void send_voice_packet(const pipes::buffer_view& /* voice packet data */, const VoicePacketFlags& /* flags */) = 0; virtual bool shouldReceiveVoice(const std::shared_ptr &sender); //Whisper bool shouldReceiveVoiceWhisper(const std::shared_ptr &sender); virtual void send_voice_whisper_packet(const pipes::buffer_view& /* teamspeak payload */, const pipes::buffer_view& /* teaspeak payload */, const VoicePacketFlags& /* flags */) = 0; inline std::chrono::milliseconds takeSpokenTime() { auto time = this->speak_time; this->speak_time = std::chrono::milliseconds(0); return time; } protected: void tick(const std::chrono::system_clock::time_point &time) override; public: void updateChannelClientProperties(bool channel_lock, bool notify) override; protected: command_result handleCommand(Command &command) override; public: bool should_handle_voice_packet(size_t /* size */); virtual void handlePacketVoiceWhisper(const pipes::buffer_view&, bool /* new */, bool /* head */); virtual void processJoin(); void processLeave(); virtual command_result handleCommandHandshakeBegin(Command&); virtual command_result handleCommandHandshakeIdentityProof(Command &); virtual command_result handleCommandClientInit(Command&); virtual command_result handleCommandRtcSessionDescribe(Command &command); virtual command_result handleCommandRtcSessionReset(Command &command); virtual command_result handleCommandRtcIceCandidate(Command &); virtual command_result handleCommandRtcBroadcast(Command &); void triggerVoiceEnd(); inline void updateSpeak(bool onlyUpdate, const std::chrono::system_clock::time_point &time); std::chrono::milliseconds speak_accuracy{1000}; std::mutex speak_mutex; std::chrono::milliseconds speak_time{0}; std::chrono::system_clock::time_point speak_begin; std::chrono::system_clock::time_point speak_last_packet; std::chrono::system_clock::time_point speak_last_no_whisper_target; std::chrono::system_clock::time_point speak_last_too_many_whisper_targets; permission::v2::PermissionFlaggedValue max_idle_time{permission::v2::empty_permission_flagged_value}; struct { HandshakeState state{HandshakeState::BEGIN}; IdentityType identityType{IdentityType::UNSET}; std::string proof_message; //TeamSpeak std::shared_ptr identityKey; //TeaSpeak std::shared_ptr identityData; } handshake; rtc::RTCClientId rtc_client_id{0}; }; }