From 10b677acdf7f2a1b1179f2cf86ef3cd818c3e0da Mon Sep 17 00:00:00 2001 From: woogerboy21 Date: Sun, 16 Oct 2016 12:48:39 -0400 Subject: [PATCH] Cleanup max user check at login This change accomplishes two goals. The first is it moves the checking for if the servers set user limit is reached out of the socket interface and into the protocol handler portion of the code (were it should live). It also eleminates the need for a DB query at login to check the user count. The user account is actually already maintained by the server and a function already existed to get the user count total. --- cockatrice/src/window_main.cpp | 4 ++++ common/pb/response.proto | 1 + common/server.h | 7 ++++--- common/server_protocolhandler.cpp | 8 ++++++++ servatrice/src/servatrice.cpp | 4 ++-- servatrice/src/servatrice.h | 6 ++++-- servatrice/src/serversocketinterface.cpp | 18 ------------------ 7 files changed, 23 insertions(+), 25 deletions(-) diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index 5c1b97b5..2b0b4c4d 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -393,6 +393,10 @@ void MainWindow::loginError(Response::ResponseCode r, QString reasonStr, quint32 client->disconnectFromServer(); break; } + case Response::RespServerFull: { + QMessageBox::critical(this, tr("Server Full"), tr("The server has reached its maximum user capacity, please check back later.")); + break; + } default: QMessageBox::critical(this, tr("Error"), tr("Unknown login error: %1").arg(static_cast(r)) + tr("\nThis usually means that your client version is out of date, and the server sent a reply your client doesn't understand.")); break; diff --git a/common/pb/response.proto b/common/pb/response.proto index 0c058173..7a97acce 100644 --- a/common/pb/response.proto +++ b/common/pb/response.proto @@ -37,6 +37,7 @@ message Response { RespRegistrationAcceptedNeedsActivation = 33; // Server accepted cient registration, but it will need token activation RespClientIdRequired = 34; // Server requires client to generate and send its client id before allowing access RespClientUpdateRequired = 35; // Client is missing features that the server is requiring + RespServerFull = 36; // Server user limit reached } enum ResponseType { JOIN_ROOM = 1000; diff --git a/common/server.h b/common/server.h index f27ae843..6fd89c1c 100644 --- a/common/server.h +++ b/common/server.h @@ -62,6 +62,7 @@ public: virtual bool getGameShouldPing() const { return false; } virtual bool getClientIdRequired() const { return false; } virtual bool getRegOnlyServer() const { return false; } + virtual bool getmaxUserLimitEnabled() const { return false; } virtual int getPingClockInterval() const { return 0; } virtual int getMaxGameInactivityTime() const { return 9999999; } virtual int getMaxPlayerInactivityTime() const { return 9999999; } @@ -71,6 +72,7 @@ public: virtual int getMaxGamesPerUser() const { return 0; } virtual int getCommandCountingInterval() const { return 0; } virtual int getMaxCommandCountPerInterval() const { return 0; } + virtual int getMaxUserLimit() const { return 9999999; } Server_DatabaseInterface *getDatabaseInterface() const; int getNextLocalGameId() { QMutexLocker locker(&nextLocalGameIdMutex); return ++nextLocalGameId; } @@ -89,6 +91,8 @@ public: void addPersistentPlayer(const QString &userName, int roomId, int gameId, int playerId); void removePersistentPlayer(const QString &userName, int roomId, int gameId, int playerId); QList getPersistentPlayerReferences(const QString &userName) const; + int getUsersCount() const; + int getGamesCount() const; private: QMultiMap persistentPlayers; mutable QReadWriteLock persistentPlayersLock; @@ -118,9 +122,6 @@ protected: QMap externalUsers; QMap rooms; QMap databaseInterfaces; - - int getUsersCount() const; - int getGamesCount() const; void addRoom(Server_Room *newRoom); }; diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index f9a3d319..d18791d0 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -383,6 +383,14 @@ Response::ResponseCode Server_ProtocolHandler::cmdPing(const Command_Ping & /*cm Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd, ResponseContainer &rc) { + // limit the number of users that can connect to the server based on configuration settings + if (server->getmaxUserLimitEnabled()) { + if (server->getUsersCount() >= server->getMaxUserLimit()) { + qDebug() << "Max Users Total Limit Reached, please increase the max_users_total setting."; + return Response::RespServerFull; + } + } + QString userName = QString::fromStdString(cmd.user_name()).simplified(); QString clientId = QString::fromStdString(cmd.clientid()).simplified(); QString clientVersion = QString::fromStdString(cmd.clientver()).simplified(); diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 32067065..3a58b3ef 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -234,11 +234,11 @@ bool Servatrice::initServer() qDebug() << "Store Replays: " << settingsCache->value("game/store_replays", true).toBool(); qDebug() << "Client ID Required: " << clientIdRequired; - bool maxUserLimitEnabled = settingsCache->value("security/enable_max_user_limit", false).toBool(); + maxUserLimitEnabled = settingsCache->value("security/enable_max_user_limit", false).toBool(); qDebug() << "Maximum user limit enabled: " << maxUserLimitEnabled; if (maxUserLimitEnabled){ - int maxUserLimit = settingsCache->value("security/max_users_total", 500).toInt(); + maxUserLimit = settingsCache->value("security/max_users_total", 500).toInt(); qDebug() << "Maximum total user limit: " << maxUserLimit; int maxTcpUserLimit = settingsCache->value("security/max_users_tcp", 500).toInt(); qDebug() << "Maximum tcp user limit: " << maxTcpUserLimit; diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index d40929d4..3cafae83 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -134,14 +134,14 @@ private: int uptime; QMutex txBytesMutex, rxBytesMutex; quint64 txBytes, rxBytes; - int maxGameInactivityTime, maxPlayerInactivityTime; + int maxGameInactivityTime, maxPlayerInactivityTime, maxUserLimit; int maxUsersPerAddress, messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval, maxGamesPerUser, commandCountingInterval, maxCommandCountPerInterval, pingClockInterval; QString shutdownReason; int shutdownMinutes; int nextShutdownMessageMinutes; QTimer *shutdownTimer; - bool isFirstShutdownMessage, clientIdRequired, regServerOnly; + bool isFirstShutdownMessage, clientIdRequired, regServerOnly, maxUserLimitEnabled; mutable QMutex serverListMutex; QList serverList; @@ -164,6 +164,7 @@ public: bool getGameShouldPing() const { return true; } bool getClientIdRequired() const { return clientIdRequired; } bool getRegOnlyServer() const { return regServerOnly; } + bool getmaxUserLimitEnabled() const {return maxUserLimitEnabled; } int getPingClockInterval() const { return pingClockInterval; } int getMaxGameInactivityTime() const { return maxGameInactivityTime; } int getMaxPlayerInactivityTime() const { return maxPlayerInactivityTime; } @@ -174,6 +175,7 @@ public: int getMaxGamesPerUser() const { return maxGamesPerUser; } int getCommandCountingInterval() const { return commandCountingInterval; } int getMaxCommandCountPerInterval() const { return maxCommandCountPerInterval; } + int getMaxUserLimit() const { return maxUserLimit; } AuthenticationMethod getAuthenticationMethod() const { return authenticationMethod; } QString getDbPrefix() const { return dbPrefix; } int getServerId() const { return serverId; } diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index fd68bdd3..eeee6d1f 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -94,23 +94,6 @@ bool AbstractServerSocketInterface::initSession() sendProtocolItem(*identSe); delete identSe; - //limit the number of total users based on configuration settings - bool enforceUserLimit = settingsCache->value("security/enable_max_user_limit", false).toBool(); - if (enforceUserLimit){ - int userLimit = settingsCache->value("security/max_users_total", 500).toInt(); - int playerCount = (databaseInterface->getActiveUserCount() + 1); - if (playerCount > userLimit){ - std::cerr << "Max Users Total Limit Reached, please increase the max_users_total setting." << std::endl; - logger->logMessage(QString("Max Users Total Limit Reached, please increase the max_users_total setting."), this); - Event_ConnectionClosed event; - event.set_reason(Event_ConnectionClosed::USER_LIMIT_REACHED); - SessionEvent *se = prepareSessionEvent(event); - sendProtocolItem(*se); - delete se; - return false; - } - } - //allow unlimited number of connections from the trusted sources QString trustedSources = settingsCache->value("security/trusted_sources","127.0.0.1,::1").toString(); if (trustedSources.contains(getAddress(),Qt::CaseInsensitive)) @@ -123,7 +106,6 @@ bool AbstractServerSocketInterface::initSession() SessionEvent *se = prepareSessionEvent(event); sendProtocolItem(*se); delete se; - return false; }