A lot of updates
This commit is contained in:
parent
1de3eee117
commit
aaea9b9339
2
music
2
music
@ -1 +1 @@
|
|||||||
Subproject commit 6bdb628586efd7f61c6746391c664c335b8b6d44
|
Subproject commit 7beec96f4b9f00b3e63bc6d092ce6c671ea3c0d5
|
@ -62,7 +62,7 @@ set(SERVER_SOURCE_FILES
|
|||||||
src/client/command_handler/misc.cpp
|
src/client/command_handler/misc.cpp
|
||||||
|
|
||||||
src/client/ConnectedClientNotifyHandler.cpp
|
src/client/ConnectedClientNotifyHandler.cpp
|
||||||
src/ServerManager.cpp
|
src/VirtualServerManager.cpp
|
||||||
src/server/file/FileServer.cpp
|
src/server/file/FileServer.cpp
|
||||||
src/channel/ServerChannel.cpp
|
src/channel/ServerChannel.cpp
|
||||||
src/channel/ClientChannelView.cpp
|
src/channel/ClientChannelView.cpp
|
||||||
@ -235,7 +235,7 @@ target_link_libraries(PermMapHelper
|
|||||||
|
|
||||||
SET(CPACK_PACKAGE_VERSION_MAJOR "1")
|
SET(CPACK_PACKAGE_VERSION_MAJOR "1")
|
||||||
SET(CPACK_PACKAGE_VERSION_MINOR "4")
|
SET(CPACK_PACKAGE_VERSION_MINOR "4")
|
||||||
SET(CPACK_PACKAGE_VERSION_PATCH "6")
|
SET(CPACK_PACKAGE_VERSION_PATCH "7")
|
||||||
if (BUILD_TYPE_NAME EQUAL OFF)
|
if (BUILD_TYPE_NAME EQUAL OFF)
|
||||||
SET(CPACK_PACKAGE_VERSION_DATA "beta")
|
SET(CPACK_PACKAGE_VERSION_DATA "beta")
|
||||||
elseif (BUILD_TYPE_NAME STREQUAL "")
|
elseif (BUILD_TYPE_NAME STREQUAL "")
|
||||||
|
@ -48,14 +48,32 @@ namespace ts {
|
|||||||
UNKNOWN
|
UNKNOWN
|
||||||
};
|
};
|
||||||
|
|
||||||
|
constexpr static std::array<category::value, 16> lookup_table{
|
||||||
|
VOICE, /* Voice */
|
||||||
|
VOICE, /* VoiceWhisper */
|
||||||
|
COMMAND, /* Command */
|
||||||
|
COMMAND, /* CommandLow */
|
||||||
|
ACK, /* Ping */
|
||||||
|
ACK, /* Pong */
|
||||||
|
ACK, /* Ack */
|
||||||
|
ACK, /* AckLow */
|
||||||
|
COMMAND, /* */
|
||||||
|
|
||||||
|
UNKNOWN,
|
||||||
|
UNKNOWN,
|
||||||
|
UNKNOWN,
|
||||||
|
UNKNOWN,
|
||||||
|
UNKNOWN,
|
||||||
|
UNKNOWN
|
||||||
|
};
|
||||||
|
|
||||||
|
/* much faster than a switch */
|
||||||
|
inline static category::value from_type(uint8_t type){
|
||||||
|
return lookup_table[type & 0xFU];
|
||||||
|
}
|
||||||
|
|
||||||
inline static category::value from_type(const protocol::PacketTypeInfo& type){
|
inline static category::value from_type(const protocol::PacketTypeInfo& type){
|
||||||
if(type == protocol::PacketTypeInfo::Command || type == protocol::PacketTypeInfo::CommandLow)
|
return from_type(type.type());
|
||||||
return value::COMMAND;
|
|
||||||
else if(type == protocol::PacketTypeInfo::Ack || type == protocol::PacketTypeInfo::AckLow)
|
|
||||||
return value::ACK;
|
|
||||||
else if(type == protocol::PacketTypeInfo::Voice || type == protocol::PacketTypeInfo::VoiceWhisper)
|
|
||||||
return value::VOICE;
|
|
||||||
return value::UNKNOWN;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
explicit ConnectionStatistics(const std::shared_ptr<ConnectionStatistics>& /* root */, bool /* spawn properties */);
|
explicit ConnectionStatistics(const std::shared_ptr<ConnectionStatistics>& /* root */, bool /* spawn properties */);
|
||||||
|
@ -378,7 +378,7 @@ FwIDAQAB
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this->voiceServerManager = new ServerManager(this);
|
this->voiceServerManager = new VirtualServerManager(this);
|
||||||
if (!this->voiceServerManager->initialize(true)) {
|
if (!this->voiceServerManager->initialize(true)) {
|
||||||
logCritical(LOG_INSTANCE, "Could not load servers!");
|
logCritical(LOG_INSTANCE, "Could not load servers!");
|
||||||
delete this->voiceServerManager;
|
delete this->voiceServerManager;
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <sql/SqlQuery.h>
|
#include <sql/SqlQuery.h>
|
||||||
#include <Properties.h>
|
#include <Properties.h>
|
||||||
#include "ServerManager.h"
|
#include "VirtualServerManager.h"
|
||||||
#include "../../license/shared/LicenseRequest.h"
|
#include "../../license/shared/LicenseRequest.h"
|
||||||
#include "lincense/LicenseHelper.h"
|
#include "lincense/LicenseHelper.h"
|
||||||
#include <ssl/SSLManager.h>
|
#include <ssl/SSLManager.h>
|
||||||
@ -38,7 +38,7 @@ namespace ts {
|
|||||||
std::shared_ptr<ts::ServerChannelTree> getChannelTree() { return this->default_tree; }
|
std::shared_ptr<ts::ServerChannelTree> getChannelTree() { return this->default_tree; }
|
||||||
std::shared_mutex& getChannelTreeLock() { return this->default_tree_lock; }
|
std::shared_mutex& getChannelTreeLock() { return this->default_tree_lock; }
|
||||||
|
|
||||||
ServerManager* getVoiceServerManager(){ return this->voiceServerManager; }
|
VirtualServerManager* getVoiceServerManager(){ return this->voiceServerManager; }
|
||||||
FileServer* getFileServer(){ return fileServer; }
|
FileServer* getFileServer(){ return fileServer; }
|
||||||
QueryServer* getQueryServer(){ return queryServer; }
|
QueryServer* getQueryServer(){ return queryServer; }
|
||||||
DatabaseHelper* databaseHelper(){ return this->dbHelper; }
|
DatabaseHelper* databaseHelper(){ return this->dbHelper; }
|
||||||
@ -107,7 +107,7 @@ namespace ts {
|
|||||||
|
|
||||||
FileServer* fileServer = nullptr;
|
FileServer* fileServer = nullptr;
|
||||||
QueryServer* queryServer = nullptr;
|
QueryServer* queryServer = nullptr;
|
||||||
ServerManager* voiceServerManager = nullptr;
|
VirtualServerManager* voiceServerManager = nullptr;
|
||||||
DatabaseHelper* dbHelper = nullptr;
|
DatabaseHelper* dbHelper = nullptr;
|
||||||
BanManager* banMgr = nullptr;
|
BanManager* banMgr = nullptr;
|
||||||
ssl::SSLManager* sslMgr = nullptr;
|
ssl::SSLManager* sslMgr = nullptr;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <log/LogUtils.h>
|
#include <log/LogUtils.h>
|
||||||
#include "ServerManager.h"
|
#include "VirtualServerManager.h"
|
||||||
#include "src/server/VoiceServer.h"
|
#include "src/server/VoiceServer.h"
|
||||||
#include "InstanceHandler.h"
|
#include "InstanceHandler.h"
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
#include <log/LogUtils.h>
|
#include <log/LogUtils.h>
|
||||||
#include <misc/std_unique_ptr.h>
|
#include <misc/std_unique_ptr.h>
|
||||||
#include <Properties.h>
|
#include <Properties.h>
|
||||||
#include "ServerManager.h"
|
#include "VirtualServerManager.h"
|
||||||
#include "src/server/VoiceServer.h"
|
#include "src/server/VoiceServer.h"
|
||||||
#include "InstanceHandler.h"
|
#include "InstanceHandler.h"
|
||||||
#include "InstanceHandler.h"
|
#include "InstanceHandler.h"
|
||||||
@ -163,9 +163,9 @@ struct SnapshotPermissionEntry {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::shared_ptr<VirtualServer> ServerManager::createServerFromSnapshot(shared_ptr<VirtualServer> old, std::string host,
|
std::shared_ptr<VirtualServer> VirtualServerManager::createServerFromSnapshot(shared_ptr<VirtualServer> old, std::string host,
|
||||||
uint16_t port, const ts::Command &arguments,
|
uint16_t port, const ts::Command &arguments,
|
||||||
std::string &error) {
|
std::string &error) {
|
||||||
ServerId serverId = 0;
|
ServerId serverId = 0;
|
||||||
map<ClientDbId, map<ChannelId, ClientDbId>> channelGroupRelations; //cid is the new cgid
|
map<ClientDbId, map<ChannelId, ClientDbId>> channelGroupRelations; //cid is the new cgid
|
||||||
map<GroupId, GroupId> channelGroupMapping;
|
map<GroupId, GroupId> channelGroupMapping;
|
||||||
@ -767,7 +767,7 @@ struct DatabaseMusicbot {
|
|||||||
std::string bot_unique_id;
|
std::string bot_unique_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
bool ServerManager::createServerSnapshot(Command &cmd, shared_ptr<VirtualServer> server, int version, std::string &error) {
|
bool VirtualServerManager::createServerSnapshot(Command &cmd, shared_ptr<VirtualServer> server, int version, std::string &error) {
|
||||||
|
|
||||||
int index = 0;
|
int index = 0;
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include <breakpad/client/linux/handler/exception_handler.h>
|
#include <breakpad/client/linux/handler/exception_handler.h>
|
||||||
#include "VirtualServer.h"
|
#include "VirtualServer.h"
|
||||||
#include "SignalHandler.h"
|
#include "SignalHandler.h"
|
||||||
#include "ServerManager.h"
|
#include "VirtualServerManager.h"
|
||||||
#include "InstanceHandler.h"
|
#include "InstanceHandler.h"
|
||||||
#include "ShutdownHelper.h"
|
#include "ShutdownHelper.h"
|
||||||
#include <csignal>
|
#include <csignal>
|
||||||
|
@ -575,17 +575,6 @@ OnlineClientReport VirtualServer::onlineStats() {
|
|||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ConnectedClient> VirtualServer::findClient(sockaddr_in *addr) {
|
|
||||||
lock_guard lock(this->clients.lock);
|
|
||||||
for(const auto& elm : this->clients.clients) {
|
|
||||||
if(elm && elm->isAddressV4())
|
|
||||||
if(elm->getAddressV4()->sin_addr.s_addr == addr->sin_addr.s_addr)
|
|
||||||
if(elm->getAddressV4()->sin_port == addr->sin_port)
|
|
||||||
return elm;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<ConnectedClient> VirtualServer::findClient(uint16_t client_id) {
|
std::shared_ptr<ConnectedClient> VirtualServer::findClient(uint16_t client_id) {
|
||||||
lock_guard lock(this->clients.lock);
|
lock_guard lock(this->clients.lock);
|
||||||
if(this->clients.clients.size() > client_id)
|
if(this->clients.clients.size() > client_id)
|
||||||
|
@ -134,7 +134,7 @@ namespace ts {
|
|||||||
friend class SpeakingClient;
|
friend class SpeakingClient;
|
||||||
friend class music::MusicBotManager;
|
friend class music::MusicBotManager;
|
||||||
friend class InstanceHandler;
|
friend class InstanceHandler;
|
||||||
friend class ServerManager;
|
friend class VirtualServerManager;
|
||||||
public:
|
public:
|
||||||
VirtualServer(ServerId serverId, sql::SqlManager*);
|
VirtualServer(ServerId serverId, sql::SqlManager*);
|
||||||
~VirtualServer();
|
~VirtualServer();
|
||||||
@ -149,7 +149,6 @@ namespace ts {
|
|||||||
size_t onlineClients();
|
size_t onlineClients();
|
||||||
OnlineClientReport onlineStats();
|
OnlineClientReport onlineStats();
|
||||||
size_t onlineChannels(){ return this->channelTree->channel_count(); }
|
size_t onlineChannels(){ return this->channelTree->channel_count(); }
|
||||||
std::shared_ptr<ConnectedClient> findClient(sockaddr_in* addr);
|
|
||||||
std::shared_ptr<ConnectedClient> findClient(ClientId clientId);
|
std::shared_ptr<ConnectedClient> findClient(ClientId clientId);
|
||||||
std::deque<std::shared_ptr<ConnectedClient>> findClientsByCldbId(ClientDbId cldbId);
|
std::deque<std::shared_ptr<ConnectedClient>> findClientsByCldbId(ClientDbId cldbId);
|
||||||
std::deque<std::shared_ptr<ConnectedClient>> findClientsByUid(ClientUid uid);
|
std::deque<std::shared_ptr<ConnectedClient>> findClientsByUid(ClientUid uid);
|
||||||
|
@ -1,16 +1,17 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <log/LogUtils.h>
|
#include <log/LogUtils.h>
|
||||||
#include "ServerManager.h"
|
#include "VirtualServerManager.h"
|
||||||
#include "src/server/VoiceServer.h"
|
#include "src/server/VoiceServer.h"
|
||||||
#include "InstanceHandler.h"
|
#include "InstanceHandler.h"
|
||||||
#include "src/server/file/FileServer.h"
|
#include "src/server/file/FileServer.h"
|
||||||
#include "src/client/ConnectedClient.h"
|
#include "src/client/ConnectedClient.h"
|
||||||
|
#include <ThreadPool/ThreadHelper.h>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
using namespace std::chrono;
|
using namespace std::chrono;
|
||||||
using namespace ts::server;
|
using namespace ts::server;
|
||||||
|
|
||||||
ServerManager::ServerManager(InstanceHandler* handle) : handle(handle) {
|
VirtualServerManager::VirtualServerManager(InstanceHandler* handle) : handle(handle) {
|
||||||
this->puzzles = new protocol::PuzzleManager();
|
this->puzzles = new protocol::PuzzleManager();
|
||||||
this->handshakeTickers = new threads::Scheduler(1, "handshake ticker");
|
this->handshakeTickers = new threads::Scheduler(1, "handshake ticker");
|
||||||
this->execute_loop = new event::EventExecutor("executor #");
|
this->execute_loop = new event::EventExecutor("executor #");
|
||||||
@ -20,7 +21,7 @@ ServerManager::ServerManager(InstanceHandler* handle) : handle(handle) {
|
|||||||
this->handshakeTickers->schedule("ticker", [&](){ this->tickHandshakeClients(); }, seconds(1));
|
this->handshakeTickers->schedule("ticker", [&](){ this->tickHandshakeClients(); }, seconds(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerManager::~ServerManager() {
|
VirtualServerManager::~VirtualServerManager() {
|
||||||
this->state = State::STOPPED;
|
this->state = State::STOPPED;
|
||||||
{
|
{
|
||||||
threads::MutexLock lock(this->instanceLock);
|
threads::MutexLock lock(this->instanceLock);
|
||||||
@ -29,9 +30,10 @@ ServerManager::~ServerManager() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
this->acknowledge.condition.notify_all();
|
this->acknowledge.condition.notify_all();
|
||||||
if(this->acknowledge.thread)
|
if(!threads::timed_join(this->acknowledge.executor,std::chrono::seconds{2})) {
|
||||||
this->acknowledge.thread->join();
|
logCritical(LOG_GENERAL, "Failed to shutdown packet resend thread.");
|
||||||
delete this->acknowledge.thread;
|
this->acknowledge.executor.detach();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete this->puzzles;
|
delete this->puzzles;
|
||||||
@ -58,7 +60,7 @@ ServerManager::~ServerManager() {
|
|||||||
this->_ioManager = nullptr;
|
this->_ioManager = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ServerManager::initialize(bool autostart) {
|
bool VirtualServerManager::initialize(bool autostart) {
|
||||||
this->execute_loop->initialize(1);
|
this->execute_loop->initialize(1);
|
||||||
|
|
||||||
this->state = State::STARTING;
|
this->state = State::STARTING;
|
||||||
@ -83,7 +85,7 @@ bool ServerManager::initialize(bool autostart) {
|
|||||||
|
|
||||||
auto beg = system_clock::now();
|
auto beg = system_clock::now();
|
||||||
size_t server_count = 0;
|
size_t server_count = 0;
|
||||||
sql::command(this->handle->getSql(), "SELECT `serverId`, `host`, `port` FROM `servers`").query([&](ServerManager* mgr, int length, std::string* values, std::string* columns){
|
sql::command(this->handle->getSql(), "SELECT `serverId`, `host`, `port` FROM `servers`").query([&](VirtualServerManager* mgr, int length, std::string* values, std::string* columns){
|
||||||
ServerId id = 0;
|
ServerId id = 0;
|
||||||
std::string host;
|
std::string host;
|
||||||
uint16_t port = 0;
|
uint16_t port = 0;
|
||||||
@ -158,7 +160,7 @@ bool ServerManager::initialize(bool autostart) {
|
|||||||
this->adjust_executor_threads();
|
this->adjust_executor_threads();
|
||||||
|
|
||||||
{
|
{
|
||||||
this->acknowledge.thread = new threads::Thread(THREAD_SAVE_OPERATIONS, [&] {
|
this->acknowledge.executor = std::thread([&]{
|
||||||
system_clock::time_point next_execute = system_clock::now() + milliseconds(500);
|
system_clock::time_point next_execute = system_clock::now() + milliseconds(500);
|
||||||
while(this->state == State::STARTED || this->state == State::STARTING) {
|
while(this->state == State::STARTED || this->state == State::STARTING) {
|
||||||
unique_lock<mutex> lock(this->acknowledge.lock);
|
unique_lock<mutex> lock(this->acknowledge.lock);
|
||||||
@ -180,14 +182,14 @@ bool ServerManager::initialize(bool autostart) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<VirtualServer> ServerManager::findServerById(ServerId sid) {
|
shared_ptr<VirtualServer> VirtualServerManager::findServerById(ServerId sid) {
|
||||||
for(auto server : this->serverInstances())
|
for(auto server : this->serverInstances())
|
||||||
if(server->getServerId() == sid)
|
if(server->getServerId() == sid)
|
||||||
return server;
|
return server;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<VirtualServer> ServerManager::findServerByPort(uint16_t port) {
|
shared_ptr<VirtualServer> VirtualServerManager::findServerByPort(uint16_t port) {
|
||||||
for(const auto& server : this->serverInstances()){
|
for(const auto& server : this->serverInstances()){
|
||||||
if(server->properties()[property::VIRTUALSERVER_PORT] == port) return server;
|
if(server->properties()[property::VIRTUALSERVER_PORT] == port) return server;
|
||||||
if(server->running() && server->getVoiceServer())
|
if(server->running() && server->getVoiceServer())
|
||||||
@ -197,7 +199,7 @@ shared_ptr<VirtualServer> ServerManager::findServerByPort(uint16_t port) {
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t ServerManager::next_available_port() {
|
uint16_t VirtualServerManager::next_available_port() {
|
||||||
auto instances = this->serverInstances();
|
auto instances = this->serverInstances();
|
||||||
deque<uint16_t> unallowed_ports;
|
deque<uint16_t> unallowed_ports;
|
||||||
for(const auto& instance : instances) {
|
for(const auto& instance : instances) {
|
||||||
@ -227,7 +229,7 @@ uint16_t ServerManager::next_available_port() {
|
|||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
ts::ServerId ServerManager::next_available_server_id(bool& success) {
|
ts::ServerId VirtualServerManager::next_available_server_id(bool& success) {
|
||||||
auto server_id_base = this->handle->properties()[property::SERVERINSTANCE_VIRTUAL_SERVER_ID_INDEX].as<ServerId>();
|
auto server_id_base = this->handle->properties()[property::SERVERINSTANCE_VIRTUAL_SERVER_ID_INDEX].as<ServerId>();
|
||||||
if(server_id_base > 65530) {
|
if(server_id_base > 65530) {
|
||||||
success = false;
|
success = false;
|
||||||
@ -264,7 +266,7 @@ ts::ServerId ServerManager::next_available_server_id(bool& success) {
|
|||||||
return serverId;
|
return serverId;
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerReport ServerManager::report() {
|
ServerReport VirtualServerManager::report() {
|
||||||
ServerReport result{};
|
ServerReport result{};
|
||||||
for(const auto& sr : this->serverInstances()) {
|
for(const auto& sr : this->serverInstances()) {
|
||||||
result.avariable++;
|
result.avariable++;
|
||||||
@ -279,7 +281,7 @@ ServerReport ServerManager::report() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
OnlineClientReport ServerManager::clientReport() {
|
OnlineClientReport VirtualServerManager::clientReport() {
|
||||||
OnlineClientReport result{};
|
OnlineClientReport result{};
|
||||||
for(const auto& server : this->serverInstances()) {
|
for(const auto& server : this->serverInstances()) {
|
||||||
if(!server->running()) continue;
|
if(!server->running()) continue;
|
||||||
@ -292,21 +294,21 @@ OnlineClientReport ServerManager::clientReport() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ServerManager::runningServers() {
|
size_t VirtualServerManager::runningServers() {
|
||||||
size_t res = 0;
|
size_t res = 0;
|
||||||
for(const auto& sr : this->serverInstances())
|
for(const auto& sr : this->serverInstances())
|
||||||
if(sr->running()) res++;
|
if(sr->running()) res++;
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t ServerManager::usedSlots() {
|
size_t VirtualServerManager::usedSlots() {
|
||||||
size_t res = 0;
|
size_t res = 0;
|
||||||
for(const auto& sr : this->serverInstances())
|
for(const auto& sr : this->serverInstances())
|
||||||
res += sr->properties()[property::VIRTUALSERVER_MAXCLIENTS].as<size_t>();
|
res += sr->properties()[property::VIRTUALSERVER_MAXCLIENTS].as<size_t>();
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
shared_ptr<VirtualServer> ServerManager::createServer(std::string hosts, uint16_t port) {
|
shared_ptr<VirtualServer> VirtualServerManager::createServer(std::string hosts, uint16_t port) {
|
||||||
bool sid_success = false;
|
bool sid_success = false;
|
||||||
|
|
||||||
ServerId serverId = this->next_available_server_id(sid_success);
|
ServerId serverId = this->next_available_server_id(sid_success);
|
||||||
@ -337,7 +339,7 @@ shared_ptr<VirtualServer> ServerManager::createServer(std::string hosts, uint16_
|
|||||||
return server;
|
return server;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ServerManager::deleteServer(shared_ptr<VirtualServer> server) {
|
bool VirtualServerManager::deleteServer(shared_ptr<VirtualServer> server) {
|
||||||
{
|
{
|
||||||
threads::MutexLock l(this->instanceLock);
|
threads::MutexLock l(this->instanceLock);
|
||||||
bool found = false;
|
bool found = false;
|
||||||
@ -389,7 +391,7 @@ bool ServerManager::deleteServer(shared_ptr<VirtualServer> server) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerManager::executeAutostart() {
|
void VirtualServerManager::executeAutostart() {
|
||||||
threads::MutexLock l(this->instanceLock);
|
threads::MutexLock l(this->instanceLock);
|
||||||
auto lastStart = system_clock::time_point();
|
auto lastStart = system_clock::time_point();
|
||||||
for(const auto& server : this->instances){
|
for(const auto& server : this->instances){
|
||||||
@ -408,7 +410,7 @@ void ServerManager::executeAutostart() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerManager::shutdownAll(const std::string& msg) {
|
void VirtualServerManager::shutdownAll(const std::string& msg) {
|
||||||
for(const auto &server : this->serverInstances())
|
for(const auto &server : this->serverInstances())
|
||||||
server->preStop(msg);
|
server->preStop(msg);
|
||||||
for(const auto &server : this->serverInstances()){
|
for(const auto &server : this->serverInstances()){
|
||||||
@ -418,7 +420,7 @@ void ServerManager::shutdownAll(const std::string& msg) {
|
|||||||
this->execute_loop->shutdown();
|
this->execute_loop->shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerManager::tickHandshakeClients() {
|
void VirtualServerManager::tickHandshakeClients() {
|
||||||
for(const auto& server : this->serverInstances()) {
|
for(const auto& server : this->serverInstances()) {
|
||||||
auto vserver = server->getVoiceServer();
|
auto vserver = server->getVoiceServer();
|
||||||
if(vserver)
|
if(vserver)
|
@ -18,7 +18,7 @@ namespace ts {
|
|||||||
size_t onlineClients;
|
size_t onlineClients;
|
||||||
size_t onlineChannels;
|
size_t onlineChannels;
|
||||||
};
|
};
|
||||||
class ServerManager {
|
class VirtualServerManager {
|
||||||
public:
|
public:
|
||||||
enum State {
|
enum State {
|
||||||
STOPPED,
|
STOPPED,
|
||||||
@ -27,8 +27,8 @@ namespace ts {
|
|||||||
STOPPING
|
STOPPING
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit ServerManager(InstanceHandler*);
|
explicit VirtualServerManager(InstanceHandler*);
|
||||||
~ServerManager();
|
~VirtualServerManager();
|
||||||
|
|
||||||
bool initialize(bool execute_autostart = true);
|
bool initialize(bool execute_autostart = true);
|
||||||
|
|
||||||
@ -57,8 +57,6 @@ namespace ts {
|
|||||||
bool createServerSnapshot(Command &cmd, std::shared_ptr<VirtualServer> server, int version, std::string &error);
|
bool createServerSnapshot(Command &cmd, std::shared_ptr<VirtualServer> server, int version, std::string &error);
|
||||||
std::shared_ptr<VirtualServer> createServerFromSnapshot(std::shared_ptr<VirtualServer> old, std::string, uint16_t, const ts::Command &, std::string &);
|
std::shared_ptr<VirtualServer> createServerFromSnapshot(std::shared_ptr<VirtualServer> old, std::string, uint16_t, const ts::Command &, std::string &);
|
||||||
|
|
||||||
size_t maxSlotLimit(){ return 254; }
|
|
||||||
|
|
||||||
protocol::PuzzleManager* rsaPuzzles() { return this->puzzles; }
|
protocol::PuzzleManager* rsaPuzzles() { return this->puzzles; }
|
||||||
|
|
||||||
event::EventExecutor* get_join_loop() { return this->join_loop; }
|
event::EventExecutor* get_join_loop() { return this->join_loop; }
|
||||||
@ -90,7 +88,7 @@ namespace ts {
|
|||||||
io::VoiceIOManager* _ioManager = nullptr;
|
io::VoiceIOManager* _ioManager = nullptr;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
threads::Thread* thread = nullptr;
|
std::thread executor{};
|
||||||
std::condition_variable condition;
|
std::condition_variable condition;
|
||||||
std::mutex lock;
|
std::mutex lock;
|
||||||
} acknowledge;
|
} acknowledge;
|
@ -68,7 +68,7 @@ namespace ts {
|
|||||||
friend class SpeakingClient;
|
friend class SpeakingClient;
|
||||||
friend class connection::VoiceClientConnection;
|
friend class connection::VoiceClientConnection;
|
||||||
friend class ts::GroupManager;
|
friend class ts::GroupManager;
|
||||||
friend class ServerManager;
|
friend class VirtualServerManager;
|
||||||
public:
|
public:
|
||||||
explicit ConnectedClient(sql::SqlManager*, const std::shared_ptr<VirtualServer>& server);
|
explicit ConnectedClient(sql::SqlManager*, const std::shared_ptr<VirtualServer>& server);
|
||||||
~ConnectedClient() override;
|
~ConnectedClient() override;
|
||||||
|
@ -642,8 +642,8 @@ bool ConnectedClient::handle_text_command(
|
|||||||
auto id = vc->getConnection()->getPacketIdManager().currentPacketId(type);
|
auto id = vc->getConnection()->getPacketIdManager().currentPacketId(type);
|
||||||
auto gen = vc->getConnection()->getPacketIdManager().generationId(type);
|
auto gen = vc->getConnection()->getPacketIdManager().generationId(type);
|
||||||
send_message(_this.lock(), " OUT " + type.name() + " => generation: " + to_string(gen) + " id: " + to_string(id));
|
send_message(_this.lock(), " OUT " + type.name() + " => generation: " + to_string(gen) + " id: " + to_string(id));
|
||||||
auto& buffer = vc->getConnection()->packet_buffers()[type.type()];
|
//auto& buffer = vc->getConnection()->packet_buffers()[type.type()];
|
||||||
send_message(_this.lock(), " IN " + type.name() + " => generation: " + to_string(buffer.generation(0)) + " id: " + to_string(buffer.current_index()));
|
//send_message(_this.lock(), " IN " + type.name() + " => generation: " + to_string(buffer.generation(0)) + " id: " + to_string(buffer.current_index()));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
} else if(TARG(0, "disconnect")) {
|
} else if(TARG(0, "disconnect")) {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "SpeakingClient.h"
|
#include "SpeakingClient.h"
|
||||||
#include <misc/endianness.h>
|
#include <misc/endianness.h>
|
||||||
#include <src/ServerManager.h>
|
#include <src/VirtualServerManager.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <src/InstanceHandler.h>
|
#include <src/InstanceHandler.h>
|
||||||
#include <misc/base64.h>
|
#include <misc/base64.h>
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include "query/Command.h"
|
#include "query/Command.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <src/server/QueryServer.h>
|
#include <src/server/QueryServer.h>
|
||||||
#include <src/ServerManager.h>
|
#include <src/VirtualServerManager.h>
|
||||||
#include <src/InstanceHandler.h>
|
#include <src/InstanceHandler.h>
|
||||||
#include <log/LogUtils.h>
|
#include <log/LogUtils.h>
|
||||||
#include <misc/digest.h>
|
#include <misc/digest.h>
|
||||||
@ -576,7 +576,7 @@ command_result QueryClient::handleCommandServerCreate(Command& cmd) {
|
|||||||
CMD_RESET_IDLE;
|
CMD_RESET_IDLE;
|
||||||
ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_virtualserver_create, 1);
|
ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_virtualserver_create, 1);
|
||||||
|
|
||||||
if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED) {
|
if(serverInstance->getVoiceServerManager()->getState() != VirtualServerManager::STARTED) {
|
||||||
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -653,7 +653,7 @@ command_result QueryClient::handleCommandServerDelete(Command& cmd) {
|
|||||||
CMD_RESET_IDLE;
|
CMD_RESET_IDLE;
|
||||||
ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_virtualserver_delete, 1);
|
ACTION_REQUIRES_INSTANCE_PERMISSION(permission::b_virtualserver_delete, 1);
|
||||||
|
|
||||||
if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED)
|
if(serverInstance->getVoiceServerManager()->getState() != VirtualServerManager::STARTED)
|
||||||
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
||||||
|
|
||||||
auto server = serverInstance->getVoiceServerManager()->findServerById(cmd["sid"]);
|
auto server = serverInstance->getVoiceServerManager()->findServerById(cmd["sid"]);
|
||||||
@ -665,7 +665,7 @@ command_result QueryClient::handleCommandServerDelete(Command& cmd) {
|
|||||||
command_result QueryClient::handleCommandServerStart(Command& cmd) {
|
command_result QueryClient::handleCommandServerStart(Command& cmd) {
|
||||||
CMD_RESET_IDLE;
|
CMD_RESET_IDLE;
|
||||||
|
|
||||||
if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED)
|
if(serverInstance->getVoiceServerManager()->getState() != VirtualServerManager::STARTED)
|
||||||
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
||||||
|
|
||||||
auto server = serverInstance->getVoiceServerManager()->findServerById(cmd["sid"]);
|
auto server = serverInstance->getVoiceServerManager()->findServerById(cmd["sid"]);
|
||||||
@ -683,7 +683,7 @@ command_result QueryClient::handleCommandServerStart(Command& cmd) {
|
|||||||
command_result QueryClient::handleCommandServerStop(Command& cmd) {
|
command_result QueryClient::handleCommandServerStop(Command& cmd) {
|
||||||
CMD_RESET_IDLE;
|
CMD_RESET_IDLE;
|
||||||
|
|
||||||
if(serverInstance->getVoiceServerManager()->getState() != ServerManager::STARTED)
|
if(serverInstance->getVoiceServerManager()->getState() != VirtualServerManager::STARTED)
|
||||||
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
return command_result{error::vs_critical, "Server manager isn't started yet or not finished starting"};
|
||||||
|
|
||||||
auto server = serverInstance->getVoiceServerManager()->findServerById(cmd["sid"]);
|
auto server = serverInstance->getVoiceServerManager()->findServerById(cmd["sid"]);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include "query/Command.h"
|
#include "query/Command.h"
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <src/server/QueryServer.h>
|
#include <src/server/QueryServer.h>
|
||||||
#include <src/ServerManager.h>
|
#include <src/VirtualServerManager.h>
|
||||||
#include <src/InstanceHandler.h>
|
#include <src/InstanceHandler.h>
|
||||||
#include "QueryClient.h"
|
#include "QueryClient.h"
|
||||||
|
|
||||||
|
@ -264,7 +264,7 @@ void VoiceClient::finalDisconnect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VoiceClient::execute_handle_packet(const std::chrono::system_clock::time_point &time) {
|
void VoiceClient::execute_handle_packet(const std::chrono::system_clock::time_point &time) {
|
||||||
this->connection->execute_handle_packet(time);
|
this->connection->execute_handle_command_packets(time);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceClient::send_voice_packet(const pipes::buffer_view &voice_buffer, const SpeakingClient::VoicePacketFlags &flags) {
|
void VoiceClient::send_voice_packet(const pipes::buffer_view &voice_buffer, const SpeakingClient::VoicePacketFlags &flags) {
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#include <EventLoop.h>
|
#include <EventLoop.h>
|
||||||
#include "../SpeakingClient.h"
|
#include "../SpeakingClient.h"
|
||||||
#include "../ConnectedClient.h"
|
#include "../ConnectedClient.h"
|
||||||
#include "protocol/CryptionHandler.h"
|
#include "protocol/CryptHandler.h"
|
||||||
#include "VoiceClientConnection.h"
|
#include "VoiceClientConnection.h"
|
||||||
#include "PrecomputedPuzzles.h"
|
#include "PrecomputedPuzzles.h"
|
||||||
#include "../../lincense/TeamSpeakLicense.h"
|
#include "../../lincense/TeamSpeakLicense.h"
|
||||||
@ -73,11 +73,11 @@ namespace ts {
|
|||||||
void initialize();
|
void initialize();
|
||||||
virtual void tick(const std::chrono::system_clock::time_point &time) override;
|
virtual void tick(const std::chrono::system_clock::time_point &time) override;
|
||||||
|
|
||||||
void handlePacketCommand(const std::unique_ptr<protocol::ClientPacket>&);
|
void handlePacketCommand(const pipes::buffer_view&);
|
||||||
void handlePacketAck(const std::unique_ptr<protocol::ClientPacket>&);
|
void handlePacketAck(const protocol::IncomingClientPacketParser&);
|
||||||
void handlePacketVoice(const std::unique_ptr<protocol::ClientPacket>&);
|
void handlePacketVoice(const protocol::IncomingClientPacketParser&);
|
||||||
void handlePacketPing(const std::unique_ptr<protocol::ClientPacket>&);
|
void handlePacketPing(const protocol::IncomingClientPacketParser&);
|
||||||
void handlePacketInit(const std::unique_ptr<protocol::ClientPacket>&);
|
void handlePacketInit(const protocol::IncomingClientPacketParser&);
|
||||||
|
|
||||||
//Handshake helpers
|
//Handshake helpers
|
||||||
|
|
||||||
@ -109,7 +109,7 @@ namespace ts {
|
|||||||
|
|
||||||
//General TS3 manager commands
|
//General TS3 manager commands
|
||||||
command_result handleCommandClientInitIv(Command&);
|
command_result handleCommandClientInitIv(Command&);
|
||||||
command_result handleCommandClientEk(const std::unique_ptr<protocol::ClientPacket>&, Command&);
|
command_result handleCommandClientEk(Command&);
|
||||||
command_result handleCommandClientInit(Command&) override;
|
command_result handleCommandClientInit(Command&) override;
|
||||||
command_result handleCommandClientDisconnect(Command&);
|
command_result handleCommandClientDisconnect(Command&);
|
||||||
|
|
||||||
|
@ -13,8 +13,8 @@
|
|||||||
//#define LOG_AUTO_ACK_AUTORESPONSE
|
//#define LOG_AUTO_ACK_AUTORESPONSE
|
||||||
//#define FUZZING_TESTING_INCOMMING
|
//#define FUZZING_TESTING_INCOMMING
|
||||||
//#define FUZZING_TESTING_OUTGOING
|
//#define FUZZING_TESTING_OUTGOING
|
||||||
#define FIZZING_TESTING_DISABLE_HANDSHAKE
|
//#define FIZZING_TESTING_DISABLE_HANDSHAKE
|
||||||
#define FUZZING_TESTING_DROP 5
|
#define FUZZING_TESTING_DROP 8
|
||||||
#define FUZZING_TESTING_DROP_MAX 10
|
#define FUZZING_TESTING_DROP_MAX 10
|
||||||
|
|
||||||
//#define CONNECTION_NO_STATISTICS
|
//#define CONNECTION_NO_STATISTICS
|
||||||
@ -65,7 +65,7 @@ void VoiceClientConnection::triggerWrite() {
|
|||||||
|
|
||||||
//Message handle methods
|
//Message handle methods
|
||||||
|
|
||||||
void VoiceClientConnection::handleDatagramReceived(const pipes::buffer_view& buffer) {
|
void VoiceClientConnection::handle_incoming_datagram(const pipes::buffer_view& buffer) {
|
||||||
#ifdef FUZZING_TESTING_INCOMMING
|
#ifdef FUZZING_TESTING_INCOMMING
|
||||||
#ifdef FIZZING_TESTING_DISABLE_HANDSHAKE
|
#ifdef FIZZING_TESTING_DISABLE_HANDSHAKE
|
||||||
if (this->client->state == ConnectionState::CONNECTED) {
|
if (this->client->state == ConnectionState::CONNECTED) {
|
||||||
@ -79,226 +79,171 @@ void VoiceClientConnection::handleDatagramReceived(const pipes::buffer_view& buf
|
|||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto packet = ClientPacket::from_buffer(buffer);
|
IncomingClientPacketParser packet_parser{buffer};
|
||||||
|
if(!packet_parser.valid()) {
|
||||||
auto packet_type = packet->type();
|
logTrace(this->client->getServerId(), "{} Received invalid packet. Dropping.", CLIENT_STR_LOG_PREFIX_(this->client));
|
||||||
auto packet_id = packet->packetId();
|
|
||||||
auto ordered = packet_type.type() == protocol::COMMAND || packet_type.type() == protocol::COMMAND_LOW;
|
|
||||||
|
|
||||||
if(packet_type.type() < 0 || packet_type.type() >= this->_packet_buffers.size()) {
|
|
||||||
logError(this->client->getServerId(), "{} Received invalid packet. Invalid packet type {}. Dropping packet.", CLIENT_STR_LOG_PREFIX_(this->client), packet_type.type());
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
assert(packet_parser.type() >= 0 && packet_parser.type() < this->incoming_generation_estimators.size());
|
||||||
|
packet_parser.set_estimated_generation(this->incoming_generation_estimators[packet_parser.type()].visit_packet(packet_parser.packet_id()));
|
||||||
|
|
||||||
auto& read_queue = this->_packet_buffers[packet_type.type()];
|
auto is_command = packet_parser.type() == protocol::COMMAND || packet_parser.type() == protocol::COMMAND_LOW;
|
||||||
packet->generationId(read_queue.generation(packet_id));
|
/* pretest if the packet is worth the effort of decoding it */
|
||||||
|
if(is_command) {
|
||||||
|
/* handle the order stuff */
|
||||||
|
auto& fragment_buffer = this->_command_fragment_buffers[command_fragment_buffer_index(packet_parser.type())];
|
||||||
|
|
||||||
if(ordered) {
|
unique_lock queue_lock(fragment_buffer.buffer_lock);
|
||||||
unique_lock queue_lock(read_queue.buffer_lock);
|
auto result = fragment_buffer.accept_index(packet_parser.packet_id());
|
||||||
auto result = read_queue.accept_index(packet_id);
|
|
||||||
if(result != 0) { /* packet index is ahead buffer index */
|
if(result != 0) { /* packet index is ahead buffer index */
|
||||||
debugMessage(this->client->getServerId(), "{} Got packet of type {} which is out of the buffer range of {} ({}). Packet ID: {}, Current index: {}. Dropping packet",
|
debugMessage(this->client->getServerId(), "{} Dropping command packet because command assembly buffer has an {} ({}|{})",
|
||||||
CLIENT_STR_LOG_PREFIX_(this->client),
|
CLIENT_STR_LOG_PREFIX_(this->client),
|
||||||
packet_type.name(),
|
|
||||||
read_queue.capacity(),
|
|
||||||
result == -1 ? "underflow" : "overflow",
|
result == -1 ? "underflow" : "overflow",
|
||||||
packet_id,
|
fragment_buffer.capacity(),
|
||||||
read_queue.current_index()
|
fragment_buffer.current_index()
|
||||||
);
|
);
|
||||||
|
|
||||||
if(result == -1) { /* underflow */
|
if(result == -1) { /* underflow */
|
||||||
/* we've already got the packet, but the client dosnt know that so we've to send the acknowledge again */
|
/* we've already got the packet, but the client dosn't know that so we've to send the acknowledge again */
|
||||||
if(this->client->crypto.protocol_encrypted && (packet->type() == PacketTypeInfo::Command || packet->type() == PacketTypeInfo::CommandLow)){ //needs an acknowledge
|
if(this->client->crypto.protocol_encrypted)
|
||||||
this->client->sendAcknowledge(packet->packetId(), packet->type() == PacketTypeInfo::CommandLow);
|
this->client->sendAcknowledge(packet_parser.packet_id(), packet_parser.type() == protocol::COMMAND_LOW);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
packet->setEncrypted(!packet->has_flag(PacketFlag::Unencrypted)); // && packet->type() != PacketType::Init1
|
|
||||||
if(packet->type() == PacketTypeInfo::Command || packet->type() == PacketTypeInfo::CommandLow){
|
|
||||||
packet->setCompressed(packet->has_flag(PacketFlag::Compressed));
|
|
||||||
}
|
|
||||||
//NOTICE I found out that the Compressed flag is set if the packet contains an audio header
|
//NOTICE I found out that the Compressed flag is set if the packet contains an audio header
|
||||||
|
|
||||||
string error = "success";
|
if(this->client->state == ConnectionState::INIT_LOW && packet_parser.type() != protocol::INIT1)
|
||||||
if(this->client->state == ConnectionState::INIT_LOW && packet->type() != PacketTypeInfo::Init1){
|
|
||||||
//Sends command packet as legacy support (skip step 1-3 | Direct clientinit with default key)
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
if(!this->crypt_handler.progressPacketIn(packet.get(), error, false)){
|
/* decrypt the packet if needed */
|
||||||
//FIXME Only try to decrypt by default when its no flood attack!
|
if(packet_parser.is_encrypted()) {
|
||||||
if(!this->client->crypto.client_init && !this->crypt_handler.use_default()) {
|
std::string error;
|
||||||
if(!this->crypt_handler.progressPacketIn(packet.get(), error, true)){
|
|
||||||
debugMessage(
|
CryptHandler::key_t crypt_key{};
|
||||||
this->client->getServerId(),
|
CryptHandler::nonce_t crypt_nonce{};
|
||||||
"{} Cant decrypt packet even with default key! Type: {}, Error: {}, Packet ID: {}, Generation: {}",
|
|
||||||
CLIENT_STR_LOG_PREFIX_(this->client),
|
auto data = (uint8_t*) packet_parser.mutable_data_ptr();
|
||||||
packet->type().name(),
|
bool use_default_key{!this->client->crypto.protocol_encrypted}, decrypt_result;
|
||||||
error,
|
|
||||||
packet_id,
|
decrypt_packet:
|
||||||
packet->generationId()
|
if(use_default_key) {
|
||||||
);
|
crypt_key = CryptHandler::default_key;
|
||||||
return;
|
crypt_nonce = CryptHandler::default_nonce;
|
||||||
} else {
|
|
||||||
debugMessage(
|
|
||||||
this->client->getServerId(),
|
|
||||||
"{} Cant decrypt packet with configured key {}. Error: {}. Succeeded with default key!",
|
|
||||||
CLIENT_STR_LOG_PREFIX_(this->client),
|
|
||||||
packet->type().name(),
|
|
||||||
error
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
bool succeeded = false;
|
if(!this->crypt_handler.generate_key_nonce(true, packet_parser.type(), packet_parser.packet_id(), packet_parser.estimated_generation(), crypt_key, crypt_nonce)) {
|
||||||
if(packet_type == PacketTypeInfo::Voice) {
|
logError(this->client->getServerId(), "{} Failed to generate crypt key/nonce. This should never happen! Dropping packet.", CLIENT_STR_LOG_PREFIX_(this->client));
|
||||||
/* FIXME: This try and error should not happen! */
|
|
||||||
packet->generationId(packet->generationId() + 1);
|
|
||||||
succeeded = this->crypt_handler.progressPacketIn(packet.get(), error, false);
|
|
||||||
}
|
|
||||||
if(succeeded) {
|
|
||||||
auto old_packet_id = read_queue.current_index();
|
|
||||||
read_queue.set_generation_packet(packet->generationId(), packet->packetId());
|
|
||||||
|
|
||||||
logWarning(this->client->getServerId(), "{} Voice packet generation counter missed generation increasement. From {} to {} from packet id {} to {}",
|
|
||||||
CLIENT_STR_LOG_PREFIX_(this->client),
|
|
||||||
packet->generationId() - 1,
|
|
||||||
packet->generationId(),
|
|
||||||
old_packet_id,
|
|
||||||
packet->packetId()
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
debugMessage(
|
|
||||||
this->client->getServerId(),
|
|
||||||
"{} Cant decrypt packet of type {}. Packet ID: {}, Estimated generation: {}, Full counter: {}. Dropping packet. Error: {}",
|
|
||||||
CLIENT_STR_LOG_PREFIX_(this->client),
|
|
||||||
packet->type().name(),
|
|
||||||
packet->packetId(),
|
|
||||||
packet->generationId(),
|
|
||||||
read_queue.full_index(),
|
|
||||||
error
|
|
||||||
);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if(packet->type() == PacketTypeInfo::Command || packet->type() == PacketTypeInfo::CommandLow){
|
decrypt_result = this->crypt_handler.decrypt(
|
||||||
if(packet->has_flag(PacketFlag::Unencrypted) && this->client->state != ConnectionState::INIT_HIGH){
|
data + IncomingClientPacketParser::kHeaderOffset, IncomingClientPacketParser::kHeaderLength,
|
||||||
this->client->disconnect("Invalid packet. Command should not be unencrypted!");
|
data + IncomingClientPacketParser::kPayloadOffset, packet_parser.payload_length(),
|
||||||
logger::logger(this->client->getServer()->getServerId())->error("{} Voice manager {}/{} tried to send a unencrypted command packet.", CLIENT_STR_LOG_PREFIX_(this->client), client->getDisplayName(), this->client->getLoggingPeerIp());
|
data,
|
||||||
return;
|
crypt_key, crypt_nonce,
|
||||||
|
error
|
||||||
|
);
|
||||||
|
|
||||||
|
if(!decrypt_result) {
|
||||||
|
if(!this->client->crypto.client_init) {
|
||||||
|
if(use_default_key) {
|
||||||
|
logTrace(this->client->getServerId(), "{} Failed to decrypt packet with default key ({}). Dropping packet.", CLIENT_STR_LOG_PREFIX_(this->client), error);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
logTrace(this->client->getServerId(), "{} Failed to decrypt packet ({}). Trying with default key.", CLIENT_STR_LOG_PREFIX_(this->client), error);
|
||||||
|
use_default_key = true;
|
||||||
|
goto decrypt_packet;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logTrace(this->client->getServerId(), "{} Failed to decrypt packet ({}). Dropping packet.", CLIENT_STR_LOG_PREFIX_(this->client), error);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
packet_parser.set_decrypted();
|
||||||
|
} else if(is_command && this->client->state != ConnectionState::INIT_HIGH) {
|
||||||
|
logTrace(this->client->getServerId(), "{} Voice client {}/{} tried to send a unencrypted command packet. Dropping packet.", CLIENT_STR_LOG_PREFIX_(this->client), client->getDisplayName(), this->client->getLoggingPeerIp());
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONNECTION_NO_STATISTICS
|
#ifndef CONNECTION_NO_STATISTICS
|
||||||
if(this->client && this->client->getServer())
|
if(this->client && this->client->getServer())
|
||||||
this->client->connectionStatistics->logIncomingPacket(*packet);
|
this->client->connectionStatistics->logIncomingPacket(stats::ConnectionStatistics::category::from_type(packet_parser.type()), buffer.length());
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef LOG_INCOMPING_PACKET_FRAGMENTS
|
#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);
|
debugMessage(lstream << CLIENT_LOG_PREFIX << "Recived packet. PacketId: " << packet->packetId() << " PacketType: " << packet->type().name() << " Flags: " << packet->flags() << " - " << packet->data() << endl);
|
||||||
#endif
|
#endif
|
||||||
if(packet->type() == PacketTypeInfo::Command || packet->type() == PacketTypeInfo::CommandLow){ //needs an acknowledge
|
if(is_command) {
|
||||||
if(this->client->crypto.protocol_encrypted) {
|
auto& fragment_buffer = this->_command_fragment_buffers[command_fragment_buffer_index(packet_parser.type())];
|
||||||
#ifdef LOG_AUTO_ACK_AUTORESPONSE
|
CommandFragment fragment_entry{
|
||||||
logMessage(this->client->getServerId(), "{}[Ack] Sending ack for incoming command packet {}", CLIENT_STR_LOG_PREFIX_(this->client), packet->packetId());
|
packet_parser.packet_id(),
|
||||||
#endif
|
packet_parser.estimated_generation(),
|
||||||
this->client->sendAcknowledge(packet->packetId(), packet->type() == PacketTypeInfo::CommandLow);
|
|
||||||
} else {
|
|
||||||
debugMessage(this->client->getServerId(), "{}[Ack] Ignoring ack for {}", CLIENT_STR_LOG_PREFIX_(this->client), packet->packetId());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
packet_parser.flags(),
|
||||||
unique_lock queue_lock(read_queue.buffer_lock);
|
(uint32_t) packet_parser.payload_length(),
|
||||||
|
packet_parser.payload().own_buffer()
|
||||||
|
};
|
||||||
|
|
||||||
if(ordered) { /* ordered */
|
{
|
||||||
if(!read_queue.insert_index(packet_id, move(packet))) {
|
unique_lock queue_lock(fragment_buffer.buffer_lock);
|
||||||
debugMessage(this->client->getServerId(), "{} Got ordered packet of type {} which is out of the buffer range of {}. Packet ID: {}, Full index: {}. Dropping packet",
|
|
||||||
CLIENT_STR_LOG_PREFIX_(this->client),
|
if(!fragment_buffer.insert_index(packet_parser.packet_id(), std::move(fragment_entry))) {
|
||||||
packet_type.name(),
|
logTrace(this->client->getServerId(), "{} Failed to insert command packet into command packet buffer.", CLIENT_STR_LOG_PREFIX_(this->client));
|
||||||
read_queue.capacity(),
|
return;
|
||||||
packet_id,
|
|
||||||
read_queue.full_index()
|
|
||||||
);
|
|
||||||
/* return; dont stop here because we've to progress the packets */
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
//TODO: Needs rethinking because read_queue.push_back increases the index, but this has not to be the packet id
|
|
||||||
if(!read_queue.push_back(move(packet))) {
|
|
||||||
debugMessage(this->client->getServerId(), "{} Got unordered packet of type {} which is out of the buffer capacity of {}. Packet ID: {}. Dropping packet.",
|
|
||||||
CLIENT_STR_LOG_PREFIX_(this->client),
|
|
||||||
packet_type.name(),
|
|
||||||
read_queue.capacity(),
|
|
||||||
packet_id,
|
|
||||||
read_queue.full_index()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
{
|
|
||||||
//A max entropy of 16 packets should not happen. This indicates more that 16 or more packets got lost
|
|
||||||
auto current_index = read_queue.current_index();
|
|
||||||
if(current_index + 16 < packet_id)
|
|
||||||
read_queue.set_full_index_to(packet_id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
this->client->sendAcknowledge(packet_parser.packet_id(), packet_parser.type() == protocol::COMMAND_LOW);
|
||||||
|
|
||||||
|
auto voice_server = this->client->voice_server;
|
||||||
|
if(voice_server)
|
||||||
|
voice_server->schedule_command_handling(this->client);
|
||||||
|
} else {
|
||||||
|
if(packet_parser.type() == protocol::VOICE || packet_parser.type() == protocol::VOICE_WHISPER)
|
||||||
|
this->client->handlePacketVoice(packet_parser);
|
||||||
|
else if(packet_parser.type() == protocol::ACK || packet_parser.type() == protocol::ACK_LOW)
|
||||||
|
this->client->handlePacketAck(packet_parser);
|
||||||
|
else if(packet_parser.type() == protocol::PING || packet_parser.type() == protocol::PONG)
|
||||||
|
this->client->handlePacketPing(packet_parser);
|
||||||
|
else {
|
||||||
|
logError(this->client->getServerId(), "{} Received hand decoded packet, but we've no method to handle it. Dropping packet.", CLIENT_STR_LOG_PREFIX_(this->client));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto voice_server = this->client->voice_server;
|
|
||||||
if(voice_server)
|
|
||||||
voice_server->schedule_execute(this->client);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VoiceClientConnection::verify_encryption(const pipes::buffer_view &packet /* incl. mac etc */) {
|
bool VoiceClientConnection::verify_encryption(const pipes::buffer_view &buffer /* incl. mac etc */) {
|
||||||
if((packet[12] & 0x80) != 0) /* we want an encrypted packet to verify the encryption */
|
IncomingClientPacketParser packet_parser{buffer};
|
||||||
return false;
|
if(!packet_parser.valid() || !packet_parser.is_encrypted()) return false;
|
||||||
|
|
||||||
auto packet_type = (protocol::PacketType) (packet[12] & 0xF);
|
assert(packet_parser.type() >= 0 && packet_parser.type() < this->incoming_generation_estimators.size());
|
||||||
if(packet_type == protocol::PING || packet_type == protocol::PONG) return false; /* these packets could never be encrypted */
|
return this->crypt_handler.verify_encryption(buffer, packet_parser.packet_id(), this->incoming_generation_estimators[packet_parser.type()].generation());
|
||||||
|
|
||||||
auto packet_id = (uint16_t) be2le16(&packet[8]);
|
|
||||||
auto generation = this->_packet_buffers[packet_type].generation(packet_id);
|
|
||||||
return this->crypt_handler.verify_encryption(packet, packet_id, generation);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceClientConnection::execute_handle_packet(const std::chrono::system_clock::time_point& /* scheduled */) {
|
void VoiceClientConnection::execute_handle_command_packets(const std::chrono::system_clock::time_point& /* scheduled */) {
|
||||||
if(this->client->state == ConnectionState::DISCONNECTED || !this->client->getServer())
|
if(this->client->state == ConnectionState::DISCONNECTED || !this->client->getServer())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
bool reexecute_handle = false;
|
//TODO: Remove the buffer_execute_lock and use the one within the this->client->handlePacketCommand method
|
||||||
unique_lock<std::recursive_timed_mutex> buffer_execute_lock;
|
unique_lock<std::recursive_timed_mutex> buffer_execute_lock;
|
||||||
auto packet = this->next_reassembled_packet(buffer_execute_lock, reexecute_handle);
|
pipes::buffer payload{};
|
||||||
|
auto reexecute_handle = this->next_reassembled_command(buffer_execute_lock, payload);
|
||||||
|
|
||||||
if(packet){
|
if(!payload.empty()){
|
||||||
auto startTime = system_clock::now();
|
auto startTime = system_clock::now();
|
||||||
try {
|
try {
|
||||||
const auto packet_type = packet->type();
|
this->client->handlePacketCommand(payload);
|
||||||
if(packet_type == PacketTypeInfo::Command || packet_type == PacketTypeInfo::CommandLow)
|
|
||||||
this->client->handlePacketCommand(packet);
|
|
||||||
else if(packet_type == PacketTypeInfo::Ack || packet_type == PacketTypeInfo::AckLow)
|
|
||||||
this->client->handlePacketAck(packet);
|
|
||||||
else if(packet_type == PacketTypeInfo::Voice || packet_type == PacketTypeInfo::VoiceWhisper)
|
|
||||||
this->client->handlePacketVoice(packet);
|
|
||||||
else if(packet_type == PacketTypeInfo::Ping || packet_type == PacketTypeInfo::Pong)
|
|
||||||
this->client->handlePacketPing(packet);
|
|
||||||
else if(packet_type == PacketTypeInfo::Init1)
|
|
||||||
this->client->handlePacketInit(packet);
|
|
||||||
} catch (std::exception& ex) {
|
} catch (std::exception& ex) {
|
||||||
logCritical(this->client->getServerId(), "{} Exception reached root tree! {}", CLIENT_STR_LOG_PREFIX_(this->client), ex.what());
|
logCritical(this->client->getServerId(), "{} Exception reached root tree! {}", CLIENT_STR_LOG_PREFIX_(this->client), ex.what());
|
||||||
}
|
}
|
||||||
|
|
||||||
auto end = system_clock::now();
|
auto end = system_clock::now();
|
||||||
if(end - startTime > milliseconds(10)) {
|
if(end - startTime > milliseconds(10)) {
|
||||||
if(packet->type() != PacketTypeInfo::Command && packet->type() != PacketTypeInfo::CommandLow) {
|
logError(this->client->getServerId(),
|
||||||
logError(this->client->getServerId(),
|
"{} Handling of command packet needs more than 10ms ({}ms)",
|
||||||
"{} Handling of packet {} needs more than 10ms ({}ms)",
|
CLIENT_STR_LOG_PREFIX_(this->client),
|
||||||
CLIENT_STR_LOG_PREFIX_(this->client),
|
duration_cast<milliseconds>(end - startTime).count()
|
||||||
packet->type().name(),
|
);
|
||||||
duration_cast<milliseconds>(end - startTime).count()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(buffer_execute_lock.owns_lock())
|
if(buffer_execute_lock.owns_lock())
|
||||||
@ -306,24 +251,20 @@ void VoiceClientConnection::execute_handle_packet(const std::chrono::system_cloc
|
|||||||
|
|
||||||
auto voice_server = this->client->voice_server;
|
auto voice_server = this->client->voice_server;
|
||||||
if(voice_server && reexecute_handle)
|
if(voice_server && reexecute_handle)
|
||||||
this->client->voice_server->schedule_execute(this->client);
|
this->client->voice_server->schedule_command_handling(this->client);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* buffer_execute_lock: lock for in order execution */
|
/* buffer_execute_lock: lock for in order execution */
|
||||||
unique_ptr<protocol::ClientPacket> VoiceClientConnection::next_reassembled_packet(unique_lock<std::recursive_timed_mutex>& buffer_execute_lock, bool& more) {
|
bool VoiceClientConnection::next_reassembled_command(unique_lock<std::recursive_timed_mutex>& buffer_execute_lock, pipes::buffer& result) {
|
||||||
packet_buffer_t* buffer = nullptr;
|
command_fragment_buffer_t* buffer{nullptr};
|
||||||
unique_lock<std::recursive_timed_mutex> buffer_lock; /* general buffer lock */
|
unique_lock<std::recursive_timed_mutex> buffer_lock; /* general buffer lock */
|
||||||
|
|
||||||
|
bool have_more{false};
|
||||||
{
|
{
|
||||||
auto base_index = this->_packet_buffers_index;
|
//FIXME: Currently command low packets cant be handeled if there is a command packet stuck in reassamble
|
||||||
auto select_index = base_index;
|
|
||||||
auto max_index = this->_packet_buffers.size();
|
|
||||||
|
|
||||||
for(uint8_t index = 0; index < max_index; index++) {
|
/* handle commands before command low packets */
|
||||||
if(!buffer)
|
for(auto& buf : this->_command_fragment_buffers) {
|
||||||
select_index++;
|
|
||||||
|
|
||||||
auto& buf = this->_packet_buffers[base_index++ % max_index];
|
|
||||||
unique_lock ring_lock(buf.buffer_lock, try_to_lock);
|
unique_lock ring_lock(buf.buffer_lock, try_to_lock);
|
||||||
if(!ring_lock.owns_lock()) continue;
|
if(!ring_lock.owns_lock()) continue;
|
||||||
|
|
||||||
@ -335,119 +276,94 @@ unique_ptr<protocol::ClientPacket> VoiceClientConnection::next_reassembled_packe
|
|||||||
buffer_lock = move(ring_lock);
|
buffer_lock = move(ring_lock);
|
||||||
buffer = &buf;
|
buffer = &buf;
|
||||||
} else {
|
} else {
|
||||||
more = true;
|
have_more = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this->_packet_buffers_index = static_cast<uint8_t>(select_index % max_index); /* guarantee that we will not hangup with commands! */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!buffer)
|
if(!buffer)
|
||||||
return nullptr; /* we've no packets */
|
return false; /* we've no packets */
|
||||||
|
|
||||||
auto current_packet = &*buffer->slot_value(0);
|
uint8_t packet_flags{0};
|
||||||
if(!current_packet) {
|
pipes::buffer payload{};
|
||||||
logCritical(this->client->getServer()->getServerId(), "buffer->slot_value(0) returned nullptr, but set flag has been set!");
|
|
||||||
return buffer->pop_front(); /* should be null! */
|
|
||||||
}
|
|
||||||
|
|
||||||
if(current_packet->type() != PacketTypeInfo::Command && current_packet->type() != PacketTypeInfo::CommandLow) {
|
/* lets find out if we've to reassemble the packet */
|
||||||
auto tmp = buffer->pop_front(); /* we don't have to reassemble anything */
|
if(buffer->slot_value(0).packet_flags & PacketFlag::Fragmented) {
|
||||||
more |= buffer->front_set(); /* set the more flag if we know that we have more of this packet */
|
uint16_t sequence_length = 1;
|
||||||
return tmp;
|
size_t total_payload_length{0};
|
||||||
}
|
|
||||||
|
|
||||||
unique_ptr<ClientPacket> final_packet;
|
|
||||||
uint16_t sequence_length = 1;
|
|
||||||
|
|
||||||
if(current_packet->has_flag(PacketFlag::Fragmented)) {
|
|
||||||
size_t buffer_length = ClientPacket::META_SIZE;
|
|
||||||
do {
|
do {
|
||||||
if(sequence_length >= buffer->capacity()) {
|
if(sequence_length >= buffer->capacity()) {
|
||||||
logError(this->client->getServerId(), "{} Received fragmented packets which have a too long order. Dropping queue, which will cause a client drop.", CLIENT_STR_LOG_PREFIX_(this->client));
|
logError(this->client->getServerId(), "{} Command fragment buffer is full, and there is not fragmented packet end. Dropping full buffer which will probably cause a connection loss.", CLIENT_STR_LOG_PREFIX_(this->client));
|
||||||
buffer->clear();
|
buffer->clear();
|
||||||
return nullptr; /* we've nothing to handle */
|
return false; /* we've nothing to handle */
|
||||||
}
|
}
|
||||||
|
|
||||||
buffer_length += current_packet->data_length();
|
if(!buffer->slot_set(sequence_length))
|
||||||
current_packet = &*buffer->slot_value(sequence_length++);
|
return false; /* we need more packets */
|
||||||
} while(current_packet && !current_packet->has_flag(PacketFlag::Fragmented));
|
|
||||||
if(!current_packet)
|
|
||||||
return nullptr; /* we haven't found the end yet! */
|
|
||||||
buffer_length += current_packet->data_length();
|
|
||||||
|
|
||||||
/* okey we have all fragments lets reassemble */
|
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.
|
* 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
|
* We're checking it here because we dont want to make a huge allocation
|
||||||
*/
|
*/
|
||||||
assert(buffer_length < 512 * 1024 * 1024);
|
assert(total_payload_length < 512 * 1024 * 1024);
|
||||||
|
|
||||||
pipes::buffer packet_buffer{buffer_length};
|
pipes::buffer packet_buffer{total_payload_length};
|
||||||
char* packet_buffer_ptr = &packet_buffer[0];
|
char* packet_buffer_ptr = &packet_buffer[0];
|
||||||
size_t packet_count = 0;
|
size_t packet_count = 0;
|
||||||
|
|
||||||
unique_ptr<ClientPacket> packet;
|
packet_flags = buffer->slot_value(0).packet_flags;
|
||||||
|
|
||||||
/* initialize packet flags etc */
|
|
||||||
{
|
|
||||||
packet = buffer->pop_front();
|
|
||||||
packet_count++;
|
|
||||||
|
|
||||||
if(!packet) {
|
|
||||||
logCritical(this->client->getServer()->getServerId(), "buffer->pop_front() returned nullptr, but set flag has been set (0)!");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto length = packet->buffer().length();
|
|
||||||
memcpy(packet_buffer_ptr, &packet->buffer()[0], length);
|
|
||||||
packet_buffer_ptr += length;
|
|
||||||
}
|
|
||||||
|
|
||||||
while(packet_count < sequence_length) {
|
while(packet_count < sequence_length) {
|
||||||
packet = buffer->pop_front();
|
auto fragment = buffer->pop_front();
|
||||||
|
memcpy(packet_buffer_ptr, fragment.payload.data_ptr(), fragment.payload_length);
|
||||||
|
|
||||||
|
packet_buffer_ptr += fragment.payload_length;
|
||||||
packet_count++;
|
packet_count++;
|
||||||
|
|
||||||
if(!packet) {
|
|
||||||
logCritical(this->client->getServer()->getServerId(), "buffer->pop_front() returned nullptr, but set flag has been set (1)!");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto length = packet->data_length();
|
|
||||||
memcpy(packet_buffer_ptr, &packet->data()[0], length);
|
|
||||||
packet_buffer_ptr += length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef _NDEBUG
|
||||||
if((packet_buffer_ptr - 1) != &packet_buffer[packet_buffer.length() - 1]) {
|
if((packet_buffer_ptr - 1) != &packet_buffer[packet_buffer.length() - 1]) {
|
||||||
logCritical(this->client->getServer()->getServerId(),
|
logCritical(this->client->getServer()->getServerId(),
|
||||||
"Buffer over/underflow: packet_buffer_ptr != &packet_buffer[packet_buffer.length() - 1]; packet_buffer_ptr := {}; packet_buffer.end() := {}",
|
"Buffer over/underflow: packet_buffer_ptr != &packet_buffer[packet_buffer.length() - 1]; packet_buffer_ptr := {}; packet_buffer.end() := {}",
|
||||||
(void*) packet_buffer_ptr,
|
(void*) packet_buffer_ptr,
|
||||||
(void*) &packet_buffer[packet_buffer.length() - 1]
|
(void*) &packet_buffer[packet_buffer.length() - 1]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
final_packet = ClientPacket::from_buffer(packet_buffer);
|
|
||||||
final_packet->setCompressed(final_packet->has_flag(PacketFlag::Compressed));
|
|
||||||
} else {
|
} else {
|
||||||
final_packet = buffer->pop_front();
|
auto packet = buffer->pop_front();
|
||||||
if(!final_packet) {
|
packet_flags = packet.packet_flags;
|
||||||
logCritical(this->client->getServer()->getServerId(), "buffer->pop_front() returned nullptr, but set flag has been set (3)!");
|
payload = packet.payload;
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
more |= buffer->front_set(); /* set the more flag if we have more to process */
|
have_more |= buffer->front_set(); /* set the more flag if we have more to process */
|
||||||
buffer_lock.unlock();
|
buffer_lock.unlock();
|
||||||
|
|
||||||
std::string error = "success";
|
if(packet_flags & PacketFlag::Compressed) {
|
||||||
if(!this->compress_handler.progressPacketIn(&*final_packet, error)) {
|
std::string error{};
|
||||||
logError(this->client->getServerId(), "{} Failed to decompress received packet. Error: {}", CLIENT_STR_LOG_PREFIX_(this->client), error);
|
|
||||||
final_packet = nullptr;
|
auto decompressed_size = compression::qlz_decompressed_size(payload.data_ptr(), payload.length());
|
||||||
|
auto buffer = buffer::allocate_buffer(decompressed_size);
|
||||||
|
if(!compression::qlz_decompress_payload(payload.data_ptr(), buffer.data_ptr(), &decompressed_size)) {
|
||||||
|
logTrace(this->client->getServerId(), "{} Failed to decompress received command. Dropping packet.", CLIENT_STR_LOG_PREFIX_(this->client));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
payload = buffer.range(0, decompressed_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
return final_packet;
|
result = std::move(payload);
|
||||||
|
return have_more;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -499,7 +415,7 @@ bool VoiceClientConnection::prepare_packet_for_write(vector<pipes::buffer> &resu
|
|||||||
|
|
||||||
string error = "success";
|
string error = "success";
|
||||||
|
|
||||||
if(packet->type().compressable() && !packet->memory_state.fragment_entry) {
|
if(packet->type().compressable() && !packet->memory_state.fragment_entry && false) {
|
||||||
packet->enable_flag(PacketFlag::Compressed);
|
packet->enable_flag(PacketFlag::Compressed);
|
||||||
if(!this->compress_handler.progressPacketOut(packet.get(), error)) {
|
if(!this->compress_handler.progressPacketOut(packet.get(), error)) {
|
||||||
logError(this->getClient()->getServerId(), "{} Could not compress outgoing packet.\nThis could cause fatal failed for the client.\nError: {}", error);
|
logError(this->getClient()->getServerId(), "{} Could not compress outgoing packet.\nThis could cause fatal failed for the client.\nError: {}", error);
|
||||||
@ -560,12 +476,33 @@ bool VoiceClientConnection::prepare_packet_for_write(vector<pipes::buffer> &resu
|
|||||||
work_lock.unlock(); /* the rest could be unordered */
|
work_lock.unlock(); /* the rest could be unordered */
|
||||||
|
|
||||||
|
|
||||||
|
CryptHandler::key_t crypt_key{};
|
||||||
|
CryptHandler::nonce_t crypt_nonce{};
|
||||||
auto statistics = this->client ? this->client->connectionStatistics : nullptr;
|
auto statistics = this->client ? this->client->connectionStatistics : nullptr;
|
||||||
for(const auto& fragment : fragments) {
|
for(const auto& fragment : fragments) {
|
||||||
if(!this->crypt_handler.progressPacketOut(fragment.get(), error, false)){
|
if(fragment->has_flag(PacketFlag::Unencrypted)) {
|
||||||
logError(this->client->getServerId(), "{} Failed to encrypt packet. Error: {}", CLIENT_STR_LOG_PREFIX_(this->client), error);
|
this->crypt_handler.write_default_mac(fragment->mac().data_ptr());
|
||||||
return false;
|
} else {
|
||||||
|
if(!this->client->crypto.protocol_encrypted) {
|
||||||
|
crypt_key = CryptHandler::default_key;
|
||||||
|
crypt_nonce = CryptHandler::default_nonce;
|
||||||
|
} else {
|
||||||
|
if(!this->crypt_handler.generate_key_nonce(false, fragment->type().type(), fragment->packetId(), fragment->generationId(), crypt_key, crypt_nonce)) {
|
||||||
|
logError(this->client->getServerId(), "{} Failed to generate crypt key/nonce for sending a packet. This should never happen! Dropping packet.", CLIENT_STR_LOG_PREFIX_(this->client));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
auto crypt_result = this->crypt_handler.encrypt(fragment->header().data_ptr(), fragment->header().length(),
|
||||||
|
fragment->data().data_ptr(), fragment->data().length(),
|
||||||
|
fragment->mac().data_ptr(),
|
||||||
|
crypt_key, crypt_nonce, error);
|
||||||
|
if(!crypt_result){
|
||||||
|
logError(this->client->getServerId(), "{} Failed to encrypt packet. Error: {}", CLIENT_STR_LOG_PREFIX_(this->client), error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef CONNECTION_NO_STATISTICS
|
#ifndef CONNECTION_NO_STATISTICS
|
||||||
if(statistics)
|
if(statistics)
|
||||||
statistics->logOutgoingPacket(*fragment);
|
statistics->logOutgoingPacket(*fragment);
|
||||||
@ -704,7 +641,35 @@ void VoiceClientConnection::reset() {
|
|||||||
|
|
||||||
{
|
{
|
||||||
lock_guard buffer_lock(this->packet_buffer_lock);
|
lock_guard buffer_lock(this->packet_buffer_lock);
|
||||||
for(auto& buffer : this->_packet_buffers)
|
for(auto& buffer : this->_command_fragment_buffers)
|
||||||
buffer.reset();
|
buffer.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VoiceClientConnection::force_insert_command(const pipes::buffer_view &buffer) {
|
||||||
|
CommandFragment fragment_entry{
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
|
||||||
|
PacketFlag::Unencrypted,
|
||||||
|
(uint32_t) buffer.length(),
|
||||||
|
buffer.own_buffer()
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
auto& fragment_buffer = this->_command_fragment_buffers[command_fragment_buffer_index(protocol::COMMAND)];
|
||||||
|
unique_lock queue_lock(fragment_buffer.buffer_lock);
|
||||||
|
fragment_buffer.push_front(std::move(fragment_entry));
|
||||||
|
}
|
||||||
|
|
||||||
|
auto voice_server = this->client->voice_server;
|
||||||
|
if(voice_server)
|
||||||
|
voice_server->schedule_command_handling(this->client);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VoiceClientConnection::register_initiv_packet() {
|
||||||
|
auto& fragment_buffer = this->_command_fragment_buffers[command_fragment_buffer_index(protocol::COMMAND)];
|
||||||
|
unique_lock buffer_lock(fragment_buffer.buffer_lock);
|
||||||
|
fragment_buffer.set_full_index_to(1); /* the first packet (0) is already the clientinitiv packet */
|
||||||
|
}
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#include <protocol/ringbuffer.h>
|
#include <protocol/ringbuffer.h>
|
||||||
#include <protocol/CompressionHandler.h>
|
#include <protocol/CompressionHandler.h>
|
||||||
#include <protocol/CryptionHandler.h>
|
#include <protocol/CryptHandler.h>
|
||||||
#include <ThreadPool/Thread.h>
|
#include <ThreadPool/Thread.h>
|
||||||
#include <ThreadPool/Mutex.h>
|
#include <ThreadPool/Mutex.h>
|
||||||
#include <protocol/buffers.h>
|
#include <protocol/buffers.h>
|
||||||
@ -10,9 +10,11 @@
|
|||||||
#include <deque>
|
#include <deque>
|
||||||
#include <event.h>
|
#include <event.h>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
#include <utility>
|
||||||
#include <pipes/buffer.h>
|
#include <pipes/buffer.h>
|
||||||
#include "VoiceClient.h"
|
#include "VoiceClient.h"
|
||||||
#include "protocol/AcknowledgeManager.h"
|
#include "protocol/AcknowledgeManager.h"
|
||||||
|
#include <protocol/generation.h>
|
||||||
|
|
||||||
//#define LOG_ACK_SYSTEM
|
//#define LOG_ACK_SYSTEM
|
||||||
#ifdef LOG_ACK_SYSTEM
|
#ifdef LOG_ACK_SYSTEM
|
||||||
@ -36,15 +38,33 @@ namespace ts {
|
|||||||
friend class server::VoiceClient;
|
friend class server::VoiceClient;
|
||||||
friend class server::POWHandler;
|
friend class server::POWHandler;
|
||||||
public:
|
public:
|
||||||
typedef protocol::PacketRingBuffer<protocol::ClientPacket, 32, std::unique_ptr<protocol::ClientPacket>> packet_buffer_t;
|
struct CommandFragment {
|
||||||
typedef std::array<packet_buffer_t, 8> packet_buffers_t;
|
uint16_t packet_id{0};
|
||||||
|
uint16_t packet_generation{0};
|
||||||
|
|
||||||
|
uint8_t packet_flags{0};
|
||||||
|
uint32_t payload_length : 24;
|
||||||
|
pipes::buffer payload{};
|
||||||
|
|
||||||
|
CommandFragment() { this->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));
|
||||||
|
|
||||||
|
typedef protocol::PacketRingBuffer<CommandFragment, 32, CommandFragment> command_fragment_buffer_t;
|
||||||
|
typedef std::array<command_fragment_buffer_t, 2> command_packet_reassembler;
|
||||||
|
|
||||||
explicit VoiceClientConnection(server::VoiceClient*);
|
explicit VoiceClientConnection(server::VoiceClient*);
|
||||||
virtual ~VoiceClientConnection();
|
virtual ~VoiceClientConnection();
|
||||||
|
|
||||||
void sendPacket(const std::shared_ptr<protocol::ServerPacket>& original_packet, bool copy = false, bool prepare_directly = false);
|
void sendPacket(const std::shared_ptr<protocol::ServerPacket>& original_packet, bool copy = false, bool prepare_directly = false);
|
||||||
|
|
||||||
CryptionHandler* getCryptHandler(){ return &crypt_handler; }
|
CryptHandler* getCryptHandler(){ return &crypt_handler; }
|
||||||
|
|
||||||
server::VoiceClient* getClient(){ return client; }
|
server::VoiceClient* getClient(){ return client; }
|
||||||
|
|
||||||
@ -62,12 +82,13 @@ namespace ts {
|
|||||||
bool wait_empty_write_and_prepare_queue(std::chrono::time_point<std::chrono::system_clock> until = std::chrono::time_point<std::chrono::system_clock>());
|
bool wait_empty_write_and_prepare_queue(std::chrono::time_point<std::chrono::system_clock> until = std::chrono::time_point<std::chrono::system_clock>());
|
||||||
|
|
||||||
protocol::PacketIdManager& getPacketIdManager() { return this->packet_id_manager; }
|
protocol::PacketIdManager& getPacketIdManager() { return this->packet_id_manager; }
|
||||||
packet_buffers_t& packet_buffers() { return this->_packet_buffers; }
|
|
||||||
|
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
|
void force_insert_command(const pipes::buffer_view& /* payload */);
|
||||||
|
void register_initiv_packet();
|
||||||
//buffer::SortedBufferQueue<protocol::ClientPacket>** getReadQueue() { return this->readTypedQueue; }
|
//buffer::SortedBufferQueue<protocol::ClientPacket>** getReadQueue() { return this->readTypedQueue; }
|
||||||
protected:
|
protected:
|
||||||
void handleDatagramReceived(const pipes::buffer_view&);
|
void handle_incoming_datagram(const pipes::buffer_view &buffer);
|
||||||
bool verify_encryption(const pipes::buffer_view& /* full packet */);
|
bool verify_encryption(const pipes::buffer_view& /* full packet */);
|
||||||
|
|
||||||
void triggerWrite();
|
void triggerWrite();
|
||||||
@ -75,13 +96,13 @@ namespace ts {
|
|||||||
server::VoiceClient* client = nullptr;
|
server::VoiceClient* client = nullptr;
|
||||||
|
|
||||||
//Decryption / encryption stuff
|
//Decryption / encryption stuff
|
||||||
CryptionHandler crypt_handler;
|
CryptHandler crypt_handler; /* access to CryptHandler is thread save */
|
||||||
CompressionHandler compress_handler;
|
CompressionHandler compress_handler;
|
||||||
AcknowledgeManager acknowledge_handler;
|
AcknowledgeManager acknowledge_handler;
|
||||||
|
|
||||||
//Handle stuff
|
//Handle stuff
|
||||||
void execute_handle_packet(const std::chrono::system_clock::time_point& /* scheduled */);
|
void execute_handle_command_packets(const std::chrono::system_clock::time_point& /* scheduled */);
|
||||||
std::unique_ptr<protocol::ClientPacket> next_reassembled_packet(std::unique_lock<std::recursive_timed_mutex>& /* packet channel execute lock */, bool& /* have more */);
|
bool next_reassembled_command(std::unique_lock<std::recursive_timed_mutex> &buffer_execute_lock /* packet channel execute lock */, pipes::buffer & /* buffer*/);
|
||||||
|
|
||||||
|
|
||||||
/* ---------- Write declarations ---------- */
|
/* ---------- Write declarations ---------- */
|
||||||
@ -143,9 +164,13 @@ namespace ts {
|
|||||||
std::atomic<uint8_t> prepare_process_count{0}; /* current thread count preparing a packet */
|
std::atomic<uint8_t> prepare_process_count{0}; /* current thread count preparing a packet */
|
||||||
bool prepare_packet_for_write(std::vector<pipes::buffer> &/* buffers which need to be transferred */, const std::shared_ptr<protocol::ServerPacket> &/* the packet */, std::unique_lock<std::mutex>& /* work lock */);
|
bool prepare_packet_for_write(std::vector<pipes::buffer> &/* buffers which need to be transferred */, const std::shared_ptr<protocol::ServerPacket> &/* the packet */, std::unique_lock<std::mutex>& /* work lock */);
|
||||||
|
|
||||||
|
std::array<protocol::generation_estimator, 9> incoming_generation_estimators{}; /* implementation is thread save */
|
||||||
std::recursive_mutex packet_buffer_lock;
|
std::recursive_mutex packet_buffer_lock;
|
||||||
packet_buffers_t _packet_buffers;
|
command_packet_reassembler _command_fragment_buffers;
|
||||||
uint8_t _packet_buffers_index = 0;
|
|
||||||
|
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 */
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -55,12 +55,9 @@ ts::command_result VoiceClient::handleCommandClientInitIv(Command& command) {
|
|||||||
this->closeConnection(); /* executing final disconnect right now! */
|
this->closeConnection(); /* executing final disconnect right now! */
|
||||||
}
|
}
|
||||||
this->connection->reset();
|
this->connection->reset();
|
||||||
{
|
this->connection->register_initiv_packet();
|
||||||
auto& read_queue = this->connection->packet_buffers()[protocol::COMMAND];
|
|
||||||
unique_lock buffer_lock(read_queue.buffer_lock);
|
|
||||||
read_queue.set_full_index_to(1); /* the first packet (0) is already the clientinitiv packet */
|
|
||||||
}
|
|
||||||
this->state = ConnectionState::INIT_HIGH;
|
this->state = ConnectionState::INIT_HIGH;
|
||||||
|
this->crypto.protocol_encrypted = false;
|
||||||
|
|
||||||
bool use_teaspeak = command.hasParm("teaspeak");
|
bool use_teaspeak = command.hasParm("teaspeak");
|
||||||
if(use_teaspeak) {
|
if(use_teaspeak) {
|
||||||
@ -157,30 +154,27 @@ ts::command_result VoiceClient::handleCommandClientInitIv(Command& command) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
this->connection->getCryptHandler()->block(); //Block until the key is setuped
|
|
||||||
string error;
|
string error;
|
||||||
if(!this->connection->getCryptHandler()->setupSharedSecret(this->crypto.alpha, this->crypto.beta, this->crypto.remote_key.get(), this->server->serverKey(), error)){
|
if(!this->connection->getCryptHandler()->setupSharedSecret(this->crypto.alpha, this->crypto.beta, this->crypto.remote_key.get(), this->server->serverKey(), error)){
|
||||||
this->connection->getCryptHandler()->unblock();
|
|
||||||
logError(this->server->getServerId(), "Could not setup shared secret! (" + error + ")");
|
logError(this->server->getServerId(), "Could not setup shared secret! (" + error + ")");
|
||||||
return ts::command_result{error::vs_critical};
|
return ts::command_result{error::vs_critical};
|
||||||
}
|
}
|
||||||
this->connection->getCryptHandler()->unblock();
|
|
||||||
this->crypto.protocol_encrypted = true;
|
this->crypto.protocol_encrypted = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ts::command_result{error::ok};
|
return ts::command_result{error::ok};
|
||||||
}
|
}
|
||||||
|
|
||||||
ts::command_result VoiceClient::handleCommandClientEk(const std::unique_ptr<protocol::ClientPacket>& packet, Command& cmd) {
|
ts::command_result VoiceClient::handleCommandClientEk(Command& cmd) {
|
||||||
this->last_packet_handshake = system_clock::now();
|
this->last_packet_handshake = system_clock::now();
|
||||||
debugMessage(this->getServerId(), "{} Got client ek!", CLIENT_STR_LOG_PREFIX);
|
debugMessage(this->getServerId(), "{} Got client ek!", CLIENT_STR_LOG_PREFIX);
|
||||||
|
|
||||||
auto client_key = base64::decode(cmd["ek"]);
|
auto client_key = base64::decode(cmd["ek"]);
|
||||||
auto x = this->crypto.chain_data->chain->generatePrivateKey(this->crypto.chain_data->root_key, this->crypto.chain_data->root_index);
|
auto private_key = this->crypto.chain_data->chain->generatePrivateKey(this->crypto.chain_data->root_key, this->crypto.chain_data->root_index);
|
||||||
|
|
||||||
this->connection->getCryptHandler()->setupSharedSecretNew(this->crypto.alpha, this->crypto.beta, (char*) x.data(), client_key.data());
|
this->connection->getCryptHandler()->setupSharedSecretNew(this->crypto.alpha, this->crypto.beta, (char*) private_key.data(), client_key.data());
|
||||||
this->connection->acknowledge_handler.reset();
|
this->connection->acknowledge_handler.reset();
|
||||||
this->crypto.protocol_encrypted = true;
|
this->crypto.protocol_encrypted = true;
|
||||||
this->sendAcknowledge(packet->packetId()); //Send the encrypted acknowledge
|
this->sendAcknowledge(2); //Send the encrypted acknowledge (most the times the second packet; If not we're going into the resend loop)
|
||||||
return ts::command_result{error::ok};
|
return ts::command_result{error::ok};
|
||||||
}
|
}
|
@ -12,14 +12,14 @@ using namespace ts::protocol;
|
|||||||
|
|
||||||
//#define PKT_LOG_PING
|
//#define PKT_LOG_PING
|
||||||
/* should never happen! */
|
/* should never happen! */
|
||||||
void VoiceClient::handlePacketInit(const unique_ptr<ts::protocol::ClientPacket> &) {}
|
void VoiceClient::handlePacketInit(const ts::protocol::IncomingClientPacketParser &) {}
|
||||||
|
|
||||||
//TODO Packet handlers -> move back to voice manager?
|
//TODO Packet handlers -> move back to voice client?
|
||||||
void VoiceClient::handlePacketCommand(const std::unique_ptr<protocol::ClientPacket>& packet) {
|
void VoiceClient::handlePacketCommand(const pipes::buffer_view& command_string) {
|
||||||
std::unique_ptr<Command> command;
|
std::unique_ptr<Command> command;
|
||||||
command_result result{};
|
command_result result{};
|
||||||
try {
|
try {
|
||||||
command = make_unique<Command>(Command::parse(packet->data(), true, !ts::config::server::strict_ut8_mode));
|
command = make_unique<Command>(Command::parse(command_string, true, !ts::config::server::strict_ut8_mode));
|
||||||
} catch(std::invalid_argument& ex) {
|
} catch(std::invalid_argument& ex) {
|
||||||
result = command_result{error::parameter_convert, std::string{ex.what()}};
|
result = command_result{error::parameter_convert, std::string{ex.what()}};
|
||||||
goto handle_error;
|
goto handle_error;
|
||||||
@ -29,7 +29,7 @@ void VoiceClient::handlePacketCommand(const std::unique_ptr<protocol::ClientPack
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(command->command() == "clientek") {
|
if(command->command() == "clientek") {
|
||||||
result = this->handleCommandClientEk(packet, *command);
|
result = this->handleCommandClientEk(*command);
|
||||||
if(result.error_code()) goto handle_error;
|
if(result.error_code()) goto handle_error;
|
||||||
} else if(command->command() == "clientinitiv") {
|
} else if(command->command() == "clientinitiv") {
|
||||||
result = this->handleCommandClientInitIv(*command);
|
result = this->handleCommandClientInitIv(*command);
|
||||||
@ -42,9 +42,9 @@ void VoiceClient::handlePacketCommand(const std::unique_ptr<protocol::ClientPack
|
|||||||
result.release_details();
|
result.release_details();
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceClient::handlePacketPing(const std::unique_ptr<protocol::ClientPacket>& packet) {
|
void VoiceClient::handlePacketPing(const protocol::IncomingClientPacketParser& packet) {
|
||||||
if (packet->type() == PacketTypeInfo::Pong) {
|
if (packet.type() == protocol::PONG) {
|
||||||
uint16_t id = be2le16((char*) packet->data().data_ptr());
|
uint16_t id = be2le16((char*) packet.payload().data_ptr());
|
||||||
if (this->lastPingId == id) {
|
if (this->lastPingId == id) {
|
||||||
#ifdef PKT_LOG_PING
|
#ifdef PKT_LOG_PING
|
||||||
logMessage(this->getServerId(), "{}[Ping] Got a valid pong for ping {}. Required time: {}", CLIENT_STR_LOG_PREFIX, id, duration_cast<microseconds>(system_clock::now() - this->lastPingRequest).count() / 1000.f);
|
logMessage(this->getServerId(), "{}[Ping] Got a valid pong for ping {}. Required time: {}", CLIENT_STR_LOG_PREFIX, id, duration_cast<microseconds>(system_clock::now() - this->lastPingRequest).count() / 1000.f);
|
||||||
@ -64,22 +64,22 @@ void VoiceClient::handlePacketPing(const std::unique_ptr<protocol::ClientPacket>
|
|||||||
logMessage(this->getServerId(), "{}[Ping] Sending pong for client requested ping {}", CLIENT_STR_LOG_PREFIX, packet->packetId());
|
logMessage(this->getServerId(), "{}[Ping] Sending pong for client requested ping {}", CLIENT_STR_LOG_PREFIX, packet->packetId());
|
||||||
#endif
|
#endif
|
||||||
char buffer[2];
|
char buffer[2];
|
||||||
le2be16(packet->packetId(), buffer);
|
le2be16(packet.packet_id(), buffer);
|
||||||
auto pkt = make_shared<ServerPacket>(PacketTypeInfo::Pong, pipes::buffer_view{buffer, 2});
|
auto pkt = make_shared<ServerPacket>(PacketTypeInfo::Pong, pipes::buffer_view{buffer, 2});
|
||||||
pkt->enable_flag(PacketFlag::Unencrypted);
|
pkt->enable_flag(PacketFlag::Unencrypted);
|
||||||
this->connection->sendPacket(pkt);
|
this->connection->sendPacket(pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceClient::handlePacketVoice(const std::unique_ptr<protocol::ClientPacket>& packet) {
|
void VoiceClient::handlePacketVoice(const protocol::IncomingClientPacketParser& packet) {
|
||||||
if (packet->type() == PacketTypeInfo::Voice) {
|
if (packet.type() == protocol::VOICE) {
|
||||||
SpeakingClient::handlePacketVoice(packet->data(), packet->has_flag(PacketFlag::Compressed), packet->has_flag(PacketFlag::Fragmented));
|
SpeakingClient::handlePacketVoice(packet.payload(), (packet.flags() & PacketFlag::Compressed) > 0, (packet.flags() & PacketFlag::Fragmented) > 0);
|
||||||
} else if(packet->type() == PacketTypeInfo::VoiceWhisper) {
|
} else if(packet.type() == protocol::VOICE_WHISPER) {
|
||||||
SpeakingClient::handlePacketVoiceWhisper(packet->data(), packet->has_flag(PacketFlag::NewProtocol));
|
SpeakingClient::handlePacketVoiceWhisper(packet.payload(), (packet.flags() & PacketFlag::NewProtocol) > 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceClient::handlePacketAck(const std::unique_ptr<protocol::ClientPacket>& packet) {
|
void VoiceClient::handlePacketAck(const protocol::IncomingClientPacketParser& packet) {
|
||||||
string error;
|
string error;
|
||||||
if(!this->connection->acknowledge_handler.process_acknowledge(*packet, error))
|
if(!this->connection->acknowledge_handler.process_acknowledge(packet.type(), packet.payload(), error))
|
||||||
debugMessage(this->getServerId(), "{} Failed to handle acknowledge: {}", CLIENT_STR_LOG_PREFIX, error);
|
debugMessage(this->getServerId(), "{} Failed to handle acknowledge: {}", CLIENT_STR_LOG_PREFIX, error);
|
||||||
}
|
}
|
@ -108,7 +108,7 @@ void WebClient::enqueue_raw_packet(const pipes::buffer_view &msg) {
|
|||||||
|
|
||||||
void WebClient::registerMessageProcess() {
|
void WebClient::registerMessageProcess() {
|
||||||
auto weakLock = this->_this;
|
auto weakLock = this->_this;
|
||||||
if(serverInstance->getVoiceServerManager()->getState() == ServerManager::STARTED)
|
if(serverInstance->getVoiceServerManager()->getState() == VirtualServerManager::STARTED)
|
||||||
serverInstance->getVoiceServerManager()->get_executor_loop()->schedule(this->event_handle_packet);
|
serverInstance->getVoiceServerManager()->get_executor_loop()->schedule(this->event_handle_packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include <log/LogUtils.h>
|
#include <log/LogUtils.h>
|
||||||
#include <misc/endianness.h>
|
#include <misc/endianness.h>
|
||||||
#include <src/client/voice/VoiceClient.h>
|
#include <src/client/voice/VoiceClient.h>
|
||||||
#include <src/ServerManager.h>
|
#include <src/VirtualServerManager.h>
|
||||||
#include <netinet/tcp.h>
|
#include <netinet/tcp.h>
|
||||||
#include <src/InstanceHandler.h>
|
#include <src/InstanceHandler.h>
|
||||||
#include <misc/memtracker.h>
|
#include <misc/memtracker.h>
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include "POWHandler.h"
|
#include "POWHandler.h"
|
||||||
#include "src/InstanceHandler.h"
|
#include "src/InstanceHandler.h"
|
||||||
#include "src/ServerManager.h"
|
#include "src/VirtualServerManager.h"
|
||||||
#include "src/client/voice/VoiceClient.h"
|
#include "src/client/voice/VoiceClient.h"
|
||||||
#include <misc/endianness.h>
|
#include <misc/endianness.h>
|
||||||
#include <log/LogUtils.h>
|
#include <log/LogUtils.h>
|
||||||
@ -138,7 +138,7 @@ void POWHandler::send_data(const std::shared_ptr<ts::server::POWHandler::Client>
|
|||||||
le2be16(101, &datagram->data[8]);
|
le2be16(101, &datagram->data[8]);
|
||||||
|
|
||||||
/* 1 byte flags and type */
|
/* 1 byte flags and type */
|
||||||
datagram->data[10] = (uint8_t) (0x08 | 0x80);
|
datagram->data[10] = (uint8_t) (0x08U | 0x80U);
|
||||||
|
|
||||||
memcpy(&datagram->data[11], buffer.data_ptr(), buffer.length());
|
memcpy(&datagram->data[11], buffer.data_ptr(), buffer.length());
|
||||||
this->server->send_datagram(client->socket, datagram);
|
this->server->send_datagram(client->socket, datagram);
|
||||||
@ -275,27 +275,7 @@ void POWHandler::handle_puzzle_solve(const std::shared_ptr<ts::server::POWHandle
|
|||||||
|
|
||||||
auto voice_client = this->register_verified_client(client);
|
auto voice_client = this->register_verified_client(client);
|
||||||
if(voice_client) {
|
if(voice_client) {
|
||||||
auto& read_queue = voice_client->connection->packet_buffers()[protocol::COMMAND];
|
voice_client->connection->force_insert_command(command);
|
||||||
|
|
||||||
auto packet = make_unique<protocol::ClientPacket>(protocol::PacketTypeInfo::Command, command);
|
|
||||||
packet->memory_state.id_branded = false;
|
|
||||||
packet->applyPacketId(0, 0); /* first packet */
|
|
||||||
|
|
||||||
{
|
|
||||||
unique_lock buffer_lock(read_queue.buffer_lock);
|
|
||||||
if(read_queue.current_index() == 0) {
|
|
||||||
if(!read_queue.insert_index(0, move(packet))) {
|
|
||||||
#ifdef POW_ERROR
|
|
||||||
debugMessage(this->get_server_id(), "[POW][{}][Puzzle] Failed to insert command packet into buffer!", net::to_string(client->address));
|
|
||||||
#endif
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
read_queue.push_front(move(packet));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
this->server->schedule_execute(&*voice_client);
|
|
||||||
client->state = LowHandshakeState::COMPLETED;
|
client->state = LowHandshakeState::COMPLETED;
|
||||||
} else {
|
} else {
|
||||||
#ifdef POW_ERROR
|
#ifdef POW_ERROR
|
||||||
|
@ -8,8 +8,7 @@
|
|||||||
#include "VoiceServer.h"
|
#include "VoiceServer.h"
|
||||||
#include "src/VirtualServer.h"
|
#include "src/VirtualServer.h"
|
||||||
|
|
||||||
namespace ts {
|
namespace ts::server {
|
||||||
namespace server {
|
|
||||||
class POWHandler {
|
class POWHandler {
|
||||||
public:
|
public:
|
||||||
enum LowHandshakeState : uint8_t {
|
enum LowHandshakeState : uint8_t {
|
||||||
@ -65,5 +64,4 @@ namespace ts {
|
|||||||
void send_data(const std::shared_ptr<Client> &client /* client */, const pipes::buffer_view &buffer /* buffer */);
|
void send_data(const std::shared_ptr<Client> &client /* client */, const pipes::buffer_view &buffer /* buffer */);
|
||||||
void reset_client(const std::shared_ptr<Client> &client /* client */);
|
void reset_client(const std::shared_ptr<Client> &client /* client */);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
@ -68,15 +68,6 @@ namespace ts {
|
|||||||
|
|
||||||
void unregisterConnection(const std::shared_ptr<QueryClient> &);
|
void unregisterConnection(const std::shared_ptr<QueryClient> &);
|
||||||
|
|
||||||
/*
|
|
||||||
std::string createQueryLogin(const std::string &name, ClientUid uid, std::string = "");
|
|
||||||
bool renameQueryLogin(ClientUid uid, const std::string &targetName);
|
|
||||||
std::string resetQueryPassword(const std::shared_ptr<QueryLoginCredentials>&, std::string = "");
|
|
||||||
|
|
||||||
std::shared_ptr<QueryLoginCredentials> findQueryLoginByName(const std::string &name);
|
|
||||||
std::shared_ptr<QueryLoginCredentials> findQueryLoginByUid(const std::string &uid);
|
|
||||||
*/
|
|
||||||
|
|
||||||
std::deque<std::shared_ptr<QueryAccount>> list_query_accounts(OptionalServerId /* server */);
|
std::deque<std::shared_ptr<QueryAccount>> list_query_accounts(OptionalServerId /* server */);
|
||||||
std::shared_ptr<QueryAccount> create_query_account(const std::string& /* name */, ServerId /* server */, const std::string& /* owner unique id */, const std::string& /* password */);
|
std::shared_ptr<QueryAccount> create_query_account(const std::string& /* name */, ServerId /* server */, const std::string& /* owner unique id */, const std::string& /* password */);
|
||||||
std::shared_ptr<PasswortedQueryAccount> load_password(const std::shared_ptr<QueryAccount>& /* account */);
|
std::shared_ptr<PasswortedQueryAccount> load_password(const std::shared_ptr<QueryAccount>& /* account */);
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#include <log/LogUtils.h>
|
#include <log/LogUtils.h>
|
||||||
#include "src/VirtualServer.h"
|
#include "src/VirtualServer.h"
|
||||||
#include <misc/endianness.h>
|
#include <misc/endianness.h>
|
||||||
#include "../ServerManager.h"
|
#include "src/VirtualServerManager.h"
|
||||||
#include "../InstanceHandler.h"
|
#include "../InstanceHandler.h"
|
||||||
#include <ThreadPool/Timer.h>
|
#include <ThreadPool/Timer.h>
|
||||||
#include <pipes/buffer.h>
|
#include <pipes/buffer.h>
|
||||||
@ -120,7 +120,7 @@ void VoiceServer::triggerWrite(const std::shared_ptr<VoiceClient>& client) {
|
|||||||
this->io->invoke_write(client);
|
this->io->invoke_write(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VoiceServer::schedule_execute(const ts::server::VoiceClient *client) {
|
void VoiceServer::schedule_command_handling(const ts::server::VoiceClient *client) {
|
||||||
auto vmanager = serverInstance->getVoiceServerManager();
|
auto vmanager = serverInstance->getVoiceServerManager();
|
||||||
if(!vmanager)
|
if(!vmanager)
|
||||||
return;
|
return;
|
||||||
@ -161,8 +161,9 @@ void VoiceServer::execute_resend(const std::chrono::system_clock::time_point &no
|
|||||||
|
|
||||||
if(client->state == ConnectionState::CONNECTED) {
|
if(client->state == ConnectionState::CONNECTED) {
|
||||||
client->disconnect(ViewReasonId::VREASON_TIMEOUT, config::messages::timeout::packet_resend_failed, nullptr, true);
|
client->disconnect(ViewReasonId::VREASON_TIMEOUT, config::messages::timeout::packet_resend_failed, nullptr, true);
|
||||||
} else
|
} else {
|
||||||
client->closeConnection(system_clock::now() + seconds(1));
|
client->closeConnection(system_clock::now() + seconds(1));
|
||||||
|
}
|
||||||
} else if(!buffers.empty()) {
|
} else if(!buffers.empty()) {
|
||||||
{
|
{
|
||||||
lock_guard client_write_lock(connection->write_queue_lock);
|
lock_guard client_write_lock(connection->write_queue_lock);
|
||||||
@ -348,16 +349,7 @@ void VoiceServer::handleMessageRead(int fd, short events, void *_event_handle) {
|
|||||||
auto new_address = net::to_string(remote_address);
|
auto new_address = net::to_string(remote_address);
|
||||||
|
|
||||||
auto command = "dummy_ipchange old_ip=" + old_address + " new_ip=" + new_address;
|
auto command = "dummy_ipchange old_ip=" + old_address + " new_ip=" + new_address;
|
||||||
auto packet = make_unique<protocol::ClientPacket>(protocol::PacketTypeInfo::Command, pipes::buffer_view{command.data(), command.length()});
|
client->connection->force_insert_command(pipes::buffer_view{command.data(), command.length()});
|
||||||
packet->memory_state.id_branded = false;
|
|
||||||
packet->applyPacketId(0, 0);
|
|
||||||
|
|
||||||
{
|
|
||||||
auto& buffer = client->connection->packet_buffers()[protocol::COMMAND];
|
|
||||||
unique_lock buffer_lock(buffer.buffer_lock);
|
|
||||||
buffer.push_front(move(packet));
|
|
||||||
}
|
|
||||||
|
|
||||||
memcpy(&client->remote_address, &remote_address, sizeof(remote_address));
|
memcpy(&client->remote_address, &remote_address, sizeof(remote_address));
|
||||||
io::DatagramPacket::extract_info(message, client->address_info);
|
io::DatagramPacket::extract_info(message, client->address_info);
|
||||||
}
|
}
|
||||||
@ -367,15 +359,7 @@ void VoiceServer::handleMessageRead(int fd, short events, void *_event_handle) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(client->state != ConnectionState::DISCONNECTED){
|
if(client->state != ConnectionState::DISCONNECTED){
|
||||||
#ifdef VC_USE_READ_QUEUE
|
client->connection->handle_incoming_datagram(read_buffer.view(0, bytes_read));
|
||||||
{
|
|
||||||
lock_guard<recursive_mutex> lock(client->connection->queueLock);
|
|
||||||
client->connection->readQueue.push_back(read_buffer.view(0, readBytes).dup(buffer::allocate_buffer(readBytes)));
|
|
||||||
}
|
|
||||||
while(client->state != ConnectionState::DISCONNECTED && client->connection->handleNextDatagram());
|
|
||||||
#else
|
|
||||||
client->connection->handleDatagramReceived(read_buffer.view(0, bytes_read));
|
|
||||||
#endif
|
|
||||||
client = nullptr;
|
client = nullptr;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -72,7 +72,7 @@ namespace ts {
|
|||||||
std::deque<std::shared_ptr<VoiceClient>> activeConnections;
|
std::deque<std::shared_ptr<VoiceClient>> activeConnections;
|
||||||
public: //lib event
|
public: //lib event
|
||||||
void triggerWrite(const std::shared_ptr<VoiceClient> &);
|
void triggerWrite(const std::shared_ptr<VoiceClient> &);
|
||||||
void schedule_execute(VoiceClient const *);
|
void schedule_command_handling(VoiceClient const *client);
|
||||||
|
|
||||||
void tickHandshakingClients();
|
void tickHandshakingClients();
|
||||||
void execute_resend(const std::chrono::system_clock::time_point& /* now */, std::chrono::system_clock::time_point& /* next resend */);
|
void execute_resend(const std::chrono::system_clock::time_point& /* now */, std::chrono::system_clock::time_point& /* next resend */);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
#include <src/SignalHandler.h>
|
#include <src/SignalHandler.h>
|
||||||
#include <src/VirtualServer.h>
|
#include <src/VirtualServer.h>
|
||||||
#include <src/client/ConnectedClient.h>
|
#include <src/client/ConnectedClient.h>
|
||||||
#include <src/ServerManager.h>
|
#include <src/VirtualServerManager.h>
|
||||||
#include <src/InstanceHandler.h>
|
#include <src/InstanceHandler.h>
|
||||||
#include <log/LogUtils.h>
|
#include <log/LogUtils.h>
|
||||||
#include <src/ShutdownHelper.h>
|
#include <src/ShutdownHelper.h>
|
||||||
|
@ -112,15 +112,12 @@ void WebListManager::tick() {
|
|||||||
logError(_entry->server->getServerId(), "[WebList] Status update failed. Error: " + error);
|
logError(_entry->server->getServerId(), "[WebList] Status update failed. Error: " + error);
|
||||||
|
|
||||||
if(_entry->fail_count == 1 && retry) {
|
if(_entry->fail_count == 1 && retry) {
|
||||||
logMessage(_entry->server->getServerId(), "[WebList] Scheduling next update attempt in 5 seconds.");
|
|
||||||
_entry->scheduled_request = now + seconds(5);
|
|
||||||
} else if(_entry->fail_count == 2 && retry) {
|
|
||||||
logMessage(_entry->server->getServerId(), "[WebList] Scheduling next update attempt in 30 seconds.");
|
|
||||||
_entry->scheduled_request = now + seconds(30);
|
|
||||||
} else if(_entry->fail_count == 3 && retry) {
|
|
||||||
logMessage(_entry->server->getServerId(), "[WebList] Scheduling next update attempt in 1 minute.");
|
logMessage(_entry->server->getServerId(), "[WebList] Scheduling next update attempt in 1 minute.");
|
||||||
_entry->scheduled_request = now + seconds(60);
|
_entry->scheduled_request = now + seconds(60);
|
||||||
} else if(_entry->fail_count >= 4) {
|
} else if(_entry->fail_count == 2 && retry) {
|
||||||
|
logMessage(_entry->server->getServerId(), "[WebList] Scheduling next update attempt in 5 minutes.");
|
||||||
|
_entry->scheduled_request = now + seconds(5 * 60);
|
||||||
|
} else if(_entry->fail_count >= 3) {
|
||||||
logMessage(_entry->server->getServerId(), "[WebList] Scheduling next update attempt in 10 minutes.");
|
logMessage(_entry->server->getServerId(), "[WebList] Scheduling next update attempt in 10 minutes.");
|
||||||
_entry->scheduled_request = now + minutes(10);
|
_entry->scheduled_request = now + minutes(10);
|
||||||
}
|
}
|
||||||
|
2
shared
2
shared
@ -1 +1 @@
|
|||||||
Subproject commit c9bd9054f6ff4507cb3d919b544beb3a450e7f39
|
Subproject commit d13c1e6d6812aa568b6cc7215100828016b92582
|
Loading…
Reference in New Issue
Block a user