From 69132ea752eb1b222f7db1b2464fedfbaac31616 Mon Sep 17 00:00:00 2001 From: Sami Littow Date: Mon, 13 Mar 2023 13:38:43 +0200 Subject: Change in client storage - Client storage vector changed to std::unordered_map, key is the socket ID - Socket ID is now the client ID - Some changes/fixes in socket handling Change-Id: I57596ab286685d1a46ea932a95125299b7a64624 Reviewed-by: Arttu Tarkiainen --- src/libs/qlicenseservice/clienthandler.cpp | 30 ++++---- .../qlicenseservice/daemon_clients/clienthandler.h | 5 +- .../qlicenseservice/daemon_clients/squishhandler.h | 7 +- src/libs/qlicenseservice/licenser.cpp | 88 +++++++++++----------- src/libs/qlicenseservice/licenser.h | 4 +- 5 files changed, 72 insertions(+), 62 deletions(-) diff --git a/src/libs/qlicenseservice/clienthandler.cpp b/src/libs/qlicenseservice/clienthandler.cpp index c13c2a0..8ecb6c5 100644 --- a/src/libs/qlicenseservice/clienthandler.cpp +++ b/src/libs/qlicenseservice/clienthandler.cpp @@ -92,6 +92,9 @@ int ClientHandler::parseRequest() bool argFound = false; std::string arg; for (const std::string &item : params) { + if (item.empty()) { + continue; + } if (!argFound) { if (item[0] == '-') { arg = item; @@ -102,7 +105,7 @@ int ClientHandler::parseRequest() std::cout << "Not a valid argument: \"" << item << "\"\n"; return e_bad_request; } - } else if (item[0] != '-' && !item.empty()) { + } else { if (arg == "-a") m_request.appName = utils::strToLower(item); else if (arg == "-v") m_request.appVersion = item; else if (arg == "-u") m_request.userId = item; @@ -117,7 +120,7 @@ int ClientHandler::parseRequest() } argFound = false; arg = ""; - } else break; + } } // Check if we're run out of items in argument list without getting the value: if (argFound) { @@ -170,6 +173,11 @@ void ClientHandler::updateLicense(const std::string &responseJson) m_license.user_id = json.get("user_id"); } +void ClientHandler::addChildClient(ClientHandler *client) +{ + m_childClients[client->getSocketId()] = client; +} + void ClientHandler::removeCachedFile() { utils::deleteFile(m_request.licenseFile); } @@ -181,23 +189,19 @@ void ClientHandler::resetTime() bool ClientHandler::removeChildClient(uint16_t socketId) { - for (uint8_t i = 0; i < m_childClients.size(); i++ ) { - if (m_childClients.at(i)->getSocketId() == socketId) { - ClientHandler *client = m_childClients[i]; - m_childClients.erase(m_childClients.begin() + i); - delete client; - return true; - } + if (m_childClients.find(socketId) != m_childClients.end()) { + ClientHandler *client = m_childClients[socketId]; + m_childClients.erase(socketId); + delete client; + return true; } return false; } bool ClientHandler::clientInStorage(uint16_t socketId) { - for (auto client : m_childClients) { - if (client->getSocketId() == socketId) { - return true; - } + if (m_childClients.find(socketId) != m_childClients.end()) { + return true; } return false; } diff --git a/src/libs/qlicenseservice/daemon_clients/clienthandler.h b/src/libs/qlicenseservice/daemon_clients/clienthandler.h index cdd5e7e..084f343 100644 --- a/src/libs/qlicenseservice/daemon_clients/clienthandler.h +++ b/src/libs/qlicenseservice/daemon_clients/clienthandler.h @@ -8,6 +8,7 @@ #include #include #include +#include #include "commonsetup.h" #include "licdsetup.h" @@ -44,7 +45,7 @@ class ClientHandler void resetTime(); bool hasFloatingLicense() { return m_floatingLicense; } bool hasParent() { return m_hasParent; } - void addChildClient(ClientHandler *client) { m_childClients.push_back(std::move(client)); } + void addChildClient(ClientHandler *client); bool removeChildClient(uint16_t socketId); bool hasChildren() { return !m_childClients.empty(); } bool stopped() { return m_stoppedWorking; } @@ -52,7 +53,7 @@ class ClientHandler bool clientInStorage(uint16_t socketId); protected: - std::vector m_childClients; + std::unordered_map m_childClients; License m_license; RequestInfo m_request; LicdSetup m_settings;; diff --git a/src/libs/qlicenseservice/daemon_clients/squishhandler.h b/src/libs/qlicenseservice/daemon_clients/squishhandler.h index 729561c..9116eaa 100644 --- a/src/libs/qlicenseservice/daemon_clients/squishhandler.h +++ b/src/libs/qlicenseservice/daemon_clients/squishhandler.h @@ -107,11 +107,12 @@ class SquishHandler : public ClientHandler { bool isLicenseRequestDue() override { // First check if this client is a subprocess - no reporting - if (m_hasParent) + if (m_hasParent) { return false; - + } uint64_t now = utils::getTimestampNow(); - if (m_license.last_timestamp == 0) return true; // startup + if (m_license.last_timestamp == 0) + return true; // startup if ((now - m_license.last_timestamp) > m_updateInterval) return true; return false; diff --git a/src/libs/qlicenseservice/licenser.cpp b/src/libs/qlicenseservice/licenser.cpp index 574fedd..f2364d6 100644 --- a/src/libs/qlicenseservice/licenser.cpp +++ b/src/libs/qlicenseservice/licenser.cpp @@ -52,8 +52,8 @@ Licenser::~Licenser() int Licenser::listen() { m_infoString = ""; - uint16_t socket = 0; // Placeholder for whatever socket gets active - std::string input = m_tcpServer->listenToClients(socket); + uint16_t socketId = 0; // Placeholder for whatever socket gets active + std::string input = m_tcpServer->listenToClients(socketId); input = utils::trimStr(input); if (input.empty()) { @@ -63,23 +63,23 @@ int Licenser::listen() return 0; //continue; } if (input == SOCKET_CLOSED_MSG) { - std::cout << "Client disconnected, socket id " << socket << std::endl; - removeReservation(socket); + std::cout << "Client disconnected, socket id " << socketId << std::endl; + removeReservation(socketId); return 0; } std::cout << "Got a request: " << input << std::endl; // Check if we already have this client in storage (floating one): - if (clientInStorage(socket)) { + if (clientInStorage(socketId)) { // do nothing - floating clients should only send request at startup - std::cout << "Floating client with ID " << socket << " sent something while working: ignoring\n"; - m_tcpServer->sendResponse(socket, "NOK\n"); + std::cout << "Floating client with ID " << socketId << " sent something while working: ignoring\n"; + m_tcpServer->sendResponse(socketId, "NOK\n"); return 0; } std::string reply = ""; // Holds server response first (if got any). After parsing, holds reply to the client bool removeRes = false; - if (parseInputAndCreateCLient(socket, input)) { + if (parseInputAndCreateCLient(socketId, input)) { if (m_currentClient->parseRequest() != e_bad_request) { RequestType reqType = m_currentClient->getRequestType(); if (reqType == RequestType::reservation_query) { @@ -87,8 +87,8 @@ int Licenser::listen() } else if (reqType == RequestType::daemon_version) { reply = getDaemonVersion(); } else { - std::cout << "Initiating a request to the server\n"; if (m_currentClient->isLicenseRequestDue()) { + std::cout << "Initiating a request to the server\n"; if (sendServerRequest(reply) == e_bad_connection) { // Bad server connection: Check the existing license file for expiry date if (!m_currentClient->isCachedReservationValid(reply)) { @@ -105,11 +105,15 @@ int Licenser::listen() } } else { reply = replyString[e_bad_request]; + removeRes = true; } } else { reply = replyString[e_bad_request]; + removeRes = true; } - if (m_currentClient->hasFloatingLicense() && !clientInStorage(socket)) { + if (m_currentClient->hasFloatingLicense() + && !clientInStorage(socketId) + && !removeRes) { // Store QA tool, Coco or Squish client (floating license) if not already stored if (m_currentClient->hasParent()) { if (!addClientToParent()) { @@ -118,7 +122,7 @@ int Licenser::listen() } } else { std::cout << "Storing client in main cache\n"; - m_floatingClients.push_back(std::move(m_currentClient)); + m_floatingClients[socketId] = std::move(m_currentClient); } } if (!m_infoString.empty()) { @@ -126,13 +130,14 @@ int Licenser::listen() reply += m_infoString; } reply +="\n"; - m_tcpServer->sendResponse(socket, reply); - std::cout << "Replied to socket " << socket << ": " << reply << std::endl; + m_tcpServer->sendResponse(socketId, reply); + std::cout << "Replied to socket " << socketId << ": " << reply << std::endl; if (removeRes) { // No license, remove reservation from cache (floating license) // or license file (site license) - removeReservation(socket); + removeReservation(socketId); + return 0; } if (m_floatingClients.size() > 0) { @@ -145,21 +150,19 @@ int Licenser::listen() int Licenser::checkTasksDue() { // Check if there's any floating clients which has tasks to be done - ClientHandler *client; - for (int i = 0 ; i < m_floatingClients.size(); i++) { - client = m_floatingClients[i]; + for (auto entry : m_floatingClients) { // First check if (parent) client has stopped and no children left - if (client->stopped() && !client->hasChildren()) { - removeReservation(client->getSocketId()); + if (entry.second->stopped() && !entry.second->hasChildren()) { + removeReservation(entry.first); return 0; } // Then check if there is any server pings due - if (client->isLicenseRequestDue()) { + if (entry.second->isLicenseRequestDue()) { std::string reply; if (sendServerRequest(reply) != e_bad_connection) { - std::cout << "Reported alive floating reservation with socket ID " << client->getSocketId() << std::endl; - std::cout << "Client has " << client->getNumberOfClients() << " sub-processes running\n"; - client->resetTime(); + std::cout << "Reported alive floating reservation with socket ID " << entry.first << std::endl; + std::cout << "Client has " << entry.second->getNumberOfClients() << " sub-processes running\n"; + entry.second->resetTime(); } } } @@ -237,12 +240,11 @@ void Licenser::doHmacHashSha256(const std::string &payload, const std::string &s for (uint8_t x : out) { ss_result << std::hex << std::setfill('0') << std::setw(2) << (int)x; } - authKey = ss_result.str(); JsonHandler pay(payload); - } + std::string Licenser::checkReservations() { // Open all license files @@ -270,12 +272,13 @@ std::string Licenser::checkReservations() return reply.str(); } + bool Licenser::addClientToParent() { bool found = false; - for (int i = 0; i < m_floatingClients.size(); i++) { - if (m_floatingClients.at(i)->getReservationId() == m_currentClient->getParentReservationId()) { - m_floatingClients.at(i)->addChildClient(m_currentClient); + for (auto parent : m_floatingClients) { + if (parent.second->getReservationId() == m_currentClient->getParentReservationId()) { + parent.second->addChildClient(m_currentClient); found = true; std::cout << "Stored client under reservation ID " << m_currentClient->getParentReservationId() << std::endl; @@ -292,19 +295,19 @@ bool Licenser::addClientToParent() void Licenser::removeReservation(int socketId) { - // Check if the client had a floating license, or is a child of one: - ClientHandler *client; - for (int i = 0; i < m_floatingClients.size(); i++) { - client = m_floatingClients[i]; - if (client->getSocketId() == socketId) { - // If parent has no running children left, we can release the reservation + // Close the socket + m_tcpServer->closeClientSocket(socketId); + // Check if the client had a floating license, or is a child of one. + // Need to loop through all of them because socketId can be under any parent + for (auto element : m_floatingClients) { + ClientHandler* client = element.second; + if (element.first == socketId) { if (!client->stopped()) { client->prepareRelease(); - m_tcpServer->closeClientSocket(socketId); // Don't remove parent yet, it might have child processes left } if (!client->hasChildren()) { - // No child processes: remove it + // If client has no running children left, we can release the reservation and remove client std::string reply; client->release(); client->buildRequestJson(); @@ -312,28 +315,28 @@ void Licenser::removeReservation(int socketId) { if (sendServerRequest(reply) != e_bad_connection) { // if connection succeeds, we can forget about this client std::cout << "Removing floating reservation with ID " << client->getReservationId() << std::endl; - m_floatingClients.erase(m_floatingClients.begin() + i); + m_floatingClients.erase(socketId); delete client; + } } return; } else if (client->removeChildClient(socketId)) { std::cout << "Removed child client under reservation ID " << client->getReservationId() << std::endl; - m_tcpServer->closeClientSocket(socketId); return; } } - m_tcpServer->closeClientSocket(socketId); return; } + bool Licenser::clientInStorage(uint16_t socketId) { for (auto client : m_floatingClients) { - if (client->getSocketId() == socketId) { + if (client.first == socketId) { return true; } - if (client->hasChildren()) { - if (client->clientInStorage(socketId)) { + if (client.second->hasChildren()) { + if (client.second->clientInStorage(socketId)) { return true; } } @@ -341,6 +344,7 @@ bool Licenser::clientInStorage(uint16_t socketId) { return false; } + std::string Licenser::getDaemonVersion() { std::string version = "Qt License Daemon (qtlicd) v"; diff --git a/src/libs/qlicenseservice/licenser.h b/src/libs/qlicenseservice/licenser.h index 0c916a2..0c77c9b 100644 --- a/src/libs/qlicenseservice/licenser.h +++ b/src/libs/qlicenseservice/licenser.h @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include #include #if _WIN32 @@ -40,7 +40,7 @@ private: uint64_t m_mocInterval; std::string m_infoString; ClientHandler *m_currentClient; - std::vector m_floatingClients; + std::unordered_map m_floatingClients; bool parseInputAndCreateCLient(uint16_t socketId, const std::string &incoming); bool addClientToParent(); -- cgit v1.2.3