diff --git a/.gitignore b/.gitignore index 29b09046..6b77edfe 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,4 @@ uics/ make.sh gitpush_serverstuff_stable pokerth_server - +.vscode/ diff --git a/pokerth_dbofficial.pro b/pokerth_dbofficial.pro index 1e646bb3..5ad35227 100644 --- a/pokerth_dbofficial.pro +++ b/pokerth_dbofficial.pro @@ -42,6 +42,7 @@ HEADERS += src/dbofficial/asyncdbauth.h \ src/dbofficial/asyncdbavatarblacklist.h \ src/dbofficial/asyncdbadminplayers.h \ src/dbofficial/asyncdbblockplayer.h \ + src/dbofficial/asyncdbplayerlastgames.h \ src/dbofficial/dbidmanager.h SOURCES += src/dbofficial/asyncdbauth.cpp \ src/dbofficial/asyncdbcreategame.cpp \ @@ -60,6 +61,7 @@ SOURCES += src/dbofficial/asyncdbauth.cpp \ src/dbofficial/asyncdbavatarblacklist.cpp \ src/dbofficial/asyncdbadminplayers.cpp \ src/dbofficial/asyncdbblockplayer.cpp \ + src/dbofficial/asyncdbplayerlastgames.cpp \ src/dbofficial/dbidmanager.cpp win32 { DEFINES += _WIN32_WINNT=0x0501 diff --git a/src/config/configfile.cpp b/src/config/configfile.cpp index dc5d2510..7c210fdd 100644 --- a/src/config/configfile.cpp +++ b/src/config/configfile.cpp @@ -312,6 +312,8 @@ ConfigFile::ConfigFile(char *argv0, bool readonly) : noWriteAccess(readonly) configList.push_back(ConfigInfo("DBServerEncryptionKey", CONFIG_TYPE_STRING, "")); configList.push_back(ConfigInfo("GameNameBadWordList", CONFIG_TYPE_STRING_LIST, "Regex")); configList.push_back(ConfigInfo("ServerRestrictGuestLogin", CONFIG_TYPE_INT, "0")); + configList.push_back(ConfigInfo("ServerLimitRankNum", CONFIG_TYPE_INT, "4")); + configList.push_back(ConfigInfo("ServerLimitRankPeriod", CONFIG_TYPE_INT, "60")); //fill tempList firstTime configBufferList = configList; diff --git a/src/db/common/serverdbgeneric.cpp b/src/db/common/serverdbgeneric.cpp index 86483a71..4872cc5b 100644 --- a/src/db/common/serverdbgeneric.cpp +++ b/src/db/common/serverdbgeneric.cpp @@ -93,6 +93,11 @@ ServerDBGeneric::SetGamePlayerPlace(unsigned /*requestId*/, DB_id /*playerId*/, { } +void +ServerDBGeneric::SetPlayerLastGames(unsigned /*requestId*/, DB_id /*playerId*/, std::vector /*last_games*/, std::string /*playerIp*/) +{ +} + void ServerDBGeneric::EndGame(unsigned /*requestId*/) { diff --git a/src/db/dbdefs.h b/src/db/dbdefs.h index d7170758..5847d6d3 100644 --- a/src/db/dbdefs.h +++ b/src/db/dbdefs.h @@ -35,6 +35,7 @@ #include #include +#include typedef unsigned DB_id; #define DB_ID_INVALID 0 @@ -45,6 +46,8 @@ struct DBPlayerData { std::string secret; std::string country; std::string last_login; + std::string last_games; + std::string last_ip; }; #endif diff --git a/src/db/serverdbgeneric.h b/src/db/serverdbgeneric.h index 1a111cc1..b24bfd00 100644 --- a/src/db/serverdbgeneric.h +++ b/src/db/serverdbgeneric.h @@ -57,6 +57,7 @@ public: virtual void AsyncCreateGame(unsigned requestId, const std::string &gameName); virtual void SetGamePlayerPlace(unsigned requestId, DB_id playerId, unsigned place); + virtual void SetPlayerLastGames(unsigned requestId, DB_id playerId, std::vector last_games, std::string playerIp); virtual void EndGame(unsigned requestId); virtual void AsyncReportAvatar(unsigned requestId, unsigned replyId, DB_id reportedPlayerId, const std::string &avatarHash, const std::string &avatarType, DB_id *byPlayerId); diff --git a/src/db/serverdbinterface.h b/src/db/serverdbinterface.h index 622f5aaa..00e20379 100644 --- a/src/db/serverdbinterface.h +++ b/src/db/serverdbinterface.h @@ -36,6 +36,7 @@ #include #include #include +#include typedef std::list db_list; @@ -57,6 +58,7 @@ public: virtual void AsyncCreateGame(unsigned requestId, const std::string &gameName) = 0; virtual void SetGamePlayerPlace(unsigned requestId, DB_id playerId, unsigned place) = 0; + virtual void SetPlayerLastGames(unsigned requestId, DB_id playerId, std::vector last_games, std::string playerIp) = 0; virtual void EndGame(unsigned requestId) = 0; virtual void AsyncReportAvatar(unsigned requestId, unsigned replyId, DB_id reportedPlayerId, const std::string &avatarHash, const std::string &avatarType, DB_id *byPlayerId) = 0; diff --git a/src/db/serverdbnoaction.h b/src/db/serverdbnoaction.h index d3f2f4da..28b62733 100644 --- a/src/db/serverdbnoaction.h +++ b/src/db/serverdbnoaction.h @@ -55,6 +55,7 @@ public: virtual void AsyncCreateGame(unsigned /*requestId*/, const std::string &/*gameName*/) {} virtual void SetGamePlayerPlace(unsigned /*requestId*/, DB_id /*playerId*/, unsigned /*place*/) {} + virtual void SetPlayerLastGames(unsigned /*requestId*/, DB_id /*playerId*/, std::vector /*last_games*/, std::string /*playerIp*/) {} virtual void EndGame(unsigned /*requestId*/) {} virtual void AsyncReportAvatar(unsigned /*requestId*/, unsigned /*replyId*/, DB_id /*reportedPlayerId*/, const std::string &/*avatarHash*/, const std::string &/*avatarType*/, DB_id * /*byPlayerId*/) {} diff --git a/src/dbofficial/asyncdbauth.cpp b/src/dbofficial/asyncdbauth.cpp index 56c0e75e..02aee093 100644 --- a/src/dbofficial/asyncdbauth.cpp +++ b/src/dbofficial/asyncdbauth.cpp @@ -52,19 +52,25 @@ AsyncDBAuth::HandleResult(mysqlpp::Query &/*query*/, DBIdManager& /*idManager*/, service.post(boost::bind(&ServerDBCallback::PlayerLoginFailed, &cb, GetId())); } else { int blocked = result[0][2]; - int active = result[0][5]; + int active = result[0][7]; if ((active != 1) || (blocked != 0)) { service.post(boost::bind(&ServerDBCallback::PlayerLoginBlocked, &cb, GetId())); } else { mysqlpp::String secret(result[0][1]); mysqlpp::String country(result[0][3]); mysqlpp::String last_login(result[0][4]); + mysqlpp::String last_games(result[0][5]); + mysqlpp::String last_ip(result[0][6]); boost::shared_ptr tmpData(new DBPlayerData); tmpData->id = result[0][0]; secret.to_string(tmpData->secret); if (!country.is_null()) country.to_string(tmpData->country); last_login.to_string(tmpData->last_login); + if (!last_games.is_null()) + last_games.to_string(tmpData->last_games); + if (!last_ip.is_null()) + last_ip.to_string(tmpData->last_ip); service.post(boost::bind(&ServerDBCallback::PlayerLoginSuccess, &cb, GetId(), tmpData)); } diff --git a/src/dbofficial/asyncdbplayerlastgames.cpp b/src/dbofficial/asyncdbplayerlastgames.cpp new file mode 100644 index 00000000..d583940f --- /dev/null +++ b/src/dbofficial/asyncdbplayerlastgames.cpp @@ -0,0 +1,62 @@ +/***************************************************************************** + * PokerTH - The open source texas holdem engine * + * Copyright (C) 2006-2016 Felix Hammer, Florian Thauer, Lothar May * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with this program. If not, see . * + * * + * * + * Additional permission under GNU AGPL version 3 section 7 * + * * + * If you modify this program, or any covered work, by linking or * + * combining it with the OpenSSL project's OpenSSL library (or a * + * modified version of that library), containing parts covered by the * + * terms of the OpenSSL or SSLeay licenses, the authors of PokerTH * + * (Felix Hammer, Florian Thauer, Lothar May) grant you additional * + * permission to convey the resulting work. * + * Corresponding Source for a non-source form of such a combination * + * shall include the source code for the parts of OpenSSL used as well * + * as that of the covered work. * + *****************************************************************************/ + +#include + + +using namespace std; + + +AsyncDBPlayerLastGames::AsyncDBPlayerLastGames(unsigned queryId, const string &preparedName, const list ¶ms) + : SingleAsyncDBQuery(queryId, preparedName, params) +{ +} + +AsyncDBPlayerLastGames::~AsyncDBPlayerLastGames() +{ +} + +void +AsyncDBPlayerLastGames::HandleResult(mysqlpp::Query &/*query*/, DBIdManager &/*idManager*/, mysqlpp::StoreQueryResult &/*result*/, boost::asio::io_service &service, ServerDBCallback &cb) +{ + // This query does not produce a result. + HandleError(service, cb); +} + +void +AsyncDBPlayerLastGames::HandleNoResult(mysqlpp::Query &/*query*/, DBIdManager& /*idManager*/, boost::asio::io_service &/*service*/, ServerDBCallback &/*cb*/) +{ +} + +void +AsyncDBPlayerLastGames::HandleError(boost::asio::io_service &service, ServerDBCallback &cb) +{ +} diff --git a/src/dbofficial/asyncdbplayerlastgames.h b/src/dbofficial/asyncdbplayerlastgames.h new file mode 100644 index 00000000..41f13e28 --- /dev/null +++ b/src/dbofficial/asyncdbplayerlastgames.h @@ -0,0 +1,57 @@ +/***************************************************************************** + * PokerTH - The open source texas holdem engine * + * Copyright (C) 2006-2016 Felix Hammer, Florian Thauer, Lothar May * + * * + * This program is free software: you can redistribute it and/or modify * + * it under the terms of the GNU Affero General Public License as * + * published by the Free Software Foundation, either version 3 of the * + * License, or (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU Affero General Public License for more details. * + * * + * You should have received a copy of the GNU Affero General Public License * + * along with this program. If not, see . * + * * + * * + * Additional permission under GNU AGPL version 3 section 7 * + * * + * If you modify this program, or any covered work, by linking or * + * combining it with the OpenSSL project's OpenSSL library (or a * + * modified version of that library), containing parts covered by the * + * terms of the OpenSSL or SSLeay licenses, the authors of PokerTH * + * (Felix Hammer, Florian Thauer, Lothar May) grant you additional * + * permission to convey the resulting work. * + * Corresponding Source for a non-source form of such a combination * + * shall include the source code for the parts of OpenSSL used as well * + * as that of the covered work. * + *****************************************************************************/ +/* Async database update to block a player. */ + +#ifndef _ASYNCDBPLAYERLASTGAMES_H_ +#define _ASYNCDBPLAYERLASTGAMES_H_ + +#include + + +class AsyncDBPlayerLastGames : public SingleAsyncDBQuery +{ +public: + AsyncDBPlayerLastGames(unsigned queryId, const std::string &preparedName, const std::list ¶ms); + virtual ~AsyncDBPlayerLastGames(); + + virtual void Init(DBIdManager& /*idManager*/) {} + + virtual void HandleResult(mysqlpp::Query &query, DBIdManager& idManager, mysqlpp::StoreQueryResult& result, boost::asio::io_service &service, ServerDBCallback &cb); + virtual void HandleNoResult(mysqlpp::Query &query, DBIdManager& idManager, boost::asio::io_service &service, ServerDBCallback &cb); + virtual void HandleError(boost::asio::io_service &service, ServerDBCallback &cb); + + virtual bool RequiresResultSet() const + { + return false; + } +}; + +#endif diff --git a/src/dbofficial/db_table_defs.h b/src/dbofficial/db_table_defs.h index 0e9db6af..5bbd04a7 100644 --- a/src/dbofficial/db_table_defs.h +++ b/src/dbofficial/db_table_defs.h @@ -42,6 +42,8 @@ #define DB_TABLE_PLAYER_COL_ACTIVE "active" #define DB_TABLE_PLAYER_COL_AVATARHASH "avatar_hash" #define DB_TABLE_PLAYER_COL_AVATARTYPE "avatar_mime" +#define DB_TABLE_PLAYER_COL_LASTGAMES "last_games" +#define DB_TABLE_PLAYER_COL_LASTIP "last_ip" #define DB_TABLE_GAME "game" #define DB_TABLE_GAME_COL_ID "idgame" diff --git a/src/dbofficial/serverdbthread.cpp b/src/dbofficial/serverdbthread.cpp index 1ae5e786..7d6889ab 100644 --- a/src/dbofficial/serverdbthread.cpp +++ b/src/dbofficial/serverdbthread.cpp @@ -41,12 +41,15 @@ #include #include #include +#include #include #include #include #include #include +#include // @TODO: remove in productive + #define QUERY_NICK_PREPARE "nick_template" #define QUERY_LOGIN_PREPARE "login_template" #define QUERY_AVATAR_BLACKLIST_PREPARE "avatar_blacklist_template" @@ -58,6 +61,7 @@ #define QUERY_REPORT_GAME_PREPARE "report_game_template" #define QUERY_ADMIN_PLAYER_PREPARE "admin_player_template" #define QUERY_BLOCK_PLAYER_PREPARE "block_player_template" +#define QUERY_PLAYER_LASTGAMES_PREPARE "player_lastgames_template" using namespace std; @@ -230,6 +234,33 @@ ServerDBThread::SetGamePlayerPlace(unsigned requestId, DB_id playerId, unsigned m_semaphore.post(); } +void +ServerDBThread::SetPlayerLastGames(unsigned requestId, DB_id playerId, std::vector last_games, std::string playerIp) +{ + LOG_ERROR("ServerDBThread::SetPlayerLastGames() entered."); + + std::ostringstream oss; + std::copy(last_games.begin(), last_games.end(), std::ostream_iterator(oss, ",")); + std::string last_gamesFieldValue( oss.str() ); + list params; + ostringstream paramStream; + params.push_back(last_gamesFieldValue); + params.push_back(playerIp); + paramStream << playerId; + params.push_back(paramStream.str()); + boost::shared_ptr asyncQuery( + new AsyncDBPlayerLastGames( + requestId, + QUERY_PLAYER_LASTGAMES_PREPARE, + params)); + { + boost::mutex::scoped_lock lock(m_asyncQueueMutex); + m_asyncQueue.push(asyncQuery); + } + LOG_ERROR("Query posted."); + m_semaphore.post(); +} + void ServerDBThread::EndGame(unsigned requestId) { @@ -432,7 +463,7 @@ ServerDBThread::EstablishDBConnection() */ prepareNick << "PREPARE " QUERY_NICK_PREPARE " FROM " << mysqlpp::quote - << "SELECT " DB_TABLE_PLAYER_COL_ID ", AES_DECRYPT(" DB_TABLE_PLAYER_COL_PASSWORD ", ?), " DB_TABLE_PLAYER_COL_VALID ", TRIM(" DB_TABLE_PLAYER_COL_COUNTRY "), " DB_TABLE_PLAYER_COL_LASTLOGIN ", " DB_TABLE_PLAYER_COL_ACTIVE " FROM " DB_TABLE_PLAYER " WHERE " DB_TABLE_PLAYER_COL_USERNAME " = ?"; + << "SELECT " DB_TABLE_PLAYER_COL_ID ", AES_DECRYPT(" DB_TABLE_PLAYER_COL_PASSWORD ", ?), " DB_TABLE_PLAYER_COL_VALID ", TRIM(" DB_TABLE_PLAYER_COL_COUNTRY "), " DB_TABLE_PLAYER_COL_LASTLOGIN ", " DB_TABLE_PLAYER_COL_LASTGAMES ", " DB_TABLE_PLAYER_COL_LASTIP ", " DB_TABLE_PLAYER_COL_ACTIVE " FROM " DB_TABLE_PLAYER " WHERE " DB_TABLE_PLAYER_COL_USERNAME " = ?"; mysqlpp::Query prepareAvatarBlacklist = m_connData->conn.query(); prepareAvatarBlacklist @@ -479,12 +510,16 @@ ServerDBThread::EstablishDBConnection() prepareBlockPlayer << "PREPARE " QUERY_BLOCK_PLAYER_PREPARE " FROM " << mysqlpp::quote << "UPDATE " DB_TABLE_PLAYER " SET " DB_TABLE_PLAYER_COL_VALID " = ?, " DB_TABLE_PLAYER_COL_ACTIVE " = ? WHERE " DB_TABLE_PLAYER_COL_ID " = ?"; + mysqlpp::Query preparePlayerLastGames = m_connData->conn.query(); + preparePlayerLastGames + << "PREPARE " QUERY_PLAYER_LASTGAMES_PREPARE " FROM " << mysqlpp::quote + << "UPDATE " DB_TABLE_PLAYER " SET " DB_TABLE_PLAYER_COL_LASTGAMES " = ?, " DB_TABLE_PLAYER_COL_LASTIP " = ? WHERE " DB_TABLE_PLAYER_COL_ID " = ?"; if (!prepareNick.exec() || !prepareAvatarBlacklist.exec() || !prepareLogin.exec() || !prepareCreateGame.exec() || !prepareEndGame.exec() || !prepareRelation.exec() || !prepareScore.exec() || !prepareReportAvatar.exec() - || !prepareReportGame.exec() || !prepareAdminPlayer.exec() || !prepareBlockPlayer.exec()) { + || !prepareReportGame.exec() || !prepareAdminPlayer.exec() || !prepareBlockPlayer.exec() || !preparePlayerLastGames.exec()) { string tmpError = string(prepareNick.error()) + prepareAvatarBlacklist.error() + prepareLogin.error() + prepareCreateGame.error() + prepareEndGame.error() + prepareRelation.error() + prepareScore.error() + prepareReportAvatar.error() + - prepareReportGame.error() + prepareAdminPlayer.error() + prepareBlockPlayer.error(); + prepareReportGame.error() + prepareAdminPlayer.error() + prepareBlockPlayer.error() + preparePlayerLastGames.error(); m_connData->conn.disconnect(); m_ioService->post(boost::bind(&ServerDBCallback::ConnectFailed, &m_callback, tmpError)); m_permanentError = true; diff --git a/src/dbofficial/serverdbthread.h b/src/dbofficial/serverdbthread.h index 274b247e..03722d1a 100644 --- a/src/dbofficial/serverdbthread.h +++ b/src/dbofficial/serverdbthread.h @@ -42,6 +42,7 @@ #include #include + struct DBConnectionData; class AsyncDBQuery; @@ -66,6 +67,7 @@ public: virtual void AsyncCreateGame(unsigned requestId, const std::string &gameName); virtual void SetGamePlayerPlace(unsigned requestId, DB_id playerId, unsigned place); + virtual void SetPlayerLastGames(unsigned requestId, DB_id playerId, std::vector last_games, std::string playerIp); virtual void EndGame(unsigned requestId); virtual void AsyncReportAvatar(unsigned requestId, unsigned replyId, DB_id reportedPlayerId, const std::string &avatarHash, const std::string &avatarType, DB_id *byPlayerId); diff --git a/src/net/common/servergame.cpp b/src/net/common/servergame.cpp index 3c219db9..a1483d92 100644 --- a/src/net/common/servergame.cpp +++ b/src/net/common/servergame.cpp @@ -293,11 +293,13 @@ ServerGame::TimerVoteKick(const boost::system::error_code &ec) PlayerDataList ServerGame::InternalStartGame() { + LOG_ERROR("InternalStartGame() entered."); // Initialize the game. PlayerDataList playerData(GetFullPlayerDataList()); if (playerData.size() >= 2) { // Set DB Backend. + // @TODO: check for wec or bbc game with bbcbot as creator if (GetGameData().gameType == GAME_TYPE_RANKING) m_database = GetLobbyThread().GetDatabase(); else @@ -346,6 +348,12 @@ ServerGame::InternalStartGame() GetDatabase().AsyncCreateGame(GetId(), GetName()); InitRankingMap(playerData); + + // @TODO: here to save last_games with mysql per player + + if (GetGameData().gameType == GAME_TYPE_RANKING) + StoreLastGames(playerData); + } return playerData; } @@ -442,6 +450,26 @@ ServerGame::StoreAndResetRanking() m_rankingMap.clear(); } +void +ServerGame::StoreLastGames(const PlayerDataList &playerDataList) +{ + // Store players lastgames in database. + PlayerDataList::const_iterator i = playerDataList.begin(); + PlayerDataList::const_iterator end = playerDataList.end(); + while (i != end) { + boost::shared_ptr tmpPlayer(*i); + // tmpPlayer->GetUniqueId() + tmpPlayer->AddPlayerLastGame((long)time(NULL)); + LOG_ERROR("TimeStamp stored: " << tmpPlayer->GetPlayerLastGames().back()); + std::vector last_games = tmpPlayer->GetPlayerLastGames(); + LOG_ERROR("Ready for storing vector for player " << tmpPlayer->GetDBId() << " - lastGameTs " << last_games.back()); + if(tmpPlayer->GetDBId() != DB_ID_INVALID){ + GetDatabase().SetPlayerLastGames(GetId(), tmpPlayer->GetDBId(), last_games, GetSessionManager().GetSessionByUniquePlayerId(tmpPlayer->GetUniqueId())->GetClientAddr()); + } + ++i; + } +} + void ServerGame::RemoveAutoLeavePlayers() { diff --git a/src/net/common/serverlobbythread.cpp b/src/net/common/serverlobbythread.cpp index d9c5169d..d7d83814 100644 --- a/src/net/common/serverlobbythread.cpp +++ b/src/net/common/serverlobbythread.cpp @@ -62,6 +62,7 @@ #include #include #include +#include #define SERVER_MAX_NUM_LOBBY_SESSIONS 512 // Maximum number of idle users in lobby. #define SERVER_MAX_NUM_TOTAL_SESSIONS 2000 // Total maximum of sessions, fitting a 2048 handle limit @@ -304,6 +305,7 @@ ServerLobbyThread::AddConnection(boost::shared_ptr sessionData) m_sessionManager.AddSession(sessionData); LOG_VERBOSE("Accepted connection - session #" << sessionData->GetId() << "."); + LOG_ERROR("Accepted connection - session #" << sessionData->GetId() << "."); sessionData->StartTimerInitTimeout(SERVER_INIT_SESSION_TIMEOUT_SEC); sessionData->StartTimerGlobalTimeout(SERVER_SESSION_FORCED_TIMEOUT_SEC); @@ -1347,7 +1349,7 @@ ServerLobbyThread::HandleNetPacketRetrieveAvatar(boost::shared_ptr void ServerLobbyThread::HandleNetPacketCreateGame(boost::shared_ptr session, const JoinNewGameMessage &newGame) { - LOG_VERBOSE("Creating new game, initiated by session #" << session->GetId() << "."); + LOG_ERROR("Creating new game, initiated by session #" << session->GetId() << "."); string password; if (newGame.has_password()) @@ -1377,6 +1379,10 @@ ServerLobbyThread::HandleNetPacketCreateGame(boost::shared_ptr sess SendJoinGameFailed(session, gameId, NTF_NET_JOIN_GUEST_FORBIDDEN); } else if (!ServerGame::CheckSettings(tmpData, password, GetServerMode())) { SendJoinGameFailed(session, gameId, NTF_NET_JOIN_INVALID_SETTINGS); + } else if (!session->GetPlayerData()->IsPlayerAllowedToJoinCreateLimitRank(m_serverConfig.readConfigString("ServerLimitRankNum"), m_serverConfig.readConfigString("ServerLimitRankPeriod")) + && tmpData.gameType == GAME_TYPE_RANKING ) { + LOG_ERROR("not allowed due to ranklimit"); + SendJoinGameFailed(session, gameId, NTF_NET_JOIN_IP_BLOCKED); } else { boost::shared_ptr game( new ServerGame( @@ -1418,6 +1424,7 @@ ServerLobbyThread::HandleNetPacketJoinGame(boost::shared_ptr sessio MoveSessionToGame(game, session, joinGame.autoleave(), true); } } else { + LOG_ERROR("JoinGame pre validation"); // As guest, you are only allowed to join normal games. if (session->GetPlayerData()->GetRights() == PLAYER_RIGHTS_GUEST && tmpData.gameType != GAME_TYPE_NORMAL) { @@ -1427,14 +1434,14 @@ ServerLobbyThread::HandleNetPacketJoinGame(boost::shared_ptr sessio SendJoinGameFailed(session, joinGame.gameid(), NTF_NET_JOIN_NOT_INVITED); } else if (!game->CheckPassword(password)) { SendJoinGameFailed(session, joinGame.gameid(), NTF_NET_JOIN_INVALID_PASSWORD); - } else if (tmpData.gameType == GAME_TYPE_RANKING - && !joinGame.spectateonly() - && session->GetClientAddr() != SERVER_ADDRESS_LOCALHOST_STR - && session->GetClientAddr() != SERVER_ADDRESS_LOCALHOST_STR_V4V6 - && session->GetClientAddr() != SERVER_ADDRESS_LOCALHOST_STR_V4 - && game->IsClientAddressConnected(session->GetClientAddr())) { + } else if (tmpData.gameType == GAME_TYPE_RANKING && !session->GetPlayerData()->IsPlayerAllowedToJoinCreateLimitRank(m_serverConfig.readConfigString("ServerLimitRankNum"), m_serverConfig.readConfigString("ServerLimitRankPeriod"))) { + SendJoinGameFailed(session, joinGame.gameid(), NTF_NET_JOIN_IP_BLOCKED); + } else if (tmpData.gameType == GAME_TYPE_RANKING && !joinGame.spectateonly() + && session->GetClientAddr() != SERVER_ADDRESS_LOCALHOST_STR + && session->GetClientAddr() != SERVER_ADDRESS_LOCALHOST_STR_V4V6 + && session->GetClientAddr() != SERVER_ADDRESS_LOCALHOST_STR_V4 + && game->IsClientAddressConnected(session->GetClientAddr())) { SendJoinGameFailed(session, joinGame.gameid(), NTF_NET_JOIN_IP_BLOCKED); - } else { MoveSessionToGame(game, session, joinGame.autoleave(), false); } @@ -1803,6 +1810,18 @@ ServerLobbyThread::UserValid(unsigned playerId, const DBPlayerData &dbPlayerData if (tmpSession && tmpSession->GetPlayerData()) { tmpSession->GetPlayerData()->SetDBId(dbPlayerData.id); tmpSession->GetPlayerData()->SetCountry(dbPlayerData.country); + if(dbPlayerData.last_games.length() > 0){ + LOG_ERROR("last_games from db = " << dbPlayerData.last_games); + vector last_games; + boost::split(last_games, dbPlayerData.last_games, boost::is_any_of(",")); + for (unsigned int i = 0; i < last_games.size(); i++){ + if(last_games[i].length() > 0) + tmpSession->GetPlayerData()->AddPlayerLastGame(stol(last_games[i])); + } + LOG_ERROR("last_games last from vector after db = " << tmpSession->GetPlayerData()->GetPlayerLastGames().back()); + }else{ + LOG_ERROR("no lastGames from db"); + } this->AuthChallenge(tmpSession, dbPlayerData.secret); } } diff --git a/src/net/common/sessionmanager.cpp b/src/net/common/sessionmanager.cpp index f4e00461..4fa89569 100644 --- a/src/net/common/sessionmanager.cpp +++ b/src/net/common/sessionmanager.cpp @@ -34,6 +34,8 @@ #include #include +#include + using namespace std; #define SERVER_MAX_GUEST_USERS_LOBBY 50 // LG: Maximum number of guests users in lobby allowed diff --git a/src/net/servergame.h b/src/net/servergame.h index fe3a125c..e9ea5867 100644 --- a/src/net/servergame.h +++ b/src/net/servergame.h @@ -148,6 +148,7 @@ protected: void SetPlayerPlace(unsigned playerId, int place); void ReplaceRankingPlayer(unsigned oldPlayerId, unsigned newPlayerId); void StoreAndResetRanking(); + void StoreLastGames(const PlayerDataList &playerDataList); void RemoveAutoLeavePlayers(); void InternalEndGame(); diff --git a/src/net/sessiondata.h b/src/net/sessiondata.h index 8521e00f..417cba7a 100644 --- a/src/net/sessiondata.h +++ b/src/net/sessiondata.h @@ -40,6 +40,7 @@ typedef unsigned SessionId; #include #include #include +#include #include #include diff --git a/src/net/sessionmanager.h b/src/net/sessionmanager.h index 36f7fb4f..a75359aa 100644 --- a/src/net/sessionmanager.h +++ b/src/net/sessionmanager.h @@ -65,6 +65,8 @@ public: bool IsPlayerConnected(unsigned uniqueId) const; bool IsClientAddressConnected(const std::string &clientAddress) const; bool IsGuestAllowedToConnect(const std::string &clientAddress) const; + bool IsPlayerAllowedToJoinCreateLimitRank(const std::string &playerName) const; + bool IsPlayerAllowedToJoinCreateLimitRank(unsigned uniqueId) const; void ForEach(boost::function)> func); diff --git a/src/playerdata.cpp b/src/playerdata.cpp index 8cd5cedf..f76185cf 100644 --- a/src/playerdata.cpp +++ b/src/playerdata.cpp @@ -29,6 +29,8 @@ * as that of the covered work. * *****************************************************************************/ #include +#include +#include // @TODO: remove in productive using namespace std; @@ -242,3 +244,59 @@ PlayerData::operator<(const PlayerData &other) const return m_number < other.GetNumber(); } +void +PlayerData::SetPlayerLastGames(std::vector last_games) +{ + boost::mutex::scoped_lock lock(m_dataMutex); + m_last_games.clear(); + m_last_games = last_games; +} + +void +PlayerData::AddPlayerLastGame(long lastGame) +{ + boost::mutex::scoped_lock lock(m_dataMutex); + + m_last_games.push_back(lastGame); +} + +std::vector +PlayerData::GetPlayerLastGames() +{ + boost::mutex::scoped_lock lock(m_dataMutex); + return m_last_games; +} + +bool +PlayerData::IsPlayerAllowedToJoinCreateLimitRank(std::string num, std::string period) +{ + bool retVal = false; +LOG_ERROR("checking IsPlayerAllowedToJoinCreateLimitRank() "); +LOG_ERROR("num = " << num << " period " << period); + boost::mutex::scoped_lock lock(m_dataMutex); + + long then = (long)time(NULL) - (long)(stoi(period) * 60); + + int count = 0; + int i=0; + for(std::vector::iterator timeStamp = m_last_games.begin(); timeStamp != m_last_games.end(); ++timeStamp) { + LOG_ERROR("timeStamp " << *timeStamp); + time_t ts = (time_t)*timeStamp; + LOG_ERROR("comparing ts " << (long)ts << " with " << then); + if((long)ts > then){ + LOG_ERROR("counting timeStamp in time " << ctime(&ts)); + count++; + }else{ + LOG_ERROR("erasing overdued timestamp " << ctime(&ts)); + timeStamp = m_last_games.erase(timeStamp); // erase overdued entries + if( timeStamp == m_last_games.end()) + break; + } + i++; + } + + if(count < stoi(num)) + retVal = true; + + return retVal; +} diff --git a/src/playerdata.h b/src/playerdata.h index 6a0ed8d3..81d0d831 100644 --- a/src/playerdata.h +++ b/src/playerdata.h @@ -116,6 +116,12 @@ public: int GetStartCash() const; void SetStartCash(int cash); + // @TODO: last_games here + void AddPlayerLastGame(long last_games); + void SetPlayerLastGames(std::vector last_games); + std::vector GetPlayerLastGames(); + bool IsPlayerAllowedToJoinCreateLimitRank(std::string num, std::string period); + bool operator<(const PlayerData &other) const; private: @@ -135,6 +141,8 @@ private: bool m_isGameAdmin; boost::shared_ptr m_netAvatarFile; + std::vector m_last_games; + mutable boost::mutex m_dataMutex; };