diff --git a/common/server.cpp b/common/server.cpp index d271f695..72eeaec0 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -186,6 +186,17 @@ QList Server::getPersistentPlayerReferences(const QString &user return persistentPlayers.values(userName); } +Server_AbstractUserInterface *Server::findUser(const QString &userName) const +{ + // Call this only with clientsLock set. + + Server_AbstractUserInterface *userHandler = users.value(userName); + if (userHandler) + return userHandler; + else + return externalUsers.value(userName); +} + void Server::addClient(Server_ProtocolHandler *client) { QWriteLocker locker(&clientsLock); diff --git a/common/server.h b/common/server.h index 8265c7d2..78b19c2a 100644 --- a/common/server.h +++ b/common/server.h @@ -46,6 +46,7 @@ public: AuthenticationResult loginUser(Server_ProtocolHandler *session, QString &name, const QString &password, QString &reason, int &secondsLeft); const QMap &getRooms() { return rooms; } + Server_AbstractUserInterface *findUser(const QString &userName) const; const QMap &getUsers() const { return users; } const QMap &getUsersBySessionId() const { return usersBySessionId; } void addClient(Server_ProtocolHandler *player); @@ -63,7 +64,6 @@ public: Server_DatabaseInterface *getDatabaseInterface() const; int getNextLocalGameId() { QMutexLocker locker(&nextLocalGameIdMutex); return ++nextLocalGameId; } - virtual void storeGameInformation(int secondsElapsed, const QSet &allPlayersEver, const QSet &allSpectatorsEver, const QList &replays) { } void sendIsl_Response(const Response &item, int serverId = -1, qint64 sessionId = -1); void sendIsl_SessionEvent(const SessionEvent &item, int serverId = -1, qint64 sessionId = -1); diff --git a/common/server_game.cpp b/common/server_game.cpp index 2577cf13..e2694d23 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -42,6 +42,7 @@ #include "pb/event_set_active_phase.pb.h" #include "pb/serverinfo_playerping.pb.h" #include "pb/game_replay.pb.h" +#include "pb/event_replay_added.pb.h" #include #include #include @@ -110,7 +111,7 @@ Server_Game::~Server_Game() currentReplay->set_duration_seconds(secondsElapsed - startTimeOfThisGame); replayList.append(currentReplay); - room->getServer()->storeGameInformation(secondsElapsed, allPlayersEver, allSpectatorsEver, replayList); + storeGameInformation(); for (int i = 0; i < replayList.size(); ++i) delete replayList[i]; @@ -118,6 +119,51 @@ Server_Game::~Server_Game() qDebug() << "Server_Game destructor: gameId=" << gameId; } +void Server_Game::storeGameInformation() +{ + const ServerInfo_Game &gameInfo = replayList.first()->game_info(); + + Event_ReplayAdded replayEvent; + ServerInfo_ReplayMatch *replayMatchInfo = replayEvent.mutable_match_info(); + replayMatchInfo->set_game_id(gameInfo.game_id()); + replayMatchInfo->set_room_name(room->getName().toStdString()); + replayMatchInfo->set_time_started(QDateTime::currentDateTime().addSecs(-secondsElapsed).toTime_t()); + replayMatchInfo->set_length(secondsElapsed); + replayMatchInfo->set_game_name(gameInfo.description()); + + const QStringList &allGameTypes = room->getGameTypes(); + QStringList gameTypes; + for (int i = gameInfo.game_types_size() - 1; i >= 0; --i) + gameTypes.append(allGameTypes[gameInfo.game_types(i)]); + + QSetIterator playerIterator(allPlayersEver); + while (playerIterator.hasNext()) + replayMatchInfo->add_player_names(playerIterator.next().toStdString()); + + for (int i = 0; i < replayList.size(); ++i) { + ServerInfo_Replay *replayInfo = replayMatchInfo->add_replay_list(); + replayInfo->set_replay_id(replayList[i]->replay_id()); + replayInfo->set_replay_name(gameInfo.description()); + replayInfo->set_duration(replayList[i]->duration_seconds()); + } + + QSet allUsersInGame = allPlayersEver + allSpectatorsEver; + QSetIterator allUsersIterator(allUsersInGame); + + SessionEvent *sessionEvent = Server_ProtocolHandler::prepareSessionEvent(replayEvent); + Server *server = room->getServer(); + server->clientsLock.lockForRead(); + while (allUsersIterator.hasNext()) { + Server_AbstractUserInterface *userHandler = server->findUser(allUsersIterator.next()); + if (userHandler) + userHandler->sendProtocolItem(*sessionEvent); + } + server->clientsLock.unlock(); + delete sessionEvent; + + server->getDatabaseInterface()->storeGameInformation(room->getName(), gameTypes, gameInfo, allPlayersEver, allSpectatorsEver, replayList); +} + void Server_Game::pingClockTimeout() { QMutexLocker locker(&gameMutex); diff --git a/common/server_game.h b/common/server_game.h index 829d60a8..f6ddbf92 100644 --- a/common/server_game.h +++ b/common/server_game.h @@ -73,6 +73,7 @@ private: void createGameStateChangedEvent(Event_GameStateChanged *event, Server_Player *playerWhosAsking, bool omniscient, bool withUserInfo); void sendGameStateToPlayers(); + void storeGameInformation(); signals: void sigStartGameIfReady(); void gameInfoChanged(ServerInfo_Game gameInfo); diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 5c779e50..a067fb3d 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -375,12 +375,9 @@ Response::ResponseCode Server_ProtocolHandler::cmdMessage(const Command_Message QReadLocker locker(&server->clientsLock); QString receiver = QString::fromStdString(cmd.user_name()); - Server_AbstractUserInterface *userInterface = server->getUsers().value(receiver); - if (!userInterface) { - userInterface = server->getExternalUsers().value(receiver); - if (!userInterface) - return Response::RespNameNotFound; - } + Server_AbstractUserInterface *userInterface = server->findUser(receiver); + if (!userInterface) + return Response::RespNameNotFound; if (databaseInterface->isInIgnoreList(receiver, QString::fromStdString(userInfo->name()))) return Response::RespInIgnoreList; @@ -401,13 +398,8 @@ Response::ResponseCode Server_ProtocolHandler::cmdGetGamesOfUser(const Command_G if (authState == NotLoggedIn) return Response::RespLoginNeeded; - // XXX This does not take external users into account. - // XXX Maybe remove this check and test if the result list is empty at the end. - { - QReadLocker clientsLocker(&server->clientsLock); - if (!server->getUsers().contains(QString::fromStdString(cmd.user_name()))) - return Response::RespNameNotFound; - } + // We don't need to check whether the user is logged in; persistent games should also work. + // The client needs to deal with an empty result list. Response_GetGamesOfUser *re = new Response_GetGamesOfUser; server->roomsLock.lockForRead(); @@ -440,12 +432,8 @@ Response::ResponseCode Server_ProtocolHandler::cmdGetUserInfo(const Command_GetU QReadLocker locker(&server->clientsLock); - ServerInfo_User_Container *infoSource; - if (server->getUsers().contains(userName)) - infoSource = server->getUsers().value(userName); - else if (server->getExternalUsers().contains(userName)) - infoSource = server->getExternalUsers().value(userName); - else + ServerInfo_User_Container *infoSource = server->findUser(userName); + if (!infoSource) return Response::RespNameNotFound; re->mutable_user_info()->CopyFrom(infoSource->copyUserInfo(true, false, userInfo->user_level() & ServerInfo_User::IsModerator)); diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 2207cf9c..cc8a95c9 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -33,8 +33,6 @@ #include "server_logger.h" #include "main.h" #include "decklist.h" -#include "pb/game_replay.pb.h" -#include "pb/event_replay_added.pb.h" #include "pb/event_server_message.pb.h" #include "pb/event_server_shutdown.pb.h" #include "pb/event_connection_closed.pb.h" @@ -355,55 +353,6 @@ QList Servatrice::getUsersWithAddressAsList(const QHost return result; } -void Servatrice::storeGameInformation(int secondsElapsed, const QSet &allPlayersEver, const QSet &allSpectatorsEver, const QList &replayList) -{ - const ServerInfo_Game &gameInfo = replayList.first()->game_info(); - - Server_Room *room = rooms.value(gameInfo.room_id()); - - Event_ReplayAdded replayEvent; - ServerInfo_ReplayMatch *replayMatchInfo = replayEvent.mutable_match_info(); - replayMatchInfo->set_game_id(gameInfo.game_id()); - replayMatchInfo->set_room_name(room->getName().toStdString()); - replayMatchInfo->set_time_started(QDateTime::currentDateTime().addSecs(-secondsElapsed).toTime_t()); - replayMatchInfo->set_length(secondsElapsed); - replayMatchInfo->set_game_name(gameInfo.description()); - - const QStringList &allGameTypes = room->getGameTypes(); - QStringList gameTypes; - for (int i = gameInfo.game_types_size() - 1; i >= 0; --i) - gameTypes.append(allGameTypes[gameInfo.game_types(i)]); - - QSetIterator playerIterator(allPlayersEver); - while (playerIterator.hasNext()) - replayMatchInfo->add_player_names(playerIterator.next().toStdString()); - - for (int i = 0; i < replayList.size(); ++i) { - ServerInfo_Replay *replayInfo = replayMatchInfo->add_replay_list(); - replayInfo->set_replay_id(replayList[i]->replay_id()); - replayInfo->set_replay_name(gameInfo.description()); - replayInfo->set_duration(replayList[i]->duration_seconds()); - } - - QSet allUsersInGame = allPlayersEver + allSpectatorsEver; - QSetIterator allUsersIterator(allUsersInGame); - - SessionEvent *sessionEvent = Server_ProtocolHandler::prepareSessionEvent(replayEvent); - clientsLock.lockForRead(); - while (allUsersIterator.hasNext()) { - const QString userName = allUsersIterator.next(); - Server_AbstractUserInterface *userHandler = users.value(userName); - if (!userHandler) - userHandler = externalUsers.value(userName); - if (userHandler) - userHandler->sendProtocolItem(*sessionEvent); - } - clientsLock.unlock(); - delete sessionEvent; - - getDatabaseInterface()->storeGameInformation(room->getName(), gameTypes, gameInfo, allPlayersEver, allSpectatorsEver, replayList); -} - void Servatrice::updateLoginMessage() { if (!servatriceDatabaseInterface->checkSql()) diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index 70acb96d..fbfac035 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -122,6 +122,7 @@ private: QMap islInterfaces; public slots: void scheduleShutdown(const QString &reason, int minutes); + void updateLoginMessage(); public: Servatrice(QSettings *_settings, QObject *parent = 0); ~Servatrice(); @@ -139,12 +140,10 @@ public: AuthenticationMethod getAuthenticationMethod() const { return authenticationMethod; } QString getDbPrefix() const { return dbPrefix; } int getServerId() const { return serverId; } - void updateLoginMessage(); int getUsersWithAddress(const QHostAddress &address) const; QList getUsersWithAddressAsList(const QHostAddress &address) const; void incTxBytes(quint64 num); void incRxBytes(quint64 num); - void storeGameInformation(int secondsElapsed, const QSet &allPlayersEver, const QSet &allSpectatorsEver, const QList &replays); void addDatabaseInterface(QThread *thread, Servatrice_DatabaseInterface *databaseInterface); bool islConnectionExists(int serverId) const; diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index 6a4897fe..db27a563 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -739,7 +739,7 @@ Response::ResponseCode ServerSocketInterface::cmdBanFromServer(const Command_Ban Response::ResponseCode ServerSocketInterface::cmdUpdateServerMessage(const Command_UpdateServerMessage & /*cmd*/, ResponseContainer & /*rc*/) { - servatrice->updateLoginMessage(); + QMetaObject::invokeMethod(server, "updateLoginMessage"); return Response::RespOk; }