From 572e4eaafa5a2b130f91ce578f2b4dd864799cdc Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Mon, 12 Mar 2012 00:36:44 +0100 Subject: [PATCH] more ISL code, mutex fixes --- common/server.cpp | 20 +++---- common/server.h | 4 +- common/server_game.cpp | 6 +-- common/server_game.h | 1 + common/server_protocolhandler.cpp | 9 +++- common/server_room.cpp | 88 +++++++++++++++++++++---------- common/server_room.h | 24 +++++++-- servatrice/src/isl_interface.cpp | 2 +- servatrice/src/servatrice.cpp | 1 + 9 files changed, 107 insertions(+), 48 deletions(-) diff --git a/common/server.cpp b/common/server.cpp index bcb41734..6e4f1bdf 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -34,6 +34,8 @@ Server::Server(QObject *parent) : QObject(parent), serverMutex(QMutex::Recursive), nextGameId(0), nextReplayId(0) { + qRegisterMetaType("ServerInfo_Game"); + qRegisterMetaType("ServerInfo_Room"); } Server::~Server() @@ -170,22 +172,22 @@ void Server::externalUserLeft(QString userName) clients[i]->sendProtocolItem(*se); } -void Server::broadcastRoomUpdate() +void Server::broadcastRoomUpdate(const ServerInfo_Room &roomInfo, bool sendToIsl) { - QMutexLocker locker(&serverMutex); - Server_Room *room = static_cast(sender()); Event_ListRooms event; - - ServerInfo_Room *roomInfo = event.add_room_list(); - room->roomMutex.lock(); - roomInfo->CopyFrom(room->getInfo(false, false, true)); - room->roomMutex.unlock(); + event.add_room_list()->CopyFrom(roomInfo); SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event); + serverMutex.lock(); for (int i = 0; i < clients.size(); ++i) if (clients[i]->getAcceptsRoomListChanges()) clients[i]->sendProtocolItem(*se); + serverMutex.unlock(); + + if (sendToIsl) + sendIslMessage(*se); + delete se; } @@ -193,7 +195,7 @@ void Server::addRoom(Server_Room *newRoom) { QMutexLocker locker(&serverMutex); rooms.insert(newRoom->getId(), newRoom); - connect(newRoom, SIGNAL(roomInfoChanged()), this, SLOT(broadcastRoomUpdate())); + connect(newRoom, SIGNAL(roomInfoChanged(ServerInfo_Room)), this, SLOT(broadcastRoomUpdate(const ServerInfo_Room &)), Qt::QueuedConnection); } int Server::getUsersCount() const diff --git a/common/server.h b/common/server.h index b9d84288..ef53d077 100644 --- a/common/server.h +++ b/common/server.h @@ -6,6 +6,7 @@ #include #include #include "pb/serverinfo_user.pb.h" +#include "pb/serverinfo_room.pb.h" class Server_Game; class Server_Room; @@ -26,7 +27,7 @@ class Server : public QObject signals: void pingClockTimeout(); private slots: - void broadcastRoomUpdate(); + void broadcastRoomUpdate(const ServerInfo_Room &roomInfo, bool sendToIsl = false); public: mutable QMutex serverMutex; Server(QObject *parent = 0); @@ -68,6 +69,7 @@ public: protected slots: void externalUserJoined(ServerInfo_User userInfo); void externalUserLeft(QString userName); + void externalRoomUpdated(ServerInfo_Room roomInfo); protected: void prepareDestroy(); QList clients; diff --git a/common/server_game.cpp b/common/server_game.cpp index b7c9c399..32d5c0ba 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -271,7 +271,7 @@ void Server_Game::doStartGameIfReady() nextTurn(); locker.unlock(); - room->broadcastGameListUpdate(this); + emit gameInfoChanged(getInfo()); } void Server_Game::startGameIfReady() @@ -364,7 +364,7 @@ Server_Player *Server_Game::addPlayer(Server_ProtocolHandler *handler, bool spec } if (broadcastUpdate) - room->broadcastGameListUpdate(this); + emit gameInfoChanged(getInfo()); return newPlayer; } @@ -409,7 +409,7 @@ void Server_Game::removePlayer(Server_Player *player) if (gameStarted && playerActive) nextTurn(); } - room->broadcastGameListUpdate(this); + emit gameInfoChanged(getInfo()); } void Server_Game::removeArrowsToPlayer(GameEventStorage &ges, Server_Player *player) diff --git a/common/server_game.h b/common/server_game.h index 5e3e3803..166e1b9b 100644 --- a/common/server_game.h +++ b/common/server_game.h @@ -67,6 +67,7 @@ private: GameReplay *currentReplay; signals: void sigStartGameIfReady(); + void gameInfoChanged(ServerInfo_Game gameInfo); private slots: void pingClockTimeout(); void doStartGameIfReady(); diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index f78f2ce4..0bb787c5 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -695,11 +695,16 @@ Response::ResponseCode Server_ProtocolHandler::cmdCreateGame(const Command_Creat QString description = QString::fromStdString(cmd.description()); if (description.size() > 60) description = description.left(60); - Server_Game *game = room->createGame(description, QString::fromStdString(cmd.password()), cmd.max_players(), gameTypes, cmd.only_buddies(), cmd.only_registered(), cmd.spectators_allowed(), cmd.spectators_need_password(), cmd.spectators_can_talk(), cmd.spectators_see_everything(), this); + + Server_Game *game = new Server_Game(this, server->getNextGameId(), description, QString::fromStdString(cmd.password()), cmd.max_players(), gameTypes, cmd.only_buddies(), cmd.only_registered(), cmd.spectators_allowed(), cmd.spectators_need_password(), cmd.spectators_can_talk(), cmd.spectators_see_everything(), room); + game->moveToThread(room->thread()); + + QMutexLocker gameListLocker(&gameListMutex); + game->gameMutex.lock(); + room->addGame(game); Server_Player *creator = game->getPlayers().values().first(); - QMutexLocker gameListLocker(&gameListMutex); games.insert(game->getGameId(), QPair(game, creator)); Event_GameJoined event1; diff --git a/common/server_room.cpp b/common/server_room.cpp index 05d83118..1d5c0578 100644 --- a/common/server_room.cpp +++ b/common/server_room.cpp @@ -12,6 +12,7 @@ Server_Room::Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent) : QObject(parent), id(_id), name(_name), description(_description), autoJoin(_autoJoin), joinMessage(_joinMessage), gameTypes(_gameTypes), roomMutex(QMutex::Recursive) { + connect(this, SIGNAL(gameListChanged(ServerInfo_Game)), this, SLOT(broadcastGameListUpdate(ServerInfo_Game)), Qt::QueuedConnection); } Server_Room::~Server_Room() @@ -32,14 +33,14 @@ Server *Server_Room::getServer() const return static_cast(parent()); } -ServerInfo_Room Server_Room::getInfo(bool complete, bool showGameTypes, bool updating) const +ServerInfo_Room Server_Room::getInfo(bool complete, bool showGameTypes, bool updating, bool includeExternalData) const { QMutexLocker locker(&roomMutex); ServerInfo_Room result; result.set_room_id(id); - result.set_game_count(games.size()); - result.set_player_count(userList.size()); + result.set_game_count(games.size() + externalGames.size()); + result.set_player_count(userList.size() + externalUsers.size()); if (!updating) { result.set_name(name.toStdString()); @@ -51,9 +52,19 @@ ServerInfo_Room Server_Room::getInfo(bool complete, bool showGameTypes, bool upd QMapIterator gameIterator(games); while (gameIterator.hasNext()) result.add_game_list()->CopyFrom(gameIterator.next().value()->getInfo()); + if (includeExternalData) { + QMapIterator externalGameIterator(externalGames); + while (externalGameIterator.hasNext()) + result.add_game_list()->CopyFrom(externalGameIterator.next().value()); + } for (int i = 0; i < userList.size(); ++i) result.add_user_list()->CopyFrom(userList[i]->copyUserInfo(false)); + if (includeExternalData) { + QMapIterator externalUserIterator(externalUsers); + while (externalUserIterator.hasNext()) + result.add_user_list()->CopyFrom(externalUserIterator.next().value().copyUserInfo(false)); + } } if (complete || showGameTypes) for (int i = 0; i < gameTypes.size(); ++i) { @@ -83,7 +94,7 @@ void Server_Room::addClient(Server_ProtocolHandler *client) userList.append(client); roomMutex.unlock(); - emit roomInfoChanged(); + emit roomInfoChanged(getInfo(false, false, true)); } void Server_Room::removeClient(Server_ProtocolHandler *client) @@ -96,7 +107,34 @@ void Server_Room::removeClient(Server_ProtocolHandler *client) event.set_name(client->getUserInfo()->name()); sendRoomEvent(prepareRoomEvent(event)); - emit roomInfoChanged(); + emit roomInfoChanged(getInfo(false, false, true)); +} + +void Server_Room::addExternalUser(const ServerInfo_User &userInfo) +{ + ServerInfo_User_Container userInfoContainer(userInfo); + Event_JoinRoom event; + event.mutable_user_info()->CopyFrom(userInfoContainer.copyUserInfo(false)); + sendRoomEvent(prepareRoomEvent(event), false); + + roomMutex.lock(); + externalUsers.insert(QString::fromStdString(userInfo.name()), userInfoContainer); + roomMutex.unlock(); + + emit roomInfoChanged(getInfo(false, false, true)); +} + +void Server_Room::removeExternalUser(const QString &name) +{ + roomMutex.lock(); + externalUsers.remove(name); + roomMutex.unlock(); + + Event_LeaveRoom event; + event.set_name(name.toStdString()); + sendRoomEvent(prepareRoomEvent(event), false); + + emit roomInfoChanged(getInfo(false, false, true)); } void Server_Room::say(Server_ProtocolHandler *client, const QString &s) @@ -107,39 +145,34 @@ void Server_Room::say(Server_ProtocolHandler *client, const QString &s) sendRoomEvent(prepareRoomEvent(event)); } -void Server_Room::sendRoomEvent(RoomEvent *event) +void Server_Room::sendRoomEvent(RoomEvent *event, bool sendToIsl) { - QMutexLocker locker(&roomMutex); - + roomMutex.lock(); for (int i = 0; i < userList.size(); ++i) userList[i]->sendProtocolItem(*event); + roomMutex.unlock(); + + if (sendToIsl) + static_cast(parent())->sendIslMessage(*event); + delete event; } -void Server_Room::broadcastGameListUpdate(Server_Game *game) +void Server_Room::broadcastGameListUpdate(ServerInfo_Game gameInfo) { - QMutexLocker locker(&roomMutex); - Event_ListGames event; - event.add_game_list()->CopyFrom(game->getInfo()); + event.add_game_list()->CopyFrom(gameInfo); sendRoomEvent(prepareRoomEvent(event)); } -Server_Game *Server_Room::createGame(const QString &description, const QString &password, int maxPlayers, const QList &gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator) +void Server_Room::addGame(Server_Game *game) { - QMutexLocker locker(&roomMutex); + // Lock roomMutex and gameMutex before calling this - Server_Game *newGame = new Server_Game(creator, static_cast(parent())->getNextGameId(), description, password, maxPlayers, gameTypes, onlyBuddies, onlyRegistered, spectatorsAllowed, spectatorsNeedPassword, spectatorsCanTalk, spectatorsSeeEverything, this); - newGame->moveToThread(thread()); - // This mutex needs to be unlocked by the caller. - newGame->gameMutex.lock(); - games.insert(newGame->getGameId(), newGame); - - broadcastGameListUpdate(newGame); - - emit roomInfoChanged(); - - return newGame; + connect(game, SIGNAL(gameInfoChanged(ServerInfo_Game)), this, SLOT(broadcastGameListUpdate(ServerInfo_Game))); + games.insert(game->getGameId(), game); + emit gameListChanged(game->getInfo()); + emit roomInfoChanged(getInfo(false, false, true)); } void Server_Room::removeGame(Server_Game *game) @@ -147,10 +180,11 @@ void Server_Room::removeGame(Server_Game *game) // No need to lock roomMutex or gameMutex. This method is only // called from ~Server_Game, which locks both mutexes anyway beforehand. - broadcastGameListUpdate(game); + disconnect(game, 0, this, 0); + emit gameListChanged(game->getInfo()); games.remove(game->getGameId()); - emit roomInfoChanged(); + emit roomInfoChanged(getInfo(false, false, true)); } int Server_Room::getGamesCreatedByUser(const QString &userName) const diff --git a/common/server_room.h b/common/server_room.h index 9ded049c..47e307cb 100644 --- a/common/server_room.h +++ b/common/server_room.h @@ -6,7 +6,9 @@ #include #include #include +#include #include "pb/serverinfo_room.pb.h" +#include "serverinfo_user_container.h" class Server_ProtocolHandler; class RoomEvent; @@ -19,7 +21,8 @@ class Server; class Server_Room : public QObject { Q_OBJECT signals: - void roomInfoChanged(); + void roomInfoChanged(ServerInfo_Room roomInfo); + void gameListChanged(ServerInfo_Game gameInfo); private: int id; QString name; @@ -28,7 +31,11 @@ private: QString joinMessage; QStringList gameTypes; QMap games; + QMap externalGames; QList userList; + QMap externalUsers; +private slots: + void broadcastGameListUpdate(ServerInfo_Game gameInfo); 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,19 +48,26 @@ public: const QStringList &getGameTypes() const { return gameTypes; } const QMap &getGames() const { return games; } Server *getServer() const; - ServerInfo_Room getInfo(bool complete, bool showGameTypes = false, bool updating = false) const; + ServerInfo_Room getInfo(bool complete, bool showGameTypes = false, bool updating = false, bool includeExternalData = true) const; int getGamesCreatedByUser(const QString &name) const; QList getGamesOfUser(const QString &name) const; void addClient(Server_ProtocolHandler *client); void removeClient(Server_ProtocolHandler *client); + + void addExternalUser(const ServerInfo_User &userInfo); + void removeExternalUser(const QString &name); + 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 &_gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator); + + void addGame(Server_Game *game); void removeGame(Server_Game *game); - void sendRoomEvent(RoomEvent *event); + void sendRoomEvent(RoomEvent *event, bool sendToIsl = true); RoomEvent *prepareRoomEvent(const ::google::protobuf::Message &roomEvent); }; +Q_DECLARE_METATYPE(ServerInfo_Game) +Q_DECLARE_METATYPE(ServerInfo_Room) + #endif diff --git a/servatrice/src/isl_interface.cpp b/servatrice/src/isl_interface.cpp index c4aa1a92..d62d9f58 100644 --- a/servatrice/src/isl_interface.cpp +++ b/servatrice/src/isl_interface.cpp @@ -107,7 +107,7 @@ void IslInterface::initServer() while (roomIterator.hasNext()) { Server_Room *room = roomIterator.next().value(); room->roomMutex.lock(); - event.add_room_list()->CopyFrom(room->getInfo(true, true, false)); + event.add_room_list()->CopyFrom(room->getInfo(true, true, false, false)); } IslMessage message; diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index be0c5eee..adcfb65a 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -856,6 +856,7 @@ void Servatrice::addIslInterface(int serverId, IslInterface *interface) islInterfaces.insert(serverId, interface); connect(interface, SIGNAL(externalUserJoined(ServerInfo_User)), this, SLOT(externalUserJoined(ServerInfo_User))); connect(interface, SIGNAL(externalUserLeft(QString)), this, SLOT(externalUserLeft(QString))); + connect(interface, SIGNAL(externalRoomUpdated(ServerInfo_Room)), this, SLOT(externalRoomUpdated(const ServerInfo_Room &))); } void Servatrice::removeIslInterface(int serverId)