From a9acb3f1ccbf1b894fb6ac526582576e8c317912 Mon Sep 17 00:00:00 2001 From: woogerboy21 Date: Sun, 12 Jul 2015 22:32:55 -0400 Subject: [PATCH] Total Max User Restriction Syntax correction. --- cockatrice/src/localserver.h | 1 + cockatrice/src/window_main.cpp | 1 + common/pb/event_connection_closed.proto | 1 + common/server_database_interface.h | 1 + servatrice/servatrice.ini.example | 5 ++++ servatrice/src/servatrice.cpp | 8 ++++++ .../src/servatrice_database_interface.cpp | 20 ++++++++++++++ .../src/servatrice_database_interface.h | 1 + servatrice/src/serversocketinterface.cpp | 26 ++++++++++++++++--- 9 files changed, 61 insertions(+), 3 deletions(-) diff --git a/cockatrice/src/localserver.h b/cockatrice/src/localserver.h index f47187f2..276ebf90 100644 --- a/cockatrice/src/localserver.h +++ b/cockatrice/src/localserver.h @@ -27,6 +27,7 @@ public: AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password, QString &reasonStr, int &secondsLeft); int getNextGameId() { return localServer->getNextLocalGameId(); } int getNextReplayId() { return -1; } + int getActiveUserCount() { return 0; } }; #endif diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index fb3d39c8..3c308d89 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -71,6 +71,7 @@ void MainWindow::processConnectionClosedEvent(const Event_ConnectionClosed &even client->disconnectFromServer(); QString reasonStr; switch (event.reason()) { + case Event_ConnectionClosed::USER_LIMIT_REACHED: reasonStr = tr("The server has reached its maximum user capacity, please check back later."); break; case Event_ConnectionClosed::TOO_MANY_CONNECTIONS: reasonStr = tr("There are too many concurrent connections from your address."); break; case Event_ConnectionClosed::BANNED: { reasonStr = tr("Banned by moderator"); diff --git a/common/pb/event_connection_closed.proto b/common/pb/event_connection_closed.proto index e516f172..d5972aa4 100644 --- a/common/pb/event_connection_closed.proto +++ b/common/pb/event_connection_closed.proto @@ -10,6 +10,7 @@ message Event_ConnectionClosed { TOO_MANY_CONNECTIONS = 3; BANNED = 4; USERNAMEINVALID = 5; + USER_LIMIT_REACHED = 6; } optional CloseReason reason = 1; optional string reason_str = 2; diff --git a/common/server_database_interface.h b/common/server_database_interface.h index 3be6f263..39e7ec9f 100644 --- a/common/server_database_interface.h +++ b/common/server_database_interface.h @@ -31,6 +31,7 @@ public slots: public: virtual int getNextGameId() = 0; virtual int getNextReplayId() = 0; + virtual int getActiveUserCount() = 0; virtual void clearSessionTables() { } virtual void lockSessionTables() { } diff --git a/servatrice/servatrice.ini.example b/servatrice/servatrice.ini.example index 41fc4f78..70078dba 100644 --- a/servatrice/servatrice.ini.example +++ b/servatrice/servatrice.ini.example @@ -188,6 +188,11 @@ max_game_inactivity_time=120 [security] +; You may want to restrict the number of users that can connect to your server at any given time. +enable_max_user_limit=false + +; Maximum number of users that can connect to the server, default is 500. +max_users_total=500 ; Maximum number of users that can connect from the same IP address; useful to avoid bots, default is 4 max_users_per_address=4 diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index ad6f6ada..69bbd44c 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -160,6 +160,14 @@ bool Servatrice::initServer() authenticationMethod = AuthenticationNone; } + bool 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(); + qDebug() << "Maximum user limit: " << maxUserLimit; + } + bool registrationEnabled = settingsCache->value("registration/enabled", false).toBool(); bool requireEmailForRegistration = settingsCache->value("registration/requireemail", true).toBool(); diff --git a/servatrice/src/servatrice_database_interface.cpp b/servatrice/src/servatrice_database_interface.cpp index 2464e88e..620957b4 100644 --- a/servatrice/src/servatrice_database_interface.cpp +++ b/servatrice/src/servatrice_database_interface.cpp @@ -805,3 +805,23 @@ bool Servatrice_DatabaseInterface::changeUserPassword(const QString &user, const } return false; } + +int Servatrice_DatabaseInterface::getActiveUserCount() +{ + int userCount = 0; + + if (!checkSql()) + return userCount; + + QSqlQuery *query = prepareQuery("select count(*) from {prefix}_sessions where id_server = :serverid AND end_time is NULL"); + query->bindValue(":serverid", server->getServerId()); + if (!execSqlQuery(query)){ + return userCount; + } + + if (query->next()){ + userCount = query->value(0).toInt(); + } + + return userCount; +} \ No newline at end of file diff --git a/servatrice/src/servatrice_database_interface.h b/servatrice/src/servatrice_database_interface.h index 8dada3dc..7e6c5847 100644 --- a/servatrice/src/servatrice_database_interface.h +++ b/servatrice/src/servatrice_database_interface.h @@ -58,6 +58,7 @@ public: int getNextGameId(); int getNextReplayId(); + int getActiveUserCount(); qint64 startSession(const QString &userName, const QString &address); void endSession(qint64 sessionId); void clearSessionTables(); diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 70f92c50..08693b5b 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -18,6 +18,7 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ +#include #include #include #include @@ -120,14 +121,33 @@ bool ServerSocketInterface::initSession() SessionEvent *identSe = prepareSessionEvent(identEvent); sendProtocolItem(*identSe); delete identSe; - - int maxUsers = servatrice->getMaxUsersPerAddress(); + + //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; + } + else { + std::cerr << "Player Count: " << playerCount << " / " << userLimit << std::endl; + } + } //allow unlimited number of connections from the trusted sources - QString trustedSources = settingsCache->value("server/trusted_sources","127.0.0.1,::1").toString(); + QString trustedSources = settingsCache->value("security/trusted_sources","127.0.0.1,::1").toString(); if (trustedSources.contains(socket->peerAddress().toString(),Qt::CaseInsensitive)) return true; + int maxUsers = servatrice->getMaxUsersPerAddress(); if ((maxUsers > 0) && (servatrice->getUsersWithAddress(socket->peerAddress()) >= maxUsers)) { Event_ConnectionClosed event; event.set_reason(Event_ConnectionClosed::TOO_MANY_CONNECTIONS);