Some fixes
This commit is contained in:
parent
709d2c0f5d
commit
2ae00f07cd
@ -22,7 +22,7 @@ namespace license {
|
||||
std::shared_ptr<License> 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));
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <client/linux/handler/exception_handler.h>
|
||||
#include <iostream>
|
||||
#include <misc/endianness.h>
|
||||
#include <misc/strobf.h>
|
||||
#include <CXXTerminal/QuickTerminal.h>
|
||||
#include <event2/thread.h>
|
||||
#include <log/LogUtils.h>
|
||||
@ -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<logger::LoggerConfig> 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<logger::LoggerConfig>();
|
||||
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<seconds>(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();
|
||||
|
@ -9,27 +9,13 @@
|
||||
#include <log/LogUtils.h>
|
||||
#include <regex>
|
||||
#include <src/geo/GeoLocation.h>
|
||||
#include <misc/strobf.h>
|
||||
|
||||
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<string> 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<string> 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<string> 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<string> 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<string> 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<std::shared_ptr<EntryBinding>> 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.");
|
||||
}
|
||||
|
@ -89,24 +89,12 @@ std::shared_ptr<Properties> 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<uint64_t, uint64_t> ConnectionStatistics::mark_file_bytes() {
|
||||
std::pair<uint64_t, uint64_t> result;
|
||||
|
||||
|
@ -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<ConnectionStatistics>& /* root */, bool /* spawn properties */);
|
||||
~ConnectionStatistics();
|
||||
|
||||
std::shared_ptr<Properties> 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<uint64_t, uint64_t> 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<ConnectionStatistics> handle;
|
||||
std::shared_ptr<Properties> properties;
|
||||
@ -89,8 +98,8 @@ namespace ts {
|
||||
std::atomic<uint64_t> mark_file_bytes_sent = 0;
|
||||
std::atomic<uint64_t> 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<StatisticEntry*> history_file_incoming{};
|
||||
std::deque<StatisticEntry*> history_file_outgoing{};
|
||||
std::deque<StatisticEntry*> history_incoming{};
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include <misc/digest.h>
|
||||
#include <misc/base64.h>
|
||||
#include <misc/rnd.h>
|
||||
#include <misc/strobf.h>
|
||||
#include <jemalloc/jemalloc.h>
|
||||
|
||||
#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();
|
||||
}
|
||||
}
|
||||
|
@ -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+\])?)?)";
|
||||
}
|
||||
}
|
@ -31,6 +31,7 @@
|
||||
#include <misc/digest.h>
|
||||
#include <misc/rnd.h>
|
||||
#include <misc/timer.h>
|
||||
#include <misc/strobf.h>
|
||||
#include <bbcode/bbcodes.h>
|
||||
|
||||
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()};
|
||||
}
|
||||
|
||||
|
||||
|
@ -255,7 +255,10 @@ bool ConnectedClient::notifyConnectionInfo(const shared_ptr<ConnectedClient> &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<ConnectedClient> &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<ConnectedClient> &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<ConnectedClient> &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<VoiceClient>(target))
|
||||
notify["connection_ping"] = floor<milliseconds>(dynamic_pointer_cast<VoiceClient>(target)->calculatePing()).count();
|
||||
else if(dynamic_pointer_cast<WebClient>(target))
|
||||
notify["connection_ping"] = floor<milliseconds>(dynamic_pointer_cast<WebClient>(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<VoiceClient>(target))
|
||||
notify["connection_ping"] = floor<milliseconds>(dynamic_pointer_cast<VoiceClient>(target)->calculatePing()).count();
|
||||
else if(dynamic_pointer_cast<WebClient>(target))
|
||||
notify["connection_ping"] = floor<milliseconds>(dynamic_pointer_cast<WebClient>(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();
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <iomanip>
|
||||
#include <netinet/in.h>
|
||||
#include <log/LogUtils.h>
|
||||
#include <misc/strobf.h>
|
||||
|
||||
#include "../InstanceHandler.h"
|
||||
#include "../manager/ConversationManager.h"
|
||||
@ -46,7 +47,7 @@ if(!var) { \
|
||||
return true; \
|
||||
} \
|
||||
if(!ignore_disabled && var->properties()[property::CLIENT_DISABLED].as<bool>()) { \
|
||||
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; \
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -451,6 +451,8 @@ void WebClient::handleMessage(const std::string &message) {
|
||||
this->voice_bridge = make_unique<web::VoiceBridge>(dynamic_pointer_cast<WebClient>(_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!
|
||||
}
|
||||
|
@ -1,4 +1,5 @@
|
||||
#include <log/LogUtils.h>
|
||||
#include <misc/strobf.h>
|
||||
#include <src/Configuration.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <src/SignalHandler.h>
|
||||
@ -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));
|
||||
}
|
@ -91,7 +91,7 @@ inline deque<std::shared_ptr<BanRecord>> 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<BanRecord>& record,
|
||||
variable{":hid", hardware_id},
|
||||
variable{":name", nickname},
|
||||
variable{":ip", ip},
|
||||
variable{":timestamp", duration_cast<milliseconds>(record->until.time_since_epoch()).count()}
|
||||
variable{":timestamp", duration_cast<milliseconds>(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}
|
||||
|
@ -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 {
|
||||
|
@ -14,7 +14,7 @@ namespace interaction {
|
||||
|
||||
template <size_t N>
|
||||
struct MemoryInfo {
|
||||
pthread_mutex_t memoryLock = PTHREAD_MUTEX_INITIALIZER;
|
||||
pthread_mutex_t memoryLock;
|
||||
|
||||
size_t instanceCount = 0;
|
||||
size_t maxInstances = N;
|
||||
|
2
shared
2
shared
@ -1 +1 @@
|
||||
Subproject commit c117799cc9b391ec8072db35bbd0558aba7dff53
|
||||
Subproject commit 316afd9f5649448798f1e15fbd2cac171623aaac
|
Loading…
Reference in New Issue
Block a user