Some changes

This commit is contained in:
WolverinDEV 2019-08-25 22:16:42 +02:00
parent 787f911b6f
commit 79f8c91157
17 changed files with 320 additions and 119 deletions

@ -1 +1 @@
Subproject commit 535d63f039b3e0b0559e7e09a5c80b04111fe93f
Subproject commit 0063a5acb2f6f5af91ca1d06dd27f432ec78e8a9

View File

@ -12,6 +12,7 @@
#include <misc/base64.h>
#include <misc/digest.h>
#include <fstream>
using namespace std;
using namespace std::chrono;
@ -24,6 +25,7 @@ using namespace license;
* Requests (license) / ip: SELECT DISTINCT `ip`, COUNT(`ip`) FROM `license_request` WHERE `keyId` = ? GROUP BY `ip`
*
* SELECT DISTINCT(`ip`), `keyId` FROM `license_request` WHERE `timestamp` > (UNIX_TIMESTAMP() - 2 * 60 * 60) * 1000
* //462
*
* SELECT DISTINCT(`ip`), `license_request`.`keyId`, `license_info`.`username` FROM `license_request` LEFT JOIN `license_info` ON `license_info`.`keyId` = `license_request`.`keyId` WHERE `timestamp` > (UNIX_TIMESTAMP() - 2 * 60 * 60) * 1000
*
@ -110,9 +112,15 @@ int main(int argc, char** argv) {
}
}
return 0;
{
*/
/*
{
ofstream _file_out("version_history.txt");
auto _now = system_clock::now();
auto statistics = license_manager->list_statistics_version(_now - hours(24) * 9, _now, duration_cast<milliseconds>(hours(1)));
cout << "Getting statistics" << endl;
auto statistics = license_manager->list_statistics_version(_now - hours(24) * 32 * 12, _now, duration_cast<milliseconds>(hours(1)));
cout << "Grouping statistics" << endl;
std::deque<std::string> versions;
const auto version_name = [](const std::string& key) {
auto space = key.find(' ');
@ -130,6 +138,7 @@ int main(int argc, char** argv) {
versions.push_back(name);
}
}
cout << "Sorting statistics" << endl;
sort(versions.begin(), versions.end(), [](const std::string& a, const std::string& b) {
const auto index_a = a.find_last_of('.');
const auto index_b = b.find_last_of('.');
@ -141,10 +150,11 @@ int main(int argc, char** argv) {
return patch_a > patch_b;
});
cout << "Date";
for(auto it = versions.begin(); it != versions.end(); it++)
cout << "," << *it;
cout << endl;
cout << "Writing statistics" << endl;
_file_out << "Date";
for(auto & version : versions)
_file_out << "," << version;
_file_out << endl;
for(const auto& entry : statistics) {
auto time = system_clock::to_time_t(entry->timestamp);
@ -158,14 +168,17 @@ int main(int argc, char** argv) {
version_count[name] += version.second;
}
cout << string_time;
_file_out << string_time;
for(const auto& name : versions) {
cout << "," << version_count[name];
_file_out << "," << version_count[name];
}
cout << endl;
}
}
*/
_file_out << endl;
}s
cout << "Done statistics" << endl;
_file_out.flush();
}
return 0;
*/
ssl_manager = make_shared<ts::ssl::SSLManager>();
{

View File

@ -45,7 +45,7 @@ message ServerValidation {
}
message LicenseResponse {
required bool valid = 1;
required bool valid = 1; //If set the license is valid. The blacklist field could still be active. If the flag is false then the blacklist will container the message
required Blacklist blacklist = 2;
optional LicenseInfo license_info = 3; //Only availible when ServerValidation::license_info = true
}

View File

@ -305,43 +305,117 @@ bool LicenseManager::logStatistic(const std::string &key, const std::string& uni
return true;
}
std::deque<std::unique_ptr<LicenseManager::GlobalUserStatistics>> LicenseManager::list_statistics_user(const system_clock::time_point &begin, const system_clock::time_point &end, const milliseconds &interval) {
map<std::string, deque<unique_ptr<LicenseManager::UserStatistics>>> server_statistics;
std::shared_ptr<LicenseManager::UserHistory> LicenseManager::list_statistics_user(const system_clock::time_point &begin, const system_clock::time_point &end, const milliseconds &interval) {
auto timeout = hours(2) + minutes(10); //TODO timeout configurable?
auto state = command(this->database,"SELECT * FROM `history_online` WHERE `timestamp` >= :timestamp_start AND `timestamp` <= :timestamp_end ORDER BY `timestamp` ASC",
/* initialize the result */
auto allocated_records = (size_t) floor((end - begin) / interval) + 1;
auto _result = (UserHistory*) malloc(sizeof(UserHistory) + sizeof(GlobalUserStatistics) * allocated_records);
new (_result) UserHistory();
auto result = shared_ptr<UserHistory>(_result, [](UserHistory* ptr){
ptr->~UserHistory();
free(ptr);
});
result->record_count = 0;
result->begin = begin;
result->end = end;
result->interval = interval;
memset(&result->history[0], 0, allocated_records * sizeof(GlobalUserStatistics));
auto info = &_result->history[0];
/* temp db variables */
map<std::string, LicenseManager::DatabaseUserStatistics> server_statistics;
bool have_key, have_uid;
LicenseManager::DatabaseUserStatistics temp_stats; /* temp struct for stats parsing */
LicenseManager::DatabaseUserStatistics* stats_ptr; /* pointer to the target stats */
std::chrono::system_clock::time_point current_timestamp = begin + interval; /* upper limit of the current interval */
auto state = command(this->database, "SELECT * FROM `history_online` WHERE `timestamp` >= :timestamp_start AND `timestamp` <= :timestamp_end ORDER BY `timestamp` ASC",
variable{":timestamp_start", duration_cast<milliseconds>(begin.time_since_epoch() - timeout).count()},
variable{":timestamp_end", duration_cast<milliseconds>(end.time_since_epoch()).count()}
).query([&server_statistics](int columns, std::string* values, std::string* names){
size_t key_id = 0;
std::string unique_id;
auto info = make_unique<LicenseManager::UserStatistics>();
).query([&](int columns, std::string* values, std::string* names) {
/* find the user statistic ptr */
{
size_t key_id = 0;
std::string unique_id;
have_key = false;
have_uid = false;
for(int index = 0; index < columns; index++) {
try {
if(names[index] == "keyId") {
key_id = stoull(values[index]);
have_key = true;
} else if(names[index] == "unique_id") {
unique_id = values[index];
have_uid = true;
} else {
continue;
}
if(have_key && have_uid)
break;
} catch (std::exception& ex) {
logError("Failed to parse column " + names[index] + " => " + ex.what() + " (Value: " + values[index] + ")");
return 0;
}
}
if(!have_key || !have_uid) return 0; //TODO: May log a warning
if(key_id == 0) return 0;
stats_ptr = &server_statistics[to_string(key_id) + "_" + unique_id];
}
for(int index = 0; index < columns; index++) {
try {
if(names[index] == "keyId")
key_id = stoull(values[index]);
else if(names[index] == "unique_id")
unique_id = values[index];
else if(names[index] == "timestamp")
info->timestamp = system_clock::time_point() + milliseconds(stoll(values[index]));
if(names[index] == "timestamp")
temp_stats.timestamp = system_clock::time_point() + milliseconds(stoll(values[index]));
else if(names[index] == "server")
info->servers_online = stoull(values[index]);
temp_stats.servers_online = stoull(values[index]);
else if(names[index] == "clients")
info->clients_online = stoull(values[index]);
temp_stats.clients_online = stoull(values[index]);
else if(names[index] == "web")
info->web_clients_online = stoull(values[index]);
temp_stats.web_clients_online = stoull(values[index]);
else if(names[index] == "music")
info->bots_online = stoull(values[index]);
temp_stats.bots_online = stoull(values[index]);
else if(names[index] == "queries")
info->queries_online = stoull(values[index]);
temp_stats.queries_online = stoull(values[index]);
} catch (std::exception& ex) {
logError("Failed to parse column " + names[index] + " => " + ex.what() + " (Value: " + values[index] + ")");
return 0;
}
}
if(key_id == 0) return 0;
server_statistics[to_string(key_id) + "_" + unique_id].push_back(std::move(info));
/* because the query could only be oldest to newest */
while(temp_stats.timestamp > current_timestamp) {
assert(_result->record_count < allocated_records); /* ensure we write to valid memory */
auto min_timestamp = current_timestamp - timeout;
for(auto& server : server_statistics) {
auto& second = server.second;
if(second.timestamp < min_timestamp || second.timestamp.time_since_epoch().count() == 0)
continue; /* last server request is too old to be counted */
info->instance_online++;
info->queries_online += second.queries_online;
info->bots_online += second.bots_online;
info->web_clients_online += second.web_clients_online;
info->clients_online += second.clients_online;
info->servers_online += second.servers_online;
}
info++;
_result->record_count++;
current_timestamp += interval; /* lets gather for the next interval */
}
/* write the "new" statistic */
memcpy(stats_ptr, &temp_stats, sizeof(temp_stats));
return 0;
});
@ -350,41 +424,28 @@ std::deque<std::unique_ptr<LicenseManager::GlobalUserStatistics>> LicenseManager
return {};
}
std::deque<std::unique_ptr<LicenseManager::GlobalUserStatistics>> result;
system_clock::time_point current_timestamp = begin;
while(current_timestamp <= end) {
auto info = make_unique<LicenseManager::GlobalUserStatistics>();
info->timestamp = current_timestamp;
/* flush the last record */
do {
assert(_result->record_count < allocated_records); /* ensure we write to valid memory */
auto min_timestamp = current_timestamp - timeout;
for(auto& server : server_statistics) {
while(!server.second.empty()) {
auto& first = *server.second.begin();
if(first->timestamp > current_timestamp) break; //Entry within the future
if(first->timestamp + timeout < current_timestamp) { //Entry within the past
server.second.pop_front();
continue;
}
if(server.second.size() > 1) {
auto& second = *(server.second.begin() + 1);
if(second->timestamp <= current_timestamp) {
server.second.pop_front(); //The next entry is more up 2 date
continue;
}
}
auto& second = server.second;
if(second.timestamp < min_timestamp)
continue; /* last server request is too old to be counted */
info->instance_online++;
info->queries_online += first->queries_online;
info->bots_online += first->bots_online;
info->web_clients_online += first->web_clients_online;
info->clients_online += first->clients_online;
info->servers_online += first->servers_online;
break;
}
info->instance_online++;
info->queries_online += second.queries_online;
info->bots_online += second.bots_online;
info->web_clients_online += second.web_clients_online;
info->clients_online += second.clients_online;
info->servers_online += second.servers_online;
}
result.push_back(std::move(info));
info++;
_result->record_count++;
current_timestamp += interval;
}
} while(current_timestamp < end);
return result;
}
@ -393,7 +454,7 @@ std::deque<std::unique_ptr<LicenseManager::GlobalVersionsStatistic>> LicenseMana
map<std::string, deque<unique_ptr<LicenseManager::GlobalVersionsStatistic>>> server_statistics;
auto timeout = hours(2) + minutes(10); //TODO timeout configurable?
auto state = command(this->database,"SELECT * FROM `history_version` WHERE `timestamp` >= :timestamp_start AND `timestamp` <= :timestamp_end ORDER BY `timestamp` ASC",
auto state = command(this->database, "SELECT * FROM `history_version` WHERE `timestamp` >= :timestamp_start AND `timestamp` <= :timestamp_end ORDER BY `timestamp` ASC",
variable{":timestamp_start", duration_cast<milliseconds>(begin.time_since_epoch() - timeout).count()},
variable{":timestamp_end", duration_cast<milliseconds>(end.time_since_epoch()).count()}
).query([&server_statistics](int columns, std::string* values, std::string* names){

View File

@ -29,13 +29,13 @@ namespace license {
threads::Mutex entry_update_lock;
std::deque<CacheEntry*> entries;
};
struct UserStatistics {
std::chrono::system_clock::time_point timestamp;
uint64_t clients_online;
uint64_t web_clients_online;
uint64_t bots_online;
uint64_t queries_online;
uint64_t servers_online;
uint64_t clients_online = 0;
uint64_t web_clients_online = 0;
uint64_t bots_online = 0;
uint64_t queries_online = 0;
uint64_t servers_online = 0;
};
struct ExtendedUserStatistics : public UserStatistics{
@ -43,13 +43,28 @@ namespace license {
};
struct GlobalUserStatistics : public UserStatistics {
uint64_t instance_online;
uint64_t instance_online = 0;
};
struct DatabaseUserStatistics : public UserStatistics {
std::chrono::system_clock::time_point timestamp{};
};
struct GlobalVersionsStatistic {
std::chrono::system_clock::time_point timestamp;
std::map<std::string, uint32_t> versions;
};
struct UserHistory {
std::chrono::system_clock::time_point begin{};
std::chrono::system_clock::time_point end{};
std::chrono::milliseconds interval{0};
size_t record_count = 0;
GlobalUserStatistics history[0];
};
static_assert(sizeof(UserHistory) == 32);
public:
LicenseManager(sql::SqlManager* database);
~LicenseManager();
@ -68,7 +83,7 @@ namespace license {
bool logRequest(const std::string& /* key */, const std::string& /* unique_id */, const std::string& /* ip */, const std::string& /* version */, int /* result */);
bool logStatistic(const std::string& /* key */, const std::string& /* unique_id */, const std::string& /* ip */, const ts::proto::license::PropertyUpdateRequest&);
//std::deque<std::unique_ptr<ExtendedUserStatistics>> list_statistics_user(const std::string& key, const std::chrono::system_clock::time_point& begin, const std::chrono::system_clock::time_point& end);
std::deque<std::unique_ptr<GlobalUserStatistics>> list_statistics_user(const std::chrono::system_clock::time_point& begin, const std::chrono::system_clock::time_point& end, const std::chrono::milliseconds& /* interval */);
std::shared_ptr<UserHistory> list_statistics_user(const std::chrono::system_clock::time_point& begin, const std::chrono::system_clock::time_point& end, const std::chrono::milliseconds& /* interval */);
std::deque<std::unique_ptr<GlobalVersionsStatistic>> list_statistics_version(const std::chrono::system_clock::time_point& begin, const std::chrono::system_clock::time_point& end, const std::chrono::milliseconds& /* interval */);
inline sql::SqlManager* sql() { return this->database; }

View File

@ -49,6 +49,8 @@ namespace license {
std::string key;
std::string unique_identifier;
bool invalid_license = false;
void init();
void uninit();
void sendPacket(const protocol::packet&);

View File

@ -95,14 +95,25 @@ bool LicenseServer::handleDisconnect(shared_ptr<ConnectedClient>& client, protoc
inline void fill_info(proto::license::LicenseInfo* proto, const shared_ptr<LicenseInfo>& info, const std::string& key) {
proto->set_key(key);
proto->set_username(info->username);
proto->set_first_name(info->first_name);
proto->set_last_name(info->last_name);
proto->set_email(info->email);
proto->set_type(info->type);
proto->set_created(duration_cast<milliseconds>(info->creation.time_since_epoch()).count());
proto->set_begin(duration_cast<milliseconds>(info->start.time_since_epoch()).count());
proto->set_end(duration_cast<milliseconds>(info->end.time_since_epoch()).count());
if(info) {
proto->set_username(info->username);
proto->set_first_name(info->first_name);
proto->set_last_name(info->last_name);
proto->set_email(info->email);
proto->set_type(info->type);
proto->set_created(duration_cast<milliseconds>(info->creation.time_since_epoch()).count());
proto->set_begin(duration_cast<milliseconds>(info->start.time_since_epoch()).count());
proto->set_end(duration_cast<milliseconds>(info->end.time_since_epoch()).count());
} else {
proto->set_username("invalid (null)");
proto->set_first_name("invalid (null)");
proto->set_last_name("invalid (null)");
proto->set_email("invalid (null)");
proto->set_type(0);
proto->set_created(0);
proto->set_begin(0);
proto->set_end(0);
}
}
std::string string_to_hex(const std::string& input)
@ -154,7 +165,9 @@ bool LicenseServer::handleServerValidation(shared_ptr<ConnectedClient> &client,
client->unique_identifier = pkt.info().has_unique_id() ? pkt.info().unique_id() : client->address();
if(remoteLicense && pkt.licensed()) {
auto info = this->manager->licenseInfo(remoteLicense->key());
if(!info) {
response.mutable_blacklist()->set_reason("License hasn't been found.");
response.set_valid(false);
/*
@ -179,6 +192,7 @@ bool LicenseServer::handleServerValidation(shared_ptr<ConnectedClient> &client,
logMessage(LOG_GENERAL, "[CLIENT][{}] Remote license hasn't been found in database. Shutting down server!", client->address());
} else {
if(info->deleted) {
response.mutable_blacklist()->set_reason("License has been deleted.");
response.set_valid(false);
logMessage(LOG_GENERAL, "[CLIENT][{}] Remote license has been deleted! Shutting down server!", client->address());
} else {
@ -191,7 +205,15 @@ bool LicenseServer::handleServerValidation(shared_ptr<ConnectedClient> &client,
response.set_valid(true);
}
response.mutable_blacklist()->set_state(ts::proto::license::VALID);
if(response.valid())
response.mutable_blacklist()->set_state(ts::proto::license::VALID);
else {
if(!response.has_license_info())
fill_info(response.mutable_license_info(), nullptr, ""); /* "Hack" for old clients which require a license. Else the server would not be stopped */
response.mutable_blacklist()->set_state(ts::proto::license::BLACKLISTED); /* "Hack" for all old clients */
client->invalid_license = true;
}
client->sendPacket(protocol::packet{protocol::PACKET_SERVER_VALIDATION_RESPONSE, response});
client->protocol.state = protocol::PROPERTY_ADJUSTMENT;
return true;
@ -199,6 +221,18 @@ bool LicenseServer::handleServerValidation(shared_ptr<ConnectedClient> &client,
bool LicenseServer::handlePacketPropertyUpdate(shared_ptr<ConnectedClient> &client, protocol::packet &packet, std::string &error) {
TEST_PROTOCOL_STATE(PROPERTY_ADJUSTMENT);
if(client->invalid_license) {
ts::proto::license::PropertyUpdateResponse response;
response.set_accepted(true);
response.set_reset_speach(0);
response.set_speach_total_remote(0);
response.set_speach_varianz_corrector(0);
client->sendPacket(protocol::packet{protocol::PACKET_SERVER_PROPERTY_ADJUSTMENT, response});
this->disconnectClient(client, "finished");
/* Not sure if we really want here to log these data. May put a lvalid=false within the db? */
return true;
}
PARSE_PROTO(PropertyUpdateRequest, pkt);
logMessage("[CLIENT][" + client->address() + "] Got server statistics:");

View File

@ -34,9 +34,9 @@ namespace license {
std::chrono::system_clock::time_point begin;
std::chrono::system_clock::time_point end;
std::chrono::milliseconds period;
HistoryType type;
HistoryType type;
std::deque<std::unique_ptr<server::LicenseManager::GlobalUserStatistics>> statistics;
std::shared_ptr<server::LicenseManager::UserHistory> statistics;
};
class StatisticManager {

View File

@ -462,13 +462,14 @@ bool WebStatistics::handle_message(const std::shared_ptr<license::web::WebStatis
response["history"]["end"] = duration_cast<milliseconds>(history->end.time_since_epoch()).count();
response["history"]["interval"] = duration_cast<milliseconds>(history->period).count();
int index = 0;
for(auto& element : history->statistics) {
response["history"]["data"][index]["instances"] = element->instance_online;
response["history"]["data"][index]["servers"] = element->servers_online;
response["history"]["data"][index]["clients"] = element->clients_online;
response["history"]["data"][index]["music"] = element->bots_online;
index++;
int index;
auto stats = history->statistics;
for(index = 0; index < stats->record_count; index++) {
response["history"]["data"][index]["instances"] = stats->history[index].instance_online;
response["history"]["data"][index]["servers"] = stats->history[index].servers_online;
response["history"]["data"][index]["clients"] = stats->history[index].clients_online;
response["history"]["data"][index]["music"] = stats->history[index].bots_online;
}
lock_guard lock(client->execute_lock);

View File

@ -101,7 +101,7 @@ namespace license {
inline std::string key() { return std::string(data.licenceKey, 64); }
inline std::chrono::time_point<std::chrono::system_clock> end() { return std::chrono::system_clock::time_point() + std::chrono::milliseconds(this->data.endTimestamp); }
inline std::string owner() { return std::string(this->data.licenceOwner); }
inline std::string owner() { return std::string(this->data.licenceOwner); } //Scopetita
inline bool isValid() { return data.endTimestamp == 0 || std::chrono::system_clock::now() < this->end(); }
inline bool isPremium(){ return isPremiumLicense(data.type); }
} __attribute__ ((__packed__));

View File

@ -9,8 +9,17 @@ using namespace std;
using namespace std::chrono;
void LicenceRequest::handlePacketDisconnect(const std::string& message) {
if(this->state != protocol::DISCONNECTING)
LICENSE_FERR(this, UnexcpectedDisconnectException, "Remote side closed the connection (" + message + ")");
if(this->state != protocol::DISCONNECTING) {
/*
* We got an early disconnect.
* Test if we have a result. If so and the license is invalid then we could use that result
*/
if(this->response && !this->response->license_valid) {
this->currentFuture->executionSucceed(this->response);
} else {
LICENSE_FERR(this, UnexcpectedDisconnectException, "Remote side closed the connection unexpectedly (" + message + ")");
}
}
}
void LicenceRequest::handlePacketHandshake(const std::string& data) {
@ -48,7 +57,9 @@ void LicenceRequest::handlePacketLicenseInfo(const std::string& message) {
auto result = make_shared<LicenseRequestResponse>();
auto licenseInfo = make_shared<LicenseInfo>();
if(!response.has_license_info() && this->data->license) LICENSE_FERR(this, InvalidResponseException, "Missing license info");
if(!response.has_license_info() && this->data->license && response.valid() && response.blacklist().state() == ts::proto::license::VALID) {
LICENSE_FERR(this, InvalidResponseException, "Missing license info");
}
if(this->data->license) {
licenseInfo->type = (LicenseType) response.license_info().type();
@ -75,7 +86,6 @@ void LicenceRequest::handlePacketLicenseInfo(const std::string& message) {
result->license = licenseInfo;
this->response = result;
ts::proto::license::PropertyUpdateRequest infos;
infos.set_speach_total(this->data->speach_total);
infos.set_speach_dead(this->data->speach_dead);

View File

@ -37,7 +37,7 @@ ConnectedClient::~ConnectedClient() {
memtrack::freed<ConnectedClient>(this);
}
std::shared_ptr<ConnectionInfoData> ConnectedClient::requestConnectionInfo(const std::shared_ptr<ConnectedClient>& receiver) {
std::shared_ptr<ConnectionInfoData> ConnectedClient::request_connection_info(const std::shared_ptr<ConnectedClient> &receiver, bool& send_temp) {
auto& info = this->connection_info;
lock_guard info_lock(info.lock);
@ -49,11 +49,17 @@ std::shared_ptr<ConnectionInfoData> ConnectedClient::requestConnectionInfo(const
info.data = nullptr;
}
info.receiver.erase(std::remove_if(info.receiver.begin(), info.receiver.end(), [&](const weak_ptr<ConnectedClient>& weak) {
auto locked = weak.lock();
return !locked || locked == receiver;
}), info.receiver.end());
info.receiver.push_back(receiver);
if(receiver) {
info.receiver.erase(std::remove_if(info.receiver.begin(), info.receiver.end(), [&](const weak_ptr<ConnectedClient>& weak) {
auto locked = weak.lock();
if(locked == receiver) {
send_temp = true;
return true;
}
return !locked;
}), info.receiver.end());
info.receiver.push_back(receiver);
}
if(chrono::system_clock::now() - info.last_requested >= chrono::seconds(1)) {
info.last_requested = chrono::system_clock::now();
@ -764,7 +770,7 @@ void ConnectedClient::sendServerInit() {
command["lt"] = LicenseType::LICENSE_HOSTING;
} else
command["lt"] = ts::config::server::DefaultServerLicense;
command["pv"] = 6; //Protocol version
command["pv"] = 6; //Protocol version
command["acn"] = this->getDisplayName();
command["aclid"] = this->getClientId();
if(dynamic_cast<VoiceClient*>(this)) {

View File

@ -157,7 +157,7 @@ namespace ts {
virtual bool notifyGroupPermList(const std::shared_ptr<Group>&, bool);
virtual bool notifyClientPermList(ClientDbId, const std::shared_ptr<permission::v2::PermissionManager>&, bool);
virtual bool notifyChannelGroupList();
virtual bool notifyConnectionInfo(std::shared_ptr<ConnectedClient>,std::shared_ptr<ConnectionInfoData>);
virtual bool notifyConnectionInfo(const std::shared_ptr<ConnectedClient> &target, const std::shared_ptr<ConnectionInfoData> &info);
virtual bool notifyChannelSubscribed(const std::deque<std::shared_ptr<BasicChannel>> &);
virtual bool notifyChannelUnsubscribed(const std::deque<std::shared_ptr<BasicChannel>> &);
@ -269,7 +269,7 @@ namespace ts {
bool shouldFloodBlock();
virtual bool ignoresFlood() { return !this->block_flood; }
std::shared_ptr<ConnectionInfoData> requestConnectionInfo(const std::shared_ptr<ConnectedClient>& /* receiver */);
std::shared_ptr<ConnectionInfoData> request_connection_info(const std::shared_ptr<ConnectedClient> & /* receiver */, bool& /* send temporary (no client response yet) */);
virtual void updateChannelClientProperties(bool /* lock channel tree */, bool /* notify our self */);
void updateTalkRights(permission::PermissionValue talk_power);

View File

@ -651,9 +651,13 @@ CommandResult ConnectedClient::handleCommandGetConnectionInfo(Command &cmd) {
auto client = this->server->findClient(cmd["clid"].as<ClientId>());
if (!client) return {findError("client_invalid_id"), "invalid client id"};
auto info = client->requestConnectionInfo(_this.lock());
if (info)
bool send_temp;
auto info = client->request_connection_info(_this.lock(), send_temp);
if (info) {
this->notifyConnectionInfo(client, info);
} else if(send_temp) {
this->notifyConnectionInfo(client, nullptr);
}
return CommandResult::Success;
}
@ -872,6 +876,7 @@ CommandResult ConnectedClient::handleCommandPermissionList(Command &cmd) {
if (!permission->clientSupported) continue;
auto &blk = list_builder[index++];
blk["permname"] = permission->name;
blk["permdesc"] = permission->description;
blk["permid"] = permission->type;
@ -879,7 +884,7 @@ CommandResult ConnectedClient::handleCommandPermissionList(Command &cmd) {
return list_builder;
};
if(this->getType() == CLIENT_TEASPEAK || this->getType() == CLIENT_TEAMSPEAK || this->getType() == CLIENT_QUERY) {
if((this->getType() == CLIENT_TEASPEAK || this->getType() == CLIENT_TEAMSPEAK || this->getType() == CLIENT_QUERY) && false) {
Command response(this->getExternalType() == CLIENT_TEAMSPEAK ? "notifypermissionlist" : "");
{
lock_guard lock(permission_list_string_lock);

View File

@ -11,6 +11,7 @@
#include <log/LogUtils.h>
#include <misc/sassert.h>
#include <misc/timer.h>
#include "./web/WebClient.h"
using namespace std::chrono;
using namespace std;
@ -247,16 +248,65 @@ bool ConnectedClient::notifyClientChannelGroupChanged(
return true;
}
bool ConnectedClient::notifyConnectionInfo(std::shared_ptr<ConnectedClient> target, std::shared_ptr<ConnectionInfoData> info) {
bool ConnectedClient::notifyConnectionInfo(const shared_ptr<ConnectedClient> &target, const shared_ptr<ConnectionInfoData> &info) {
Command notify("notifyconnectioninfo");
notify["clid"] = target->getClientId();
if(target->getClientId() != this->getClientId()){
for(const auto& elm : info->properties)
notify[elm.first] = elm.second;
notify["connection_connected_time"] = chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now() - target->connectTimestamp).count();
notify["connection_filetransfer_bandwidth_sent"] = 0;
notify["connection_filetransfer_bandwidth_received"] = 0;
if(target->getClientId() != this->getClientId()) {
/* default values which normally sets the client */
notify["connection_bandwidth_received_last_minute_control"] = -1;
notify["connection_bandwidth_received_last_minute_keepalive"] = -1;
notify["connection_bandwidth_received_last_minute_speech"] = -1;
notify["connection_bandwidth_received_last_second_control"] = -1;
notify["connection_bandwidth_received_last_second_keepalive"] = -1;
notify["connection_bandwidth_received_last_second_speech"] = -1;
notify["connection_bandwidth_sent_last_minute_control"] = -1;
notify["connection_bandwidth_sent_last_minute_keepalive"] = -1;
notify["connection_bandwidth_sent_last_minute_speech"] = -1;
notify["connection_bandwidth_sent_last_second_control"] = -1;
notify["connection_bandwidth_sent_last_second_keepalive"] = -1;
notify["connection_bandwidth_sent_last_second_speech"] = -1;
notify["connection_bytes_received_control"] = -1;
notify["connection_bytes_received_keepalive"] = -1;
notify["connection_bytes_received_speech"] = -1;
notify["connection_bytes_sent_control"] = -1;
notify["connection_bytes_sent_keepalive"] = -1;
notify["connection_bytes_sent_speech"] = -1;
notify["connection_packets_received_control"] = -1;
notify["connection_packets_received_keepalive"] = -1;
notify["connection_packets_received_speech"] = -1;
notify["connection_packets_sent_control"] = -1;
notify["connection_packets_sent_keepalive"] = -1;
notify["connection_packets_sent_speech"] = -1;
notify["connection_server2client_packetloss_control"] = -1;
notify["connection_server2client_packetloss_keepalive"] = -1;
notify["connection_server2client_packetloss_speech"] = -1;
notify["connection_server2client_packetloss_total"] = -1;
notify["connection_ping"] = 0;
notify["connection_ping_deviation"] = 0;
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();
}
}
if(target->getClientId() == this->getClientId() || this->permissionGranted(permission::PERMTEST_ORDERED, permission::b_client_remoteaddress_view, 1, target->currentChannel, true)) {
@ -264,11 +314,13 @@ bool ConnectedClient::notifyConnectionInfo(std::shared_ptr<ConnectedClient> targ
notify["connection_client_port"] = target->getPeerPort();
}
notify["connection_client2server_packetloss_speech"] = 0.f;
notify["connection_client2server_packetloss_keepalive"] = 0.f;
notify["connection_client2server_packetloss_control"] = 0.f;
notify["connection_client2server_packetloss_total"] = 0.f;
//Needs to be filled out
notify["connection_client2server_packetloss_speech"] = -1;
notify["connection_client2server_packetloss_keepalive"] = -1;
notify["connection_client2server_packetloss_control"] = -1;
notify["connection_client2server_packetloss_total"] = -1;
notify["connection_connected_time"] = chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now() - target->connectTimestamp).count();
notify["connection_idle_time"] = chrono::duration_cast<chrono::milliseconds>(chrono::system_clock::now() - target->idleTimestamp).count();
this->sendCommand(notify);
return true;

View File

@ -90,7 +90,8 @@ void VoiceClient::tick(const std::chrono::system_clock::time_point &time) {
duration_cast<milliseconds>(time - this->lastPingRequest).count(),
duration_cast<milliseconds>(time - this->lastPingResponse).count());
this->requestConnectionInfo(nullptr);
bool force;
this->request_connection_info(nullptr, force);
this->lastPingResponse = system_clock::now();
return;
}

View File

@ -124,6 +124,7 @@ ts::CommandResult VoiceClient::handleCommandClientInitIv(Command& command) {
initivexpand2["beta"] = base64::encode(this->crypto.beta);
initivexpand2["omega"] = serverOmega;
initivexpand2["proof"] = proof;
initivexpand2["tvd"] = "";
initivexpand2["root"] = base64::encode((char*) this->crypto.chain_data->public_key, 32);
initivexpand2["ot"] = 1;