From d3b96b1a88eb094a88f576334ca0e668720379da Mon Sep 17 00:00:00 2001 From: Max-Wilhelm Bruker Date: Fri, 30 Dec 2011 21:50:25 +0100 Subject: [PATCH] PB: server compiles again, standalone RemoteClient is able to log in --- cockatrice/cockatrice.pro | 5 - cockatrice/src/abstractclient.cpp | 107 +++--- cockatrice/src/abstractclient.h | 49 ++- cockatrice/src/dlg_creategame.cpp | 6 +- cockatrice/src/dlg_creategame.h | 5 +- cockatrice/src/localclient.cpp | 4 +- cockatrice/src/localclient.h | 5 +- cockatrice/src/localserver.cpp | 6 +- cockatrice/src/localserver.h | 8 +- cockatrice/src/localserverinterface.cpp | 8 +- cockatrice/src/localserverinterface.h | 28 +- cockatrice/src/pending_command.cpp | 8 - cockatrice/src/pending_command.h | 14 +- cockatrice/src/player.cpp | 1 - cockatrice/src/remoteclient.cpp | 114 +++---- cockatrice/src/remoteclient.h | 11 +- cockatrice/src/window_main.cpp | 14 +- cockatrice/src/window_main.h | 4 +- common/color.h | 2 +- .../proto/event_server_identification.proto | 10 + common/pb/proto/session_event.proto | 1 + common/protocol.cpp | 52 --- common/protocol.h | 85 ++--- common/server.cpp | 46 +-- common/server.h | 8 +- common/server_cardzone.cpp | 16 +- common/server_cardzone.h | 1 + common/server_game.cpp | 304 ++++++++++-------- common/server_game.h | 11 +- common/server_player.cpp | 200 +++++++----- common/server_player.h | 9 +- common/server_protocolhandler.cpp | 115 ++++--- common/server_protocolhandler.h | 8 +- common/server_room.cpp | 72 +++-- servatrice/servatrice.ini.example | 1 + servatrice/src/servatrice.cpp | 130 +++++--- servatrice/src/servatrice.h | 15 +- servatrice/src/serversocketinterface.cpp | 264 +++++++-------- servatrice/src/serversocketinterface.h | 48 +-- 39 files changed, 988 insertions(+), 807 deletions(-) delete mode 100644 cockatrice/src/pending_command.cpp create mode 100644 common/pb/proto/event_server_identification.proto diff --git a/cockatrice/cockatrice.pro b/cockatrice/cockatrice.pro index d204768f..f821d18b 100644 --- a/cockatrice/cockatrice.pro +++ b/cockatrice/cockatrice.pro @@ -88,8 +88,6 @@ HEADERS += src/abstractcounter.h \ ../common/serializable_item.h \ ../common/decklist.h \ ../common/protocol.h \ - ../common/protocol_items.h \ - ../common/protocol_datastructures.h \ ../common/rng_abstract.h \ ../common/rng_sfmt.h \ ../common/server.h \ @@ -170,12 +168,9 @@ SOURCES += src/abstractcounter.cpp \ src/localclient.cpp \ src/priceupdater.cpp \ src/soundengine.cpp \ - src/pending_command.cpp \ ../common/serializable_item.cpp \ ../common/decklist.cpp \ ../common/protocol.cpp \ - ../common/protocol_items.cpp \ - ../common/protocol_datastructures.cpp \ ../common/rng_abstract.cpp \ ../common/rng_sfmt.cpp \ ../common/sfmt/SFMT.c \ diff --git a/cockatrice/src/abstractclient.cpp b/cockatrice/src/abstractclient.cpp index f1cce27d..a059674a 100644 --- a/cockatrice/src/abstractclient.cpp +++ b/cockatrice/src/abstractclient.cpp @@ -1,9 +1,19 @@ #include "abstractclient.h" #include "protocol.h" -#include "protocol_items.h" #include "pending_command.h" #include "pb/commands.pb.h" +#include "pb/event_server_identification.pb.h" +#include "pb/event_server_message.pb.h" +#include "pb/event_server_shutdown.pb.h" +#include "pb/event_connection_closed.pb.h" +#include "pb/event_user_message.pb.h" +#include "pb/event_list_rooms.pb.h" +#include "pb/event_add_to_list.pb.h" +#include "pb/event_remove_from_list.pb.h" +#include "pb/event_user_joined.pb.h" +#include "pb/event_user_left.pb.h" +#include "pb/event_game_joined.pb.h" #include AbstractClient::AbstractClient(QObject *parent) @@ -15,57 +25,54 @@ AbstractClient::~AbstractClient() { } -void AbstractClient::processProtocolItem(ProtocolItem *item) +void AbstractClient::processProtocolItem(const ServerMessage &item) { - ProtocolResponse *response = qobject_cast(item); - if (response) { - const int cmdId = response->getCmdId(); - PendingCommand *pend = pendingCommands.value(cmdId, 0); - if (!pend) - return; - - pendingCommands.remove(cmdId); - pend->processResponse(response); - if (response->getReceiverMayDelete()) - delete response; - pend->deleteLater(); - - return; - } - - GenericEvent *genericEvent = qobject_cast(item); - if (genericEvent) { - switch (genericEvent->getItemId()) { - case ItemId_Event_ConnectionClosed: emit connectionClosedEventReceived(static_cast(item)); break; - case ItemId_Event_ServerShutdown: emit serverShutdownEventReceived(static_cast(item)); break; - case ItemId_Event_AddToList: emit addToListEventReceived(static_cast(item)); break; - case ItemId_Event_RemoveFromList: emit removeFromListEventReceived(static_cast(item)); break; - case ItemId_Event_UserJoined: emit userJoinedEventReceived(static_cast(item)); break; - case ItemId_Event_UserLeft: emit userLeftEventReceived(static_cast(item)); break; - case ItemId_Event_ServerMessage: emit serverMessageEventReceived(static_cast(item)); break; - case ItemId_Event_ListRooms: emit listRoomsEventReceived(static_cast(item)); break; - case ItemId_Event_GameJoined: emit gameJoinedEventReceived(static_cast(item)); break; - case ItemId_Event_Message: emit messageEventReceived(static_cast(item)); break; + switch (item.message_type()) { + case ServerMessage::RESPONSE: { + const Response &response = item.response(); + const int cmdId = response.cmd_id(); + PendingCommand *pend = pendingCommands.value(cmdId, 0); + if (!pend) + return; + + pendingCommands.remove(cmdId); + pend->processResponse(response); + pend->deleteLater(); + break; + } + case ServerMessage::SESSION_EVENT: { + const SessionEvent &event = item.session_event(); + std::vector< const ::google::protobuf::FieldDescriptor * > fieldList; + event.GetReflection()->ListFields(event, &fieldList); + int num = 0; + for (unsigned int j = 0; j < fieldList.size(); ++j) + if (fieldList[j]->is_extension()) { + num = fieldList[j]->number(); + break; + } + switch ((SessionEvent::SessionEventType) num) { + case SessionEvent::SERVER_IDENTIFICATION: emit serverIdentificationEventReceived(event.GetExtension(Event_ServerIdentification::ext)); break; + case SessionEvent::SERVER_MESSAGE: emit serverMessageEventReceived(event.GetExtension(Event_ServerMessage::ext)); break; + case SessionEvent::SERVER_SHUTDOWN: emit serverShutdownEventReceived(event.GetExtension(Event_ServerShutdown::ext)); break; + case SessionEvent::CONNECTION_CLOSED: emit connectionClosedEventReceived(event.GetExtension(Event_ConnectionClosed::ext)); break; + case SessionEvent::USER_MESSAGE: emit userMessageEventReceived(event.GetExtension(Event_UserMessage::ext)); break; + case SessionEvent::LIST_ROOMS: emit listRoomsEventReceived(event.GetExtension(Event_ListRooms::ext)); break; + case SessionEvent::ADD_TO_LIST: emit addToListEventReceived(event.GetExtension(Event_AddToList::ext)); break; + case SessionEvent::REMOVE_FROM_LIST: emit removeFromListEventReceived(event.GetExtension(Event_RemoveFromList::ext)); break; + case SessionEvent::USER_JOINED: emit userJoinedEventReceived(event.GetExtension(Event_UserJoined::ext)); break; + case SessionEvent::USER_LEFT: emit userLeftEventReceived(event.GetExtension(Event_UserLeft::ext)); break; + case SessionEvent::GAME_JOINED: emit gameJoinedEventReceived(event.GetExtension(Event_GameJoined::ext)); break; + } + break; + } + case ServerMessage::GAME_EVENT_CONTAINER: { + emit gameEventContainerReceived(item.game_event_container()); + break; + } + case ServerMessage::ROOM_EVENT: { + emit roomEventReceived(item.room_event()); + break; } - if (genericEvent->getReceiverMayDelete()) - delete genericEvent; - return; - } - - GameEventContainer *gameEventContainer = qobject_cast(item); - if (gameEventContainer) { - emit gameEventContainerReceived(gameEventContainer); - if (gameEventContainer->getReceiverMayDelete()) - delete gameEventContainer; - return; - } - - RoomEvent *roomEvent = qobject_cast(item); - if (roomEvent) { - emit roomEventReceived(roomEvent); - if (roomEvent->getReceiverMayDelete()) - delete roomEvent; - return; } } diff --git a/cockatrice/src/abstractclient.h b/cockatrice/src/abstractclient.h index 3076def3..49e196a4 100644 --- a/cockatrice/src/abstractclient.h +++ b/cockatrice/src/abstractclient.h @@ -3,17 +3,15 @@ #include #include -#include -#include "protocol_datastructures.h" +#include "pb/response.pb.h" +#include "pb/serverinfo_user.pb.h" class PendingCommand; class CommandContainer; -class ProtocolItem; -class ProtocolResponse; -class TopLevelProtocolItem; -class CommandContainer; class RoomEvent; class GameEventContainer; +class ServerMessage; +class Event_ServerIdentification; class Event_AddToList; class Event_RemoveFromList; class Event_UserJoined; @@ -21,7 +19,7 @@ class Event_UserLeft; class Event_ServerMessage; class Event_ListRooms; class Event_GameJoined; -class Event_Message; +class Event_UserMessage; class Event_ConnectionClosed; class Event_ServerShutdown; @@ -38,30 +36,31 @@ class AbstractClient : public QObject { Q_OBJECT signals: void statusChanged(ClientStatus _status); - void serverError(ResponseCode resp); + void serverError(Response::ResponseCode resp); // Room events - void roomEventReceived(RoomEvent *event); + void roomEventReceived(const RoomEvent &event); // Game events - void gameEventContainerReceived(GameEventContainer *event); - // Generic events - void connectionClosedEventReceived(Event_ConnectionClosed *event); - void serverShutdownEventReceived(Event_ServerShutdown *event); - void addToListEventReceived(Event_AddToList *event); - void removeFromListEventReceived(Event_RemoveFromList *event); - void userJoinedEventReceived(Event_UserJoined *event); - void userLeftEventReceived(Event_UserLeft *event); - void serverMessageEventReceived(Event_ServerMessage *event); - void listRoomsEventReceived(Event_ListRooms *event); - void gameJoinedEventReceived(Event_GameJoined *event); - void messageEventReceived(Event_Message *event); - void userInfoChanged(ServerInfo_User *userInfo); - void buddyListReceived(const QList &buddyList); - void ignoreListReceived(const QList &ignoreList); + void gameEventContainerReceived(const GameEventContainer &event); + // Session events + void serverIdentificationEventReceived(const Event_ServerIdentification &event); + void connectionClosedEventReceived(const Event_ConnectionClosed &event); + void serverShutdownEventReceived(const Event_ServerShutdown &event); + void addToListEventReceived(const Event_AddToList &event); + void removeFromListEventReceived(const Event_RemoveFromList &event); + void userJoinedEventReceived(const Event_UserJoined &event); + void userLeftEventReceived(const Event_UserLeft &event); + void serverMessageEventReceived(const Event_ServerMessage &event); + void listRoomsEventReceived(const Event_ListRooms &event); + void gameJoinedEventReceived(const Event_GameJoined &event); + void userMessageEventReceived(const Event_UserMessage &event); + void userInfoChanged(const ServerInfo_User &userInfo); + void buddyListReceived(const QList &buddyList); + void ignoreListReceived(const QList &ignoreList); private: int nextCmdId; protected slots: - void processProtocolItem(ProtocolItem *item); + void processProtocolItem(const ServerMessage &item); protected: QMap pendingCommands; ClientStatus status; diff --git a/cockatrice/src/dlg_creategame.cpp b/cockatrice/src/dlg_creategame.cpp index c71c0b36..b4ea389c 100644 --- a/cockatrice/src/dlg_creategame.cpp +++ b/cockatrice/src/dlg_creategame.cpp @@ -125,19 +125,19 @@ void DlgCreateGame::actOK() } PendingCommand *pend = room->prepareRoomCommand(cmd); - connect(pend, SIGNAL(finished(ResponseCode)), this, SLOT(checkResponse(ResponseCode))); + connect(pend, SIGNAL(finished(Response::ResponseCode)), this, SLOT(checkResponse(Response::ResponseCode))); room->sendRoomCommand(pend); okButton->setEnabled(false); cancelButton->setEnabled(false); } -void DlgCreateGame::checkResponse(ResponseCode response) +void DlgCreateGame::checkResponse(Response::ResponseCode response) { okButton->setEnabled(true); cancelButton->setEnabled(true); - if (response == RespOk) + if (response == Response::RespOk) accept(); else { QMessageBox::critical(this, tr("Error"), tr("Server error.")); diff --git a/cockatrice/src/dlg_creategame.h b/cockatrice/src/dlg_creategame.h index 27e04cf3..556afc9c 100644 --- a/cockatrice/src/dlg_creategame.h +++ b/cockatrice/src/dlg_creategame.h @@ -2,7 +2,8 @@ #define DLG_CREATEGAME_H #include -#include "protocol_datastructures.h" +#include +#include "pb/response.pb.h" class QLabel; class QLineEdit; @@ -18,7 +19,7 @@ public: DlgCreateGame(TabRoom *_room, const QMap &_gameTypes, QWidget *parent = 0); private slots: void actOK(); - void checkResponse(ResponseCode response); + void checkResponse(Response::ResponseCode response); void spectatorsAllowedChanged(int state); private: TabRoom *room; diff --git a/cockatrice/src/localclient.cpp b/cockatrice/src/localclient.cpp index 30ee2cfa..c47e21b7 100644 --- a/cockatrice/src/localclient.cpp +++ b/cockatrice/src/localclient.cpp @@ -7,7 +7,7 @@ LocalClient::LocalClient(LocalServerInterface *_lsi, const QString &_playerName, QObject *parent) : AbstractClient(parent), lsi(_lsi) { - connect(lsi, SIGNAL(itemToClient(ProtocolItem *)), this, SLOT(itemFromServer(ProtocolItem *))); + connect(lsi, SIGNAL(itemToClient(const ServerMessage &)), this, SLOT(itemFromServer(const ServerMessage &))); Command_Login loginCmd; loginCmd.set_user_name(_playerName.toStdString()); @@ -27,7 +27,7 @@ void LocalClient::sendCommandContainer(const CommandContainer &cont) lsi->itemFromClient(cont); } -void LocalClient::itemFromServer(ProtocolItem *item) +void LocalClient::itemFromServer(const ServerMessage &item) { processProtocolItem(item); } diff --git a/cockatrice/src/localclient.h b/cockatrice/src/localclient.h index 42f0aef6..2a8da910 100644 --- a/cockatrice/src/localclient.h +++ b/cockatrice/src/localclient.h @@ -14,11 +14,8 @@ public: ~LocalClient(); void sendCommandContainer(const CommandContainer &cont); - private slots: - void itemFromServer(ProtocolItem *item); -signals: - void itemToServer(ProtocolItem *item); + void itemFromServer(const ServerMessage &item); }; #endif \ No newline at end of file diff --git a/cockatrice/src/localserver.cpp b/cockatrice/src/localserver.cpp index 2793a28e..16216b87 100644 --- a/cockatrice/src/localserver.cpp +++ b/cockatrice/src/localserver.cpp @@ -20,7 +20,9 @@ LocalServerInterface *LocalServer::newConnection() return lsi; } -ServerInfo_User *LocalServer::getUserData(const QString &name) +ServerInfo_User LocalServer::getUserData(const QString &name) { - return new ServerInfo_User(name); + ServerInfo_User result; + result.set_name(name.toStdString()); + return result; } \ No newline at end of file diff --git a/cockatrice/src/localserver.h b/cockatrice/src/localserver.h index 36838cc6..6b87fcd7 100644 --- a/cockatrice/src/localserver.h +++ b/cockatrice/src/localserver.h @@ -23,9 +23,11 @@ protected: int startSession(const QString & /*userName*/, const QString & /*address*/) { return -1; } void endSession(int /*sessionId*/) { } bool userExists(const QString & /*name*/) { return false; } - ServerInfo_User *getUserData(const QString &name); - QMap getBuddyList(const QString & /*name*/) { return QMap(); } - QMap getIgnoreList(const QString & /*name*/) { return QMap(); } + ServerInfo_User getUserData(const QString &name); + QMap getBuddyList(const QString & /*name*/) { return QMap(); } + QMap getIgnoreList(const QString & /*name*/) { return QMap(); } + bool isInBuddyList(const QString & /*whoseList*/, const QString & /*who*/) { return false; } + bool isInIgnoreList(const QString & /*whoseList*/, const QString & /*who*/) { return false; } }; #endif \ No newline at end of file diff --git a/cockatrice/src/localserverinterface.cpp b/cockatrice/src/localserverinterface.cpp index df1eeb36..6d161e0f 100644 --- a/cockatrice/src/localserverinterface.cpp +++ b/cockatrice/src/localserverinterface.cpp @@ -12,16 +12,12 @@ LocalServerInterface::~LocalServerInterface() prepareDestroy(); } -void LocalServerInterface::sendProtocolItem(ProtocolItem *item, bool deleteItem) +void LocalServerInterface::transmitProtocolItem(const ServerMessage &item) { - item->setReceiverMayDelete(false); emit itemToClient(item); - if (deleteItem) - delete item; } -#include "pb/commands.pb.h" + void LocalServerInterface::itemFromClient(const CommandContainer &item) { - qDebug() << "READ" << QString::fromStdString(item.ShortDebugString()); processCommandContainer(item); } diff --git a/cockatrice/src/localserverinterface.h b/cockatrice/src/localserverinterface.h index 19d2d58c..a1b08ea3 100644 --- a/cockatrice/src/localserverinterface.h +++ b/cockatrice/src/localserverinterface.h @@ -10,27 +10,25 @@ class LocalServerInterface : public Server_ProtocolHandler Q_OBJECT private: DeckList *getDeckFromDatabase(int /*deckId*/) { return 0; } - ResponseCode cmdAddToList(const Command_AddToList & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } - ResponseCode cmdRemoveFromList(const Command_RemoveFromList & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } - ResponseCode cmdDeckList(const Command_DeckList & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } - ResponseCode cmdDeckNewDir(const Command_DeckNewDir & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } - ResponseCode cmdDeckDelDir(const Command_DeckDelDir & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } - ResponseCode cmdDeckDel(const Command_DeckDel & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } - ResponseCode cmdDeckUpload(const Command_DeckUpload & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } - ResponseCode cmdDeckDownload(const Command_DeckDownload & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } - ResponseCode cmdBanFromServer(const Command_BanFromServer & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } - ResponseCode cmdShutdownServer(const Command_ShutdownServer & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } - ResponseCode cmdUpdateServerMessage(const Command_UpdateServerMessage & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } -protected: - bool getCompressionSupport() const { return false; } + Response::ResponseCode cmdAddToList(const Command_AddToList & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; } + Response::ResponseCode cmdRemoveFromList(const Command_RemoveFromList & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; } + Response::ResponseCode cmdDeckList(const Command_DeckList & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; } + Response::ResponseCode cmdDeckNewDir(const Command_DeckNewDir & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; } + Response::ResponseCode cmdDeckDelDir(const Command_DeckDelDir & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; } + Response::ResponseCode cmdDeckDel(const Command_DeckDel & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; } + Response::ResponseCode cmdDeckUpload(const Command_DeckUpload & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; } + Response::ResponseCode cmdDeckDownload(const Command_DeckDownload & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; } + Response::ResponseCode cmdBanFromServer(const Command_BanFromServer & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; } + Response::ResponseCode cmdShutdownServer(const Command_ShutdownServer & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; } + Response::ResponseCode cmdUpdateServerMessage(const Command_UpdateServerMessage & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; } public: LocalServerInterface(LocalServer *_server); ~LocalServerInterface(); QString getAddress() const { return QString(); } - void sendProtocolItem(ProtocolItem *item, bool deleteItem = true); + void transmitProtocolItem(const ServerMessage &item); signals: - void itemToClient(ProtocolItem *item); + void itemToClient(const ServerMessage &item); public slots: void itemFromClient(const CommandContainer &item); }; diff --git a/cockatrice/src/pending_command.cpp b/cockatrice/src/pending_command.cpp deleted file mode 100644 index 9c698286..00000000 --- a/cockatrice/src/pending_command.cpp +++ /dev/null @@ -1,8 +0,0 @@ -#include "pending_command.h" -#include "protocol.h" - -void PendingCommand::processResponse(ProtocolResponse *response) -{ - emit finished(response); - emit finished(response->getResponseCode()); -} diff --git a/cockatrice/src/pending_command.h b/cockatrice/src/pending_command.h index 8cc59948..b582ed81 100644 --- a/cockatrice/src/pending_command.h +++ b/cockatrice/src/pending_command.h @@ -1,17 +1,15 @@ #ifndef PENDING_COMMAND_H #define PENDING_COMMAND_H -#include "protocol_datastructures.h" #include "pb/commands.pb.h" +#include "pb/response.pb.h" #include -class ProtocolResponse; - class PendingCommand : public QObject { Q_OBJECT signals: - void finished(ProtocolResponse *response); - void finished(ResponseCode response); + void finished(const Response &response); + void finished(Response::ResponseCode response); private: CommandContainer commandContainer; QVariant extraData; @@ -22,7 +20,11 @@ public: CommandContainer &getCommandContainer() { return commandContainer; } void setExtraData(const QVariant &_extraData) { extraData = _extraData; } QVariant getExtraData() const { return extraData; } - void processResponse(ProtocolResponse *response); + void processResponse(const Response &response) + { + emit finished(response); + emit finished(response.response_code()); + } int tick() { return ++ticks; } }; diff --git a/cockatrice/src/player.cpp b/cockatrice/src/player.cpp index d1c37f2d..5dd4fc51 100644 --- a/cockatrice/src/player.cpp +++ b/cockatrice/src/player.cpp @@ -12,7 +12,6 @@ #include "handcounter.h" #include "cardlist.h" #include "tab_game.h" -#include "protocol_items.h" #include "gamescene.h" #include "settingscache.h" #include "dlg_create_token.h" diff --git a/cockatrice/src/remoteclient.cpp b/cockatrice/src/remoteclient.cpp index ba492cdc..8015e189 100644 --- a/cockatrice/src/remoteclient.cpp +++ b/cockatrice/src/remoteclient.cpp @@ -1,20 +1,15 @@ #include -#include -#include -#include #include "remoteclient.h" #include "protocol.h" -#include "protocol_items.h" #include "pending_command.h" #include "pb/commands.pb.h" #include "pb/session_commands.pb.h" +#include "pb/response_login.pb.h" RemoteClient::RemoteClient(QObject *parent) - : AbstractClient(parent), timeRunning(0), lastDataReceived(0), topLevelItem(0) + : AbstractClient(parent), timeRunning(0), lastDataReceived(0), messageInProgress(false), messageLength(0) { - ProtocolItem::initializeHash(); - timer = new QTimer(this); timer->setInterval(1000); connect(timer, SIGNAL(timeout()), this, SLOT(ping())); @@ -24,7 +19,7 @@ RemoteClient::RemoteClient(QObject *parent) connect(socket, SIGNAL(readyRead()), this, SLOT(readData())); connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slotSocketError(QAbstractSocket::SocketError))); - xmlReader = new QXmlStreamReader; + connect(this, SIGNAL(serverIdentificationEventReceived(const Event_ServerIdentification &)), this, SLOT(processServerIdentificationEvent(const Event_ServerIdentification &))); } RemoteClient::~RemoteClient() @@ -46,61 +41,72 @@ void RemoteClient::slotConnected() setStatus(StatusAwaitingWelcome); } -void RemoteClient::loginResponse(ProtocolResponse *response) +void RemoteClient::processServerIdentificationEvent(const Event_ServerIdentification & /*event*/) { - if (response->getResponseCode() == RespOk) { - Response_Login *resp = qobject_cast(response); - if (!resp) { - disconnectFromServer(); - return; - } + setStatus(StatusLoggingIn); + + Command_Login cmdLogin; + cmdLogin.set_user_name(userName.toStdString()); + cmdLogin.set_password(password.toStdString()); + + PendingCommand *pend = prepareSessionCommand(cmdLogin); + connect(pend, SIGNAL(finished(const Response &)), this, SLOT(loginResponse(const Response &))); + sendCommand(pend); +} + +void RemoteClient::loginResponse(const Response &response) +{ + if (response.response_code() == Response::RespOk) { + const Response_Login &resp = response.GetExtension(Response_Login::ext); setStatus(StatusLoggedIn); - emit userInfoChanged(resp->getUserInfo()); - emit buddyListReceived(resp->getBuddyList()); - emit ignoreListReceived(resp->getIgnoreList()); + emit userInfoChanged(resp.user_info()); + + QList buddyList; + for (int i = resp.buddy_list_size() - 1; i >= 0; --i) + buddyList.append(resp.buddy_list(i)); + emit buddyListReceived(buddyList); + + QList ignoreList; + for (int i = resp.ignore_list_size() - 1; i >= 0; --i) + ignoreList.append(resp.ignore_list(i)); + emit ignoreListReceived(ignoreList); } else { - emit serverError(response->getResponseCode()); + emit serverError(response.response_code()); setStatus(StatusDisconnecting); } } void RemoteClient::readData() { - QByteArray data = socket->readAll(); - qDebug() << data; - xmlReader->addData(data); lastDataReceived = timeRunning; + QByteArray data = socket->readAll(); - while (!xmlReader->atEnd()) { - xmlReader->readNext(); - if (topLevelItem) - topLevelItem->readElement(xmlReader); - else if (xmlReader->isStartElement() && (xmlReader->name().toString() == "cockatrice_server_stream")) { - int serverVersion = xmlReader->attributes().value("version").toString().toInt(); - if (serverVersion != ProtocolItem::protocolVersion) { - emit protocolVersionMismatch(ProtocolItem::protocolVersion, serverVersion); - disconnectFromServer(); + inputBuffer.append(data); + + do { + if (!messageInProgress) { + if (inputBuffer.size() >= 4) { + messageLength = (((quint32) (unsigned char) inputBuffer[0]) << 24) + + (((quint32) (unsigned char) inputBuffer[1]) << 16) + + (((quint32) (unsigned char) inputBuffer[2]) << 8) + + ((quint32) (unsigned char) inputBuffer[3]); + inputBuffer.remove(0, 4); + messageInProgress = true; + } else return; - } -/* xmlWriter->writeStartDocument(); - xmlWriter->writeStartElement("cockatrice_client_stream"); - xmlWriter->writeAttribute("version", QString::number(ProtocolItem::protocolVersion)); - xmlWriter->writeAttribute("comp", "1"); -*/ - topLevelItem = new TopLevelProtocolItem; - connect(topLevelItem, SIGNAL(protocolItemReceived(ProtocolItem *)), this, SLOT(processProtocolItem(ProtocolItem *))); - - setStatus(StatusLoggingIn); - - Command_Login cmdLogin; - cmdLogin.set_user_name(userName.toStdString()); - cmdLogin.set_password(password.toStdString()); - - PendingCommand *pend = prepareSessionCommand(cmdLogin); - connect(pend, SIGNAL(finished(ProtocolResponse *)), this, SLOT(loginResponse(ProtocolResponse *))); - sendCommand(pend); } - } + if (inputBuffer.size() < messageLength) + return; + + ServerMessage newServerMessage; + newServerMessage.ParseFromArray(inputBuffer.data(), messageLength); + qDebug(QString::fromStdString(newServerMessage.ShortDebugString()).toUtf8()); + inputBuffer.remove(0, messageLength); + messageInProgress = false; + + processProtocolItem(newServerMessage); + } while (!inputBuffer.isEmpty()); + if (status == StatusDisconnecting) disconnectFromServer(); } @@ -131,12 +137,10 @@ void RemoteClient::connectToServer(const QString &hostname, unsigned int port, c void RemoteClient::disconnectFromServer() { - delete topLevelItem; - topLevelItem = 0; - - xmlReader->clear(); - timer->stop(); + + messageInProgress = false; + messageLength = 0; QList pc = pendingCommands.values(); for (int i = 0; i < pc.size(); i++) diff --git a/cockatrice/src/remoteclient.h b/cockatrice/src/remoteclient.h index 3b22b6b8..798cbb7f 100644 --- a/cockatrice/src/remoteclient.h +++ b/cockatrice/src/remoteclient.h @@ -5,8 +5,6 @@ #include "abstractclient.h" class QTimer; -class QXmlStreamReader; -class QXmlStreamWriter; class RemoteClient : public AbstractClient { Q_OBJECT @@ -21,15 +19,18 @@ private slots: void readData(); void slotSocketError(QAbstractSocket::SocketError error); void ping(); - void loginResponse(ProtocolResponse *response); + void processServerIdentificationEvent(const Event_ServerIdentification &event); + void loginResponse(const Response &response); private: static const int maxTimeout = 10; int timeRunning, lastDataReceived; + + QByteArray inputBuffer; + bool messageInProgress; + int messageLength; QTimer *timer; QTcpSocket *socket; - QXmlStreamReader *xmlReader; - TopLevelProtocolItem *topLevelItem; void sendCommandContainer(const CommandContainer &cont); public: diff --git a/cockatrice/src/window_main.cpp b/cockatrice/src/window_main.cpp index 7b53be12..0b2c7502 100644 --- a/cockatrice/src/window_main.cpp +++ b/cockatrice/src/window_main.cpp @@ -51,7 +51,7 @@ void MainWindow::updateTabMenu(QMenu *menu) void MainWindow::processConnectionClosedEvent(Event_ConnectionClosed *event) { - QString reason = event->getReason(); +/* QString reason = event->getReason(); client->disconnectFromServer(); QString reasonStr; if (reason == "too_many_connections") @@ -63,11 +63,13 @@ void MainWindow::processConnectionClosedEvent(Event_ConnectionClosed *event) else reasonStr = tr("Unknown reason."); QMessageBox::critical(this, tr("Connection closed"), tr("The server has terminated your connection.\nReason: %1").arg(reasonStr)); +*/ } void MainWindow::processServerShutdownEvent(Event_ServerShutdown *event) { - QMessageBox::information(this, tr("Scheduled server shutdown"), tr("The server is going to be restarted in %n minute(s).\nAll running games will be lost.\nReason for shutdown: %1", "", event->getMinutes()).arg(event->getReason())); +/* QMessageBox::information(this, tr("Scheduled server shutdown"), tr("The server is going to be restarted in %n minute(s).\nAll running games will be lost.\nReason for shutdown: %1", "", event->getMinutes()).arg(event->getReason())); + * */ } void MainWindow::statusChanged(ClientStatus _status) @@ -199,11 +201,11 @@ void MainWindow::serverTimeout() QMessageBox::critical(this, tr("Error"), tr("Server timeout")); } -void MainWindow::serverError(ResponseCode r) +void MainWindow::serverError(Response::ResponseCode r) { switch (r) { - case RespWrongPassword: QMessageBox::critical(this, tr("Error"), tr("Invalid login data.")); break; - case RespWouldOverwriteOldSession: QMessageBox::critical(this, tr("Error"), tr("There is already an active session using this user name.\nPlease close that session first and re-login.")); break; + case Response::RespWrongPassword: QMessageBox::critical(this, tr("Error"), tr("Invalid login data.")); break; + case Response::RespWouldOverwriteOldSession: QMessageBox::critical(this, tr("Error"), tr("There is already an active session using this user name.\nPlease close that session first and re-login.")); break; default: ; } } @@ -302,7 +304,7 @@ MainWindow::MainWindow(QWidget *parent) client = new RemoteClient(this); connect(client, SIGNAL(connectionClosedEventReceived(Event_ConnectionClosed *)), this, SLOT(processConnectionClosedEvent(Event_ConnectionClosed *))); connect(client, SIGNAL(serverShutdownEventReceived(Event_ServerShutdown *)), this, SLOT(processServerShutdownEvent(Event_ServerShutdown *))); - connect(client, SIGNAL(serverError(ResponseCode)), this, SLOT(serverError(ResponseCode))); + connect(client, SIGNAL(serverError(Response::ResponseCode)), this, SLOT(serverError(Response::ResponseCode))); connect(client, SIGNAL(socketError(const QString &)), this, SLOT(socketError(const QString &))); connect(client, SIGNAL(serverTimeout()), this, SLOT(serverTimeout())); connect(client, SIGNAL(statusChanged(ClientStatus)), this, SLOT(statusChanged(ClientStatus))); diff --git a/cockatrice/src/window_main.h b/cockatrice/src/window_main.h index 4d8b45d6..3acf6650 100644 --- a/cockatrice/src/window_main.h +++ b/cockatrice/src/window_main.h @@ -22,7 +22,7 @@ #include #include "abstractclient.h" -#include "protocol_datastructures.h" +#include "pb/response.pb.h" class TabSupervisor; class RemoteClient; @@ -38,7 +38,7 @@ private slots: void processConnectionClosedEvent(Event_ConnectionClosed *event); void processServerShutdownEvent(Event_ServerShutdown *event); void serverTimeout(); - void serverError(ResponseCode r); + void serverError(Response::ResponseCode r); void socketError(const QString &errorStr); void protocolVersionMismatch(int localVersion, int remoteVersion); void userInfoReceived(ServerInfo_User *userInfo); diff --git a/common/color.h b/common/color.h index c0f38ce4..441306cf 100644 --- a/common/color.h +++ b/common/color.h @@ -24,6 +24,7 @@ public: { return QColor(value / 65536, (value % 65536) / 256, value % 256); } +#endif color get_color() const // HACK { color c; @@ -32,7 +33,6 @@ public: c.set_b(value % 256); return c; } -#endif }; #endif \ No newline at end of file diff --git a/common/pb/proto/event_server_identification.proto b/common/pb/proto/event_server_identification.proto new file mode 100644 index 00000000..d4417c03 --- /dev/null +++ b/common/pb/proto/event_server_identification.proto @@ -0,0 +1,10 @@ +import "session_event.proto"; + +message Event_ServerIdentification { + extend SessionEvent { + optional Event_ServerIdentification ext = 500; + } + optional string server_name = 1; + optional string server_version = 2; + optional uint32 protocol_version = 3; +} diff --git a/common/pb/proto/session_event.proto b/common/pb/proto/session_event.proto index dd72e4e0..f97778ab 100644 --- a/common/pb/proto/session_event.proto +++ b/common/pb/proto/session_event.proto @@ -1,5 +1,6 @@ message SessionEvent { enum SessionEventType { + SERVER_IDENTIFICATION = 500; SERVER_MESSAGE = 1000; SERVER_SHUTDOWN = 1001; CONNECTION_CLOSED = 1002; diff --git a/common/protocol.cpp b/common/protocol.cpp index bd571194..e68e2839 100644 --- a/common/protocol.cpp +++ b/common/protocol.cpp @@ -1,55 +1,3 @@ -#include -#include -#include "protocol.h" - -ProtocolItem::ProtocolItem(const QString &_itemType, const QString &_itemSubType) - : SerializableItem_Map(_itemType, _itemSubType), receiverMayDelete(true) -{ -} - -void ProtocolItem::initializeHash() -{ -} - -BlaContainer::BlaContainer() - : ProtocolItem("container", "cmd"), resp(0), gameEventQueuePublic(0), gameEventQueueOmniscient(0), gameEventQueuePrivate(0), privatePlayerId(-1) -{ -} - -void BlaContainer::setResponse(ProtocolResponse *_resp) -{ - delete resp; - resp = _resp; -} - -void BlaContainer::enqueueGameEventPublic(GameEvent *event, int gameId, GameEventContext *context) -{ - if (!gameEventQueuePublic) - gameEventQueuePublic = new GameEventContainer(QList(), gameId); - gameEventQueuePublic->addGameEvent(event); - if (context) - gameEventQueuePublic->setContext(context); -} - -void BlaContainer::enqueueGameEventOmniscient(GameEvent *event, int gameId, GameEventContext *context) -{ - if (!gameEventQueueOmniscient) - gameEventQueueOmniscient = new GameEventContainer(QList(), gameId); - gameEventQueueOmniscient->addGameEvent(event); - if (context) - gameEventQueueOmniscient->setContext(context); -} - -void BlaContainer::enqueueGameEventPrivate(GameEvent *event, int gameId, int playerId, GameEventContext *context) -{ - if (!gameEventQueuePrivate) - gameEventQueuePrivate = new GameEventContainer(QList(), gameId); - gameEventQueuePrivate->addGameEvent(event); - privatePlayerId = playerId; - if (context) - gameEventQueuePrivate->setContext(context); -} - /* Response_DeckDownload::Response_DeckDownload(int _cmdId, ResponseCode _responseCode, DeckList *_deck) : ProtocolResponse(_cmdId, _responseCode, "deck_download") diff --git a/common/protocol.h b/common/protocol.h index 5c58aad8..52106efa 100644 --- a/common/protocol.h +++ b/common/protocol.h @@ -6,66 +6,70 @@ #include #include #include -#include "serializable_item.h" #include #include #include "pb/server_message.pb.h" -class QXmlStreamReader; -class QXmlStreamWriter; -class QXmlStreamAttributes; - -class ProtocolResponse; class DeckList; class GameEvent; class GameEventContainer; class GameEventContext; -class MoveCardToZone; -class ProtocolItem : public SerializableItem_Map { - Q_OBJECT -private: - bool receiverMayDelete; +static const int protocolVersion = 13; + +class GameEventStorageItem { public: - static const int protocolVersion = 13; - virtual int getItemId() const = 0; - bool getReceiverMayDelete() const { return receiverMayDelete; } - void setReceiverMayDelete(bool _receiverMayDelete) { receiverMayDelete = _receiverMayDelete; } - ProtocolItem(const QString &_itemType, const QString &_itemSubType); - bool isEmpty() const { return false; } + enum EventRecipient { SendToPrivate = 0x01, SendToOthers = 0x02}; + Q_DECLARE_FLAGS(EventRecipients, EventRecipient) +private: + ::google::protobuf::Message *event; + int playerId; + EventRecipients recipients; +public: + GameEventStorageItem(const ::google::protobuf::Message &_event, int _playerId, EventRecipients _recipients) + : event(_event.New()), playerId(_playerId), recipients(_recipients) + { + event->CopyFrom(_event); + } + ~GameEventStorageItem() + { + delete event; + } + const ::google::protobuf::Message &getEvent() const { return *event; } + int getPlayerId() const { return playerId; } + EventRecipients getRecipients() const { return recipients; } }; - -// ---------------- -// --- COMMANDS --- -// ---------------- +Q_DECLARE_OPERATORS_FOR_FLAGS(GameEventStorageItem::EventRecipients) class GameEventStorage { private: ::google::protobuf::Message *gameEventContext; - GameEventContainer *gameEventQueuePublic; - GameEventContainer *gameEventQueueOmniscient; - GameEventContainer *gameEventQueuePrivate; + QList gameEventList; int privatePlayerId; public: - GameEventStorage(); - ~GameEventStorage(); + GameEventStorage() + : gameEventContext(0) + { + } + ~GameEventStorage() + { + delete gameEventContext; + for (int i = 0; i < gameEventList.size(); ++i) + delete gameEventList[i]; + } void setGameEventContext(::google::protobuf::Message *_gameEventContext) { gameEventContext = _gameEventContext; } ::google::protobuf::Message *getGameEventContext() const { return gameEventContext; } - GameEventContainer *getGameEventQueuePublic() const { return gameEventQueuePublic; } - void enqueueGameEventPublic(const ::google::protobuf::Message &event, int playerId); - - GameEventContainer *getGameEventQueueOmniscient() const { return gameEventQueueOmniscient; } - void enqueueGameEventOmniscient(const ::google::protobuf::Message &event, int playerId); - - GameEventContainer *getGameEventQueuePrivate() const { return gameEventQueuePrivate; } - void enqueueGameEventPrivate(const ::google::protobuf::Message &event, int playerId); - // XXX - DRAN DENKEN, dass privatePlayerId gesetzt wird int getPrivatePlayerId() const { return privatePlayerId; } - void enqueueGameEvent(const ::google::protobuf::Message &event, int playerId); + void enqueueGameEvent(const ::google::protobuf::Message &event, int playerId, GameEventStorageItem::EventRecipients recipients = GameEventStorageItem::SendToPrivate | GameEventStorageItem::SendToOthers, int _privatePlayerId = -1) + { + gameEventList.append(new GameEventStorageItem(event, playerId, recipients)); + if (_privatePlayerId != -1) + privatePlayerId = _privatePlayerId; + } }; class ResponseContainer { @@ -74,7 +78,14 @@ private: QList > preResponseQueue, postResponseQueue; public: ResponseContainer() : responseExtension(0) { } - ~ResponseContainer() { /* XXX responseExtension und Inhalt beider Listen löschen */ } + ~ResponseContainer() + { + delete responseExtension; + for (int i = 0; i < preResponseQueue.size(); ++i) + delete preResponseQueue[i].second; + for (int i = 0; i < postResponseQueue.size(); ++i) + delete postResponseQueue[i].second; + } void setResponseExtension(::google::protobuf::Message *_responseExtension) { responseExtension = _responseExtension; } ::google::protobuf::Message *getResponseExtension() const { return responseExtension; } void enqueuePreResponseItem(ServerMessage::MessageType type, ::google::protobuf::Message *item) { preResponseQueue.append(qMakePair(type, item)); } diff --git a/common/server.cpp b/common/server.cpp index 4a37dadc..762c0874 100644 --- a/common/server.cpp +++ b/common/server.cpp @@ -22,7 +22,9 @@ #include "server_counter.h" #include "server_room.h" #include "server_protocolhandler.h" -#include "protocol_datastructures.h" +#include "pb/event_user_joined.pb.h" +#include "pb/event_user_left.pb.h" +#include "pb/event_list_rooms.pb.h" #include #include @@ -56,14 +58,13 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString if (authState == PasswordWrong) return authState; - ServerInfo_User *data = getUserData(name); - data->setAddress(session->getAddress()); - name = data->getName(); // Compensate for case indifference + ServerInfo_User data = getUserData(name); + data.set_address(session->getAddress().toStdString()); + name = QString::fromStdString(data.name()); // Compensate for case indifference if (authState == PasswordRight) { if (users.contains(name)) { qDebug("Login denied: would overwrite old session"); - delete data; return WouldOverwriteOldSession; } } else if (authState == UnknownUser) { @@ -74,7 +75,7 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString while (users.contains(tempName) || userExists(tempName)) tempName = name + "_" + QString::number(++i); name = tempName; - data->setName(name); + data.set_name(name.toStdString()); } session->setUserInfo(data); @@ -85,11 +86,13 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString session->setSessionId(startSession(name, session->getAddress())); qDebug() << "session id:" << session->getSessionId(); - Event_UserJoined *event = new Event_UserJoined(new ServerInfo_User(data, false)); + Event_UserJoined event; + event.mutable_user_info()->CopyFrom(session->copyUserInfo(false)); + SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event); for (int i = 0; i < clients.size(); ++i) if (clients[i]->getAcceptsUserListChanges()) - clients[i]->sendProtocolItem(event, false); - delete event; + clients[i]->sendProtocolItem(*se); + delete se; return authState; } @@ -106,14 +109,16 @@ void Server::removeClient(Server_ProtocolHandler *client) clients.removeAt(clients.indexOf(client)); ServerInfo_User *data = client->getUserInfo(); if (data) { - Event_UserLeft *event = new Event_UserLeft(data->getName()); + Event_UserLeft event; + event.set_name(data->name()); + SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event); for (int i = 0; i < clients.size(); ++i) if (clients[i]->getAcceptsUserListChanges()) - clients[i]->sendProtocolItem(event, false); - delete event; + clients[i]->sendProtocolItem(*se); + delete se; - users.remove(data->getName()); - qDebug() << "Server::removeClient: name=" << data->getName(); + users.remove(QString::fromStdString(data->name())); + qDebug() << "Server::removeClient: name=" << QString::fromStdString(data->name()); if (client->getSessionId() != -1) endSession(client->getSessionId()); @@ -126,16 +131,19 @@ void Server::broadcastRoomUpdate() { QMutexLocker locker(&serverMutex); Server_Room *room = static_cast(sender()); - QList eventRoomList; + Event_ListRooms event; + + ServerInfo_Room *roomInfo = event.add_room_list(); room->roomMutex.lock(); - eventRoomList.append(new ServerInfo_Room(room->getId(), room->getName(), room->getDescription(), room->getGames().size(), room->size(), room->getAutoJoin())); + roomInfo->CopyFrom(room->getInfo(false)); room->roomMutex.unlock(); - Event_ListRooms *event = new Event_ListRooms(eventRoomList); + + SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event); for (int i = 0; i < clients.size(); ++i) if (clients[i]->getAcceptsRoomListChanges()) - clients[i]->sendProtocolItem(event, false); - delete event; + clients[i]->sendProtocolItem(*se); + delete se; } void Server::addRoom(Server_Room *newRoom) diff --git a/common/server.h b/common/server.h index 467642f6..92288bf5 100644 --- a/common/server.h +++ b/common/server.h @@ -42,8 +42,10 @@ public: virtual int getMaxGamesPerUser() const { return 0; } virtual bool getThreaded() const = 0; - virtual QMap getBuddyList(const QString &name) = 0; - virtual QMap getIgnoreList(const QString &name) = 0; + virtual QMap getBuddyList(const QString &name) = 0; + virtual QMap getIgnoreList(const QString &name) = 0; + virtual bool isInBuddyList(const QString &whoseList, const QString &who) = 0; + virtual bool isInIgnoreList(const QString &whoseList, const QString &who) = 0; protected: void prepareDestroy(); QList clients; @@ -54,7 +56,7 @@ protected: virtual void endSession(int sessionId) = 0; virtual bool userExists(const QString &user) = 0; virtual AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password) = 0; - virtual ServerInfo_User *getUserData(const QString &name) = 0; + virtual ServerInfo_User getUserData(const QString &name) = 0; int getUsersCount() const; int getGamesCount() const; int nextGameId; diff --git a/common/server_cardzone.cpp b/common/server_cardzone.cpp index 3e5d6bc7..a69cdc71 100644 --- a/common/server_cardzone.cpp +++ b/common/server_cardzone.cpp @@ -26,7 +26,7 @@ #include "server_game.h" #include "pb/command_move_card.pb.h" -Server_CardZone::Server_CardZone(Server_Player *_player, const QString &_name, bool _has_coords, ZoneType _type) +Server_CardZone::Server_CardZone(Server_Player *_player, const QString &_name, bool _has_coords, ServerInfo_Zone::ZoneType _type) : player(_player), name(_name), has_coords(_has_coords), type(_type), cardsBeingLookedAt(0) { } @@ -62,7 +62,7 @@ Server_Card *Server_CardZone::getCard(int id, int *position) { QMutexLocker locker(&player->getGame()->gameMutex); - if (type != HiddenZone) { + if (type != ServerInfo_Zone::HiddenZone) { QListIterator CardIterator(cards); int i = 0; while (CardIterator.hasNext()) { @@ -160,7 +160,7 @@ bool Server_CardZone::isColumnEmpty(int x, int y) const return !coordMap.contains((x / 3) * 3); } -void Server_CardZone::moveCard(BlaContainer *bla, QMap &coordMap, Server_Card *card, int x, int y) +void Server_CardZone::moveCard(GameEventStorage &ges, QMap &coordMap, Server_Card *card, int x, int y) { QMutexLocker locker(&player->getGame()->gameMutex); @@ -168,13 +168,13 @@ void Server_CardZone::moveCard(BlaContainer *bla, QMap &coor CardToMove *cardToMove = new CardToMove; cardToMove->set_card_id(card->getId()); - player->moveCard(bla, this, QList() << cardToMove, this, x, y, card->getFaceDown(), false); + player->moveCard(ges, this, QList() << cardToMove, this, x, y, card->getFaceDown(), false); delete cardToMove; coordMap.insert(y * 10000 + x, card); } -void Server_CardZone::fixFreeSpaces(BlaContainer *bla) +void Server_CardZone::fixFreeSpaces(GameEventStorage &ges) { QMutexLocker locker(&player->getGame()->gameMutex); @@ -193,15 +193,15 @@ void Server_CardZone::fixFreeSpaces(BlaContainer *bla) if (!coordMap.contains(y * 10000 + baseX)) { if (coordMap.contains(y * 10000 + baseX + 1)) - moveCard(bla, coordMap, coordMap.value(y * 10000 + baseX + 1), baseX, y); + moveCard(ges, coordMap, coordMap.value(y * 10000 + baseX + 1), baseX, y); else if (coordMap.contains(y * 10000 + baseX + 2)) { - moveCard(bla, coordMap, coordMap.value(y * 10000 + baseX + 2), baseX, y); + moveCard(ges, coordMap, coordMap.value(y * 10000 + baseX + 2), baseX, y); continue; } else continue; } if (!coordMap.contains(y * 10000 + baseX + 1) && coordMap.contains(y * 10000 + baseX + 2)) - moveCard(bla, coordMap, coordMap.value(y * 10000 + baseX + 2), baseX + 1, y); + moveCard(ges, coordMap, coordMap.value(y * 10000 + baseX + 2), baseX + 1, y); } } diff --git a/common/server_cardzone.h b/common/server_cardzone.h index ee0a7f3a..c4a1f998 100644 --- a/common/server_cardzone.h +++ b/common/server_cardzone.h @@ -22,6 +22,7 @@ #include #include +#include #include "pb/serverinfo_zone.pb.h" class Server_Card; diff --git a/common/server_game.cpp b/common/server_game.cpp index 734db1cb..757efeda 100644 --- a/common/server_game.cpp +++ b/common/server_game.cpp @@ -25,11 +25,26 @@ #include "server_card.h" #include "server_cardzone.h" #include "server_counter.h" +#include "decklist.h" +#include "pb/event_game_closed.pb.h" +#include "pb/event_game_host_changed.pb.h" +#include "pb/event_game_state_changed.pb.h" +#include "pb/event_connection_state_changed.pb.h" +#include "pb/event_kicked.pb.h" +#include "pb/event_ping.pb.h" +#include "pb/event_join.pb.h" +#include "pb/event_leave.pb.h" +#include "pb/event_delete_arrow.pb.h" +#include "pb/event_set_active_player.pb.h" +#include "pb/event_set_active_phase.pb.h" +#include "pb/serverinfo_playerping.pb.h" +#include +#include "protocol.h" #include #include Server_Game::Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *_room) - : QObject(), room(_room), hostId(0), creatorInfo(new ServerInfo_User(_creator->getUserInfo())), gameStarted(false), gameId(_gameId), description(_description), password(_password), maxPlayers(_maxPlayers), gameTypes(_gameTypes), activePlayer(-1), activePhase(-1), onlyBuddies(_onlyBuddies), onlyRegistered(_onlyRegistered), spectatorsAllowed(_spectatorsAllowed), spectatorsNeedPassword(_spectatorsNeedPassword), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), inactivityCounter(0), secondsElapsed(0), gameMutex(QMutex::Recursive) + : QObject(), room(_room), hostId(0), creatorInfo(new ServerInfo_User(_creator->copyUserInfo(false))), gameStarted(false), gameId(_gameId), description(_description), password(_password), maxPlayers(_maxPlayers), gameTypes(_gameTypes), activePlayer(-1), activePhase(-1), onlyBuddies(_onlyBuddies), onlyRegistered(_onlyRegistered), spectatorsAllowed(_spectatorsAllowed), spectatorsNeedPassword(_spectatorsNeedPassword), spectatorsCanTalk(_spectatorsCanTalk), spectatorsSeeEverything(_spectatorsSeeEverything), inactivityCounter(0), secondsElapsed(0), gameMutex(QMutex::Recursive) { connect(this, SIGNAL(sigStartGameIfReady()), this, SLOT(doStartGameIfReady()), Qt::QueuedConnection); @@ -47,7 +62,7 @@ Server_Game::~Server_Game() QMutexLocker roomLocker(&room->roomMutex); QMutexLocker locker(&gameMutex); - sendGameEvent(new Event_GameClosed); + sendGameEventContainer(prepareGameEvent(Event_GameClosed(), -1)); QMapIterator playerIterator(players); while (playerIterator.hasNext()) @@ -56,13 +71,16 @@ Server_Game::~Server_Game() room->removeGame(this); delete creatorInfo; + creatorInfo = 0; qDebug() << "Server_Game destructor: gameId=" << gameId; } void Server_Game::pingClockTimeout() { QMutexLocker locker(&gameMutex); - ++secondsElapsed; + + Event_Ping event; + event.set_seconds_elapsed(++secondsElapsed); QList pingList; QMapIterator playerIterator(players); @@ -79,9 +97,12 @@ void Server_Game::pingClockTimeout() allPlayersInactive = false; } else pingTime = -1; - pingList.append(new ServerInfo_PlayerPing(player->getPlayerId(), pingTime)); + + ServerInfo_PlayerPing *pingInfo = event.add_ping_list(); + pingInfo->set_player_id(player->getPlayerId()); + pingInfo->set_ping_time(pingTime); } - sendGameEvent(new Event_Ping(secondsElapsed, pingList)); + sendGameEventContainer(prepareGameEvent(event, -1)); const int maxTime = room->getServer()->getMaxGameInactivityTime(); if (allPlayersInactive) { @@ -144,7 +165,15 @@ void Server_Game::doStartGameIfReady() playerIterator.toFront(); while (playerIterator.hasNext()) { Server_Player *player = playerIterator.next().value(); - sendGameEventToPlayer(player, new Event_GameStateChanged(gameStarted, 0, 0, getGameState(player))); + Event_GameStateChanged event; + event.set_game_started(true); + event.set_active_player_id(0); + event.set_active_phase(0); + QListIterator gameStateIterator(getGameState(player)); + while (gameStateIterator.hasNext()) + event.add_player_list()->CopyFrom(gameStateIterator.next()); + + player->sendGameEvent(prepareGameEvent(event, -1)); } /* QSqlQuery query; @@ -200,31 +229,37 @@ void Server_Game::stopGameIfFinished() playerIterator.toFront(); while (playerIterator.hasNext()) { Server_Player *player = playerIterator.next().value(); - sendGameEventToPlayer(player, new Event_GameStateChanged(gameStarted, -1, -1, getGameState(player))); + Event_GameStateChanged event; + event.set_game_started(false); + QListIterator gameStateIterator(getGameState(player)); + while (gameStateIterator.hasNext()) + event.add_player_list()->CopyFrom(gameStateIterator.next()); + + player->sendGameEvent(prepareGameEvent(event, -1)); } } -ResponseCode Server_Game::checkJoin(ServerInfo_User *user, const QString &_password, bool spectator, bool overrideRestrictions) +Response::ResponseCode Server_Game::checkJoin(ServerInfo_User *user, const QString &_password, bool spectator, bool overrideRestrictions) { - if (!(overrideRestrictions && (user->getUserLevel() & ServerInfo_User::IsModerator))) { + if (!(overrideRestrictions && (user->user_level() & ServerInfo_User::IsModerator))) { if ((_password != password) && !(spectator && !spectatorsNeedPassword)) - return RespWrongPassword; - if (!(user->getUserLevel() & ServerInfo_User::IsRegistered) && onlyRegistered) - return RespUserLevelTooLow; + return Response::RespWrongPassword; + if (!(user->user_level() & ServerInfo_User::IsRegistered) && onlyRegistered) + return Response::RespUserLevelTooLow; if (onlyBuddies) - if (!room->getServer()->getBuddyList(creatorInfo->getName()).contains(user->getName())) - return RespOnlyBuddies; - if (room->getServer()->getIgnoreList(creatorInfo->getName()).contains(user->getName())) - return RespInIgnoreList; + if (!room->getServer()->isInBuddyList(QString::fromStdString(creatorInfo->name()), QString::fromStdString(user->name()))) + return Response::RespOnlyBuddies; + if (room->getServer()->isInIgnoreList(QString::fromStdString(creatorInfo->name()), QString::fromStdString(user->name()))) + return Response::RespInIgnoreList; if (spectator) { if (!spectatorsAllowed) - return RespSpectatorsNotAllowed; + return Response::RespSpectatorsNotAllowed; } } if (!spectator && (gameStarted || (getPlayerCount() >= getMaxPlayers()))) - return RespGameFull; + return Response::RespGameFull; - return RespOk; + return Response::RespOk; } bool Server_Game::containsUser(const QString &userName) const @@ -233,7 +268,7 @@ bool Server_Game::containsUser(const QString &userName) const QMapIterator playerIterator(players); while (playerIterator.hasNext()) - if (playerIterator.next().value()->getUserInfo()->getName() == userName) + if (playerIterator.next().value()->getUserInfo()->name() == userName.toStdString()) return true; return false; } @@ -245,13 +280,17 @@ Server_Player *Server_Game::addPlayer(Server_ProtocolHandler *handler, bool spec const QList &keyList = players.keys(); int playerId = keyList.isEmpty() ? 0 : (keyList.last() + 1); - Server_Player *newPlayer = new Server_Player(this, playerId, handler->getUserInfo(), spectator, handler); + Server_Player *newPlayer = new Server_Player(this, playerId, handler->copyUserInfo(true), spectator, handler); newPlayer->moveToThread(thread()); - sendGameEvent(new Event_Join(newPlayer->getProperties())); + + Event_Join joinEvent; + joinEvent.mutable_player_properties()->CopyFrom(newPlayer->getProperties()); + sendGameEventContainer(prepareGameEvent(joinEvent, -1)); + players.insert(playerId, newPlayer); - if (newPlayer->getUserInfo()->getName() == creatorInfo->getName()) { + if (newPlayer->getUserInfo()->name() == creatorInfo->name()) { hostId = playerId; - sendGameEvent(new Event_GameHostChanged(playerId)); + sendGameEventContainer(prepareGameEvent(Event_GameHostChanged(), playerId)); } if (broadcastUpdate) @@ -268,7 +307,7 @@ void Server_Game::removePlayer(Server_Player *player) players.remove(player->getPlayerId()); removeArrowsToPlayer(player); - sendGameEvent(new Event_Leave(player->getPlayerId())); + sendGameEventContainer(prepareGameEvent(Event_Leave(), player->getPlayerId())); bool playerActive = activePlayer == player->getPlayerId(); bool playerHost = hostId == player->getPlayerId(); bool spectator = player->getSpectator(); @@ -289,7 +328,7 @@ void Server_Game::removePlayer(Server_Player *player) } if (newHostId != -1) { hostId = newHostId; - sendGameEvent(new Event_GameHostChanged(hostId)); + sendGameEventContainer(prepareGameEvent(Event_GameHostChanged(), hostId)); } } stopGameIfFinished(); @@ -319,7 +358,10 @@ void Server_Game::removeArrowsToPlayer(Server_Player *player) toDelete.append(a); } for (int i = 0; i < toDelete.size(); ++i) { - sendGameEvent(new Event_DeleteArrow(p->getPlayerId(), toDelete[i]->getId())); + Event_DeleteArrow event; + event.set_arrow_id(toDelete[i]->getId()); + sendGameEventContainer(prepareGameEvent(event, p->getPlayerId())); + p->deleteArrow(toDelete[i]->getId()); } } @@ -334,7 +376,8 @@ bool Server_Game::kickPlayer(int playerId) if (!playerToKick) return false; - sendGameEventToPlayer(playerToKick, new Event_Kicked); + playerToKick->sendGameEvent(prepareGameEvent(Event_Kicked(), -1)); + removePlayer(playerToKick); return true; @@ -345,7 +388,11 @@ void Server_Game::setActivePlayer(int _activePlayer) QMutexLocker locker(&gameMutex); activePlayer = _activePlayer; - sendGameEvent(new Event_SetActivePlayer(activePlayer, activePlayer)); + + Event_SetActivePlayer event; + event.set_active_player_id(activePlayer); + sendGameEventContainer(prepareGameEvent(event, -1)); + setActivePhase(0); } @@ -359,13 +406,20 @@ void Server_Game::setActivePhase(int _activePhase) QList toDelete = player->getArrows().values(); for (int i = 0; i < toDelete.size(); ++i) { Server_Arrow *a = toDelete[i]; - sendGameEvent(new Event_DeleteArrow(player->getPlayerId(), a->getId())); + + Event_DeleteArrow event; + event.set_arrow_id(a->getId()); + sendGameEventContainer(prepareGameEvent(event, player->getPlayerId())); + player->deleteArrow(a->getId()); } } activePhase = _activePhase; - sendGameEvent(new Event_SetActivePhase(-1, activePhase)); + + Event_SetActivePhase event; + event.set_phase(activePhase); + sendGameEventContainer(prepareGameEvent(event, -1)); } void Server_Game::nextTurn() @@ -389,163 +443,161 @@ void Server_Game::postConnectionStatusUpdate(Server_Player *player, bool connect { QMutexLocker locker(&gameMutex); - sendGameEvent(new Event_ConnectionStateChanged(player->getPlayerId(), connectionStatus)); + Event_ConnectionStateChanged event; + event.set_connected(connectionStatus); + sendGameEventContainer(prepareGameEvent(event, player->getPlayerId())); } -QList Server_Game::getGameState(Server_Player *playerWhosAsking) const +QList Server_Game::getGameState(Server_Player *playerWhosAsking) const { QMutexLocker locker(&gameMutex); - QList result; + QList result; QMapIterator playerIterator(players); while (playerIterator.hasNext()) { Server_Player *player = playerIterator.next().value(); - + + ServerInfo_Player playerInfo; + playerInfo.mutable_properties()->CopyFrom(player->getProperties()); + if (player == playerWhosAsking) + playerInfo.set_deck_list(player->getDeck()->writeToString_Native().toStdString()); + QList arrowList; QMapIterator arrowIterator(player->getArrows()); while (arrowIterator.hasNext()) { Server_Arrow *arrow = arrowIterator.next().value(); Server_Card *targetCard = qobject_cast(arrow->getTargetItem()); - if (targetCard) - arrowList.append(new ServerInfo_Arrow( - arrow->getId(), - arrow->getStartCard()->getZone()->getPlayer()->getPlayerId(), - arrow->getStartCard()->getZone()->getName(), - arrow->getStartCard()->getId(), - targetCard->getZone()->getPlayer()->getPlayerId(), - targetCard->getZone()->getName(), - targetCard->getId(), - arrow->getColor() - )); - else - arrowList.append(new ServerInfo_Arrow( - arrow->getId(), - arrow->getStartCard()->getZone()->getPlayer()->getPlayerId(), - arrow->getStartCard()->getZone()->getName(), - arrow->getStartCard()->getId(), - qobject_cast(arrow->getTargetItem())->getPlayerId(), - QString(), - -1, - arrow->getColor() - )); + ServerInfo_Arrow *arrowInfo = playerInfo.add_arrow_list(); + arrowInfo->set_id(arrow->getId()); + arrowInfo->set_start_player_id(arrow->getStartCard()->getZone()->getPlayer()->getPlayerId()); + arrowInfo->set_start_zone(arrow->getStartCard()->getZone()->getName().toStdString()); + arrowInfo->set_start_card_id(arrow->getStartCard()->getId()); + arrowInfo->mutable_arrow_color()->CopyFrom(arrow->getColor().get_color()); + if (targetCard) { + arrowInfo->set_target_player_id(targetCard->getZone()->getPlayer()->getPlayerId()); + arrowInfo->set_target_zone(targetCard->getZone()->getName().toStdString()); + arrowInfo->set_target_card_id(targetCard->getId()); + } else + arrowInfo->set_target_player_id(qobject_cast(arrow->getTargetItem())->getPlayerId()); } - - QList counterList; + QMapIterator counterIterator(player->getCounters()); while (counterIterator.hasNext()) { Server_Counter *counter = counterIterator.next().value(); - counterList.append(new ServerInfo_Counter(counter->getId(), counter->getName(), counter->getColor(), counter->getRadius(), counter->getCount())); + ServerInfo_Counter *counterInfo = playerInfo.add_counter_list(); + counterInfo->set_id(counter->getId()); + counterInfo->set_name(counter->getName().toStdString()); + counterInfo->mutable_counter_color()->CopyFrom(counter->getColor().get_color()); + counterInfo->set_radius(counter->getRadius()); + counterInfo->set_count(counter->getCount()); } QList zoneList; QMapIterator zoneIterator(player->getZones()); while (zoneIterator.hasNext()) { Server_CardZone *zone = zoneIterator.next().value(); - QList cardList; + ServerInfo_Zone *zoneInfo = playerInfo.add_zone_list(); + zoneInfo->set_name(zone->getName().toStdString()); + zoneInfo->set_type(zone->getType()); + zoneInfo->set_with_coords(zone->hasCoords()); + zoneInfo->set_card_count(zone->cards.size()); if ( - (((playerWhosAsking == player) || (playerWhosAsking->getSpectator() && spectatorsSeeEverything)) && (zone->getType() != HiddenZone)) - || ((playerWhosAsking != player) && (zone->getType() == PublicZone)) + (((playerWhosAsking == player) || (playerWhosAsking->getSpectator() && spectatorsSeeEverything)) && (zone->getType() != ServerInfo_Zone::HiddenZone)) + || ((playerWhosAsking != player) && (zone->getType() == ServerInfo_Zone::PublicZone)) ) { QListIterator cardIterator(zone->cards); while (cardIterator.hasNext()) { Server_Card *card = cardIterator.next(); + ServerInfo_Card *cardInfo = zoneInfo->add_card_list(); QString displayedName = card->getFaceDown() ? QString() : card->getName(); + cardInfo->set_id(card->getId()); + cardInfo->set_name(displayedName.toStdString()); + cardInfo->set_x(card->getX()); + cardInfo->set_y(card->getY()); + cardInfo->set_face_down(card->getFaceDown()); + cardInfo->set_tapped(card->getTapped()); + cardInfo->set_attacking(card->getAttacking()); + cardInfo->set_color(card->getColor().toStdString()); + cardInfo->set_pt(card->getPT().toStdString()); + cardInfo->set_annotation(card->getAnnotation().toStdString()); + cardInfo->set_destroy_on_zone_change(card->getDestroyOnZoneChange()); + cardInfo->set_doesnt_untap(card->getDoesntUntap()); + QList cardCounterList; QMapIterator cardCounterIterator(card->getCounters()); while (cardCounterIterator.hasNext()) { cardCounterIterator.next(); - cardCounterList.append(new ServerInfo_CardCounter(cardCounterIterator.key(), cardCounterIterator.value())); + ServerInfo_CardCounter *counterInfo = cardInfo->add_counter_list(); + counterInfo->set_id(cardCounterIterator.key()); + counterInfo->set_value(cardCounterIterator.value()); } - - int attachPlayerId = -1; - QString attachZone; - int attachCardId = -1; + if (card->getParentCard()) { - attachPlayerId = card->getParentCard()->getZone()->getPlayer()->getPlayerId(); - attachZone = card->getParentCard()->getZone()->getName(); - attachCardId = card->getParentCard()->getId(); + cardInfo->set_attach_player_id(card->getParentCard()->getZone()->getPlayer()->getPlayerId()); + cardInfo->set_attach_zone(card->getParentCard()->getZone()->getName().toStdString()); + cardInfo->set_attach_card_id(card->getParentCard()->getId()); } - cardList.append(new ServerInfo_Card(card->getId(), displayedName, card->getX(), card->getY(), card->getFaceDown(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), card->getDoesntUntap(), cardCounterList, attachPlayerId, attachZone, attachCardId)); } } - zoneList.append(new ServerInfo_Zone(zone->getName(), zone->getType(), zone->hasCoords(), zone->cards.size(), cardList)); } - - result.append(new ServerInfo_Player(player->getProperties(), player == playerWhosAsking ? player->getDeck() : 0, zoneList, counterList, arrowList)); + + result.append(playerInfo); } return result; } -void Server_Game::sendGameEvent(GameEvent *event, GameEventContext *context, Server_Player *exclude) -{ - sendGameEventContainer(new GameEventContainer(QList() << event, -1, context), exclude); -} - -void Server_Game::sendGameEventContainer(GameEventContainer *cont, Server_Player *exclude, bool excludeOmniscient) +void Server_Game::sendGameEventContainer(GameEventContainer *cont, GameEventStorageItem::EventRecipients recipients, int privatePlayerId) { QMutexLocker locker(&gameMutex); - cont->setGameId(gameId); + cont->set_game_id(gameId); QMapIterator playerIterator(players); while (playerIterator.hasNext()) { Server_Player *p = playerIterator.next().value(); - if ((p != exclude) && !(excludeOmniscient && p->getSpectator() && spectatorsSeeEverything)) - p->sendProtocolItem(cont, false); - } - - delete cont; -} - -void Server_Game::sendGameEventContainerOmniscient(GameEventContainer *cont, Server_Player *exclude) -{ - QMutexLocker locker(&gameMutex); - - cont->setGameId(gameId); - QMapIterator playerIterator(players); - while (playerIterator.hasNext()) { - Server_Player *p = playerIterator.next().value(); - if ((p != exclude) && (p->getSpectator() && spectatorsSeeEverything)) - p->sendProtocolItem(cont, false); + const bool playerPrivate = (p->getPlayerId() == privatePlayerId) || (p->getSpectator() && spectatorsSeeEverything); + if ((recipients.testFlag(GameEventStorageItem::SendToPrivate) && playerPrivate) || (recipients.testFlag(GameEventStorageItem::SendToOthers) && !playerPrivate)) + p->sendGameEvent(cont); } delete cont; } -void Server_Game::sendGameEventToPlayer(Server_Player *player, GameEvent *event) +GameEventContainer *Server_Game::prepareGameEvent(const ::google::protobuf::Message &gameEvent, int playerId, GameEventContext *context) { - player->sendProtocolItem(new GameEventContainer(QList() << event, gameId)); + GameEventContainer *cont = new GameEventContainer; + cont->set_game_id(gameId); + if (context) + cont->mutable_context()->CopyFrom(*context); + GameEvent *event = cont->add_event_list(); + if (playerId != -1) + event->set_player_id(playerId); + event->GetReflection()->MutableMessage(event, gameEvent.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(gameEvent); + return cont; } -ServerInfo_Game *Server_Game::getInfo() const +ServerInfo_Game Server_Game::getInfo() const { QMutexLocker locker(&gameMutex); - if (players.isEmpty()) - // Game is closing - return new ServerInfo_Game(room->getId(), getGameId(), QString(), false, 0, getMaxPlayers(), false, QList(), 0, false, 0); - else { - // Game is open - - QList gameTypeList; + ServerInfo_Game result; + result.set_room_id(room->getId()); + result.set_game_id(getGameId()); + result.set_max_players(getMaxPlayers()); + if (!players.isEmpty()) { for (int i = 0; i < gameTypes.size(); ++i) - gameTypeList.append(new GameTypeId(gameTypes[i])); + result.add_game_types(gameTypes[i]); - return new ServerInfo_Game( - room->getId(), - getGameId(), - getDescription(), - !getPassword().isEmpty(), - getPlayerCount(), - getMaxPlayers(), - gameStarted, - gameTypeList, - new ServerInfo_User(getCreatorInfo(), false), - onlyBuddies, - onlyRegistered, - getSpectatorsAllowed(), - getSpectatorsNeedPassword(), - getSpectatorCount() - ); + result.set_description(getDescription().toStdString()); + result.set_with_password(!getPassword().isEmpty()); + result.set_player_count(getPlayerCount()); + result.set_started(gameStarted); + result.mutable_creator_info()->CopyFrom(*getCreatorInfo()); + result.set_only_buddies(onlyBuddies); + result.set_only_registered(onlyRegistered); + result.set_spectators_allowed(getSpectatorsAllowed()); + result.set_spectators_need_password(getSpectatorsNeedPassword()); + result.set_spectators_count(getSpectatorCount()); } + return result; } diff --git a/common/server_game.h b/common/server_game.h index ab1f93e9..eee07fed 100644 --- a/common/server_game.h +++ b/common/server_game.h @@ -28,6 +28,7 @@ #include "protocol.h" #include "pb/response.pb.h" #include "pb/serverinfo_player.pb.h" +#include "pb/serverinfo_game.pb.h" class QTimer; class GameEventContainer; @@ -65,7 +66,7 @@ public: mutable QMutex gameMutex; Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *parent); ~Server_Game(); - ServerInfo_Game *getInfo() const; + ServerInfo_Game getInfo() const; int getHostId() const { return hostId; } ServerInfo_User *getCreatorInfo() const { return creatorInfo; } bool getGameStarted() const { return gameStarted; } @@ -98,14 +99,10 @@ public: QList getGameState(Server_Player *playerWhosAsking) const; - GameEventContainer *prepareGameEvent(const ::google::protobuf::Message &gameEvent, int playerId); - GameEventContainer *prepareGameEvent(const ::google::protobuf::Message &gameEvent, int playerId, const GameEventContext &context); + GameEventContainer *prepareGameEvent(const ::google::protobuf::Message &gameEvent, int playerId, GameEventContext *context = 0); GameEventContext prepareGameEventContext(const ::google::protobuf::Message &gameEventContext); -// void sendGameEvent(GameEvent *event, GameEventContext *context = 0, Server_Player *exclude = 0); - void sendGameEventContainer(GameEventContainer *cont, Server_Player *exclude = 0, bool excludeOmniscient = false); - void sendGameEventContainerOmniscient(GameEventContainer *cont, Server_Player *exclude = 0); - void sendGameEventToPlayer(Server_Player *player, GameEvent *event); + void sendGameEventContainer(GameEventContainer *cont, GameEventStorageItem::EventRecipients recipients = GameEventStorageItem::SendToPrivate | GameEventStorageItem::SendToOthers, int privatePlayerId = -1); }; #endif diff --git a/common/server_player.cpp b/common/server_player.cpp index ee9c1c0b..b04321df 100644 --- a/common/server_player.cpp +++ b/common/server_player.cpp @@ -6,12 +6,19 @@ #include "server_game.h" #include "server_protocolhandler.h" #include "protocol.h" -#include "protocol_items.h" #include "decklist.h" +#include "pb/response.pb.h" #include "pb/command_move_card.pb.h" +#include "pb/serverinfo_user.pb.h" +#include "pb/event_attach_card.pb.h" +#include "pb/event_draw_cards.pb.h" +#include "pb/event_destroy_card.pb.h" +#include "pb/event_move_card.pb.h" +#include "pb/event_set_card_attr.pb.h" +#include "pb/context_move_card.pb.h" #include -Server_Player::Server_Player(Server_Game *_game, int _playerId, ServerInfo_User *_userInfo, bool _spectator, Server_ProtocolHandler *_handler) +Server_Player::Server_Player(Server_Game *_game, int _playerId, const ServerInfo_User &_userInfo, bool _spectator, Server_ProtocolHandler *_handler) : game(_game), handler(_handler), userInfo(new ServerInfo_User(_userInfo)), deck(0), playerId(_playerId), spectator(_spectator), nextCardId(0), readyStart(false), conceded(false) { } @@ -32,18 +39,13 @@ void Server_Player::prepareDestroy() playerMutex.unlock(); delete userInfo; + userInfo = 0; clearZones(); deleteLater(); } -void Server_Player::moveToThread(QThread *thread) -{ - QObject::moveToThread(thread); - userInfo->moveToThread(thread); -} - int Server_Player::newCardId() { QMutexLocker locker(&game->gameMutex); @@ -87,15 +89,15 @@ void Server_Player::setupZones() // ------------------------------------------------------------------ // Create zones - Server_CardZone *deckZone = new Server_CardZone(this, "deck", false, HiddenZone); + Server_CardZone *deckZone = new Server_CardZone(this, "deck", false, ServerInfo_Zone::HiddenZone); addZone(deckZone); - Server_CardZone *sbZone = new Server_CardZone(this, "sb", false, HiddenZone); + Server_CardZone *sbZone = new Server_CardZone(this, "sb", false, ServerInfo_Zone::HiddenZone); addZone(sbZone); - addZone(new Server_CardZone(this, "table", true, PublicZone)); - addZone(new Server_CardZone(this, "hand", false, PrivateZone)); - addZone(new Server_CardZone(this, "stack", false, PublicZone)); - addZone(new Server_CardZone(this, "grave", false, PublicZone)); - addZone(new Server_CardZone(this, "rfg", false, PublicZone)); + addZone(new Server_CardZone(this, "table", true, ServerInfo_Zone::PublicZone)); + addZone(new Server_CardZone(this, "hand", false, ServerInfo_Zone::PrivateZone)); + addZone(new Server_CardZone(this, "stack", false, ServerInfo_Zone::PublicZone)); + addZone(new Server_CardZone(this, "grave", false, ServerInfo_Zone::PublicZone)); + addZone(new Server_CardZone(this, "rfg", false, ServerInfo_Zone::PublicZone)); addCounter(new Server_Counter(0, "life", Color(255, 255, 255), 25, 20)); addCounter(new Server_Counter(1, "w", Color(255, 255, 150), 20, 0)); @@ -188,7 +190,15 @@ ServerInfo_PlayerProperties Server_Player::getProperties() { QMutexLocker locker(&game->gameMutex); - return new ServerInfo_PlayerProperties(playerId, new ServerInfo_User(userInfo), spectator, conceded, readyStart, deck ? deck->getDeckHash() : QString()); + ServerInfo_PlayerProperties result; + result.set_player_id(playerId); + result.mutable_user_info()->CopyFrom(*userInfo); + result.set_spectator(spectator); + result.set_conceded(conceded); + result.set_ready_start(readyStart); + result.set_deck_hash(deck ? deck->getDeckHash().toStdString() : std::string()); + + return result; } void Server_Player::setDeck(DeckList *_deck) @@ -244,7 +254,7 @@ bool Server_Player::deleteCounter(int counterId) return true; } -ResponseCode Server_Player::drawCards(BlaContainer *bla, int number) +Response::ResponseCode Server_Player::drawCards(GameEventStorage &ges, int number) { QMutexLocker locker(&game->gameMutex); @@ -252,51 +262,55 @@ ResponseCode Server_Player::drawCards(BlaContainer *bla, int number) Server_CardZone *handZone = zones.value("hand"); if (deckZone->cards.size() < number) number = deckZone->cards.size(); - - QList cardListPrivate; - QList cardListOmniscient; + + Event_DrawCards eventOthers; + eventOthers.set_number(number); + Event_DrawCards eventPrivate(eventOthers); + for (int i = 0; i < number; ++i) { Server_Card *card = deckZone->cards.takeFirst(); handZone->cards.append(card); lastDrawList.append(card->getId()); - cardListPrivate.append(new ServerInfo_Card(card->getId(), card->getName())); - cardListOmniscient.append(new ServerInfo_Card(card->getId(), card->getName())); + + ServerInfo_Card *cardInfo = eventPrivate.add_cards(); + cardInfo->set_id(card->getId()); + cardInfo->set_name(card->getName().toStdString()); } - bla->enqueueGameEventPrivate(new Event_DrawCards(playerId, cardListPrivate.size(), cardListPrivate), game->getGameId()); - bla->enqueueGameEventOmniscient(new Event_DrawCards(playerId, cardListOmniscient.size(), cardListOmniscient), game->getGameId()); - bla->enqueueGameEventPublic(new Event_DrawCards(playerId, cardListPrivate.size()), game->getGameId()); - - return RespOk; + + ges.enqueueGameEvent(eventPrivate, playerId, GameEventStorageItem::SendToPrivate, playerId); + ges.enqueueGameEvent(eventOthers, playerId, GameEventStorageItem::SendToOthers); + + return Response::RespOk; } -ResponseCode Server_Player::undoDraw(BlaContainer *bla) +Response::ResponseCode Server_Player::undoDraw(GameEventStorage &ges) { QMutexLocker locker(&game->gameMutex); if (lastDrawList.isEmpty()) - return RespContextError; + return Response::RespContextError; - ResponseCode retVal; + Response::ResponseCode retVal; CardToMove *cardToMove = new CardToMove; cardToMove->set_card_id(lastDrawList.takeLast()); - retVal = moveCard(bla, zones.value("hand"), QList() << cardToMove, zones.value("deck"), 0, 0, false, true); + retVal = moveCard(ges, zones.value("hand"), QList() << cardToMove, zones.value("deck"), 0, 0, false, true); delete cardToMove; return retVal; } -ResponseCode Server_Player::moveCard(BlaContainer *bla, const QString &_startZone, const QList &_cards, int targetPlayerId, const QString &_targetZone, int x, int y) +Response::ResponseCode Server_Player::moveCard(GameEventStorage &ges, const QString &_startZone, const QList &_cards, int targetPlayerId, const QString &_targetZone, int x, int y) { QMutexLocker locker(&game->gameMutex); Server_CardZone *startzone = getZones().value(_startZone); Server_Player *targetPlayer = game->getPlayers().value(targetPlayerId); if (!targetPlayer) - return RespNameNotFound; + return Response::RespNameNotFound; Server_CardZone *targetzone = targetPlayer->getZones().value(_targetZone); if ((!startzone) || (!targetzone)) - return RespNameNotFound; + return Response::RespNameNotFound; - return moveCard(bla, startzone, _cards, targetzone, x, y); + return moveCard(ges, startzone, _cards, targetzone, x, y); } class Server_Player::MoveCardCompareFunctor { @@ -320,13 +334,13 @@ public: } }; -ResponseCode Server_Player::moveCard(BlaContainer *bla, Server_CardZone *startzone, const QList &_cards, Server_CardZone *targetzone, int x, int y, bool fixFreeSpaces, bool undoingDraw) +Response::ResponseCode Server_Player::moveCard(GameEventStorage &ges, Server_CardZone *startzone, const QList &_cards, Server_CardZone *targetzone, int x, int y, bool fixFreeSpaces, bool undoingDraw) { QMutexLocker locker(&game->gameMutex); // Disallow controller change to other zones than the table. - if (((targetzone->getType() != PublicZone) || !targetzone->hasCoords()) && (startzone->getPlayer() != targetzone->getPlayer())) - return RespContextError; + if (((targetzone->getType() != ServerInfo_Zone::PublicZone) || !targetzone->hasCoords()) && (startzone->getPlayer() != targetzone->getPlayer())) + return Response::RespContextError; if (!targetzone->hasCoords() && (x == -1)) x = targetzone->cards.size(); @@ -337,9 +351,9 @@ ResponseCode Server_Player::moveCard(BlaContainer *bla, Server_CardZone *startzo int position; Server_Card *card = startzone->getCard(_cards[i]->card_id(), &position); if (!card) - return RespNameNotFound; + return Response::RespNameNotFound; if (!card->getAttachedCards().isEmpty() && !targetzone->isColumnEmpty(x, y)) - return RespContextError; + return Response::RespContextError; cardsToMove.append(QPair(card, position)); cardProperties.insert(card, _cards[i]); } @@ -382,7 +396,7 @@ ResponseCode Server_Player::moveCard(BlaContainer *bla, Server_CardZone *startzo // Make a copy of the list because the original one gets modified during the loop QList attachedCards = card->getAttachedCards(); for (int i = 0; i < attachedCards.size(); ++i) - attachedCards[i]->getZone()->getPlayer()->unattachCard(bla, attachedCards[i]); + attachedCards[i]->getZone()->getPlayer()->unattachCard(ges, attachedCards[i]); } if (startzone != targetzone) { @@ -402,9 +416,12 @@ ResponseCode Server_Player::moveCard(BlaContainer *bla, Server_CardZone *startzo } if (card->getDestroyOnZoneChange() && (startzone->getName() != targetzone->getName())) { - bla->enqueueGameEventPrivate(new Event_DestroyCard(getPlayerId(), startzone->getName(), card->getId()), game->getGameId(), -1, new Context_MoveCard); - bla->enqueueGameEventOmniscient(new Event_DestroyCard(getPlayerId(), startzone->getName(), card->getId()), game->getGameId(), new Context_MoveCard); - bla->enqueueGameEventPublic(new Event_DestroyCard(getPlayerId(), startzone->getName(), card->getId()), game->getGameId(), new Context_MoveCard); + Event_DestroyCard event; + event.set_zone_name(startzone->getName().toStdString()); + event.set_card_id(card->getId()); + ges.setGameEventContext(new Context_MoveCard); + ges.enqueueGameEvent(event, playerId); + card->deleteLater(); } else { if (!targetzone->hasCoords()) { @@ -415,13 +432,13 @@ ResponseCode Server_Player::moveCard(BlaContainer *bla, Server_CardZone *startzo targetzone->insertCard(card, newX, y); - bool targetBeingLookedAt = (targetzone->getType() != HiddenZone) || (targetzone->getCardsBeingLookedAt() > newX) || (targetzone->getCardsBeingLookedAt() == -1); - bool sourceBeingLookedAt = (startzone->getType() != HiddenZone) || (startzone->getCardsBeingLookedAt() > position) || (startzone->getCardsBeingLookedAt() == -1); + bool targetBeingLookedAt = (targetzone->getType() != ServerInfo_Zone::HiddenZone) || (targetzone->getCardsBeingLookedAt() > newX) || (targetzone->getCardsBeingLookedAt() == -1); + bool sourceBeingLookedAt = (startzone->getType() != ServerInfo_Zone::HiddenZone) || (startzone->getCardsBeingLookedAt() > position) || (startzone->getCardsBeingLookedAt() == -1); bool targetHiddenToPlayer = thisCardProperties->face_down() || !targetBeingLookedAt; - bool targetHiddenToOthers = thisCardProperties->face_down() || (targetzone->getType() != PublicZone); + bool targetHiddenToOthers = thisCardProperties->face_down() || (targetzone->getType() != ServerInfo_Zone::PublicZone); bool sourceHiddenToPlayer = card->getFaceDown() || !sourceBeingLookedAt; - bool sourceHiddenToOthers = card->getFaceDown() || (startzone->getType() != PublicZone); + bool sourceHiddenToOthers = card->getFaceDown() || (startzone->getType() != ServerInfo_Zone::PublicZone); QString privateCardName, publicCardName; if (!(sourceHiddenToPlayer && targetHiddenToPlayer)) @@ -444,65 +461,85 @@ ResponseCode Server_Player::moveCard(BlaContainer *bla, Server_CardZone *startzo privateCardName = QString(); } int privatePosition = -1; - if (startzone->getType() == HiddenZone) + if (startzone->getType() == ServerInfo_Zone::HiddenZone) privatePosition = position; - bla->enqueueGameEventPrivate(new Event_MoveCard(getPlayerId(), privateOldCardId, privateCardName, startzone->getName(), privatePosition, targetzone->getPlayer()->getPlayerId(), targetzone->getName(), newX, y, privateNewCardId, thisCardProperties->face_down()), game->getGameId(), -1, undoingDraw ? static_cast(new Context_UndoDraw) : static_cast(new Context_MoveCard)); - bla->enqueueGameEventOmniscient(new Event_MoveCard(getPlayerId(), privateOldCardId, privateCardName, startzone->getName(), privatePosition, targetzone->getPlayer()->getPlayerId(), targetzone->getName(), newX, y, privateNewCardId, thisCardProperties->face_down()), game->getGameId(), undoingDraw ? static_cast(new Context_UndoDraw) : static_cast(new Context_MoveCard)); + + Event_MoveCard eventOthers; + eventOthers.set_start_zone(startzone->getName().toStdString()); + eventOthers.set_target_player_id(targetzone->getPlayer()->getPlayerId()); + eventOthers.set_target_zone(targetzone->getName().toStdString()); + eventOthers.set_x(newX); + eventOthers.set_y(y); + eventOthers.set_face_down(thisCardProperties->face_down()); + + Event_MoveCard eventPrivate(eventOthers); + eventPrivate.set_card_id(privateOldCardId); + eventPrivate.set_card_name(privateCardName.toStdString()); + eventPrivate.set_position(privatePosition); + eventPrivate.set_new_card_id(privateNewCardId); // Other players do not get to see the start and/or target position of the card if the respective // part of the zone is being looked at. The information is not needed anyway because in hidden zones, // all cards are equal. if ( - ((startzone->getType() == HiddenZone) && ((startzone->getCardsBeingLookedAt() > position) || (startzone->getCardsBeingLookedAt() == -1))) - || (startzone->getType() == PublicZone) + ((startzone->getType() == ServerInfo_Zone::HiddenZone) && ((startzone->getCardsBeingLookedAt() > position) || (startzone->getCardsBeingLookedAt() == -1))) + || (startzone->getType() == ServerInfo_Zone::PublicZone) ) position = -1; - if ((targetzone->getType() == HiddenZone) && ((targetzone->getCardsBeingLookedAt() > newX) || (targetzone->getCardsBeingLookedAt() == -1))) + if ((targetzone->getType() == ServerInfo_Zone::HiddenZone) && ((targetzone->getCardsBeingLookedAt() > newX) || (targetzone->getCardsBeingLookedAt() == -1))) newX = -1; - - if ((startzone->getType() == PublicZone) || (targetzone->getType() == PublicZone)) - bla->enqueueGameEventPublic(new Event_MoveCard(getPlayerId(), oldCardId, publicCardName, startzone->getName(), position, targetzone->getPlayer()->getPlayerId(), targetzone->getName(), newX, y, card->getId(), thisCardProperties->face_down()), game->getGameId(), undoingDraw ? static_cast(new Context_UndoDraw) : static_cast(new Context_MoveCard)); - else - bla->enqueueGameEventPublic(new Event_MoveCard(getPlayerId(), -1, QString(), startzone->getName(), position, targetzone->getPlayer()->getPlayerId(), targetzone->getName(), newX, y, -1, false), game->getGameId(), undoingDraw ? static_cast(new Context_UndoDraw) : static_cast(new Context_MoveCard)); + + eventOthers.set_position(position); + if ((startzone->getType() == ServerInfo_Zone::PublicZone) || (targetzone->getType() == ServerInfo_Zone::PublicZone)) { + eventOthers.set_card_id(oldCardId); + eventOthers.set_card_name(publicCardName.toStdString()); + eventOthers.set_new_card_id(card->getId()); + } + + ges.enqueueGameEvent(eventPrivate, playerId, GameEventStorageItem::SendToPrivate, playerId); + ges.enqueueGameEvent(eventOthers, playerId, GameEventStorageItem::SendToOthers); if (thisCardProperties->tapped()) - setCardAttrHelper(bla, targetzone->getName(), card->getId(), "tapped", "1"); + setCardAttrHelper(ges, targetzone->getName(), card->getId(), "tapped", "1"); QString ptString = QString::fromStdString(thisCardProperties->pt()); if (!ptString.isEmpty() && !thisCardProperties->face_down()) - setCardAttrHelper(bla, targetzone->getName(), card->getId(), "pt", ptString); + setCardAttrHelper(ges, targetzone->getName(), card->getId(), "pt", ptString); } } if (startzone->hasCoords() && fixFreeSpaces) - startzone->fixFreeSpaces(bla); + startzone->fixFreeSpaces(ges); - return RespOk; + return Response::RespOk; } -void Server_Player::unattachCard(BlaContainer *bla, Server_Card *card) +void Server_Player::unattachCard(GameEventStorage &ges, Server_Card *card) { QMutexLocker locker(&game->gameMutex); Server_CardZone *zone = card->getZone(); card->setParentCard(0); - bla->enqueueGameEventPrivate(new Event_AttachCard(getPlayerId(), zone->getName(), card->getId(), -1, QString(), -1), game->getGameId()); - bla->enqueueGameEventPublic(new Event_AttachCard(getPlayerId(), zone->getName(), card->getId(), -1, QString(), -1), game->getGameId()); + + Event_AttachCard event; + event.set_start_zone(zone->getName().toStdString()); + event.set_card_id(card->getId()); + ges.enqueueGameEvent(event, playerId); CardToMove *cardToMove = new CardToMove; cardToMove->set_card_id(card->getId()); - moveCard(bla, zone, QList() << cardToMove, zone, -1, card->getY(), card->getFaceDown()); + moveCard(ges, zone, QList() << cardToMove, zone, -1, card->getY(), card->getFaceDown()); delete cardToMove; } -ResponseCode Server_Player::setCardAttrHelper(BlaContainer *bla, const QString &zoneName, int cardId, const QString &attrName, const QString &attrValue) +Response::ResponseCode Server_Player::setCardAttrHelper(GameEventStorage &ges, const QString &zoneName, int cardId, const QString &attrName, const QString &attrValue) { QMutexLocker locker(&game->gameMutex); Server_CardZone *zone = getZones().value(zoneName); if (!zone) - return RespNameNotFound; + return Response::RespNameNotFound; if (!zone->hasCoords()) - return RespContextError; + return Response::RespContextError; QString result; if (cardId == -1) { @@ -510,26 +547,31 @@ ResponseCode Server_Player::setCardAttrHelper(BlaContainer *bla, const QString & while (CardIterator.hasNext()) { result = CardIterator.next()->setAttribute(attrName, attrValue, true); if (result.isNull()) - return RespInvalidCommand; + return Response::RespInvalidCommand; } } else { Server_Card *card = zone->getCard(cardId); if (!card) - return RespNameNotFound; + return Response::RespNameNotFound; result = card->setAttribute(attrName, attrValue, false); if (result.isNull()) - return RespInvalidCommand; + return Response::RespInvalidCommand; } - bla->enqueueGameEventPrivate(new Event_SetCardAttr(getPlayerId(), zone->getName(), cardId, attrName, result), game->getGameId()); - bla->enqueueGameEventPublic(new Event_SetCardAttr(getPlayerId(), zone->getName(), cardId, attrName, result), game->getGameId()); - bla->enqueueGameEventOmniscient(new Event_SetCardAttr(getPlayerId(), zone->getName(), cardId, attrName, result), game->getGameId()); - return RespOk; + + Event_SetCardAttr event; + event.set_zone_name(zone->getName().toStdString()); + event.set_card_id(cardId); + event.set_attr_name(attrName.toStdString()); + event.set_attr_value(result.toStdString()); + ges.enqueueGameEvent(event, playerId); + + return Response::RespOk; } -void Server_Player::sendProtocolItem(ProtocolItem *item, bool deleteItem) +void Server_Player::sendGameEvent(GameEventContainer *cont) { QMutexLocker locker(&playerMutex); if (handler) - handler->sendProtocolItem(item, deleteItem); + handler->sendProtocolItem(*cont); } diff --git a/common/server_player.h b/common/server_player.h index 95cbd254..2342e7c2 100644 --- a/common/server_player.h +++ b/common/server_player.h @@ -7,6 +7,8 @@ #include #include +#include "pb/response.pb.h" + class DeckList; class Server_Game; class Server_CardZone; @@ -14,11 +16,11 @@ class Server_Counter; class Server_Arrow; class Server_Card; class Server_ProtocolHandler; -class ProtocolItem; class ServerInfo_User; class ServerInfo_PlayerProperties; class CommandContainer; class CardToMove; +class GameEventContainer; class GameEventStorage; class Server_Player : public Server_ArrowTarget { @@ -41,10 +43,9 @@ private: bool readyStart; bool conceded; public: - Server_Player(Server_Game *_game, int _playerId, ServerInfo_User *_userInfo, bool _spectator, Server_ProtocolHandler *_handler); + Server_Player(Server_Game *_game, int _playerId, const ServerInfo_User &_userInfo, bool _spectator, Server_ProtocolHandler *_handler); ~Server_Player(); void prepareDestroy(); - void moveToThread(QThread *thread); Server_ProtocolHandler *getProtocolHandler() const { return handler; } void setProtocolHandler(Server_ProtocolHandler *_handler) { playerMutex.lock(); handler = _handler; playerMutex.unlock(); } @@ -87,7 +88,7 @@ public: void unattachCard(GameEventStorage &ges, Server_Card *card); Response::ResponseCode setCardAttrHelper(GameEventStorage &ges, const QString &zone, int cardId, const QString &attrName, const QString &attrValue); - void sendProtocolItem(ProtocolItem *item, bool deleteItem = true); + void sendGameEvent(GameEventContainer *event); }; #endif diff --git a/common/server_protocolhandler.cpp b/common/server_protocolhandler.cpp index 2734c004..ef966f76 100644 --- a/common/server_protocolhandler.cpp +++ b/common/server_protocolhandler.cpp @@ -77,6 +77,7 @@ #include "pb/event_set_counter.pb.h" #include "pb/event_dump_zone.pb.h" #include "pb/event_stop_dump_zone.pb.h" +#include "pb/event_reveal_cards.pb.h" #include "pb/context_deck_select.pb.h" #include "pb/context_concede.pb.h" #include "pb/context_ready_start.pb.h" @@ -124,12 +125,25 @@ void Server_ProtocolHandler::prepareDestroy() gameListMutex.unlock(); delete userInfo; - QMapIterator i(buddyList); - while (i.hasNext()) - delete i.next().value(); - QMapIterator j(ignoreList); - while (j.hasNext()) - delete j.next().value(); +} + +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(); + if (!complete) + result.clear_avatar_bmp(); + } + return result; } void Server_ProtocolHandler::playerRemovedFromGame(Server_Game *game) @@ -186,6 +200,13 @@ void Server_ProtocolHandler::sendProtocolItem(ServerMessage::MessageType type, c } } +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; @@ -499,19 +520,14 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd // XXX stimmt so nicht, beim alten Kopierkonstruktor wurde hier "true" übergeben re->mutable_user_info()->CopyFrom(*userInfo); - QList _buddyList, _ignoreList; if (authState == PasswordRight) { - buddyList = server->getBuddyList(userName); - - QMapIterator buddyIterator(buddyList); + QMapIterator buddyIterator(server->getBuddyList(userName)); while (buddyIterator.hasNext()) - re->add_buddy_list()->CopyFrom(*buddyIterator.next().value()); + re->add_buddy_list()->CopyFrom(buddyIterator.next().value()); - ignoreList = server->getIgnoreList(userName); - - QMapIterator ignoreIterator(ignoreList); + QMapIterator ignoreIterator(server->getIgnoreList(userName)); while (ignoreIterator.hasNext()) - re->add_ignore_list()->CopyFrom(*ignoreIterator.next().value()); + re->add_ignore_list()->CopyFrom(ignoreIterator.next().value()); } server->serverMutex.lock(); @@ -573,7 +589,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdMessage(const Command_Message Server_ProtocolHandler *userHandler = server->getUsers().value(receiver); if (!userHandler) return Response::RespNameNotFound; - if (userHandler->getIgnoreList().contains(getUserName())) + if (server->isInIgnoreList(receiver, QString::fromStdString(userInfo->name()))) return Response::RespInIgnoreList; Event_UserMessage event; @@ -856,7 +872,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdDeckSelect(const Command_DeckS Event_PlayerPropertiesChanged event; event.mutable_player_properties()->CopyFrom(player->getProperties()); - ges.enqueueGameEventPublic(event, player->getPlayerId()); + ges.enqueueGameEvent(event, player->getPlayerId()); Context_DeckSelect *context = new Context_DeckSelect; context->set_deck_hash(deck->getDeckHash().toStdString()); @@ -907,7 +923,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdConcede(const Command_Concede Event_PlayerPropertiesChanged event; event.mutable_player_properties()->CopyFrom(player->getProperties()); - ges.enqueueGameEventPublic(event, player->getPlayerId()); + ges.enqueueGameEvent(event, player->getPlayerId()); ges.setGameEventContext(new Context_Concede()); game->stopGameIfFinished(); @@ -932,7 +948,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdReadyStart(const Command_Ready Event_PlayerPropertiesChanged event; event.mutable_player_properties()->CopyFrom(player->getProperties()); - ges.enqueueGameEventPublic(event, player->getPlayerId()); + ges.enqueueGameEvent(event, player->getPlayerId()); ges.setGameEventContext(new Context_ReadyStart()); game->startGameIfReady(); @@ -946,7 +962,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdGameSay(const Command_GameSay Event_GameSay event; event.set_message(cmd.message()); - ges.enqueueGameEventPublic(event, player->getPlayerId()); + ges.enqueueGameEvent(event, player->getPlayerId()); return Response::RespOk; } @@ -963,7 +979,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdShuffle(const Command_Shuffle player->getZones().value("deck")->shuffle(); - ges.enqueueGameEventPublic(Event_Shuffle(), player->getPlayerId()); + ges.enqueueGameEvent(Event_Shuffle(), player->getPlayerId()); return Response::RespOk; } @@ -1630,7 +1646,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdStopDumpZone(const Command_Sto return Response::RespOk; } -Response::ResponseCode Server_ProtocolHandler::cmdRevealCards(const Command_RevealCards &cmd, Server_Game *game, Server_Player *player, ResponseContainer &rc, GameEventStorage &ges) +Response::ResponseCode Server_ProtocolHandler::cmdRevealCards(const Command_RevealCards &cmd, Server_Game *game, Server_Player *player, ResponseContainer & /*rc*/, GameEventStorage &ges) { if (player->getSpectator()) return Response::RespFunctionNotAllowed; @@ -1664,39 +1680,54 @@ Response::ResponseCode Server_ProtocolHandler::cmdRevealCards(const Command_Reve cardsToReveal.append(card); } + Event_RevealCards eventOthers; + eventOthers.set_zone_name(zone->getName().toStdString()); + if (cmd.has_card_id()) + eventOthers.set_card_id(cmd.card_id()); + if (cmd.has_player_id()) + eventOthers.set_other_player_id(cmd.player_id()); + + Event_RevealCards eventPrivate(eventOthers); + QList respCardListPrivate, respCardListOmniscient; for (int i = 0; i < cardsToReveal.size(); ++i) { Server_Card *card = cardsToReveal[i]; + ServerInfo_Card *cardInfo = eventPrivate.add_cards(); - QList cardCounterListPrivate, cardCounterListOmniscient; + cardInfo->set_id(card->getId()); + cardInfo->set_name(card->getName().toStdString()); + cardInfo->set_x(card->getX()); + cardInfo->set_y(card->getY()); + cardInfo->set_face_down(card->getFaceDown()); + cardInfo->set_tapped(card->getTapped()); + cardInfo->set_attacking(card->getAttacking()); + cardInfo->set_color(card->getColor().toStdString()); + cardInfo->set_pt(card->getPT().toStdString()); + cardInfo->set_annotation(card->getAnnotation().toStdString()); + cardInfo->set_destroy_on_zone_change(card->getDestroyOnZoneChange()); + cardInfo->set_doesnt_untap(card->getDoesntUntap()); + + QList cardCounterList; QMapIterator cardCounterIterator(card->getCounters()); while (cardCounterIterator.hasNext()) { cardCounterIterator.next(); - cardCounterListPrivate.append(new ServerInfo_CardCounter(cardCounterIterator.key(), cardCounterIterator.value())); - cardCounterListOmniscient.append(new ServerInfo_CardCounter(cardCounterIterator.key(), cardCounterIterator.value())); + ServerInfo_CardCounter *counterInfo = cardInfo->add_counter_list(); + counterInfo->set_id(cardCounterIterator.key()); + counterInfo->set_value(cardCounterIterator.value()); } - int attachPlayerId = -1; - QString attachZone; - int attachCardId = -1; if (card->getParentCard()) { - attachPlayerId = card->getParentCard()->getZone()->getPlayer()->getPlayerId(); - attachZone = card->getParentCard()->getZone()->getName(); - attachCardId = card->getParentCard()->getId(); + cardInfo->set_attach_player_id(card->getParentCard()->getZone()->getPlayer()->getPlayerId()); + cardInfo->set_attach_zone(card->getParentCard()->getZone()->getName().toStdString()); + cardInfo->set_attach_card_id(card->getParentCard()->getId()); } - - if (cmd.has_player_id()) - respCardListPrivate.append(new ServerInfo_Card(card->getId(), card->getName(), card->getX(), card->getY(), card->getFaceDown(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), card->getDoesntUntap(), cardCounterListPrivate, attachPlayerId, attachZone, attachCardId)); - respCardListOmniscient.append(new ServerInfo_Card(card->getId(), card->getName(), card->getX(), card->getY(), card->getFaceDown(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), card->getDoesntUntap(), cardCounterListOmniscient, attachPlayerId, attachZone, attachCardId)); } - if (!cmd.has_player_id()) - bla->enqueueGameEventPublic(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd.card_id(), -1, respCardListOmniscient), game->getGameId()); - else { - bla->enqueueGameEventPublic(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd.card_id(), otherPlayer->getPlayerId()), game->getGameId()); - bla->enqueueGameEventPrivate(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd.card_id(), otherPlayer->getPlayerId(), respCardListPrivate), game->getGameId(), otherPlayer->getPlayerId()); - bla->enqueueGameEventOmniscient(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd.card_id(), otherPlayer->getPlayerId(), respCardListOmniscient), game->getGameId()); - } + if (cmd.has_player_id()) { + ges.enqueueGameEvent(eventPrivate, player->getPlayerId(), GameEventStorageItem::SendToPrivate, cmd.player_id()); + ges.enqueueGameEvent(eventOthers, player->getPlayerId(), GameEventStorageItem::SendToOthers); + } else + ges.enqueueGameEvent(eventPrivate, player->getPlayerId()); return Response::RespOk; } diff --git a/common/server_protocolhandler.h b/common/server_protocolhandler.h index 5fb1dff4..d7f7cda1 100644 --- a/common/server_protocolhandler.h +++ b/common/server_protocolhandler.h @@ -93,10 +93,8 @@ protected: bool acceptsUserListChanges; bool acceptsRoomListChanges; ServerInfo_User *userInfo; - QMap buddyList, ignoreList; void prepareDestroy(); - virtual bool getCompressionSupport() const = 0; int sessionId; private: QString thisUserName; @@ -182,9 +180,7 @@ public: ServerInfo_User copyUserInfo(bool complete, bool moderatorInfo = false) const; const QString &getUserName() const { return thisUserName; } virtual QString getAddress() const = 0; - void setUserInfo(ServerInfo_User *_userInfo) { userInfo = _userInfo; } - const QMap &getBuddyList() const { return buddyList; } - const QMap &getIgnoreList() const { return ignoreList; } + void setUserInfo(const ServerInfo_User &_userInfo); int getSessionId() const { return sessionId; } void setSessionId(int _sessionId) { sessionId = _sessionId; } @@ -197,7 +193,7 @@ public: void sendProtocolItem(const RoomEvent &item); void sendProtocolItem(ServerMessage::MessageType type, const ::google::protobuf::Message &item); - SessionEvent *prepareSessionEvent(const ::google::protobuf::Message &sessionEvent); + static SessionEvent *prepareSessionEvent(const ::google::protobuf::Message &sessionEvent); }; #endif diff --git a/common/server_room.cpp b/common/server_room.cpp index 9e9aa571..88e3b626 100644 --- a/common/server_room.cpp +++ b/common/server_room.cpp @@ -3,6 +3,12 @@ #include "server_game.h" #include +#include "pb/event_join_room.pb.h" +#include "pb/event_leave_room.pb.h" +#include "pb/event_list_games.pb.h" +#include "pb/event_room_say.pb.h" +#include + 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) { @@ -26,33 +32,52 @@ Server *Server_Room::getServer() const return static_cast(parent()); } -ServerInfo_Room *Server_Room::getInfo(bool complete, bool showGameTypes) const +ServerInfo_Room Server_Room::getInfo(bool complete, bool showGameTypes) const { QMutexLocker locker(&roomMutex); - QList gameList; - QList userList; - QList gameTypeList; + ServerInfo_Room result; + result.set_room_id(id); + result.set_name(name.toStdString()); + result.set_description(description.toStdString()); + result.set_game_count(games.size()); + result.set_player_count(size()); + result.set_auto_join(autoJoin); + if (complete) { QMapIterator gameIterator(games); while (gameIterator.hasNext()) - gameList.append(gameIterator.next().value()->getInfo()); + result.add_game_list()->CopyFrom(gameIterator.next().value()->getInfo()); for (int i = 0; i < size(); ++i) - userList.append(new ServerInfo_User(at(i)->getUserInfo(), false)); + result.add_user_list()->CopyFrom(at(i)->copyUserInfo(false)); } if (complete || showGameTypes) - for (int i = 0; i < gameTypes.size(); ++i) - gameTypeList.append(new ServerInfo_GameType(i, gameTypes[i])); + for (int i = 0; i < gameTypes.size(); ++i) { + ServerInfo_GameType *gameTypeInfo = result.add_gametype_list(); + gameTypeInfo->set_game_type_id(i); + gameTypeInfo->set_description(gameTypes[i].toStdString()); + } - return new ServerInfo_Room(id, name, description, games.size(), size(), autoJoin, gameList, userList, gameTypeList); + return result; +} + +RoomEvent *Server_Room::prepareRoomEvent(const ::google::protobuf::Message &roomEvent) +{ + RoomEvent *event = new RoomEvent; + event->set_room_id(id); + event->GetReflection()->MutableMessage(event, roomEvent.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(roomEvent); + return event; } void Server_Room::addClient(Server_ProtocolHandler *client) { QMutexLocker locker(&roomMutex); - sendRoomEvent(new Event_JoinRoom(id, new ServerInfo_User(client->getUserInfo(), false))); + Event_JoinRoom event; + event.mutable_user_info()->CopyFrom(client->copyUserInfo(false)); + sendRoomEvent(prepareRoomEvent(event)); + append(client); emit roomInfoChanged(); } @@ -62,13 +87,20 @@ void Server_Room::removeClient(Server_ProtocolHandler *client) QMutexLocker locker(&roomMutex); removeAt(indexOf(client)); - sendRoomEvent(new Event_LeaveRoom(id, client->getUserInfo()->getName())); + + Event_LeaveRoom event; + event.set_name(client->getUserInfo()->name()); + sendRoomEvent(prepareRoomEvent(event)); + emit roomInfoChanged(); } void Server_Room::say(Server_ProtocolHandler *client, const QString &s) { - sendRoomEvent(new Event_RoomSay(id, client->getUserInfo()->getName(), s)); + Event_RoomSay event; + event.set_name(client->getUserInfo()->name()); + event.set_message(s.toStdString()); + sendRoomEvent(prepareRoomEvent(event)); } void Server_Room::sendRoomEvent(RoomEvent *event) @@ -76,7 +108,7 @@ void Server_Room::sendRoomEvent(RoomEvent *event) QMutexLocker locker(&roomMutex); for (int i = 0; i < size(); ++i) - at(i)->sendProtocolItem(event, false); + at(i)->sendProtocolItem(*event); delete event; } @@ -84,11 +116,9 @@ void Server_Room::broadcastGameListUpdate(Server_Game *game) { QMutexLocker locker(&roomMutex); - Event_ListGames *event = new Event_ListGames(id, QList() << game->getInfo()); - - for (int i = 0; i < size(); i++) - at(i)->sendProtocolItem(event, false); - delete event; + Event_ListGames event; + event.add_game_list()->CopyFrom(game->getInfo()); + 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) @@ -126,14 +156,14 @@ int Server_Room::getGamesCreatedByUser(const QString &userName) const QMapIterator gamesIterator(games); int result = 0; while (gamesIterator.hasNext()) - if (gamesIterator.next().value()->getCreatorInfo()->getName() == userName) + if (gamesIterator.next().value()->getCreatorInfo()->name() == userName.toStdString()) ++result; return result; } -QList Server_Room::getGamesOfUser(const QString &userName) const +QList Server_Room::getGamesOfUser(const QString &userName) const { - QList result; + QList result; QMapIterator gamesIterator(games); while (gamesIterator.hasNext()) { Server_Game *game = gamesIterator.next().value(); diff --git a/servatrice/servatrice.ini.example b/servatrice/servatrice.ini.example index 8a01bc85..9c3b17b7 100644 --- a/servatrice/servatrice.ini.example +++ b/servatrice/servatrice.ini.example @@ -2,6 +2,7 @@ port=4747 statusupdate=15000 logfile=server.log +name="My Cockatrice server" id=1 threaded=0 diff --git a/servatrice/src/servatrice.cpp b/servatrice/src/servatrice.cpp index c3c103b9..4ea857a7 100644 --- a/servatrice/src/servatrice.cpp +++ b/servatrice/src/servatrice.cpp @@ -29,6 +29,9 @@ #include "server_logger.h" #include "main.h" #include "passwordhasher.h" +#include "pb/event_server_message.pb.h" +#include "pb/event_server_shutdown.pb.h" +#include "pb/event_connection_closed.pb.h" void Servatrice_TcpServer::incomingConnection(int socketDescriptor) { @@ -50,8 +53,7 @@ Servatrice::Servatrice(QSettings *_settings, QObject *parent) connect(pingClock, SIGNAL(timeout()), this, SIGNAL(pingClockTimeout())); pingClock->start(1000); - ProtocolItem::initializeHash(); - + serverName = settings->value("server/name").toString(); serverId = settings->value("server/id", 0).toInt(); int statusUpdateTime = settings->value("server/statusupdate").toInt(); statusUpdateClock = new QTimer(this); @@ -245,7 +247,54 @@ bool Servatrice::userExists(const QString &user) } else return false; } -ServerInfo_User *Servatrice::evalUserQueryResult(const QSqlQuery &query, bool complete) +int Servatrice::getUserIdInDB(const QString &name) +{ + QMutexLocker locker(&dbMutex); + QSqlQuery query; + query.prepare("select id from " + dbPrefix + "_users where name = :name and active = 1"); + query.bindValue(":name", name); + if (!execSqlQuery(query)) + return -1; + if (!query.next()) + return -1; + return query.value(0).toInt(); +} + +bool Servatrice::isInBuddyList(const QString &whoseList, const QString &who) +{ + QMutexLocker locker(&dbMutex); + checkSql(); + + int id1 = getUserIdInDB(whoseList); + int id2 = getUserIdInDB(who); + + QSqlQuery query; + query.prepare("select 1 from " + dbPrefix + "_buddylist where id_user1 = :id_user1 and id_user2 = :id_user2"); + query.bindValue(":id_user1", id1); + query.bindValue(":id_user2", id2); + if (!execSqlQuery(query)) + return false; + return query.next(); +} + +bool Servatrice::isInIgnoreList(const QString &whoseList, const QString &who) +{ + QMutexLocker locker(&dbMutex); + checkSql(); + + int id1 = getUserIdInDB(whoseList); + int id2 = getUserIdInDB(who); + + QSqlQuery query; + query.prepare("select 1 from " + dbPrefix + "_ignorelist where id_user1 = :id_user1 and id_user2 = :id_user2"); + query.bindValue(":id_user1", id1); + query.bindValue(":id_user2", id2); + if (!execSqlQuery(query)) + return false; + return query.next(); +} + +ServerInfo_User Servatrice::evalUserQueryResult(const QSqlQuery &query, bool complete) { QString name = query.value(0).toString(); int is_admin = query.value(1).toInt(); @@ -270,21 +319,23 @@ ServerInfo_User *Servatrice::evalUserQueryResult(const QSqlQuery &query, bool co else if (is_admin == 2) userLevel |= ServerInfo_User::IsModerator; - return new ServerInfo_User( - name, - userLevel, - QString(), - realName, - gender, - country, - avatarBmp - ); + ServerInfo_User result; + result.set_name(name.toStdString()); + result.set_user_level(userLevel); + result.set_real_name(realName.toStdString()); + result.set_gender(gender); + result.set_country(country.toStdString()); + result.set_avatar_bmp(avatarBmp.data(), avatarBmp.size()); + return result; } -ServerInfo_User *Servatrice::getUserData(const QString &name) +ServerInfo_User Servatrice::getUserData(const QString &name) { QMutexLocker locker(&dbMutex); const QString method = settings->value("authentication/method").toString(); + ServerInfo_User result; + result.set_name(name.toStdString()); + result.set_user_level(ServerInfo_User::IsUser); if (method == "sql") { checkSql(); @@ -292,14 +343,14 @@ ServerInfo_User *Servatrice::getUserData(const QString &name) query.prepare("select name, admin, realname, gender, country, avatar_bmp from " + dbPrefix + "_users where name = :name and active = 1"); query.bindValue(":name", name); if (!execSqlQuery(query)) - return new ServerInfo_User(name, ServerInfo_User::IsUser); + return result; if (query.next()) return evalUserQueryResult(query, true); else - return new ServerInfo_User(name, ServerInfo_User::IsUser); + return result; } else - return new ServerInfo_User(name, ServerInfo_User::IsUser); + return result; } int Servatrice::getUsersWithAddress(const QHostAddress &address) const @@ -337,10 +388,10 @@ void Servatrice::endSession(int sessionId) execSqlQuery(query); } -QMap Servatrice::getBuddyList(const QString &name) +QMap Servatrice::getBuddyList(const QString &name) { QMutexLocker locker(&dbMutex); - QMap result; + QMap result; const QString method = settings->value("authentication/method").toString(); if (method == "sql") { @@ -353,17 +404,17 @@ QMap Servatrice::getBuddyList(const QString &name) return result; while (query.next()) { - ServerInfo_User *temp = evalUserQueryResult(query, false); - result.insert(temp->getName(), temp); + const ServerInfo_User &temp = evalUserQueryResult(query, false); + result.insert(QString::fromStdString(temp.name()), temp); } } return result; } -QMap Servatrice::getIgnoreList(const QString &name) +QMap Servatrice::getIgnoreList(const QString &name) { QMutexLocker locker(&dbMutex); - QMap result; + QMap result; const QString method = settings->value("authentication/method").toString(); if (method == "sql") { @@ -376,8 +427,8 @@ QMap Servatrice::getIgnoreList(const QString &name) return result; while (query.next()) { - ServerInfo_User *temp = evalUserQueryResult(query, false); - result.insert(temp->getName(), temp); + ServerInfo_User temp = evalUserQueryResult(query, false); + result.insert(QString::fromStdString(temp.name()), temp); } } return result; @@ -394,12 +445,13 @@ void Servatrice::updateLoginMessage() if (query.next()) { loginMessage = query.value(0).toString(); - Event_ServerMessage *event = new Event_ServerMessage(loginMessage); + Event_ServerMessage event; + event.set_message(loginMessage.toStdString()); + SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event); QMapIterator usersIterator(users); - while (usersIterator.hasNext()) { - usersIterator.next().value()->sendProtocolItem(event, false); - } - delete event; + while (usersIterator.hasNext()) + usersIterator.next().value()->sendProtocolItem(*se); + delete se; } } @@ -467,15 +519,21 @@ void Servatrice::shutdownTimeout() --shutdownMinutes; - GenericEvent *event; - if (shutdownMinutes) - event = new Event_ServerShutdown(shutdownReason, shutdownMinutes); - else - event = new Event_ConnectionClosed("server_shutdown"); + SessionEvent *se; + if (shutdownMinutes) { + Event_ServerShutdown event; + event.set_reason(shutdownReason.toStdString()); + event.set_minutes(shutdownMinutes); + se = Server_ProtocolHandler::prepareSessionEvent(event); + } else { + Event_ConnectionClosed event; + event.set_reason("server_shutdown"); + se = Server_ProtocolHandler::prepareSessionEvent(event); + } for (int i = 0; i < clients.size(); ++i) - clients[i]->sendProtocolItem(event, false); - delete event; + clients[i]->sendProtocolItem(*se); + delete se; if (!shutdownMinutes) deleteLater(); diff --git a/servatrice/src/servatrice.h b/servatrice/src/servatrice.h index e22aa01c..01038ee4 100644 --- a/servatrice/src/servatrice.h +++ b/servatrice/src/servatrice.h @@ -51,13 +51,14 @@ private slots: void statusUpdate(); void shutdownTimeout(); public: - QMutex dbMutex; + mutable QMutex dbMutex; static const QString versionString; Servatrice(QSettings *_settings, QObject *parent = 0); ~Servatrice(); bool openDatabase(); void checkSql(); bool execSqlQuery(QSqlQuery &query); + QString getServerName() const { return serverName; } QString getLoginMessage() const { return loginMessage; } bool getGameShouldPing() const { return true; } int getMaxGameInactivityTime() const { return maxGameInactivityTime; } @@ -70,13 +71,16 @@ public: bool getThreaded() const { return threaded; } QString getDbPrefix() const { return dbPrefix; } void updateLoginMessage(); - ServerInfo_User *getUserData(const QString &name); + ServerInfo_User getUserData(const QString &name); int getUsersWithAddress(const QHostAddress &address) const; - QMap getBuddyList(const QString &name); - QMap getIgnoreList(const QString &name); + QMap getBuddyList(const QString &name); + QMap getIgnoreList(const QString &name); + bool isInBuddyList(const QString &whoseList, const QString &who); + bool isInIgnoreList(const QString &whoseList, const QString &who); void scheduleShutdown(const QString &reason, int minutes); void incTxBytes(quint64 num); void incRxBytes(quint64 num); + int getUserIdInDB(const QString &name); protected: int startSession(const QString &userName, const QString &address); void endSession(int sessionId); @@ -85,6 +89,7 @@ protected: private: QTimer *pingClock, *statusUpdateClock; QTcpServer *tcpServer; + QString serverName; QString loginMessage; QString dbPrefix; QSettings *settings; @@ -95,7 +100,7 @@ private: quint64 txBytes, rxBytes; int maxGameInactivityTime, maxPlayerInactivityTime; int maxUsersPerAddress, messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval, maxGamesPerUser; - ServerInfo_User *evalUserQueryResult(const QSqlQuery &query, bool complete); + ServerInfo_User evalUserQueryResult(const QSqlQuery &query, bool complete); QString shutdownReason; int shutdownMinutes; diff --git a/servatrice/src/serversocketinterface.cpp b/servatrice/src/serversocketinterface.cpp index d3ff9468..037c26fa 100644 --- a/servatrice/src/serversocketinterface.cpp +++ b/servatrice/src/serversocketinterface.cpp @@ -18,15 +18,12 @@ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * ***************************************************************************/ -#include -#include #include #include #include #include "serversocketinterface.h" #include "servatrice.h" #include "protocol.h" -#include "protocol_items.h" #include "decklist.h" #include "server_player.h" #include "main.h" @@ -38,32 +35,43 @@ #include "pb/command_deck_new_dir.pb.h" #include "pb/command_deck_del_dir.pb.h" #include "pb/command_deck_del.pb.h" +#include "pb/event_connection_closed.pb.h" +#include "pb/event_server_message.pb.h" +#include "pb/event_server_identification.pb.h" +#include "pb/event_add_to_list.pb.h" +#include "pb/event_remove_from_list.pb.h" +#include "pb/response_deck_download.pb.h" +#include "pb/serverinfo_user.pb.h" #include #include ServerSocketInterface::ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent) - : Server_ProtocolHandler(_server, parent), servatrice(_server), socket(_socket), topLevelItem(0), compressionSupport(false), messageInProgress(false) + : Server_ProtocolHandler(_server, parent), servatrice(_server), socket(_socket), messageInProgress(false) { - xmlWriter = new QXmlStreamWriter(&xmlBuffer); - xmlReader = new QXmlStreamReader; - connect(socket, SIGNAL(readyRead()), this, SLOT(readClient())); connect(socket, SIGNAL(disconnected()), this, SLOT(deleteLater())); connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(catchSocketError(QAbstractSocket::SocketError))); - connect(this, SIGNAL(xmlBufferChanged()), this, SLOT(flushXmlBuffer()), Qt::QueuedConnection); + connect(this, SIGNAL(outputBufferChanged()), this, SLOT(flushOutputBuffer()), Qt::QueuedConnection); - xmlWriter->writeStartDocument(); - xmlWriter->writeStartElement("cockatrice_server_stream"); - xmlWriter->writeAttribute("version", QString::number(ProtocolItem::protocolVersion)); - flushXmlBuffer(); + Event_ServerIdentification identEvent; + identEvent.set_server_name(servatrice->getServerName().toStdString()); + identEvent.set_server_version(Servatrice::versionString.toStdString()); + identEvent.set_protocol_version(protocolVersion); + SessionEvent *identSe = prepareSessionEvent(identEvent); + sendProtocolItem(*identSe); + delete identSe; int maxUsers = _server->getMaxUsersPerAddress(); if ((maxUsers > 0) && (_server->getUsersWithAddress(socket->peerAddress()) >= maxUsers)) { - sendProtocolItem(new Event_ConnectionClosed("too_many_connections")); + Event_ConnectionClosed event; + event.set_reason("too_many_connections"); + SessionEvent *se = prepareSessionEvent(event); + sendProtocolItem(*se); + delete se; + deleteLater(); - } else - sendProtocolItem(new Event_ServerMessage(Servatrice::versionString)); + } server->addClient(this); } @@ -74,23 +82,20 @@ ServerSocketInterface::~ServerSocketInterface() prepareDestroy(); - flushXmlBuffer(); - delete xmlWriter; - delete xmlReader; + flushOutputBuffer(); delete socket; socket = 0; - delete topLevelItem; } -void ServerSocketInterface::flushXmlBuffer() +void ServerSocketInterface::flushOutputBuffer() { - QMutexLocker locker(&xmlBufferMutex); - if (xmlBuffer.isEmpty()) + QMutexLocker locker(&outputBufferMutex); + if (outputBuffer.isEmpty()) return; - servatrice->incTxBytes(xmlBuffer.size()); - socket->write(xmlBuffer.toUtf8()); + servatrice->incTxBytes(outputBuffer.size()); + socket->write(outputBuffer); socket->flush(); - xmlBuffer.clear(); + outputBuffer.clear(); } void ServerSocketInterface::readClient() @@ -131,52 +136,46 @@ void ServerSocketInterface::catchSocketError(QAbstractSocket::SocketError socket deleteLater(); } -void ServerSocketInterface::sendProtocolItem(ProtocolItem *item, bool deleteItem) +void ServerSocketInterface::transmitProtocolItem(const ServerMessage &item) { - QMutexLocker locker(&xmlBufferMutex); + QByteArray buf; + unsigned int size = item.ByteSize(); + buf.resize(size + 4); + item.SerializeToArray(buf.data() + 4, size); + buf.data()[3] = (unsigned char) size; + buf.data()[2] = (unsigned char) (size >> 8); + buf.data()[1] = (unsigned char) (size >> 16); + buf.data()[0] = (unsigned char) (size >> 24); - item->write(xmlWriter); - if (deleteItem) - delete item; - - emit xmlBufferChanged(); + QMutexLocker locker(&outputBufferMutex); + outputBuffer.append(buf); + emit outputBufferChanged(); } -int ServerSocketInterface::getUserIdInDB(const QString &name) const -{ - QMutexLocker locker(&servatrice->dbMutex); - QSqlQuery query; - query.prepare("select id from " + servatrice->getDbPrefix() + "_users where name = :name"); - query.bindValue(":name", name); - if (!servatrice->execSqlQuery(query)) - return -1; - if (!query.next()) - return -1; - return query.value(0).toInt(); -} - -ResponseCode ServerSocketInterface::cmdAddToList(const Command_AddToList &cmd, BlaContainer *bla) +Response::ResponseCode ServerSocketInterface::cmdAddToList(const Command_AddToList &cmd, ResponseContainer &rc) { if (authState != PasswordRight) - return RespFunctionNotAllowed; + return Response::RespFunctionNotAllowed; QString list = QString::fromStdString(cmd.list()); QString user = QString::fromStdString(cmd.user_name()); if ((list != "buddy") && (list != "ignore")) - return RespContextError; + return Response::RespContextError; - if ((list == "buddy") && buddyList.contains(user)) - return RespContextError; - if ((list == "ignore") && ignoreList.contains(user)) - return RespContextError; + if (list == "buddy") + if (servatrice->isInBuddyList(QString::fromStdString(userInfo->name()), user)) + return Response::RespContextError; + if (list == "ignore") + if (servatrice->isInIgnoreList(QString::fromStdString(userInfo->name()), user)) + return Response::RespContextError; - int id1 = getUserIdInDB(userInfo->getName()); - int id2 = getUserIdInDB(user); + int id1 = servatrice->getUserIdInDB(QString::fromStdString(userInfo->name())); + int id2 = servatrice->getUserIdInDB(user); if (id2 < 0) - return RespNameNotFound; + return Response::RespNameNotFound; if (id1 == id2) - return RespContextError; + return Response::RespContextError; QMutexLocker locker(&servatrice->dbMutex); QSqlQuery query; @@ -184,38 +183,38 @@ ResponseCode ServerSocketInterface::cmdAddToList(const Command_AddToList &cmd, B query.bindValue(":id1", id1); query.bindValue(":id2", id2); if (!servatrice->execSqlQuery(query)) - return RespInternalError; + return Response::RespInternalError; - ServerInfo_User *info = servatrice->getUserData(user); - if (list == "buddy") - buddyList.insert(info->getName(), info); - else if (list == "ignore") - ignoreList.insert(info->getName(), info); + Event_AddToList *event = new Event_AddToList; + event->set_list_name(cmd.list()); + event->mutable_user_info()->CopyFrom(servatrice->getUserData(user)); + rc.enqueuePreResponseItem(ServerMessage::SESSION_EVENT, event); - bla->enqueueItem(new Event_AddToList(list, new ServerInfo_User(info))); - return RespOk; + return Response::RespOk; } -ResponseCode ServerSocketInterface::cmdRemoveFromList(const Command_RemoveFromList &cmd, BlaContainer *bla) +Response::ResponseCode ServerSocketInterface::cmdRemoveFromList(const Command_RemoveFromList &cmd, ResponseContainer &rc) { if (authState != PasswordRight) - return RespFunctionNotAllowed; + return Response::RespFunctionNotAllowed; QString list = QString::fromStdString(cmd.list()); QString user = QString::fromStdString(cmd.user_name()); if ((list != "buddy") && (list != "ignore")) - return RespContextError; + return Response::RespContextError; - if ((list == "buddy") && !buddyList.contains(user)) - return RespContextError; - if ((list == "ignore") && !ignoreList.contains(user)) - return RespContextError; + if (list == "buddy") + if (!servatrice->isInBuddyList(QString::fromStdString(userInfo->name()), user)) + return Response::RespContextError; + if (list == "ignore") + if (!servatrice->isInIgnoreList(QString::fromStdString(userInfo->name()), user)) + return Response::RespContextError; - int id1 = getUserIdInDB(userInfo->getName()); - int id2 = getUserIdInDB(user); + int id1 = servatrice->getUserIdInDB(QString::fromStdString(userInfo->name())); + int id2 = servatrice->getUserIdInDB(user); if (id2 < 0) - return RespNameNotFound; + return Response::RespNameNotFound; QMutexLocker locker(&servatrice->dbMutex); QSqlQuery query; @@ -223,18 +222,14 @@ ResponseCode ServerSocketInterface::cmdRemoveFromList(const Command_RemoveFromLi query.bindValue(":id1", id1); query.bindValue(":id2", id2); if (!servatrice->execSqlQuery(query)) - return RespInternalError; + return Response::RespInternalError; - if (list == "buddy") { - delete buddyList.value(user); - buddyList.remove(user); - } else if (list == "ignore") { - delete ignoreList.value(user); - ignoreList.remove(user); - } + Event_RemoveFromList *event = new Event_RemoveFromList; + event->set_list_name(cmd.list()); + event->set_user_name(cmd.user_name()); + rc.enqueuePreResponseItem(ServerMessage::SESSION_EVENT, event); - bla->enqueueItem(new Event_RemoveFromList(list, user)); - return RespOk; + return Response::RespOk; } int ServerSocketInterface::getDeckPathId(int basePathId, QStringList path) @@ -249,7 +244,7 @@ int ServerSocketInterface::getDeckPathId(int basePathId, QStringList path) query.prepare("select id from " + servatrice->getDbPrefix() + "_decklist_folders where id_parent = :id_parent and name = :name and user = :user"); query.bindValue(":id_parent", basePathId); query.bindValue(":name", path.takeFirst()); - query.bindValue(":user", userInfo->getName()); + query.bindValue(":user", QString::fromStdString(userInfo->name())); if (!servatrice->execSqlQuery(query)) return -1; if (!query.next()) @@ -265,7 +260,7 @@ int ServerSocketInterface::getDeckPathId(const QString &path) { return getDeckPathId(0, path.split("/")); } - +/* bool ServerSocketInterface::deckListHelper(DeckList_Directory *folder) { QMutexLocker locker(&servatrice->dbMutex); @@ -296,50 +291,50 @@ bool ServerSocketInterface::deckListHelper(DeckList_Directory *folder) return true; } - +*/ // CHECK AUTHENTICATION! // Also check for every function that data belonging to other users cannot be accessed. -ResponseCode ServerSocketInterface::cmdDeckList(const Command_DeckList & /*cmd*/, BlaContainer *bla) +Response::ResponseCode ServerSocketInterface::cmdDeckList(const Command_DeckList & /*cmd*/, ResponseContainer &rc) { if (authState != PasswordRight) - return RespFunctionNotAllowed; + return Response::RespFunctionNotAllowed; servatrice->checkSql(); - DeckList_Directory *root = new DeckList_Directory(QString()); +/* DeckList_Directory *root = new DeckList_Directory(QString()); QSqlQuery query; if (!deckListHelper(root)) - return RespContextError; + return Response::RespContextError; ProtocolResponse *resp = new Response_DeckList(-1, RespOk, root); if (getCompressionSupport()) resp->setCompressed(true); bla->setResponse(resp); - - return RespNothing; +*/ + return Response::RespNothing; } -ResponseCode ServerSocketInterface::cmdDeckNewDir(const Command_DeckNewDir &cmd, BlaContainer * /*cont*/) +Response::ResponseCode ServerSocketInterface::cmdDeckNewDir(const Command_DeckNewDir &cmd, ResponseContainer & /*rc*/) { if (authState != PasswordRight) - return RespFunctionNotAllowed; + return Response::RespFunctionNotAllowed; servatrice->checkSql(); int folderId = getDeckPathId(QString::fromStdString(cmd.path())); if (folderId == -1) - return RespNameNotFound; + return Response::RespNameNotFound; QMutexLocker locker(&servatrice->dbMutex); QSqlQuery query; query.prepare("insert into " + servatrice->getDbPrefix() + "_decklist_folders (id_parent, user, name) values(:id_parent, :user, :name)"); query.bindValue(":id_parent", folderId); - query.bindValue(":user", userInfo->getName()); + query.bindValue(":user", QString::fromStdString(userInfo->name())); query.bindValue(":name", QString::fromStdString(cmd.dir_name())); if (!servatrice->execSqlQuery(query)) - return RespContextError; - return RespOk; + return Response::RespContextError; + return Response::RespOk; } void ServerSocketInterface::deckDelDirHelper(int basePathId) @@ -364,24 +359,24 @@ void ServerSocketInterface::deckDelDirHelper(int basePathId) servatrice->execSqlQuery(query); } -ResponseCode ServerSocketInterface::cmdDeckDelDir(const Command_DeckDelDir &cmd, BlaContainer * /*cont*/) +Response::ResponseCode ServerSocketInterface::cmdDeckDelDir(const Command_DeckDelDir &cmd, ResponseContainer & /*rc*/) { if (authState != PasswordRight) - return RespFunctionNotAllowed; + return Response::RespFunctionNotAllowed; servatrice->checkSql(); int basePathId = getDeckPathId(QString::fromStdString(cmd.path())); if (basePathId == -1) - return RespNameNotFound; + return Response::RespNameNotFound; deckDelDirHelper(basePathId); - return RespOk; + return Response::RespOk; } -ResponseCode ServerSocketInterface::cmdDeckDel(const Command_DeckDel &cmd, BlaContainer * /*cont*/) +Response::ResponseCode ServerSocketInterface::cmdDeckDel(const Command_DeckDel &cmd, ResponseContainer & /*rc*/) { if (authState != PasswordRight) - return RespFunctionNotAllowed; + return Response::RespFunctionNotAllowed; servatrice->checkSql(); @@ -390,30 +385,30 @@ ResponseCode ServerSocketInterface::cmdDeckDel(const Command_DeckDel &cmd, BlaCo query.prepare("select id from " + servatrice->getDbPrefix() + "_decklist_files where id = :id and user = :user"); query.bindValue(":id", cmd.deck_id()); - query.bindValue(":user", userInfo->getName()); + query.bindValue(":user", QString::fromStdString(userInfo->name())); servatrice->execSqlQuery(query); if (!query.next()) - return RespNameNotFound; + return Response::RespNameNotFound; query.prepare("delete from " + servatrice->getDbPrefix() + "_decklist_files where id = :id"); query.bindValue(":id", cmd.deck_id()); servatrice->execSqlQuery(query); - return RespOk; + return Response::RespOk; } -ResponseCode ServerSocketInterface::cmdDeckUpload(const Command_DeckUpload &cmd, BlaContainer *bla) +Response::ResponseCode ServerSocketInterface::cmdDeckUpload(const Command_DeckUpload &cmd, ResponseContainer &rc) { if (authState != PasswordRight) - return RespFunctionNotAllowed; + return Response::RespFunctionNotAllowed; servatrice->checkSql(); if (!cmd.has_deck_list()) - return RespInvalidData; + return Response::RespInvalidData; int folderId = getDeckPathId(QString::fromStdString(cmd.path())); if (folderId == -1) - return RespNameNotFound; + return Response::RespNameNotFound; QString deckStr = QString::fromStdString(cmd.deck_list()); DeckList deck(deckStr); @@ -426,13 +421,13 @@ ResponseCode ServerSocketInterface::cmdDeckUpload(const Command_DeckUpload &cmd, QSqlQuery query; query.prepare("insert into " + servatrice->getDbPrefix() + "_decklist_files (id_folder, user, name, upload_time, content) values(:id_folder, :user, :name, NOW(), :content)"); query.bindValue(":id_folder", folderId); - query.bindValue(":user", userInfo->getName()); + query.bindValue(":user", QString::fromStdString(userInfo->name())); query.bindValue(":name", deckName); query.bindValue(":content", deckStr); servatrice->execSqlQuery(query); - bla->setResponse(new Response_DeckUpload(-1, RespOk, new DeckList_File(deckName, query.lastInsertId().toInt(), QDateTime::currentDateTime()))); - return RespNothing; +// bla->setResponse(new Response_DeckUpload(-1, RespOk, new DeckList_File(deckName, query.lastInsertId().toInt(), QDateTime::currentDateTime()))); + return Response::RespNothing; } DeckList *ServerSocketInterface::getDeckFromDatabase(int deckId) @@ -444,10 +439,10 @@ DeckList *ServerSocketInterface::getDeckFromDatabase(int deckId) query.prepare("select content from " + servatrice->getDbPrefix() + "_decklist_files where id = :id and user = :user"); query.bindValue(":id", deckId); - query.bindValue(":user", userInfo->getName()); + query.bindValue(":user", QString::fromStdString(userInfo->name())); servatrice->execSqlQuery(query); if (!query.next()) - throw RespNameNotFound; + throw Response::RespNameNotFound; QXmlStreamReader deckReader(query.value(0).toString()); DeckList *deck = new DeckList; @@ -456,25 +451,30 @@ DeckList *ServerSocketInterface::getDeckFromDatabase(int deckId) return deck; } -ResponseCode ServerSocketInterface::cmdDeckDownload(const Command_DeckDownload &cmd, BlaContainer *bla) +Response::ResponseCode ServerSocketInterface::cmdDeckDownload(const Command_DeckDownload &cmd, ResponseContainer &rc) { if (authState != PasswordRight) - return RespFunctionNotAllowed; + return Response::RespFunctionNotAllowed; DeckList *deck; try { deck = getDeckFromDatabase(cmd.deck_id()); - } catch(ResponseCode r) { + } catch(Response::ResponseCode r) { return r; } - bla->setResponse(new Response_DeckDownload(-1, RespOk, deck)); - return RespNothing; + + Response_DeckDownload *re = new Response_DeckDownload; + re->set_deck(deck->writeToString_Native().toStdString()); + rc.setResponseExtension(re); + delete deck; + + return Response::RespOk; } // MODERATOR FUNCTIONS. // May be called by admins and moderators. Permission is checked by the calling function. -ResponseCode ServerSocketInterface::cmdBanFromServer(const Command_BanFromServer &cmd, BlaContainer * /*cont*/) +Response::ResponseCode ServerSocketInterface::cmdBanFromServer(const Command_BanFromServer &cmd, ResponseContainer & /*rc*/) { QString userName = QString::fromStdString(cmd.user_name()); QString address = QString::fromStdString(cmd.address()); @@ -485,7 +485,7 @@ ResponseCode ServerSocketInterface::cmdBanFromServer(const Command_BanFromServer query.prepare("insert into " + servatrice->getDbPrefix() + "_bans (user_name, ip_address, id_admin, time_from, minutes, reason) values(:user_name, :ip_address, :id_admin, NOW(), :minutes, :reason)"); query.bindValue(":user_name", userName); query.bindValue(":ip_address", address); - query.bindValue(":id_admin", getUserIdInDB(userInfo->getName())); + query.bindValue(":id_admin", servatrice->getUserIdInDB(QString::fromStdString(userInfo->name()))); query.bindValue(":minutes", minutes); query.bindValue(":reason", QString::fromStdString(cmd.reason()) + "\n"); servatrice->execSqlQuery(query); @@ -493,24 +493,28 @@ ResponseCode ServerSocketInterface::cmdBanFromServer(const Command_BanFromServer ServerSocketInterface *user = static_cast(server->getUsers().value(userName)); if (user) { - user->sendProtocolItem(new Event_ConnectionClosed("banned")); + Event_ConnectionClosed event; + event.set_reason("banned"); + SessionEvent *se = user->prepareSessionEvent(event); + user->sendProtocolItem(*se); + delete se; user->deleteLater(); } - return RespOk; + return Response::RespOk; } // ADMIN FUNCTIONS. // Permission is checked by the calling function. -ResponseCode ServerSocketInterface::cmdUpdateServerMessage(const Command_UpdateServerMessage & /*cmd*/, BlaContainer * /*cont*/) +Response::ResponseCode ServerSocketInterface::cmdUpdateServerMessage(const Command_UpdateServerMessage & /*cmd*/, ResponseContainer & /*rc*/) { servatrice->updateLoginMessage(); - return RespOk; + return Response::RespOk; } -ResponseCode ServerSocketInterface::cmdShutdownServer(const Command_ShutdownServer &cmd, BlaContainer * /*cont*/) +Response::ResponseCode ServerSocketInterface::cmdShutdownServer(const Command_ShutdownServer &cmd, ResponseContainer & /*rc*/) { servatrice->scheduleShutdown(QString::fromStdString(cmd.reason()), cmd.minutes()); - return RespOk; + return Response::RespOk; } diff --git a/servatrice/src/serversocketinterface.h b/servatrice/src/serversocketinterface.h index 82badaa0..1cd055eb 100644 --- a/servatrice/src/serversocketinterface.h +++ b/servatrice/src/serversocketinterface.h @@ -27,11 +27,7 @@ class QTcpSocket; class Servatrice; -class QXmlStreamReader; -class QXmlStreamWriter; class DeckList; -class TopLevelProtocolItem; -class QByteArray; class ServerSocketInterface : public Server_ProtocolHandler { @@ -39,51 +35,41 @@ class ServerSocketInterface : public Server_ProtocolHandler private slots: void readClient(); void catchSocketError(QAbstractSocket::SocketError socketError); -// void processProtocolItem(ProtocolItem *item); - void flushXmlBuffer(); + void flushOutputBuffer(); signals: - void xmlBufferChanged(); + void outputBufferChanged(); private: - QMutex xmlBufferMutex; + QMutex outputBufferMutex; Servatrice *servatrice; QTcpSocket *socket; - QXmlStreamWriter *xmlWriter; - QXmlStreamReader *xmlReader; - QString xmlBuffer; - TopLevelProtocolItem *topLevelItem; - bool compressionSupport; - QByteArray inputBuffer; + QByteArray inputBuffer, outputBuffer; bool messageInProgress; int messageLength; - int getUserIdInDB(const QString &name) const; - - ResponseCode cmdAddToList(const Command_AddToList &cmd, BlaContainer *bla); - ResponseCode cmdRemoveFromList(const Command_RemoveFromList &cmd, BlaContainer *bla); + Response::ResponseCode cmdAddToList(const Command_AddToList &cmd, ResponseContainer &rc); + Response::ResponseCode cmdRemoveFromList(const Command_RemoveFromList &cmd, ResponseContainer &rc); int getDeckPathId(int basePathId, QStringList path); int getDeckPathId(const QString &path); - bool deckListHelper(DeckList_Directory *folder); - ResponseCode cmdDeckList(const Command_DeckList &cmd, BlaContainer *bla); - ResponseCode cmdDeckNewDir(const Command_DeckNewDir &cmd, BlaContainer *bla); +// bool deckListHelper(DeckList_Directory *folder); + Response::ResponseCode cmdDeckList(const Command_DeckList &cmd, ResponseContainer &rc); + Response::ResponseCode cmdDeckNewDir(const Command_DeckNewDir &cmd, ResponseContainer &rc); void deckDelDirHelper(int basePathId); - ResponseCode cmdDeckDelDir(const Command_DeckDelDir &cmd, BlaContainer *bla); - ResponseCode cmdDeckDel(const Command_DeckDel &cmd, BlaContainer *bla); - ResponseCode cmdDeckUpload(const Command_DeckUpload &cmd, BlaContainer *bla); + Response::ResponseCode cmdDeckDelDir(const Command_DeckDelDir &cmd, ResponseContainer &rc); + Response::ResponseCode cmdDeckDel(const Command_DeckDel &cmd, ResponseContainer &rc); + Response::ResponseCode cmdDeckUpload(const Command_DeckUpload &cmd, ResponseContainer &rc); DeckList *getDeckFromDatabase(int deckId); - ResponseCode cmdDeckDownload(const Command_DeckDownload &cmd, BlaContainer *bla); - ResponseCode cmdBanFromServer(const Command_BanFromServer &cmd, BlaContainer *bla); - ResponseCode cmdShutdownServer(const Command_ShutdownServer &cmd, BlaContainer *bla); - ResponseCode cmdUpdateServerMessage(const Command_UpdateServerMessage &cmd, BlaContainer *bla); -protected: - bool getCompressionSupport() const { return compressionSupport; } + Response::ResponseCode cmdDeckDownload(const Command_DeckDownload &cmd, ResponseContainer &rc); + Response::ResponseCode cmdBanFromServer(const Command_BanFromServer &cmd, ResponseContainer &rc); + Response::ResponseCode cmdShutdownServer(const Command_ShutdownServer &cmd, ResponseContainer &rc); + Response::ResponseCode cmdUpdateServerMessage(const Command_UpdateServerMessage &cmd, ResponseContainer &rc); public: ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent = 0); ~ServerSocketInterface(); QHostAddress getPeerAddress() const { return socket->peerAddress(); } QString getAddress() const { return socket->peerAddress().toString(); } - void sendProtocolItem(ProtocolItem *item, bool deleteItem = true); + void transmitProtocolItem(const ServerMessage &item); }; #endif