Some code refactoring

This commit is contained in:
WolverinDEV 2021-02-07 12:27:40 +01:00
parent c31eb18849
commit 2b38287317
39 changed files with 131 additions and 921 deletions

View File

@ -25,7 +25,6 @@ if (BUILD_INCLUDE_FILE)
include(${BUILD_INCLUDE_FILE})
endif ()
set(CMAKE_PREFIX_PATH "/home/wolverindev/clib/qt/5.6.1/5.6/gcc_64/lib/cmake")
set(LIBEVENT_PATH "${LIBRARY_PATH}/event/build/lib/")
function(resolve_library VARIABLE FALLBACK PATHS)

@ -1 +1 @@
Subproject commit ecba83b0d985a35e200faba32e1fcfe01fc3ec42
Subproject commit a255c93b1a7d3e6d619f32cd8de49beb8f373477

View File

@ -8,6 +8,7 @@
#include <ThreadPool/ThreadHelper.h>
#include <misc/endianness.h>
#include <shared/include/license/client.h>
#include <log/LogUtils.h>
#include "shared/include/license/client.h"
#include "crypt.h"

2
rtclib

@ -1 +1 @@
Subproject commit f6b03688f0f80803f182fdaab7d645f4f7633bdf
Subproject commit 4af616299dedd540391eb230c058a7274135155a

View File

@ -48,7 +48,6 @@ set(SERVER_SOURCE_FILES
src/client/voice/VoiceClientHandschake.cpp
src/client/voice/VoiceClientCommandHandler.cpp
src/client/voice/VoiceClientConnectionPacketHandler.cpp
src/client/voice/PacketStatistics.cpp
src/TS3ServerClientManager.cpp
src/VirtualServer.cpp
src/FileServerHandler.cpp
@ -145,11 +144,8 @@ set(SERVER_SOURCE_FILES
src/client/SpeakingClientHandshake.cpp
src/client/command_handler/music.cpp src/client/command_handler/file.cpp
src/client/voice/PacketDecoder.cpp
src/client/voice/PacketEncoder.cpp
src/client/shared/ServerCommandExecutor.cpp
src/client/shared/RawCommand.cpp
src/client/voice/PingHandler.cpp
src/client/voice/CryptSetupHandler.cpp
src/client/shared/WhisperHandler.cpp
@ -175,42 +171,12 @@ endif ()
add_executable(PermHelper helpers/permgen.cpp)
target_link_libraries(PermHelper
${LIBRARY_PATH_ED255}
TeaSpeak #Static
TeaLicenseHelper #Static
TeaMusic #Static
${LIBRARY_PATH_THREAD_POOL} #Static
${LIBRARY_PATH_TERMINAL} #Static
${LIBRARY_PATH_VARIBALES}
${LIBRARY_PATH_YAML}
pthread
TeaSpeak
stdc++fs
${LIBEVENT_PATH}/libevent.a
${LIBEVENT_PATH}/libevent_pthreads.a
${LIBRARY_PATH_OPUS}
${LIBRARY_PATH_JSON}
${LIBRARY_PATH_PROTOBUF}
#${LIBWEBRTC_LIBRARIES} #ATTENTIAN! WebRTC does not work with crypto! (Already contains a crypto version)
${LIBRARY_TOM_CRYPT}
${LIBRARY_TOM_MATH}
#We're forsed to use boringssl caused by the fact that boringssl is already within webrtc!
#Require a so
sqlite3
${LIBRARY_PATH_BREAKPAD}
${LIBRARY_PATH_JDBC}
${LIBRARY_PATH_PROTOBUF}
${LIBRARY_PATH_DATA_PIPES}
${LIBRARY_PATH_BORINGSSL_SSL}
${LIBRARY_PATH_BORINGSSL_CRYPTO}
dl
jemalloc
)
CXXTerminal::static
libevent::core libevent::pthreads
${StringVariable_LIBRARIES_STATIC}
)
add_executable(PermMapHelper helpers/PermMapGen.cpp)
target_link_libraries(PermMapHelper
@ -357,6 +323,5 @@ target_link_libraries(Snapshots-Permissions-Test PUBLIC
tomcrypt::static
tommath::static
${glib20_DIR}/lib/x86_64-linux-gnu/libffi.so.7 ${nice_DIR}/lib/libnice.so.10
)
target_include_directories(Snapshots-Permissions-Test PUBLIC ${CMAKE_SOURCE_DIR}/server/src/)
target_include_directories(Snapshots-Permissions-Test PUBLIC ${CMAKE_SOURCE_DIR}/server/src/)

View File

@ -1,10 +1,7 @@
#include <fstream>
#include <query/Command.h>
#include <cstring>
#include <utility>
#include <functional> /* required from permission manager */
#include "log/LogUtils.h"
#include "Definitions.h"
#include "PermissionManager.h"

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -119,7 +119,7 @@ void ConnectedClient::updateChannelClientProperties(bool lock_channel_tree, bool
}
deque<property::ClientProperties> notifyList;
debugMessage(this->getServerId(), "{} Got a channel talk power of {} Talk power set is {}", CLIENT_STR_LOG_PREFIX, permission_talk_power, this->properties()[property::CLIENT_TALK_POWER].as<uint64_t>());
debugMessage(this->getServerId(), "{} Got a channel talk power of {} Talk power set is {}", CLIENT_STR_LOG_PREFIX, permission_talk_power.has_value ? permission_talk_power.value : 0, this->properties()[property::CLIENT_TALK_POWER].as<uint64_t>());
if((permission_talk_power.has_value ? permission_talk_power.value : 0) != this->properties()[property::CLIENT_TALK_POWER].as<uint64_t>()) { //We do not have to update tp if there's no channel
this->properties()[property::CLIENT_TALK_POWER] = (permission_talk_power.has_value ? permission_talk_power.value : 0);
notifyList.emplace_back(property::CLIENT_TALK_POWER);

View File

@ -7,6 +7,7 @@
#include "../manager/PermissionNameMapper.h"
#include "music/MusicClient.h"
#include <misc/sassert.h>
#include <log/LogUtils.h>
#include "./web/WebClient.h"
using namespace std::chrono;

View File

@ -274,17 +274,17 @@ command_result SpeakingClient::handleCommandClientInit(Command& cmd) {
});
if(clones_uid > 0 && permissions[permission::i_client_max_clones_uid].has_value && !permission::v2::permission_granted(clones_uid, permissions[permission::i_client_max_clones_uid])) {
logMessage(this->getServerId(), "{} Disconnecting because there are already {} uid clones connected. (Allowed: {})", CLIENT_STR_LOG_PREFIX, clones_uid, permissions[permission::i_client_max_clones_uid]);
logMessage(this->getServerId(), "{} Disconnecting because there are already {} uid clones connected. (Allowed: {})", CLIENT_STR_LOG_PREFIX, clones_uid, permissions[permission::i_client_max_clones_uid].value);
return command_result{error:: client_too_many_clones_connected, "too many clones connected (uid)"};
}
if(clones_ip > 0 && permissions[permission::i_client_max_clones_ip].has_value && !permission::v2::permission_granted(clones_ip, permissions[permission::i_client_max_clones_ip])) {
logMessage(this->getServerId(), "{} Disconnecting because there are already {} ip clones connected. (Allowed: {})", CLIENT_STR_LOG_PREFIX, clones_ip, permissions[permission::i_client_max_clones_ip]);
logMessage(this->getServerId(), "{} Disconnecting because there are already {} ip clones connected. (Allowed: {})", CLIENT_STR_LOG_PREFIX, clones_ip, permissions[permission::i_client_max_clones_ip].value);
return command_result{error:: client_too_many_clones_connected, "too many clones connected (ip)"};
}
if(clones_hwid > 0 && permissions[permission::i_client_max_clones_hwid].has_value && !permission::v2::permission_granted(clones_hwid, permissions[permission::i_client_max_clones_hwid])) {
logMessage(this->getServerId(), "{} Disconnecting because there are already {} hwid clones connected. (Allowed: {})", CLIENT_STR_LOG_PREFIX, clones_hwid, permissions[permission::i_client_max_clones_hwid]);
logMessage(this->getServerId(), "{} Disconnecting because there are already {} hwid clones connected. (Allowed: {})", CLIENT_STR_LOG_PREFIX, clones_hwid, permissions[permission::i_client_max_clones_hwid].value);
return command_result{error:: client_too_many_clones_connected, "too many clones connected (hwid)"};
}
TIMING_STEP(timings, "max clones ");

View File

@ -28,6 +28,8 @@
#include <misc/hex.h>
#include <misc/rnd.h>
#include <log/LogUtils.h>
using namespace std::chrono;
using namespace std;
using namespace ts;

View File

@ -5,6 +5,7 @@
#include "src/InstanceHandler.h"
#include <pipes/errors.h>
#include <misc/std_unique_ptr.h>
#include <log/LogUtils.h>
using namespace std;
using namespace std::chrono;

View File

@ -5,6 +5,7 @@
#include <src/VirtualServerManager.h>
#include <src/InstanceHandler.h>
#include "QueryClient.h"
#include <log/LogUtils.h>
using namespace std;
using namespace std::chrono;

View File

@ -1,19 +0,0 @@
//
// Created by WolverinDEV on 28/01/2021.
//
#include "RawCommand.h"
using namespace ts::server::command;
ReassembledCommand *ReassembledCommand::allocate(size_t size) {
auto instance = (ReassembledCommand*) malloc(sizeof(ReassembledCommand) + size);
instance->length_ = size;
instance->capacity_ = size;
instance->next_command = nullptr;
return instance;
}
void ReassembledCommand::free(ReassembledCommand *command) {
::free(command);
}

View File

@ -1,48 +0,0 @@
#pragma once
#include <cstdint>
#include <string_view>
#include <pipes/buffer.h>
namespace ts::server::command {
struct CommandFragment {
uint16_t packet_id{0};
uint16_t packet_generation{0};
uint8_t packet_flags{0};
uint32_t payload_length : 24;
pipes::buffer payload{};
CommandFragment() : payload_length{0} { }
CommandFragment(uint16_t packetId, uint16_t packetGeneration, uint8_t packetFlags, uint32_t payloadLength, pipes::buffer payload)
: packet_id{packetId}, packet_generation{packetGeneration}, packet_flags{packetFlags}, payload_length{payloadLength}, payload{std::move(payload)} {}
CommandFragment& operator=(const CommandFragment&) = default;
CommandFragment(const CommandFragment& other) = default;
CommandFragment(CommandFragment&&) = default;
};
static_assert(sizeof(CommandFragment) == 8 + sizeof(pipes::buffer));
struct ReassembledCommand {
public:
static ReassembledCommand* allocate(size_t /* command length */);
static void free(ReassembledCommand* /* command */);
[[nodiscard]] inline size_t length() const { return this->length_; }
inline void set_length(size_t length) { assert(this->capacity_ >= length); this->length_ = length; }
[[nodiscard]] inline size_t capacity() const { return this->capacity_; }
[[nodiscard]] inline const char* command() const { return (const char*) this + sizeof(ReassembledCommand); }
[[nodiscard]] inline char* command() { return (char*) this + sizeof(ReassembledCommand); }
[[nodiscard]] inline std::string_view command_view() const { return std::string_view{this->command(), this->length()}; }
mutable ReassembledCommand* next_command; /* nullptr by default */
private:
explicit ReassembledCommand() = default;
size_t capacity_;
size_t length_;
};
}

View File

@ -4,15 +4,16 @@
#include <utility>
#include <ThreadPool/ThreadHelper.h>
#include <log/LogUtils.h>
#include "./ServerCommandExecutor.h"
#include "src/client/voice/PacketDecoder.h"
#include "protocol/PacketDecoder.h"
#include "protocol/RawCommand.h"
#include "src/client/voice/VoiceClientConnection.h"
using namespace ts;
using namespace ts::server;
using namespace ts::server::command;
using namespace ts::command;
namespace ts::server {
struct ServerCommandQueueInner {

View File

@ -8,11 +8,11 @@ namespace ts::server {
class VoiceClient;
}
namespace ts::server {
namespace command {
struct ReassembledCommand;
}
namespace ts::command {
struct ReassembledCommand;
}
namespace ts::server {
class ServerCommandExecutor;
class ServerCommandQueue;
struct ServerCommandQueueInner;

View File

@ -5,6 +5,7 @@
#include "WhisperHandler.h"
#include "src/client/voice/VoiceClientConnection.h"
#include <misc/endianness.h>
#include <log/LogUtils.h>
using namespace ts::server::whisper;
@ -17,7 +18,7 @@ WhisperHandler::~WhisperHandler() {
}
}
bool WhisperHandler::validate_whisper_packet(const protocol::ClientPacketParser &packet, bool& match_last_header, void *&payload_ptr, size_t &payload_length) {
bool WhisperHandler::validate_whisper_packet(const protocol::PacketParser &packet, bool& match_last_header, void *&payload_ptr, size_t &payload_length) {
size_t head_length;
if(packet.flags() & protocol::PacketFlag::NewProtocol) {
if(packet.payload_length() < 3 + 10) {
@ -68,7 +69,7 @@ bool WhisperHandler::validate_whisper_packet(const protocol::ClientPacketParser
return true;
}
bool WhisperHandler::process_packet(const protocol::ClientPacketParser &packet, void *&payload_ptr, size_t &payload_length) {
bool WhisperHandler::process_packet(const protocol::PacketParser &packet, void *&payload_ptr, size_t &payload_length) {
bool match_last_header;
if(!this->validate_whisper_packet(packet, match_last_header, payload_ptr, payload_length)) {
return false;

View File

@ -1,8 +1,11 @@
#pragma once
#include <string_view>
#include <chrono>
#include <mutex>
#include <Error.h>
#include <protocol/Packet.h>
#include <string_view>
namespace ts::connection {
class VoiceClientConnection;
@ -42,7 +45,7 @@ namespace ts::server::whisper {
* Preprocess a whisper packet.
* If the result is false the packet should not be send into the rtc source pipe.
*/
bool process_packet(const protocol::ClientPacketParser& /* packet */, void*& /* payload ptr */, size_t& /* payload length */);
bool process_packet(const protocol::PacketParser& /* packet */, void*& /* payload ptr */, size_t& /* payload length */);
ts::command_result initialize_session_new(uint32_t /* stream id */, uint8_t /* type */, uint8_t /* target */, uint64_t /* type id */);
ts::command_result initialize_session_old(uint32_t /* stream id */, const uint16_t* /* client ids */, size_t /* client count */, const uint64_t* /* channel ids */, size_t /* channel count */);
@ -70,7 +73,7 @@ namespace ts::server::whisper {
* This also updates the last head ptr.
* @return True if the packet is a valid whisper packet. The payload ptr and payload length variables will be set
*/
bool validate_whisper_packet(const protocol::ClientPacketParser& /* packet */, bool& /* matches last header */, void*& /* payload ptr */, size_t& /* payload length */);
bool validate_whisper_packet(const protocol::PacketParser& /* packet */, bool& /* matches last header */, void*& /* payload ptr */, size_t& /* payload length */);
ts::command_result configure_rtc_clients(uint32_t /* stream id */, const std::vector<std::shared_ptr<SpeakingClient>>& /* clients */);
[[nodiscard]] size_t max_whisper_targets();

View File

@ -1,304 +0,0 @@
//
// Created by WolverinDEV on 10/03/2020.
//
#include "PacketDecoder.h"
#include <protocol/buffers.h>
#include <protocol/AcknowledgeManager.h>
#include <protocol/CompressionHandler.h>
#include <protocol/CryptHandler.h>
#include "../../ConnectionStatistics.h"
using namespace ts;
using namespace ts::protocol;
using namespace ts::connection;
using namespace ts::server::server::udp;
PacketDecoder::PacketDecoder(ts::connection::CryptHandler *crypt_handler)
: crypt_handler_{crypt_handler} {
memtrack::allocated<PacketDecoder>(this);
}
PacketDecoder::~PacketDecoder() {
memtrack::freed<PacketDecoder>(this);
this->reset();
}
void PacketDecoder::reset() {
std::lock_guard buffer_lock(this->packet_buffer_lock);
for(auto& buffer : this->_command_fragment_buffers) {
buffer.reset();
}
}
PacketProcessResult PacketDecoder::process_incoming_data(ClientPacketParser &packet_parser, std::string& error) {
#ifdef FUZZING_TESTING_INCOMMING
if(rand() % 100 < 20)
return PacketProcessResult::FUZZ_DROPPED;
#ifdef FIZZING_TESTING_DISABLE_HANDSHAKE
if (this->client->state == ConnectionState::CONNECTED) {
#endif
if ((rand() % FUZZING_TESTING_DROP_MAX) < FUZZING_TESTING_DROP) {
debugMessage(this->client->getServerId(), "{}[FUZZING] Dropping incoming packet of length {}", CLIENT_STR_LOG_PREFIX_(this->client), buffer.length());
return;
}
#ifdef FIZZING_TESTING_DISABLE_HANDSHAKE
}
#endif
#endif
auto result = this->decode_incoming_packet(error, packet_parser);
if(result != PacketProcessResult::SUCCESS) {
return result;
}
#ifdef LOG_INCOMPING_PACKET_FRAGMENTS
debugMessage(lstream << CLIENT_LOG_PREFIX << "Recived packet. PacketId: " << packet->packetId() << " PacketType: " << packet->type().name() << " Flags: " << packet->flags() << " - " << packet->data() << endl);
#endif
auto is_command = packet_parser.type() == protocol::COMMAND || packet_parser.type() == protocol::COMMAND_LOW;
if(is_command) {
auto& fragment_buffer = this->_command_fragment_buffers[command_fragment_buffer_index(packet_parser.type())];
CommandFragment fragment_entry{
packet_parser.packet_id(),
packet_parser.estimated_generation(),
packet_parser.flags(),
(uint32_t) packet_parser.payload_length(),
packet_parser.payload().own_buffer()
};
std::unique_lock queue_lock(fragment_buffer.buffer_lock);
auto insert_result = fragment_buffer.insert_index2(packet_parser.full_packet_id(), std::move(fragment_entry));
if(insert_result != 0) {
queue_lock.unlock();
error = "pid: " + std::to_string(packet_parser.packet_id()) + ", ";
error += "bidx: " + std::to_string(fragment_buffer.current_index()) + ", ";
error += "bcap: " + std::to_string(fragment_buffer.capacity());
if(insert_result == -2) {
return PacketProcessResult::DUPLICATED_PACKET;
} else if(insert_result == -1) {
this->callback_send_acknowledge(this->callback_argument, packet_parser.packet_id(), packet_parser.type() == protocol::COMMAND_LOW);
return PacketProcessResult::BUFFER_UNDERFLOW;
} else if(insert_result == 1) {
return PacketProcessResult::BUFFER_OVERFLOW;
}
assert(false);
return PacketProcessResult::UNKNOWN_ERROR;
}
this->callback_send_acknowledge(this->callback_argument, packet_parser.packet_id(), packet_parser.type() == protocol::COMMAND_LOW);
ReassembledCommand* command{nullptr};
CommandReassembleResult assemble_result;
do {
if(!queue_lock.owns_lock()) {
queue_lock.lock();
}
assemble_result = this->try_reassemble_ordered_packet(fragment_buffer, queue_lock, command);
if(assemble_result == CommandReassembleResult::SUCCESS || assemble_result == CommandReassembleResult::MORE_COMMANDS_PENDING) {
this->callback_decoded_command(this->callback_argument, command);
}
if(command) {
/* ownership hasn't transferred */
ReassembledCommand::free(command);
command = nullptr;
}
switch (assemble_result) {
case CommandReassembleResult::NO_COMMANDS_PENDING:
case CommandReassembleResult::SUCCESS:
case CommandReassembleResult::MORE_COMMANDS_PENDING:
break;
case CommandReassembleResult::SEQUENCE_LENGTH_TOO_LONG:
return PacketProcessResult::COMMAND_BUFFER_OVERFLOW;
case CommandReassembleResult::COMMAND_TOO_LARGE:
return PacketProcessResult::COMMAND_TOO_LARGE;
case CommandReassembleResult::COMMAND_DECOMPRESS_FAILED:
return PacketProcessResult::COMMAND_DECOMPRESS_FAILED;
default:
assert(false);
break;
}
} while(assemble_result == CommandReassembleResult::MORE_COMMANDS_PENDING);
} else {
this->callback_decoded_packet(this->callback_argument, packet_parser);
}
return PacketProcessResult::SUCCESS;
}
PacketProcessResult PacketDecoder::decode_incoming_packet(std::string& error, ClientPacketParser &packet_parser) {
assert(packet_parser.type() >= 0 && packet_parser.type() < this->incoming_generation_estimators.size());
auto& generation_estimator = this->incoming_generation_estimators[packet_parser.type()];
{
std::lock_guard glock{this->incoming_generation_estimator_lock};
packet_parser.set_estimated_generation(generation_estimator.visit_packet(packet_parser.packet_id()));
}
/* decrypt the packet if needed */
if(packet_parser.is_encrypted()) {
CryptHandler::key_t crypt_key{};
CryptHandler::nonce_t crypt_nonce{};
auto data = (uint8_t*) packet_parser.mutable_data_ptr();
bool use_default_key{!this->crypt_handler_->encryption_initialized()}, decrypt_result;
decrypt_packet:
if(use_default_key) {
crypt_key = CryptHandler::kDefaultKey;
crypt_nonce = CryptHandler::kDefaultNonce;
} else {
if(!this->crypt_handler_->generate_key_nonce(true, packet_parser.type(), packet_parser.packet_id(), packet_parser.estimated_generation(), crypt_key, crypt_nonce))
return PacketProcessResult::DECRYPT_KEY_GEN_FAILED;
}
decrypt_result = this->crypt_handler_->decrypt(
data + ClientPacketParser::kHeaderOffset, ClientPacketParser::kHeaderLength,
data + ClientPacketParser::kPayloadOffset, packet_parser.payload_length(),
data,
crypt_key, crypt_nonce,
error
);
if(!decrypt_result) {
if(packet_parser.packet_id() < 10 && packet_parser.estimated_generation() == 0) {
if(use_default_key) {
return PacketProcessResult::DECRYPT_FAILED;
} else {
use_default_key = true;
goto decrypt_packet;
}
} else {
return PacketProcessResult::DECRYPT_FAILED;
}
}
packet_parser.set_decrypted();
}
return PacketProcessResult::SUCCESS;
}
bool PacketDecoder::verify_encryption(const pipes::buffer_view &buffer) {
ClientPacketParser packet_parser{buffer};
if(!packet_parser.valid() || !packet_parser.is_encrypted()) return false;
assert(packet_parser.type() >= 0 && packet_parser.type() < this->incoming_generation_estimators.size());
return this->crypt_handler_->verify_encryption(buffer, packet_parser.packet_id(), this->incoming_generation_estimators[packet_parser.type()].generation());
}
void PacketDecoder::register_initiv_packet() {
auto& fragment_buffer = this->_command_fragment_buffers[command_fragment_buffer_index(protocol::COMMAND)];
std::unique_lock buffer_lock(fragment_buffer.buffer_lock);
fragment_buffer.set_full_index_to(1); /* the first packet (0) is already the clientinitiv packet */
}
CommandReassembleResult PacketDecoder::try_reassemble_ordered_packet(
command_fragment_buffer_t &buffer,
std::unique_lock<std::mutex> &buffer_lock,
ReassembledCommand *&assembled_command) {
assert(buffer_lock.owns_lock());
if(!buffer.front_set()) {
return CommandReassembleResult::NO_COMMANDS_PENDING;
}
uint8_t packet_flags;
std::unique_ptr<ReassembledCommand, void(*)(ReassembledCommand*)> rcommand{nullptr, ReassembledCommand::free};
/* lets find out if we've to reassemble the packet */
auto& first_buffer = buffer.slot_value(0);
if(first_buffer.packet_flags & PacketFlag::Fragmented) {
uint16_t sequence_length{1};
size_t total_payload_length{first_buffer.payload_length};
do {
if(sequence_length >= buffer.capacity()) {
return CommandReassembleResult::SEQUENCE_LENGTH_TOO_LONG;
}
if(!buffer.slot_set(sequence_length)) {
return CommandReassembleResult::NO_COMMANDS_PENDING; /* we need more packets */
}
auto& packet = buffer.slot_value(sequence_length++);
total_payload_length += packet.payload_length;
if(packet.packet_flags & PacketFlag::Fragmented) {
/* yep we find the end */
break;
}
} while(true);
/* ok we have all fragments lets reassemble */
/*
* Packet sequence could never be so long. If it is so then the data_length() returned an invalid value.
* We're checking it here because we dont want to make a huge allocation
*/
assert(total_payload_length < 512 * 1024 * 1024);
rcommand.reset(ReassembledCommand::allocate(total_payload_length));
char* packet_buffer_ptr = rcommand->command();
size_t packet_count{0};
packet_flags = buffer.slot_value(0).packet_flags;
while(packet_count < sequence_length) {
auto fragment = buffer.pop_front();
memcpy(packet_buffer_ptr, fragment.payload.data_ptr(), fragment.payload_length);
packet_buffer_ptr += fragment.payload_length;
packet_count++;
}
#ifndef _NDEBUG
if((packet_buffer_ptr - 1) != &rcommand->command()[rcommand->length() - 1]) {
logCritical(0,
"Buffer over/underflow: packet_buffer_ptr != &packet_buffer[packet_buffer.length() - 1]; packet_buffer_ptr := {}; packet_buffer.end() := {}",
(void*) packet_buffer_ptr,
(void*) &rcommand->command()[rcommand->length() - 1]
);
}
#endif
} else {
auto packet = buffer.pop_front();
packet_flags = packet.packet_flags;
rcommand.reset(ReassembledCommand::allocate(packet.payload_length));
memcpy(rcommand->command(), packet.payload.data_ptr(), packet.payload_length);
}
auto more_commands_pending = buffer.front_set(); /* set the more flag if we have more to process */
buffer_lock.unlock();
if(packet_flags & PacketFlag::Compressed) {
std::string error{};
auto compressed_command = std::move(rcommand);
auto decompressed_size = compression::qlz_decompressed_size(compressed_command->command(), compressed_command->length());
if(decompressed_size > 64 * 1024 * 1024) {
return CommandReassembleResult::COMMAND_TOO_LARGE;
}
rcommand.reset(ReassembledCommand::allocate(decompressed_size));
if(!compression::qlz_decompress_payload(compressed_command->command(), rcommand->command(), &decompressed_size)) {
return CommandReassembleResult::COMMAND_DECOMPRESS_FAILED;
}
rcommand->set_length(decompressed_size);
}
assembled_command = rcommand.release();
return more_commands_pending ? CommandReassembleResult::MORE_COMMANDS_PENDING : CommandReassembleResult::SUCCESS;
}

View File

@ -1,96 +0,0 @@
#pragma once
#include <misc/spin_mutex.h>
#include <mutex>
#include <deque>
#include <protocol/Packet.h>
#include <protocol/generation.h>
#include <protocol/ringbuffer.h>
#include "../shared/RawCommand.h"
namespace ts::connection {
class CryptHandler;
class CompressionHandler;
class AcknowledgeManager;
}
namespace ts::stats {
class ConnectionStatistics;
}
namespace ts::server::server::udp {
enum struct PacketProcessResult {
SUCCESS,
UNKNOWN_ERROR,
FUZZ_DROPPED,
DUPLICATED_PACKET, /* error message contains debug properties */
BUFFER_OVERFLOW, /* error message contains debug properties */
BUFFER_UNDERFLOW, /* error message contains debug properties */
COMMAND_BUFFER_OVERFLOW, /* can cause a total connection drop */
COMMAND_SEQUENCE_LENGTH_TOO_LONG, /* unrecoverable error */
COMMAND_TOO_LARGE,
COMMAND_DECOMPRESS_FAILED,
DECRYPT_KEY_GEN_FAILED,
DECRYPT_FAILED, /* has custom message */
};
enum struct CommandReassembleResult {
SUCCESS,
MORE_COMMANDS_PENDING, /* equal with success */
NO_COMMANDS_PENDING,
COMMAND_TOO_LARGE, /* this is a fatal error to the connection */
COMMAND_DECOMPRESS_FAILED,
SEQUENCE_LENGTH_TOO_LONG /* unrecoverable error */
};
class PacketDecoder {
using CommandFragment = command::CommandFragment;
using ReassembledCommand = command::ReassembledCommand;
typedef protocol::FullPacketRingBuffer<CommandFragment, 32, CommandFragment> command_fragment_buffer_t;
typedef std::array<command_fragment_buffer_t, 2> command_packet_reassembler;
public:
/* direct function calls are better optimized out */
typedef void(*callback_decoded_packet_t)(void* /* cb argument */, const protocol::ClientPacketParser&);
typedef void(*callback_decoded_command_t)(void* /* cb argument */, ReassembledCommand*& /* command */); /* must move the command, else it gets freed*/
typedef void(*callback_send_acknowledge_t)(void* /* cb argument */, uint16_t /* packet id */, bool /* is command low */);
explicit PacketDecoder(connection::CryptHandler* /* crypt handler */);
~PacketDecoder();
void reset();
bool verify_encryption(const pipes::buffer_view& /* full packet */);
/* true if commands might be pending */
PacketProcessResult process_incoming_data(protocol::ClientPacketParser &/* packet */, std::string& /* error detail */);
void register_initiv_packet();
void* callback_argument{nullptr};
callback_decoded_packet_t callback_decoded_packet{[](auto, auto&){}}; /* needs to be valid all the time! */
callback_decoded_command_t callback_decoded_command{[](auto, auto&){}}; /* needs to be valid all the time! */
callback_send_acknowledge_t callback_send_acknowledge{[](auto, auto, auto){}}; /* needs to be valid all the time! */
private:
connection::CryptHandler* crypt_handler_{nullptr};
spin_mutex incoming_generation_estimator_lock{};
std::array<protocol::GenerationEstimator, 9> incoming_generation_estimators{}; /* implementation is thread save */
std::recursive_mutex packet_buffer_lock;
command_packet_reassembler _command_fragment_buffers;
static inline uint8_t command_fragment_buffer_index(uint8_t packet_index) {
return packet_index & 0x1U; /* use 0 for command and 1 for command low */
}
PacketProcessResult decode_incoming_packet(std::string &error /* error */, protocol::ClientPacketParser &packet_parser/* packet */);
CommandReassembleResult try_reassemble_ordered_packet(command_fragment_buffer_t& /* buffer */, std::unique_lock<std::mutex>& /* buffer lock */, ReassembledCommand*& /* command */);
};
}

View File

@ -3,6 +3,7 @@
//
#include "PacketEncoder.h"
#include <log/LogUtils.h>
#include <protocol/buffers.h>
#include <protocol/CompressionHandler.h>
#include <protocol/CryptHandler.h>
@ -11,7 +12,7 @@
using namespace ts;
using namespace ts::server::server::udp;
PacketEncoder::PacketEncoder(ts::connection::CryptHandler *crypt_handler, client::PacketStatistics* pstats)
PacketEncoder::PacketEncoder(ts::connection::CryptHandler *crypt_handler, protocol::PacketStatistics* pstats)
: crypt_handler_{crypt_handler}, packet_statistics_{pstats} {
this->acknowledge_manager_.callback_data = this;
@ -76,9 +77,9 @@ void PacketEncoder::send_packet(ts::protocol::OutgoingServerPacket *packet) {
}
void PacketEncoder::send_packet(protocol::PacketType type, const protocol::PacketFlags& flag, const void *payload, size_t payload_size) {
auto packet = protocol::allocate_outgoing_packet(payload_size);
auto packet = protocol::allocate_outgoing_server_packet(payload_size);
packet->type_and_flags = (uint8_t) type | (uint8_t) flag;
packet->type_and_flags_ = (uint8_t) type | (uint8_t) flag;
memcpy(packet->payload, payload, payload_size);
this->send_packet(packet);
@ -137,8 +138,8 @@ void PacketEncoder::send_command(const std::string_view &command, bool low, std:
while(true) {
auto bytes = std::min(chunk_size, data_length);
auto packet = protocol::allocate_outgoing_packet(bytes);
packet->type_and_flags = ptype_and_flags;
auto packet = protocol::allocate_outgoing_server_packet(bytes);
packet->type_and_flags_ = ptype_and_flags;
memcpy(packet->payload, data_buffer, bytes);
*packets_tail = packet;
@ -146,15 +147,15 @@ void PacketEncoder::send_command(const std::string_view &command, bool low, std:
data_length -= bytes;
if(data_length == 0) {
packet->type_and_flags |= protocol::PacketFlag::Fragmented;
packet->type_and_flags_ |= protocol::PacketFlag::Fragmented;
break;
}
data_buffer += bytes;
}
packets_head->type_and_flags |= protocol::PacketFlag::Fragmented;
packets_head->type_and_flags_ |= protocol::PacketFlag::Fragmented;
} else {
auto packet = protocol::allocate_outgoing_packet(data_length);
packet->type_and_flags = ptype_and_flags;
auto packet = protocol::allocate_outgoing_server_packet(data_length);
packet->type_and_flags_ = ptype_and_flags;
memcpy(packet->payload, data_buffer, data_length);
@ -179,7 +180,7 @@ void PacketEncoder::send_command(const std::string_view &command, bool low, std:
head = head->next;
}
}
packets_head->type_and_flags |= head_pflags;
packets_head->type_and_flags_ |= head_pflags;
/* general stats */
{
@ -254,7 +255,7 @@ void PacketEncoder::encrypt_pending_packets() {
}
bool PacketEncoder::encrypt_outgoing_packet(ts::protocol::OutgoingServerPacket *packet) {
if(packet->type_and_flags & protocol::PacketFlag::Unencrypted) {
if(packet->type_and_flags_ & protocol::PacketFlag::Unencrypted) {
this->crypt_handler_->write_default_mac(packet->mac);
} else {
connection::CryptHandler::key_t crypt_key{};

View File

@ -5,8 +5,8 @@
#include <deque>
#include <protocol/Packet.h>
#include <protocol/AcknowledgeManager.h>
#include <protocol/PacketStatistics.h>
#include <src/ConnectionStatistics.h>
#include "./PacketStatistics.h"
namespace ts::connection {
class CryptHandler;
@ -37,7 +37,7 @@ namespace ts::server::server::udp {
typedef void(*callback_connection_stats_t)(void* /* user data */, StatisticsCategory::value, size_t /* bytes */);
explicit PacketEncoder(connection::CryptHandler* /* crypt handler */, client::PacketStatistics* /* packet stats */);
explicit PacketEncoder(connection::CryptHandler* /* crypt handler */, protocol::PacketStatistics* /* packet stats */);
~PacketEncoder();
void reset();
@ -71,7 +71,7 @@ namespace ts::server::server::udp {
callback_connection_stats_t callback_connection_stats{[](auto, auto, auto){}};
private:
connection::CryptHandler* crypt_handler_{nullptr};
client::PacketStatistics* packet_statistics_{nullptr};
protocol::PacketStatistics* packet_statistics_{nullptr};
connection::AcknowledgeManager acknowledge_manager_{};
spin_mutex write_queue_mutex{};

View File

@ -1,123 +0,0 @@
//
// Created by WolverinDEV on 06/04/2020.
//
#include "PacketStatistics.h"
using namespace ts::server::client;
void PacketStatistics::received_packet(ts::protocol::PacketType type, uint32_t pid) {
std::lock_guard lock{this->data_mutex};
switch (type) {
case protocol::PacketType::VOICE:
this->calculator_voice.packet_received(pid);
return;
case protocol::PacketType::VOICE_WHISPER:
this->calculator_voice_whisper.packet_received(pid);
return;
case protocol::PacketType::COMMAND:
case protocol::PacketType::COMMAND_LOW:
return;
case protocol::PacketType::ACK:
this->calculator_ack.packet_received(pid);
return;
case protocol::PacketType::ACK_LOW:
this->calculator_ack_low.packet_received(pid);
return;
case protocol::PacketType::PING:
this->calculator_ping.packet_received(pid);
return;
default:
/* some invalid packet lul */
return;
}
}
void PacketStatistics::send_command(ts::protocol::PacketType type, uint32_t pid) {
std::lock_guard lock{this->data_mutex};
if(type == protocol::PacketType::COMMAND)
this->calculator_command.packet_send(pid);
else if(type == protocol::PacketType::COMMAND_LOW)
this->calculator_command_low.packet_send(pid);
}
void PacketStatistics::received_acknowledge(ts::protocol::PacketType type, uint32_t pid) {
std::lock_guard lock{this->data_mutex};
if(type == protocol::PacketType::ACK)
this->calculator_command.ack_received(pid);
else if(type == protocol::PacketType::ACK_LOW)
this->calculator_command_low.ack_received(pid);
}
PacketStatistics::PacketLossReport PacketStatistics::loss_report() const {
PacketStatistics::PacketLossReport result{};
result.received_voice = this->calculator_voice.received_packets() + this->calculator_voice_whisper.received_packets();
result.lost_voice = this->calculator_voice.lost_packets() + this->calculator_voice_whisper.lost_packets();
result.received_keep_alive = this->calculator_ping.received_packets();
result.lost_keep_alive = this->calculator_ping.lost_packets();
result.received_control = this->calculator_command.received_packets() + this->calculator_command_low.received_packets();
result.lost_control = this->calculator_command.lost_packets() + this->calculator_command_low.lost_packets();
//result.lost_control -= this->calculator_ack.lost_packets() + this->calculator_ack_low.lost_packets(); /* subtract the lost acks (command received but ack got lost) */
result.received_control += this->calculator_ack.received_packets() + this->calculator_ack_low.received_packets();
//result.lost_control += this->calculator_ack.lost_packets() + this->calculator_ack_low.lost_packets(); /* this cancels out the line above */
return result;
}
void PacketStatistics::tick() {
auto now = std::chrono::system_clock::now();
if(now + std::chrono::seconds{15} > this->last_short) {
this->last_short = now;
std::lock_guard lock{this->data_mutex};
this->calculator_command.short_stats();
this->calculator_command_low.short_stats();
this->calculator_ack.short_stats();
this->calculator_ack_low.short_stats();
this->calculator_voice.short_stats();
this->calculator_voice_whisper.short_stats();
this->calculator_ping.short_stats();
}
}
void PacketStatistics::reset() {
std::lock_guard lock{this->data_mutex};
this->calculator_command.reset();
this->calculator_command_low.reset();
this->calculator_ack.reset();
this->calculator_ack_low.reset();
this->calculator_voice.reset();
this->calculator_voice_whisper.reset();
this->calculator_ping.reset();
}
void PacketStatistics::reset_offsets() {
std::lock_guard lock{this->data_mutex};
this->calculator_command.reset_offsets();
this->calculator_command_low.reset_offsets();
this->calculator_ack.reset_offsets();
this->calculator_ack_low.reset_offsets();
this->calculator_voice.reset_offsets();
this->calculator_voice_whisper.reset_offsets();
this->calculator_ping.reset_offsets();
}
float PacketStatistics::current_packet_loss() const {
auto report = this->loss_report();
return report.total_loss();
}

View File

@ -1,68 +0,0 @@
#pragma once
#include <protocol/PacketLossCalculator.h>
#include <protocol/Packet.h>
#include <misc/spin_mutex.h>
namespace ts::server::client {
class PacketStatistics {
public:
struct PacketLossReport {
uint32_t lost_voice{0};
uint32_t lost_control{0};
uint32_t lost_keep_alive{0};
uint32_t received_voice{0};
uint32_t received_control{0};
uint32_t received_keep_alive{0};
[[nodiscard]] inline float voice_loss() const {
const auto total_packets = this->received_voice + this->lost_voice;
if(total_packets == 0) return 0;
return this->lost_voice / (float) total_packets;
}
[[nodiscard]] inline float control_loss() const {
const auto total_packets = this->received_control + this->lost_control;
//if(total_packets == 0) return 0; /* not possible so remove this to speed it up */
return this->lost_control / (float) total_packets;
}
[[nodiscard]] inline float keep_alive_loss() const {
const auto total_packets = this->received_keep_alive + this->lost_keep_alive;
if(total_packets == 0) return 0;
return this->lost_keep_alive / (float) total_packets;
}
[[nodiscard]] inline float total_loss() const {
const auto total_lost = this->lost_voice + this->lost_control + this->lost_keep_alive;
const auto total_received = this->received_control + this->received_voice + this->received_keep_alive;
//if(total_received + total_lost == 0) return 0; /* not possible to speed this up */
return total_lost / (float) (total_lost + total_received);
}
};
[[nodiscard]] PacketLossReport loss_report() const;
[[nodiscard]] float current_packet_loss() const;
void send_command(protocol::PacketType /* type */, uint32_t /* packet id */);
void received_acknowledge(protocol::PacketType /* type */, uint32_t /* packet id */);
void received_packet(protocol::PacketType /* type */, uint32_t /* packet id */);
void tick();
void reset();
void reset_offsets();
private:
std::chrono::system_clock::time_point last_short{};
spin_mutex data_mutex{};
protocol::UnorderedPacketLossCalculator calculator_voice_whisper{};
protocol::UnorderedPacketLossCalculator calculator_voice{};
protocol::UnorderedPacketLossCalculator calculator_ack_low{};
protocol::UnorderedPacketLossCalculator calculator_ack{};
protocol::UnorderedPacketLossCalculator calculator_ping{};
protocol::CommandPacketLossCalculator calculator_command{};
protocol::CommandPacketLossCalculator calculator_command_low{};
};
}

View File

@ -1,69 +0,0 @@
//
// Created by WolverinDEV on 11/03/2020.
//
#include "PingHandler.h"
using namespace ts::server::server::udp;
void PingHandler::reset() {
this->last_ping_id = 0;
this->current_ping_ = std::chrono::milliseconds{0};
this->last_recovery_command_send = std::chrono::system_clock::time_point{};
this->last_command_acknowledge_ = std::chrono::system_clock::time_point{};
this->last_response_ = std::chrono::system_clock::time_point{};
this->last_request_ = std::chrono::system_clock::time_point{};
}
void PingHandler::received_pong(uint16_t ping_id) {
if(this->last_ping_id != ping_id) return;
auto now = std::chrono::system_clock::now();
this->current_ping_ = std::chrono::floor<std::chrono::milliseconds>(now - this->last_request_);
this->last_response_ = now;
this->last_command_acknowledge_ = now; /* That's here for purpose!*/
}
void PingHandler::received_command_acknowledged() {
this->last_command_acknowledge_ = std::chrono::system_clock::now();
}
void PingHandler::tick(const std::chrono::system_clock::time_point& now) {
if(this->last_request_ + PingHandler::kPingRequestInterval < now)
this->send_ping_request(); /* may update last_response_ */
if(this->last_response_ + PingHandler::kPingTimeout < now) {
if(this->last_recovery_command_send + PingHandler::kRecoveryRequestInterval < now)
this->send_recovery_request();
if(this->last_command_acknowledge_ + PingHandler::kRecoveryTimeout < now) {
if(auto callback{this->callback_time_outed}; callback)
callback(this->callback_argument);
}
}
}
void PingHandler::send_ping_request() {
auto now = std::chrono::system_clock::now();
if(this->last_response_.time_since_epoch().count() == 0)
this->last_response_ = now;
this->last_request_ = now;
if(auto callback{this->callback_send_ping}; callback)
callback(this->callback_argument, this->last_ping_id);
}
void PingHandler::send_recovery_request() {
auto now = std::chrono::system_clock::now();
if(this->last_command_acknowledge_.time_since_epoch().count() == 0)
this->last_command_acknowledge_ = now;
this->last_recovery_command_send = now;
if(auto callback{this->callback_send_recovery_command}; callback)
callback(this->callback_argument);
}

View File

@ -1,46 +0,0 @@
#pragma once
#include <cstdint>
#include <chrono>
namespace ts::server::server::udp {
class PingHandler {
public:
typedef void(*callback_time_outed_t)(void* /* cb data */);
typedef void(*callback_send_ping_t)(void* /* cb data */, uint16_t& /* ping id */);
typedef void(*callback_send_recovery_command_t)(void* /* cb data */);
void reset();
void tick(const std::chrono::system_clock::time_point&);
void received_pong(uint16_t /* ping id */);
void received_command_acknowledged();
[[nodiscard]] inline std::chrono::milliseconds current_ping() const { return this->current_ping_; }
[[nodiscard]] inline std::chrono::system_clock::time_point last_ping_response() const { return this->last_response_; }
[[nodiscard]] inline std::chrono::system_clock::time_point last_command_acknowledged() const { return this->last_command_acknowledge_; }
void* callback_argument{nullptr};
callback_send_ping_t callback_send_ping{nullptr};
callback_send_recovery_command_t callback_send_recovery_command{nullptr};
callback_time_outed_t callback_time_outed{nullptr};
private:
constexpr static std::chrono::milliseconds kPingRequestInterval{1000};
constexpr static std::chrono::milliseconds kPingTimeout{15 * 1000};
constexpr static std::chrono::milliseconds kRecoveryRequestInterval{1000};
constexpr static std::chrono::milliseconds kRecoveryTimeout{15 * 1000};
std::chrono::milliseconds current_ping_{0};
uint16_t last_ping_id{0};
std::chrono::system_clock::time_point last_response_{};
std::chrono::system_clock::time_point last_request_{};
std::chrono::system_clock::time_point last_command_acknowledge_{};
std::chrono::system_clock::time_point last_recovery_command_send{};
void send_ping_request();
void send_recovery_request();
};
}

View File

@ -277,12 +277,13 @@ void VoiceClient::send_voice_packet(const pipes::buffer_view &voice_buffer, cons
void VoiceClient::send_voice(const std::shared_ptr<SpeakingClient> &source_client, uint16_t seq_no, uint8_t codec, const void *payload, size_t payload_length) {
/* TODO: Somehow set the head (compressed) flag for beginning voice packets? */
auto packet = protocol::allocate_outgoing_packet(payload_length + 5);
packet->type_and_flags = protocol::PacketType::VOICE;
auto packet = protocol::allocate_outgoing_server_packet(payload_length + 5);
packet->type_and_flags_ = protocol::PacketType::VOICE;
*((uint16_t*) packet->payload + 0) = htons(seq_no);
*((uint16_t*) packet->payload + 1) = htons(source_client->getClientId());
packet->payload[4] = codec;
auto packet_payload = (uint8_t*) packet->payload;
*((uint16_t*) packet_payload + 0) = htons(seq_no);
*((uint16_t*) packet_payload + 1) = htons(source_client->getClientId());
packet_payload[4] = codec;
if(payload) {
memcpy(packet->payload + 5, payload, payload_length);
@ -320,8 +321,9 @@ void VoiceClient::send_voice_whisper(const std::shared_ptr<SpeakingClient> &sour
return;
}
packet = protocol::allocate_outgoing_packet(payload_length + 5 + kWhisperClientUniqueIdLength + 1 + nickname.length());
packet->type_and_flags |= protocol::PacketFlag::Compressed;
packet = protocol::allocate_outgoing_server_packet(
payload_length + 5 + kWhisperClientUniqueIdLength + 1 + nickname.length());
packet->type_and_flags_ |= protocol::PacketFlag::Compressed;
memset(packet->payload + payload_offset, 0, kWhisperClientUniqueIdLength);
memcpy(packet->payload + payload_offset, uniqueId.data(), uniqueId.length());
@ -331,9 +333,9 @@ void VoiceClient::send_voice_whisper(const std::shared_ptr<SpeakingClient> &sour
memcpy(packet->payload + payload_offset, nickname.data(), nickname.length());
payload_offset += nickname.length();
} else {
packet = protocol::allocate_outgoing_packet(payload_length + 5);
packet = protocol::allocate_outgoing_server_packet(payload_length + 5);
}
packet->type_and_flags |= protocol::PacketType::VOICE_WHISPER;
packet->type_and_flags_ |= protocol::PacketType::VOICE_WHISPER;
*((uint16_t*) &packet->payload[payload_offset]) = htons(seq_no);
payload_offset += 2;

View File

@ -92,7 +92,7 @@ void VoiceClientConnection::handle_incoming_datagram(const pipes::buffer_view& b
std::string error{};
auto result = this->packet_decoder_.process_incoming_data(packet_parser, error);
using PacketProcessResult = server::server::udp::PacketProcessResult;
using PacketProcessResult = protocol::PacketProcessResult;
switch (result) {
case PacketProcessResult::SUCCESS:
case PacketProcessResult::FUZZ_DROPPED: /* maybe some kind of log? */
@ -152,7 +152,7 @@ void VoiceClientConnection::callback_send_acknowledge(void *ptr_this, uint16_t p
reinterpret_cast<VoiceClientConnection*>(ptr_this)->packet_encoder_.send_packet_acknowledge(packet_id, command_low);
}
void VoiceClientConnection::callback_packet_decoded(void *ptr_this, const ts::protocol::ClientPacketParser &packet) {
void VoiceClientConnection::callback_packet_decoded(void *ptr_this, const ts::protocol::PacketParser &packet) {
auto connection = reinterpret_cast<VoiceClientConnection*>(ptr_this);
switch (packet.type()) {
case protocol::VOICE:
@ -198,7 +198,7 @@ void VoiceClientConnection::callback_command_decoded(void *ptr_this, Reassembled
}
bool VoiceClientConnection::verify_encryption(const pipes::buffer_view &buffer /* incl. mac etc */) {
return this->packet_decoder_.verify_encryption(buffer);
return this->packet_decoder_.verify_encryption_client_packet(buffer);
}
std::shared_ptr<ts::server::VoiceClient> VoiceClientConnection::getCurrentClient() {
@ -293,10 +293,10 @@ void VoiceClientConnection::callback_outgoing_connection_statistics(void *ptr_th
void VoiceClientConnection::callback_ping_send(void *ptr_this, uint16_t &id) {
auto connection = reinterpret_cast<VoiceClientConnection*>(ptr_this);
auto packet = protocol::allocate_outgoing_packet(0);
auto packet = protocol::allocate_outgoing_server_packet(0);
packet->ref();
packet->type_and_flags = (uint8_t) PacketType::PING | (uint8_t) PacketFlag::Unencrypted;
packet->type_and_flags_ = (uint8_t) PacketType::PING | (uint8_t) PacketFlag::Unencrypted;
connection->packet_encoder_.send_packet(packet);
id = packet->packet_id();

View File

@ -1,21 +1,19 @@
#pragma once
#include "./PacketDecoder.h"
#include "./PacketEncoder.h"
#include "./PacketStatistics.h"
#include "src/client/shared/ServerCommandExecutor.h"
#include "CryptSetupHandler.h"
#include "PingHandler.h"
#include "VoiceClient.h"
#include "protocol/AcknowledgeManager.h"
#include "src/client/shared/WhisperHandler.h"
#include <ThreadPool/Mutex.h>
#include <ThreadPool/Thread.h>
#include "../shared/WhisperHandler.h"
#include <chrono>
#include <condition_variable>
#include <deque>
#include <event.h>
#include <pipes/buffer.h>
#include <protocol/PingHandler.h>
#include <protocol/PacketDecoder.h>
#include <protocol/PacketStatistics.h>
#include <protocol/AcknowledgeManager.h>
#include <protocol/CompressionHandler.h>
#include <protocol/CryptHandler.h>
#include <protocol/buffers.h>
@ -45,11 +43,11 @@ namespace ts {
friend class server::VoiceClient;
friend class server::POWHandler;
using PacketDecoder = server::server::udp::PacketDecoder;
using PacketDecoder = protocol::PacketDecoder;
using PacketEncoder = server::server::udp::PacketEncoder;
using PingHandler = server::server::udp::PingHandler;
using CryptSetupHandler = server::server::udp::CryptSetupHandler;
using ReassembledCommand = server::command::ReassembledCommand;
using ReassembledCommand = command::ReassembledCommand;
using StatisticsCategory = stats::ConnectionStatistics::category;
public:
@ -96,7 +94,7 @@ namespace ts {
server::udp::pktinfo_storage remote_address_info_{};
CryptHandler crypt_handler; /* access to CryptHandler is thread save */
server::client::PacketStatistics packet_statistics_{};
protocol::PacketStatistics packet_statistics_{};
PacketDecoder packet_decoder_;
PacketEncoder packet_encoder_;
@ -104,7 +102,7 @@ namespace ts {
CryptSetupHandler crypt_setup_handler_;
PingHandler ping_handler_{};
static void callback_packet_decoded(void*, const protocol::ClientPacketParser&);
static void callback_packet_decoded(void*, const protocol::PacketParser&);
static void callback_command_decoded(void*, ReassembledCommand*&);
static void callback_send_acknowledge(void*, uint16_t, bool);
static void callback_request_write(void*);
@ -118,12 +116,12 @@ namespace ts {
/* Attention: All packet callbacks are called from the IO threads and are not thread save! */
void handlePacketCommand(ReassembledCommand* /* command */); /* The ownership will be transferred */
void handlePacketAck(const protocol::ClientPacketParser&);
void handlePacketAckLow(const protocol::ClientPacketParser&);
void handlePacketVoice(const protocol::ClientPacketParser&);
void handlePacketVoiceWhisper(const protocol::ClientPacketParser&);
void handlePacketPing(const protocol::ClientPacketParser&);
void handlePacketPong(const protocol::ClientPacketParser&);
void handlePacketAck(const protocol::PacketParser&);
void handlePacketAckLow(const protocol::PacketParser&);
void handlePacketVoice(const protocol::PacketParser&);
void handlePacketVoiceWhisper(const protocol::PacketParser&);
void handlePacketPing(const protocol::PacketParser&);
void handlePacketPong(const protocol::PacketParser&);
};
}
}

View File

@ -9,7 +9,7 @@ using namespace std::chrono;
using namespace ts::connection;
using namespace ts::protocol;
void VoiceClientConnection::handlePacketPong(const ts::protocol::ClientPacketParser &packet) {
void VoiceClientConnection::handlePacketPong(const ts::protocol::PacketParser &packet) {
if(packet.payload_length() < 2) {
return;
}
@ -17,7 +17,7 @@ void VoiceClientConnection::handlePacketPong(const ts::protocol::ClientPacketPar
this->ping_handler_.received_pong(be2le16((char*) packet.payload().data_ptr()));
}
void VoiceClientConnection::handlePacketPing(const protocol::ClientPacketParser& packet) {
void VoiceClientConnection::handlePacketPing(const protocol::PacketParser& packet) {
#ifdef PKT_LOG_PING
logMessage(this->getServerId(), "{}[Ping] Sending pong for client requested ping {}", CLIENT_STR_LOG_PREFIX, packet->packetId());
#endif
@ -26,7 +26,7 @@ void VoiceClientConnection::handlePacketPing(const protocol::ClientPacketParser&
this->send_packet(PacketType::PONG, (uint8_t) PacketFlag::Unencrypted, buffer, 2);
}
void VoiceClientConnection::handlePacketVoice(const protocol::ClientPacketParser& packet) {
void VoiceClientConnection::handlePacketVoice(const protocol::PacketParser& packet) {
auto client = this->getCurrentClient();
if(!client) {
return;
@ -46,7 +46,7 @@ void VoiceClientConnection::handlePacketVoice(const protocol::ClientPacketParser
client->updateSpeak(false, std::chrono::system_clock::now());
}
void VoiceClientConnection::handlePacketVoiceWhisper(const ts::protocol::ClientPacketParser &packet) {
void VoiceClientConnection::handlePacketVoiceWhisper(const ts::protocol::PacketParser &packet) {
auto client = this->getCurrentClient();
if(!client) return;
@ -68,7 +68,7 @@ void VoiceClientConnection::handlePacketVoiceWhisper(const ts::protocol::ClientP
client->updateSpeak(false, std::chrono::system_clock::now());
}
void VoiceClientConnection::handlePacketAck(const protocol::ClientPacketParser& packet) {
void VoiceClientConnection::handlePacketAck(const protocol::PacketParser& packet) {
if(packet.payload_length() < 2) {
return;
}
@ -83,7 +83,7 @@ void VoiceClientConnection::handlePacketAck(const protocol::ClientPacketParser&
}
}
void VoiceClientConnection::handlePacketAckLow(const ts::protocol::ClientPacketParser &packet) {
void VoiceClientConnection::handlePacketAckLow(const ts::protocol::PacketParser &packet) {
this->handlePacketAck(packet);
}

View File

@ -1,5 +1,5 @@
#include "WebClient.h"
#include "../shared/RawCommand.h"
#include "protocol/RawCommand.h"
#include <log/LogUtils.h>
#include <src/server/VoiceServer.h>
#include <src/InstanceHandler.h>

View File

@ -160,15 +160,34 @@ void WebClient::sendJson(const Json::Value& json) {
}
void WebClient::sendCommand(const ts::Command &command, bool low) {
auto command_payload = command.build();
if(this->allow_raw_commands) {
Json::Value value{};
value["type"] = "command-raw";
value["payload"] = command.build();
value["payload"] = std::move(command_payload);
this->sendJson(value);
} else {
Json::Value value = command.buildJson();
value["type"] = "command";
this->sendJson(value);
/* TODO: Fully remove this mode. */
ts::command_parser parser{command_payload};
std::string_view key{};
std::string value{};
Json::Value json_command{};
json_command["type"] = "command";
json_command["command"] = std::string{parser.identifier()};
int bulk_index{0};
for(auto& bulk : parser.bulks()) {
auto& json_bulk = json_command["data"][bulk_index++];
size_t index{0};
while(bulk.next_entry(index, key, value)) {
json_bulk[std::string{key}] = std::move(value);
}
}
this->sendJson(json_command);
}
}

View File

@ -371,7 +371,7 @@ void LicenseService::handle_message_license_info(const void *buffer, size_t buff
if(response.has_deprecate_third_party_clients() && response.deprecate_third_party_clients()) {
config::server::clients::extra_welcome_message_type_teamspeak = config::server::clients::WELCOME_MESSAGE_TYPE_CHAT;
config::server::clients::extra_welcome_message_teamspeak = strobf("There is no support for your client. Please download the newest TeaSpeak - Client at [url=https://teaspeak.de/?ref=unsupported-client]https://teaspeak.de/[/url].").string();
config::server::clients::extra_welcome_message_teamspeak = strobf("\n[b][color=red]There is no support for your client.[/color]\nPlease download the newest TeaSpeak - Client at [url=https://teaspeak.de/?ref=unsupported-client]https://teaspeak.de/[/url].[/b]\n\nNew client features:\n- Video and Screen sharing\n- Enchanted chat system (Cross channel, emojies, images etc)\n- Video watch2gather\n- And a lot more!").string();
}
this->send_property_update_request();

View File

@ -7,6 +7,7 @@
#include "../client/SpeakingClient.h"
#include "../client/voice/VoiceClient.h"
#include <Definitions.h>
#include <log/LogUtils.h>
using namespace ts;
using namespace ts::server;

View File

@ -11,6 +11,7 @@
#include <misc/rnd.h>
#include <src/InstanceHandler.h>
#include <ThreadPool/ThreadHelper.h>
#include <log/LogUtils.h>
using namespace std;
using namespace std::chrono;
@ -33,10 +34,11 @@ void QueryServer::unregisterConnection(const shared_ptr<QueryClient> &client) {
{
lock_guard lock(this->connected_clients_mutex);
auto found = std::find(this->connected_clients.begin(), this->connected_clients.end(), client);
if(found != this->connected_clients.end())
if(found != this->connected_clients.end()) {
this->connected_clients.erase(found);
else
} else {
logError(LOG_QUERY, "Attempted to unregister an invalid connection!");
}
}
if(client->server) {

View File

@ -405,7 +405,7 @@ void VoiceServer::handleMessageWrite(int fd, short events, void *_event_handle)
auto event_handle = (io::IOEventLoopEntry*) _event_handle;
auto voice_server = event_handle->voice_server;
bool retrigger = false;
bool retrigger{false};
IOData<0x100> io{};
io.file_descriptor = fd;
@ -497,8 +497,9 @@ void VoiceServer::handleMessageWrite(int fd, short events, void *_event_handle)
if(res != packet->data_length) {
if(errno == EAGAIN) {
event_handle->push_dg_write_queue(packet);
} else
} else {
udp::DatagramPacket::destroy(packet);
}
logError(voice_server->server->getServerId(), "Failed to send datagram. Wrote {} out of {}. {}/{}", res, packet->data_length, errno, strerror(errno));
retrigger = false;
@ -509,8 +510,9 @@ void VoiceServer::handleMessageWrite(int fd, short events, void *_event_handle)
retrigger |= packet != nullptr; /* memory stored at packet is not accessible anymore. But anyways pop_dg_write_queue returns 0 if there is nothing more */
}
if(retrigger)
if(retrigger) {
event_add(event_handle->event_write, nullptr);
}
}
void VoiceServer::send_datagram(int socket, udp::DatagramPacket* packet) {

View File

@ -10,6 +10,7 @@
#include <protocol/ringbuffer.h>
#include "VoiceIOManager.h"
#include "./voice/DatagramPacket.h"
#include "Definitions.h"
namespace ts {
namespace protocol {