TeaSpeakLibrary/src/protocol/Packet.h

371 lines
15 KiB
C
Raw Normal View History

2019-06-26 16:11:22 -04:00
#pragma once
#include <cstring>
#include <string>
#include <map>
#include <utility>
#include <ThreadPool/Future.h>
#include <pipes/buffer.h>
#include "../query/Command.h"
namespace ts {
namespace protocol {
2020-01-23 20:49:59 -05:00
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
};
2019-06-26 16:11:22 -04:00
struct PacketTypeProperties {
std::string name;
2020-01-23 20:49:59 -05:00
PacketType type;
int max_length;
2019-06-26 16:11:22 -04:00
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; }
2020-01-23 20:49:59 -05:00
PacketType type() const { return data->type; }
2019-06-26 16:11:22 -04:00
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;
}
2020-01-23 20:49:59 -05:00
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; }
2019-06-26 16:11:22 -04:00
PacketTypeInfo(const PacketTypeInfo&);
2020-01-23 20:49:59 -05:00
PacketTypeInfo(PacketTypeInfo&& remote) : data(remote.data) {}
2019-09-05 06:30:07 -04:00
2020-01-23 20:49:59 -05:00
~PacketTypeInfo();
2019-06-26 16:11:22 -04:00
private:
static std::map<int, PacketTypeInfo> types;
2019-09-05 06:30:07 -04:00
PacketTypeInfo(const std::string&, PacketType, bool, int) noexcept;
2020-01-23 20:49:59 -05:00
PacketTypeProperties* data;
bool owns_data = false;
2019-06-26 16:11:22 -04:00
};
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) {}
2019-09-22 10:57:01 -04:00
PacketIdManager(PacketIdManager&& ref) : data(std::move(ref.data)) {}
2019-06-26 16:11:22 -04:00
uint16_t nextPacketId(const PacketTypeInfo &type){
return static_cast<uint16_t>(data->packetCounter[type.type()]++ & 0xFFFF);
}
uint16_t currentPacketId(const PacketTypeInfo &type){
return static_cast<uint16_t>(data->packetCounter[type.type()] & 0xFFFF);
}
uint16_t generationId(const PacketTypeInfo &type){
return static_cast<uint16_t>((data->packetCounter[type.type()] >> 16) & 0xFFFF);
}
2020-01-23 20:49:59 -05:00
void reset() {
memset(&data->packetCounter[0], 0, sizeof(uint32_t) * 16);
2019-06-26 16:11:22 -04:00
}
private:
std::shared_ptr<PacketIdManagerData> data;
};
namespace PacketFlag {
enum PacketFlag : uint8_t {
2019-06-26 16:11:22 -04:00
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
};
2020-01-23 20:49:59 -05:00
typedef uint8_t PacketFlags;
2019-06-26 16:11:22 -04:00
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);
virtual ~BasicPacket();
2020-01-23 20:49:59 -05:00
BasicPacket(const BasicPacket&) = delete;
BasicPacket(BasicPacket&&) = delete;
2019-06-26 16:11:22 -04:00
virtual uint16_t packetId() const = 0;
virtual uint16_t generationId() const = 0;
virtual PacketTypeInfo type() const = 0;
2019-07-05 14:02:40 -04:00
/* packet flag info */
inline bool has_flag(PacketFlag::PacketFlag flag) const { return this->_flags_type_byte() & flag; }
2020-01-23 20:49:59 -05:00
inline uint8_t flag_mask() const { return this->_flags_type_byte(); };
[[nodiscard]] std::string flags() const;
2019-07-05 14:02:40 -04:00
/* manipulate flags */
inline void set_flags(PacketFlag::PacketFlags flags) {
2020-01-23 20:49:59 -05:00
uint8_t& byte = this->_flags_type_byte();
byte &= 0xF; /* clear all flags */
byte |= (flags & 0xF0);
2019-07-05 14:02:40 -04:00
}
2019-07-05 15:34:41 -04:00
inline void enable_flag(PacketFlag::PacketFlag flag){ this->toggle_flag(flag, true); }
2020-01-23 20:49:59 -05:00
inline void toggle_flag(PacketFlag::PacketFlag flag, bool state) {
if(state)
this->_flags_type_byte() |= flag;
else
this->_flags_type_byte() &= (uint8_t) ~flag;
2019-07-05 14:02:40 -04:00
}
2019-06-26 16:11:22 -04:00
virtual void applyPacketId(PacketIdManager &);
virtual void applyPacketId(uint16_t, uint16_t);
2020-01-23 20:49:59 -05:00
void setListener(std::unique_ptr<threads::Future<bool>> 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<threads::Future<bool>>& getListener() { return this->listener; }
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
inline size_t length() const { return this->_buffer.length(); }
inline const pipes::buffer_view mac() const { return this->_buffer.view(0, MAC_SIZE); }
inline pipes::buffer mac() { return this->_buffer.range(0, MAC_SIZE); }
inline size_t mac_length() const { return MAC_SIZE; }
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
inline const 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 header_length() const { return this->_header_length; }
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
inline size_t data_length() const { return this->_buffer.length() - (MAC_SIZE + this->_header_length); }
inline const 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); }
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
void append_data(const std::vector<pipes::buffer> &data);
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
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());
2019-06-26 16:11:22 -04:00
}
2020-01-23 20:49:59 -05:00
inline void mac(const pipes::buffer_view &_new){
2019-06-26 16:11:22 -04:00
assert(_new.length() >= MAC_SIZE);
memcpy(this->_buffer.data_ptr(), _new.data_ptr(), MAC_SIZE);
}
2020-01-23 20:49:59 -05:00
[[nodiscard]] inline bool isEncrypted() const { return this->memory_state.encrypted; }
inline void setEncrypted(bool flag){ this->memory_state.encrypted = flag; }
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
[[nodiscard]] inline bool isCompressed() const { return this->memory_state.compressed; }
inline void setCompressed(bool flag){ this->memory_state.compressed = flag; }
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
[[nodiscard]] inline bool isFragmentEntry() const { return this->memory_state.fragment_entry; }
2019-06-26 16:11:22 -04:00
inline void setFragmentedEntry(bool flag){ this->memory_state.fragment_entry = flag; }
Command asCommand();
2020-01-23 20:49:59 -05:00
//Has the size of a byte
union {
2019-06-26 16:11:22 -04:00
#ifdef WIN32
__pragma(pack(push, 1))
#endif
2020-01-23 20:49:59 -05:00
struct {
bool encrypted: 1;
bool compressed: 1;
bool fragment_entry: 1;
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
bool id_branded: 1;
}
2019-06-26 16:11:22 -04:00
#ifdef WIN32
__pragma(pack(pop));
#else
__attribute__((packed));
#endif
2020-01-23 20:49:59 -05:00
uint8_t flags = 0;
} memory_state;
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
pipes::buffer buffer() { return this->_buffer; }
void buffer(pipes::buffer buffer) {
assert(buffer.length() >= this->_header_length + MAC_SIZE);
this->_buffer = std::move(buffer);
}
2019-06-26 16:11:22 -04:00
protected:
2020-01-23 20:49:59 -05:00
BasicPacket() = default;
2020-01-23 20:49:59 -05:00
virtual const uint8_t& _flags_type_byte() const = 0;
virtual uint8_t& _flags_type_byte() = 0;
2019-07-05 14:02:40 -04:00
2020-01-23 20:49:59 -05:00
virtual void setPacketId(uint16_t, uint16_t) = 0;
uint8_t _header_length;
pipes::buffer _buffer;
2019-06-26 16:11:22 -04:00
uint16_t genId = 0;
2020-01-23 20:49:59 -05:00
std::unique_ptr<threads::Future<bool>> listener;
2019-06-26 16:11:22 -04:00
};
2020-01-23 20:49:59 -05:00
/**
* Packet from the client
*/
class ClientPacket : public BasicPacket {
friend std::unique_ptr<ClientPacket> std::make_unique<ClientPacket>();
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;
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
[[nodiscard]] static std::unique_ptr<ClientPacket> from_buffer(const pipes::buffer_view& buffer);
2020-01-23 20:49:59 -05:00
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;
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
uint16_t clientId() const;
void clientId(uint16_t);
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
uint16_t packetId() const override;
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
uint16_t generationId() const override;
void generationId(uint16_t generation) { this->genId = generation; }
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
PacketTypeInfo type() const override;
void type(const PacketTypeInfo&);
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
private:
ClientPacket() = default;
2020-01-23 20:49:59 -05:00
const uint8_t &_flags_type_byte() const override {
return this->header().data_ptr<uint8_t>()[4];
}
2019-07-05 14:02:40 -04:00
2020-01-23 20:49:59 -05:00
uint8_t &_flags_type_byte() override {
return this->header().data_ptr<uint8_t>()[4];
}
2019-07-05 14:02:40 -04:00
2020-01-23 20:49:59 -05:00
void setPacketId(uint16_t, uint16_t) override;
};
2019-06-26 16:11:22 -04:00
2020-02-15 08:01:07 -05:00
class ClientPacketParser {
2020-01-26 20:21:39 -05:00
public:
constexpr static auto kHeaderOffset = 8;
constexpr static auto kHeaderLength = CLIENT_HEADER_SIZE;
constexpr static auto kPayloadOffset = kHeaderOffset + CLIENT_HEADER_SIZE;
2020-02-15 08:01:07 -05:00
explicit ClientPacketParser(pipes::buffer_view buffer) : _buffer{std::move(buffer)} {}
ClientPacketParser(const ClientPacketParser&) = delete;
2020-01-26 20:21:39 -05:00
[[nodiscard]] inline bool valid() const {
if(this->_buffer.length() < kPayloadOffset) return false;
return this->type() <= 8;
}
[[nodiscard]] inline const void* data_ptr() const { return this->_buffer.data_ptr(); }
[[nodiscard]] inline void* mutable_data_ptr() { return (void*) this->_buffer.data_ptr(); }
[[nodiscard]] inline pipes::buffer_view buffer() const { return this->_buffer; }
2020-02-15 08:01:07 -05:00
[[nodiscard]] inline pipes::buffer_view mac() const { return this->_buffer.view(0, 8); }
[[nodiscard]] inline pipes::buffer_view payload() const { return this->_buffer.view(kPayloadOffset); }
2020-01-26 20:21:39 -05:00
[[nodiscard]] inline size_t payload_length() const { return this->_buffer.length() - kPayloadOffset; }
[[nodiscard]] uint16_t client_id() const;
[[nodiscard]] uint16_t packet_id() const;
[[nodiscard]] uint8_t type() const;
[[nodiscard]] uint8_t flags() const;
[[nodiscard]] bool is_encrypted() const;
[[nodiscard]] bool is_compressed() const;
[[nodiscard]] bool is_fragmented() const;
[[nodiscard]] uint16_t estimated_generation() const { return this->generation; }
2020-02-15 08:01:07 -05:00
void set_estimated_generation(uint16_t gen) { this->generation = gen; }
2020-01-26 20:21:39 -05:00
inline void set_decrypted() { this->decrypted = true; }
inline void set_uncompressed() { this->uncompressed = true; }
inline void set_defragmented() { this->defragmented = true; }
private:
uint16_t generation{};
bool decrypted{false}, uncompressed{false}, defragmented{false};
pipes::buffer_view _buffer{};
};
2019-06-26 16:11:22 -04:00
/**
* Packet from the server
*/
class ServerPacket : public BasicPacket {
2020-01-23 20:49:59 -05:00
friend std::unique_ptr<ServerPacket> std::make_unique<ServerPacket>();
2019-06-26 16:11:22 -04:00
public:
2020-01-23 20:49:59 -05:00
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;
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
[[nodiscard]] static std::unique_ptr<ServerPacket> from_buffer(const pipes::buffer_view& buffer);
2019-06-26 16:11:22 -04:00
ServerPacket(uint8_t flagMask, const pipes::buffer_view& data);
ServerPacket(const PacketTypeInfo& type, const pipes::buffer_view& data);
2020-01-23 20:49:59 -05:00
ServerPacket(PacketTypeInfo type, size_t /* data length */);
2019-06-26 16:11:22 -04:00
~ServerPacket() override;
2020-01-23 20:49:59 -05:00
ServerPacket(const ServerPacket&) = delete;
ServerPacket(ServerPacket&&) = delete;
2019-06-26 16:11:22 -04:00
[[nodiscard]] uint16_t packetId() const override;
2020-01-23 20:49:59 -05:00
[[nodiscard]] uint16_t generationId() const override;
void generationId(uint16_t generation) { this->genId = generation; }
[[nodiscard]] PacketTypeInfo type() const override;
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
private:
ServerPacket() = default;
2020-01-23 20:49:59 -05:00
[[nodiscard]] const uint8_t &_flags_type_byte() const override {
return this->header().data_ptr<uint8_t>()[2];
}
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
uint8_t &_flags_type_byte() override {
return this->header().data_ptr<uint8_t>()[2];
}
2019-06-26 16:11:22 -04:00
2020-01-23 20:49:59 -05:00
void setPacketId(uint16_t, uint16_t) override;
2019-06-26 16:11:22 -04:00
};
}
}