From 2ae00f07cdd55886711964b6018e72943d1b9b39 Mon Sep 17 00:00:00 2001 From: WolverinDEV Date: Sat, 14 Sep 2019 12:06:48 +0200 Subject: [PATCH] Some fixes --- license/shared/License.cpp | 4 +- server/main.cpp | 47 ++++++-------- server/src/Configuration.cpp | 46 +++++-------- server/src/ConnectionStatistics.cpp | 46 +++++++------ server/src/ConnectionStatistics.h | 65 +++++++++++-------- server/src/InstanceHandler.cpp | 3 +- server/src/build.cpp | 3 +- .../client/ConnectedClientCommandHandler.cpp | 4 +- .../client/ConnectedClientNotifyHandler.cpp | 54 +++++++++++---- .../ConnectedClientTextCommandHandler.cpp | 3 +- server/src/client/file/FileClient.cpp | 4 +- server/src/client/web/WSWebClient.cpp | 2 + server/src/client/web/WebClient.cpp | 9 ++- server/src/lincense/LicenseHelper.cpp | 45 ++++++------- server/src/manager/BanManager.cpp | 6 +- .../pinteraction/ApplicationInteraction.cpp | 9 +++ .../src/pinteraction/ApplicationInteraction.h | 2 +- shared | 2 +- 18 files changed, 198 insertions(+), 156 deletions(-) diff --git a/license/shared/License.cpp b/license/shared/License.cpp index 68c0d9d..91cba7a 100644 --- a/license/shared/License.cpp +++ b/license/shared/License.cpp @@ -22,7 +22,7 @@ namespace license { std::shared_ptr readLocalLicence(const std::string& buffer, std::string& error){ string bbuffer = base64::decode(buffer); if(bbuffer.length() < sizeof(License)) { - error = "Invalid license size"; + error = "invalid size"; return nullptr; } @@ -30,7 +30,7 @@ namespace license { memcpy(license, bbuffer.data(), sizeof(License)); if(license->header.version != LICENSE_VERSION){ - error = "Invalid license version (" + to_string(license->header.version) + ")"; + error = "invalid version (" + to_string(license->header.version) + ")"; return nullptr; } xorBuffer(&((char*) license)[sizeof(License::header)], sizeof(License::data), license->header.cryptKey, sizeof(license->header.cryptKey)); diff --git a/server/main.cpp b/server/main.cpp index faa39fb..5d80311 100644 --- a/server/main.cpp +++ b/server/main.cpp @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -119,13 +120,6 @@ int main(int argc, char** argv) { OpenSSL_add_ssl_algorithms(); ts::permission::setup_permission_resolve(); - { - u_char buffer[SHA512_DIGEST_LENGTH]; - SHA512_CTX md{}; - SHA512_Init(&md); - SHA512_Update(&md, "Hello World", 11); - SHA512_Final(buffer,&md); - } { auto evthread_use_pthreads_result = evthread_use_pthreads(); assert(evthread_use_pthreads_result == 0); @@ -241,18 +235,18 @@ int main(int argc, char** argv) { std::string descriptors = "LTGE"; bool crypt_init = false; for(const auto& c : descriptors) - if(crypt_init |= crypt_mp_init(&c)) + if((crypt_init |= crypt_mp_init(&c))) break; if(!crypt_init) { logCritical(LOG_GENERAL, "Could not initialise libtomcrypt mp descriptors!"); return 1; } if(register_prng(&sprng_desc) == -1) { - cerr << "could not setup prng" << endl; + logCritical(LOG_GENERAL, "could not setup prng"); return EXIT_FAILURE; } if (register_cipher(&rijndael_desc) == -1) { - cerr << "could not setup rijndael" << endl; + logCritical(LOG_GENERAL, "could not setup rijndael"); return EXIT_FAILURE; } testTomMath(); @@ -263,18 +257,17 @@ int main(int argc, char** argv) { shared_ptr logConfig = nullptr; std::string line; - logMessage("Loading configuration"); - terminal::instance()->writeMessage("Loading configuration"); + logMessageFmt(true, LOG_GENERAL, "Loading configuration"); auto cfgErrors = ts::config::parseConfig(CONFIG_NAME); if(!cfgErrors.empty()){ - logError("Could not load configuration. Errors: (" + to_string(cfgErrors.size()) + ")"); + logErrorFmt(true, LOG_GENERAL, "Could not load configuration. Errors: (" + to_string(cfgErrors.size()) + ")"); for(const auto& entry : cfgErrors) - logError(" - " + entry); - logError("Stopping server..."); + logError(true, LOG_GENERAL, " - {}", entry); + logErrorFmt(true, LOG_GENERAL, "Stopping server..."); goto stopApp; } - logMessage("Setting up log"); + logMessage(LOG_GENERAL, "Setting up logging"); logConfig = make_shared(); logConfig->logfileLevel = (spdlog::level::level_enum) ts::config::log::logfileLevel; logConfig->terminalLevel = (spdlog::level::level_enum) ts::config::log::terminalLevel; @@ -291,23 +284,23 @@ int main(int argc, char** argv) { logger::updateLogLevels(); if(ts::config::license_original && ts::config::license_original->data.type != license::LicenseType::DEMO){ - logMessageFmt(true, LOG_GENERAL, "[]---------------------------------------------------------[]"); - logMessageFmt(true, LOG_GENERAL, " §aThank you for buying the TeaSpeak-§lPremium-§aSoftware! "); - logMessageFmt(true, LOG_GENERAL, " §aLicense information:"); - logMessageFmt(true, LOG_GENERAL, " §aLicense owner : §e" + ts::config::license_original->owner()); - logMessageFmt(true, LOG_GENERAL, " §aLicense type : §e" + license::LicenseTypeNames[ts::config::license_original->data.type]); + logMessageFmt(true, LOG_GENERAL, strobf("[]---------------------------------------------------------[]").string()); + logMessageFmt(true, LOG_GENERAL, strobf(" §aThank you for buying the TeaSpeak-§lPremium-§aSoftware! ").string()); + logMessageFmt(true, LOG_GENERAL, strobf(" §aLicense information:").string()); + logMessageFmt(true, LOG_GENERAL, strobf(" §aLicense owner : §e").string() + ts::config::license_original->owner()); + logMessageFmt(true, LOG_GENERAL, strobf(" §aLicense type : §e").string() + license::LicenseTypeNames[ts::config::license_original->data.type]); if(ts::config::license_original->end().time_since_epoch().count() == 0){ - logMessageFmt(true, LOG_GENERAL, " §aLicense expires: §enever"); + logMessageFmt(true, LOG_GENERAL, strobf(" §aLicense expires: §enever").string()); } else { char timeBuffer[32]; time_t t = duration_cast(ts::config::license_original->end().time_since_epoch()).count(); tm* stime = localtime(&t); strftime(timeBuffer, 32, "%c", stime); - logMessageFmt(true, LOG_GENERAL, " §aLicense expires: §e" + string(timeBuffer)); + logMessageFmt(true, LOG_GENERAL, strobf(" §aLicense expires: §e").string() + string(timeBuffer)); } - logMessage(string() + " §aLicense valid : " + (ts::config::license_original->isValid() ? "§ayes" : "§cno")); - logMessageFmt(true, LOG_GENERAL, "[]---------------------------------------------------------[]"); + logMessage(string() + strobf(" §aLicense valid : ").string() + (ts::config::license_original->isValid() ? strobf("§ayes").string() : strobf("§cno").string())); + logMessageFmt(true, LOG_GENERAL, strobf("[]---------------------------------------------------------[]").string()); } logMessage(LOG_GENERAL, "Starting TeaSpeak-Server v{}", build::version()->string(true)); @@ -400,7 +393,7 @@ int main(int argc, char** argv) { stopApp: - logMessage("Stopping application"); + logMessageFmt(true, LOG_GENERAL, "Stopping application"); if(serverInstance) serverInstance->stopInstance(); delete serverInstance; @@ -410,7 +403,7 @@ int main(int argc, char** argv) { if(sql) sql->finalize(); delete sql; - logMessage("Application suspend successful!"); + logMessageFmt(true, LOG_GENERAL, "Application suspend successful!"); logger::uninstall(); terminal::uninstall(); diff --git a/server/src/Configuration.cpp b/server/src/Configuration.cpp index 8edc479..61b6b4c 100644 --- a/server/src/Configuration.cpp +++ b/server/src/Configuration.cpp @@ -9,27 +9,13 @@ #include #include #include +#include using namespace std; using namespace std::chrono; using namespace ts; using namespace ts::config; -inline std::string decode_string(const std::string& input) -{ - const size_t passwordLength = 16; - static const char password[passwordLength] = "invalid pointer"; - // out = in XOR NOT(password) - std::string result = input; - for (size_t i = 0; i < input.length(); i++) - result[i] ^= ~password[i % passwordLength]; - return result; -} - -//"Password" is "invalid pointe" -#define CRYPTED_VERSION_PLATFORM decode_string("\xda\xf8\xe7\xeb\xeb") //Its "Linux" -#define CRYPTED_VERSION_PREFIX decode_string("\xc2\xf4\xe8\xcd\xe3\xf3\xfa\xb4\xaf") //Its "TeaSpeak " - //Variable define std::string config::database::url; std::string config::database::sqlite::locking_mode; @@ -432,7 +418,7 @@ vector config::parseConfig(const std::string& path) { //Due to an implementation mistake every default license looks like this: //AQA7CN26AAAAAMoLy9BIR2S9HyMeqBx7ZMUUc1rFXkt5YztwZCQRngncqtSs8hsQrzszzeNQSEcVXLtvIhm6m331OgjdugAAAADKbA25Oxab9/MK0xK3iZ8mUg+YkaZQkYS2Bj4Kcq2WFTCynv+sIfeYaei+VV8f/AJvxJDUfADJoSoGX85BIT3cTV+usRs3Adx0Ix/Wi5G4roL8Ypl0p8lYwELLGEVyEQf21rYMWOtVkQk2yoGuQikgLxr6p9sShKmAoES1lbHr8Xk= //teaspeak_license = license::createLocalLicence(license::LicenseType::DEMO, system_clock::time_point(), "TeaSpeak"); - teaspeak_license = "AQA7CN26AAAAAMoLy9BIR2S9HyMeqBx7ZMUUc1rFXkt5YztwZCQRngncqtSs8hsQrzszzeNQSEcVXLtvIhm6m331OgjdugAAAADKbA25Oxab9/MK0xK3iZ8mUg+YkaZQkYS2Bj4Kcq2WFTCynv+sIfeYaei+VV8f/AJvxJDUfADJoSoGX85BIT3cTV+usRs3Adx0Ix/Wi5G4roL8Ypl0p8lYwELLGEVyEQf21rYMWOtVkQk2yoGuQikgLxr6p9sShKmAoES1lbHr8Xk="; + teaspeak_license = strobf("AQA7CN26AAAAAMoLy9BIR2S9HyMeqBx7ZMUUc1rFXkt5YztwZCQRngncqtSs8hsQrzszzeNQSEcVXLtvIhm6m331OgjdugAAAADKbA25Oxab9/MK0xK3iZ8mUg+YkaZQkYS2Bj4Kcq2WFTCynv+sIfeYaei+VV8f/AJvxJDUfADJoSoGX85BIT3cTV+usRs3Adx0Ix/Wi5G4roL8Ypl0p8lYwELLGEVyEQf21rYMWOtVkQk2yoGuQikgLxr6p9sShKmAoES1lbHr8Xk=").string(); config::license = license::readLocalLicence(teaspeak_license, err); } else { config::license_original = license::readLocalLicence(teaspeak_license, err); @@ -441,8 +427,8 @@ vector config::parseConfig(const std::string& path) { if(!config::license){ #if true - logErrorFmt(true, LOG_GENERAL, "The given license isnt valid!"); - logErrorFmt(true, LOG_GENERAL, "Falling back to the default license."); + logErrorFmt(true, LOG_GENERAL, strobf("The given license isnt valid!").string()); + logErrorFmt(true, LOG_GENERAL, strobf("Falling back to the default license.").string()); teaspeak_license = "none"; goto license_parsing; #else @@ -451,17 +437,17 @@ vector config::parseConfig(const std::string& path) { #endif } if(!config::license){ - errors.emplace_back("Invalid license code!"); + errors.emplace_back(strobf("Invalid license code!").string()); return errors; } if(!config::license->isValid()) { if(config::license->data.type == license::LicenseType::INVALID) { - errors.emplace_back("Give license isn't valid!"); + errors.emplace_back(strobf("Give license isn't valid!").string()); return errors; } - logErrorFmt(true, LOG_GENERAL, "The given license isnt valid!"); - logErrorFmt(true, LOG_GENERAL, "Falling back to the default license."); + logErrorFmt(true, LOG_GENERAL, strobf("The given license isnt valid!").string()); + logErrorFmt(true, LOG_GENERAL, strobf("Falling back to the default license.").string()); teaspeak_license = "none"; goto license_parsing; } @@ -475,7 +461,7 @@ vector config::parseConfig(const std::string& path) { for(const auto& entry : config::web::ice_servers) { auto dp = entry.find(':'); if(dp == string::npos) { - errors.push_back("Invalid ice server entry! Missing port"); + errors.emplace_back("Invalid ice server entry! Missing port"); continue; } auto host = entry.substr(0, dp); @@ -493,21 +479,21 @@ vector config::parseConfig(const std::string& path) { } } - auto currentVersion = CRYPTED_VERSION_PREFIX + build::version()->string(true); + auto currentVersion = strobf("TeaSpeak ").string() + build::version()->string(true); if(currentVersion != config::server::DefaultServerVersion) { auto ref = config::server::DefaultServerVersion; try { - auto pattern = "TeaSpeak " + build::pattern(); + auto pattern = strobf("TeaSpeak\\s+").string() + build::pattern(); static std::regex const matcher(pattern); if (std::regex_match(ref, matcher)) { - logMessage("Updating displayed version in config to " + currentVersion); + logMessage(LOG_GENERAL, "Updating displayed TeaSpeak server version in config from {} to {}", ref, currentVersion); config["server"]["version"] = currentVersion; config::server::DefaultServerVersion = currentVersion; } else { - debugMessage("Pattern not match (" + pattern + ")"); + debugMessage(LOG_GENERAL, "Config version string does not matches default pattern. Do no updating it (Pattern: {}, Value: {})", pattern, ref); } } catch(std::exception& e){ - logError("Could not update displayed version (" + string(e.what()) + ")"); + logError(LOG_GENERAL, "Could not update displayed version ({})", e.what()); } } @@ -1114,13 +1100,13 @@ std::deque> config::create_bindings() { BIND_GROUP(server) { CREATE_BINDING("platform", PREMIUM_ONLY); - BIND_STRING(config::server::DefaultServerPlatform, CRYPTED_VERSION_PLATFORM); + BIND_STRING(config::server::DefaultServerPlatform, strobf("Linux").string()); ADD_DESCRIPTION("The displayed platform to the client"); ADD_NOTE("This option is only for the premium version."); } { CREATE_BINDING("version", PREMIUM_ONLY); - BIND_STRING(config::server::DefaultServerVersion, CRYPTED_VERSION_PREFIX + build::version()->string(true)); + BIND_STRING(config::server::DefaultServerVersion, strobf("TeaSpeak ").string() + build::version()->string(true)); ADD_DESCRIPTION("The displayed version to the client"); ADD_NOTE("This option is only for the premium version."); } diff --git a/server/src/ConnectionStatistics.cpp b/server/src/ConnectionStatistics.cpp index 2402efe..928eb84 100644 --- a/server/src/ConnectionStatistics.cpp +++ b/server/src/ConnectionStatistics.cpp @@ -89,24 +89,12 @@ std::shared_ptr ConnectionStatistics::statistics() { return this->properties; } -/* general statistics */ -inline int8_t typeIndex(const PacketTypeInfo& type){ - if(type == PacketTypeInfo::Command || type == PacketTypeInfo::CommandLow) - return 1; - else if(type == PacketTypeInfo::Ack || type == PacketTypeInfo::AckLow) - return 2; - else if(type == PacketTypeInfo::Voice || type == PacketTypeInfo::VoiceWhisper) - return 3; - return -1; -} - -void ConnectionStatistics::logIncomingPacket(const ClientPacket& pkt) { +void ConnectionStatistics::logIncomingPacket(const category::value &category, size_t size) { auto info_entry = new StatisticEntry{}; info_entry->timestamp = system_clock::now(); - info_entry->size = uint16_t(pkt.data().length() + pkt.header().length() + pkt.mac().length()); + info_entry->size = uint16_t(size); - auto index = typeIndex(pkt.type()); - this->_log_incoming_packet(info_entry, index); + this->_log_incoming_packet(info_entry, category); } void ConnectionStatistics::_log_incoming_packet(ts::stats::StatisticEntry *info_entry, int8_t index) { @@ -128,15 +116,15 @@ void ConnectionStatistics::_log_incoming_packet(ts::stats::StatisticEntry *info_ this->handle->_log_incoming_packet(info_entry, index); } -void ConnectionStatistics::logOutgoingPacket(const ServerPacket& pkt) { +void ConnectionStatistics::logOutgoingPacket(const category::value &category, size_t size) { auto info_entry = new StatisticEntry{}; info_entry->timestamp = system_clock::now(); - info_entry->size = uint16_t(pkt.data().length() + pkt.header().length() + pkt.mac().length()); + info_entry->size = uint16_t(size); - auto index = typeIndex(pkt.type()); - this->_log_outgoing_packet(info_entry, index); + this->_log_outgoing_packet(info_entry, category); } + void ConnectionStatistics::_log_outgoing_packet(ts::stats::StatisticEntry *info_entry, int8_t index) { if(index >= 0 && index <= 3) { this->connection_packets_sent[index] ++; @@ -157,7 +145,7 @@ void ConnectionStatistics::_log_outgoing_packet(ts::stats::StatisticEntry *info_ } /* file transfer */ -void ConnectionStatistics::logFileTransfareIn(uint64_t bytes) { +void ConnectionStatistics::logFileTransferIn(uint64_t bytes) { auto info_entry = new StatisticEntry{}; info_entry->timestamp = system_clock::now(); info_entry->size = bytes; @@ -180,7 +168,7 @@ void ConnectionStatistics::_log_incoming_file_packet(ts::stats::StatisticEntry * this->handle->_log_incoming_file_packet(info_entry); } -void ConnectionStatistics::logFileTransfareOut(uint64_t bytes) { +void ConnectionStatistics::logFileTransferOut(uint64_t bytes) { auto info_entry = new StatisticEntry{}; info_entry->timestamp = system_clock::now(); info_entry->size = bytes; @@ -306,6 +294,22 @@ DataSummery ConnectionStatistics::dataReport() { return report; } +FullReport ConnectionStatistics::full_report() { + FullReport report{}; + + for(size_t index = 0 ; index < 4; index++) { + report.connection_bytes_sent[index] = (uint64_t) this->connection_bytes_sent[index]; + report.connection_packets_sent[index] = (uint64_t) this->connection_packets_sent[index]; + report.connection_bytes_received[index] = (uint64_t) this->connection_bytes_received[index]; + report.connection_packets_received[index] = (uint64_t) this->connection_packets_received[index]; + } + + report.file_bytes_sent = this->file_bytes_sent; + report.file_bytes_received = this->file_bytes_received; + + return report; +} + std::pair ConnectionStatistics::mark_file_bytes() { std::pair result; diff --git a/server/src/ConnectionStatistics.h b/server/src/ConnectionStatistics.h index acc90cd..e2fc2de 100644 --- a/server/src/ConnectionStatistics.h +++ b/server/src/ConnectionStatistics.h @@ -28,21 +28,52 @@ namespace ts { uint32_t file_send; }; + struct FullReport { + uint64_t connection_packets_sent[4]{0, 0, 0, 0}; + uint64_t connection_bytes_sent[4]{0, 0, 0, 0}; + uint64_t connection_packets_received[4]{0, 0, 0, 0}; + uint64_t connection_bytes_received[4]{0, 0, 0, 0}; + + uint64_t file_bytes_sent = 0; + uint64_t file_bytes_received = 0; + }; + class ConnectionStatistics { public: + struct category { + enum value { + COMMAND, + ACK, + VOICE, + UNKNOWN + }; + + inline static category::value from_type(const protocol::PacketTypeInfo& type){ + if(type == protocol::PacketTypeInfo::Command || type == protocol::PacketTypeInfo::CommandLow) + 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& /* root */, bool /* spawn properties */); ~ConnectionStatistics(); std::shared_ptr statistics(); - void logIncomingPacket(const protocol::ClientPacket&); - void logOutgoingPacket(const protocol::ServerPacket&); - void logFileTransfareIn(uint64_t); - void logFileTransfareOut(uint64_t); + inline void logIncomingPacket(const protocol::ClientPacket& packet) { this->logIncomingPacket(category::from_type(packet.type()), packet.length()); } + void logIncomingPacket(const category::value& /* category */, size_t /* length */); + inline void logOutgoingPacket(const protocol::ServerPacket& packet) { this->logOutgoingPacket(category::from_type(packet.type()), packet.length()); } + void logOutgoingPacket(const category::value& /* category */, size_t /* length */); + void logFileTransferIn(uint64_t); + void logFileTransferOut(uint64_t); void tick(); DataSummery dataReport(); + FullReport full_report(); std::pair mark_file_bytes(); @@ -51,28 +82,6 @@ namespace ts { inline bool has_properties() { return !!this->properties; } private: - class spin_lock { - std::atomic_flag locked = ATOMIC_FLAG_INIT; - public: - void lock() { - uint8_t round = 0; - while (locked.test_and_set(std::memory_order_acquire)) { - //Yield when we're using this lock for a longer time, which we usually not doing - if(round++ % 8 == 0) - std::this_thread::yield(); - } - } - - inline bool try_lock() { - return !locked.test_and_set(std::memory_order_acquire); - } - - void unlock() { - locked.clear(std::memory_order_release); - } - }; - typedef spin_lock fast_lock_t; - bool _measure_bandwidths = true; std::shared_ptr handle; std::shared_ptr properties; @@ -89,8 +98,8 @@ namespace ts { std::atomic mark_file_bytes_sent = 0; std::atomic mark_file_bytes_received = 0; - fast_lock_t history_lock_outgoing; - fast_lock_t history_lock_incoming; + spin_lock history_lock_outgoing; + spin_lock history_lock_incoming; std::deque history_file_incoming{}; std::deque history_file_outgoing{}; std::deque history_incoming{}; diff --git a/server/src/InstanceHandler.cpp b/server/src/InstanceHandler.cpp index 7f4cd9d..d7419b6 100644 --- a/server/src/InstanceHandler.cpp +++ b/server/src/InstanceHandler.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include #ifndef _POSIX_SOURCE @@ -479,7 +480,7 @@ void InstanceHandler::tickInstance() { this->dbHelper->tick(); } { - ALARM_TIMER(t, "InstanceHandler::tickInstance -> license tick", milliseconds(5)); + ALARM_TIMER(t, strobf("InstanceHandler::tickInstance -> license tick").string(), milliseconds(5)); this->licenseHelper->tick(); } } diff --git a/server/src/build.cpp b/server/src/build.cpp index 8e63faa..133b429 100644 --- a/server/src/build.cpp +++ b/server/src/build.cpp @@ -67,6 +67,7 @@ namespace build { int buildCount(){ return BUILD_COUNT; } std::string pattern(){ - return R"([0-9]{1,5}\.[0-9]{1,5}\.[0-9]{1,5}(\-.*)?)"; + //return R"([0-9]{1,5}\.[0-9]{1,5}\.[0-9]{1,5}(\-.*)?)"; + return R"([0-9]{1,5}\.[0-9]{1,5}\.[0-9]{1,5}(-\S+( \[[Bb]uild: \d+\])?)?)"; } } \ No newline at end of file diff --git a/server/src/client/ConnectedClientCommandHandler.cpp b/server/src/client/ConnectedClientCommandHandler.cpp index f5de7b0..31bf002 100644 --- a/server/src/client/ConnectedClientCommandHandler.cpp +++ b/server/src/client/ConnectedClientCommandHandler.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include namespace fs = std::experimental::filesystem; @@ -4130,6 +4131,7 @@ CommandResult ConnectedClient::handleCommandBanTriggerList(ts::Command &cmd) { CMD_RESET_IDLE; CMD_CHK_AND_INC_FLOOD_POINTS(25); CACHED_PERM_CHECK(permission::b_client_ban_trigger_list, 1, true); + CMD_REQ_PARM("banid"); auto record = serverInstance->banManager()->findBanById(this->getServerId(), cmd["banid"]); @@ -6199,7 +6201,7 @@ CommandResult ConnectedClient::handleCommandMusicBotCreate(Command& cmd) { if(config::license->isPremium()) return {findError("music_limit_reached"), ""}; else - return {findError("music_limit_reached"), "You reached the server music bot limit. You could increase this limit by extend your server with a premium license."}; + return {findError("music_limit_reached"), strobf("You reached the server music bot limit. You could increase this limit by extend your server with a premium license.").string()}; } diff --git a/server/src/client/ConnectedClientNotifyHandler.cpp b/server/src/client/ConnectedClientNotifyHandler.cpp index 37bbe18..9c69962 100644 --- a/server/src/client/ConnectedClientNotifyHandler.cpp +++ b/server/src/client/ConnectedClientNotifyHandler.cpp @@ -255,7 +255,10 @@ bool ConnectedClient::notifyConnectionInfo(const shared_ptr &ta Command notify("notifyconnectioninfo"); notify["clid"] = target->getClientId(); + /* we deliver data to the web client as well, because its a bit dump :D */ if(target->getClientId() != this->getClientId()) { + auto report = target->connectionStatistics->full_report(); + /* default values which normally sets the client */ notify["connection_bandwidth_received_last_minute_control"] = -1; notify["connection_bandwidth_received_last_minute_keepalive"] = -1; @@ -271,6 +274,7 @@ bool ConnectedClient::notifyConnectionInfo(const shared_ptr &ta notify["connection_bandwidth_sent_last_second_keepalive"] = -1; notify["connection_bandwidth_sent_last_second_speech"] = -1; + /* its flipped here because the report is out of the clients view */ notify["connection_bytes_received_control"] = -1; notify["connection_bytes_received_keepalive"] = -1; notify["connection_bytes_received_speech"] = -1; @@ -278,6 +282,7 @@ bool ConnectedClient::notifyConnectionInfo(const shared_ptr &ta notify["connection_bytes_sent_keepalive"] = -1; notify["connection_bytes_sent_speech"] = -1; + /* its flipped here because the report is out of the clients view */ notify["connection_packets_received_control"] = -1; notify["connection_packets_received_keepalive"] = -1; notify["connection_packets_received_speech"] = -1; @@ -296,22 +301,43 @@ bool ConnectedClient::notifyConnectionInfo(const shared_ptr &ta notify["connection_connected_time"] = 0; notify["connection_idle_time"] = 0; - notify["connection_filetransfer_bandwidth_sent"] = 0; - notify["connection_filetransfer_bandwidth_received"] = 0; - - if(info) { - for(const auto& elm : info->properties) { - notify[elm.first] = elm.second; - } - } else { - //Fill in some server stuff - if(dynamic_pointer_cast(target)) - notify["connection_ping"] = floor(dynamic_pointer_cast(target)->calculatePing()).count(); - else if(dynamic_pointer_cast(target)) - notify["connection_ping"] = floor(dynamic_pointer_cast(target)->client_ping()).count(); - } + /* its flipped here because the report is out of the clients view */ + notify["connection_filetransfer_bandwidth_sent"] = report.file_bytes_received; + notify["connection_filetransfer_bandwidth_received"] = report.file_bytes_sent; } + if(info) { + for(const auto& elm : info->properties) { + notify[elm.first] = elm.second; + } + } else { + //Fill in some server stuff + if(dynamic_pointer_cast(target)) + notify["connection_ping"] = floor(dynamic_pointer_cast(target)->calculatePing()).count(); + else if(dynamic_pointer_cast(target)) + notify["connection_ping"] = floor(dynamic_pointer_cast(target)->client_ping()).count(); + + if(target->getType() == ClientType::CLIENT_TEASPEAK || target->getType() == ClientType::CLIENT_TEAMSPEAK || target->getType() == ClientType::CLIENT_WEB) { + auto report = target->connectionStatistics->full_report(); + + /* its flipped here because the report is out of the clients view */ + notify["connection_bytes_received_control"] = report.connection_bytes_sent[stats::ConnectionStatistics::category::COMMAND]; + notify["connection_bytes_received_keepalive"] = report.connection_bytes_sent[stats::ConnectionStatistics::category::ACK]; + notify["connection_bytes_received_speech"] = report.connection_bytes_sent[stats::ConnectionStatistics::category::VOICE]; + notify["connection_bytes_sent_control"] = report.connection_bytes_sent[stats::ConnectionStatistics::category::COMMAND]; + notify["connection_bytes_sent_keepalive"] = report.connection_bytes_sent[stats::ConnectionStatistics::category::ACK]; + notify["connection_bytes_sent_speech"] = report.connection_bytes_sent[stats::ConnectionStatistics::category::VOICE]; + + /* its flipped here because the report is out of the clients view */ + notify["connection_packets_received_control"] = report.connection_packets_sent[stats::ConnectionStatistics::category::COMMAND]; + notify["connection_packets_received_keepalive"] = report.connection_packets_sent[stats::ConnectionStatistics::category::ACK]; + notify["connection_packets_received_speech"] = report.connection_packets_sent[stats::ConnectionStatistics::category::VOICE]; + notify["connection_packets_sent_control"] = report.connection_packets_sent[stats::ConnectionStatistics::category::COMMAND]; + notify["connection_packets_sent_keepalive"] = report.connection_packets_sent[stats::ConnectionStatistics::category::ACK]; + notify["connection_packets_sent_speech"] = report.connection_packets_sent[stats::ConnectionStatistics::category::VOICE]; + } + } + if(target->getClientId() == this->getClientId() || this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_remoteaddress_view, 1, target->currentChannel, true)) { notify["connection_client_ip"] = target->getLoggingPeerIp(); notify["connection_client_port"] = target->getPeerPort(); diff --git a/server/src/client/ConnectedClientTextCommandHandler.cpp b/server/src/client/ConnectedClientTextCommandHandler.cpp index 2abff2d..07c38ff 100644 --- a/server/src/client/ConnectedClientTextCommandHandler.cpp +++ b/server/src/client/ConnectedClientTextCommandHandler.cpp @@ -2,6 +2,7 @@ #include #include #include +#include #include "../InstanceHandler.h" #include "../manager/ConversationManager.h" @@ -46,7 +47,7 @@ if(!var) { \ return true; \ } \ if(!ignore_disabled && var->properties()[property::CLIENT_DISABLED].as()) { \ - send_message(serverInstance->musicRoot(), "This bot has been disabled. Upgrade your TeaSpeak license to use more bots."); \ + send_message(serverInstance->musicRoot(), strobf("This bot has been disabled. Upgrade your TeaSpeak license to use more bots.").string()); \ return true; \ } diff --git a/server/src/client/file/FileClient.cpp b/server/src/client/file/FileClient.cpp index c6659b6..17b3d82 100644 --- a/server/src/client/file/FileClient.cpp +++ b/server/src/client/file/FileClient.cpp @@ -353,7 +353,7 @@ bool FileClient::tick() { } this->bytesHandled += read; - this->client->getConnectionStatistics()->logFileTransfareOut(read); + this->client->getConnectionStatistics()->logFileTransferOut(read); if(read > 0){ writeBuffer.resize(read); this->sendMessage(writeBuffer); @@ -449,7 +449,7 @@ bool FileClient::applyKey(const string &key) { bool FileClient::uploadWriteBytes(const pipes::buffer_view& message) { - this->client->getConnectionStatistics()->logFileTransfareIn(message.length()); + this->client->getConnectionStatistics()->logFileTransferIn(message.length()); if(!fstream->good()){ logError(LOG_FT, "{} uploadWriteBytes(...) called with invalid fstream!", this->client_prefix()); return false; diff --git a/server/src/client/web/WSWebClient.cpp b/server/src/client/web/WSWebClient.cpp index aa2c0f5..ae28774 100644 --- a/server/src/client/web/WSWebClient.cpp +++ b/server/src/client/web/WSWebClient.cpp @@ -103,6 +103,7 @@ void WebClient::enqueue_raw_packet(const pipes::buffer_view &msg) { if(this->writeEvent) event_add(this->writeEvent, nullptr); } + this->connectionStatistics->logOutgoingPacket(stats::ConnectionStatistics::category::COMMAND, buffer.length()); } void WebClient::registerMessageProcess() { @@ -136,6 +137,7 @@ void WebClient::processNextMessage(const std::chrono::system_clock::time_point& bool has_next = !this->queue_read.empty(); buffer_lock.unlock(); + this->connectionStatistics->logIncomingPacket(stats::ConnectionStatistics::category::COMMAND, buffer.length()); if(!this->ssl_detected) { this->ssl_detected = true; this->ssl_encrypted = is_ssl_handshake_header(buffer); diff --git a/server/src/client/web/WebClient.cpp b/server/src/client/web/WebClient.cpp index 848f065..ff6cc82 100644 --- a/server/src/client/web/WebClient.cpp +++ b/server/src/client/web/WebClient.cpp @@ -451,6 +451,8 @@ void WebClient::handleMessage(const std::string &message) { this->voice_bridge = make_unique(dynamic_pointer_cast(_this.lock())); //FIXME Add config this->voice_bridge->callback_voice_data = [&](const pipes::buffer_view& buffer, bool a, bool b) { + /* may somehow get the "real" packet size? */ + this->connectionStatistics->logIncomingPacket(stats::ConnectionStatistics::category::VOICE, buffer.length()); this->handlePacketVoice(buffer, a, b); }; this->voice_bridge->callback_initialized = [&](){ @@ -637,10 +639,15 @@ void WebClient::send_voice_packet(const pipes::buffer_view &view, const Speaking shared_lock read_voice_bridge_lock(this->voice_bridge_lock); if(this->voice_bridge) { auto channel = this->voice_bridge->voice_channel(); - if(channel) channel->send(view); + if(channel) { + channel->send(view); + /* may somehow get the "real" packet size? */ + this->connectionStatistics->logOutgoingPacket(stats::ConnectionStatistics::category::VOICE, view.length()); + } } } void WebClient::send_voice_whisper_packet(const pipes::buffer_view &view, const SpeakingClient::VoicePacketFlags &flags) { logError(this->server->getServerId(), "Web client got whisper packet"); + //As well log the data! } diff --git a/server/src/lincense/LicenseHelper.cpp b/server/src/lincense/LicenseHelper.cpp index 6bf54e6..5754c5e 100644 --- a/server/src/lincense/LicenseHelper.cpp +++ b/server/src/lincense/LicenseHelper.cpp @@ -1,4 +1,5 @@ #include +#include #include #include #include @@ -50,7 +51,7 @@ void LicenseHelper::tick() { if(promise.state() != threads::FutureState::WORKING){ auto exception = this->request.current->exception(); if(promise.state() == threads::FutureState::FAILED) { - this->handle_request_failed(verbose, exception ? exception->what() : "unknown"); + this->handle_request_failed(verbose, exception ? exception->what() : strobf("unknown").c_str()); this->request.current = nullptr; /* connection should be already closed */ return; } else { @@ -58,23 +59,23 @@ void LicenseHelper::tick() { this->request.current = nullptr; /* connection should be already closed */ if(!response){ - this->handle_request_failed(verbose, exception ? exception->what() : "invalid result (null)"); + this->handle_request_failed(verbose, exception ? exception->what() : strobf("invalid result (null)").c_str()); return; } if(!response->license_valid || !response->properties_valid){ if(!response->license_valid) { - if(config::license->isPremium()) logCritical("Could not validate license."); - else logCritical("Your server has been shutdown remotely!"); + if(config::license->isPremium()) logCritical(strobf("Could not validate license.").c_str()); + else logCritical(strobf("Your server has been shutdown remotely!").c_str()); } else if(!response->properties_valid) { - logCritical("Property adjustment failed!"); + logCritical(strobf("Property adjustment failed!").c_str()); } else - logCritical("Your license expired!"); - logCritical("Stopping application!"); + logCritical(strobf("Your license expired!").c_str()); + logCritical(strobf("Stopping application!").c_str()); ts::server::shutdownInstance(); return; } else { this->scheduled_request = this->last_request + hours(2); - logMessage(LOG_INSTANCE, "License successfully validated! Scheduling next check at {}", format_time(this->scheduled_request)); + logMessage(LOG_INSTANCE, strobf("License successfully validated! Scheduling next check at {}").c_str(), format_time(this->scheduled_request)); if(response->speach_reset) serverInstance->resetSpeechTime(); serverInstance->properties()[property::SERVERINSTANCE_SPOKEN_TIME_VARIANZ] = response->speach_varianz_adjustment; @@ -99,9 +100,9 @@ void LicenseHelper::tick() { void LicenseHelper::do_request(bool verbose) { if(verbose) { if(config::license && config::license->isPremium()) - logMessage(LOG_INSTANCE, "Validating license"); + logMessage(LOG_INSTANCE, strobf("Validating license").c_str()); else - logMessage(LOG_INSTANCE, "Validating instance integrity"); + logMessage(LOG_INSTANCE, strobf("Validating instance integrity").c_str()); } this->last_request = system_clock::now(); @@ -116,7 +117,7 @@ void LicenseHelper::do_request(bool verbose) { if(verbose) { auto promise = request->requestInfo(); if(promise.state() == threads::FutureState::WORKING) { - logMessage(LOG_INSTANCE, "Old check timed out (10 min). Running new one!"); + logMessage(LOG_INSTANCE, strobf("Old check timed out (10 min). Running new one!").c_str()); } } request->abortRequest(); @@ -131,26 +132,26 @@ void LicenseHelper::do_request(bool verbose) { server_addr.sin_family = AF_INET; #ifdef DO_LOCAL_REQUEST - auto license_host = gethostbyname("localhost"); + auto license_host = gethostbyname(strobf("localhost").c_str()); server_addr.sin_addr.s_addr = ((in_addr*) license_host->h_addr)->s_addr; #else - auto license_host = gethostbyname("license.teaspeak.de"); + auto license_host = gethostbyname(strobf("license.teaspeak.de").c_str()); if(!license_host){ - if(verbose) logError("Could not valid license! (1)"); + if(verbose) logError(strobf("Could not valid license! (1)").c_str()); return; } if(!license_host->h_addr){ - if(verbose) logError("Could not valid license! (2)"); + if(verbose) logError(strobf("Could not valid license! (2)").c_str()); return; } server_addr.sin_addr.s_addr = ((in_addr*) license_host->h_addr)->s_addr; - logger::logger(0)->debug("Requesting server {}", inet_ntoa(server_addr.sin_addr)); + logger::logger(0)->debug(strobf("Requesting server {}").c_str(), inet_ntoa(server_addr.sin_addr)); int first = server_addr.sin_addr.s_addr >> 24; if(first == 0 || first == 127 || first == 255) { if(config::license->isPremium()) { - logError("You tried to nullroot 'license.teaspeak.de'!"); - logCritical("Could not validate license!"); - logCritical("Stopping server!"); + logError(strobf("You tried to nullroot 'license.teaspeak.de'!").c_str()); + logCritical(strobf("Could not validate license!").c_str()); + logCritical(strobf("Stopping server!").c_str()); ts::server::shutdownInstance(); return; } @@ -175,9 +176,9 @@ void LicenseHelper::do_request(bool verbose) { void LicenseHelper::handle_request_failed(bool verbose, const std::string& error) { if(verbose) { if(config::license && config::license->isPremium()) - logError(LOG_INSTANCE, "License validation failed: {}", error); + logError(LOG_INSTANCE, strobf("License validation failed: {}").c_str(), error); else - logError(LOG_INSTANCE, "Instance integrity check failed: {}", error); + logError(LOG_INSTANCE, strobf("Instance integrity check failed: {}").c_str(), error); } this->request_fail_count++; milliseconds next_request; @@ -193,5 +194,5 @@ void LicenseHelper::handle_request_failed(bool verbose, const std::string& error this->scheduled_request = this->last_request + next_request; if(verbose) - logMessage(LOG_INSTANCE, "Scheduling next check at {}", format_time(this->scheduled_request)); + logMessage(LOG_INSTANCE, strobf("Scheduling next check at {}").c_str(), format_time(this->scheduled_request)); } \ No newline at end of file diff --git a/server/src/manager/BanManager.cpp b/server/src/manager/BanManager.cpp index 41dfc66..e4e78c7 100644 --- a/server/src/manager/BanManager.cpp +++ b/server/src/manager/BanManager.cpp @@ -91,7 +91,7 @@ inline deque> resolveBansByQuery(sql::command& comman if(!res) cerr << res << endl; - debugMessage("Query: " + command.sqlCommand() + " -> " + to_string(result.size())); + debugMessage(LOG_GENERAL, "Query: {} -> {}", command.sqlCommand(), result.size()); return result; } @@ -263,11 +263,11 @@ void BanManager::trigger_ban(const std::shared_ptr& record, variable{":hid", hardware_id}, variable{":name", nickname}, variable{":ip", ip}, - variable{":timestamp", duration_cast(record->until.time_since_epoch()).count()} + variable{":timestamp", duration_cast(chrono::system_clock::now().time_since_epoch()).count()} ).executeLater().waitAndGetLater(LOG_SQL_CMD, {1, "future failed"}); record->triggered++; - sql::command(this->sql, "UPDATE `bannedClients` SET `triggered` = :triggered WHERE `banId` = :bid AND `serverId` = :sid", + sql::command(this->sql, "UPDATE `bannedClients` SET `triggered` = :triggered WHERE `banId` = :banId AND `serverId` = :sid", variable{":sid", record->serverId}, variable{":banId", record->banId}, variable{":triggered", record->triggered} diff --git a/server/src/pinteraction/ApplicationInteraction.cpp b/server/src/pinteraction/ApplicationInteraction.cpp index 2c2834a..fb9b321 100644 --- a/server/src/pinteraction/ApplicationInteraction.cpp +++ b/server/src/pinteraction/ApplicationInteraction.cpp @@ -46,6 +46,15 @@ namespace interaction { *(DefaultMemoryInfo*) SHARED_MEMORY_PTR = DefaultMemoryInfo{}; info = (DefaultMemoryInfo*) SHARED_MEMORY_PTR; + /* initialize the mutex */ + { + pthread_mutexattr_t attr{}; + pthread_mutexattr_init(&attr); + pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_NORMAL); + pthread_mutexattr_setpshared(&attr, true); + pthread_mutex_init(&info->memoryLock, &attr); + } + pthread_mutex_lock(&info->memoryLock); memset(info->infoUsed, 0, sizeof(info->infoUsed) / sizeof(info->infoUsed[0])); } else { diff --git a/server/src/pinteraction/ApplicationInteraction.h b/server/src/pinteraction/ApplicationInteraction.h index e23d8cb..d42a9fe 100644 --- a/server/src/pinteraction/ApplicationInteraction.h +++ b/server/src/pinteraction/ApplicationInteraction.h @@ -14,7 +14,7 @@ namespace interaction { template struct MemoryInfo { - pthread_mutex_t memoryLock = PTHREAD_MUTEX_INITIALIZER; + pthread_mutex_t memoryLock; size_t instanceCount = 0; size_t maxInstances = N; diff --git a/shared b/shared index c117799..316afd9 160000 --- a/shared +++ b/shared @@ -1 +1 @@ -Subproject commit c117799cc9b391ec8072db35bbd0558aba7dff53 +Subproject commit 316afd9f5649448798f1e15fbd2cac171623aaac