changed leave game shortcut, server cleanups, added max_games_per_user

This commit is contained in:
Max-Wilhelm Bruker 2011-04-21 01:52:09 +02:00
parent d0b8c6ebd9
commit 38b31681e2
11 changed files with 85 additions and 64 deletions

View file

@ -296,7 +296,7 @@ void TabGame::retranslateUi()
aConcede->setText(tr("&Concede")); aConcede->setText(tr("&Concede"));
aConcede->setShortcut(tr("F2")); aConcede->setShortcut(tr("F2"));
aLeaveGame->setText(tr("&Leave game")); aLeaveGame->setText(tr("&Leave game"));
aLeaveGame->setShortcut(tr("Esc")); aLeaveGame->setShortcut(tr("Ctrl+Q"));
sayLabel->setText(tr("&Say:")); sayLabel->setText(tr("&Say:"));
cardInfo->retranslateUi(); cardInfo->retranslateUi();

View file

@ -112,24 +112,28 @@ void Server::broadcastRoomUpdate()
delete event; delete event;
} }
void Server::gameCreated(Server_Game *game)
{
QMutexLocker locker(&serverMutex);
games.insert(game->getGameId(), game);
}
void Server::gameClosing(int gameId)
{
QMutexLocker locker(&serverMutex);
qDebug("Server::gameClosing");
games.remove(gameId);
}
void Server::addRoom(Server_Room *newRoom) void Server::addRoom(Server_Room *newRoom)
{ {
QMutexLocker locker(&serverMutex); QMutexLocker locker(&serverMutex);
rooms.insert(newRoom->getId(), newRoom); rooms.insert(newRoom->getId(), newRoom);
connect(newRoom, SIGNAL(roomInfoChanged()), this, SLOT(broadcastRoomUpdate())); connect(newRoom, SIGNAL(roomInfoChanged()), this, SLOT(broadcastRoomUpdate()));
connect(newRoom, SIGNAL(gameCreated(Server_Game *)), this, SLOT(gameCreated(Server_Game *))); }
connect(newRoom, SIGNAL(gameClosing(int)), this, SLOT(gameClosing(int)));
int Server::getUsersCount() const
{
QMutexLocker locker(&serverMutex);
return users.size();
}
int Server::getGamesCount() const
{
int result = 0;
QMutexLocker locker(&serverMutex);
QMapIterator<int, Server_Room *> roomIterator(rooms);
while (roomIterator.hasNext()) {
Server_Room *room = roomIterator.next().value();
QMutexLocker roomLocker(&room->roomMutex);
result += room->getGames().size();
}
return result;
} }

View file

@ -19,15 +19,12 @@ class Server : public QObject
signals: signals:
void pingClockTimeout(); void pingClockTimeout();
private slots: private slots:
void gameCreated(Server_Game *game);
void gameClosing(int gameId);
void broadcastRoomUpdate(); void broadcastRoomUpdate();
public: public:
mutable QMutex serverMutex; mutable QMutex serverMutex;
Server(QObject *parent = 0); Server(QObject *parent = 0);
~Server(); ~Server();
AuthenticationResult loginUser(Server_ProtocolHandler *session, QString &name, const QString &password); AuthenticationResult loginUser(Server_ProtocolHandler *session, QString &name, const QString &password);
QList<Server_Game *> getGames() const { return games.values(); }
const QMap<int, Server_Room *> &getRooms() { return rooms; } const QMap<int, Server_Room *> &getRooms() { return rooms; }
int getNextGameId() { return nextGameId++; } int getNextGameId() { return nextGameId++; }
@ -42,12 +39,12 @@ public:
virtual int getMessageCountingInterval() const { return 0; } virtual int getMessageCountingInterval() const { return 0; }
virtual int getMaxMessageCountPerInterval() const { return 0; } virtual int getMaxMessageCountPerInterval() const { return 0; }
virtual int getMaxMessageSizePerInterval() const { return 0; } virtual int getMaxMessageSizePerInterval() const { return 0; }
virtual int getMaxGamesPerUser() const { return 0; }
virtual QMap<QString, ServerInfo_User *> getBuddyList(const QString &name) = 0; virtual QMap<QString, ServerInfo_User *> getBuddyList(const QString &name) = 0;
virtual QMap<QString, ServerInfo_User *> getIgnoreList(const QString &name) = 0; virtual QMap<QString, ServerInfo_User *> getIgnoreList(const QString &name) = 0;
virtual bool getUserBanned(Server_ProtocolHandler * /*client*/, const QString & /*userName*/) const { return false; } virtual bool getUserBanned(Server_ProtocolHandler * /*client*/, const QString & /*userName*/) const { return false; }
protected: protected:
QMap<int, Server_Game *> games;
QList<Server_ProtocolHandler *> clients; QList<Server_ProtocolHandler *> clients;
QMap<QString, Server_ProtocolHandler *> users; QMap<QString, Server_ProtocolHandler *> users;
QMap<int, Server_Room *> rooms; QMap<int, Server_Room *> rooms;
@ -55,6 +52,8 @@ protected:
virtual bool userExists(const QString &user) = 0; virtual bool userExists(const QString &user) = 0;
virtual AuthenticationResult checkUserPassword(const QString &user, const QString &password) = 0; virtual AuthenticationResult checkUserPassword(const QString &user, const QString &password) = 0;
virtual ServerInfo_User *getUserData(const QString &name) = 0; virtual ServerInfo_User *getUserData(const QString &name) = 0;
int getUsersCount() const;
int getGamesCount() const;
int nextGameId; int nextGameId;
void addRoom(Server_Room *newRoom); void addRoom(Server_Room *newRoom);
}; };

View file

@ -44,6 +44,7 @@ Server_Game::Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QS
Server_Game::~Server_Game() Server_Game::~Server_Game()
{ {
QMutexLocker roomLocker(&room->roomMutex);
QMutexLocker locker(&gameMutex); QMutexLocker locker(&gameMutex);
sendGameEvent(new Event_GameClosed); sendGameEvent(new Event_GameClosed);
@ -53,7 +54,7 @@ Server_Game::~Server_Game()
delete playerIterator.next().value(); delete playerIterator.next().value();
players.clear(); players.clear();
emit gameClosing(); room->removeGame(this);
delete creatorInfo; delete creatorInfo;
qDebug("Server_Game destructor"); qDebug("Server_Game destructor");
} }
@ -233,6 +234,7 @@ Server_Player *Server_Game::addPlayer(Server_ProtocolHandler *handler, bool spec
void Server_Game::removePlayer(Server_Player *player) void Server_Game::removePlayer(Server_Player *player)
{ {
QMutexLocker roomLocker(&room->roomMutex);
QMutexLocker locker(&gameMutex); QMutexLocker locker(&gameMutex);
players.remove(player->getPlayerId()); players.remove(player->getPlayerId());
@ -281,6 +283,7 @@ void Server_Game::removeArrowsToPlayer(Server_Player *player)
bool Server_Game::kickPlayer(int playerId) bool Server_Game::kickPlayer(int playerId)
{ {
QMutexLocker roomLocker(&room->roomMutex);
QMutexLocker locker(&gameMutex); QMutexLocker locker(&gameMutex);
Server_Player *playerToKick = players.value(playerId); Server_Player *playerToKick = players.value(playerId);

View file

@ -53,7 +53,6 @@ private:
int secondsElapsed; int secondsElapsed;
QTimer *pingClock; QTimer *pingClock;
signals: signals:
void gameClosing();
void sigStartGameIfReady(); void sigStartGameIfReady();
private slots: private slots:
void pingClockTimeout(); void pingClockTimeout();

View file

@ -276,37 +276,21 @@ ResponseCode Server_ProtocolHandler::cmdLogin(Command_Login *cmd, CommandContain
enqueueProtocolItem(new Event_ServerMessage(server->getLoginMessage())); enqueueProtocolItem(new Event_ServerMessage(server->getLoginMessage()));
QList<ServerInfo_User *> _buddyList, _ignoreList;
if (authState == PasswordRight) { if (authState == PasswordRight) {
buddyList = server->getBuddyList(userInfo->getName()); buddyList = server->getBuddyList(userInfo->getName());
QMapIterator<QString, ServerInfo_User *> buddyIterator(buddyList);
while (buddyIterator.hasNext())
_buddyList.append(new ServerInfo_User(buddyIterator.next().value()));
ignoreList = server->getIgnoreList(userInfo->getName()); ignoreList = server->getIgnoreList(userInfo->getName());
// This might not scale very well. Use an extra QMap if it becomes a problem. QMapIterator<QString, ServerInfo_User *> ignoreIterator(ignoreList);
QMutexLocker serverLocker(&server->serverMutex); while (ignoreIterator.hasNext())
QMutexLocker gameListLocker(&gameListMutex); _ignoreList.append(new ServerInfo_User(ignoreIterator.next().value()));
const QList<Server_Game *> &serverGames = server->getGames();
for (int i = 0; i < serverGames.size(); ++i) {
QMutexLocker gameLocker(&serverGames[i]->gameMutex);
const QList<Server_Player *> &gamePlayers = serverGames[i]->getPlayers().values();
for (int j = 0; j < gamePlayers.size(); ++j)
if (gamePlayers[j]->getUserInfo()->getName() == userInfo->getName()) {
gamePlayers[j]->setProtocolHandler(this);
games.insert(serverGames[i]->getGameId(), QPair<Server_Game *, Server_Player *>(serverGames[i], gamePlayers[j]));
enqueueProtocolItem(new Event_GameJoined(serverGames[i]->getGameId(), serverGames[i]->getDescription(), gamePlayers[j]->getPlayerId(), gamePlayers[j]->getSpectator(), serverGames[i]->getSpectatorsCanTalk(), serverGames[i]->getSpectatorsSeeEverything(), true));
enqueueProtocolItem(GameEventContainer::makeNew(new Event_GameStateChanged(serverGames[i]->getGameStarted(), serverGames[i]->getActivePlayer(), serverGames[i]->getActivePhase(), serverGames[i]->getGameState(gamePlayers[j])), serverGames[i]->getGameId()));
}
}
} }
QList<ServerInfo_User *> _buddyList;
QMapIterator<QString, ServerInfo_User *> buddyIterator(buddyList);
while (buddyIterator.hasNext())
_buddyList.append(new ServerInfo_User(buddyIterator.next().value()));
QList<ServerInfo_User *> _ignoreList;
QMapIterator<QString, ServerInfo_User *> ignoreIterator(ignoreList);
while (ignoreIterator.hasNext())
_ignoreList.append(new ServerInfo_User(ignoreIterator.next().value()));
cont->setResponse(new Response_Login(cont->getCmdId(), RespOk, new ServerInfo_User(userInfo, true), _buddyList, _ignoreList)); cont->setResponse(new Response_Login(cont->getCmdId(), RespOk, new ServerInfo_User(userInfo, true), _buddyList, _ignoreList));
return RespNothing; return RespNothing;
} }
@ -374,11 +358,31 @@ ResponseCode Server_ProtocolHandler::cmdJoinRoom(Command_JoinRoom *cmd, CommandC
if (!r) if (!r)
return RespNameNotFound; return RespNameNotFound;
QMutexLocker roomLocker(&r->roomMutex);
r->addClient(this); r->addClient(this);
rooms.insert(r->getId(), r); rooms.insert(r->getId(), r);
enqueueProtocolItem(new Event_RoomSay(r->getId(), QString(), r->getJoinMessage())); enqueueProtocolItem(new Event_RoomSay(r->getId(), QString(), r->getJoinMessage()));
// This might not scale very well. Use an extra QMap if it becomes a problem.
QMutexLocker gameListLocker(&gameListMutex);
QMapIterator<int, Server_Game *> gameIterator(r->getGames());
while (gameIterator.hasNext()) {
Server_Game *game = gameIterator.next().value();
QMutexLocker gameLocker(&game->gameMutex);
const QList<Server_Player *> &gamePlayers = game->getPlayers().values();
for (int j = 0; j < gamePlayers.size(); ++j)
if (gamePlayers[j]->getUserInfo()->getName() == userInfo->getName()) {
gamePlayers[j]->setProtocolHandler(this);
games.insert(game->getGameId(), QPair<Server_Game *, Server_Player *>(game, gamePlayers[j]));
enqueueProtocolItem(new Event_GameJoined(game->getGameId(), game->getDescription(), gamePlayers[j]->getPlayerId(), gamePlayers[j]->getSpectator(), game->getSpectatorsCanTalk(), game->getSpectatorsSeeEverything(), true));
enqueueProtocolItem(GameEventContainer::makeNew(new Event_GameStateChanged(game->getGameStarted(), game->getActivePlayer(), game->getActivePhase(), game->getGameState(gamePlayers[j])), game->getGameId()));
break;
}
}
cont->setResponse(new Response_JoinRoom(cont->getCmdId(), RespOk, r->getInfo(true))); cont->setResponse(new Response_JoinRoom(cont->getCmdId(), RespOk, r->getInfo(true)));
return RespNothing; return RespNothing;
} }
@ -437,6 +441,10 @@ ResponseCode Server_ProtocolHandler::cmdCreateGame(Command_CreateGame *cmd, Comm
if (authState == PasswordWrong) if (authState == PasswordWrong)
return RespLoginNeeded; return RespLoginNeeded;
if (server->getMaxGamesPerUser() > 0)
if (room->getGamesCreatedByUser(userInfo->getName()) >= server->getMaxGamesPerUser())
return RespContextError;
QList<int> gameTypes; QList<int> gameTypes;
QList<GameTypeId *> gameTypeList = cmd->getGameTypes(); QList<GameTypeId *> gameTypeList = cmd->getGameTypes();
for (int i = 0; i < gameTypeList.size(); ++i) for (int i = 0; i < gameTypeList.size(); ++i)

View file

@ -87,26 +87,33 @@ Server_Game *Server_Room::createGame(const QString &description, const QString &
// This mutex needs to be unlocked by the caller. // This mutex needs to be unlocked by the caller.
newGame->gameMutex.lock(); newGame->gameMutex.lock();
games.insert(newGame->getGameId(), newGame); games.insert(newGame->getGameId(), newGame);
connect(newGame, SIGNAL(gameClosing()), this, SLOT(removeGame()));
broadcastGameListUpdate(newGame); broadcastGameListUpdate(newGame);
emit gameCreated(newGame);
emit roomInfoChanged(); emit roomInfoChanged();
return newGame; return newGame;
} }
void Server_Room::removeGame() void Server_Room::removeGame(Server_Game *game)
{ {
QMutexLocker locker(&roomMutex); // No need to lock roomMutex or gameMutex. This method is only
// called from ~Server_Game, which locks both mutexes anyway beforehand.
Server_Game *game = static_cast<Server_Game *>(sender());
QMutexLocker gameLocker(&game->gameMutex);
broadcastGameListUpdate(game); broadcastGameListUpdate(game);
games.remove(game->getGameId()); games.remove(game->getGameId());
emit gameClosing(game->getGameId());
emit roomInfoChanged(); emit roomInfoChanged();
} }
int Server_Room::getGamesCreatedByUser(const QString &userName) const
{
QMutexLocker locker(&roomMutex);
QMapIterator<int, Server_Game *> gamesIterator(games);
int result = 0;
while (gamesIterator.hasNext())
if (gamesIterator.next().value()->getCreatorInfo()->getName() == userName)
++result;
return result;
}

View file

@ -18,8 +18,6 @@ class Server_Room : public QObject, public QList<Server_ProtocolHandler *> {
Q_OBJECT Q_OBJECT
signals: signals:
void roomInfoChanged(); void roomInfoChanged();
void gameCreated(Server_Game *game);
void gameClosing(int gameId);
private: private:
int id; int id;
QString name; QString name;
@ -28,8 +26,6 @@ private:
QString joinMessage; QString joinMessage;
QStringList gameTypes; QStringList gameTypes;
QMap<int, Server_Game *> games; QMap<int, Server_Game *> games;
private slots:
void removeGame();
public: public:
mutable QMutex roomMutex; mutable QMutex roomMutex;
Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent); Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent);
@ -41,12 +37,14 @@ public:
const QMap<int, Server_Game *> &getGames() const { return games; } const QMap<int, Server_Game *> &getGames() const { return games; }
Server *getServer() const; Server *getServer() const;
ServerInfo_Room *getInfo(bool complete) const; ServerInfo_Room *getInfo(bool complete) const;
int getGamesCreatedByUser(const QString &name) const;
void addClient(Server_ProtocolHandler *client); void addClient(Server_ProtocolHandler *client);
void removeClient(Server_ProtocolHandler *client); void removeClient(Server_ProtocolHandler *client);
void say(Server_ProtocolHandler *client, const QString &s); void say(Server_ProtocolHandler *client, const QString &s);
void broadcastGameListUpdate(Server_Game *game); void broadcastGameListUpdate(Server_Game *game);
Server_Game *createGame(const QString &description, const QString &password, int maxPlayers, const QList<int> &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator); Server_Game *createGame(const QString &description, const QString &password, int maxPlayers, const QList<int> &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator);
void removeGame(Server_Game *game);
void sendRoomEvent(RoomEvent *event); void sendRoomEvent(RoomEvent *event);
}; };

View file

@ -35,3 +35,4 @@ max_users_per_address=4
message_counting_interval=10 message_counting_interval=10
max_message_size_per_interval=1000 max_message_size_per_interval=1000
max_message_count_per_interval=10 max_message_count_per_interval=10
max_games_per_user=5

View file

@ -102,6 +102,7 @@ Servatrice::Servatrice(QSettings *_settings, QObject *parent)
messageCountingInterval = settings->value("security/message_counting_interval").toInt(); messageCountingInterval = settings->value("security/message_counting_interval").toInt();
maxMessageCountPerInterval = settings->value("security/max_message_count_per_interval").toInt(); maxMessageCountPerInterval = settings->value("security/max_message_count_per_interval").toInt();
maxMessageSizePerInterval = settings->value("security/max_message_size_per_interval").toInt(); maxMessageSizePerInterval = settings->value("security/max_message_size_per_interval").toInt();
maxGamesPerUser = settings->value("security/max_games_per_user").toInt();
} }
Servatrice::~Servatrice() Servatrice::~Servatrice()
@ -357,9 +358,9 @@ void Servatrice::statusUpdate()
query.prepare("insert into " + dbPrefix + "_uptime (id_server, timest, uptime, users_count, games_count) values(:id, NOW(), :uptime, :users_count, :games_count)"); query.prepare("insert into " + dbPrefix + "_uptime (id_server, timest, uptime, users_count, games_count) values(:id, NOW(), :uptime, :users_count, :games_count)");
query.bindValue(":id", serverId); query.bindValue(":id", serverId);
query.bindValue(":uptime", uptime); query.bindValue(":uptime", uptime);
query.bindValue(":users_count", users.size()); query.bindValue(":users_count", getUsersCount());
query.bindValue(":games_count", games.size()); query.bindValue(":games_count", getGamesCount());
execSqlQuery(query); execSqlQuery(query);
} }
const QString Servatrice::versionString = "Servatrice 0.20110406"; const QString Servatrice::versionString = "Servatrice 0.20110421";

View file

@ -65,6 +65,7 @@ public:
int getMessageCountingInterval() const { return messageCountingInterval; } int getMessageCountingInterval() const { return messageCountingInterval; }
int getMaxMessageCountPerInterval() const { return maxMessageCountPerInterval; } int getMaxMessageCountPerInterval() const { return maxMessageCountPerInterval; }
int getMaxMessageSizePerInterval() const { return maxMessageSizePerInterval; } int getMaxMessageSizePerInterval() const { return maxMessageSizePerInterval; }
int getMaxGamesPerUser() const { return maxGamesPerUser; }
QString getDbPrefix() const { return dbPrefix; } QString getDbPrefix() const { return dbPrefix; }
void updateLoginMessage(); void updateLoginMessage();
ServerInfo_User *getUserData(const QString &name); ServerInfo_User *getUserData(const QString &name);
@ -88,7 +89,7 @@ private:
QList<QPair<QHostAddress, int> > addressBanList; QList<QPair<QHostAddress, int> > addressBanList;
QList<QPair<QString, int> > nameBanList; QList<QPair<QString, int> > nameBanList;
int maxGameInactivityTime, maxPlayerInactivityTime; int maxGameInactivityTime, maxPlayerInactivityTime;
int maxUsersPerAddress, messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval; int maxUsersPerAddress, messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval, maxGamesPerUser;
ServerInfo_User *evalUserQueryResult(const QSqlQuery &query, bool complete); ServerInfo_User *evalUserQueryResult(const QSqlQuery &query, bool complete);
}; };