From 96d2ca28a8f8b7b529821032b76cd1da6bac82cb Mon Sep 17 00:00:00 2001 From: WolverinDEV Date: Thu, 4 Jul 2019 18:05:50 +0200 Subject: [PATCH 1/4] Fixed build for windows --- src/EventLoop.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/EventLoop.cpp b/src/EventLoop.cpp index e409080..890ebba 100644 --- a/src/EventLoop.cpp +++ b/src/EventLoop.cpp @@ -3,9 +3,9 @@ #include #include #include -#include "src/log/LogUtils.h" -#include -#include "EventLoop.h" +#include "./log/LogUtils.h" +#include "./misc/sassert.h" +#include "./EventLoop.h" using namespace std; using namespace ts::event; @@ -65,7 +65,7 @@ void EventExecutor::shutdown() { this->_shutdown(lock); } -bool EventExecutor::schedule(const std::shared_ptr &entry) { +bool EventExecutor::schedule(const std::shared_ptr &entry) { unique_lock lock(this->lock); if(!entry || entry->_event_ptr) return true; /* already scheduled */ @@ -89,7 +89,7 @@ bool EventExecutor::schedule(const std::shared_ptr &entry) { return true; } -bool EventExecutor::cancel(const std::shared_ptr &entry) { +bool EventExecutor::cancel(const std::shared_ptr &entry) { unique_lock lock(this->lock); if(!entry || !entry->_event_ptr) return false; @@ -158,7 +158,7 @@ void EventExecutor::_reassign_thread_names(std::unique_lock &lock) { } #endif -void EventExecutor::_executor(event::EventExecutor *loop) { +void EventExecutor::_executor(ts::event::EventExecutor *loop) { while(true) { unique_lock lock(loop->lock); loop->condition.wait(lock, [&] { From 91ae593110ffa5cd85c8fe61181fbbe658c29b9a Mon Sep 17 00:00:00 2001 From: WolverinDEV Date: Thu, 4 Jul 2019 20:35:09 +0200 Subject: [PATCH 2/4] Fixed crash in server --- src/EventLoop.cpp | 9 +++++++-- src/misc/timer.h | 3 ++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/EventLoop.cpp b/src/EventLoop.cpp index 890ebba..046db2b 100644 --- a/src/EventLoop.cpp +++ b/src/EventLoop.cpp @@ -204,12 +204,17 @@ void EventExecutor::_executor(ts::event::EventExecutor *loop) { } auto event_handler = linked_entry->entry.lock(); + if(!event_handler) { + /* event handler passed away while waiting for beeing executed */ + delete linked_entry; + continue; + } + sassert(event_handler->_event_ptr == linked_entry); event_handler->_event_ptr = nullptr; lock.unlock(); - if(event_handler) - event_handler->event_execute(linked_entry->scheduled); + event_handler->event_execute(linked_entry->scheduled); delete linked_entry; } } \ No newline at end of file diff --git a/src/misc/timer.h b/src/misc/timer.h index 334f4a3..6bcf5f1 100644 --- a/src/misc/timer.h +++ b/src/misc/timer.h @@ -33,4 +33,5 @@ name ##_timings.timings.push_back({step, std::chrono::system_clock::now()}); tp = entry.ts; \ } \ return result; \ -})() \ No newline at end of file +})() +/* FIX the "backslash-newline at end of file" warning */ \ No newline at end of file From e7915780af60ee11186702a92ae9775785eda1eb Mon Sep 17 00:00:00 2001 From: WolverinDEV Date: Thu, 4 Jul 2019 20:40:15 +0200 Subject: [PATCH 3/4] fixed stuff --- src/protocol/CryptionHandler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/protocol/CryptionHandler.cpp b/src/protocol/CryptionHandler.cpp index c87b9b8..c21901b 100644 --- a/src/protocol/CryptionHandler.cpp +++ b/src/protocol/CryptionHandler.cpp @@ -1,4 +1,4 @@ -#define NO_OPEN_SSL /* because we're lazy and dont want to build this lib extra for the TeaClient */ +//#define NO_OPEN_SSL /* because we're lazy and dont want to build this lib extra for the TeaClient */ #define FIXEDINT_H_INCLUDED /* else it will be included by ge */ #include "misc/endianness.h" From 232ea83c3a76cc246a7a0492ea9412f0f9e50a21 Mon Sep 17 00:00:00 2001 From: WolverinDEV Date: Fri, 5 Jul 2019 20:02:40 +0200 Subject: [PATCH 4/4] Updated some stuff --- src/EventLoop.h | 2 +- src/misc/advanced_mutex.h | 2 +- src/misc/spin_lock.h | 12 ++-- src/misc/timer.h | 78 +++++++++++++---------- src/protocol/CompressionHandler.cpp | 2 +- src/protocol/CryptionHandler.cpp | 96 ++++++++++++----------------- src/protocol/CryptionHandler.h | 2 +- src/protocol/Packet.cpp | 45 +++----------- src/protocol/Packet.h | 68 ++++++++++++-------- src/protocol/ringbuffer.h | 9 +-- test/RingTest.cpp | 23 +++++++ 11 files changed, 175 insertions(+), 164 deletions(-) diff --git a/src/EventLoop.h b/src/EventLoop.h index 3a424da..8b5c717 100644 --- a/src/EventLoop.h +++ b/src/EventLoop.h @@ -35,7 +35,7 @@ namespace ts { if(!_instance) return; - ((void(*)(class_t*, const std::chrono::system_clock::time_point &)) this->callback)(&*_instance, point); + ((void(*)(class_t*, const std::chrono::system_clock::time_point &)) (void*) this->callback)(&*_instance, point); } }; diff --git a/src/misc/advanced_mutex.h b/src/misc/advanced_mutex.h index 0dd3948..bcd2409 100644 --- a/src/misc/advanced_mutex.h +++ b/src/misc/advanced_mutex.h @@ -190,7 +190,7 @@ namespace std { count--; } else { // normal unlocking - owner = std::thread::id(); + owner = this_id; count = 0; handle.unlock(); } diff --git a/src/misc/spin_lock.h b/src/misc/spin_lock.h index 6f0c3f1..b223abf 100644 --- a/src/misc/spin_lock.h +++ b/src/misc/spin_lock.h @@ -6,12 +6,14 @@ class spin_lock { std::atomic_flag locked = ATOMIC_FLAG_INIT; public: - void lock() { + inline void lock() { uint8_t round = 0; while (locked.test_and_set(std::memory_order_acquire)) { - //Yield when we're using this lock for a longer time, which we usually not doing - if(round++ % 8 == 0) - std::this_thread::yield(); + while(locked._M_i) { /* waiting 'till its zero so we can try an exchanged again; Atomic exchanges have a huge bug overhead to deal with! */ + //Yield when we're using this lock for a longer time, which we usually not doing + if(round++ % 8 == 0) + std::this_thread::yield(); + } } } @@ -19,7 +21,7 @@ class spin_lock { return !locked.test_and_set(std::memory_order_acquire); } - void unlock() { + inline void unlock() { locked.clear(std::memory_order_release); } }; \ No newline at end of file diff --git a/src/misc/timer.h b/src/misc/timer.h index 6bcf5f1..35a8d02 100644 --- a/src/misc/timer.h +++ b/src/misc/timer.h @@ -1,37 +1,51 @@ #pragma once -#define TIMING_START(_name) \ -struct { \ - struct entry { \ + +#ifndef TIMING_DISABLED + #define TIMING_REPORT(expression) \ + expression + + #define TIMING_START(_name) \ + struct { \ + struct entry { \ + std::string name; \ + std::chrono::system_clock::time_point ts; \ + }; \ + \ std::string name; \ - std::chrono::system_clock::time_point ts; \ - }; \ - \ - std::string name; \ - std::chrono::system_clock::time_point begin; \ - std::chrono::system_clock::time_point end; \ - std::deque timings; \ -} _name ##_timings; \ -_name ##_timings.begin = std::chrono::system_clock::now(); \ + std::chrono::system_clock::time_point begin; \ + std::chrono::system_clock::time_point end; \ + std::deque timings; \ + } _name ##_timings; \ + _name ##_timings.begin = std::chrono::system_clock::now(); \ -#define TIMING_STEP(name, step) \ -name ##_timings.timings.push_back({step, std::chrono::system_clock::now()}); + #define TIMING_STEP(name, step) \ + name ##_timings.timings.push_back({step, std::chrono::system_clock::now()}); -#define TIMING_FINISH(_name) \ -([&](){ \ - _name ##_timings.end = std::chrono::system_clock::now(); \ - std::string result; \ - result = "timings for " + _name ##_timings.name + ": "; \ - result += std::to_string(std::chrono::duration_cast(_name ##_timings.end - _name ##_timings.begin).count()) + "ms"; \ - \ - auto tp = _name ##_timings.begin; \ - for(const auto& entry : _name ##_timings.timings) { \ - result += "\n "; \ - result += "- " + entry.name + ": "; \ - result += "@" + std::to_string(std::chrono::duration_cast(entry.ts - _name ##_timings.begin).count()) + "ms"; \ - result += ": " + std::to_string(std::chrono::duration_cast(entry.ts - tp).count()) + "ms"; \ - tp = entry.ts; \ - } \ - return result; \ -})() -/* FIX the "backslash-newline at end of file" warning */ \ No newline at end of file + #define TIMING_FINISH_U(_name, unit, unit_name) \ + ([&](){ \ + _name ##_timings.end = std::chrono::system_clock::now(); \ + std::string result; \ + result = "timings for " + _name ##_timings.name + ": "; \ + result += std::to_string(std::chrono::duration_cast(_name ##_timings.end - _name ##_timings.begin).count()) + unit_name; \ + \ + auto tp = _name ##_timings.begin; \ + for(const auto& entry : _name ##_timings.timings) { \ + result += "\n "; \ + result += "- " + entry.name + ": "; \ + result += "@" + std::to_string(std::chrono::duration_cast(entry.ts - _name ##_timings.begin).count()) + unit_name; \ + result += ": " + std::to_string(std::chrono::duration_cast(entry.ts - tp).count()) + unit_name; \ + tp = entry.ts; \ + } \ + return result; \ + })() + + #define TIMING_FINISH(_name) TIMING_FINISH_U(_name, milliseconds, "ms") +#else + #define TIMING_REPORT(expression) + #define TIMING_START(_name) + #define TIMING_STEP(name, step) + #define TIMING_FINISH_U(_name, unit, unit_name) + #define TIMING_FINISH(_name) +#endif +/* FIX the "backslash-newline at end of file" warning */ diff --git a/src/protocol/CompressionHandler.cpp b/src/protocol/CompressionHandler.cpp index 24f77b0..6ffa39c 100644 --- a/src/protocol/CompressionHandler.cpp +++ b/src/protocol/CompressionHandler.cpp @@ -70,7 +70,7 @@ bool CompressionHandler::progressPacketIn(protocol::BasicPacket* packet, std::st } bool CompressionHandler::progressPacketOut(protocol::BasicPacket* packet, std::string& error) { - if(packet->hasFlag(protocol::PacketFlag::Compressed) && !packet->isCompressed()) { + if(packet->has_flag(protocol::PacketFlag::Compressed) && !packet->isCompressed()) { if(!this->compress(packet, error)) return false; packet->setCompressed(true); } diff --git a/src/protocol/CryptionHandler.cpp b/src/protocol/CryptionHandler.cpp index c21901b..d04d913 100644 --- a/src/protocol/CryptionHandler.cpp +++ b/src/protocol/CryptionHandler.cpp @@ -8,6 +8,7 @@ #include "misc/memtracker.h" #include "misc/digest.h" #include "CryptionHandler.h" +#include "../misc/sassert.h" using namespace std; using namespace ts; @@ -27,7 +28,7 @@ void CryptionHandler::reset() { this->useDefaultChipherKeyNonce = true; this->iv_struct_length = 0; memset(this->iv_struct, 0, sizeof(this->iv_struct)); - memcpy(this->current_mac, this->default_mac, sizeof(this->default_mac)); + memcpy(this->current_mac, CryptionHandler::default_mac, sizeof(CryptionHandler::default_mac)); for(auto& cache : this->cache_key_client) cache.generation = 0xFFEF; @@ -35,21 +36,21 @@ void CryptionHandler::reset() { cache.generation = 0xFFEF; } +#define SHARED_KEY_BUFFER_LENGTH (256) bool CryptionHandler::setupSharedSecret(const std::string& alpha, const std::string& beta, ecc_key *publicKey, ecc_key *ownKey, std::string &error) { - size_t bufferLength = 128; - uint8_t* buffer = new uint8_t[bufferLength]; + size_t buffer_length = SHARED_KEY_BUFFER_LENGTH; + uint8_t buffer[SHARED_KEY_BUFFER_LENGTH]; int err; - if((err = ecc_shared_secret(ownKey, publicKey, buffer, (unsigned long*) &bufferLength)) != CRYPT_OK){ - delete[] buffer; + if((err = ecc_shared_secret(ownKey, publicKey, buffer, (unsigned long*) &buffer_length)) != CRYPT_OK){ error = "Could not calculate shared secret. Message: " + string(error_to_string(err)); return false; } - auto result = this->setupSharedSecret(alpha, beta, string((const char*) buffer, bufferLength), error); - delete[] buffer; + + auto result = this->setupSharedSecret(alpha, beta, string((const char*) buffer, buffer_length), error); return result; } -bool CryptionHandler::setupSharedSecret(const std::string& alpha, const std::string& beta, std::string sharedKey, std::string &error) { +bool CryptionHandler::setupSharedSecret(const std::string& alpha, const std::string& beta, const std::string& sharedKey, std::string &error) { auto secret_hash = digest::sha1(sharedKey); char ivStruct[SHA_DIGEST_LENGTH]; @@ -108,7 +109,7 @@ void _fe_neg(fe h, const fe f) { h[9] = h9; } -inline std::string keyMul(const uint8_t* publicKey /* compressed */, const uint8_t* privateKey /* uncompressed */, bool negate){ +inline void keyMul(uint8_t(& target_buffer)[32], const uint8_t* publicKey /* compressed */, const uint8_t* privateKey /* uncompressed */, bool negate){ ge_p3 keyA{}; ge_p2 result{}; @@ -119,30 +120,27 @@ inline std::string keyMul(const uint8_t* publicKey /* compressed */, const uint8 } ge_scalarmult_vartime(&result, privateKey, &keyA); - char buffer[32]; - ge_tobytes((uint8_t*) buffer, &result); - return string(buffer, 32); + ge_tobytes(target_buffer, &result); } bool CryptionHandler::setupSharedSecretNew(const std::string &alpha, const std::string &beta, const char* privateKey /* uncompressed */, const char* publicKey /* compressed */) { - assert(alpha.length() == 10); - assert(beta.length() == 54); + if(alpha.length() != 10 || beta.length() != 54) + return false; - string shared; - string sharedIv; - shared.resize(32, '\0'); - sharedIv.resize(64, '\0'); - ed25519_key_exchange((uint8_t*) shared.data(), (uint8_t*) publicKey, (uint8_t*) privateKey); - shared = keyMul(reinterpret_cast(publicKey), reinterpret_cast(privateKey), true); //Remote key get negated - sharedIv = digest::sha512(shared); + uint8_t shared[32]; + uint8_t shared_iv[64]; + + ed25519_key_exchange(shared, (uint8_t*) publicKey, (uint8_t*) privateKey); + keyMul(shared, reinterpret_cast(publicKey), reinterpret_cast(privateKey), true); //Remote key get negated + digest::sha512((char*) shared, 32, shared_iv); auto xor_key = alpha + beta; for(int i = 0; i < 64; i++) - sharedIv[i] ^= xor_key[i]; + shared_iv[i] ^= xor_key[i]; { lock_guard lock(this->cache_key_lock); - memcpy(this->iv_struct, sharedIv.data(), 64); + memcpy(this->iv_struct, shared_iv, 64); this->iv_struct_length = 64; auto digest_buffer = digest::sha1((char*) this->iv_struct, 64); @@ -165,6 +163,7 @@ bool CryptionHandler::generate_key_nonce(protocol::BasicPacket* packet, bool use ); } +#define GENERATE_BUFFER_LENGTH (128) bool CryptionHandler::generate_key_nonce( bool to_server, /* its from the client to the server */ protocol::PacketType type, @@ -189,8 +188,10 @@ bool CryptionHandler::generate_key_nonce( auto& key_cache = key_cache_array[type]; if(key_cache.generation != generation) { const size_t buffer_length = 6 + this->iv_struct_length; - char* buffer = new char[buffer_length]; - memset(buffer, 0, 6 + this->iv_struct_length); + sassert(buffer_length < GENERATE_BUFFER_LENGTH); + + char buffer[GENERATE_BUFFER_LENGTH]; + memset(buffer, 0, buffer_length); if (to_server) { buffer[0] = 0x31; @@ -201,13 +202,11 @@ bool CryptionHandler::generate_key_nonce( le2be32(generation, buffer, 2); memcpy(&buffer[6], this->iv_struct, this->iv_struct_length); - auto key_nonce = digest::sha256(buffer, 6 + this->iv_struct_length); + auto key_nonce = digest::sha256(buffer, buffer_length); memcpy(key_cache.key, key_nonce.data(), 16); memcpy(key_cache.nonce, key_nonce.data() + 16, 16); key_cache.generation = generation; - - delete[] buffer; } memcpy(key, key_cache.key, 16); @@ -234,9 +233,10 @@ bool CryptionHandler::verify_encryption(const pipes::buffer_view &packet, uint16 auto length = data.length(); - const unsigned long target_length = 2048; - uint8_t target_buffer[2048]; - if(target_length < length) + /* static shareable void buffer */ + const static unsigned long void_target_length = 2048; + static uint8_t void_target_buffer[2048]; + if(void_target_length < length) return false; err = eax_decrypt_verify_memory(find_cipher("rijndael"), @@ -248,7 +248,7 @@ bool CryptionHandler::verify_encryption(const pipes::buffer_view &packet, uint16 (unsigned long) header.length(), /* header length */ (const unsigned char *) data.data_ptr(), (unsigned long) data.length(), - (unsigned char *) target_buffer, + (unsigned char *) void_target_buffer, (unsigned char *) mac.data_ptr(), (unsigned long) mac.length(), &success @@ -270,14 +270,6 @@ bool CryptionHandler::decryptPacket(protocol::BasicPacket *packet, std::string & return false; } - size_t target_length = 2048; - uint8_t target_buffer[2048]; - auto length = data.length(); - if(target_length < length) { - error = "buffer too large"; - return false; - } - err = eax_decrypt_verify_memory(find_cipher("rijndael"), (uint8_t *) key, /* the key */ (unsigned long) 16, /* key is 16 bytes */ @@ -287,7 +279,7 @@ bool CryptionHandler::decryptPacket(protocol::BasicPacket *packet, std::string & (unsigned long) header.length(), /* header length */ (const unsigned char *) data.data_ptr(), (unsigned long) data.length(), - (unsigned char *) target_buffer, + (unsigned char *) data.data_ptr(), (unsigned char *) packet->mac().data_ptr(), (unsigned long) packet->mac().length(), &success @@ -302,7 +294,6 @@ bool CryptionHandler::decryptPacket(protocol::BasicPacket *packet, std::string & return false; } - packet->data(pipes::buffer_view{target_buffer, length}); packet->setEncrypted(false); return true; } @@ -314,18 +305,9 @@ bool CryptionHandler::encryptPacket(protocol::BasicPacket *packet, std::string & return false; } - size_t length = packet->data().length(); - size_t tag_length = 8; char tag_buffer[8]; - size_t target_length = 2048; - uint8_t target_buffer[2048]; - if(target_length < length) { - error = "buffer too large"; - return false; - } - int err; if((err = eax_encrypt_authenticate_memory(find_cipher("rijndael"), (uint8_t *) key, /* the key */ @@ -336,7 +318,7 @@ bool CryptionHandler::encryptPacket(protocol::BasicPacket *packet, std::string & (unsigned long) packet->header().length(), /* header length */ (uint8_t *) packet->data().data_ptr(), /* The plain text */ (unsigned long) packet->data().length(), /* Plain text length */ - (uint8_t *) target_buffer, /* The result buffer */ + (uint8_t *) packet->data().data_ptr(), /* The result buffer */ (uint8_t *) tag_buffer, (unsigned long *) &tag_length )) != CRYPT_OK){ @@ -344,16 +326,14 @@ bool CryptionHandler::encryptPacket(protocol::BasicPacket *packet, std::string & return false; } assert(tag_length == 8); - - packet->data(pipes::buffer_view{target_buffer, length}); - packet->mac().write(tag_buffer, tag_length); + packet->mac().write(tag_buffer, tag_length); packet->setEncrypted(true); return true; } bool CryptionHandler::progressPacketIn(protocol::BasicPacket* packet, std::string& error, bool use_default) { while(blocked) - this_thread::sleep_for(chrono::microseconds(100)); + this_thread::yield(); if(packet->isEncrypted()){ bool success = decryptPacket(packet, error, use_default); @@ -365,9 +345,9 @@ bool CryptionHandler::progressPacketIn(protocol::BasicPacket* packet, std::strin bool CryptionHandler::progressPacketOut(protocol::BasicPacket* packet, std::string& error, bool use_default) { while(blocked) - this_thread::sleep_for(chrono::microseconds(100)); + this_thread::yield(); - if(packet->hasFlag(PacketFlag::Unencrypted)) { + if(packet->has_flag(PacketFlag::Unencrypted)) { packet->mac().write(this->current_mac, 8); } else { bool success = encryptPacket(packet, error, use_default); diff --git a/src/protocol/CryptionHandler.h b/src/protocol/CryptionHandler.h index 07fbcb0..929bb09 100644 --- a/src/protocol/CryptionHandler.h +++ b/src/protocol/CryptionHandler.h @@ -26,7 +26,7 @@ namespace ts { //TeamSpeak old bool setupSharedSecret(const std::string& alpha, const std::string& beta, ecc_key* publicKey, ecc_key* ownKey, std::string &error); - bool setupSharedSecret(const std::string& alpha, const std::string& beta, std::string sharedKey, std::string &error); + bool setupSharedSecret(const std::string& alpha, const std::string& beta, const std::string& sharedKey, std::string &error); //TeamSpeak new bool setupSharedSecretNew(const std::string& alpha, const std::string& beta, const char privateKey[32], const char publicKey[32]); diff --git a/src/protocol/Packet.cpp b/src/protocol/Packet.cpp index a17d4a7..15cfd89 100644 --- a/src/protocol/Packet.cpp +++ b/src/protocol/Packet.cpp @@ -91,10 +91,10 @@ namespace ts { std::string BasicPacket::flags() const { std::string result; - if(hasFlag(PacketFlag::Unencrypted)) result += string(result.empty() ? "" : " | ") + "Unencrypted"; - if(hasFlag(PacketFlag::Compressed)) result += string(result.empty() ? "" : " | ") + "Compressed"; - if(hasFlag(PacketFlag::Fragmented)) result += string(result.empty() ? "" : " | ") + "Fragmented"; - if(hasFlag(PacketFlag::NewProtocol)) result += string(result.empty() ? "" : " | ") + "NewProtocol"; + if(this->has_flag(PacketFlag::Unencrypted)) result += string(result.empty() ? "" : " | ") + "Unencrypted"; + if(this->has_flag(PacketFlag::Compressed)) result += string(result.empty() ? "" : " | ") + "Compressed"; + if(this->has_flag(PacketFlag::Fragmented)) result += string(result.empty() ? "" : " | ") + "Fragmented"; + if(this->has_flag(PacketFlag::NewProtocol)) result += string(result.empty() ? "" : " | ") + "NewProtocol"; if(result.empty()) result = "none"; return result; @@ -130,6 +130,10 @@ namespace ts { memcpy(this->data().data_ptr(), data.data_ptr(), data.length()); } + ServerPacket::ServerPacket(ts::protocol::PacketTypeInfo type, size_t data_length) : BasicPacket(SERVER_HEADER_SIZE, data_length) { + this->header()[2] |= type.type(); + } + ServerPacket::~ServerPacket() {} uint16_t ServerPacket::packetId() const { @@ -149,22 +153,6 @@ namespace ts { return PacketTypeInfo::fromid(this->header()[2] & 0xF); } - uint8_t ServerPacket::flagMask() const { - return this->header()[2]; - } - - bool ServerPacket::hasFlag(PacketFlag::PacketFlag flag) const { - return (this->header()[2] & flag) > 0; - } - - void ServerPacket::toggle(PacketFlag::PacketFlag flag, bool state) { - if(state){ - this->header()[2] |= flag; - } else { - this->header()[2] &= ~flag; - } - } - ClientPacket::ClientPacket(const pipes::buffer_view& buffer) : BasicPacket(CLIENT_HEADER_SIZE, buffer.own_buffer()) { } @@ -198,23 +186,6 @@ namespace ts { field |= type.type(); } - bool ClientPacket::hasFlag(PacketFlag::PacketFlag flag) const { - return (this->header()[4] & flag) > 0; - } - - uint8_t ClientPacket::flagMask() const { - return this->header()[4]; - } - - - void ClientPacket::toggle(PacketFlag::PacketFlag flag, bool state) { - if(state){ - this->header()[4] |= flag; - } else { - this->header()[4] &= ~flag; - } - } - void ClientPacket::setPacketId(uint16_t pkId, uint16_t gen) { this->header()[0] = (uint8_t) ((pkId >> 8) & 0xFF); this->header()[1] = (uint8_t) ((pkId >> 0) & 0xFF); diff --git a/src/protocol/Packet.h b/src/protocol/Packet.h index 2f690ff..5db8f2e 100644 --- a/src/protocol/Packet.h +++ b/src/protocol/Packet.h @@ -114,6 +114,7 @@ namespace ts { Compressed = 0x40, //If packet type voice than its the header Unencrypted = 0x80 }; + typedef uint8_t PacketFlags; std::string to_string(PacketFlag flag); } @@ -134,11 +135,26 @@ namespace ts { 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; + + /* 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; + + /* manipulate flags */ + inline void set_flags(PacketFlag::PacketFlags flags) { + uint8_t& byte = this->_flags_type_byte(); + byte &= 0xF; /* clear all flags */ + byte |= (flags & 0xF0); + } + inline void enabled_flag(PacketFlag::PacketFlag flag){ this->toggle_flag(flag, true); } + inline void toggle_flag(PacketFlag::PacketFlag flag, bool state) { + if(state) + this->_flags_type_byte() |= flag; + else + this->_flags_type_byte() &= ~flag; + } + virtual void applyPacketId(PacketIdManager &); virtual void applyPacketId(uint16_t, uint16_t); @@ -149,14 +165,14 @@ namespace ts { } inline std::unique_ptr>& getListener() { return this->listener; } - inline pipes::buffer_view mac() const { return this->_buffer.view(0, MAC_SIZE); } + 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 pipes::buffer_view header() const { return this->_buffer.view(MAC_SIZE, this->_header_length); } + 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 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 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); } void append_data(const std::vector &data); @@ -206,15 +222,12 @@ namespace ts { pipes::buffer buffer() { return this->_buffer; } void buffer(pipes::buffer buffer) { this->_buffer = std::move(buffer); } protected: + virtual const uint8_t& _flags_type_byte() const = 0; + virtual uint8_t& _flags_type_byte() = 0; + 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; @@ -237,8 +250,6 @@ namespace ts { ClientPacket(const ClientPacket&) = delete; ClientPacket(ClientPacket&&) = delete; - void toggle(PacketFlag::PacketFlag flag, bool state) override; - uint16_t clientId() const; void clientId(uint16_t); @@ -250,10 +261,15 @@ namespace ts { PacketTypeInfo type() const override; void type(const PacketTypeInfo&); - bool hasFlag(PacketFlag::PacketFlag flag) const override; - uint8_t flagMask() const override; - private: + const uint8_t &_flags_type_byte() const override { + return this->header().data_ptr()[4]; + } + + uint8_t &_flags_type_byte() override { + return this->header().data_ptr()[4]; + } + void setPacketId(uint16_t, uint16_t) override; }; @@ -269,6 +285,7 @@ namespace ts { 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(PacketTypeInfo type, size_t /* data length */); ~ServerPacket() override; ServerPacket(const ServerPacket&) = delete; ServerPacket(ServerPacket&&) = delete; @@ -278,12 +295,15 @@ namespace ts { 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: + const uint8_t &_flags_type_byte() const override { + return this->header().data_ptr()[2]; + } + + uint8_t &_flags_type_byte() override { + return this->header().data_ptr()[2]; + } + void setPacketId(uint16_t, uint16_t) override; }; } diff --git a/src/protocol/ringbuffer.h b/src/protocol/ringbuffer.h index 200cc6d..52da63f 100644 --- a/src/protocol/ringbuffer.h +++ b/src/protocol/ringbuffer.h @@ -73,7 +73,7 @@ namespace ts { slot.flag_set = false; auto entry = std::move(slot.entry); this->_ring_base_index += 1; - this->_ring_index += 1; + this->_ring_index_full += 1; if(this->_ring_base_index >= this->_capacity) this->_ring_base_index -= this->_capacity; return entry; @@ -85,7 +85,7 @@ namespace ts { this->_ring_base_index = (size_type) this->_capacity; this->_ring_base_index -= 1; - this->_ring_index -= 1; + this->_ring_index_full -= 1; auto& slot = this->_slots[this->_ring_base_index]; slot.entry = std::forward(entry); @@ -118,7 +118,7 @@ namespace ts { if(index > this->_ring_index) this->_ring_index = index; else if(index < 100 && this->_ring_index > std::numeric_limits::max() - 100) { - this->_ring_index += 200; /* let the index overflow into the generation counter */ + this->_ring_index_full += 200; /* let the index overflow into the generation counter */ this->_ring_index = index; /* set the lover (16) bytes */ } } @@ -161,8 +161,9 @@ namespace ts { struct { static_assert(8 - sizeof(size_type) > 0, "Invalid size type!"); - uint8_t padding[8 - sizeof(size_type)]; + /* little endian */ size_type _ring_index; /* index of the insert index | overflow is welcome here */ + uint8_t padding[8 - sizeof(size_type)]; }; }; diff --git a/test/RingTest.cpp b/test/RingTest.cpp index 774dd6f..9a0b32c 100644 --- a/test/RingTest.cpp +++ b/test/RingTest.cpp @@ -94,5 +94,28 @@ int main() { buffer.push_front(2); buffer.push_front(1); print_queue(buffer); + + */ + + /* + [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65527, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! + [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65528, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! + [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65529, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! + [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65530, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! + [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65531, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! + [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65532, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! + [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65533, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! + [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65534, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! + [2019-07-05 13:49:02] [DEBUG] 162 | [127.0.0.1:60793/Another TeaSpeak user | 1] Cant decrypt packet of type Voice. Packet ID: 65535, Estimated generation: 2, Full counter: 65536. Dropping packet. Error: memory verify failed! + */ + PacketRingBuffer buffer; + buffer.set_generation_packet(0, 65500); + + while(buffer.current_index() < 100 || (buffer.full_index() >> 16) == 0) { + buffer.push_back(nullptr); + buffer.pop_front(); + cout << buffer.full_index() << " | " << buffer.current_index() << " | " << buffer.generation(buffer.current_index()) << endl; + } + __asm__("nop"); } \ No newline at end of file