changed leave game shortcut, server cleanups, added max_games_per_user
This commit is contained in:
parent
d0b8c6ebd9
commit
38b31681e2
11 changed files with 85 additions and 64 deletions
|
@ -296,7 +296,7 @@ void TabGame::retranslateUi()
|
|||
aConcede->setText(tr("&Concede"));
|
||||
aConcede->setShortcut(tr("F2"));
|
||||
aLeaveGame->setText(tr("&Leave game"));
|
||||
aLeaveGame->setShortcut(tr("Esc"));
|
||||
aLeaveGame->setShortcut(tr("Ctrl+Q"));
|
||||
|
||||
sayLabel->setText(tr("&Say:"));
|
||||
cardInfo->retranslateUi();
|
||||
|
|
|
@ -112,24 +112,28 @@ void Server::broadcastRoomUpdate()
|
|||
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)
|
||||
{
|
||||
QMutexLocker locker(&serverMutex);
|
||||
rooms.insert(newRoom->getId(), newRoom);
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -19,15 +19,12 @@ class Server : public QObject
|
|||
signals:
|
||||
void pingClockTimeout();
|
||||
private slots:
|
||||
void gameCreated(Server_Game *game);
|
||||
void gameClosing(int gameId);
|
||||
void broadcastRoomUpdate();
|
||||
public:
|
||||
mutable QMutex serverMutex;
|
||||
Server(QObject *parent = 0);
|
||||
~Server();
|
||||
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; }
|
||||
int getNextGameId() { return nextGameId++; }
|
||||
|
||||
|
@ -42,12 +39,12 @@ public:
|
|||
virtual int getMessageCountingInterval() const { return 0; }
|
||||
virtual int getMaxMessageCountPerInterval() 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 *> getIgnoreList(const QString &name) = 0;
|
||||
virtual bool getUserBanned(Server_ProtocolHandler * /*client*/, const QString & /*userName*/) const { return false; }
|
||||
protected:
|
||||
QMap<int, Server_Game *> games;
|
||||
QList<Server_ProtocolHandler *> clients;
|
||||
QMap<QString, Server_ProtocolHandler *> users;
|
||||
QMap<int, Server_Room *> rooms;
|
||||
|
@ -55,6 +52,8 @@ protected:
|
|||
virtual bool userExists(const QString &user) = 0;
|
||||
virtual AuthenticationResult checkUserPassword(const QString &user, const QString &password) = 0;
|
||||
virtual ServerInfo_User *getUserData(const QString &name) = 0;
|
||||
int getUsersCount() const;
|
||||
int getGamesCount() const;
|
||||
int nextGameId;
|
||||
void addRoom(Server_Room *newRoom);
|
||||
};
|
||||
|
|
|
@ -44,6 +44,7 @@ Server_Game::Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QS
|
|||
|
||||
Server_Game::~Server_Game()
|
||||
{
|
||||
QMutexLocker roomLocker(&room->roomMutex);
|
||||
QMutexLocker locker(&gameMutex);
|
||||
|
||||
sendGameEvent(new Event_GameClosed);
|
||||
|
@ -53,7 +54,7 @@ Server_Game::~Server_Game()
|
|||
delete playerIterator.next().value();
|
||||
players.clear();
|
||||
|
||||
emit gameClosing();
|
||||
room->removeGame(this);
|
||||
delete creatorInfo;
|
||||
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)
|
||||
{
|
||||
QMutexLocker roomLocker(&room->roomMutex);
|
||||
QMutexLocker locker(&gameMutex);
|
||||
|
||||
players.remove(player->getPlayerId());
|
||||
|
@ -281,6 +283,7 @@ void Server_Game::removeArrowsToPlayer(Server_Player *player)
|
|||
|
||||
bool Server_Game::kickPlayer(int playerId)
|
||||
{
|
||||
QMutexLocker roomLocker(&room->roomMutex);
|
||||
QMutexLocker locker(&gameMutex);
|
||||
|
||||
Server_Player *playerToKick = players.value(playerId);
|
||||
|
|
|
@ -53,7 +53,6 @@ private:
|
|||
int secondsElapsed;
|
||||
QTimer *pingClock;
|
||||
signals:
|
||||
void gameClosing();
|
||||
void sigStartGameIfReady();
|
||||
private slots:
|
||||
void pingClockTimeout();
|
||||
|
|
|
@ -276,36 +276,20 @@ ResponseCode Server_ProtocolHandler::cmdLogin(Command_Login *cmd, CommandContain
|
|||
|
||||
enqueueProtocolItem(new Event_ServerMessage(server->getLoginMessage()));
|
||||
|
||||
QList<ServerInfo_User *> _buddyList, _ignoreList;
|
||||
if (authState == PasswordRight) {
|
||||
buddyList = server->getBuddyList(userInfo->getName());
|
||||
ignoreList = server->getIgnoreList(userInfo->getName());
|
||||
|
||||
// This might not scale very well. Use an extra QMap if it becomes a problem.
|
||||
QMutexLocker serverLocker(&server->serverMutex);
|
||||
QMutexLocker gameListLocker(&gameListMutex);
|
||||
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;
|
||||
|
||||
ignoreList = server->getIgnoreList(userInfo->getName());
|
||||
|
||||
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));
|
||||
return RespNothing;
|
||||
|
@ -374,11 +358,31 @@ ResponseCode Server_ProtocolHandler::cmdJoinRoom(Command_JoinRoom *cmd, CommandC
|
|||
if (!r)
|
||||
return RespNameNotFound;
|
||||
|
||||
QMutexLocker roomLocker(&r->roomMutex);
|
||||
r->addClient(this);
|
||||
rooms.insert(r->getId(), r);
|
||||
|
||||
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)));
|
||||
return RespNothing;
|
||||
}
|
||||
|
@ -437,6 +441,10 @@ ResponseCode Server_ProtocolHandler::cmdCreateGame(Command_CreateGame *cmd, Comm
|
|||
if (authState == PasswordWrong)
|
||||
return RespLoginNeeded;
|
||||
|
||||
if (server->getMaxGamesPerUser() > 0)
|
||||
if (room->getGamesCreatedByUser(userInfo->getName()) >= server->getMaxGamesPerUser())
|
||||
return RespContextError;
|
||||
|
||||
QList<int> gameTypes;
|
||||
QList<GameTypeId *> gameTypeList = cmd->getGameTypes();
|
||||
for (int i = 0; i < gameTypeList.size(); ++i)
|
||||
|
|
|
@ -87,26 +87,33 @@ Server_Game *Server_Room::createGame(const QString &description, const QString &
|
|||
// This mutex needs to be unlocked by the caller.
|
||||
newGame->gameMutex.lock();
|
||||
games.insert(newGame->getGameId(), newGame);
|
||||
connect(newGame, SIGNAL(gameClosing()), this, SLOT(removeGame()));
|
||||
|
||||
broadcastGameListUpdate(newGame);
|
||||
|
||||
emit gameCreated(newGame);
|
||||
emit roomInfoChanged();
|
||||
|
||||
return newGame;
|
||||
}
|
||||
|
||||
void Server_Room::removeGame()
|
||||
void Server_Room::removeGame(Server_Game *game)
|
||||
{
|
||||
QMutexLocker locker(&roomMutex);
|
||||
|
||||
Server_Game *game = static_cast<Server_Game *>(sender());
|
||||
QMutexLocker gameLocker(&game->gameMutex);
|
||||
// No need to lock roomMutex or gameMutex. This method is only
|
||||
// called from ~Server_Game, which locks both mutexes anyway beforehand.
|
||||
|
||||
broadcastGameListUpdate(game);
|
||||
games.remove(game->getGameId());
|
||||
|
||||
emit gameClosing(game->getGameId());
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -18,8 +18,6 @@ class Server_Room : public QObject, public QList<Server_ProtocolHandler *> {
|
|||
Q_OBJECT
|
||||
signals:
|
||||
void roomInfoChanged();
|
||||
void gameCreated(Server_Game *game);
|
||||
void gameClosing(int gameId);
|
||||
private:
|
||||
int id;
|
||||
QString name;
|
||||
|
@ -28,8 +26,6 @@ private:
|
|||
QString joinMessage;
|
||||
QStringList gameTypes;
|
||||
QMap<int, Server_Game *> games;
|
||||
private slots:
|
||||
void removeGame();
|
||||
public:
|
||||
mutable QMutex roomMutex;
|
||||
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; }
|
||||
Server *getServer() const;
|
||||
ServerInfo_Room *getInfo(bool complete) const;
|
||||
int getGamesCreatedByUser(const QString &name) const;
|
||||
|
||||
void addClient(Server_ProtocolHandler *client);
|
||||
void removeClient(Server_ProtocolHandler *client);
|
||||
void say(Server_ProtocolHandler *client, const QString &s);
|
||||
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);
|
||||
void removeGame(Server_Game *game);
|
||||
|
||||
void sendRoomEvent(RoomEvent *event);
|
||||
};
|
||||
|
|
|
@ -35,3 +35,4 @@ max_users_per_address=4
|
|||
message_counting_interval=10
|
||||
max_message_size_per_interval=1000
|
||||
max_message_count_per_interval=10
|
||||
max_games_per_user=5
|
||||
|
|
|
@ -102,6 +102,7 @@ Servatrice::Servatrice(QSettings *_settings, QObject *parent)
|
|||
messageCountingInterval = settings->value("security/message_counting_interval").toInt();
|
||||
maxMessageCountPerInterval = settings->value("security/max_message_count_per_interval").toInt();
|
||||
maxMessageSizePerInterval = settings->value("security/max_message_size_per_interval").toInt();
|
||||
maxGamesPerUser = settings->value("security/max_games_per_user").toInt();
|
||||
}
|
||||
|
||||
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.bindValue(":id", serverId);
|
||||
query.bindValue(":uptime", uptime);
|
||||
query.bindValue(":users_count", users.size());
|
||||
query.bindValue(":games_count", games.size());
|
||||
query.bindValue(":users_count", getUsersCount());
|
||||
query.bindValue(":games_count", getGamesCount());
|
||||
execSqlQuery(query);
|
||||
}
|
||||
|
||||
const QString Servatrice::versionString = "Servatrice 0.20110406";
|
||||
const QString Servatrice::versionString = "Servatrice 0.20110421";
|
||||
|
|
|
@ -65,6 +65,7 @@ public:
|
|||
int getMessageCountingInterval() const { return messageCountingInterval; }
|
||||
int getMaxMessageCountPerInterval() const { return maxMessageCountPerInterval; }
|
||||
int getMaxMessageSizePerInterval() const { return maxMessageSizePerInterval; }
|
||||
int getMaxGamesPerUser() const { return maxGamesPerUser; }
|
||||
QString getDbPrefix() const { return dbPrefix; }
|
||||
void updateLoginMessage();
|
||||
ServerInfo_User *getUserData(const QString &name);
|
||||
|
@ -88,7 +89,7 @@ private:
|
|||
QList<QPair<QHostAddress, int> > addressBanList;
|
||||
QList<QPair<QString, int> > nameBanList;
|
||||
int maxGameInactivityTime, maxPlayerInactivityTime;
|
||||
int maxUsersPerAddress, messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval;
|
||||
int maxUsersPerAddress, messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval, maxGamesPerUser;
|
||||
ServerInfo_User *evalUserQueryResult(const QSqlQuery &query, bool complete);
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue