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 {
|
|
|
|
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<int, PacketTypeInfo> 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<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);
|
|
|
|
}
|
|
|
|
|
|
|
|
void reset() {
|
|
|
|
memset(&data->packetCounter[0], 0, sizeof(uint32_t) * 16);
|
|
|
|
}
|
|
|
|
private:
|
|
|
|
std::shared_ptr<PacketIdManagerData> 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<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; }
|
|
|
|
|
|
|
|
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); }
|
|
|
|
|
2019-06-28 12:14:44 -04:00
|
|
|
inline size_t data_length() const { return this->_buffer.length() - (MAC_SIZE + this->_header_length); }
|
2019-06-26 16:11:22 -04:00
|
|
|
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<pipes::buffer> &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<uint8_t, decltype(::free)*> buffer;
|
|
|
|
/*
|
|
|
|
std::string _header;
|
|
|
|
std::string _data;
|
|
|
|
std::string _mac;
|
|
|
|
*/
|
|
|
|
|
|
|
|
uint16_t genId = 0;
|
|
|
|
std::unique_ptr<threads::Future<bool>> 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;
|
|
|
|
};
|
|
|
|
}
|
|
|
|
}
|