more ISL code: join, leave, and userMessage work on both sides

This commit is contained in:
Max-Wilhelm Bruker 2012-03-11 17:25:45 +01:00
parent 5963c2239c
commit 0ae18d7b2e
16 changed files with 363 additions and 112 deletions

View file

@ -8,13 +8,16 @@ SET(common_SOURCES
rng_qt.cpp rng_qt.cpp
rng_sfmt.cpp rng_sfmt.cpp
server.cpp server.cpp
server_abstractuserinterface.cpp
server_card.cpp server_card.cpp
server_cardzone.cpp server_cardzone.cpp
server_game.cpp server_game.cpp
server_player.cpp server_player.cpp
server_protocolhandler.cpp server_protocolhandler.cpp
server_remoteuserinterface.cpp
server_response_containers.cpp server_response_containers.cpp
server_room.cpp server_room.cpp
serverinfo_user_container.cpp
sfmt/SFMT.c sfmt/SFMT.c
) )
SET(common_HEADERS SET(common_HEADERS

View file

@ -19,4 +19,5 @@ message ServerInfo_User {
optional string country = 6; optional string country = 6;
optional bytes avatar_bmp = 7; optional bytes avatar_bmp = 7;
optional sint32 id = 8 [default = -1]; optional sint32 id = 8 [default = -1];
optional sint32 server_id = 9 [default = -1];
} }

View file

@ -22,6 +22,7 @@
#include "server_counter.h" #include "server_counter.h"
#include "server_room.h" #include "server_room.h"
#include "server_protocolhandler.h" #include "server_protocolhandler.h"
#include "server_remoteuserinterface.h"
#include "pb/event_user_joined.pb.h" #include "pb/event_user_joined.pb.h"
#include "pb/event_user_left.pb.h" #include "pb/event_user_left.pb.h"
#include "pb/event_list_rooms.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) for (int i = 0; i < clients.size(); ++i)
if (clients[i]->getAcceptsUserListChanges()) if (clients[i]->getAcceptsUserListChanges())
clients[i]->sendProtocolItem(*se); clients[i]->sendProtocolItem(*se);
serverMutex.unlock(); locker.unlock();
sendIslMessage(*se); sendIslMessage(*se);
delete se; delete se;
@ -139,6 +140,36 @@ void Server::removeClient(Server_ProtocolHandler *client)
qDebug() << "Server::removeClient:" << clients.size() << "clients; " << users.size() << "users left"; 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() void Server::broadcastRoomUpdate()
{ {
QMutexLocker locker(&serverMutex); QMutexLocker locker(&serverMutex);
@ -184,6 +215,15 @@ int Server::getGamesCount() const
return result; 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) void Server::sendIslMessage(const SessionEvent &item, int serverId)
{ {
IslMessage msg; IslMessage msg;
@ -192,3 +232,21 @@ void Server::sendIslMessage(const SessionEvent &item, int serverId)
doSendIslMessage(msg, 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);
}

View file

@ -10,9 +10,13 @@
class Server_Game; class Server_Game;
class Server_Room; class Server_Room;
class Server_ProtocolHandler; class Server_ProtocolHandler;
class Server_AbstractUserInterface;
class GameReplay; class GameReplay;
class IslMessage; class IslMessage;
class Response;
class SessionEvent; class SessionEvent;
class GameEventContainer;
class RoomEvent;
enum AuthenticationResult { NotLoggedIn = 0, PasswordRight = 1, UnknownUser = 2, WouldOverwriteOldSession = 3, UserIsBanned = 4 }; enum AuthenticationResult { NotLoggedIn = 0, PasswordRight = 1, UnknownUser = 2, WouldOverwriteOldSession = 3, UserIsBanned = 4 };
@ -53,11 +57,22 @@ public:
virtual void storeGameInformation(int secondsElapsed, const QSet<QString> &allPlayersEver, const QSet<QString> &allSpectatorsEver, const QList<GameReplay *> &replays) { } virtual void storeGameInformation(int secondsElapsed, const QSet<QString> &allPlayersEver, const QSet<QString> &allSpectatorsEver, const QList<GameReplay *> &replays) { }
void sendIslMessage(const Response &item, int serverId = -1);
void sendIslMessage(const SessionEvent &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<QString, Server_AbstractUserInterface *> &getExternalUsers() const { return externalUsers; }
protected slots:
void externalUserJoined(ServerInfo_User userInfo);
void externalUserLeft(QString userName);
protected: protected:
void prepareDestroy(); void prepareDestroy();
QList<Server_ProtocolHandler *> clients; QList<Server_ProtocolHandler *> clients;
QMap<QString, Server_ProtocolHandler *> users; QMap<QString, Server_ProtocolHandler *> users;
QMap<QString, Server_AbstractUserInterface *> externalUsers;
QMap<int, Server_Room *> rooms; QMap<int, Server_Room *> rooms;
virtual int startSession(const QString &userName, const QString &address) { return -1; } virtual int startSession(const QString &userName, const QString &address) { return -1; }

View file

@ -0,0 +1,19 @@
#include "server_abstractuserinterface.h"
#include <google/protobuf/descriptor.h>
void Server_AbstractUserInterface::sendProtocolItemByType(ServerMessage::MessageType type, const ::google::protobuf::Message &item)
{
switch (type) {
case ServerMessage::RESPONSE: sendProtocolItem(static_cast<const Response &>(item)); break;
case ServerMessage::SESSION_EVENT: sendProtocolItem(static_cast<const SessionEvent &>(item)); break;
case ServerMessage::GAME_EVENT_CONTAINER: sendProtocolItem(static_cast<const GameEventContainer &>(item)); break;
case ServerMessage::ROOM_EVENT: sendProtocolItem(static_cast<const RoomEvent &>(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;
}

View file

@ -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

View file

@ -9,6 +9,7 @@
#include "server_game.h" #include "server_game.h"
#include "server_player.h" #include "server_player.h"
#include "decklist.h" #include "decklist.h"
#include "get_pb_extension.h"
#include <QDateTime> #include <QDateTime>
#include "pb/serverinfo_zone.pb.h" #include "pb/serverinfo_zone.pb.h"
#include "pb/commands.pb.h" #include "pb/commands.pb.h"
@ -88,7 +89,7 @@
#include <google/protobuf/descriptor.h> #include <google/protobuf/descriptor.h>
Server_ProtocolHandler::Server_ProtocolHandler(Server *_server, QObject *parent) 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())); connect(server, SIGNAL(pingClockTimeout()), this, SLOT(pingClockTimeout()));
} }
@ -126,29 +127,6 @@ void Server_ProtocolHandler::prepareDestroy()
g->gameMutex.unlock(); g->gameMutex.unlock();
} }
gameListMutex.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) void Server_ProtocolHandler::playerRemovedFromGame(Server_Game *game)
@ -195,37 +173,13 @@ void Server_ProtocolHandler::sendProtocolItem(const RoomEvent &item)
transmitProtocolItem(msg); transmitProtocolItem(msg);
} }
void Server_ProtocolHandler::sendProtocolItem(ServerMessage::MessageType type, const ::google::protobuf::Message &item)
{
switch (type) {
case ServerMessage::RESPONSE: sendProtocolItem(static_cast<const Response &>(item)); break;
case ServerMessage::SESSION_EVENT: sendProtocolItem(static_cast<const SessionEvent &>(item)); break;
case ServerMessage::GAME_EVENT_CONTAINER: sendProtocolItem(static_cast<const GameEventContainer &>(item)); break;
case ServerMessage::ROOM_EVENT: sendProtocolItem(static_cast<const RoomEvent &>(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 Server_ProtocolHandler::processSessionCommandContainer(const CommandContainer &cont, ResponseContainer &rc)
{ {
Response::ResponseCode finalResponseCode = Response::RespOk; Response::ResponseCode finalResponseCode = Response::RespOk;
for (int i = cont.session_command_size() - 1; i >= 0; --i) { for (int i = cont.session_command_size() - 1; i >= 0; --i) {
Response::ResponseCode resp = Response::RespInvalidCommand; Response::ResponseCode resp = Response::RespInvalidCommand;
const SessionCommand &sc = cont.session_command(i); const SessionCommand &sc = cont.session_command(i);
std::vector< const ::google::protobuf::FieldDescriptor * > fieldList; const int num = getPbExtension(sc);
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;
}
if (num != SessionCommand::PING) if (num != SessionCommand::PING)
emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this); emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this);
switch ((SessionCommand::SessionCommandType) num) { 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) { for (int i = cont.room_command_size() - 1; i >= 0; --i) {
Response::ResponseCode resp = Response::RespInvalidCommand; Response::ResponseCode resp = Response::RespInvalidCommand;
const RoomCommand &sc = cont.room_command(i); const RoomCommand &sc = cont.room_command(i);
std::vector< const ::google::protobuf::FieldDescriptor * > fieldList; const int num = getPbExtension(sc);
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;
}
emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this); emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this);
switch ((RoomCommand::RoomCommandType) num) { switch ((RoomCommand::RoomCommandType) num) {
case RoomCommand::LEAVE_ROOM: resp = cmdLeaveRoom(sc.GetExtension(Command_LeaveRoom::ext), room, rc); break; 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) { for (int i = cont.game_command_size() - 1; i >= 0; --i) {
Response::ResponseCode resp = Response::RespInvalidCommand; Response::ResponseCode resp = Response::RespInvalidCommand;
const GameCommand &sc = cont.game_command(i); const GameCommand &sc = cont.game_command(i);
std::vector< const ::google::protobuf::FieldDescriptor * > fieldList; const int num = getPbExtension(sc);
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;
}
emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this); emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this);
switch ((GameCommand::GameCommandType) num) { switch ((GameCommand::GameCommandType) num) {
case GameCommand::KICK_FROM_GAME: resp = cmdKickFromGame(sc.GetExtension(Command_KickFromGame::ext), game, player, rc, ges); break; 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) { for (int i = cont.moderator_command_size() - 1; i >= 0; --i) {
Response::ResponseCode resp = Response::RespInvalidCommand; Response::ResponseCode resp = Response::RespInvalidCommand;
const ModeratorCommand &sc = cont.moderator_command(i); const ModeratorCommand &sc = cont.moderator_command(i);
std::vector< const ::google::protobuf::FieldDescriptor * > fieldList; const int num = getPbExtension(sc);
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;
}
emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this); emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this);
switch ((ModeratorCommand::ModeratorCommandType) num) { switch ((ModeratorCommand::ModeratorCommandType) num) {
case ModeratorCommand::BAN_FROM_SERVER: resp = cmdBanFromServer(sc.GetExtension(Command_BanFromServer::ext), rc); break; 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) { for (int i = cont.admin_command_size() - 1; i >= 0; --i) {
Response::ResponseCode resp = Response::RespInvalidCommand; Response::ResponseCode resp = Response::RespInvalidCommand;
const AdminCommand &sc = cont.admin_command(i); const AdminCommand &sc = cont.admin_command(i);
std::vector< const ::google::protobuf::FieldDescriptor * > fieldList; const int num = getPbExtension(sc);
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;
}
emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this); emit logDebugMessage(QString::fromStdString(sc.ShortDebugString()), this);
switch ((AdminCommand::AdminCommandType) num) { switch ((AdminCommand::AdminCommandType) num) {
case AdminCommand::SHUTDOWN_SERVER: resp = cmdShutdownServer(sc.GetExtension(Command_ShutdownServer::ext), rc); break; 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<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &preResponseQueue = responseContainer.getPreResponseQueue(); const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &preResponseQueue = responseContainer.getPreResponseQueue();
for (int i = 0; i < preResponseQueue.size(); ++i) 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 response;
response.set_cmd_id(cont.cmd_id()); response.set_cmd_id(cont.cmd_id());
@ -454,7 +380,7 @@ void Server_ProtocolHandler::processCommandContainer(const CommandContainer &con
const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &postResponseQueue = responseContainer.getPostResponseQueue(); const QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > &postResponseQueue = responseContainer.getPostResponseQueue();
for (int i = 0; i < postResponseQueue.size(); ++i) 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() void Server_ProtocolHandler::pingClockTimeout()
@ -577,11 +503,15 @@ Response::ResponseCode Server_ProtocolHandler::cmdMessage(const Command_Message
if (authState == NotLoggedIn) if (authState == NotLoggedIn)
return Response::RespLoginNeeded; return Response::RespLoginNeeded;
server->serverMutex.lock(); QMutexLocker locker(&server->serverMutex);
QString receiver = QString::fromStdString(cmd.user_name()); QString receiver = QString::fromStdString(cmd.user_name());
Server_ProtocolHandler *userHandler = server->getUsers().value(receiver); Server_AbstractUserInterface *userInterface = server->getUsers().value(receiver);
if (!userHandler) if (!userInterface) {
userInterface = server->getExternalUsers().value(receiver);
if (!userInterface)
return Response::RespNameNotFound; return Response::RespNameNotFound;
}
if (server->isInIgnoreList(receiver, QString::fromStdString(userInfo->name()))) if (server->isInIgnoreList(receiver, QString::fromStdString(userInfo->name())))
return Response::RespInIgnoreList; return Response::RespInIgnoreList;
@ -591,9 +521,8 @@ Response::ResponseCode Server_ProtocolHandler::cmdMessage(const Command_Message
event.set_message(cmd.message()); event.set_message(cmd.message());
SessionEvent *se = prepareSessionEvent(event); SessionEvent *se = prepareSessionEvent(event);
userHandler->sendProtocolItem(*se); userInterface->sendProtocolItem(*se);
rc.enqueuePreResponseItem(ServerMessage::SESSION_EVENT, se); rc.enqueuePreResponseItem(ServerMessage::SESSION_EVENT, se);
server->serverMutex.unlock();
return Response::RespOk; return Response::RespOk;
} }
@ -634,12 +563,18 @@ Response::ResponseCode Server_ProtocolHandler::cmdGetUserInfo(const Command_GetU
if (userName.isEmpty()) if (userName.isEmpty())
re->mutable_user_info()->CopyFrom(*userInfo); re->mutable_user_info()->CopyFrom(*userInfo);
else { else {
server->serverMutex.lock();
Server_ProtocolHandler *handler = server->getUsers().value(userName); QMutexLocker locker(&server->serverMutex);
if (!handler)
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; 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); rc.setResponseExtension(re);
@ -699,6 +634,9 @@ Response::ResponseCode Server_ProtocolHandler::cmdListUsers(const Command_ListUs
QMapIterator<QString, Server_ProtocolHandler *> userIterator = server->getUsers(); QMapIterator<QString, Server_ProtocolHandler *> userIterator = server->getUsers();
while (userIterator.hasNext()) while (userIterator.hasNext())
re->add_user_list()->CopyFrom(userIterator.next().value()->copyUserInfo(false)); re->add_user_list()->CopyFrom(userIterator.next().value()->copyUserInfo(false));
QMapIterator<QString, Server_AbstractUserInterface *> extIterator = server->getExternalUsers();
while (extIterator.hasNext())
re->add_user_list()->CopyFrom(extIterator.next().value()->copyUserInfo(false));
server->serverMutex.unlock(); server->serverMutex.unlock();
acceptsUserListChanges = true; acceptsUserListChanges = true;
@ -747,7 +685,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdCreateGame(const Command_Creat
return Response::RespLoginNeeded; return Response::RespLoginNeeded;
if (server->getMaxGamesPerUser() > 0) if (server->getMaxGamesPerUser() > 0)
if (room->getGamesCreatedByUser(getUserName()) >= server->getMaxGamesPerUser()) if (room->getGamesCreatedByUser(QString::fromStdString(userInfo->name())) >= server->getMaxGamesPerUser())
return Response::RespContextError; return Response::RespContextError;
QList<int> gameTypes; QList<int> gameTypes;

View file

@ -4,6 +4,7 @@
#include <QObject> #include <QObject>
#include <QPair> #include <QPair>
#include "server.h" #include "server.h"
#include "server_abstractuserinterface.h"
#include "pb/response.pb.h" #include "pb/response.pb.h"
#include "pb/server_message.pb.h" #include "pb/server_message.pb.h"
@ -84,25 +85,21 @@ class Command_BanFromServer;
class Command_UpdateServerMessage; class Command_UpdateServerMessage;
class Command_ShutdownServer; class Command_ShutdownServer;
class Server_ProtocolHandler : public QObject { class Server_ProtocolHandler : public QObject, public Server_AbstractUserInterface {
Q_OBJECT Q_OBJECT
protected: protected:
Server *server;
QMap<int, QPair<Server_Game *, Server_Player *> > games; QMap<int, QPair<Server_Game *, Server_Player *> > games;
QMap<int, Server_Room *> rooms; QMap<int, Server_Room *> rooms;
Server *getServer() const { return server; }
QPair<Server_Game *, Server_Player *> getGame(int gameId) const; QPair<Server_Game *, Server_Player *> getGame(int gameId) const;
AuthenticationResult authState; AuthenticationResult authState;
bool acceptsUserListChanges; bool acceptsUserListChanges;
bool acceptsRoomListChanges; bool acceptsRoomListChanges;
ServerInfo_User *userInfo;
void prepareDestroy(); void prepareDestroy();
int sessionId; int sessionId;
private: private:
QString thisUserName;
QList<int> messageSizeOverTime, messageCountOverTime; QList<int> messageSizeOverTime, messageCountOverTime;
int timeRunning, lastDataReceived; int timeRunning, lastDataReceived;
QTimer *pingClock; QTimer *pingClock;
@ -186,11 +183,7 @@ public:
bool getAcceptsUserListChanges() const { return acceptsUserListChanges; } bool getAcceptsUserListChanges() const { return acceptsUserListChanges; }
bool getAcceptsRoomListChanges() const { return acceptsRoomListChanges; } 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; virtual QString getAddress() const = 0;
void setUserInfo(const ServerInfo_User &_userInfo);
int getSessionId() const { return sessionId; } int getSessionId() const { return sessionId; }
void setSessionId(int _sessionId) { sessionId = _sessionId; } void setSessionId(int _sessionId) { sessionId = _sessionId; }
@ -201,9 +194,6 @@ public:
void sendProtocolItem(const SessionEvent &item); void sendProtocolItem(const SessionEvent &item);
void sendProtocolItem(const GameEventContainer &item); void sendProtocolItem(const GameEventContainer &item);
void sendProtocolItem(const RoomEvent &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 #endif

View file

@ -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());
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -5,8 +5,12 @@
#include "server_protocolhandler.h" #include "server_protocolhandler.h"
#include "server_room.h" #include "server_room.h"
#include "get_pb_extension.h"
#include "pb/isl_message.pb.h" #include "pb/isl_message.pb.h"
#include "pb/event_server_complete_list.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 <google/protobuf/descriptor.h> #include <google/protobuf/descriptor.h>
void IslInterface::sharedCtor(const QSslCertificate &cert, const QSslKey &privateKey) void IslInterface::sharedCtor(const QSslCertificate &cert, const QSslKey &privateKey)
@ -37,6 +41,19 @@ IslInterface::~IslInterface()
logger->logMessage("[ISL] session ended", this); logger->logMessage("[ISL] session ended", this);
flushOutputBuffer(); flushOutputBuffer();
QStringList usersToDelete;
server->serverMutex.lock();
QMapIterator<QString, Server_AbstractUserInterface *> 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() void IslInterface::initServer()
@ -218,7 +235,63 @@ void IslInterface::transmitMessage(const IslMessage &item)
emit outputBufferChanged(); 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) void IslInterface::processMessage(const IslMessage &item)
{ {
qDebug() << QString::fromStdString(item.DebugString()); 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: ;
}
} }

View file

@ -4,12 +4,18 @@
#include "servatrice.h" #include "servatrice.h"
#include <QSslCertificate> #include <QSslCertificate>
#include <QWaitCondition> #include <QWaitCondition>
#include "pb/serverinfo_user.pb.h"
class Servatrice; class Servatrice;
class QSslSocket; class QSslSocket;
class QSslKey; class QSslKey;
class IslMessage; class IslMessage;
class Event_ServerCompleteList;
class Event_UserMessage;
class Event_UserJoined;
class Event_UserLeft;
class IslInterface : public QObject { class IslInterface : public QObject {
Q_OBJECT Q_OBJECT
private slots: private slots:
@ -18,6 +24,9 @@ private slots:
void flushOutputBuffer(); void flushOutputBuffer();
signals: signals:
void outputBufferChanged(); void outputBufferChanged();
void externalUserJoined(ServerInfo_User userInfo);
void externalUserLeft(QString name);
private: private:
int serverId; int serverId;
int socketDescriptor; int socketDescriptor;
@ -33,6 +42,13 @@ private:
bool messageInProgress; bool messageInProgress;
int messageLength; 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 processMessage(const IslMessage &item);
void sharedCtor(const QSslCertificate &cert, const QSslKey &privateKey); void sharedCtor(const QSslCertificate &cert, const QSslKey &privateKey);
public slots: public slots:

View file

@ -64,6 +64,8 @@ void Servatrice_IslServer::incomingConnection(int socketDescriptor)
Servatrice::Servatrice(QSettings *_settings, QObject *parent) Servatrice::Servatrice(QSettings *_settings, QObject *parent)
: Server(parent), dbMutex(QMutex::Recursive), settings(_settings), uptime(0), shutdownTimer(0) : Server(parent), dbMutex(QMutex::Recursive), settings(_settings), uptime(0), shutdownTimer(0)
{ {
qRegisterMetaType<ServerInfo_User>("ServerInfo_User");
serverName = settings->value("server/name").toString(); serverName = settings->value("server/name").toString();
serverId = settings->value("server/id", 0).toInt(); 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 // Only call with islLock locked for writing
islInterfaces.insert(serverId, 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)));
} }
void Servatrice::removeIslInterface(int serverId) void Servatrice::removeIslInterface(int serverId)
@ -866,13 +870,10 @@ void Servatrice::doSendIslMessage(const IslMessage &msg, int serverId)
{ {
QReadLocker locker(&islLock); QReadLocker locker(&islLock);
qDebug() << "hallo";
if (serverId == -1) { if (serverId == -1) {
QMapIterator<int, IslInterface *> islIterator(islInterfaces); QMapIterator<int, IslInterface *> islIterator(islInterfaces);
while (islIterator.hasNext()) { while (islIterator.hasNext())
qDebug() << "welt";
islIterator.next().value()->transmitMessage(msg); islIterator.next().value()->transmitMessage(msg);
}
} else { } else {
IslInterface *interface = islInterfaces.value(serverId); IslInterface *interface = islInterfaces.value(serverId);
if (interface) if (interface)

View file

@ -26,6 +26,7 @@
#include <QSslKey> #include <QSslKey>
#include <QHostAddress> #include <QHostAddress>
#include <QReadWriteLock> #include <QReadWriteLock>
#include <QMetaType>
#include "server.h" #include "server.h"
class QSqlDatabase; class QSqlDatabase;
@ -166,4 +167,6 @@ private:
QMap<int, IslInterface *> islInterfaces; QMap<int, IslInterface *> islInterfaces;
}; };
Q_DECLARE_METATYPE(ServerInfo_User)
#endif #endif