Merge remote-tracking branch 'origin/master'

This commit is contained in:
WolverinDEV 2019-07-05 20:45:36 +02:00
commit 29bd5e55c4
12 changed files with 189 additions and 172 deletions

View File

@ -3,9 +3,9 @@
#include <condition_variable>
#include <cassert>
#include <algorithm>
#include "src/log/LogUtils.h"
#include <src/misc/sassert.h>
#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<event::EventEntry> &entry) {
bool EventExecutor::schedule(const std::shared_ptr<ts::event::EventEntry> &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<event::EventEntry> &entry) {
return true;
}
bool EventExecutor::cancel(const std::shared_ptr<event::EventEntry> &entry) {
bool EventExecutor::cancel(const std::shared_ptr<ts::event::EventEntry> &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<std::mutex> &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, [&] {
@ -204,11 +204,16 @@ void EventExecutor::_executor(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);
delete linked_entry;
}

View File

@ -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);
}
};

View File

@ -190,7 +190,7 @@ namespace std {
count--;
} else {
// normal unlocking
owner = std::thread::id();
owner = this_id;
count = 0;
handle.unlock();
}

View File

@ -6,20 +6,22 @@
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)) {
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();
}
}
}
inline bool try_lock() {
return !locked.test_and_set(std::memory_order_acquire);
}
void unlock() {
inline void unlock() {
locked.clear(std::memory_order_release);
}
};

View File

@ -1,7 +1,12 @@
#pragma once
#define TIMING_START(_name) \
struct { \
#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; \
@ -11,26 +16,36 @@ struct { \
std::chrono::system_clock::time_point begin; \
std::chrono::system_clock::time_point end; \
std::deque<entry> timings; \
} _name ##_timings; \
_name ##_timings.begin = std::chrono::system_clock::now(); \
} _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) \
([&](){ \
#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<std::chrono::milliseconds>(_name ##_timings.end - _name ##_timings.begin).count()) + "ms"; \
result += std::to_string(std::chrono::duration_cast<std::chrono::unit>(_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<std::chrono::milliseconds>(entry.ts - _name ##_timings.begin).count()) + "ms"; \
result += ": " + std::to_string(std::chrono::duration_cast<std::chrono::milliseconds>(entry.ts - tp).count()) + "ms"; \
result += "@" + std::to_string(std::chrono::duration_cast<std::chrono::unit>(entry.ts - _name ##_timings.begin).count()) + unit_name; \
result += ": " + std::to_string(std::chrono::duration_cast<std::chrono::unit>(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 */

View File

@ -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);
}

View File

@ -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"
@ -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<const uint8_t *>(publicKey), reinterpret_cast<const uint8_t *>(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<const uint8_t *>(publicKey), reinterpret_cast<const uint8_t *>(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,8 +326,6 @@ 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->setEncrypted(true);
return true;
@ -353,7 +333,7 @@ bool CryptionHandler::encryptPacket(protocol::BasicPacket *packet, std::string &
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);

View File

@ -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]);

View File

@ -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);

View File

@ -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<threads::Future<bool>>& 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<pipes::buffer> &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<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;
@ -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<uint8_t>()[4];
}
uint8_t &_flags_type_byte() override {
return this->header().data_ptr<uint8_t>()[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<uint8_t>()[2];
}
uint8_t &_flags_type_byte() override {
return this->header().data_ptr<uint8_t>()[2];
}
void setPacketId(uint16_t, uint16_t) override;
};
}

View File

@ -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<E>(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<size_type>::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)];
};
};

View File

@ -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<int, 16> 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");
}