From 85b321409dd54f4f55e07c6e7d1ed311520c510b Mon Sep 17 00:00:00 2001 From: WolverinDEV Date: Sat, 19 Oct 2019 13:55:45 +0200 Subject: [PATCH] Fixed some implicit type convs and improved packet api. --- src/Variable.h | 6 ++-- src/misc/strobf.h | 10 +++++-- src/protocol/CompressionHandler.cpp | 28 +++++++++---------- src/protocol/Packet.cpp | 30 ++++++++++++-------- src/protocol/Packet.h | 43 +++++++++++++++++++---------- 5 files changed, 71 insertions(+), 46 deletions(-) diff --git a/src/Variable.h b/src/Variable.h index 8146640..75acf72 100644 --- a/src/Variable.h +++ b/src/Variable.h @@ -126,14 +126,14 @@ DEFINE_VARIABLE_TRANSFORM(std::string, VARTYPE_TEXT, in, in.value()); DEFINE_VARIABLE_TRANSFORM(char*, VARTYPE_TEXT, std::string((const char*) in), (char*) in.value().c_str()); DEFINE_VARIABLE_TRANSFORM(const char*, VARTYPE_TEXT, std::string((const char*) in), in.value().c_str()); -DEFINE_VARIABLE_TRANSFORM(int8_t, VARTYPE_INT, std::to_string(in), std::stoi(in.value())); +DEFINE_VARIABLE_TRANSFORM(int8_t, VARTYPE_INT, std::to_string(in), (int8_t) std::stoi(in.value())); DEFINE_VARIABLE_TRANSFORM(uint8_t, VARTYPE_INT, std::to_string(in), (uint8_t) std::stoul(in.value())); -DEFINE_VARIABLE_TRANSFORM(int16_t, VARTYPE_INT, std::to_string(in), std::stoi(in.value())); +DEFINE_VARIABLE_TRANSFORM(int16_t, VARTYPE_INT, std::to_string(in), (int16_t) std::stoi(in.value())); DEFINE_VARIABLE_TRANSFORM(uint16_t, VARTYPE_INT, std::to_string(in), (uint16_t) std::stoul(in.value())); DEFINE_VARIABLE_TRANSFORM(int32_t, VARTYPE_INT, std::to_string(in), std::stoi(in.value())); -DEFINE_VARIABLE_TRANSFORM(uint32_t, VARTYPE_INT, std::to_string(in), std::stoul(in.value())); +DEFINE_VARIABLE_TRANSFORM(uint32_t, VARTYPE_INT, std::to_string(in), (uint32_t) std::stoul(in.value())); DEFINE_VARIABLE_TRANSFORM(int64_t, VARTYPE_LONG, std::to_string(in), std::stoll(in.value())); DEFINE_VARIABLE_TRANSFORM(uint64_t, VARTYPE_LONG, std::to_string(in), std::stoull(in.value())); diff --git a/src/misc/strobf.h b/src/misc/strobf.h index f2e2d90..d7ab1ba 100644 --- a/src/misc/strobf.h +++ b/src/misc/strobf.h @@ -39,7 +39,9 @@ namespace str_obf { return !str[h] ? 5381 : (string_hash(str, h + 1) * 33) ^ str[h]; } -#pragma warning(disable: 4146) // unary minus operator applied to unsigned type, result still unsigned +#ifdef WIN32 + #pragma warning(disable: 4146) // unary minus operator applied to unsigned type, result still unsigned +#endif constexpr std::uint32_t rng32_next(std::uint64_t& state, const std::uint32_t& inc) noexcept { std::uint64_t oldstate = state; // Advance internal state @@ -49,7 +51,9 @@ namespace str_obf { std::uint32_t rot = oldstate >> 59u; return (xorshifted >> rot) | (xorshifted << ((-rot) & 31)); } -#pragma warning(default: 4146) // unary minus operator applied to unsigned type, result still unsigned +#ifdef WIN32 + #pragma warning(default: 4146) // unary minus operator applied to unsigned type, result still unsigned +#endif /* we use a buffer dividable by 8 so the compiler could do crazy shit, when loading (moving) the characters */ constexpr size_t recommand_message_buffer(size_t message_size) noexcept { @@ -198,4 +202,4 @@ constexpr auto variable_name = ::str_obf::encode(string, str_obf::generate_key<_ (([]{ \ static strobf_define(_, message); \ return strobf_val(_); \ -})()) \ No newline at end of file +})()) diff --git a/src/protocol/CompressionHandler.cpp b/src/protocol/CompressionHandler.cpp index 6ffa39c..e78ec53 100644 --- a/src/protocol/CompressionHandler.cpp +++ b/src/protocol/CompressionHandler.cpp @@ -12,30 +12,30 @@ using namespace std; bool CompressionHandler::compress(protocol::BasicPacket* packet, std::string &error) { //// "Always allocate size + 400 bytes for the destination buffer when compressing." <= http://www.quicklz.com/manual.html - auto length = packet->data().length(); - auto header_length = packet->header().length() + packet->mac().length(); - size_t expected_bytes = min(length * 2, length + 400); - auto buffer = buffer::allocate_buffer(expected_bytes + header_length); + auto packet_payload = packet->data(); + auto header_length = packet->length() - packet_payload.length(); + + size_t max_compressed_payload_size = max(min(packet_payload.length() * 2, packet_payload.length() + 400), 24UL); /* at least 12 bytes (QLZ header) */ + auto target_buffer = buffer::allocate_buffer(max_compressed_payload_size + header_length); qlz_state_compress state_compress{}; - size_t actualLength = qlz_compress(packet->data().data_ptr(), (char*) &buffer[header_length], packet->data().length(), &state_compress); - if(actualLength > buffer.length()) { - logCritical(0, "Buffer overflow! Compressed data is longer than expected. (Expected: {}, Written: {}, Source length: {}, Allocated block size: {})", - expected_bytes, - actualLength, - packet->data().length(), - buffer.capacity() + size_t actual_length = qlz_compress(packet_payload.data_ptr(), (char*) &target_buffer[header_length], packet_payload.length(), &state_compress); + if(actual_length > max_compressed_payload_size) { + logCritical(0, "Buffer overflow! Compressed data is longer than expected. (Expected: {}, Written: {}, Allocated block size: {})", + max_compressed_payload_size, + actual_length, + target_buffer.capacity() ); error = "overflow"; return false; } - if(actualLength <= 0){ + if(actual_length <= 0){ error = "Cloud not compress packet"; return false; } - memcpy(buffer.data_ptr(), packet->buffer().data_ptr(), header_length); - packet->buffer(buffer.range(0, actualLength + header_length)); + memcpy(target_buffer.data_ptr(), packet->buffer().data_ptr(), header_length); + packet->buffer(target_buffer.range(0, actual_length + header_length)); return true; } diff --git a/src/protocol/Packet.cpp b/src/protocol/Packet.cpp index 0cfbf52..b2b0714 100644 --- a/src/protocol/Packet.cpp +++ b/src/protocol/Packet.cpp @@ -30,7 +30,7 @@ namespace ts { std::map PacketTypeInfo::types; PacketTypeInfo PacketTypeInfo::fromid(int id) { - for(auto elm : types) + for(const auto& elm : types) if(elm.first == id) return elm.second; return PacketTypeInfo::Undefined; } @@ -69,11 +69,6 @@ namespace ts { memset(this->_buffer.data_ptr(), 0, this->_buffer.length()); } - BasicPacket::BasicPacket(size_t header_length, const pipes::buffer &buffer) { - this->_header_length = (uint8_t) header_length; - this->_buffer = buffer; - } - BasicPacket::~BasicPacket() {} void BasicPacket::append_data(const std::vector &data) { @@ -123,16 +118,22 @@ namespace ts { * @param buffer -> [mac][Header [uint16 BE packetId | [uint8](4bit flags | 4bit type)]][Data] * @return */ + std::unique_ptr ServerPacket::from_buffer(const pipes::buffer_view &buffer) { + auto result = make_unique(); - ServerPacket::ServerPacket(const pipes::buffer_view& buffer) : BasicPacket(SERVER_HEADER_SIZE, buffer.own_buffer()) { } + result->_buffer = buffer.own_buffer(); + result->_header_length = SERVER_HEADER_SIZE; + + return result; + } ServerPacket::ServerPacket(uint8_t flagMask, const pipes::buffer_view& data) : BasicPacket(SERVER_HEADER_SIZE, data.length()) { this->header()[2] = flagMask; memcpy(this->data().data_ptr(), data.data_ptr(), data.length()); } - ServerPacket::ServerPacket(PacketTypeInfo type, const pipes::buffer_view& data) : BasicPacket(SERVER_HEADER_SIZE, data.length()) { - this->header()[2] |= type.type(); + ServerPacket::ServerPacket(const PacketTypeInfo& type, const pipes::buffer_view& data) : BasicPacket(SERVER_HEADER_SIZE, data.length()) { + this->header()[2] |= (uint8_t) type.type(); memcpy(this->data().data_ptr(), data.data_ptr(), data.length()); } @@ -160,7 +161,14 @@ namespace ts { } - ClientPacket::ClientPacket(const pipes::buffer_view& buffer) : BasicPacket(CLIENT_HEADER_SIZE, buffer.own_buffer()) { } + std::unique_ptr ClientPacket::from_buffer(const pipes::buffer_view &buffer) { + auto result = make_unique(); + + result->_buffer = buffer.own_buffer(); + result->_header_length = CLIENT_HEADER_SIZE; + + return result; + } ClientPacket::ClientPacket(const PacketTypeInfo &type, const pipes::buffer_view& data) : BasicPacket(CLIENT_HEADER_SIZE, data.length()) { this->header()[4] = type.type() & 0xF; @@ -188,7 +196,7 @@ namespace ts { void ClientPacket::type(const ts::protocol::PacketTypeInfo &type) { auto& field = this->header().data_ptr()[4]; - field &= ~0xF; + field &= (uint8_t) ~0xF; field |= type.type(); } diff --git a/src/protocol/Packet.h b/src/protocol/Packet.h index e51e0cf..3c388be 100644 --- a/src/protocol/Packet.h +++ b/src/protocol/Packet.h @@ -109,7 +109,7 @@ namespace ts { }; namespace PacketFlag { - enum PacketFlag { + enum PacketFlag : uint8_t { None = 0x00, Fragmented = 0x10, //If packet type voice then its toggle the CELT Mono NewProtocol = 0x20, @@ -128,7 +128,6 @@ namespace ts { 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; @@ -141,7 +140,7 @@ namespace ts { /* packet flag info */ inline bool has_flag(PacketFlag::PacketFlag flag) const { return this->_flags_type_byte() & flag; } inline uint8_t flag_mask() const { return this->_flags_type_byte(); }; - std::string flags() const; + [[nodiscard]] std::string flags() const; /* manipulate flags */ inline void set_flags(PacketFlag::PacketFlags flags) { @@ -154,7 +153,7 @@ namespace ts { if(state) this->_flags_type_byte() |= flag; else - this->_flags_type_byte() &= ~flag; + this->_flags_type_byte() &= (uint8_t) ~flag; } virtual void applyPacketId(PacketIdManager &); @@ -192,13 +191,13 @@ namespace ts { memcpy(this->_buffer.data_ptr(), _new.data_ptr(), MAC_SIZE); } - inline bool isEncrypted() const { return this->memory_state.encrypted; } + [[nodiscard]] 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; } + [[nodiscard]] 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; } + [[nodiscard]] inline bool isFragmentEntry() const { return this->memory_state.fragment_entry; } inline void setFragmentedEntry(bool flag){ this->memory_state.fragment_entry = flag; } Command asCommand(); @@ -225,8 +224,13 @@ namespace ts { } memory_state; pipes::buffer buffer() { return this->_buffer; } - void buffer(pipes::buffer buffer) { this->_buffer = std::move(buffer); } + void buffer(pipes::buffer buffer) { + assert(buffer.length() >= this->_header_length + MAC_SIZE); + this->_buffer = std::move(buffer); + } protected: + BasicPacket() = default; + virtual const uint8_t& _flags_type_byte() const = 0; virtual uint8_t& _flags_type_byte() = 0; @@ -243,12 +247,14 @@ namespace ts { * Packet from the client */ class ClientPacket : public BasicPacket { + friend std::unique_ptr std::make_unique(); 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); + [[nodiscard]] static std::unique_ptr from_buffer(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; @@ -267,6 +273,8 @@ namespace ts { void type(const PacketTypeInfo&); private: + ClientPacket() = default; + const uint8_t &_flags_type_byte() const override { return this->header().data_ptr()[4]; } @@ -282,26 +290,31 @@ namespace ts { * Packet from the server */ class ServerPacket : public BasicPacket { + friend std::unique_ptr std::make_unique(); 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); + [[nodiscard]] static std::unique_ptr from_buffer(const pipes::buffer_view& buffer); + ServerPacket(uint8_t flagMask, const pipes::buffer_view& data); - ServerPacket(PacketTypeInfo type, const pipes::buffer_view& data); + ServerPacket(const PacketTypeInfo& type, const pipes::buffer_view& data); ServerPacket(PacketTypeInfo type, size_t /* data length */); ~ServerPacket() override; + ServerPacket(const ServerPacket&) = delete; ServerPacket(ServerPacket&&) = delete; - uint16_t packetId() const override; - uint16_t generationId() const override; + [[nodiscard]] uint16_t packetId() const override; + [[nodiscard]] uint16_t generationId() const override; void generationId(uint16_t generation) { this->genId = generation; } - PacketTypeInfo type() const override; + [[nodiscard]] PacketTypeInfo type() const override; private: - const uint8_t &_flags_type_byte() const override { + ServerPacket() = default; + + [[nodiscard]] const uint8_t &_flags_type_byte() const override { return this->header().data_ptr()[2]; }