Some license server improvements
This commit is contained in:
parent
14d9936d90
commit
3e39bcc38c
@ -45,42 +45,32 @@ add_executable(TeaLicenseServer ${LICENCE_SOURCE_FILES} ${PROTO_SRCS} ${PROTO_HD
|
|||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(TeaLicenseServer
|
target_link_libraries(TeaLicenseServer
|
||||||
${LIBRARY_PATH_THREAD_POOL} #Static
|
threadpool::static #Static
|
||||||
TeaSpeak #Static
|
TeaSpeak #Static
|
||||||
TeaLicenseHelper #Static
|
TeaLicenseHelper #Static
|
||||||
${LIBRARY_PATH_TERMINAL} #Static
|
CXXTerminal::static #Static
|
||||||
${LIBRARY_PATH_VARIBALES}
|
${StringVariable_LIBRARIES_STATIC}
|
||||||
${LIBRARY_PATH_YAML}
|
# stdc++fs
|
||||||
pthread
|
libevent::core libevent::pthreads
|
||||||
stdc++fs
|
yaml-cpp
|
||||||
libevent::core
|
|
||||||
libevent::pthreads
|
|
||||||
${LIBRARY_PATH_OPUS}
|
|
||||||
${LIBRARY_PATH_JSON}
|
|
||||||
${LIBRARY_PATH_PROTOBUF}
|
${LIBRARY_PATH_PROTOBUF}
|
||||||
|
${ed25519_LIBRARIES_STATIC}
|
||||||
|
|
||||||
#We're forsed to use boringssl caused by the fact that boringssl is already within webrtc!
|
#We're forsed to use boringssl caused by the fact that boringssl is already within webrtc!
|
||||||
|
|
||||||
#Require a so
|
#Require a so
|
||||||
sqlite3
|
sqlite3
|
||||||
|
protobuf::libprotobuf
|
||||||
|
|
||||||
${LIBRARY_PATH_BREAKPAD}
|
tomcrypt::static
|
||||||
${LIBRARY_PATH_PROTOBUF}
|
tommath::static
|
||||||
|
|
||||||
#${LIBWEBRTC_LIBRARIES} #ATTENTIAN! WebRTC does not work with crypto! (Already contains a crypto version)
|
|
||||||
${LIBRARY_TOM_CRYPT}
|
|
||||||
${LIBRARY_TOM_MATH}
|
|
||||||
|
|
||||||
mysqlclient.a
|
mysqlclient.a
|
||||||
|
jsoncpp_lib
|
||||||
${LIBRARY_PATH_ED255}
|
${DataPipes_LIBRARIES_SHARED} # Also includes glib2.0
|
||||||
|
openssl::ssl::shared
|
||||||
${LIBRARY_PATH_DATA_PIPES}
|
openssl::crypto::shared
|
||||||
${LIBRARY_PATH_NICE}
|
pthread
|
||||||
${LIBRARY_PATH_GLIBC}
|
|
||||||
|
|
||||||
${LIBRARY_PATH_BORINGSSL_SSL}
|
|
||||||
${LIBRARY_PATH_BORINGSSL_CRYPTO}
|
|
||||||
dl
|
dl
|
||||||
z
|
z
|
||||||
)
|
)
|
||||||
|
@ -117,8 +117,8 @@ int main(int argc, char** argv) {
|
|||||||
bool db_connected = true;
|
bool db_connected = true;
|
||||||
((sql::mysql::MySQLManager*) database)->listener_disconnected = [&](bool wanted){
|
((sql::mysql::MySQLManager*) database)->listener_disconnected = [&](bool wanted){
|
||||||
if(wanted) return;
|
if(wanted) return;
|
||||||
logCritical("Lost connection to MySQL server!");
|
logCritical(LOG_GENERAL, "Lost connection to MySQL server!");
|
||||||
logCritical("Stopping server!");
|
logCritical(LOG_GENERAL, "Stopping server!");
|
||||||
db_connected = false;
|
db_connected = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -126,7 +126,7 @@ int main(int argc, char** argv) {
|
|||||||
logMessage(LOG_GENERAL, "Connecting to {}", argv[1]);
|
logMessage(LOG_GENERAL, "Connecting to {}", argv[1]);
|
||||||
auto connect_result = database->connect(string(argv[1]));
|
auto connect_result = database->connect(string(argv[1]));
|
||||||
if(!connect_result) {
|
if(!connect_result) {
|
||||||
logError("Could not connect to mysql server! (" + connect_result.fmtStr() + ")");
|
logError(LOG_GENERAL, "Could not connect to mysql server! (" + connect_result.fmtStr() + ")");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#if false
|
#if false
|
||||||
@ -140,7 +140,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
license_manager = make_shared<server::LicenseManager>(database);
|
license_manager = make_shared<server::LicenseManager>(database);
|
||||||
if(!license_manager->setup(error)) {
|
if(!license_manager->setup(error)) {
|
||||||
logError("Could not start license manager! (" +error + ")");
|
logError(LOG_GENERAL, "Could not start license manager! (" +error + ")");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -244,7 +244,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
{
|
{
|
||||||
web_server = make_shared<license::web::WebStatistics>(license_manager, statistic_manager);
|
web_server = make_shared<license::web::WebStatistics>(license_manager, statistic_manager);
|
||||||
logMessage("Starting web server on [:::]:27788");
|
logMessage(LOG_GENERAL, "Starting web server on [:::]:27788");
|
||||||
if(!web_server->start(error, 27788, ssl_manager->getContext("web_stats"))) {
|
if(!web_server->start(error, 27788, ssl_manager->getContext("web_stats"))) {
|
||||||
logError(LOG_GENERAL, "Failed to start web statistics server!");
|
logError(LOG_GENERAL, "Failed to start web statistics server!");
|
||||||
return 0;
|
return 0;
|
||||||
@ -255,7 +255,7 @@ int main(int argc, char** argv) {
|
|||||||
user_manager = make_shared<UserManager>(database);
|
user_manager = make_shared<UserManager>(database);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
logMessage("Starting license server on [:::]:27786");
|
logMessage(LOG_GENERAL, "Starting license server on [:::]:27786");
|
||||||
struct sockaddr_in listen_addr{};
|
struct sockaddr_in listen_addr{};
|
||||||
memset(&listen_addr, 0, sizeof(listen_addr));
|
memset(&listen_addr, 0, sizeof(listen_addr));
|
||||||
listen_addr.sin_family = AF_INET;
|
listen_addr.sin_family = AF_INET;
|
||||||
@ -264,7 +264,7 @@ int main(int argc, char** argv) {
|
|||||||
|
|
||||||
license_server = make_shared<LicenseServer>(listen_addr, license_manager, statistic_manager, web_server, user_manager);
|
license_server = make_shared<LicenseServer>(listen_addr, license_manager, statistic_manager, web_server, user_manager);
|
||||||
license_server->web_certificate = load_web_certificate();
|
license_server->web_certificate = load_web_certificate();
|
||||||
license_server->startServer();
|
license_server->start();
|
||||||
}
|
}
|
||||||
|
|
||||||
while(db_connected && web_server->running() && license_server->isRunning()) {
|
while(db_connected && web_server->running() && license_server->isRunning()) {
|
||||||
@ -280,7 +280,7 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
web_server->stop();
|
web_server->stop();
|
||||||
license_server->stopServer();
|
license_server->stop();
|
||||||
if(database) database->disconnect();
|
if(database) database->disconnect();
|
||||||
|
|
||||||
logger::uninstall();
|
logger::uninstall();
|
||||||
@ -299,6 +299,6 @@ bool handle_command(string& line) {
|
|||||||
logMessage(LOG_LICENSE_WEB, " {} clients are currently connected!", clients.size());
|
logMessage(LOG_LICENSE_WEB, " {} clients are currently connected!", clients.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
logError("Invalid command: " + line);
|
logError(LOG_GENERAL, "Invalid command: " + line);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
@ -59,7 +59,7 @@ bool LicenseManager::setup(std::string& error) {
|
|||||||
|
|
||||||
SET_VERSION(0);
|
SET_VERSION(0);
|
||||||
case 0:
|
case 0:
|
||||||
logMessage("Updating database! To version 1");
|
logMessage(LOG_GENERAL, "Updating database! To version 1");
|
||||||
CTBL("CREATE TABLE IF NOT EXISTS `history_speach` (`keyId` INT, `timestamp` BIGINT, `total` BIGINT, `dead` BIGINT, `online` BIGINT, `varianz` BIGINT)");
|
CTBL("CREATE TABLE IF NOT EXISTS `history_speach` (`keyId` INT, `timestamp` BIGINT, `total` BIGINT, `dead` BIGINT, `online` BIGINT, `varianz` BIGINT)");
|
||||||
CTBL("CREATE TABLE IF NOT EXISTS `history_online` (`keyId` INT, `timestamp` BIGINT, `server` INT, `clients` INT, `web` INT, `music` INT, `queries` INT)");
|
CTBL("CREATE TABLE IF NOT EXISTS `history_online` (`keyId` INT, `timestamp` BIGINT, `server` INT, `clients` INT, `web` INT, `music` INT, `queries` INT)");
|
||||||
|
|
||||||
@ -116,7 +116,7 @@ bool LicenseManager::registerLicense(const std::string& key, const shared_ptr<Li
|
|||||||
result res;
|
result res;
|
||||||
res = command(this->database, "INSERT INTO `license` (`key`, `type`, `deleted`, `issuer`) VALUES (:key, :type, :deleted, :issuer)", variable{":key", key}, variable{":type", (uint32_t) info->type}, variable{":deleted", false}, variable{":issuer", issuer}).execute();
|
res = command(this->database, "INSERT INTO `license` (`key`, `type`, `deleted`, `issuer`) VALUES (:key, :type, :deleted, :issuer)", variable{":key", key}, variable{":type", (uint32_t) info->type}, variable{":deleted", false}, variable{":issuer", issuer}).execute();
|
||||||
if(!res) {
|
if(!res) {
|
||||||
logError("Could not register new license (" + res.fmtStr() + ")");
|
logError(LOG_GENERAL, "Could not register new license (" + res.fmtStr() + ")");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
auto keyId = this->id_cache->getKeyId(key);
|
auto keyId = this->id_cache->getKeyId(key);
|
||||||
@ -133,7 +133,7 @@ bool LicenseManager::registerLicense(const std::string& key, const shared_ptr<Li
|
|||||||
variable{":end", duration_cast<milliseconds>(info->end.time_since_epoch()).count()}
|
variable{":end", duration_cast<milliseconds>(info->end.time_since_epoch()).count()}
|
||||||
).execute();
|
).execute();
|
||||||
if(!res) {
|
if(!res) {
|
||||||
logError("Could not register new license info (" + res.fmtStr() + ")");
|
logError(LOG_GENERAL, "Could not register new license info (" + res.fmtStr() + ")");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -145,13 +145,13 @@ bool LicenseManager::deleteLicense(const std::string& key, bool full) {
|
|||||||
if(keyId == 0) return false; //Never exists
|
if(keyId == 0) return false; //Never exists
|
||||||
|
|
||||||
auto res = command(this->database, "DELETE FROM `license` WHERE `key` = :key", variable{":key", key}).execute();
|
auto res = command(this->database, "DELETE FROM `license` WHERE `key` = :key", variable{":key", key}).execute();
|
||||||
if(!res) logError("Could not delete license (" + res.fmtStr() + ")");
|
if(!res) logError(LOG_GENERAL, "Could not delete license (" + res.fmtStr() + ")");
|
||||||
res = command(this->database, "DELETE FROM `license_info` WHERE `keyId` = :key", variable{":keyId", keyId}).execute();
|
res = command(this->database, "DELETE FROM `license_info` WHERE `keyId` = :key", variable{":keyId", keyId}).execute();
|
||||||
if(!res) logError("Could not delete license (" + res.fmtStr() + ")");
|
if(!res) logError(LOG_GENERAL, "Could not delete license (" + res.fmtStr() + ")");
|
||||||
return !!res;
|
return !!res;
|
||||||
} else {
|
} else {
|
||||||
auto res = command(this->database, "UPDATE `license` SET `deleted` = :true WHERE `key` = :key", variable{":true", true}, variable{":key", key}).execute();
|
auto res = command(this->database, "UPDATE `license` SET `deleted` = :true WHERE `key` = :key", variable{":true", true}, variable{":key", key}).execute();
|
||||||
if(!res) logError("Could not delete license (" + res.fmtStr() + ")");
|
if(!res) logError(LOG_GENERAL, "Could not delete license (" + res.fmtStr() + ")");
|
||||||
return !!res;
|
return !!res;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,7 +162,7 @@ bool LicenseManager::validLicenseKey(const std::string& key) {
|
|||||||
*flag = true;
|
*flag = true;
|
||||||
return 0;
|
return 0;
|
||||||
}, &valid);
|
}, &valid);
|
||||||
if(!res) logError("Could not validate license (" + res.fmtStr() + ")");
|
if(!res) logError(LOG_GENERAL, "Could not validate license (" + res.fmtStr() + ")");
|
||||||
return !!res && valid;
|
return !!res && valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -214,7 +214,7 @@ inline std::map<std::string, std::shared_ptr<LicenseInfo>> query_license(SqlMana
|
|||||||
return 0;
|
return 0;
|
||||||
}, &result);
|
}, &result);
|
||||||
logTrace(LOG_GENERAL, "Query returned {} results", result.size());
|
logTrace(LOG_GENERAL, "Query returned {} results", result.size());
|
||||||
if(!res) logError("Could not query license (" + res.fmtStr() + ")");
|
if(!res) logError(LOG_GENERAL, "Could not query license (" + res.fmtStr() + ")");
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -246,7 +246,7 @@ bool LicenseManager::logRequest(const std::string& key, const std::string& uniqu
|
|||||||
variable{":unique_id", unique_id},
|
variable{":unique_id", unique_id},
|
||||||
variable{":result", state}).execute();
|
variable{":result", state}).execute();
|
||||||
if(!res) {
|
if(!res) {
|
||||||
logError("Could not log license validation (" + res.fmtStr() + ")");
|
logError(LOG_GENERAL, "Could not log license validation (" + res.fmtStr() + ")");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,7 +258,7 @@ bool LicenseManager::logRequest(const std::string& key, const std::string& uniqu
|
|||||||
variable{":version", version}
|
variable{":version", version}
|
||||||
).execute();
|
).execute();
|
||||||
if(!res)
|
if(!res)
|
||||||
logError("Could not log license version statistic (" + res.fmtStr() + ")");
|
logError(LOG_GENERAL, "Could not log license version statistic (" + res.fmtStr() + ")");
|
||||||
res = {};
|
res = {};
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -284,7 +284,7 @@ bool LicenseManager::logStatistic(const std::string &key, const std::string& uni
|
|||||||
variable{":query", data.queries_online()}
|
variable{":query", data.queries_online()}
|
||||||
).execute();
|
).execute();
|
||||||
if(!res)
|
if(!res)
|
||||||
logError("Could not log license statistics (" + res.fmtStr() + ")");
|
logError(LOG_GENERAL, "Could not log license statistics (" + res.fmtStr() + ")");
|
||||||
res = {};
|
res = {};
|
||||||
}
|
}
|
||||||
//SELECT * FROM `license_info` WHERE `keyId` IN (SELECT `keyId` FROM `license` WHERE `key` = '000')
|
//SELECT * FROM `license_info` WHERE `keyId` IN (SELECT `keyId` FROM `license` WHERE `key` = '000')
|
||||||
@ -299,7 +299,7 @@ bool LicenseManager::logStatistic(const std::string &key, const std::string& uni
|
|||||||
variable{":varianz", data.speach_varianz()}
|
variable{":varianz", data.speach_varianz()}
|
||||||
).execute();
|
).execute();
|
||||||
if(!res)
|
if(!res)
|
||||||
logError("Could not log license statistics (" + res.fmtStr() + ")");
|
logError(LOG_GENERAL, "Could not log license statistics (" + res.fmtStr() + ")");
|
||||||
res = {};
|
res = {};
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -347,48 +347,38 @@ std::shared_ptr<LicenseManager::UserHistory> LicenseManager::list_statistics_use
|
|||||||
have_key = false;
|
have_key = false;
|
||||||
have_uid = false;
|
have_uid = false;
|
||||||
for(int index = 0; index < columns; index++) {
|
for(int index = 0; index < columns; index++) {
|
||||||
try {
|
|
||||||
if(names[index] == "keyId") {
|
if(names[index] == "keyId") {
|
||||||
key_id = stoull(values[index]);
|
key_id = strtol(values[index].c_str(), nullptr, 10);
|
||||||
|
if(key_id == 0) return 0; /* invalid key id */
|
||||||
|
|
||||||
have_key = true;
|
have_key = true;
|
||||||
|
if(have_key && have_uid) goto process_tag;
|
||||||
} else if(names[index] == "unique_id") {
|
} else if(names[index] == "unique_id") {
|
||||||
unique_id = values[index];
|
unique_id = values[index];
|
||||||
have_uid = true;
|
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(have_key && have_uid) goto process_tag;
|
||||||
if(key_id == 0) return 0;
|
}
|
||||||
|
}
|
||||||
|
return 0; /* key or uid haven't been found */
|
||||||
|
|
||||||
|
process_tag:
|
||||||
stats_ptr = &server_statistics[to_string(key_id) + "_" + unique_id];
|
stats_ptr = &server_statistics[to_string(key_id) + "_" + unique_id];
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int index = 0; index < columns; index++) {
|
for(int index = 0; index < columns; index++) {
|
||||||
try {
|
|
||||||
if(names[index] == "timestamp")
|
if(names[index] == "timestamp")
|
||||||
temp_stats.timestamp = system_clock::time_point() + milliseconds(stoll(values[index]));
|
temp_stats.timestamp = system_clock::time_point() + milliseconds(stoll(values[index]));
|
||||||
else if(names[index] == "server")
|
else if(names[index] == "server")
|
||||||
temp_stats.servers_online = stoull(values[index]);
|
temp_stats.servers_online = strtol(values[index].c_str(), nullptr, 10);
|
||||||
else if(names[index] == "clients")
|
else if(names[index] == "clients")
|
||||||
temp_stats.clients_online = stoull(values[index]);
|
temp_stats.clients_online = strtol(values[index].c_str(), nullptr, 10);
|
||||||
else if(names[index] == "web")
|
else if(names[index] == "web")
|
||||||
temp_stats.web_clients_online = stoull(values[index]);
|
temp_stats.web_clients_online = strtol(values[index].c_str(), nullptr, 10);
|
||||||
else if(names[index] == "music")
|
else if(names[index] == "music")
|
||||||
temp_stats.bots_online = stoull(values[index]);
|
temp_stats.bots_online = strtol(values[index].c_str(), nullptr, 10);
|
||||||
else if(names[index] == "queries")
|
else if(names[index] == "queries")
|
||||||
temp_stats.queries_online = stoull(values[index]);
|
temp_stats.queries_online = strtol(values[index].c_str(), nullptr, 10);
|
||||||
} catch (std::exception& ex) {
|
|
||||||
logError("Failed to parse column " + names[index] + " => " + ex.what() + " (Value: " + values[index] + ")");
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* because the query could only be oldest to newest */
|
/* because the query could only be oldest to newest */
|
||||||
@ -420,7 +410,7 @@ std::shared_ptr<LicenseManager::UserHistory> LicenseManager::list_statistics_use
|
|||||||
});
|
});
|
||||||
|
|
||||||
if(!state) {
|
if(!state) {
|
||||||
logError("Could not read license statistics (" + state.fmtStr() + ")");
|
logError(LOG_GENERAL, "Could not read license statistics (" + state.fmtStr() + ")");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -472,7 +462,7 @@ std::deque<std::unique_ptr<LicenseManager::GlobalVersionsStatistic>> LicenseMana
|
|||||||
else if(names[index] == "version")
|
else if(names[index] == "version")
|
||||||
info->versions[values[index]] = 1;
|
info->versions[values[index]] = 1;
|
||||||
} catch (std::exception& ex) {
|
} catch (std::exception& ex) {
|
||||||
logError("Failed to parse column " + names[index] + " => " + ex.what() + " (Value: " + values[index] + ")");
|
logError(LOG_GENERAL, "Failed to parse column " + names[index] + " => " + ex.what() + " (Value: " + values[index] + ")");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -483,7 +473,7 @@ std::deque<std::unique_ptr<LicenseManager::GlobalVersionsStatistic>> LicenseMana
|
|||||||
});
|
});
|
||||||
|
|
||||||
if(!state) {
|
if(!state) {
|
||||||
logError("Could not read license statistics (" + state.fmtStr() + ")");
|
logError(LOG_GENERAL, "Could not read license statistics (" + state.fmtStr() + ")");
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
#include <netinet/in.h>
|
#include <netinet/in.h>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
#include <utility>
|
||||||
#include <arpa/inet.h>
|
#include <arpa/inet.h>
|
||||||
#include <log/LogUtils.h>
|
#include <log/LogUtils.h>
|
||||||
#include <misc/endianness.h>
|
#include <misc/endianness.h>
|
||||||
@ -9,6 +10,7 @@
|
|||||||
#include <shared/License.h>
|
#include <shared/License.h>
|
||||||
#include <shared/crypt.h>
|
#include <shared/crypt.h>
|
||||||
#include <misc/base64.h>
|
#include <misc/base64.h>
|
||||||
|
#include <ThreadPool/ThreadHelper.h>
|
||||||
#include "LicenseServer.h"
|
#include "LicenseServer.h"
|
||||||
#include "crypt.h"
|
#include "crypt.h"
|
||||||
#include "UserManager.h"
|
#include "UserManager.h"
|
||||||
@ -19,98 +21,100 @@ using namespace license;
|
|||||||
using namespace ts;
|
using namespace ts;
|
||||||
|
|
||||||
LicenseServer::LicenseServer(const sockaddr_in& addr,
|
LicenseServer::LicenseServer(const sockaddr_in& addr,
|
||||||
const std::shared_ptr<server::LicenseManager>& manager,
|
std::shared_ptr<server::LicenseManager> manager,
|
||||||
const shared_ptr<license::stats::StatisticManager> &stats,
|
shared_ptr<license::stats::StatisticManager> stats,
|
||||||
const shared_ptr<license::web::WebStatistics> &wstats,
|
shared_ptr<license::web::WebStatistics> wstats,
|
||||||
const std::shared_ptr<UserManager>& user_manager) : manager(manager), statistics(stats), web_statistics(wstats), user_manager(user_manager) {
|
std::shared_ptr<UserManager> user_manager) : manager{std::move(manager)}, statistics{std::move(stats)}, web_statistics{std::move(wstats)}, user_manager{std::move(user_manager)} {
|
||||||
this->localAddr = new sockaddr_in{};
|
memcpy(&this->localAddr, &addr, sizeof(addr));
|
||||||
memcpy(this->localAddr, &addr, sizeof(addr));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
LicenseServer::~LicenseServer() {
|
LicenseServer::~LicenseServer() {
|
||||||
this->stopServer();
|
this->stop();
|
||||||
delete this->localAddr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#define SFAIL(message) \
|
#define SFAIL(message) \
|
||||||
do { \
|
do { \
|
||||||
logError(lstream << (message) << " Message: " << errno << "/" << strerror(errno)); \
|
logError(LOG_GENERAL, " Message: {} ({}/{})", message, errno, strerror(errno)); \
|
||||||
this->stopServer(); \
|
this->stop(); \
|
||||||
return false; \
|
return false; \
|
||||||
} while(0)
|
} while(0)
|
||||||
|
|
||||||
static int enabled = 1;
|
static int enabled = 1;
|
||||||
static int disabled = 0;
|
static int disabled = 0;
|
||||||
bool LicenseServer::startServer() {
|
bool LicenseServer::start() {
|
||||||
{
|
{
|
||||||
lock_guard lock(this->lock);
|
lock_guard lock(this->client_lock);
|
||||||
if(this->running) return false;
|
if(this->running) return false;
|
||||||
this->running = true;
|
this->running = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
fileDescriptor = socket(AF_INET, SOCK_STREAM, 0);
|
server_socket = socket(AF_INET, SOCK_STREAM, 0);
|
||||||
if (fileDescriptor < 0) SFAIL("Could not create new socket");
|
if (server_socket < 0) SFAIL("Could not create new socket");
|
||||||
|
|
||||||
if(setsockopt(this->fileDescriptor, SOL_SOCKET, SO_REUSEADDR, &enabled, sizeof(enabled)) < 0) SFAIL("could not set reuse address");
|
if(setsockopt(this->server_socket, SOL_SOCKET, SO_REUSEADDR, &enabled, sizeof(enabled)) < 0) SFAIL("could not set reuse address");
|
||||||
if(setsockopt(this->fileDescriptor, IPPROTO_TCP, TCP_CORK, &disabled, sizeof(disabled)) < 0) SFAIL("could not set no push");
|
if(setsockopt(this->server_socket, IPPROTO_TCP, TCP_CORK, &disabled, sizeof(disabled)) < 0) SFAIL("could not set no push");
|
||||||
if(bind(this->fileDescriptor, (struct sockaddr *) this->localAddr, sizeof(sockaddr_in)) < 0) SFAIL("Could not bind socket on " + string(inet_ntoa(this->localAddr->sin_addr)));
|
if(bind(this->server_socket, (struct sockaddr *) &this->localAddr, sizeof(sockaddr_in)) < 0) SFAIL("Could not bind socket on " + string(inet_ntoa(this->localAddr.sin_addr)));
|
||||||
|
|
||||||
if(listen(this->fileDescriptor, 32) < 0) SFAIL("Could not listen on socket");
|
if(listen(this->server_socket, 32) < 0) SFAIL("Could not listen on socket");
|
||||||
|
|
||||||
this->evBase = event_base_new();
|
this->evBase = event_base_new();
|
||||||
this->acceptEvent = event_new(this->evBase, this->fileDescriptor, EV_READ | EV_PERSIST, LicenseServer::handleEventAccept, this);
|
this->event_accept = event_new(this->evBase, this->server_socket, EV_READ | EV_PERSIST, LicenseServer::handleEventAccept, this);
|
||||||
this->client_cleanup = evtimer_new(this->evBase, LicenseServer::handleEventCleanup, this);
|
this->event_cleanup = evtimer_new(this->evBase, LicenseServer::handleEventCleanup, this);
|
||||||
|
|
||||||
event_add(this->acceptEvent, nullptr);
|
event_add(this->event_accept, nullptr);
|
||||||
{
|
{
|
||||||
timeval now{1, 0};
|
timeval now{1, 0};
|
||||||
evtimer_add(this->client_cleanup, &now);
|
evtimer_add(this->event_cleanup, &now);
|
||||||
}
|
}
|
||||||
evBaseDispatch = new threads::Thread(THREAD_SAVE_OPERATIONS, [&](){
|
|
||||||
|
event_base_dispatch = std::thread([&]{
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
event_base_dispatch(this->evBase);
|
::event_base_dispatch(this->evBase);
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void LicenseServer::stopServer() {
|
void LicenseServer::stop() {
|
||||||
{
|
{
|
||||||
lock_guard lock(this->lock);
|
lock_guard lock(this->client_lock);
|
||||||
if(!this->running) return;
|
if(!this->running) return;
|
||||||
this->running = false;
|
this->running = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* first unregister the accept event so we don't get new clients */
|
||||||
|
if(this->event_accept) {
|
||||||
|
event_del(this->event_accept);
|
||||||
|
event_free(this->event_accept);
|
||||||
|
}
|
||||||
|
this->event_accept = nullptr;
|
||||||
|
|
||||||
|
/* disconnect all clients */
|
||||||
for(const auto& client : this->getClients())
|
for(const auto& client : this->getClients())
|
||||||
this->closeConnection(client);
|
this->closeConnection(client);
|
||||||
|
|
||||||
if(this->acceptEvent) {
|
|
||||||
event_del(this->acceptEvent);
|
|
||||||
event_free(this->acceptEvent);
|
|
||||||
}
|
|
||||||
this->acceptEvent = nullptr;
|
|
||||||
|
|
||||||
if(this->client_cleanup) {
|
|
||||||
event_del_block(this->client_cleanup);
|
|
||||||
event_free(this->client_cleanup);
|
|
||||||
this->client_cleanup = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(this->evBase)
|
if(this->evBase)
|
||||||
event_base_loopbreak(this->evBase);
|
event_base_loopbreak(this->evBase);
|
||||||
|
|
||||||
if(this->evBaseDispatch)
|
if(!threads::timed_join(this->event_base_dispatch, std::chrono::seconds{2})) {
|
||||||
this->evBaseDispatch->join();
|
this->event_base_dispatch.detach();
|
||||||
delete this->evBaseDispatch;
|
logCritical(LOG_GENERAL, "Failed to join event base dispatch thread. This will cause memory leaks.");
|
||||||
this->evBaseDispatch = nullptr;
|
|
||||||
if(this->evBase) {
|
|
||||||
event_base_loopbreak(this->evBase); /* again for some reason */
|
|
||||||
event_base_free(this->evBase);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Needs to be cleaned up after event loop has been destroyed. Because its used within the event loop. */
|
||||||
|
if(this->event_cleanup) {
|
||||||
|
event_del_block(this->event_cleanup);
|
||||||
|
event_free(this->event_cleanup);
|
||||||
|
this->event_cleanup = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(this->evBase)
|
||||||
|
event_base_free(this->evBase);
|
||||||
this->evBase = nullptr;
|
this->evBase = nullptr;
|
||||||
|
|
||||||
if(this->fileDescriptor != 0) {
|
if(this->server_socket != 0) {
|
||||||
shutdown(this->fileDescriptor, SHUT_RDWR);
|
shutdown(this->server_socket, SHUT_RDWR);
|
||||||
close(this->fileDescriptor);
|
close(this->server_socket);
|
||||||
this->fileDescriptor = 0;
|
this->server_socket = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,8 +124,8 @@ void LicenseServer::handleEventCleanup(int, short, void* ptrServer) {
|
|||||||
server->cleanup_clients();
|
server->cleanup_clients();
|
||||||
timeval next{1, 0};
|
timeval next{1, 0};
|
||||||
|
|
||||||
if(server->client_cleanup)
|
if(server->event_cleanup)
|
||||||
event_add(server->client_cleanup, &next);
|
event_add(server->event_cleanup, &next);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Basic IO
|
//Basic IO
|
||||||
@ -129,26 +133,27 @@ void LicenseServer::handleEventWrite(int fd, short, void* ptrServer) {
|
|||||||
auto server = static_cast<LicenseServer *>(ptrServer);
|
auto server = static_cast<LicenseServer *>(ptrServer);
|
||||||
auto client = server->findClient(fd);
|
auto client = server->findClient(fd);
|
||||||
if(!client) return;
|
if(!client) return;
|
||||||
buffer::RawBuffer* buffer = nullptr;
|
|
||||||
{
|
|
||||||
threads::MutexLock lock(client->network.lock);
|
|
||||||
buffer = TAILQ_FIRST(&client->network.writeQueue);
|
|
||||||
if(!buffer) return;
|
|
||||||
|
|
||||||
auto writtenBytes = send(fd, &buffer->buffer[buffer->index], buffer->length - buffer->index, 0);
|
buffer::RawBuffer* write_buffer{nullptr};
|
||||||
|
while(true) { //TODO: May add some kind of timeout?
|
||||||
|
std::lock_guard lock(client->network.write_queue_lock);
|
||||||
|
write_buffer = TAILQ_FIRST(&client->network.write_queue);
|
||||||
|
if(!write_buffer) return;
|
||||||
|
|
||||||
|
auto writtenBytes = send(fd, &write_buffer->buffer[write_buffer->index], write_buffer->length - write_buffer->index, 0);
|
||||||
if(writtenBytes <= 0) {
|
if(writtenBytes <= 0) {
|
||||||
if(writtenBytes == -1 && errno == EAGAIN)
|
if(writtenBytes == -1 && errno == EAGAIN)
|
||||||
return;
|
return;
|
||||||
logError(LOG_LICENSE_CONTROLL, "Invalid write. Disconnecting remote client. Message: {}/{}", errno, strerror(errno));
|
logError(LOG_LICENSE_CONTROLL, "Invalid write. Disconnecting remote client. Message: {}/{}", errno, strerror(errno));
|
||||||
} else {
|
} else {
|
||||||
buffer->index += writtenBytes;
|
write_buffer->index += writtenBytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(buffer->index >= buffer->length) {
|
if(write_buffer->index >= write_buffer->length) {
|
||||||
TAILQ_REMOVE(&client->network.writeQueue, buffer, tail);
|
TAILQ_REMOVE(&client->network.write_queue, write_buffer, tail);
|
||||||
delete buffer;
|
delete write_buffer;
|
||||||
}
|
}
|
||||||
if(!TAILQ_EMPTY(&client->network.writeQueue))
|
if(!TAILQ_EMPTY(&client->network.write_queue))
|
||||||
event_add(client->network.writeEvent, nullptr);
|
event_add(client->network.writeEvent, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -164,23 +169,31 @@ void ConnectedClient::sendPacket(const protocol::packet& packet) {
|
|||||||
xorBuffer(&buffer->buffer[sizeof(packet.header)], packet.data.length(), this->protocol.cryptKey.data(), this->protocol.cryptKey.length());
|
xorBuffer(&buffer->buffer[sizeof(packet.header)], packet.data.length(), this->protocol.cryptKey.data(), this->protocol.cryptKey.length());
|
||||||
|
|
||||||
{
|
{
|
||||||
threads::MutexLock lock(this->network.lock);
|
lock_guard queue_lock{this->network.write_queue_lock};
|
||||||
TAILQ_INSERT_TAIL(&this->network.writeQueue, buffer, tail);
|
TAILQ_INSERT_TAIL(&this->network.write_queue, buffer, tail);
|
||||||
}
|
}
|
||||||
|
{
|
||||||
|
lock_guard state_lock{this->protocol.state_lock};
|
||||||
|
if(this->protocol.state == protocol::UNCONNECTED) goto error_cleanup;
|
||||||
|
|
||||||
event_add(this->network.writeEvent, nullptr);
|
event_add(this->network.writeEvent, nullptr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
error_cleanup:
|
||||||
|
delete buffer;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectedClient::init() {
|
void ConnectedClient::init() {
|
||||||
protocol.last_read = std::chrono::system_clock::now();
|
protocol.last_read = std::chrono::system_clock::now();
|
||||||
TAILQ_INIT(&network.writeQueue);
|
TAILQ_INIT(&network.write_queue);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConnectedClient::uninit() {
|
void ConnectedClient::uninit() {
|
||||||
{
|
{
|
||||||
threads::MutexLock lock(this->network.lock);
|
lock_guard queue_lock{this->network.write_queue_lock};
|
||||||
ts::buffer::RawBuffer* buffer;
|
ts::buffer::RawBuffer* buffer;
|
||||||
while ((buffer = TAILQ_FIRST(&this->network.writeQueue))) {
|
while ((buffer = TAILQ_FIRST(&this->network.write_queue))) {
|
||||||
TAILQ_REMOVE(&this->network.writeQueue, buffer, tail);
|
TAILQ_REMOVE(&this->network.write_queue, buffer, tail);
|
||||||
delete buffer;
|
delete buffer;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -236,21 +249,21 @@ void LicenseServer::handleEventAccept(int fd, short, void* ptrServer) {
|
|||||||
if(setsockopt(client->network.fileDescriptor, IPPROTO_TCP, TCP_CORK, &disabled, sizeof(disabled)) < 0);// CERR("could not set no push");
|
if(setsockopt(client->network.fileDescriptor, IPPROTO_TCP, TCP_CORK, &disabled, sizeof(disabled)) < 0);// CERR("could not set no push");
|
||||||
|
|
||||||
if (client->network.fileDescriptor < 0) {
|
if (client->network.fileDescriptor < 0) {
|
||||||
logCritical("Could not accept new client! (" + to_string(client->network.fileDescriptor) + "|" + to_string(errno) + "|" + strerror(errno) + ")");
|
logCritical(LOG_GENERAL, "Could not accept new client! (" + to_string(client->network.fileDescriptor) + "|" + to_string(errno) + "|" + strerror(errno) + ")");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
client->protocol.state = protocol::HANDSCAKE;
|
client->protocol.state = protocol::HANDSCAKE;
|
||||||
{
|
{
|
||||||
lock_guard lock(server->lock);
|
lock_guard lock(server->client_lock);
|
||||||
server->currentClients.push_back(client);
|
server->clients.push_back(client);
|
||||||
}
|
}
|
||||||
|
|
||||||
client->network.readEvent = event_new(server->evBase, client->network.fileDescriptor, EV_READ | EV_PERSIST, LicenseServer::handleEventRead, server);
|
client->network.readEvent = event_new(server->evBase, client->network.fileDescriptor, EV_READ | EV_PERSIST, LicenseServer::handleEventRead, server);
|
||||||
client->network.writeEvent = event_new(server->evBase, client->network.fileDescriptor, EV_WRITE, LicenseServer::handleEventWrite, server);
|
client->network.writeEvent = event_new(server->evBase, client->network.fileDescriptor, EV_WRITE, LicenseServer::handleEventWrite, server);
|
||||||
event_add(client->network.readEvent, nullptr);
|
event_add(client->network.readEvent, nullptr);
|
||||||
|
|
||||||
logMessage(lstream << "Got new client from " << inet_ntoa(client->network.remoteAddr.sin_addr));
|
logMessage(LOG_GENERAL, "Accepted new client from {}", inet_ntoa(client->network.remoteAddr.sin_addr));
|
||||||
}
|
}
|
||||||
|
|
||||||
void LicenseServer::disconnectClient(const std::shared_ptr<ConnectedClient>& client, const std::string &reason) {
|
void LicenseServer::disconnectClient(const std::shared_ptr<ConnectedClient>& client, const std::string &reason) {
|
||||||
@ -258,15 +271,15 @@ void LicenseServer::disconnectClient(const std::shared_ptr<ConnectedClient>& cli
|
|||||||
}
|
}
|
||||||
|
|
||||||
void LicenseServer::closeConnection(const std::shared_ptr<ConnectedClient> &client, bool blocking) {
|
void LicenseServer::closeConnection(const std::shared_ptr<ConnectedClient> &client, bool blocking) {
|
||||||
if(this->evBaseDispatch && threads::self::id() == *this->evBaseDispatch) {
|
if(this_thread::get_id() == this->event_base_dispatch.get_id()) {
|
||||||
std::thread(std::bind(&LicenseServer::closeConnection, this, client, true)).detach();
|
std::thread(std::bind(&LicenseServer::closeConnection, this, client, true)).detach();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
|
||||||
unique_lock lock(client->network.lock);
|
unique_lock lock(client->network.write_queue_lock);
|
||||||
if(!TAILQ_EMPTY(&client->network.writeQueue)) {
|
if(!TAILQ_EMPTY(&client->network.write_queue)) {
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
if(!blocking) {
|
if(!blocking) {
|
||||||
@ -277,7 +290,7 @@ void LicenseServer::closeConnection(const std::shared_ptr<ConnectedClient> &clie
|
|||||||
while(system_clock::now() - start < seconds(5)){
|
while(system_clock::now() - start < seconds(5)){
|
||||||
{
|
{
|
||||||
lock.lock();
|
lock.lock();
|
||||||
if(TAILQ_EMPTY(&client->network.writeQueue)) break;
|
if(TAILQ_EMPTY(&client->network.write_queue)) break;
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
}
|
}
|
||||||
threads::self::sleep_for(milliseconds(5));
|
threads::self::sleep_for(milliseconds(5));
|
||||||
@ -289,49 +302,57 @@ void LicenseServer::closeConnection(const std::shared_ptr<ConnectedClient> &clie
|
|||||||
|
|
||||||
void LicenseServer::unregisterClient(const std::shared_ptr<ConnectedClient> &client) {
|
void LicenseServer::unregisterClient(const std::shared_ptr<ConnectedClient> &client) {
|
||||||
{
|
{
|
||||||
lock_guard lock(this->lock);
|
lock_guard lock(this->client_lock);
|
||||||
|
|
||||||
auto it = find(this->currentClients.begin(), this->currentClients.end(), client);
|
auto it = find(this->clients.begin(), this->clients.end(), client);
|
||||||
if(it != this->currentClients.end())
|
if(it != this->clients.end())
|
||||||
this->currentClients.erase(it);
|
this->clients.erase(it);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard state_lock{client->protocol.state_lock};
|
||||||
client->protocol.state = protocol::UNCONNECTED;
|
client->protocol.state = protocol::UNCONNECTED;
|
||||||
|
}
|
||||||
client->uninit();
|
client->uninit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void LicenseServer::cleanup_clients() {
|
void LicenseServer::cleanup_clients() {
|
||||||
unique_lock lock(this->lock);
|
unique_lock lock(this->client_lock);
|
||||||
auto clients = this->currentClients;
|
auto clients = this->clients;
|
||||||
lock.unlock();
|
lock.unlock();
|
||||||
|
|
||||||
|
size_t cleanup_count{0};
|
||||||
for(const auto& client : clients) {
|
for(const auto& client : clients) {
|
||||||
if(client->protocol.last_read + minutes(1) < system_clock::now()) {
|
if(client->protocol.last_read + minutes(1) < system_clock::now()) {
|
||||||
|
cleanup_count++;
|
||||||
if(client->protocol.state != protocol::DISCONNECTING && client->protocol.state != protocol::UNCONNECTED) {
|
if(client->protocol.state != protocol::DISCONNECTING && client->protocol.state != protocol::UNCONNECTED) {
|
||||||
this->disconnectClient(client, "timeout");
|
this->disconnectClient(client, "timeout");
|
||||||
this->closeConnection(client);
|
this->closeConnection(client);
|
||||||
client->protocol.state = protocol::DISCONNECTING;
|
|
||||||
|
std::lock_guard state_lock{client->protocol.state_lock};
|
||||||
|
client->protocol.state = protocol::UNCONNECTED;
|
||||||
} else {
|
} else {
|
||||||
auto it = find(this->currentClients.begin(), this->currentClients.end(), client);
|
auto it = find(this->clients.begin(), this->clients.end(), client);
|
||||||
if(it != this->currentClients.end())
|
if(it != this->clients.end())
|
||||||
this->currentClients.erase(it);
|
this->clients.erase(it);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
debugMessage("Client's cleaned up");
|
if(cleanup_count)
|
||||||
|
debugMessage(LOG_GENERAL, "{} clients have been cleaned up due to a read timeout.", cleanup_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<ConnectedClient> LicenseServer::findClient(int fileDescriptor) {
|
std::shared_ptr<ConnectedClient> LicenseServer::findClient(int fd) {
|
||||||
lock_guard lock(this->lock);
|
lock_guard lock(this->client_lock);
|
||||||
for(const auto& cl : this->currentClients)
|
for(const auto& cl : this->clients)
|
||||||
if(cl->network.fileDescriptor == fileDescriptor)
|
if(cl->network.fileDescriptor == fd)
|
||||||
return cl;
|
return cl;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ERR(message) \
|
#define ERR(message) \
|
||||||
do { \
|
do { \
|
||||||
logError(lstream << message); \
|
logError(LOG_GENERAL, message); \
|
||||||
this->closeConnection(client); \
|
this->closeConnection(client); \
|
||||||
return; \
|
return; \
|
||||||
} while(0)
|
} while(0)
|
||||||
@ -374,7 +395,7 @@ void LicenseServer::handleMessage(shared_ptr<ConnectedClient>& client, const std
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(!success) {
|
if(!success) {
|
||||||
logError("[CLIENT][" + client->address() + "] Failed to handle packet. message: " + error);
|
logError(LOG_GENERAL, "[CLIENT][" + client->address() + "] Failed to handle packet. message: " + error);
|
||||||
this->disconnectClient(client, error);
|
this->disconnectClient(client, error);
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -31,15 +31,17 @@ namespace license {
|
|||||||
struct {
|
struct {
|
||||||
sockaddr_in remoteAddr;
|
sockaddr_in remoteAddr;
|
||||||
int fileDescriptor = 0;
|
int fileDescriptor = 0;
|
||||||
event* readEvent = nullptr;
|
event* readEvent = nullptr; /* protected via state_lock (check state and the use these variables) */
|
||||||
event* writeEvent = nullptr;
|
event* writeEvent = nullptr;
|
||||||
|
|
||||||
threads::Mutex lock;
|
std::mutex write_queue_lock{};
|
||||||
TAILQ_HEAD(, ts::buffer::RawBuffer) writeQueue;
|
TAILQ_HEAD(, ts::buffer::RawBuffer) write_queue;
|
||||||
} network;
|
} network;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
|
std::mutex state_lock{};
|
||||||
protocol::RequestState state = protocol::UNCONNECTED;
|
protocol::RequestState state = protocol::UNCONNECTED;
|
||||||
|
|
||||||
std::chrono::system_clock::time_point last_read;
|
std::chrono::system_clock::time_point last_read;
|
||||||
std::string cryptKey = "";
|
std::string cryptKey = "";
|
||||||
} protocol;
|
} protocol;
|
||||||
@ -66,20 +68,20 @@ namespace license {
|
|||||||
|
|
||||||
class LicenseServer {
|
class LicenseServer {
|
||||||
public:
|
public:
|
||||||
explicit LicenseServer(const sockaddr_in&, const std::shared_ptr<server::LicenseManager>&, const std::shared_ptr<stats::StatisticManager>& /* stats */, const std::shared_ptr<web::WebStatistics>& /* web stats */, const std::shared_ptr<UserManager>& /* user manager */);
|
explicit LicenseServer(const sockaddr_in&, std::shared_ptr<server::LicenseManager> , std::shared_ptr<stats::StatisticManager> /* stats */, std::shared_ptr<web::WebStatistics> /* web stats */, std::shared_ptr<UserManager> /* user manager */);
|
||||||
~LicenseServer();
|
~LicenseServer();
|
||||||
|
|
||||||
bool startServer();
|
bool start();
|
||||||
bool isRunning(){ return this->running; }
|
bool isRunning(){ return this->running; }
|
||||||
void stopServer();
|
void stop();
|
||||||
|
|
||||||
std::shared_ptr<ConnectedClient> findClient(int fileDescriptor);
|
std::shared_ptr<ConnectedClient> findClient(int fileDescriptor);
|
||||||
void disconnectClient(const std::shared_ptr<ConnectedClient>&, const std::string& reason);
|
void disconnectClient(const std::shared_ptr<ConnectedClient>&, const std::string& reason);
|
||||||
void closeConnection(const std::shared_ptr<ConnectedClient>&, bool blocking = false);
|
void closeConnection(const std::shared_ptr<ConnectedClient>&, bool blocking = false);
|
||||||
|
|
||||||
std::deque<std::shared_ptr<ConnectedClient>> getClients() {
|
std::deque<std::shared_ptr<ConnectedClient>> getClients() {
|
||||||
std::lock_guard lock(this->lock);
|
std::lock_guard lock(this->client_lock);
|
||||||
return currentClients;
|
return clients;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<WebCertificate> web_certificate{nullptr};
|
std::shared_ptr<WebCertificate> web_certificate{nullptr};
|
||||||
@ -92,18 +94,18 @@ namespace license {
|
|||||||
std::shared_ptr<server::LicenseManager> manager;
|
std::shared_ptr<server::LicenseManager> manager;
|
||||||
std::shared_ptr<UserManager> user_manager;
|
std::shared_ptr<UserManager> user_manager;
|
||||||
|
|
||||||
bool running = false;
|
std::mutex client_lock;
|
||||||
|
std::deque<std::shared_ptr<ConnectedClient>> clients;
|
||||||
|
|
||||||
std::mutex lock;
|
bool running = false; /* also secured by client_lock */
|
||||||
std::deque<std::shared_ptr<ConnectedClient>> currentClients;
|
|
||||||
|
|
||||||
sockaddr_in* localAddr = nullptr;
|
sockaddr_in localAddr{};
|
||||||
int fileDescriptor = 0;
|
int server_socket = 0;
|
||||||
event_base* evBase = nullptr;
|
event_base* evBase = nullptr;
|
||||||
event* acceptEvent = nullptr;
|
event* event_accept = nullptr;
|
||||||
event* client_cleanup = nullptr;
|
event* event_cleanup = nullptr;
|
||||||
|
|
||||||
threads::Thread* evBaseDispatch = nullptr;
|
std::thread event_base_dispatch{};
|
||||||
|
|
||||||
static void handleEventCleanup(int, short, void*);
|
static void handleEventCleanup(int, short, void*);
|
||||||
static void handleEventAccept(int, short, void*);
|
static void handleEventAccept(int, short, void*);
|
||||||
|
@ -89,7 +89,7 @@ bool LicenseServer::handleHandshake(shared_ptr<ConnectedClient>& client, protoco
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool LicenseServer::handleDisconnect(shared_ptr<ConnectedClient>& client, protocol::packet& packet, std::string &error) {
|
bool LicenseServer::handleDisconnect(shared_ptr<ConnectedClient>& client, protocol::packet& packet, std::string &error) {
|
||||||
logMessage("[CLIENT][" + client->address() + "] Remote disconnect. Reason: " + packet.data);
|
logMessage(LOG_GENERAL, "[CLIENT][" + client->address() + "] Remote disconnect. Reason: " + packet.data);
|
||||||
this->closeConnection(client);
|
this->closeConnection(client);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -236,24 +236,24 @@ bool LicenseServer::handlePacketPropertyUpdate(shared_ptr<ConnectedClient> &clie
|
|||||||
}
|
}
|
||||||
PARSE_PROTO(PropertyUpdateRequest, pkt);
|
PARSE_PROTO(PropertyUpdateRequest, pkt);
|
||||||
|
|
||||||
logMessage("[CLIENT][" + client->address() + "] Got server statistics:");
|
logMessage(LOG_GENERAL, "[CLIENT][" + client->address() + "] Got server statistics:");
|
||||||
logMessage("[CLIENT][" + client->address() + "] Spoken total : " + to_string(pkt.speach_total()));
|
logMessage(LOG_GENERAL, "[CLIENT][" + client->address() + "] Spoken total : " + to_string(pkt.speach_total()));
|
||||||
logMessage("[CLIENT][" + client->address() + "] Spoken dead : " + to_string(pkt.speach_dead()));
|
logMessage(LOG_GENERAL, "[CLIENT][" + client->address() + "] Spoken dead : " + to_string(pkt.speach_dead()));
|
||||||
logMessage("[CLIENT][" + client->address() + "] Spoken online : " + to_string(pkt.speach_online()));
|
logMessage(LOG_GENERAL, "[CLIENT][" + client->address() + "] Spoken online : " + to_string(pkt.speach_online()));
|
||||||
logMessage("[CLIENT][" + client->address() + "] Spoken varianz : " + to_string(pkt.speach_varianz()));
|
logMessage(LOG_GENERAL, "[CLIENT][" + client->address() + "] Spoken varianz : " + to_string(pkt.speach_varianz()));
|
||||||
logMessage("[CLIENT][" + client->address() + "] -------------------------------");
|
logMessage(LOG_GENERAL, "[CLIENT][" + client->address() + "] -------------------------------");
|
||||||
logMessage("[CLIENT][" + client->address() + "] Users online : " + to_string(pkt.clients_online()));
|
logMessage(LOG_GENERAL, "[CLIENT][" + client->address() + "] Users online : " + to_string(pkt.clients_online()));
|
||||||
logMessage("[CLIENT][" + client->address() + "] Web Users online : " + to_string(pkt.web_clients_online()));
|
logMessage(LOG_GENERAL, "[CLIENT][" + client->address() + "] Web Users online : " + to_string(pkt.web_clients_online()));
|
||||||
logMessage("[CLIENT][" + client->address() + "] Queries online : " + to_string(pkt.queries_online()));
|
logMessage(LOG_GENERAL, "[CLIENT][" + client->address() + "] Queries online : " + to_string(pkt.queries_online()));
|
||||||
logMessage("[CLIENT][" + client->address() + "] Bots online : " + to_string(pkt.bots_online()));
|
logMessage(LOG_GENERAL, "[CLIENT][" + client->address() + "] Bots online : " + to_string(pkt.bots_online()));
|
||||||
logMessage("[CLIENT][" + client->address() + "] Servers : " + to_string(pkt.servers_online()));
|
logMessage(LOG_GENERAL, "[CLIENT][" + client->address() + "] Servers : " + to_string(pkt.servers_online()));
|
||||||
this->manager->logStatistic(client->key, client->unique_identifier, client->address(), pkt);
|
this->manager->logStatistic(client->key, client->unique_identifier, client->address(), pkt);
|
||||||
//TODO test stuff if its possible!
|
//TODO test stuff if its possible!
|
||||||
|
|
||||||
ts::proto::license::WebCertificate* web_certificate{nullptr};
|
ts::proto::license::WebCertificate* web_certificate{nullptr};
|
||||||
if(pkt.has_web_cert_revision()) {
|
if(pkt.has_web_cert_revision()) {
|
||||||
logMessage("[CLIENT][" + client->address() + "] -------------------------------");
|
logMessage(LOG_GENERAL, "[CLIENT][" + client->address() + "] -------------------------------");
|
||||||
logMessage("[CLIENT][" + client->address() + "] Web cert revision : " + hex::hex(pkt.web_cert_revision()));
|
logMessage(LOG_GENERAL, "[CLIENT][" + client->address() + "] Web cert revision : " + hex::hex(pkt.web_cert_revision()));
|
||||||
|
|
||||||
auto cert = this->web_certificate;
|
auto cert = this->web_certificate;
|
||||||
if(cert && cert->revision != pkt.web_cert_revision()) {
|
if(cert && cert->revision != pkt.web_cert_revision()) {
|
||||||
@ -285,7 +285,7 @@ bool LicenseServer::handlePacketAuth(shared_ptr<ConnectedClient> &client, protoc
|
|||||||
TEST_PROTOCOL_STATE(MANAGER_AUTHORIZATION);
|
TEST_PROTOCOL_STATE(MANAGER_AUTHORIZATION);
|
||||||
PARSE_PROTO(AuthorizationRequest, pkt);
|
PARSE_PROTO(AuthorizationRequest, pkt);
|
||||||
|
|
||||||
logMessage("[MANAGER][" + client->address() + "] Got login. User: " + pkt.username() + " Password: " + pkt.password());
|
logMessage(LOG_GENERAL, "[MANAGER][" + client->address() + "] Got login. User: " + pkt.username() + " Password: " + pkt.password());
|
||||||
|
|
||||||
ts::proto::license::AuthorizationResponse response;
|
ts::proto::license::AuthorizationResponse response;
|
||||||
response.set_success(false);
|
response.set_success(false);
|
||||||
@ -316,11 +316,11 @@ bool LicenseServer::handlePacketAuth(shared_ptr<ConnectedClient> &client, protoc
|
|||||||
response.set_message("username or password mismatch");
|
response.set_message("username or password mismatch");
|
||||||
|
|
||||||
if(response.success()) {
|
if(response.success()) {
|
||||||
logMessage("[MANAGER][" + client->address() + "] Got succeeded user login. User: " + pkt.username() + " Password: " + pkt.password());
|
logMessage(LOG_GENERAL, "[MANAGER][" + client->address() + "] Got succeeded user login. User: " + pkt.username() + " Password: " + pkt.password());
|
||||||
client->username = pkt.username();
|
client->username = pkt.username();
|
||||||
client->protocol.state = protocol::MANAGER_CONNECTED;
|
client->protocol.state = protocol::MANAGER_CONNECTED;
|
||||||
} else
|
} else
|
||||||
logMessage("[MANAGER][" + client->address() + "] Got failed user login. User: " + pkt.username() + " Password: " + pkt.password());
|
logMessage(LOG_GENERAL, "[MANAGER][" + client->address() + "] Got failed user login. User: " + pkt.username() + " Password: " + pkt.password());
|
||||||
|
|
||||||
client->sendPacket(protocol::packet{protocol::PACKET_SERVER_AUTH_RESPONSE, response});
|
client->sendPacket(protocol::packet{protocol::PACKET_SERVER_AUTH_RESPONSE, response});
|
||||||
return true;
|
return true;
|
||||||
|
@ -17,6 +17,19 @@ namespace license {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct HistoryStatistics {
|
struct HistoryStatistics {
|
||||||
|
enum HistoryPeriod {
|
||||||
|
DAY,
|
||||||
|
WEEK,
|
||||||
|
MONTH,
|
||||||
|
HALF_YEAR,
|
||||||
|
YEAR
|
||||||
|
};
|
||||||
|
enum HistoryOffset {
|
||||||
|
NOW,
|
||||||
|
ONE_BEFORE,
|
||||||
|
SEVEN_BEFORE,
|
||||||
|
TWELVE_BEFORE
|
||||||
|
};
|
||||||
enum HistoryType {
|
enum HistoryType {
|
||||||
LAST_DAY,
|
LAST_DAY,
|
||||||
DAY_YESTERDAY,
|
DAY_YESTERDAY,
|
||||||
|
@ -38,11 +38,10 @@ bool WebStatistics::start(std::string &error, uint16_t port, const std::shared_p
|
|||||||
this->ssl = ssl;
|
this->ssl = ssl;
|
||||||
|
|
||||||
{
|
{
|
||||||
this->socket.local_address = make_unique<sockaddr_in>();
|
memset(&this->socket.address, 0, sizeof(sockaddr_in));
|
||||||
memset(this->socket.local_address.get(), 0, sizeof(sockaddr_in));
|
this->socket.address.sin_family = AF_INET;
|
||||||
this->socket.local_address->sin_family = AF_INET;
|
this->socket.address.sin_addr.s_addr = INADDR_ANY;
|
||||||
this->socket.local_address->sin_addr.s_addr = INADDR_ANY;
|
this->socket.address.sin_port = htons(port);
|
||||||
this->socket.local_address->sin_port = htons(port);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
this->socket.file_descriptor = ::socket(AF_INET, SOCK_STREAM, 0);
|
this->socket.file_descriptor = ::socket(AF_INET, SOCK_STREAM, 0);
|
||||||
@ -50,7 +49,7 @@ bool WebStatistics::start(std::string &error, uint16_t port, const std::shared_p
|
|||||||
|
|
||||||
if(setsockopt(this->socket.file_descriptor, SOL_SOCKET, SO_REUSEADDR, &enabled, sizeof(enabled)) < 0) SFAIL("could not set reuse address");
|
if(setsockopt(this->socket.file_descriptor, SOL_SOCKET, SO_REUSEADDR, &enabled, sizeof(enabled)) < 0) SFAIL("could not set reuse address");
|
||||||
if(setsockopt(this->socket.file_descriptor, IPPROTO_TCP, TCP_CORK, &disabled, sizeof(disabled)) < 0) SFAIL("could not set no push");
|
if(setsockopt(this->socket.file_descriptor, IPPROTO_TCP, TCP_CORK, &disabled, sizeof(disabled)) < 0) SFAIL("could not set no push");
|
||||||
if(bind(this->socket.file_descriptor, (struct sockaddr *) this->socket.local_address.get(), sizeof(sockaddr_in)) < 0) SFAIL("Could not bind socket on " + string(inet_ntoa(this->socket.local_address->sin_addr)));
|
if(bind(this->socket.file_descriptor, (struct sockaddr *) &this->socket.address, sizeof(sockaddr_in)) < 0) SFAIL("Could not bind socket on " + string(inet_ntoa(this->socket.address.sin_addr)));
|
||||||
|
|
||||||
if(listen(this->socket.file_descriptor, 32) < 0) SFAIL("Could not listen on socket");
|
if(listen(this->socket.file_descriptor, 32) < 0) SFAIL("Could not listen on socket");
|
||||||
|
|
||||||
@ -162,13 +161,11 @@ void WebStatistics::initialize_client(const std::shared_ptr<license::web::WebSta
|
|||||||
|
|
||||||
auto lmethod = request.method;
|
auto lmethod = request.method;
|
||||||
transform(lmethod.begin(), lmethod.end(), lmethod.begin(), ::tolower);
|
transform(lmethod.begin(), lmethod.end(), lmethod.begin(), ::tolower);
|
||||||
if(lmethod == "get" && !request.parameters["type"].empty())
|
if(lmethod == "get" && request.parameters.count("type") && !request.parameters.at("type").empty())
|
||||||
this->handle_request(_client, request, response);
|
this->handle_request(_client, request, response);
|
||||||
};
|
};
|
||||||
|
|
||||||
client->pipe_websocket->initialize();
|
client->pipe_websocket->initialize();
|
||||||
|
|
||||||
//FIXME Setup ssl
|
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
@ -369,6 +366,15 @@ std::shared_ptr<WebStatistics::Client> WebStatistics::find_client_by_fd(int file
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool WebStatistics::send_message(const std::shared_ptr<Client> &client, const pipes::buffer_view &buffer) {
|
||||||
|
lock_guard<recursive_mutex> lock(client->execute_lock);
|
||||||
|
if(client->pipe_websocket) {
|
||||||
|
client->pipe_websocket->send({pipes::TEXT, buffer.own_buffer()});
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
#define HERR(message, ...) \
|
#define HERR(message, ...) \
|
||||||
do {\
|
do {\
|
||||||
logError(LOG_LICENSE_WEB, "[{}] " message, client->client_prefix(), ##__VA_ARGS__); \
|
logError(LOG_LICENSE_WEB, "[{}] " message, client->client_prefix(), ##__VA_ARGS__); \
|
||||||
@ -393,7 +399,7 @@ bool WebStatistics::handle_message(const std::shared_ptr<license::web::WebStatis
|
|||||||
_response = json_dump(response);
|
_response = json_dump(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
client->pipe_websocket->send({pipes::TEXT, _response});
|
this->send_message(client, _response);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -426,9 +432,9 @@ bool WebStatistics::handle_message(const std::shared_ptr<license::web::WebStatis
|
|||||||
response["statistics"]["clients"] = to_string(stats->clients);
|
response["statistics"]["clients"] = to_string(stats->clients);
|
||||||
response["statistics"]["music"] = to_string(stats->bots);
|
response["statistics"]["music"] = to_string(stats->bots);
|
||||||
|
|
||||||
client->pipe_websocket->send({pipes::TEXT, json_dump(response)});
|
this->send_message(client, json_dump(response));
|
||||||
return true;
|
return true;
|
||||||
} else if(message["request_type"].asString() == "history") {
|
} else if(message["request_type"].asString() == "history" ) {
|
||||||
auto type = message["history_type"].asInt();
|
auto type = message["history_type"].asInt();
|
||||||
if(type < 0 || type > stats::HistoryStatistics::LAST_HALF_YEAR)
|
if(type < 0 || type > stats::HistoryStatistics::LAST_HALF_YEAR)
|
||||||
__throw_range_error("invalid range!");
|
__throw_range_error("invalid range!");
|
||||||
@ -447,6 +453,7 @@ bool WebStatistics::handle_message(const std::shared_ptr<license::web::WebStatis
|
|||||||
this->update_flood(client, 80);
|
this->update_flood(client, 80);
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: Some kind of handle else this could crash the server on shutdown
|
||||||
std::thread([&, client, type, message]() {
|
std::thread([&, client, type, message]() {
|
||||||
auto history = this->statistics_manager->history((stats::HistoryStatistics::HistoryType) type);
|
auto history = this->statistics_manager->history((stats::HistoryStatistics::HistoryType) type);
|
||||||
|
|
||||||
@ -462,16 +469,63 @@ bool WebStatistics::handle_message(const std::shared_ptr<license::web::WebStatis
|
|||||||
|
|
||||||
int index;
|
int index;
|
||||||
auto stats = history->statistics;
|
auto stats = history->statistics;
|
||||||
|
auto& history_data = response["history"]["data"];
|
||||||
for(index = 0; index < stats->record_count; index++) {
|
for(index = 0; index < stats->record_count; index++) {
|
||||||
response["history"]["data"][index]["instances"] = stats->history[index].instance_online;
|
auto& indexed_data = history_data[index];
|
||||||
response["history"]["data"][index]["servers"] = stats->history[index].servers_online;
|
indexed_data["instances"] = stats->history[index].instance_online;
|
||||||
response["history"]["data"][index]["clients"] = stats->history[index].clients_online;
|
indexed_data["servers"] = stats->history[index].servers_online;
|
||||||
response["history"]["data"][index]["music"] = stats->history[index].bots_online;
|
indexed_data["clients"] = stats->history[index].clients_online;
|
||||||
|
indexed_data["music"] = stats->history[index].bots_online;
|
||||||
}
|
}
|
||||||
|
|
||||||
lock_guard lock(client->execute_lock);
|
this->send_message(client, json_dump(response));
|
||||||
if(client->pipe_websocket)
|
}).detach();
|
||||||
client->pipe_websocket->send({pipes::TEXT, json_dump(response)});
|
return true;
|
||||||
|
} else if(message["request_type"].asString() == "history_custom") {
|
||||||
|
auto begin = std::chrono::milliseconds{message["history_begin"].asInt64()};
|
||||||
|
auto end = std::chrono::milliseconds{message["history_end"].asInt64()};
|
||||||
|
auto interval = std::chrono::milliseconds{message["history_interval"].asInt64()};
|
||||||
|
auto code = message["code"].asString();
|
||||||
|
|
||||||
|
auto token = message["token"].asString();
|
||||||
|
if(token != "blubalutsch") {
|
||||||
|
Json::Value response;
|
||||||
|
response["type"] = "error";
|
||||||
|
response["code"] = code;
|
||||||
|
response["message"] = "invalid token";
|
||||||
|
this->send_message(client, json_dump(response));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Some kind of handle else this could crash the server on shutdown
|
||||||
|
std::thread([&, client, begin, end, interval, code]{
|
||||||
|
auto data = this->license_manager->list_statistics_user(
|
||||||
|
std::chrono::system_clock::time_point{} + begin,
|
||||||
|
std::chrono::system_clock::time_point{} + end,
|
||||||
|
interval
|
||||||
|
);
|
||||||
|
|
||||||
|
Json::Value response;
|
||||||
|
response["type"] = "response";
|
||||||
|
response["code"] = code;
|
||||||
|
|
||||||
|
response["history"]["timestamp"] = duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count();
|
||||||
|
response["history"]["begin"] = duration_cast<milliseconds>(begin).count();
|
||||||
|
response["history"]["end"] = duration_cast<milliseconds>(end).count();
|
||||||
|
response["history"]["interval"] = duration_cast<milliseconds>(interval).count();
|
||||||
|
|
||||||
|
|
||||||
|
int index;
|
||||||
|
auto& history_data = response["history"]["data"];
|
||||||
|
for(index = 0; index < data->record_count; index++) {
|
||||||
|
auto& indexed_data = history_data[index];
|
||||||
|
indexed_data["instances"] = data->history[index].instance_online;
|
||||||
|
indexed_data["servers"] = data->history[index].servers_online;
|
||||||
|
indexed_data["clients"] = data->history[index].clients_online;
|
||||||
|
indexed_data["music"] = data->history[index].bots_online;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->send_message(client, json_dump(response));
|
||||||
}).detach();
|
}).detach();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -482,8 +536,8 @@ bool WebStatistics::handle_message(const std::shared_ptr<license::web::WebStatis
|
|||||||
Json::Value response;
|
Json::Value response;
|
||||||
response["type"] = "error";
|
response["type"] = "error";
|
||||||
response["code"] = message["code"];
|
response["code"] = message["code"];
|
||||||
response["message"] = "could not assign action";
|
response["message"] = "could not execute action";
|
||||||
client->pipe_websocket->send({pipes::TEXT, json_dump(response)});
|
this->send_message(client, json_dump(response));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -492,7 +546,7 @@ bool WebStatistics::handle_message(const std::shared_ptr<license::web::WebStatis
|
|||||||
response["type"] = "error";
|
response["type"] = "error";
|
||||||
response["code"] = message["code"];
|
response["code"] = message["code"];
|
||||||
response["message"] = "could not assign action";
|
response["message"] = "could not assign action";
|
||||||
client->pipe_websocket->send({pipes::TEXT, json_dump(response)});
|
this->send_message(client, json_dump(response));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ namespace license {
|
|||||||
struct Client {
|
struct Client {
|
||||||
std::unique_ptr<sockaddr_in> peer_address;
|
std::unique_ptr<sockaddr_in> peer_address;
|
||||||
int file_descriptor = 0;
|
int file_descriptor = 0;
|
||||||
|
|
||||||
event* event_read = nullptr;
|
event* event_read = nullptr;
|
||||||
event* event_write = nullptr;
|
event* event_write = nullptr;
|
||||||
|
|
||||||
@ -63,6 +64,7 @@ namespace license {
|
|||||||
|
|
||||||
void close_connection(const std::shared_ptr<Client>& /* client */);
|
void close_connection(const std::shared_ptr<Client>& /* client */);
|
||||||
std::shared_ptr<Client> find_client_by_fd(int /* file descriptor */);
|
std::shared_ptr<Client> find_client_by_fd(int /* file descriptor */);
|
||||||
|
bool send_message(const std::shared_ptr<Client>& /* client */, const pipes::buffer_view& /* data */);
|
||||||
|
|
||||||
void broadcast_message(const Json::Value& /* message */);
|
void broadcast_message(const Json::Value& /* message */);
|
||||||
|
|
||||||
@ -77,10 +79,10 @@ namespace license {
|
|||||||
std::shared_ptr<stats::StatisticManager> statistics_manager;
|
std::shared_ptr<stats::StatisticManager> statistics_manager;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
std::unique_ptr<sockaddr_in> local_address;
|
sockaddr_in address{};
|
||||||
int file_descriptor = 0;
|
int file_descriptor{0};
|
||||||
event* event_accept = nullptr;
|
event* event_accept{nullptr};
|
||||||
event_base* event_base = nullptr;
|
struct event_base* event_base{nullptr};
|
||||||
std::unique_ptr<threads::Thread> event_base_dispatch;
|
std::unique_ptr<threads::Thread> event_base_dispatch;
|
||||||
} socket;
|
} socket;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user