diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index afdd8588..992c24e2 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -8,13 +8,16 @@ SET(common_SOURCES rng_qt.cpp rng_sfmt.cpp server.cpp + server_abstractuserinterface.cpp server_card.cpp server_cardzone.cpp server_game.cpp server_player.cpp server_protocolhandler.cpp + server_remoteuserinterface.cpp server_response_containers.cpp server_room.cpp + serverinfo_user_container.cpp sfmt/SFMT.c ) SET(common_HEADERS diff --git a/common/pb/serverinfo_user.proto b/common/pb/serverinfo_user.proto index b24f7e55..2dcc58bb 100644 --- a/common/pb/serverinfo_user.proto +++ b/common/pb/serverinfo_user.proto @@ -19,4 +19,5 @@ message ServerInfo_User { optional string country = 6; optional bytes avatar_bmp = 7; optional sint32 id = 8 [default = -1]; + optional sint32 server_id = 9 [default = -1]; } diff --git a/common/server.cpp b/common/server.cpp index 090e0344..bcb41734 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -22,6 +22,7 @@ #include "server_counter.h" #include "server_room.h" #include "server_protocolhandler.h" +#include "server_remoteuserinterface.h" #include "pb/event_user_joined.pb.h" #include "pb/event_user_left.pb.h" #include "pb/event_list_rooms.pb.h" @@ -100,7 +101,7 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString for (int i = 0; i < clients.size(); ++i) if (clients[i]->getAcceptsUserListChanges()) clients[i]->sendProtocolItem(*se); - serverMutex.unlock(); + locker.unlock(); sendIslMessage(*se); delete se; @@ -139,6 +140,36 @@ void Server::removeClient(Server_ProtocolHandler *client) qDebug() << "Server::removeClient:" << clients.size() << "clients; " << users.size() << "users left"; } +void Server::externalUserJoined(ServerInfo_User userInfo) +{ + // This function is always called from the main thread via signal/slot. + QMutexLocker locker(&serverMutex); + + externalUsers.insert(QString::fromStdString(userInfo.name()), new Server_RemoteUserInterface(this, ServerInfo_User_Container(userInfo))); + + Event_UserJoined event; + event.mutable_user_info()->CopyFrom(userInfo); + SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event); + for (int i = 0; i < clients.size(); ++i) + if (clients[i]->getAcceptsUserListChanges()) + clients[i]->sendProtocolItem(*se); +} + +void Server::externalUserLeft(QString userName) +{ + // This function is always called from the main thread via signal/slot. + QMutexLocker locker(&serverMutex); + + delete externalUsers.take(userName); + + Event_UserLeft event; + event.set_name(userName.toStdString()); + SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event); + for (int i = 0; i < clients.size(); ++i) + if (clients[i]->getAcceptsUserListChanges()) + clients[i]->sendProtocolItem(*se); +} + void Server::broadcastRoomUpdate() { QMutexLocker locker(&serverMutex); @@ -184,6 +215,15 @@ int Server::getGamesCount() const return result; } +void Server::sendIslMessage(const Response &item, int serverId) +{ + IslMessage msg; + msg.set_message_type(IslMessage::RESPONSE); + msg.mutable_response()->CopyFrom(item); + + doSendIslMessage(msg, serverId); +} + void Server::sendIslMessage(const SessionEvent &item, int serverId) { IslMessage msg; @@ -192,3 +232,21 @@ void Server::sendIslMessage(const SessionEvent &item, int serverId) doSendIslMessage(msg, serverId); } + +void Server::sendIslMessage(const GameEventContainer &item, int serverId) +{ + IslMessage msg; + msg.set_message_type(IslMessage::GAME_EVENT_CONTAINER); + msg.mutable_game_event_container()->CopyFrom(item); + + doSendIslMessage(msg, serverId); +} + +void Server::sendIslMessage(const RoomEvent &item, int serverId) +{ + IslMessage msg; + msg.set_message_type(IslMessage::ROOM_EVENT); + msg.mutable_room_event()->CopyFrom(item); + + doSendIslMessage(msg, serverId); +} diff --git a/common/server.h b/common/server.h index c9375679..b9d84288 100644 --- a/common/server.h +++ b/common/server.h @@ -10,9 +10,13 @@ class Server_Game; class Server_Room; class Server_ProtocolHandler; +class Server_AbstractUserInterface; class GameReplay; class IslMessage; +class Response; class SessionEvent; +class GameEventContainer; +class RoomEvent; enum AuthenticationResult { NotLoggedIn = 0, PasswordRight = 1, UnknownUser = 2, WouldOverwriteOldSession = 3, UserIsBanned = 4 }; @@ -53,11 +57,22 @@ public: virtual void storeGameInformation(int secondsElapsed, const QSet &allPlayersEver, const QSet &allSpectatorsEver, const QList &replays) { } + void sendIslMessage(const Response &item, int serverId = -1); void sendIslMessage(const SessionEvent &item, int serverId = -1); + void sendIslMessage(const GameEventContainer &item, int serverId = -1); + void sendIslMessage(const RoomEvent &item, int serverId = -1); + + void addExternalUser(const ServerInfo_User &userInfo); + void removeExternalUser(const QString &userName); + const QMap &getExternalUsers() const { return externalUsers; } +protected slots: + void externalUserJoined(ServerInfo_User userInfo); + void externalUserLeft(QString userName); protected: void prepareDestroy(); QList clients; QMap users; + QMap externalUsers; QMap rooms; virtual int startSession(const QString &userName, const QString &address) { return -1; } diff --git a/common/server_abstractuserinterface.cpp b/common/server_abstractuserinterface.cpp new file mode 100644 index 00000000..30814950 --- /dev/null +++ b/common/server_abstractuserinterface.cpp @@ -0,0 +1,19 @@ +#include "server_abstractuserinterface.h" +#include + +void Server_AbstractUserInterface::sendProtocolItemByType(ServerMessage::MessageType type, const ::google::protobuf::Message &item) +{ + switch (type) { + case ServerMessage::RESPONSE: sendProtocolItem(static_cast(item)); break; + case ServerMessage::SESSION_EVENT: sendProtocolItem(static_cast(item)); break; + case ServerMessage::GAME_EVENT_CONTAINER: sendProtocolItem(static_cast(item)); break; + case ServerMessage::ROOM_EVENT: sendProtocolItem(static_cast(item)); break; + } +} + +SessionEvent *Server_AbstractUserInterface::prepareSessionEvent(const ::google::protobuf::Message &sessionEvent) +{ + SessionEvent *event = new SessionEvent; + event->GetReflection()->MutableMessage(event, sessionEvent.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(sessionEvent); + return event; +} diff --git a/common/server_abstractuserinterface.h b/common/server_abstractuserinterface.h new file mode 100644 index 00000000..6c6e3e23 --- /dev/null +++ b/common/server_abstractuserinterface.h @@ -0,0 +1,31 @@ +#ifndef SERVER_ABSTRACTUSERINTERFACE +#define SERVER_ABSTRACTUSERINTERFACE + +#include "serverinfo_user_container.h" +#include "pb/server_message.pb.h" + +class Response; +class SessionEvent; +class GameEventContainer; +class RoomEvent; + +class Server; + +class Server_AbstractUserInterface : public ServerInfo_User_Container { +protected: + Server *server; +public: + Server_AbstractUserInterface(Server *_server) : server(_server) { } + Server_AbstractUserInterface(Server *_server, const ServerInfo_User_Container &other) : ServerInfo_User_Container(other), server(_server) { } + virtual ~Server_AbstractUserInterface() { } + + virtual void sendProtocolItem(const Response &item) = 0; + virtual void sendProtocolItem(const SessionEvent &item) = 0; + virtual void sendProtocolItem(const GameEventContainer &item) = 0; + virtual void sendProtocolItem(const RoomEvent &item) = 0; + void sendProtocolItemByType(ServerMessage::MessageType type, const ::google::protobuf::Message &item); + + static SessionEvent *prepareSessionEvent(const ::google::protobuf::Message &sessionEvent); +}; + +#endif diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 0c950786..f78f2ce4 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -9,6 +9,7 @@ #include "server_game.h" #include "server_player.h" #include "decklist.h" +#include "get_pb_extension.h" #include #include "pb/serverinfo_zone.pb.h" #include "pb/commands.pb.h" @@ -88,7 +89,7 @@ #include Server_ProtocolHandler::Server_ProtocolHandler(Server *_server, QObject *parent) - : QObject(parent), server(_server), authState(NotLoggedIn), acceptsUserListChanges(false), acceptsRoomListChanges(false), userInfo(0), sessionId(-1), timeRunning(0), lastDataReceived(0), gameListMutex(QMutex::Recursive) + : QObject(parent), Server_AbstractUserInterface(_server), authState(NotLoggedIn), acceptsUserListChanges(false), acceptsRoomListChanges(false), sessionId(-1), timeRunning(0), lastDataReceived(0), gameListMutex(QMutex::Recursive) { connect(server, SIGNAL(pingClockTimeout()), this, SLOT(pingClockTimeout())); } @@ -126,29 +127,6 @@ void Server_ProtocolHandler::prepareDestroy() g->gameMutex.unlock(); } gameListMutex.unlock(); - - delete userInfo; -} - -void Server_ProtocolHandler::setUserInfo(const ServerInfo_User &_userInfo) -{ - userInfo = new ServerInfo_User; - userInfo->CopyFrom(_userInfo); -} - -ServerInfo_User Server_ProtocolHandler::copyUserInfo(bool complete, bool moderatorInfo) const -{ - ServerInfo_User result; - if (userInfo) { - result.CopyFrom(*userInfo); - if (!moderatorInfo) { - result.clear_address(); - result.clear_id(); - } - if (!complete) - result.clear_avatar_bmp(); - } - return result; } void Server_ProtocolHandler::playerRemovedFromGame(Server_Game *game) @@ -195,37 +173,13 @@ void Server_ProtocolHandler::sendProtocolItem(const RoomEvent &item) transmitProtocolItem(msg); } -void Server_ProtocolHandler::sendProtocolItem(ServerMessage::MessageType type, const ::google::protobuf::Message &item) -{ - switch (type) { - case ServerMessage::RESPONSE: sendProtocolItem(static_cast(item)); break; - case ServerMessage::SESSION_EVENT: sendProtocolItem(static_cast(item)); break; - case ServerMessage::GAME_EVENT_CONTAINER: sendProtocolItem(static_cast(item)); break; - case ServerMessage::ROOM_EVENT: sendProtocolItem(static_cast(item)); break; - } -} - -SessionEvent *Server_ProtocolHandler::prepareSessionEvent(const ::google::protobuf::Message &sessionEvent) -{ - SessionEvent *event = new SessionEvent; - event->GetReflection()->MutableMessage(event, sessionEvent.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(sessionEvent); - return event; -} - Response::ResponseCode Server_ProtocolHandler::processSessionCommandContainer(const CommandContainer &cont, ResponseContainer &rc) { Response::ResponseCode finalResponseCode = Response::RespOk; for (int i = cont.session_command_size() - 1; i >= 0; --i) { Response::ResponseCode resp = Response::RespInvalidCommand; const SessionCommand &sc = cont.session_command(i); - std::vector< const ::google::protobuf::FieldDescriptor * > fieldList; - sc.GetReflection()->ListFields(sc, &fieldList); - int num = 0; - for (unsigned int j = 0; j < fieldList.size(); ++j) - if (fieldList[j]->is_extension()) { - num = fieldList[j]->number(); - break; - } + const int num = getPbExtension(sc); if (num != SessionCommand::PING) emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this); switch ((SessionCommand::SessionCommandType) num) { @@ -270,14 +224,7 @@ Response::ResponseCode Server_ProtocolHandler::processRoomCommandContainer(const for (int i = cont.room_command_size() - 1; i >= 0; --i) { Response::ResponseCode resp = Response::RespInvalidCommand; const RoomCommand &sc = cont.room_command(i); - std::vector< const ::google::protobuf::FieldDescriptor * > fieldList; - sc.GetReflection()->ListFields(sc, &fieldList); - int num = 0; - for (unsigned int j = 0; j < fieldList.size(); ++j) - if (fieldList[j]->is_extension()) { - num = fieldList[j]->number(); - break; - } + const int num = getPbExtension(sc); emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this); switch ((RoomCommand::RoomCommandType) num) { case RoomCommand::LEAVE_ROOM: resp = cmdLeaveRoom(sc.GetExtension(Command_LeaveRoom::ext), room, rc); break; @@ -313,14 +260,7 @@ Response::ResponseCode Server_ProtocolHandler::processGameCommandContainer(const for (int i = cont.game_command_size() - 1; i >= 0; --i) { Response::ResponseCode resp = Response::RespInvalidCommand; const GameCommand &sc = cont.game_command(i); - std::vector< const ::google::protobuf::FieldDescriptor * > fieldList; - sc.GetReflection()->ListFields(sc, &fieldList); - int num = 0; - for (unsigned int j = 0; j < fieldList.size(); ++j) - if (fieldList[j]->is_extension()) { - num = fieldList[j]->number(); - break; - } + const int num = getPbExtension(sc); emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this); switch ((GameCommand::GameCommandType) num) { case GameCommand::KICK_FROM_GAME: resp = cmdKickFromGame(sc.GetExtension(Command_KickFromGame::ext), game, player, rc, ges); break; @@ -372,14 +312,7 @@ Response::ResponseCode Server_ProtocolHandler::processModeratorCommandContainer( for (int i = cont.moderator_command_size() - 1; i >= 0; --i) { Response::ResponseCode resp = Response::RespInvalidCommand; const ModeratorCommand &sc = cont.moderator_command(i); - std::vector< const ::google::protobuf::FieldDescriptor * > fieldList; - sc.GetReflection()->ListFields(sc, &fieldList); - int num = 0; - for (unsigned int j = 0; j < fieldList.size(); ++j) - if (fieldList[j]->is_extension()) { - num = fieldList[j]->number(); - break; - } + const int num = getPbExtension(sc); emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this); switch ((ModeratorCommand::ModeratorCommandType) num) { case ModeratorCommand::BAN_FROM_SERVER: resp = cmdBanFromServer(sc.GetExtension(Command_BanFromServer::ext), rc); break; @@ -401,14 +334,7 @@ Response::ResponseCode Server_ProtocolHandler::processAdminCommandContainer(cons for (int i = cont.admin_command_size() - 1; i >= 0; --i) { Response::ResponseCode resp = Response::RespInvalidCommand; const AdminCommand &sc = cont.admin_command(i); - std::vector< const ::google::protobuf::FieldDescriptor * > fieldList; - sc.GetReflection()->ListFields(sc, &fieldList); - int num = 0; - for (unsigned int j = 0; j < fieldList.size(); ++j) - if (fieldList[j]->is_extension()) { - num = fieldList[j]->number(); - break; - } + const int num = getPbExtension(sc); emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this); switch ((AdminCommand::AdminCommandType) num) { case AdminCommand::SHUTDOWN_SERVER: resp = cmdShutdownServer(sc.GetExtension(Command_ShutdownServer::ext), rc); break; @@ -442,7 +368,7 @@ void Server_ProtocolHandler::processCommandContainer(const CommandContainer &con const QList > &preResponseQueue = responseContainer.getPreResponseQueue(); for (int i = 0; i < preResponseQueue.size(); ++i) - sendProtocolItem(preResponseQueue[i].first, *preResponseQueue[i].second); + sendProtocolItemByType(preResponseQueue[i].first, *preResponseQueue[i].second); Response response; response.set_cmd_id(cont.cmd_id()); @@ -454,7 +380,7 @@ void Server_ProtocolHandler::processCommandContainer(const CommandContainer &con const QList > &postResponseQueue = responseContainer.getPostResponseQueue(); for (int i = 0; i < postResponseQueue.size(); ++i) - sendProtocolItem(postResponseQueue[i].first, *postResponseQueue[i].second); + sendProtocolItemByType(postResponseQueue[i].first, *postResponseQueue[i].second); } void Server_ProtocolHandler::pingClockTimeout() @@ -577,11 +503,15 @@ Response::ResponseCode Server_ProtocolHandler::cmdMessage(const Command_Message if (authState == NotLoggedIn) return Response::RespLoginNeeded; - server->serverMutex.lock(); + QMutexLocker locker(&server->serverMutex); + QString receiver = QString::fromStdString(cmd.user_name()); - Server_ProtocolHandler *userHandler = server->getUsers().value(receiver); - if (!userHandler) - return Response::RespNameNotFound; + Server_AbstractUserInterface *userInterface = server->getUsers().value(receiver); + if (!userInterface) { + userInterface = server->getExternalUsers().value(receiver); + if (!userInterface) + return Response::RespNameNotFound; + } if (server->isInIgnoreList(receiver, QString::fromStdString(userInfo->name()))) return Response::RespInIgnoreList; @@ -591,9 +521,8 @@ Response::ResponseCode Server_ProtocolHandler::cmdMessage(const Command_Message event.set_message(cmd.message()); SessionEvent *se = prepareSessionEvent(event); - userHandler->sendProtocolItem(*se); + userInterface->sendProtocolItem(*se); rc.enqueuePreResponseItem(ServerMessage::SESSION_EVENT, se); - server->serverMutex.unlock(); return Response::RespOk; } @@ -634,12 +563,18 @@ Response::ResponseCode Server_ProtocolHandler::cmdGetUserInfo(const Command_GetU if (userName.isEmpty()) re->mutable_user_info()->CopyFrom(*userInfo); else { - server->serverMutex.lock(); - Server_ProtocolHandler *handler = server->getUsers().value(userName); - if (!handler) + + QMutexLocker locker(&server->serverMutex); + + 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 return Response::RespNameNotFound; - re->mutable_user_info()->CopyFrom(handler->copyUserInfo(true, userInfo->user_level() & ServerInfo_User::IsModerator)); - server->serverMutex.unlock(); + + re->mutable_user_info()->CopyFrom(infoSource->copyUserInfo(true, userInfo->user_level() & ServerInfo_User::IsModerator)); } rc.setResponseExtension(re); @@ -699,6 +634,9 @@ Response::ResponseCode Server_ProtocolHandler::cmdListUsers(const Command_ListUs QMapIterator userIterator = server->getUsers(); while (userIterator.hasNext()) re->add_user_list()->CopyFrom(userIterator.next().value()->copyUserInfo(false)); + QMapIterator extIterator = server->getExternalUsers(); + while (extIterator.hasNext()) + re->add_user_list()->CopyFrom(extIterator.next().value()->copyUserInfo(false)); server->serverMutex.unlock(); acceptsUserListChanges = true; @@ -747,7 +685,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdCreateGame(const Command_Creat return Response::RespLoginNeeded; if (server->getMaxGamesPerUser() > 0) - if (room->getGamesCreatedByUser(getUserName()) >= server->getMaxGamesPerUser()) + if (room->getGamesCreatedByUser(QString::fromStdString(userInfo->name())) >= server->getMaxGamesPerUser()) return Response::RespContextError; QList gameTypes; diff --git a/common/server_protocolhandler.h b/common/server_protocolhandler.h index 152dd455..0ea586a5 100644 --- a/common/server_protocolhandler.h +++ b/common/server_protocolhandler.h @@ -4,6 +4,7 @@ #include #include #include "server.h" +#include "server_abstractuserinterface.h" #include "pb/response.pb.h" #include "pb/server_message.pb.h" @@ -84,25 +85,21 @@ class Command_BanFromServer; class Command_UpdateServerMessage; class Command_ShutdownServer; -class Server_ProtocolHandler : public QObject { +class Server_ProtocolHandler : public QObject, public Server_AbstractUserInterface { Q_OBJECT protected: - Server *server; QMap > games; QMap rooms; - Server *getServer() const { return server; } QPair getGame(int gameId) const; AuthenticationResult authState; bool acceptsUserListChanges; bool acceptsRoomListChanges; - ServerInfo_User *userInfo; void prepareDestroy(); int sessionId; private: - QString thisUserName; QList messageSizeOverTime, messageCountOverTime; int timeRunning, lastDataReceived; QTimer *pingClock; @@ -186,11 +183,7 @@ public: bool getAcceptsUserListChanges() const { return acceptsUserListChanges; } bool getAcceptsRoomListChanges() const { return acceptsRoomListChanges; } - ServerInfo_User *getUserInfo() const { return userInfo; } - ServerInfo_User copyUserInfo(bool complete, bool moderatorInfo = false) const; - const QString &getUserName() const { return thisUserName; } virtual QString getAddress() const = 0; - void setUserInfo(const ServerInfo_User &_userInfo); int getSessionId() const { return sessionId; } void setSessionId(int _sessionId) { sessionId = _sessionId; } @@ -201,9 +194,6 @@ public: void sendProtocolItem(const SessionEvent &item); void sendProtocolItem(const GameEventContainer &item); void sendProtocolItem(const RoomEvent &item); - void sendProtocolItem(ServerMessage::MessageType type, const ::google::protobuf::Message &item); - - static SessionEvent *prepareSessionEvent(const ::google::protobuf::Message &sessionEvent); }; #endif diff --git a/common/server_remoteuserinterface.cpp b/common/server_remoteuserinterface.cpp new file mode 100644 index 00000000..b20bbbe5 --- /dev/null +++ b/common/server_remoteuserinterface.cpp @@ -0,0 +1,22 @@ +#include "server_remoteuserinterface.h" +#include "server.h" + +void Server_RemoteUserInterface::sendProtocolItem(const Response &item) +{ + server->sendIslMessage(item, userInfo->server_id()); +} + +void Server_RemoteUserInterface::sendProtocolItem(const SessionEvent &item) +{ + server->sendIslMessage(item, userInfo->server_id()); +} + +void Server_RemoteUserInterface::sendProtocolItem(const GameEventContainer &item) +{ + server->sendIslMessage(item, userInfo->server_id()); +} + +void Server_RemoteUserInterface::sendProtocolItem(const RoomEvent &item) +{ + server->sendIslMessage(item, userInfo->server_id()); +} diff --git a/common/server_remoteuserinterface.h b/common/server_remoteuserinterface.h new file mode 100644 index 00000000..82dafdb6 --- /dev/null +++ b/common/server_remoteuserinterface.h @@ -0,0 +1,16 @@ +#ifndef SERVER_REMOTEUSERINTERFACE_H +#define SERVER_REMOTEUSERINTERFACE_H + +#include "server_abstractuserinterface.h" + +class Server_RemoteUserInterface : public Server_AbstractUserInterface { +public: + Server_RemoteUserInterface(Server *_server, const ServerInfo_User_Container &_userInfoContainer) : Server_AbstractUserInterface(_server, _userInfoContainer) { } + + void sendProtocolItem(const Response &item); + void sendProtocolItem(const SessionEvent &item); + void sendProtocolItem(const GameEventContainer &item); + void sendProtocolItem(const RoomEvent &item); +}; + +#endif diff --git a/common/serverinfo_user_container.cpp b/common/serverinfo_user_container.cpp new file mode 100644 index 00000000..6268f15a --- /dev/null +++ b/common/serverinfo_user_container.cpp @@ -0,0 +1,46 @@ +#include "serverinfo_user_container.h" +#include "pb/serverinfo_user.pb.h" + +ServerInfo_User_Container::ServerInfo_User_Container(ServerInfo_User *_userInfo) + : userInfo(_userInfo) +{ +} + +ServerInfo_User_Container::ServerInfo_User_Container(const ServerInfo_User &_userInfo) + : userInfo(new ServerInfo_User(_userInfo)) +{ +} + +ServerInfo_User_Container::ServerInfo_User_Container(const ServerInfo_User_Container &other) +{ + if (other.userInfo) + userInfo = new ServerInfo_User(*other.userInfo); + else + userInfo = 0; +} + +ServerInfo_User_Container::~ServerInfo_User_Container() +{ + delete userInfo; +} + +void ServerInfo_User_Container::setUserInfo(const ServerInfo_User &_userInfo) +{ + userInfo = new ServerInfo_User; + userInfo->CopyFrom(_userInfo); +} + +ServerInfo_User ServerInfo_User_Container::copyUserInfo(bool complete, bool moderatorInfo) const +{ + ServerInfo_User result; + if (userInfo) { + result.CopyFrom(*userInfo); + if (!moderatorInfo) { + result.clear_address(); + result.clear_id(); + } + if (!complete) + result.clear_avatar_bmp(); + } + return result; +} diff --git a/common/serverinfo_user_container.h b/common/serverinfo_user_container.h new file mode 100644 index 00000000..1786bd4d --- /dev/null +++ b/common/serverinfo_user_container.h @@ -0,0 +1,19 @@ +#ifndef SERVERINFO_USER_CONTAINER +#define SERVERINFO_USER_CONTAINER + +class ServerInfo_User; + +class ServerInfo_User_Container { +protected: + ServerInfo_User *userInfo; +public: + ServerInfo_User_Container(ServerInfo_User *_userInfo = 0); + ServerInfo_User_Container(const ServerInfo_User &_userInfo); + ServerInfo_User_Container(const ServerInfo_User_Container &other); + virtual ~ServerInfo_User_Container(); + ServerInfo_User *getUserInfo() const { return userInfo; } + void setUserInfo(const ServerInfo_User &_userInfo); + ServerInfo_User copyUserInfo(bool complete, bool moderatorInfo = false) const; +}; + +#endif diff --git a/servatrice/src/isl_interface.cpp b/servatrice/src/isl_interface.cpp index b667867d..c4aa1a92 100644 --- a/servatrice/src/isl_interface.cpp +++ b/servatrice/src/isl_interface.cpp @@ -5,8 +5,12 @@ #include "server_protocolhandler.h" #include "server_room.h" +#include "get_pb_extension.h" #include "pb/isl_message.pb.h" #include "pb/event_server_complete_list.pb.h" +#include "pb/event_user_message.pb.h" +#include "pb/event_user_joined.pb.h" +#include "pb/event_user_left.pb.h" #include void IslInterface::sharedCtor(const QSslCertificate &cert, const QSslKey &privateKey) @@ -37,6 +41,19 @@ IslInterface::~IslInterface() logger->logMessage("[ISL] session ended", this); flushOutputBuffer(); + + QStringList usersToDelete; + server->serverMutex.lock(); + QMapIterator extUsers = server->getExternalUsers(); + while (extUsers.hasNext()) { + extUsers.next(); + if (extUsers.value()->getUserInfo()->server_id() == serverId) + usersToDelete.append(extUsers.key()); + } + server->serverMutex.unlock(); + + for (int i = 0; i < usersToDelete.size(); ++i) + emit externalUserLeft(usersToDelete[i]); } void IslInterface::initServer() @@ -218,7 +235,63 @@ void IslInterface::transmitMessage(const IslMessage &item) emit outputBufferChanged(); } +void IslInterface::sessionEvent_ServerCompleteList(const Event_ServerCompleteList &event) +{ + for (int i = 0; i < event.user_list_size(); ++i) { + ServerInfo_User temp(event.user_list(i)); + temp.set_server_id(serverId); + emit externalUserJoined(temp); + } +} + +void IslInterface::sessionEvent_UserMessage(const SessionEvent &sessionEvent, const Event_UserMessage &event) +{ + QMutexLocker locker(&server->serverMutex); + + Server_ProtocolHandler *userInterface = server->getUsers().value(QString::fromStdString(event.receiver_name())); + if (userInterface) + userInterface->sendProtocolItem(sessionEvent); +} + +void IslInterface::sessionEvent_UserJoined(const Event_UserJoined &event) +{ + emit externalUserJoined(event.user_info()); +} + +void IslInterface::sessionEvent_UserLeft(const Event_UserLeft &event) +{ + emit externalUserLeft(QString::fromStdString(event.name())); +} + +void IslInterface::processSessionEvent(const SessionEvent &event) +{ + switch (getPbExtension(event)) { + case SessionEvent::SERVER_COMPLETE_LIST: sessionEvent_ServerCompleteList(event.GetExtension(Event_ServerCompleteList::ext)); break; + case SessionEvent::USER_MESSAGE: sessionEvent_UserMessage(event, event.GetExtension(Event_UserMessage::ext)); break; + case SessionEvent::USER_JOINED: sessionEvent_UserJoined(event.GetExtension(Event_UserJoined::ext)); break; + case SessionEvent::USER_LEFT: sessionEvent_UserLeft(event.GetExtension(Event_UserLeft::ext)); break; + default: ; + } +} + void IslInterface::processMessage(const IslMessage &item) { qDebug() << QString::fromStdString(item.DebugString()); + + switch (item.message_type()) { + case IslMessage::SESSION_EVENT: processSessionEvent(item.session_event()); break; + case IslMessage::RESPONSE: { + break; + } + case IslMessage::GAME_COMMAND_CONTAINER: { + break; + } + case IslMessage::GAME_EVENT_CONTAINER: { + break; + } + case IslMessage::ROOM_EVENT: { + break; + } + default: ; + } } diff --git a/servatrice/src/isl_interface.h b/servatrice/src/isl_interface.h index a59377b3..47508565 100644 --- a/servatrice/src/isl_interface.h +++ b/servatrice/src/isl_interface.h @@ -4,12 +4,18 @@ #include "servatrice.h" #include #include +#include "pb/serverinfo_user.pb.h" class Servatrice; class QSslSocket; class QSslKey; class IslMessage; +class Event_ServerCompleteList; +class Event_UserMessage; +class Event_UserJoined; +class Event_UserLeft; + class IslInterface : public QObject { Q_OBJECT private slots: @@ -18,6 +24,9 @@ private slots: void flushOutputBuffer(); signals: void outputBufferChanged(); + + void externalUserJoined(ServerInfo_User userInfo); + void externalUserLeft(QString name); private: int serverId; int socketDescriptor; @@ -33,6 +42,13 @@ private: bool messageInProgress; int messageLength; + void sessionEvent_ServerCompleteList(const Event_ServerCompleteList &event); + void sessionEvent_UserMessage(const SessionEvent &sessionEvent, const Event_UserMessage &event); + void sessionEvent_UserJoined(const Event_UserJoined &event); + void sessionEvent_UserLeft(const Event_UserLeft &event); + + void processSessionEvent(const SessionEvent &event); + void processMessage(const IslMessage &item); void sharedCtor(const QSslCertificate &cert, const QSslKey &privateKey); public slots: diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index 687e9221..be0c5eee 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -64,6 +64,8 @@ void Servatrice_IslServer::incomingConnection(int socketDescriptor) Servatrice::Servatrice(QSettings *_settings, QObject *parent) : Server(parent), dbMutex(QMutex::Recursive), settings(_settings), uptime(0), shutdownTimer(0) { + qRegisterMetaType("ServerInfo_User"); + serverName = settings->value("server/name").toString(); serverId = settings->value("server/id", 0).toInt(); @@ -852,6 +854,8 @@ void Servatrice::addIslInterface(int serverId, IslInterface *interface) // Only call with islLock locked for writing islInterfaces.insert(serverId, interface); + connect(interface, SIGNAL(externalUserJoined(ServerInfo_User)), this, SLOT(externalUserJoined(ServerInfo_User))); + connect(interface, SIGNAL(externalUserLeft(QString)), this, SLOT(externalUserLeft(QString))); } void Servatrice::removeIslInterface(int serverId) @@ -866,13 +870,10 @@ void Servatrice::doSendIslMessage(const IslMessage &msg, int serverId) { QReadLocker locker(&islLock); - qDebug() << "hallo"; if (serverId == -1) { QMapIterator islIterator(islInterfaces); - while (islIterator.hasNext()) { - qDebug() << "welt"; + while (islIterator.hasNext()) islIterator.next().value()->transmitMessage(msg); - } } else { IslInterface *interface = islInterfaces.value(serverId); if (interface) diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index 87e466f5..95710cd1 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -26,6 +26,7 @@ #include #include #include +#include #include "server.h" class QSqlDatabase; @@ -166,4 +167,6 @@ private: QMap islInterfaces; }; +Q_DECLARE_METATYPE(ServerInfo_User) + #endif