#pragma once #include #include #include #include #include #include #include "../query/Command.h" namespace ts { namespace protocol { enum PacketType : uint8_t { VOICE = 0x00, VOICE_WHISPER = 0x01, COMMAND = 0x02, COMMAND_LOW = 0x03, PING = 0x04, PONG = 0x05, ACK = 0x06, ACK_LOW = 0x07, INIT1 = 0x08, PACKET_MAX = INIT1, UNDEFINED = 0xFF }; struct PacketTypeProperties { std::string name; PacketType type; int max_length; bool requireAcknowledge; }; class PacketTypeInfo { public: static PacketTypeInfo Voice; static PacketTypeInfo VoiceWhisper; static PacketTypeInfo Command; static PacketTypeInfo CommandLow; static PacketTypeInfo Ping; static PacketTypeInfo Pong; static PacketTypeInfo Ack; static PacketTypeInfo AckLow; static PacketTypeInfo Init1; static PacketTypeInfo Undefined; static PacketTypeInfo fromid(int id); std::string name() const { return data->name; } PacketType type() const { return data->type; } bool requireAcknowledge(){ return data->requireAcknowledge; } bool operator==(const PacketTypeInfo& other) const { return other.data->type == this->data->type; } bool operator!=(const PacketTypeInfo& other){ return other.data->type != this->data->type; } int max_length() const { return data->max_length; } inline bool fragmentable() { return *this == PacketTypeInfo::Command || *this == PacketTypeInfo::CommandLow; } inline bool compressable() { return *this == PacketTypeInfo::Command || *this == PacketTypeInfo::CommandLow; } PacketTypeInfo(PacketTypeInfo&); PacketTypeInfo(const PacketTypeInfo&); PacketTypeInfo(PacketTypeInfo&& remote) : data(remote.data) {} private: static std::map types; PacketTypeInfo(std::string, PacketType, bool, int) noexcept; PacketTypeProperties* data; }; struct PacketIdManagerData { PacketIdManagerData(){ memset(this->packetCounter, 0, sizeof(uint32_t) * 16); } uint32_t packetCounter[16]{}; }; class PacketIdManager { public: PacketIdManager() : data(new PacketIdManagerData){} ~PacketIdManager() = default; PacketIdManager(const PacketIdManager& ref) : data(ref.data) {} PacketIdManager(PacketIdManager& ref) : data(ref.data) {} uint16_t nextPacketId(const PacketTypeInfo &type){ return static_cast(data->packetCounter[type.type()]++ & 0xFFFF); } uint16_t currentPacketId(const PacketTypeInfo &type){ return static_cast(data->packetCounter[type.type()] & 0xFFFF); } uint16_t generationId(const PacketTypeInfo &type){ return static_cast((data->packetCounter[type.type()] >> 16) & 0xFFFF); } void reset() { memset(&data->packetCounter[0], 0, sizeof(uint32_t) * 16); } private: std::shared_ptr data; }; namespace PacketFlag { enum PacketFlag { None = 0x00, Fragmented = 0x10, //If packet type voice then its toggle the CELT Mono NewProtocol = 0x20, Compressed = 0x40, //If packet type voice than its the header Unencrypted = 0x80 }; std::string to_string(PacketFlag flag); } #define MAC_SIZE 8 #define SERVER_HEADER_SIZE 3 #define CLIENT_HEADER_SIZE 5 class BasicPacket { public: explicit BasicPacket(size_t header_length, size_t data_length); explicit BasicPacket(size_t header_length, const pipes::buffer& buffer); virtual ~BasicPacket(); BasicPacket(const BasicPacket&) = delete; BasicPacket(BasicPacket&&) = delete; virtual uint16_t packetId() const = 0; virtual uint16_t generationId() const = 0; virtual PacketTypeInfo type() const = 0; virtual bool hasFlag(PacketFlag::PacketFlag flag) const = 0; virtual uint8_t flagMask() const = 0; virtual std::string flags() const; virtual void enableFlag(PacketFlag::PacketFlag flag){ toggle(flag, true); } virtual void toggle(PacketFlag::PacketFlag flag, bool state) = 0; virtual void applyPacketId(PacketIdManager &); virtual void applyPacketId(uint16_t, uint16_t); void setListener(std::unique_ptr> listener){ if(!this->type().requireAcknowledge()) throw std::logic_error("Packet type does not support a acknowledge listener!"); this->listener = std::move(listener); } inline std::unique_ptr>& getListener() { return this->listener; } inline pipes::buffer_view mac() const { return this->_buffer.view(0, MAC_SIZE); } inline pipes::buffer mac() { return this->_buffer.range(0, MAC_SIZE); } inline pipes::buffer_view header() const { return this->_buffer.view(MAC_SIZE, this->_header_length); } inline pipes::buffer header() { return this->_buffer.range(MAC_SIZE, this->_header_length); } inline size_t data_length() const { return this->_buffer.length() - MAC_SIZE - this->_header_length; } inline pipes::buffer_view data() const { return this->_buffer.view(MAC_SIZE + this->_header_length); } inline pipes::buffer data() { return this->_buffer.range(MAC_SIZE + this->_header_length); } void append_data(const std::vector &data); inline void data(const pipes::buffer_view &data){ this->_buffer.resize(MAC_SIZE + this->_header_length + data.length()); memcpy((char*) this->_buffer.data_ptr() + MAC_SIZE + this->_header_length, data.data_ptr(), data.length()); } inline void mac(const pipes::buffer_view &_new){ assert(_new.length() >= MAC_SIZE); memcpy(this->_buffer.data_ptr(), _new.data_ptr(), MAC_SIZE); } inline bool isEncrypted() const { return this->memory_state.encrypted; } inline void setEncrypted(bool flag){ this->memory_state.encrypted = flag; } inline bool isCompressed() const { return this->memory_state.compressed; } inline void setCompressed(bool flag){ this->memory_state.compressed = flag; } inline bool isFragmentEntry() const { return this->memory_state.fragment_entry; } inline void setFragmentedEntry(bool flag){ this->memory_state.fragment_entry = flag; } Command asCommand(); //Has the size of a byte union { #ifdef WIN32 __pragma(pack(push, 1)) #endif struct { bool encrypted: 1; bool compressed: 1; bool fragment_entry: 1; bool id_branded: 1; } #ifdef WIN32 __pragma(pack(pop)); #else __attribute__((packed)); #endif uint8_t flags = 0; } memory_state; pipes::buffer buffer() { return this->_buffer; } void buffer(pipes::buffer buffer) { this->_buffer = std::move(buffer); } protected: virtual void setPacketId(uint16_t, uint16_t) = 0; uint8_t _header_length; pipes::buffer _buffer; //std::unique_ptr buffer; /* std::string _header; std::string _data; std::string _mac; */ uint16_t genId = 0; std::unique_ptr> listener; }; /** * Packet from the client */ class ClientPacket : public BasicPacket { public: static constexpr size_t META_MAC_SIZE = 8; static constexpr size_t META_HEADER_SIZE = CLIENT_HEADER_SIZE; static constexpr size_t META_SIZE = META_MAC_SIZE + META_HEADER_SIZE; explicit ClientPacket(const pipes::buffer_view& buffer); ClientPacket(const PacketTypeInfo& type, const pipes::buffer_view& data); ClientPacket(const PacketTypeInfo& type, uint8_t flag_mask, const pipes::buffer_view& data); ~ClientPacket() override; ClientPacket(const ClientPacket&) = delete; ClientPacket(ClientPacket&&) = delete; void toggle(PacketFlag::PacketFlag flag, bool state) override; uint16_t clientId() const; void clientId(uint16_t); uint16_t packetId() const override; uint16_t generationId() const override; void generationId(uint16_t generation) { this->genId = generation; } PacketTypeInfo type() const override; void type(const PacketTypeInfo&); bool hasFlag(PacketFlag::PacketFlag flag) const override; uint8_t flagMask() const override; private: void setPacketId(uint16_t, uint16_t) override; }; /** * Packet from the server */ class ServerPacket : public BasicPacket { public: static constexpr size_t META_MAC_SIZE = 8; static constexpr size_t META_HEADER_SIZE = SERVER_HEADER_SIZE; static constexpr size_t META_SIZE = META_MAC_SIZE + META_HEADER_SIZE; explicit ServerPacket(const pipes::buffer_view& buffer); ServerPacket(uint8_t flagMask, const pipes::buffer_view& data); ServerPacket(PacketTypeInfo type, const pipes::buffer_view& data); ~ServerPacket() override; ServerPacket(const ServerPacket&) = delete; ServerPacket(ServerPacket&&) = delete; uint16_t packetId() const override; uint16_t generationId() const override; void generationId(uint16_t generation) { this->genId = generation; } PacketTypeInfo type() const override; bool hasFlag(PacketFlag::PacketFlag flag) const override; uint8_t flagMask() const override; void toggle(PacketFlag::PacketFlag flag, bool state) override; private: void setPacketId(uint16_t, uint16_t) override; }; } }