Updated the logging system

This commit is contained in:
WolverinDEV 2019-11-23 21:16:55 +01:00
parent b7d60361c0
commit fb5dc72970
28 changed files with 135 additions and 104 deletions

@ -12,7 +12,7 @@ using namespace std::chrono;
using namespace ts; using namespace ts;
using namespace license; using namespace license;
#define DEBUG_LICENSE_CLIENT //#define DEBUG_LICENSE_CLIENT
#define CERR(message) LICENSE_FERR(this, CouldNotConnectException, message) #define CERR(message) LICENSE_FERR(this, CouldNotConnectException, message)
@ -91,7 +91,7 @@ void LicenceRequest::handleEventWrite(int fd, short event, void* ptrClient) {
void LicenceRequest::sendPacket(const protocol::packet& packet) { void LicenceRequest::sendPacket(const protocol::packet& packet) {
if(this->state == protocol::UNCONNECTED || this->state == protocol::DISCONNECTING) { if(this->state == protocol::UNCONNECTED || this->state == protocol::DISCONNECTING) {
if(this->verbose) if(this->verbose)
logError("Tried to send a packet to an unconnected remote!"); logError(LOG_GENERAL, "Tried to send a packet to an unconnected remote!");
return; return;
} }
packet.prepare(); packet.prepare();
@ -243,7 +243,7 @@ void LicenceRequest::closeConnection() {
#ifdef DEBUG_LICENSE_CLIENT #ifdef DEBUG_LICENSE_CLIENT
if(this->verbose) { if(this->verbose) {
debugMessage("Running close in a new thread"); debugMessage(LOG_GENERAL,"Running close in a new thread");
this->closeThread->name("License request close"); this->closeThread->name("License request close");
} }
#endif #endif

@ -301,7 +301,7 @@ int main(int argc, char** argv) {
strftime(timeBuffer, 32, "%c", stime); strftime(timeBuffer, 32, "%c", stime);
logMessageFmt(true, LOG_GENERAL, strobf(" §aLicense expires: §e").string() + string(timeBuffer)); logMessageFmt(true, LOG_GENERAL, strobf(" §aLicense expires: §e").string() + string(timeBuffer));
} }
logMessage(string() + strobf(" §aLicense valid : ").string() + (ts::config::license_original->isValid() ? strobf("§ayes").string() : strobf("§cno").string())); logMessageFmt(true, LOG_GENERAL, string() + strobf(" §aLicense valid : ").string() + (ts::config::license_original->isValid() ? strobf("§ayes").string() : strobf("§cno").string()));
logMessageFmt(true, LOG_GENERAL, strobf("[]---------------------------------------------------------[]").string()); logMessageFmt(true, LOG_GENERAL, strobf("[]---------------------------------------------------------[]").string());
} }
@ -322,11 +322,11 @@ int main(int argc, char** argv) {
else if(ts::config::geo::type == geoloc::PROVIDER_IP2LOCATION) else if(ts::config::geo::type == geoloc::PROVIDER_IP2LOCATION)
geoloc::provider = new geoloc::IP2LocationProvider(ts::config::geo::mappingFile); geoloc::provider = new geoloc::IP2LocationProvider(ts::config::geo::mappingFile);
else { else {
logCritical("Invalid geo resolver type!"); logCritical(LOG_GENERAL,"Invalid geo resolver type!");
} }
if(geoloc::provider && !geoloc::provider->load(errorMessage)) { if(geoloc::provider && !geoloc::provider->load(errorMessage)) {
logCritical("Could not setup geoloc! Fallback to default flag!"); logCritical(LOG_GENERAL,"Could not setup geoloc! Fallback to default flag!");
logCritical("Message: " + errorMessage); logCritical(LOG_GENERAL,"Message: {}", errorMessage);
geoloc::provider = nullptr; geoloc::provider = nullptr;
errorMessage = ""; errorMessage = "";
} }
@ -335,8 +335,8 @@ int main(int argc, char** argv) {
geoloc::provider_vpn = new geoloc::IPCatBlocker(ts::config::geo::vpn_file); geoloc::provider_vpn = new geoloc::IPCatBlocker(ts::config::geo::vpn_file);
if(geoloc::provider_vpn && !geoloc::provider_vpn->load(errorMessage)) { if(geoloc::provider_vpn && !geoloc::provider_vpn->load(errorMessage)) {
logCritical("Could not setup vpn detector!"); logCritical(LOG_GENERAL,"Could not setup vpn detector!");
logCritical("Message: " + errorMessage); logCritical(LOG_GENERAL,"Message: {}", errorMessage);
geoloc::provider_vpn = nullptr; geoloc::provider_vpn = nullptr;
errorMessage = ""; errorMessage = "";
} }
@ -345,7 +345,7 @@ int main(int argc, char** argv) {
sql = new ts::server::SqlDataManager(); sql = new ts::server::SqlDataManager();
if(!sql->initialize(errorMessage)) { if(!sql->initialize(errorMessage)) {
logCritical("Could not initialize SQL!"); logCriticalFmt(true, LOG_GENERAL, "Could not initialize SQL!");
if(errorMessage.find("database is locked") != string::npos) { if(errorMessage.find("database is locked") != string::npos) {
logCriticalFmt(true, LOG_GENERAL, "----------------------------[ ATTENTION ]----------------------------"); logCriticalFmt(true, LOG_GENERAL, "----------------------------[ ATTENTION ]----------------------------");
logCriticalFmt(true, LOG_GENERAL, "{:^69}", "You're database is already in use!"); logCriticalFmt(true, LOG_GENERAL, "{:^69}", "You're database is already in use!");

@ -267,7 +267,7 @@ void remapValue(YAML::Node& node, const string &oldPath, const string &newPath){
if(old.size() > 1) { if(old.size() > 1) {
auto oldNode = old[old.size() - 1]; auto oldNode = old[old.size() - 1];
oldNode = YAML::Null; oldNode = YAML::Null;
if(old[old.size() - 2].remove(oldNode)) logError("Could not remove old config entry"); if(old[old.size() - 2].remove(oldNode)) logError(LOG_GENERAL, "Could not remove old config entry");
} }
} }
@ -350,8 +350,8 @@ vector<string> config::parseConfig(const std::string& path) {
} }
{ {
if(config_version != CURRENT_CONFIG_VERSION) { if(config_version != CURRENT_CONFIG_VERSION) {
logMessage("You're using an outdated config."); logMessage(LOG_GENERAL, "You're using an outdated config.");
logMessage("Updating config"); logMessage(LOG_GENERAL, "Updating config");
switch (config_version){ switch (config_version){
case 1: case 1:

@ -65,7 +65,7 @@ int collectData(deque<shared_ptr<ClientDatabaseInfo>>* list, int length, char**
else if(strcmp(columns[index], "lastName") == 0) else if(strcmp(columns[index], "lastName") == 0)
entry->lastName = values[index]; entry->lastName = values[index];
else if(strcmp(columns[index], "serverId") == 0); else if(strcmp(columns[index], "serverId") == 0);
else logError("Invalid db key for manager data. Key: " + string(columns[index])); else logError(LOG_GENERAL, "Invalid db key for manager data. Key: {}", columns[index]);
list->push_back(entry); list->push_back(entry);
return 0; return 0;
@ -82,7 +82,7 @@ std::deque<std::shared_ptr<ClientDatabaseInfo>> DatabaseHelper::queryDatabaseInf
for(auto elm : list) for(auto elm : list)
query += " `cldbid` = " + to_string(elm) + " OR"; query += " `cldbid` = " + to_string(elm) + " OR";
query = query.substr(0, query.length() - 3) + ")"; query = query.substr(0, query.length() - 3) + ")";
logTrace("[SQL] queryDatabseInfo(...) -> " + query); logTrace(server ? server->getServerId() : 0, "[SQL] queryDatabseInfo(...) -> {}", query);
auto state = sql::command(this->sql, query, variable{":serverId", server ? server->getServerId() : 0}).query(std::function<decltype(collectData)>(collectData), &result); auto state = sql::command(this->sql, query, variable{":serverId", server ? server->getServerId() : 0}).query(std::function<decltype(collectData)>(collectData), &result);
auto pf = LOG_SQL_CMD; auto pf = LOG_SQL_CMD;
pf(state); pf(state);
@ -112,7 +112,7 @@ std::deque<std::shared_ptr<ClientDatabaseInfo>> DatabaseHelper::queryDatabaseInf
for(const auto &elm : list) for(const auto &elm : list)
query += " `clientUid` = '" + elm + "' OR"; query += " `clientUid` = '" + elm + "' OR";
query = query.substr(0, query.length() - 3) + ")"; query = query.substr(0, query.length() - 3) + ")";
logTrace("[SQL] queryDatabseInfoByUid(...) -> " + query); logTrace(server ? server->getServerId() : 0, "[SQL] queryDatabseInfoByUid(...) -> {}", query);
auto state = sql::command(this->sql, query, variable{":serverId", server ? server->getServerId() : 0}).query(function<decltype(collectData)>(collectData), &result); auto state = sql::command(this->sql, query, variable{":serverId", server ? server->getServerId() : 0}).query(function<decltype(collectData)>(collectData), &result);
auto pf = LOG_SQL_CMD; auto pf = LOG_SQL_CMD;
pf(state); pf(state);

@ -248,7 +248,7 @@ bool InstanceHandler::startInstance() {
} }
this->sslMgr = new ssl::SSLManager(); this->sslMgr = new ssl::SSLManager();
if(!this->sslMgr->initialize()) { if(!this->sslMgr->initialize()) {
logCritical("Failed to initialize ssl manager."); logCritical(LOG_GENERAL, "Failed to initialize ssl manager.");
return false; return false;
} }
@ -363,7 +363,7 @@ FwIDAQAB
-----END PUBLIC KEY----- -----END PUBLIC KEY-----
)", error, true); )", error, true);
if(!rsa) { //TODO just disable the forum verification if(!rsa) { //TODO just disable the forum verification
logCritical("Failed to initialize WebClient TeaForum key! (" + error + ")"); logCritical(LOG_GENERAL, "Failed to initialize WebClient TeaForum key! ({})", error);
return false; return false;
} }
this->web_event_loop = make_shared<webio::LoopManager>(); this->web_event_loop = make_shared<webio::LoopManager>();

@ -62,10 +62,10 @@ bool ServerManager::initialize(bool autostart) {
this->execute_loop->initialize(1); this->execute_loop->initialize(1);
this->state = State::STARTING; this->state = State::STARTING;
logMessage("Generating server puzzles..."); logMessage(LOG_INSTANCE, "Generating server puzzles...");
auto start = system_clock::now(); auto start = system_clock::now();
this->puzzles->precomputePuzzles(config::voice::DefaultPuzzlePrecomputeSize); this->puzzles->precomputePuzzles(config::voice::DefaultPuzzlePrecomputeSize);
logMessage("Puzzles generated! Time required: " + to_string(duration_cast<milliseconds>(system_clock::now() - start).count()) + "ms"); logMessage(LOG_INSTANCE, "Puzzles generated! Time required: " + to_string(duration_cast<milliseconds>(system_clock::now() - start).count()) + "ms");
size_t serverCount = 0; size_t serverCount = 0;
sql::command(this->handle->getSql(), "SELECT COUNT(`serverId`) FROM `servers`").query([](size_t& ptr, int, char** v, char**) { ptr = stoll(v[0]); return 0; }, serverCount); sql::command(this->handle->getSql(), "SELECT COUNT(`serverId`) FROM `servers`").query([](size_t& ptr, int, char** v, char**) { ptr = stoll(v[0]); return 0; }, serverCount);
@ -139,7 +139,7 @@ bool ServerManager::initialize(bool autostart) {
if(!server->start(msg)) if(!server->start(msg))
logError(server->getServerId(), "Failed to start server.\n Message: " + msg); logError(server->getServerId(), "Failed to start server.\n Message: " + msg);
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
logError(string() + "Could not start server! Got an active exception. Message " + ex.what()); logError(server->getServerId(), "Could not start server! Got an active exception. Message {}", ex.what());
} }
} }
if(id > 0) if(id > 0)
@ -400,9 +400,9 @@ void ServerManager::executeAutostart() {
string msg; string msg;
try { try {
if(!server->start(msg)) if(!server->start(msg))
logError(server->getServerId(), "Failed to start server.\n Message: " + msg); logError(server->getServerId(), "Failed to start server.\n Message:{}", msg);
} catch (const std::exception& ex) { } catch (const std::exception& ex) {
logError(string() + "Could not start server! Got an active exception. Message " + ex.what()); logError(server->getServerId(), "Could not start server! Got an active exception. Message {}", ex.what());
} }
} }
} }

@ -657,7 +657,7 @@ std::shared_ptr<TSServer> ServerManager::createServerFromSnapshot(shared_ptr<TSS
} }
} }
debugMessage("Wait for success!"); debugMessage(serverId, "Wait for success!");
for(const auto& future : futures) { for(const auto& future : futures) {
auto result = future.second.waitAndGet({-1, "timeout"}, chrono::system_clock::now() + chrono::seconds(5)); auto result = future.second.waitAndGet({-1, "timeout"}, chrono::system_clock::now() + chrono::seconds(5));

@ -83,7 +83,7 @@ void server::cancelShutdown(bool notify) {
current->active = false; current->active = false;
current->shutdownNotify.notify_all(); current->shutdownNotify.notify_all();
if(!threads::save_join(current->shutdown_thread)) { if(!threads::save_join(current->shutdown_thread)) {
logCritical("Could not terminal shutdown thread!"); logCritical(LOG_GENERAL, "Could not terminate shutdown thread!");
current->shutdown_thread.detach(); current->shutdown_thread.detach();
} }
currentShutdown = nullptr; currentShutdown = nullptr;

@ -14,12 +14,12 @@ namespace fs = std::experimental::filesystem;
google_breakpad::ExceptionHandler* globalExceptionHandler = nullptr; google_breakpad::ExceptionHandler* globalExceptionHandler = nullptr;
#define SIG(s, c) \ #define SIG(s, c) \
if(signal(s, c) != nullptr) logError(lstream << "Cant setup " #s); if(signal(s, c) != nullptr) logError(LOG_GENERAL, "Cant setup signal handler for " #s);
extern bool mainThreadDone; extern bool mainThreadDone;
static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded) { static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded) {
logCritical("The server crashed!"); logCritical(LOG_GENERAL, "The server crashed!");
try { try {
if(!fs::exists(fs::u8path(ts::config::crash_path))) if(!fs::exists(fs::u8path(ts::config::crash_path)))
fs::create_directories(fs::u8path(ts::config::crash_path)); fs::create_directories(fs::u8path(ts::config::crash_path));
@ -27,9 +27,9 @@ static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
auto path = fs::u8path(descriptor.path()); auto path = fs::u8path(descriptor.path());
path = fs::u8path(ts::config::crash_path + "crash_dump_" + path.filename().string()); path = fs::u8path(ts::config::crash_path + "crash_dump_" + path.filename().string());
fs::rename(fs::u8path(descriptor.path()), path); fs::rename(fs::u8path(descriptor.path()), path);
logCritical("Wrote crash dump to " + path.relative_path().string()); logCritical(LOG_GENERAL, "Wrote crash dump to " + path.relative_path().string());
} catch (...) { } catch (...) {
logCritical("Failed to write/move crash dump!"); logCritical(LOG_GENERAL, "Failed to write/move crash dump!");
} }
if(std::current_exception()) { if(std::current_exception()) {
logCritical(LOG_GENERAL, "Exception reached stack root and cause the server to crash!"); logCritical(LOG_GENERAL, "Exception reached stack root and cause the server to crash!");
@ -40,10 +40,10 @@ static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
logCritical(LOG_GENERAL, " Message: {}", ex.what()); logCritical(LOG_GENERAL, " Message: {}", ex.what());
} catch(...) {} } catch(...) {}
} }
logCritical("Please report this crash to the TeaSpeak maintainer WolverinDEV"); logCritical(LOG_GENERAL, "Please report this crash to the TeaSpeak maintainer WolverinDEV");
logCritical("Official issue and bug tracker url: https://github.com/TeaSpeak/TeaSpeak/issues"); logCritical(LOG_GENERAL, "Official issue and bug tracker url: https://github.com/TeaSpeak/TeaSpeak/issues");
logCritical("Any reports of crashes are useless if you not provide the above generated crashlog!"); logCritical(LOG_GENERAL, "Any reports of crashes are useless if you not provide the above generated crashlog!");
logCritical("Stopping server"); logCritical(LOG_GENERAL, "Stopping server");
ts::server::shutdownInstance(ts::config::messages::applicationCrashed); ts::server::shutdownInstance(ts::config::messages::applicationCrashed);
while(!mainThreadDone) threads::self::sleep_for(chrono::seconds(1)); while(!mainThreadDone) threads::self::sleep_for(chrono::seconds(1));
return succeeded; return succeeded;
@ -51,11 +51,11 @@ static bool dumpCallback(const google_breakpad::MinidumpDescriptor& descriptor,
std::atomic spawn_failed_count = 0; std::atomic spawn_failed_count = 0;
bool ts::syssignal::setup() { bool ts::syssignal::setup() {
logMessage("Setting up exception handler"); logMessage(LOG_GENERAL, "Setting up exception handler");
globalExceptionHandler = new google_breakpad::ExceptionHandler(google_breakpad::MinidumpDescriptor("."), nullptr, dumpCallback, nullptr, true, -1); globalExceptionHandler = new google_breakpad::ExceptionHandler(google_breakpad::MinidumpDescriptor("."), nullptr, dumpCallback, nullptr, true, -1);
SIG(SIGTERM, &ts::syssignal::handleStopSignal); SIG(SIGTERM, &ts::syssignal::handleStopSignal);
if(isatty(fileno(stdin))) //We cant listen for this siganl if stdin ist a atty if(isatty(fileno(stdin))) //We cant listen for this signal if stdin ist a atty
SIG(SIGINT, &ts::syssignal::handleStopSignal); SIG(SIGINT, &ts::syssignal::handleStopSignal);
return true; return true;

@ -183,14 +183,17 @@ bool TSServer::assignDefaultChannel(const shared_ptr<ConnectedClient>& client, b
channel = this->channelTree->findChannelByPath(str); channel = this->channelTree->findChannelByPath(str);
if (channel) { if (channel) {
if(!channel->permission_granted(permission::i_channel_needed_join_power, client->calculate_permission_value(permission::i_channel_join_power, channel->channelId()), false)) { if(!channel->permission_granted(permission::i_channel_needed_join_power, client->calculate_permission_value(permission::i_channel_join_power, channel->channelId()), false)) {
logMessage(this->serverId, "[{}] Client tried to connect to a channel which he hasn't permission for. Channel: {} ({})", CLIENT_STR_LOG_PREFIX_(client), channel->channelId(), channel->name()); logMessage(this->serverId, "{} Client tried to connect to a channel which he hasn't permission for. Channel: {} ({})", CLIENT_STR_LOG_PREFIX_(client), channel->channelId(), channel->name());
channel = nullptr; channel = nullptr;
} else if (!channel->passwordMatch(client->properties()[property::CLIENT_DEFAULT_CHANNEL_PASSWORD], true) && client->permissionValue(permission::PERMTEST_ORDERED, permission::b_channel_join_ignore_password, channel) < 1) { } else if (!channel->passwordMatch(client->properties()[property::CLIENT_DEFAULT_CHANNEL_PASSWORD], true) && client->permissionValue(permission::PERMTEST_ORDERED, permission::b_channel_join_ignore_password, channel) < 1) {
logMessage(this->serverId, "[{}] Client tried to connect to a channel which is password protected and he hasn't the right password. Channel: {} ({})", CLIENT_STR_LOG_PREFIX_(client), channel->channelId(), channel->name()); logMessage(this->serverId, "{} Client tried to connect to a channel which is password protected and he hasn't the right password. Channel: {} ({})", CLIENT_STR_LOG_PREFIX_(client), channel->channelId(), channel->name());
channel = nullptr; channel = nullptr;
} }
} else } else
logMessage("Client " + client->getDisplayName() + "/" + client->getUid() + " tried to join on a not existing channel. Name: " + client->properties()[property::CLIENT_DEFAULT_CHANNEL].as<std::string>()); logMessage(this->serverId, "{} Client {}/{} tried to join on a not existing channel. Name: {}",
CLIENT_STR_LOG_PREFIX_(client),
client->getDisplayName(), client->getUid(),
client->properties()[property::CLIENT_DEFAULT_CHANNEL].as<std::string>());
} }
if(!channel) channel = this->channelTree->getDefaultChannel(); if(!channel) channel = this->channelTree->getDefaultChannel();
if(!channel) return false; if(!channel) return false;

@ -493,7 +493,7 @@ void TSServer::stop(const std::string& reason) {
} else if(cl->getType() == CLIENT_INTERNAL) { } else if(cl->getType() == CLIENT_INTERNAL) {
} else { } else {
logError("Got manager with unknown type: " + to_string(cl->getType())); logError(this->serverId, "Got client with unknown type: " + to_string(cl->getType()));
} }
} }
this->musicManager->disconnectBots(); this->musicManager->disconnectBots();

@ -218,7 +218,7 @@ inline std::shared_ptr<TreeView::LinkedTreeEntry> buildChannelTree(ServerId serv
if(channel->channelOrder() != 0) { if(channel->channelOrder() != 0) {
if(channel->channelOrder() == channel->channelId()) { if(channel->channelOrder() == channel->channelId()) {
brokenTree = true; brokenTree = true;
logError("Channel order refers to itself! (Resetting)"); logError(serverId, "Channel order refers to itself! (Resetting)");
channel->properties()[property::CHANNEL_ORDER] = 0; channel->properties()[property::CHANNEL_ORDER] = 0;
continue; continue;
} }
@ -475,7 +475,7 @@ void ServerChannelTree::loadChannelsFromDatabase() {
return; return;
} }
logMessage(this->getServerId(), lstream << "Got " << this->tmpChannelList.size() << " saved channels" << endl); logMessage(this->getServerId(), "Loaded {} saved channels. Assembling...", this->tmpChannelList.size());
this->initializeTempParents(); this->initializeTempParents();
this->buildChannelTreeFromTemp(); this->buildChannelTreeFromTemp();
this->validateChannelNames(); this->validateChannelNames();

@ -1,5 +1,7 @@
#include <memory> #include <memory>
#include <spdlog/sinks/rotating_file_sink.h>
#include <iostream> #include <iostream>
#include <bitset> #include <bitset>
#include <algorithm> #include <algorithm>
@ -475,7 +477,8 @@ CommandResult ConnectedClient::handleCommandServerEdit(Command &cmd) {
serverInstance->getWebList()->enable_report(target_server); serverInstance->getWebList()->enable_report(target_server);
else else
serverInstance->getWebList()->disable_report(target_server); serverInstance->getWebList()->disable_report(target_server);
debugMessage(string() + "Changed weblist state to -> " + (cmd["virtualserver_weblist_enabled"].as<bool>() ? "activated" : "disabled")); debugMessage(target_server->getServerId(), "Changed weblist state to -> {}",
cmd["virtualserver_weblist_enabled"].as<bool>() ? "activated" : "disabled");
} }
} SERVEREDIT_CHK_PROP_CACHED("virtualserver_needed_identity_security_level", permission::b_virtualserver_modify_needed_identity_security_level, int) } } SERVEREDIT_CHK_PROP_CACHED("virtualserver_needed_identity_security_level", permission::b_virtualserver_modify_needed_identity_security_level, int) }
@ -3812,7 +3815,7 @@ CommandResult ConnectedClient::handleCommandFTDeleteFile(Command &cmd) {
for (const auto &file : files) { for (const auto &file : files) {
if (!file) continue; if (!file) continue;
if (!serverInstance->getFileServer()->deleteFile(file)) { if (!serverInstance->getFileServer()->deleteFile(file)) {
logCritical(this->getServerId(), lstream << "Cound not delete file " << file->path << "/" << file->name); logCritical(this->getServerId(), "Could not delete file {}/{}", file->path, file->name);
} }
} }
@ -7370,8 +7373,12 @@ CommandResult ConnectedClient::handleCommandLogView(ts::Command& cmd) {
PERM_CHECKR(permission::b_virtualserver_log_view, 1, true); PERM_CHECKR(permission::b_virtualserver_log_view, 1, true);
for(const auto& sink : logger::logger(target_server)->sinks()) { for(const auto& sink : logger::logger(target_server)->sinks()) {
if(dynamic_pointer_cast<logger::ColoredFileSink>(sink)) { if(dynamic_pointer_cast<spdlog::sinks::rotating_file_sink_mt>(sink)) {
log_path = dynamic_pointer_cast<logger::ColoredFileSink>(sink)->_file_helper.filename(); log_path = dynamic_pointer_cast<spdlog::sinks::rotating_file_sink_mt>(sink)->filename();
break;
} else if(dynamic_pointer_cast<spdlog::sinks::rotating_file_sink_st>(sink)) {
log_path = dynamic_pointer_cast<spdlog::sinks::rotating_file_sink_st>(sink)->filename();
break;
} }
} }
if(log_path.empty()) if(log_path.empty())

@ -220,8 +220,12 @@ bool DataClient::permissionGranted(PermissionTestType test, permission::Permissi
auto client = dynamic_cast<ConnectedClient*>(this); auto client = dynamic_cast<ConnectedClient*>(this);
if(client) if(client)
serverId = client->getServerId(); serverId = client->getServerId();
debugMessage(serverId, lstream << "[Permission] Value test result for test type " << test << "."); debugMessage(serverId, "[Permission] Value test result for test type {}.", test);
debugMessage(serverId, lstream << "[Permission] Permission: " << permission::resolvePermissionData(type)->name << " Required value: " << required << " Gained value: " << value << " Force required: " << force_granted << " Channel: " << (target ? target->name() : "none") << " Result: " << result); debugMessage(serverId,
"[Permission] Permission: {} Required value: {} Gained value: {} Force required: {} Channel: {} Result: {}",
permission::resolvePermissionData(type)->name,
required, value, force_granted, (target ? target->name() : "none"), result
);
}; };
#endif #endif
return result; return result;
@ -237,8 +241,12 @@ bool DataClient::permissionGrantGranted(PermissionTestType test, permission::Per
auto client = dynamic_cast<ConnectedClient*>(this); auto client = dynamic_cast<ConnectedClient*>(this);
if(client) if(client)
serverId = client->getServerId(); serverId = client->getServerId();
debugMessage(serverId, lstream << "[Permission] Grant test result for test type " << test << "."); debugMessage(serverId, "[Permission] Grant test result for test type {}.", test);
debugMessage(serverId, lstream << "[Permission] Permission: " << permission::resolvePermissionData(type)->name << " Required value: " << required << " Gained value: " << value << " Force required: " << force_granted << " Channel: " << (target ? target->name() : "none") << " Result: " << result); debugMessage(serverId,
"[Permission] Permission: {} Required value: {} Gained value: {} Force required: {} Channel: {} Result: {}",
permission::resolvePermissionData(type)->name,
required, value, force_granted, (target ? target->name() : "none"), result
);
}; };
#endif #endif
return result; return result;

@ -27,7 +27,7 @@ void InternalClient::sendCommand(const ts::Command &command, bool low) {
} }
bool InternalClient::closeConnection(const std::chrono::system_clock::time_point& timeout) { bool InternalClient::closeConnection(const std::chrono::system_clock::time_point& timeout) {
logError("Internal manager is force to disconnect?"); logError(this->getServerId(), "Internal client is force to disconnect?");
if(this->server) if(this->server)
this->server->unregisterInternalClient(static_pointer_cast<InternalClient>(_this.lock())); this->server->unregisterInternalClient(static_pointer_cast<InternalClient>(_this.lock()));

@ -57,39 +57,51 @@ CommandResult SpeakingClient::handleCommandHandshakeBegin(Command& cmd) { //If !
try { try {
this->handshake.identityData = make_shared<Json::Value>(); this->handshake.identityData = make_shared<Json::Value>();
this->handshake.proof_message = cmd["data"].string(); this->handshake.proof_message = cmd["data"].string();
Json::Reader reader;
std::istringstream stream(this->handshake.proof_message);
reader.parse(stream, *this->handshake.identityData);
if(!stream) return {findError("web_handshake_invalid"), "invalid json!"};
if((*this->handshake.identityData)["user_id"].isNull()) return {findError("web_handshake_invalid"), "Missing json data!"}; std::string error{};
if((*this->handshake.identityData)["user_name"].isNull()) return {findError("web_handshake_invalid"), "Missing json data!"}; Json::CharReaderBuilder rbuilder{};
if((*this->handshake.identityData)["user_group"].isNull()) return {findError("web_handshake_invalid"), "Missing json data!"}; const std::unique_ptr<Json::CharReader> reader(rbuilder.newCharReader());
if((*this->handshake.identityData)["user_groups"].isNull()) return {findError("web_handshake_invalid"), "Missing json data!"};
if((*this->handshake.identityData)["data_age"].isNull()) return {findError("web_handshake_invalid"), "Missing json data!"}; auto& json_str = this->handshake.proof_message;
if(!reader->parse(json_str.data(), json_str.data() + json_str.size(), &*this->handshake.identityData, &error)) {
debugMessage(this->getServerId(), "[{}] Failed to parse forum account data: {}", error);
return {findError("web_handshake_invalid"), "invalid json!"};
}
auto& json_data = *this->handshake.identityData;
if(json_data["user_id"].isNull())
return {findError("web_handshake_invalid"), "Missing json data (user_id)!"};
if(json_data["user_name"].isNull())
return {findError("web_handshake_invalid"), "Missing json data (user_name)!"};
if(json_data["user_group"].isNull())
return {findError("web_handshake_invalid"), "Missing json data (user_group)!"};
if(json_data["user_groups"].isNull())
return {findError("web_handshake_invalid"), "Missing json data (user_groups)!"};
if(json_data["data_age"].isNull())
return {findError("web_handshake_invalid"), "Missing json data (data_age)!"};
//Type test //Type test
(*this->handshake.identityData)["user_id"].asInt64(); json_data["user_id"].asInt64();
if((*this->handshake.identityData)["data_age"].asUInt64() < duration_cast<milliseconds>((system_clock::now() - hours(72)).time_since_epoch()).count()) if(json_data["data_age"].asUInt64() < duration_cast<milliseconds>((system_clock::now() - hours(72)).time_since_epoch()).count())
return {findError("web_handshake_invalid"), "Provided data is too old!"}; return {findError("web_handshake_invalid"), "Provided data is too old!"};
this->properties()[property::CLIENT_UNIQUE_IDENTIFIER] = base64::encode(digest::sha1("TeaSpeak-Forum#" + (*this->handshake.identityData)["user_id"].asString())); this->properties()[property::CLIENT_UNIQUE_IDENTIFIER] = base64::encode(digest::sha1("TeaSpeak-Forum#" + json_data["user_id"].asString()));
this->properties()[property::CLIENT_TEAFORO_ID] = (*this->handshake.identityData)["user_id"].asInt64(); this->properties()[property::CLIENT_TEAFORO_ID] = json_data["user_id"].asInt64();
this->properties()[property::CLIENT_TEAFORO_NAME] = (*this->handshake.identityData)["user_name"].asString(); this->properties()[property::CLIENT_TEAFORO_NAME] = json_data["user_name"].asString();
{ {
///* 0x01 := Banned | 0x02 := Stuff | 0x04 := Premium */ ///* 0x01 := Banned | 0x02 := Stuff | 0x04 := Premium */
uint64_t flags = 0; uint64_t flags = 0;
if((*this->handshake.identityData)["is_banned"].isBool() && (*this->handshake.identityData)["is_banned"].asBool()) if(json_data["is_banned"].isBool() && json_data["is_banned"].asBool())
flags |= 0x01U; flags |= 0x01U;
if((*this->handshake.identityData)["is_staff"].isBool() && (*this->handshake.identityData)["is_staff"].asBool()) if(json_data["is_staff"].isBool() && json_data["is_staff"].asBool())
flags |= 0x02U; flags |= 0x02U;
if((*this->handshake.identityData)["is_premium"].isBool() && (*this->handshake.identityData)["is_premium"].asBool()) if(json_data["is_premium"].isBool() && json_data["is_premium"].asBool())
flags |= 0x04U; flags |= 0x04U;
this->properties()[property::CLIENT_TEAFORO_FLAGS] = flags; this->properties()[property::CLIENT_TEAFORO_FLAGS] = flags;

@ -96,7 +96,7 @@ MusicClient::~MusicClient() {
void MusicClient::sendCommand(const ts::Command &command, bool low) { } void MusicClient::sendCommand(const ts::Command &command, bool low) { }
bool MusicClient::closeConnection(const std::chrono::system_clock::time_point&) { bool MusicClient::closeConnection(const std::chrono::system_clock::time_point&) {
logError("Music manager is forced to disconnect!"); logError(this->getServerId(), "Music manager is forced to disconnect!");
/* /*
if(this->server) if(this->server)

@ -124,7 +124,7 @@ void QueryClient::writeMessage(const std::string& message) {
if(this->connectionType == ConnectionType::PLAIN) this->writeRawMessage(message); if(this->connectionType == ConnectionType::PLAIN) this->writeRawMessage(message);
else if(this->connectionType == ConnectionType::SSL_ENCRIPTED) this->ssl_handler.send(pipes::buffer_view{(void*) message.data(), message.length()}); else if(this->connectionType == ConnectionType::SSL_ENCRIPTED) this->ssl_handler.send(pipes::buffer_view{(void*) message.data(), message.length()});
else logCritical("Invalid query connection type!"); else logCritical(LOG_GENERAL, "Invalid query connection type to write to!");
} }

@ -135,7 +135,7 @@ CommandResult QueryClient::handleCommandLogin(Command& cmd) {
username = cmd[0][0].key(); username = cmd[0][0].key();
password = cmd[0][1].key(); password = cmd[0][1].key();
} }
debugMessage("Attempted query login with " + username + " - " + password); debugMessage(LOG_QUERY, "Having query login attempt for username {}", username);
auto _account = serverInstance->getQueryServer()->find_query_account_by_name(username); auto _account = serverInstance->getQueryServer()->find_query_account_by_name(username);
auto account = _account ? serverInstance->getQueryServer()->load_password(_account) : nullptr; auto account = _account ? serverInstance->getQueryServer()->load_password(_account) : nullptr;
@ -374,7 +374,6 @@ CommandResult QueryClient::handleCommandJoin(Command &) {
if(this->currentChannel) if(this->currentChannel)
return {findError("server_already_joined"), "already joined!"}; return {findError("server_already_joined"), "already joined!"};
debugMessage("Uid -> " + this->properties()[property::CLIENT_UNIQUE_IDENTIFIER].as<string>());
this->server->assignDefaultChannel(this->ref(), true); this->server->assignDefaultChannel(this->ref(), true);
return CommandResult::Success; return CommandResult::Success;
} }
@ -811,7 +810,7 @@ CommandResult QueryClient::handleCommandServerSnapshotDeploy(Command& cmd) {
auto hash = cmd["hash"].string(); auto hash = cmd["hash"].string();
if(hash.empty()) return {findError("parameter_invalid"), "Invalid hash (not present)"}; if(hash.empty()) return {findError("parameter_invalid"), "Invalid hash (not present)"};
debugMessage("Hash: '" + hash + "'"); debugMessage(this->getServerId(), "Serversnapshot calculated hash: {}", hash);
bool mapping = cmd.hasParm("mapping"); bool mapping = cmd.hasParm("mapping");
cmd.disableParm("mapping"); cmd.disableParm("mapping");
@ -834,7 +833,7 @@ CommandResult QueryClient::handleCommandServerSnapshotDeploy(Command& cmd) {
Command res(""); Command res("");
if(!result){ if(!result){
logError("Could not apply server snapshot: " + error); logError(this->getServerId(), "Could not apply server snapshot: {}", error);
res["success"] = false; res["success"] = false;
res["sid"] = 0; res["sid"] = 0;
res["message"] = error; res["message"] = error;
@ -929,7 +928,7 @@ CommandResult QueryClient::handleCommandServerNotifyRegister(Command &cmd) {
CMD_REQ_PARM("event"); CMD_REQ_PARM("event");
CMD_RESET_IDLE; CMD_RESET_IDLE;
if(!cmd[0].has("specifier") && cmd["event"].as<string>() != "all") { //Lagacy support if(!cmd[0].has("specifier") && cmd["event"].as<string>() != "all") { //Lagacy support
logMessage("[Query] Client " + this->getLoggingPeerIp() + ":" + to_string(this->getPeerPort()) + " uses the lagacy notify system, which is deprecated!"); logMessage(this->getServerId(), "{} Client {}:{} uses the lagacy notify system, which is deprecated!", CLIENT_STR_LOG_PREFIX, this->getLoggingPeerIp(), this->getPeerPort());
string event = cmd["event"]; string event = cmd["event"];
std::transform(event.begin(), event.end(), event.begin(), ::tolower); std::transform(event.begin(), event.end(), event.begin(), ::tolower);
#include "XMacroEventTypes.h" #include "XMacroEventTypes.h"
@ -985,7 +984,7 @@ CommandResult QueryClient::handleCommandServerNotifyUnregister(Command &cmd) {
CMD_REQ_PARM("event"); CMD_REQ_PARM("event");
CMD_RESET_IDLE; CMD_RESET_IDLE;
if(!cmd[0].has("specifier")){ if(!cmd[0].has("specifier")){
logMessage("[Query] Client " + this->getLoggingPeerIp() + ":" + to_string(this->getPeerPort()) + " uses the lagacy notify system, which is deprecated!"); logMessage(this->getServerId(), "{} Client {}:{} uses the lagacy notify system, which is deprecated!", CLIENT_STR_LOG_PREFIX, this->getLoggingPeerIp(), this->getPeerPort());
string event = cmd["event"]; string event = cmd["event"];
std::transform(event.begin(), event.end(), event.begin(), ::tolower); std::transform(event.begin(), event.end(), event.begin(), ::tolower);
#include "XMacroEventTypes.h" #include "XMacroEventTypes.h"

@ -42,7 +42,7 @@ VoiceClient::~VoiceClient() {
this->connection = nullptr; this->connection = nullptr;
if(this->flushing_thread) if(this->flushing_thread)
logCritical(0, "Deleting a VoiceClient which should still be hold within the flush thread!"); logCritical(this->getServerId(), "Deleting a VoiceClient which should still be hold within the flush thread!");
memtrack::freed<VoiceClient>(this); memtrack::freed<VoiceClient>(this);
} }
@ -50,7 +50,7 @@ VoiceClient::~VoiceClient() {
void VoiceClient::sendCommand0(const ts::Command &command, bool low, bool direct, std::unique_ptr<threads::Future<bool>> listener) { void VoiceClient::sendCommand0(const ts::Command &command, bool low, bool direct, std::unique_ptr<threads::Future<bool>> listener) {
auto cmd = command.build(); auto cmd = command.build();
if(cmd.empty()) { if(cmd.empty()) {
logCritical("Attempted to send an empty command!"); logCritical(this->getServerId(), "{} Attempted to send an empty command!", CLIENT_STR_LOG_PREFIX);
return; return;
} }

@ -29,13 +29,11 @@ CommandResult VoiceClient::handleCommand(ts::Command &command) {
return SpeakingClient::handleCommand(command); return SpeakingClient::handleCommand(command);
} }
inline int getSecurityLevel(ecc_key* pubKey, size_t offset) { inline bool calculate_security_level(int& result, ecc_key* pubKey, size_t offset) {
size_t pubLength = 256; size_t pubLength = 256;
char pubBuffer[256]; char pubBuffer[256];
if(ecc_export(reinterpret_cast<unsigned char *>(pubBuffer), &pubLength, PK_PUBLIC, pubKey) != CRYPT_OK){ if((result = ecc_export(reinterpret_cast<unsigned char *>(pubBuffer), &pubLength, PK_PUBLIC, pubKey)) != CRYPT_OK)
logError(lstream << "failed to export pub key" << endl); return false;
return -1;
}
std::string hashStr = base64_encode(pubBuffer, pubLength) + to_string(offset); std::string hashStr = base64_encode(pubBuffer, pubLength) + to_string(offset);
char shaBuffer[SHA_DIGEST_LENGTH]; char shaBuffer[SHA_DIGEST_LENGTH];
@ -53,7 +51,8 @@ inline int getSecurityLevel(ecc_key* pubKey, size_t offset) {
else break; else break;
} }
} }
return zeroBits; result = zeroBits;
return true;
} }
CommandResult VoiceClient::handleCommandClientInit(Command &cmd) { CommandResult VoiceClient::handleCommandClientInit(Command &cmd) {
@ -61,7 +60,11 @@ CommandResult VoiceClient::handleCommandClientInit(Command &cmd) {
this->connection->acknowledge_handler.reset(); this->connection->acknowledge_handler.reset();
if(this->getType() == ClientType::CLIENT_TEAMSPEAK) { if(this->getType() == ClientType::CLIENT_TEAMSPEAK) {
auto securityLevel = getSecurityLevel(this->crypto.remote_key.get(), cmd["client_key_offset"]); int securityLevel;
if(!calculate_security_level(securityLevel, this->crypto.remote_key.get(), cmd["client_key_offset"])) {
logError(this->getServerId(), "[{}] Failed to calculate security level. Error code: {}", CLIENT_STR_LOG_PREFIX, securityLevel);
return {ErrorType::VSError};
}
if(securityLevel < 8) if(securityLevel < 8)
return {findError("channel_invalid_security_hash"), "cant calculate security level"}; return {findError("channel_invalid_security_hash"), "cant calculate security level"};

@ -65,13 +65,13 @@ void LicenseHelper::tick() {
} }
if(!response->license_valid || !response->properties_valid){ if(!response->license_valid || !response->properties_valid){
if(!response->license_valid) { if(!response->license_valid) {
if(config::license->isPremium()) logCritical(strobf("Could not validate license.").c_str()); if(config::license->isPremium()) logCritical(LOG_INSTANCE, strobf("Could not validate license.").c_str());
else logCritical(strobf("Your server has been shutdown remotely!").c_str()); else logCritical(LOG_INSTANCE, strobf("Your server has been shutdown remotely!").c_str());
} else if(!response->properties_valid) { } else if(!response->properties_valid) {
logCritical(strobf("Property adjustment failed!").c_str()); logCritical(LOG_INSTANCE, strobf("Property adjustment failed!").c_str());
} else } else
logCritical(strobf("Your license expired!").c_str()); logCritical(LOG_INSTANCE, strobf("Your license expired!").c_str());
logCritical(strobf("Stopping application!").c_str()); logCritical(LOG_INSTANCE, strobf("Stopping application!").c_str());
ts::server::shutdownInstance(); ts::server::shutdownInstance();
return; return;
} else { } else {
@ -138,11 +138,11 @@ void LicenseHelper::do_request(bool verbose) {
#else #else
auto license_host = gethostbyname(strobf("license.teaspeak.de").c_str()); auto license_host = gethostbyname(strobf("license.teaspeak.de").c_str());
if(!license_host){ if(!license_host){
if(verbose) logError(strobf("Could not valid license! (1)").c_str()); if(verbose) logError(LOG_INSTANCE, strobf("Could not valid license! (1)").c_str());
return; return;
} }
if(!license_host->h_addr){ if(!license_host->h_addr){
if(verbose) logError(strobf("Could not valid license! (2)").c_str()); if(verbose) logError(LOG_INSTANCE, strobf("Could not valid license! (2)").c_str());
return; return;
} }
server_addr.sin_addr.s_addr = ((in_addr*) license_host->h_addr)->s_addr; server_addr.sin_addr.s_addr = ((in_addr*) license_host->h_addr)->s_addr;
@ -150,9 +150,9 @@ void LicenseHelper::do_request(bool verbose) {
int first = server_addr.sin_addr.s_addr >> 24; int first = server_addr.sin_addr.s_addr >> 24;
if(first == 0 || first == 127 || first == 255) { if(first == 0 || first == 127 || first == 255) {
if(config::license->isPremium()) { if(config::license->isPremium()) {
logError(strobf("You tried to nullroot 'license.teaspeak.de'!").c_str()); logError(LOG_INSTANCE, strobf("You tried to nullroot 'license.teaspeak.de'!").c_str());
logCritical(strobf("Could not validate license!").c_str()); logCritical(LOG_INSTANCE, strobf("Could not validate license!").c_str());
logCritical(strobf("Stopping server!").c_str()); logCritical(LOG_INSTANCE, strobf("Stopping server!").c_str());
ts::server::shutdownInstance(); ts::server::shutdownInstance();
return; return;
} }

@ -18,7 +18,7 @@ bool BanManager::loadBans() {
this->current_ban_index.store(0); this->current_ban_index.store(0);
try { try {
if(config::server::delete_old_bans) { if(config::server::delete_old_bans) {
debugMessage("Deleting old bans"); debugMessage(LOG_INSTANCE, "Deleting old bans");
LOG_SQL_CMD(sql::command(this->sql, "DELETE FROM `bannedClients` WHERE `until` < :now AND `until` > 0", variable{":now", duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count()}).execute()); LOG_SQL_CMD(sql::command(this->sql, "DELETE FROM `bannedClients` WHERE `until` < :now AND `until` > 0", variable{":now", duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count()}).execute());
} }
LOG_SQL_CMD(sql::command(this->sql, "SELECT `banId` FROM `bannedClients` ORDER BY `banId` DESC LIMIT 1").query([](atomic<BanId>& counter, int, string* values, string*) { LOG_SQL_CMD(sql::command(this->sql, "SELECT `banId` FROM `bannedClients` ORDER BY `banId` DESC LIMIT 1").query([](atomic<BanId>& counter, int, string* values, string*) {

@ -239,7 +239,7 @@ int MusicBotManager::sqlCreateMusicBot(int length, std::string* values, std::str
} }
handle->groups->enableCache(musicBot->getClientDatabaseId()); handle->groups->enableCache(musicBot->getClientDatabaseId());
if(musicBot->getClientDatabaseId() != botId) logCritical("Invalid music bot id mapping!"); if(musicBot->getClientDatabaseId() != botId) logCritical(handle->getServerId(),"Invalid music bot id mapping!");
{ {
auto playlist = this->find_playlist(musicBot->properties()[property::CLIENT_PLAYLIST_ID]); auto playlist = this->find_playlist(musicBot->properties()[property::CLIENT_PLAYLIST_ID]);

@ -42,7 +42,7 @@ namespace interaction {
DefaultMemoryInfo* info = nullptr; DefaultMemoryInfo* info = nullptr;
if(shmInfo.shm_nattch == 0){ //Im the first program! if(shmInfo.shm_nattch == 0){ //Im the first program!
debugMessage("Created new memory struct"); debugMessage(LOG_GENERAL, "Created new memory struct");
*(DefaultMemoryInfo*) SHARED_MEMORY_PTR = DefaultMemoryInfo{}; *(DefaultMemoryInfo*) SHARED_MEMORY_PTR = DefaultMemoryInfo{};
info = (DefaultMemoryInfo*) SHARED_MEMORY_PTR; info = (DefaultMemoryInfo*) SHARED_MEMORY_PTR;
@ -81,7 +81,7 @@ namespace interaction {
auto instanceInfo = ownInfo(); auto instanceInfo = ownInfo();
instanceInfo->pid = ::getpid(); instanceInfo->pid = ::getpid();
pthread_mutex_unlock(&info->memoryLock); pthread_mutex_unlock(&info->memoryLock);
debugMessage("Got application instance id " + to_string(INSTANCE_ID)); debugMessage(LOG_GENERAL, "Got application instance id {}", INSTANCE_ID);
return true; return true;
} }
@ -95,13 +95,13 @@ namespace interaction {
shmid_ds info{}; shmid_ds info{};
memset(&info, 0, sizeof(info)); memset(&info, 0, sizeof(info));
if(shmctl(SHARED_MEMORY_ID, IPC_STAT, &info) < 0){ if(shmctl(SHARED_MEMORY_ID, IPC_STAT, &info) < 0){
logMessage(lstream << "Could not collect info: " << strerror(errno)); logMessage(LOG_INSTANCE, "Could not collect info: {}", errno);
return; return;
} }
if(info.shm_nattch == 0){ if(info.shm_nattch == 0){
shmctl(SHARED_MEMORY_ID, IPC_RMID, nullptr); shmctl(SHARED_MEMORY_ID, IPC_RMID, nullptr);
logMessage("Deleting shared memory"); logMessage(LOG_INSTANCE, "Deleting shared memory");
} }
} }

@ -248,7 +248,7 @@ bool VoiceServer::unregisterConnection(std::shared_ptr<VoiceClient> connection)
auto found = std::find(this->activeConnections.begin(), this->activeConnections.end(), connection); auto found = std::find(this->activeConnections.begin(), this->activeConnections.end(), connection);
if(found != activeConnections.end()) if(found != activeConnections.end())
this->activeConnections.erase(found); this->activeConnections.erase(found);
else logError("unregisterConnection(...) -> could not find client"); else logError(LOG_GENERAL, "unregisterConnection(...) -> could not find client");
return true; return true;
} }

@ -40,7 +40,6 @@ namespace terminal {
do { do {
size_t next = str.find(' ', index); size_t next = str.find(' ', index);
auto elm = str.substr(index, next - index); auto elm = str.substr(index, next - index);
debugMessage("Having message part: " + elm + " - " + to_string(index));
if(index == 0){ if(index == 0){
cmd.command = elm; cmd.command = elm;
@ -194,7 +193,7 @@ namespace terminal {
logError("Invalid mode/serverId"); logError("Invalid mode/serverId");
return false; return false;
} }
debugMessage("Chat message mode " + to_string(mode)); debugMessage(LOG_GENERAL,"Chat message mode " + to_string(mode));
std::string message; std::string message;
int index = 3; int index = 3;

2
shared

@ -1 +1 @@
Subproject commit 41fb8415cdade6ea36cba2bb0221b7177710d41e Subproject commit b9e2da8bb48ce74561c69cf5c5e3d252d6251ee9