PB: server compiles again, standalone RemoteClient is able to log in

This commit is contained in:
Max-Wilhelm Bruker 2011-12-30 21:50:25 +01:00
parent 10018280e5
commit d3b96b1a88
39 changed files with 988 additions and 807 deletions

View file

@ -88,8 +88,6 @@ HEADERS += src/abstractcounter.h \
../common/serializable_item.h \ ../common/serializable_item.h \
../common/decklist.h \ ../common/decklist.h \
../common/protocol.h \ ../common/protocol.h \
../common/protocol_items.h \
../common/protocol_datastructures.h \
../common/rng_abstract.h \ ../common/rng_abstract.h \
../common/rng_sfmt.h \ ../common/rng_sfmt.h \
../common/server.h \ ../common/server.h \
@ -170,12 +168,9 @@ SOURCES += src/abstractcounter.cpp \
src/localclient.cpp \ src/localclient.cpp \
src/priceupdater.cpp \ src/priceupdater.cpp \
src/soundengine.cpp \ src/soundengine.cpp \
src/pending_command.cpp \
../common/serializable_item.cpp \ ../common/serializable_item.cpp \
../common/decklist.cpp \ ../common/decklist.cpp \
../common/protocol.cpp \ ../common/protocol.cpp \
../common/protocol_items.cpp \
../common/protocol_datastructures.cpp \
../common/rng_abstract.cpp \ ../common/rng_abstract.cpp \
../common/rng_sfmt.cpp \ ../common/rng_sfmt.cpp \
../common/sfmt/SFMT.c \ ../common/sfmt/SFMT.c \

View file

@ -1,9 +1,19 @@
#include "abstractclient.h" #include "abstractclient.h"
#include "protocol.h" #include "protocol.h"
#include "protocol_items.h"
#include "pending_command.h" #include "pending_command.h"
#include "pb/commands.pb.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 <google/protobuf/descriptor.h> #include <google/protobuf/descriptor.h>
AbstractClient::AbstractClient(QObject *parent) 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<ProtocolResponse *>(item); switch (item.message_type()) {
if (response) { case ServerMessage::RESPONSE: {
const int cmdId = response->getCmdId(); const Response &response = item.response();
PendingCommand *pend = pendingCommands.value(cmdId, 0); const int cmdId = response.cmd_id();
if (!pend) PendingCommand *pend = pendingCommands.value(cmdId, 0);
return; if (!pend)
return;
pendingCommands.remove(cmdId);
pend->processResponse(response); pendingCommands.remove(cmdId);
if (response->getReceiverMayDelete()) pend->processResponse(response);
delete response; pend->deleteLater();
pend->deleteLater(); break;
}
return; case ServerMessage::SESSION_EVENT: {
} const SessionEvent &event = item.session_event();
std::vector< const ::google::protobuf::FieldDescriptor * > fieldList;
GenericEvent *genericEvent = qobject_cast<GenericEvent *>(item); event.GetReflection()->ListFields(event, &fieldList);
if (genericEvent) { int num = 0;
switch (genericEvent->getItemId()) { for (unsigned int j = 0; j < fieldList.size(); ++j)
case ItemId_Event_ConnectionClosed: emit connectionClosedEventReceived(static_cast<Event_ConnectionClosed *>(item)); break; if (fieldList[j]->is_extension()) {
case ItemId_Event_ServerShutdown: emit serverShutdownEventReceived(static_cast<Event_ServerShutdown *>(item)); break; num = fieldList[j]->number();
case ItemId_Event_AddToList: emit addToListEventReceived(static_cast<Event_AddToList *>(item)); break; break;
case ItemId_Event_RemoveFromList: emit removeFromListEventReceived(static_cast<Event_RemoveFromList *>(item)); break; }
case ItemId_Event_UserJoined: emit userJoinedEventReceived(static_cast<Event_UserJoined *>(item)); break; switch ((SessionEvent::SessionEventType) num) {
case ItemId_Event_UserLeft: emit userLeftEventReceived(static_cast<Event_UserLeft *>(item)); break; case SessionEvent::SERVER_IDENTIFICATION: emit serverIdentificationEventReceived(event.GetExtension(Event_ServerIdentification::ext)); break;
case ItemId_Event_ServerMessage: emit serverMessageEventReceived(static_cast<Event_ServerMessage *>(item)); break; case SessionEvent::SERVER_MESSAGE: emit serverMessageEventReceived(event.GetExtension(Event_ServerMessage::ext)); break;
case ItemId_Event_ListRooms: emit listRoomsEventReceived(static_cast<Event_ListRooms *>(item)); break; case SessionEvent::SERVER_SHUTDOWN: emit serverShutdownEventReceived(event.GetExtension(Event_ServerShutdown::ext)); break;
case ItemId_Event_GameJoined: emit gameJoinedEventReceived(static_cast<Event_GameJoined *>(item)); break; case SessionEvent::CONNECTION_CLOSED: emit connectionClosedEventReceived(event.GetExtension(Event_ConnectionClosed::ext)); break;
case ItemId_Event_Message: emit messageEventReceived(static_cast<Event_Message *>(item)); 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<GameEventContainer *>(item);
if (gameEventContainer) {
emit gameEventContainerReceived(gameEventContainer);
if (gameEventContainer->getReceiverMayDelete())
delete gameEventContainer;
return;
}
RoomEvent *roomEvent = qobject_cast<RoomEvent *>(item);
if (roomEvent) {
emit roomEventReceived(roomEvent);
if (roomEvent->getReceiverMayDelete())
delete roomEvent;
return;
} }
} }

View file

@ -3,17 +3,15 @@
#include <QObject> #include <QObject>
#include <QVariant> #include <QVariant>
#include <google/protobuf/message.h> #include "pb/response.pb.h"
#include "protocol_datastructures.h" #include "pb/serverinfo_user.pb.h"
class PendingCommand; class PendingCommand;
class CommandContainer; class CommandContainer;
class ProtocolItem;
class ProtocolResponse;
class TopLevelProtocolItem;
class CommandContainer;
class RoomEvent; class RoomEvent;
class GameEventContainer; class GameEventContainer;
class ServerMessage;
class Event_ServerIdentification;
class Event_AddToList; class Event_AddToList;
class Event_RemoveFromList; class Event_RemoveFromList;
class Event_UserJoined; class Event_UserJoined;
@ -21,7 +19,7 @@ class Event_UserLeft;
class Event_ServerMessage; class Event_ServerMessage;
class Event_ListRooms; class Event_ListRooms;
class Event_GameJoined; class Event_GameJoined;
class Event_Message; class Event_UserMessage;
class Event_ConnectionClosed; class Event_ConnectionClosed;
class Event_ServerShutdown; class Event_ServerShutdown;
@ -38,30 +36,31 @@ class AbstractClient : public QObject {
Q_OBJECT Q_OBJECT
signals: signals:
void statusChanged(ClientStatus _status); void statusChanged(ClientStatus _status);
void serverError(ResponseCode resp); void serverError(Response::ResponseCode resp);
// Room events // Room events
void roomEventReceived(RoomEvent *event); void roomEventReceived(const RoomEvent &event);
// Game events // Game events
void gameEventContainerReceived(GameEventContainer *event); void gameEventContainerReceived(const GameEventContainer &event);
// Generic events // Session events
void connectionClosedEventReceived(Event_ConnectionClosed *event); void serverIdentificationEventReceived(const Event_ServerIdentification &event);
void serverShutdownEventReceived(Event_ServerShutdown *event); void connectionClosedEventReceived(const Event_ConnectionClosed &event);
void addToListEventReceived(Event_AddToList *event); void serverShutdownEventReceived(const Event_ServerShutdown &event);
void removeFromListEventReceived(Event_RemoveFromList *event); void addToListEventReceived(const Event_AddToList &event);
void userJoinedEventReceived(Event_UserJoined *event); void removeFromListEventReceived(const Event_RemoveFromList &event);
void userLeftEventReceived(Event_UserLeft *event); void userJoinedEventReceived(const Event_UserJoined &event);
void serverMessageEventReceived(Event_ServerMessage *event); void userLeftEventReceived(const Event_UserLeft &event);
void listRoomsEventReceived(Event_ListRooms *event); void serverMessageEventReceived(const Event_ServerMessage &event);
void gameJoinedEventReceived(Event_GameJoined *event); void listRoomsEventReceived(const Event_ListRooms &event);
void messageEventReceived(Event_Message *event); void gameJoinedEventReceived(const Event_GameJoined &event);
void userInfoChanged(ServerInfo_User *userInfo); void userMessageEventReceived(const Event_UserMessage &event);
void buddyListReceived(const QList<ServerInfo_User *> &buddyList); void userInfoChanged(const ServerInfo_User &userInfo);
void ignoreListReceived(const QList<ServerInfo_User *> &ignoreList); void buddyListReceived(const QList<ServerInfo_User> &buddyList);
void ignoreListReceived(const QList<ServerInfo_User> &ignoreList);
private: private:
int nextCmdId; int nextCmdId;
protected slots: protected slots:
void processProtocolItem(ProtocolItem *item); void processProtocolItem(const ServerMessage &item);
protected: protected:
QMap<int, PendingCommand *> pendingCommands; QMap<int, PendingCommand *> pendingCommands;
ClientStatus status; ClientStatus status;

View file

@ -125,19 +125,19 @@ void DlgCreateGame::actOK()
} }
PendingCommand *pend = room->prepareRoomCommand(cmd); 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); room->sendRoomCommand(pend);
okButton->setEnabled(false); okButton->setEnabled(false);
cancelButton->setEnabled(false); cancelButton->setEnabled(false);
} }
void DlgCreateGame::checkResponse(ResponseCode response) void DlgCreateGame::checkResponse(Response::ResponseCode response)
{ {
okButton->setEnabled(true); okButton->setEnabled(true);
cancelButton->setEnabled(true); cancelButton->setEnabled(true);
if (response == RespOk) if (response == Response::RespOk)
accept(); accept();
else { else {
QMessageBox::critical(this, tr("Error"), tr("Server error.")); QMessageBox::critical(this, tr("Error"), tr("Server error."));

View file

@ -2,7 +2,8 @@
#define DLG_CREATEGAME_H #define DLG_CREATEGAME_H
#include <QDialog> #include <QDialog>
#include "protocol_datastructures.h" #include <QMap>
#include "pb/response.pb.h"
class QLabel; class QLabel;
class QLineEdit; class QLineEdit;
@ -18,7 +19,7 @@ public:
DlgCreateGame(TabRoom *_room, const QMap<int, QString> &_gameTypes, QWidget *parent = 0); DlgCreateGame(TabRoom *_room, const QMap<int, QString> &_gameTypes, QWidget *parent = 0);
private slots: private slots:
void actOK(); void actOK();
void checkResponse(ResponseCode response); void checkResponse(Response::ResponseCode response);
void spectatorsAllowedChanged(int state); void spectatorsAllowedChanged(int state);
private: private:
TabRoom *room; TabRoom *room;

View file

@ -7,7 +7,7 @@
LocalClient::LocalClient(LocalServerInterface *_lsi, const QString &_playerName, QObject *parent) LocalClient::LocalClient(LocalServerInterface *_lsi, const QString &_playerName, QObject *parent)
: AbstractClient(parent), lsi(_lsi) : 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; Command_Login loginCmd;
loginCmd.set_user_name(_playerName.toStdString()); loginCmd.set_user_name(_playerName.toStdString());
@ -27,7 +27,7 @@ void LocalClient::sendCommandContainer(const CommandContainer &cont)
lsi->itemFromClient(cont); lsi->itemFromClient(cont);
} }
void LocalClient::itemFromServer(ProtocolItem *item) void LocalClient::itemFromServer(const ServerMessage &item)
{ {
processProtocolItem(item); processProtocolItem(item);
} }

View file

@ -14,11 +14,8 @@ public:
~LocalClient(); ~LocalClient();
void sendCommandContainer(const CommandContainer &cont); void sendCommandContainer(const CommandContainer &cont);
private slots: private slots:
void itemFromServer(ProtocolItem *item); void itemFromServer(const ServerMessage &item);
signals:
void itemToServer(ProtocolItem *item);
}; };
#endif #endif

View file

@ -20,7 +20,9 @@ LocalServerInterface *LocalServer::newConnection()
return lsi; 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;
} }

View file

@ -23,9 +23,11 @@ protected:
int startSession(const QString & /*userName*/, const QString & /*address*/) { return -1; } int startSession(const QString & /*userName*/, const QString & /*address*/) { return -1; }
void endSession(int /*sessionId*/) { } void endSession(int /*sessionId*/) { }
bool userExists(const QString & /*name*/) { return false; } bool userExists(const QString & /*name*/) { return false; }
ServerInfo_User *getUserData(const QString &name); ServerInfo_User getUserData(const QString &name);
QMap<QString, ServerInfo_User *> getBuddyList(const QString & /*name*/) { return QMap<QString, ServerInfo_User *>(); } QMap<QString, ServerInfo_User> getBuddyList(const QString & /*name*/) { return QMap<QString, ServerInfo_User>(); }
QMap<QString, ServerInfo_User *> getIgnoreList(const QString & /*name*/) { return QMap<QString, ServerInfo_User *>(); } QMap<QString, ServerInfo_User> getIgnoreList(const QString & /*name*/) { return QMap<QString, ServerInfo_User>(); }
bool isInBuddyList(const QString & /*whoseList*/, const QString & /*who*/) { return false; }
bool isInIgnoreList(const QString & /*whoseList*/, const QString & /*who*/) { return false; }
}; };
#endif #endif

View file

@ -12,16 +12,12 @@ LocalServerInterface::~LocalServerInterface()
prepareDestroy(); prepareDestroy();
} }
void LocalServerInterface::sendProtocolItem(ProtocolItem *item, bool deleteItem) void LocalServerInterface::transmitProtocolItem(const ServerMessage &item)
{ {
item->setReceiverMayDelete(false);
emit itemToClient(item); emit itemToClient(item);
if (deleteItem)
delete item;
} }
#include "pb/commands.pb.h"
void LocalServerInterface::itemFromClient(const CommandContainer &item) void LocalServerInterface::itemFromClient(const CommandContainer &item)
{ {
qDebug() << "READ" << QString::fromStdString(item.ShortDebugString());
processCommandContainer(item); processCommandContainer(item);
} }

View file

@ -10,27 +10,25 @@ class LocalServerInterface : public Server_ProtocolHandler
Q_OBJECT Q_OBJECT
private: private:
DeckList *getDeckFromDatabase(int /*deckId*/) { return 0; } DeckList *getDeckFromDatabase(int /*deckId*/) { return 0; }
ResponseCode cmdAddToList(const Command_AddToList & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } Response::ResponseCode cmdAddToList(const Command_AddToList & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; }
ResponseCode cmdRemoveFromList(const Command_RemoveFromList & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } Response::ResponseCode cmdRemoveFromList(const Command_RemoveFromList & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; }
ResponseCode cmdDeckList(const Command_DeckList & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } Response::ResponseCode cmdDeckList(const Command_DeckList & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; }
ResponseCode cmdDeckNewDir(const Command_DeckNewDir & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } Response::ResponseCode cmdDeckNewDir(const Command_DeckNewDir & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; }
ResponseCode cmdDeckDelDir(const Command_DeckDelDir & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } Response::ResponseCode cmdDeckDelDir(const Command_DeckDelDir & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; }
ResponseCode cmdDeckDel(const Command_DeckDel & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } Response::ResponseCode cmdDeckDel(const Command_DeckDel & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; }
ResponseCode cmdDeckUpload(const Command_DeckUpload & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } Response::ResponseCode cmdDeckUpload(const Command_DeckUpload & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; }
ResponseCode cmdDeckDownload(const Command_DeckDownload & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } Response::ResponseCode cmdDeckDownload(const Command_DeckDownload & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; }
ResponseCode cmdBanFromServer(const Command_BanFromServer & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } Response::ResponseCode cmdBanFromServer(const Command_BanFromServer & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; }
ResponseCode cmdShutdownServer(const Command_ShutdownServer & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } Response::ResponseCode cmdShutdownServer(const Command_ShutdownServer & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; }
ResponseCode cmdUpdateServerMessage(const Command_UpdateServerMessage & /*cmd*/, BlaContainer * /*bla*/) { return RespFunctionNotAllowed; } Response::ResponseCode cmdUpdateServerMessage(const Command_UpdateServerMessage & /*cmd*/, ResponseContainer & /*rc*/) { return Response::RespFunctionNotAllowed; }
protected:
bool getCompressionSupport() const { return false; }
public: public:
LocalServerInterface(LocalServer *_server); LocalServerInterface(LocalServer *_server);
~LocalServerInterface(); ~LocalServerInterface();
QString getAddress() const { return QString(); } QString getAddress() const { return QString(); }
void sendProtocolItem(ProtocolItem *item, bool deleteItem = true); void transmitProtocolItem(const ServerMessage &item);
signals: signals:
void itemToClient(ProtocolItem *item); void itemToClient(const ServerMessage &item);
public slots: public slots:
void itemFromClient(const CommandContainer &item); void itemFromClient(const CommandContainer &item);
}; };

View file

@ -1,8 +0,0 @@
#include "pending_command.h"
#include "protocol.h"
void PendingCommand::processResponse(ProtocolResponse *response)
{
emit finished(response);
emit finished(response->getResponseCode());
}

View file

@ -1,17 +1,15 @@
#ifndef PENDING_COMMAND_H #ifndef PENDING_COMMAND_H
#define PENDING_COMMAND_H #define PENDING_COMMAND_H
#include "protocol_datastructures.h"
#include "pb/commands.pb.h" #include "pb/commands.pb.h"
#include "pb/response.pb.h"
#include <QVariant> #include <QVariant>
class ProtocolResponse;
class PendingCommand : public QObject { class PendingCommand : public QObject {
Q_OBJECT Q_OBJECT
signals: signals:
void finished(ProtocolResponse *response); void finished(const Response &response);
void finished(ResponseCode response); void finished(Response::ResponseCode response);
private: private:
CommandContainer commandContainer; CommandContainer commandContainer;
QVariant extraData; QVariant extraData;
@ -22,7 +20,11 @@ public:
CommandContainer &getCommandContainer() { return commandContainer; } CommandContainer &getCommandContainer() { return commandContainer; }
void setExtraData(const QVariant &_extraData) { extraData = _extraData; } void setExtraData(const QVariant &_extraData) { extraData = _extraData; }
QVariant getExtraData() const { return 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; } int tick() { return ++ticks; }
}; };

View file

@ -12,7 +12,6 @@
#include "handcounter.h" #include "handcounter.h"
#include "cardlist.h" #include "cardlist.h"
#include "tab_game.h" #include "tab_game.h"
#include "protocol_items.h"
#include "gamescene.h" #include "gamescene.h"
#include "settingscache.h" #include "settingscache.h"
#include "dlg_create_token.h" #include "dlg_create_token.h"

View file

@ -1,20 +1,15 @@
#include <QTimer> #include <QTimer>
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include <QCryptographicHash>
#include "remoteclient.h" #include "remoteclient.h"
#include "protocol.h" #include "protocol.h"
#include "protocol_items.h"
#include "pending_command.h" #include "pending_command.h"
#include "pb/commands.pb.h" #include "pb/commands.pb.h"
#include "pb/session_commands.pb.h" #include "pb/session_commands.pb.h"
#include "pb/response_login.pb.h"
RemoteClient::RemoteClient(QObject *parent) 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 = new QTimer(this);
timer->setInterval(1000); timer->setInterval(1000);
connect(timer, SIGNAL(timeout()), this, SLOT(ping())); 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(readyRead()), this, SLOT(readData()));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slotSocketError(QAbstractSocket::SocketError))); 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() RemoteClient::~RemoteClient()
@ -46,61 +41,72 @@ void RemoteClient::slotConnected()
setStatus(StatusAwaitingWelcome); setStatus(StatusAwaitingWelcome);
} }
void RemoteClient::loginResponse(ProtocolResponse *response) void RemoteClient::processServerIdentificationEvent(const Event_ServerIdentification & /*event*/)
{ {
if (response->getResponseCode() == RespOk) { setStatus(StatusLoggingIn);
Response_Login *resp = qobject_cast<Response_Login *>(response);
if (!resp) { Command_Login cmdLogin;
disconnectFromServer(); cmdLogin.set_user_name(userName.toStdString());
return; 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); setStatus(StatusLoggedIn);
emit userInfoChanged(resp->getUserInfo()); emit userInfoChanged(resp.user_info());
emit buddyListReceived(resp->getBuddyList());
emit ignoreListReceived(resp->getIgnoreList()); QList<ServerInfo_User> buddyList;
for (int i = resp.buddy_list_size() - 1; i >= 0; --i)
buddyList.append(resp.buddy_list(i));
emit buddyListReceived(buddyList);
QList<ServerInfo_User> ignoreList;
for (int i = resp.ignore_list_size() - 1; i >= 0; --i)
ignoreList.append(resp.ignore_list(i));
emit ignoreListReceived(ignoreList);
} else { } else {
emit serverError(response->getResponseCode()); emit serverError(response.response_code());
setStatus(StatusDisconnecting); setStatus(StatusDisconnecting);
} }
} }
void RemoteClient::readData() void RemoteClient::readData()
{ {
QByteArray data = socket->readAll();
qDebug() << data;
xmlReader->addData(data);
lastDataReceived = timeRunning; lastDataReceived = timeRunning;
QByteArray data = socket->readAll();
while (!xmlReader->atEnd()) { inputBuffer.append(data);
xmlReader->readNext();
if (topLevelItem) do {
topLevelItem->readElement(xmlReader); if (!messageInProgress) {
else if (xmlReader->isStartElement() && (xmlReader->name().toString() == "cockatrice_server_stream")) { if (inputBuffer.size() >= 4) {
int serverVersion = xmlReader->attributes().value("version").toString().toInt(); messageLength = (((quint32) (unsigned char) inputBuffer[0]) << 24)
if (serverVersion != ProtocolItem::protocolVersion) { + (((quint32) (unsigned char) inputBuffer[1]) << 16)
emit protocolVersionMismatch(ProtocolItem::protocolVersion, serverVersion); + (((quint32) (unsigned char) inputBuffer[2]) << 8)
disconnectFromServer(); + ((quint32) (unsigned char) inputBuffer[3]);
inputBuffer.remove(0, 4);
messageInProgress = true;
} else
return; 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) if (status == StatusDisconnecting)
disconnectFromServer(); disconnectFromServer();
} }
@ -131,12 +137,10 @@ void RemoteClient::connectToServer(const QString &hostname, unsigned int port, c
void RemoteClient::disconnectFromServer() void RemoteClient::disconnectFromServer()
{ {
delete topLevelItem;
topLevelItem = 0;
xmlReader->clear();
timer->stop(); timer->stop();
messageInProgress = false;
messageLength = 0;
QList<PendingCommand *> pc = pendingCommands.values(); QList<PendingCommand *> pc = pendingCommands.values();
for (int i = 0; i < pc.size(); i++) for (int i = 0; i < pc.size(); i++)

View file

@ -5,8 +5,6 @@
#include "abstractclient.h" #include "abstractclient.h"
class QTimer; class QTimer;
class QXmlStreamReader;
class QXmlStreamWriter;
class RemoteClient : public AbstractClient { class RemoteClient : public AbstractClient {
Q_OBJECT Q_OBJECT
@ -21,15 +19,18 @@ private slots:
void readData(); void readData();
void slotSocketError(QAbstractSocket::SocketError error); void slotSocketError(QAbstractSocket::SocketError error);
void ping(); void ping();
void loginResponse(ProtocolResponse *response); void processServerIdentificationEvent(const Event_ServerIdentification &event);
void loginResponse(const Response &response);
private: private:
static const int maxTimeout = 10; static const int maxTimeout = 10;
int timeRunning, lastDataReceived; int timeRunning, lastDataReceived;
QByteArray inputBuffer;
bool messageInProgress;
int messageLength;
QTimer *timer; QTimer *timer;
QTcpSocket *socket; QTcpSocket *socket;
QXmlStreamReader *xmlReader;
TopLevelProtocolItem *topLevelItem;
void sendCommandContainer(const CommandContainer &cont); void sendCommandContainer(const CommandContainer &cont);
public: public:

View file

@ -51,7 +51,7 @@ void MainWindow::updateTabMenu(QMenu *menu)
void MainWindow::processConnectionClosedEvent(Event_ConnectionClosed *event) void MainWindow::processConnectionClosedEvent(Event_ConnectionClosed *event)
{ {
QString reason = event->getReason(); /* QString reason = event->getReason();
client->disconnectFromServer(); client->disconnectFromServer();
QString reasonStr; QString reasonStr;
if (reason == "too_many_connections") if (reason == "too_many_connections")
@ -63,11 +63,13 @@ void MainWindow::processConnectionClosedEvent(Event_ConnectionClosed *event)
else else
reasonStr = tr("Unknown reason."); reasonStr = tr("Unknown reason.");
QMessageBox::critical(this, tr("Connection closed"), tr("The server has terminated your connection.\nReason: %1").arg(reasonStr)); QMessageBox::critical(this, tr("Connection closed"), tr("The server has terminated your connection.\nReason: %1").arg(reasonStr));
*/
} }
void MainWindow::processServerShutdownEvent(Event_ServerShutdown *event) 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) void MainWindow::statusChanged(ClientStatus _status)
@ -199,11 +201,11 @@ void MainWindow::serverTimeout()
QMessageBox::critical(this, tr("Error"), tr("Server timeout")); QMessageBox::critical(this, tr("Error"), tr("Server timeout"));
} }
void MainWindow::serverError(ResponseCode r) void MainWindow::serverError(Response::ResponseCode r)
{ {
switch (r) { switch (r) {
case RespWrongPassword: QMessageBox::critical(this, tr("Error"), tr("Invalid login data.")); break; case Response::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::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: ; default: ;
} }
} }
@ -302,7 +304,7 @@ MainWindow::MainWindow(QWidget *parent)
client = new RemoteClient(this); client = new RemoteClient(this);
connect(client, SIGNAL(connectionClosedEventReceived(Event_ConnectionClosed *)), this, SLOT(processConnectionClosedEvent(Event_ConnectionClosed *))); 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(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(socketError(const QString &)), this, SLOT(socketError(const QString &)));
connect(client, SIGNAL(serverTimeout()), this, SLOT(serverTimeout())); connect(client, SIGNAL(serverTimeout()), this, SLOT(serverTimeout()));
connect(client, SIGNAL(statusChanged(ClientStatus)), this, SLOT(statusChanged(ClientStatus))); connect(client, SIGNAL(statusChanged(ClientStatus)), this, SLOT(statusChanged(ClientStatus)));

View file

@ -22,7 +22,7 @@
#include <QMainWindow> #include <QMainWindow>
#include "abstractclient.h" #include "abstractclient.h"
#include "protocol_datastructures.h" #include "pb/response.pb.h"
class TabSupervisor; class TabSupervisor;
class RemoteClient; class RemoteClient;
@ -38,7 +38,7 @@ private slots:
void processConnectionClosedEvent(Event_ConnectionClosed *event); void processConnectionClosedEvent(Event_ConnectionClosed *event);
void processServerShutdownEvent(Event_ServerShutdown *event); void processServerShutdownEvent(Event_ServerShutdown *event);
void serverTimeout(); void serverTimeout();
void serverError(ResponseCode r); void serverError(Response::ResponseCode r);
void socketError(const QString &errorStr); void socketError(const QString &errorStr);
void protocolVersionMismatch(int localVersion, int remoteVersion); void protocolVersionMismatch(int localVersion, int remoteVersion);
void userInfoReceived(ServerInfo_User *userInfo); void userInfoReceived(ServerInfo_User *userInfo);

View file

@ -24,6 +24,7 @@ public:
{ {
return QColor(value / 65536, (value % 65536) / 256, value % 256); return QColor(value / 65536, (value % 65536) / 256, value % 256);
} }
#endif
color get_color() const // HACK color get_color() const // HACK
{ {
color c; color c;
@ -32,7 +33,6 @@ public:
c.set_b(value % 256); c.set_b(value % 256);
return c; return c;
} }
#endif
}; };
#endif #endif

View file

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

View file

@ -1,5 +1,6 @@
message SessionEvent { message SessionEvent {
enum SessionEventType { enum SessionEventType {
SERVER_IDENTIFICATION = 500;
SERVER_MESSAGE = 1000; SERVER_MESSAGE = 1000;
SERVER_SHUTDOWN = 1001; SERVER_SHUTDOWN = 1001;
CONNECTION_CLOSED = 1002; CONNECTION_CLOSED = 1002;

View file

@ -1,55 +1,3 @@
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#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<GameEvent *>(), gameId);
gameEventQueuePublic->addGameEvent(event);
if (context)
gameEventQueuePublic->setContext(context);
}
void BlaContainer::enqueueGameEventOmniscient(GameEvent *event, int gameId, GameEventContext *context)
{
if (!gameEventQueueOmniscient)
gameEventQueueOmniscient = new GameEventContainer(QList<GameEvent *>(), 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<GameEvent *>(), gameId);
gameEventQueuePrivate->addGameEvent(event);
privatePlayerId = playerId;
if (context)
gameEventQueuePrivate->setContext(context);
}
/* /*
Response_DeckDownload::Response_DeckDownload(int _cmdId, ResponseCode _responseCode, DeckList *_deck) Response_DeckDownload::Response_DeckDownload(int _cmdId, ResponseCode _responseCode, DeckList *_deck)
: ProtocolResponse(_cmdId, _responseCode, "deck_download") : ProtocolResponse(_cmdId, _responseCode, "deck_download")

View file

@ -6,66 +6,70 @@
#include <QHash> #include <QHash>
#include <QObject> #include <QObject>
#include <QVariant> #include <QVariant>
#include "serializable_item.h"
#include <QPair> #include <QPair>
#include <google/protobuf/message.h> #include <google/protobuf/message.h>
#include "pb/server_message.pb.h" #include "pb/server_message.pb.h"
class QXmlStreamReader;
class QXmlStreamWriter;
class QXmlStreamAttributes;
class ProtocolResponse;
class DeckList; class DeckList;
class GameEvent; class GameEvent;
class GameEventContainer; class GameEventContainer;
class GameEventContext; class GameEventContext;
class MoveCardToZone;
class ProtocolItem : public SerializableItem_Map { static const int protocolVersion = 13;
Q_OBJECT
private: class GameEventStorageItem {
bool receiverMayDelete;
public: public:
static const int protocolVersion = 13; enum EventRecipient { SendToPrivate = 0x01, SendToOthers = 0x02};
virtual int getItemId() const = 0; Q_DECLARE_FLAGS(EventRecipients, EventRecipient)
bool getReceiverMayDelete() const { return receiverMayDelete; } private:
void setReceiverMayDelete(bool _receiverMayDelete) { receiverMayDelete = _receiverMayDelete; } ::google::protobuf::Message *event;
ProtocolItem(const QString &_itemType, const QString &_itemSubType); int playerId;
bool isEmpty() const { return false; } 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; }
}; };
Q_DECLARE_OPERATORS_FOR_FLAGS(GameEventStorageItem::EventRecipients)
// ----------------
// --- COMMANDS ---
// ----------------
class GameEventStorage { class GameEventStorage {
private: private:
::google::protobuf::Message *gameEventContext; ::google::protobuf::Message *gameEventContext;
GameEventContainer *gameEventQueuePublic; QList<GameEventStorageItem *> gameEventList;
GameEventContainer *gameEventQueueOmniscient;
GameEventContainer *gameEventQueuePrivate;
int privatePlayerId; int privatePlayerId;
public: 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; } void setGameEventContext(::google::protobuf::Message *_gameEventContext) { gameEventContext = _gameEventContext; }
::google::protobuf::Message *getGameEventContext() const { return 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; } 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 { class ResponseContainer {
@ -74,7 +78,14 @@ private:
QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > preResponseQueue, postResponseQueue; QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > preResponseQueue, postResponseQueue;
public: public:
ResponseContainer() : responseExtension(0) { } 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; } void setResponseExtension(::google::protobuf::Message *_responseExtension) { responseExtension = _responseExtension; }
::google::protobuf::Message *getResponseExtension() const { return responseExtension; } ::google::protobuf::Message *getResponseExtension() const { return responseExtension; }
void enqueuePreResponseItem(ServerMessage::MessageType type, ::google::protobuf::Message *item) { preResponseQueue.append(qMakePair(type, item)); } void enqueuePreResponseItem(ServerMessage::MessageType type, ::google::protobuf::Message *item) { preResponseQueue.append(qMakePair(type, item)); }

View file

@ -22,7 +22,9 @@
#include "server_counter.h" #include "server_counter.h"
#include "server_room.h" #include "server_room.h"
#include "server_protocolhandler.h" #include "server_protocolhandler.h"
#include "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 <QCoreApplication> #include <QCoreApplication>
#include <QDebug> #include <QDebug>
@ -56,14 +58,13 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString
if (authState == PasswordWrong) if (authState == PasswordWrong)
return authState; return authState;
ServerInfo_User *data = getUserData(name); ServerInfo_User data = getUserData(name);
data->setAddress(session->getAddress()); data.set_address(session->getAddress().toStdString());
name = data->getName(); // Compensate for case indifference name = QString::fromStdString(data.name()); // Compensate for case indifference
if (authState == PasswordRight) { if (authState == PasswordRight) {
if (users.contains(name)) { if (users.contains(name)) {
qDebug("Login denied: would overwrite old session"); qDebug("Login denied: would overwrite old session");
delete data;
return WouldOverwriteOldSession; return WouldOverwriteOldSession;
} }
} else if (authState == UnknownUser) { } else if (authState == UnknownUser) {
@ -74,7 +75,7 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString
while (users.contains(tempName) || userExists(tempName)) while (users.contains(tempName) || userExists(tempName))
tempName = name + "_" + QString::number(++i); tempName = name + "_" + QString::number(++i);
name = tempName; name = tempName;
data->setName(name); data.set_name(name.toStdString());
} }
session->setUserInfo(data); session->setUserInfo(data);
@ -85,11 +86,13 @@ AuthenticationResult Server::loginUser(Server_ProtocolHandler *session, QString
session->setSessionId(startSession(name, session->getAddress())); session->setSessionId(startSession(name, session->getAddress()));
qDebug() << "session id:" << session->getSessionId(); 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) for (int i = 0; i < clients.size(); ++i)
if (clients[i]->getAcceptsUserListChanges()) if (clients[i]->getAcceptsUserListChanges())
clients[i]->sendProtocolItem(event, false); clients[i]->sendProtocolItem(*se);
delete event; delete se;
return authState; return authState;
} }
@ -106,14 +109,16 @@ void Server::removeClient(Server_ProtocolHandler *client)
clients.removeAt(clients.indexOf(client)); clients.removeAt(clients.indexOf(client));
ServerInfo_User *data = client->getUserInfo(); ServerInfo_User *data = client->getUserInfo();
if (data) { 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) for (int i = 0; i < clients.size(); ++i)
if (clients[i]->getAcceptsUserListChanges()) if (clients[i]->getAcceptsUserListChanges())
clients[i]->sendProtocolItem(event, false); clients[i]->sendProtocolItem(*se);
delete event; delete se;
users.remove(data->getName()); users.remove(QString::fromStdString(data->name()));
qDebug() << "Server::removeClient: name=" << data->getName(); qDebug() << "Server::removeClient: name=" << QString::fromStdString(data->name());
if (client->getSessionId() != -1) if (client->getSessionId() != -1)
endSession(client->getSessionId()); endSession(client->getSessionId());
@ -126,16 +131,19 @@ void Server::broadcastRoomUpdate()
{ {
QMutexLocker locker(&serverMutex); QMutexLocker locker(&serverMutex);
Server_Room *room = static_cast<Server_Room *>(sender()); Server_Room *room = static_cast<Server_Room *>(sender());
QList<ServerInfo_Room *> eventRoomList; Event_ListRooms event;
ServerInfo_Room *roomInfo = event.add_room_list();
room->roomMutex.lock(); 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(); room->roomMutex.unlock();
Event_ListRooms *event = new Event_ListRooms(eventRoomList);
SessionEvent *se = Server_ProtocolHandler::prepareSessionEvent(event);
for (int i = 0; i < clients.size(); ++i) for (int i = 0; i < clients.size(); ++i)
if (clients[i]->getAcceptsRoomListChanges()) if (clients[i]->getAcceptsRoomListChanges())
clients[i]->sendProtocolItem(event, false); clients[i]->sendProtocolItem(*se);
delete event; delete se;
} }
void Server::addRoom(Server_Room *newRoom) void Server::addRoom(Server_Room *newRoom)

View file

@ -42,8 +42,10 @@ public:
virtual int getMaxGamesPerUser() const { return 0; } virtual int getMaxGamesPerUser() const { return 0; }
virtual bool getThreaded() const = 0; virtual bool getThreaded() const = 0;
virtual QMap<QString, ServerInfo_User *> getBuddyList(const QString &name) = 0; virtual QMap<QString, ServerInfo_User> getBuddyList(const QString &name) = 0;
virtual QMap<QString, ServerInfo_User *> getIgnoreList(const QString &name) = 0; virtual QMap<QString, ServerInfo_User> 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: protected:
void prepareDestroy(); void prepareDestroy();
QList<Server_ProtocolHandler *> clients; QList<Server_ProtocolHandler *> clients;
@ -54,7 +56,7 @@ protected:
virtual void endSession(int sessionId) = 0; virtual void endSession(int sessionId) = 0;
virtual bool userExists(const QString &user) = 0; virtual bool userExists(const QString &user) = 0;
virtual AuthenticationResult checkUserPassword(Server_ProtocolHandler *handler, const QString &user, const QString &password) = 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 getUsersCount() const;
int getGamesCount() const; int getGamesCount() const;
int nextGameId; int nextGameId;

View file

@ -26,7 +26,7 @@
#include "server_game.h" #include "server_game.h"
#include "pb/command_move_card.pb.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) : 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); QMutexLocker locker(&player->getGame()->gameMutex);
if (type != HiddenZone) { if (type != ServerInfo_Zone::HiddenZone) {
QListIterator<Server_Card *> CardIterator(cards); QListIterator<Server_Card *> CardIterator(cards);
int i = 0; int i = 0;
while (CardIterator.hasNext()) { while (CardIterator.hasNext()) {
@ -160,7 +160,7 @@ bool Server_CardZone::isColumnEmpty(int x, int y) const
return !coordMap.contains((x / 3) * 3); return !coordMap.contains((x / 3) * 3);
} }
void Server_CardZone::moveCard(BlaContainer *bla, QMap<int, Server_Card *> &coordMap, Server_Card *card, int x, int y) void Server_CardZone::moveCard(GameEventStorage &ges, QMap<int, Server_Card *> &coordMap, Server_Card *card, int x, int y)
{ {
QMutexLocker locker(&player->getGame()->gameMutex); QMutexLocker locker(&player->getGame()->gameMutex);
@ -168,13 +168,13 @@ void Server_CardZone::moveCard(BlaContainer *bla, QMap<int, Server_Card *> &coor
CardToMove *cardToMove = new CardToMove; CardToMove *cardToMove = new CardToMove;
cardToMove->set_card_id(card->getId()); cardToMove->set_card_id(card->getId());
player->moveCard(bla, this, QList<const CardToMove *>() << cardToMove, this, x, y, card->getFaceDown(), false); player->moveCard(ges, this, QList<const CardToMove *>() << cardToMove, this, x, y, card->getFaceDown(), false);
delete cardToMove; delete cardToMove;
coordMap.insert(y * 10000 + x, card); coordMap.insert(y * 10000 + x, card);
} }
void Server_CardZone::fixFreeSpaces(BlaContainer *bla) void Server_CardZone::fixFreeSpaces(GameEventStorage &ges)
{ {
QMutexLocker locker(&player->getGame()->gameMutex); 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)) {
if (coordMap.contains(y * 10000 + baseX + 1)) 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)) { 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; continue;
} else } else
continue; continue;
} }
if (!coordMap.contains(y * 10000 + baseX + 1) && coordMap.contains(y * 10000 + baseX + 2)) 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);
} }
} }

View file

@ -22,6 +22,7 @@
#include <QList> #include <QList>
#include <QString> #include <QString>
#include <QMap>
#include "pb/serverinfo_zone.pb.h" #include "pb/serverinfo_zone.pb.h"
class Server_Card; class Server_Card;

View file

@ -25,11 +25,26 @@
#include "server_card.h" #include "server_card.h"
#include "server_cardzone.h" #include "server_cardzone.h"
#include "server_counter.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 <google/protobuf/descriptor.h>
#include "protocol.h"
#include <QTimer> #include <QTimer>
#include <QDebug> #include <QDebug>
Server_Game::Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList<int> &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *_room) Server_Game::Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList<int> &_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); connect(this, SIGNAL(sigStartGameIfReady()), this, SLOT(doStartGameIfReady()), Qt::QueuedConnection);
@ -47,7 +62,7 @@ Server_Game::~Server_Game()
QMutexLocker roomLocker(&room->roomMutex); QMutexLocker roomLocker(&room->roomMutex);
QMutexLocker locker(&gameMutex); QMutexLocker locker(&gameMutex);
sendGameEvent(new Event_GameClosed); sendGameEventContainer(prepareGameEvent(Event_GameClosed(), -1));
QMapIterator<int, Server_Player *> playerIterator(players); QMapIterator<int, Server_Player *> playerIterator(players);
while (playerIterator.hasNext()) while (playerIterator.hasNext())
@ -56,13 +71,16 @@ Server_Game::~Server_Game()
room->removeGame(this); room->removeGame(this);
delete creatorInfo; delete creatorInfo;
creatorInfo = 0;
qDebug() << "Server_Game destructor: gameId=" << gameId; qDebug() << "Server_Game destructor: gameId=" << gameId;
} }
void Server_Game::pingClockTimeout() void Server_Game::pingClockTimeout()
{ {
QMutexLocker locker(&gameMutex); QMutexLocker locker(&gameMutex);
++secondsElapsed;
Event_Ping event;
event.set_seconds_elapsed(++secondsElapsed);
QList<ServerInfo_PlayerPing *> pingList; QList<ServerInfo_PlayerPing *> pingList;
QMapIterator<int, Server_Player *> playerIterator(players); QMapIterator<int, Server_Player *> playerIterator(players);
@ -79,9 +97,12 @@ void Server_Game::pingClockTimeout()
allPlayersInactive = false; allPlayersInactive = false;
} else } else
pingTime = -1; 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(); const int maxTime = room->getServer()->getMaxGameInactivityTime();
if (allPlayersInactive) { if (allPlayersInactive) {
@ -144,7 +165,15 @@ void Server_Game::doStartGameIfReady()
playerIterator.toFront(); playerIterator.toFront();
while (playerIterator.hasNext()) { while (playerIterator.hasNext()) {
Server_Player *player = playerIterator.next().value(); 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<ServerInfo_Player> gameStateIterator(getGameState(player));
while (gameStateIterator.hasNext())
event.add_player_list()->CopyFrom(gameStateIterator.next());
player->sendGameEvent(prepareGameEvent(event, -1));
} }
/* QSqlQuery query; /* QSqlQuery query;
@ -200,31 +229,37 @@ void Server_Game::stopGameIfFinished()
playerIterator.toFront(); playerIterator.toFront();
while (playerIterator.hasNext()) { while (playerIterator.hasNext()) {
Server_Player *player = playerIterator.next().value(); 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<ServerInfo_Player> 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)) if ((_password != password) && !(spectator && !spectatorsNeedPassword))
return RespWrongPassword; return Response::RespWrongPassword;
if (!(user->getUserLevel() & ServerInfo_User::IsRegistered) && onlyRegistered) if (!(user->user_level() & ServerInfo_User::IsRegistered) && onlyRegistered)
return RespUserLevelTooLow; return Response::RespUserLevelTooLow;
if (onlyBuddies) if (onlyBuddies)
if (!room->getServer()->getBuddyList(creatorInfo->getName()).contains(user->getName())) if (!room->getServer()->isInBuddyList(QString::fromStdString(creatorInfo->name()), QString::fromStdString(user->name())))
return RespOnlyBuddies; return Response::RespOnlyBuddies;
if (room->getServer()->getIgnoreList(creatorInfo->getName()).contains(user->getName())) if (room->getServer()->isInIgnoreList(QString::fromStdString(creatorInfo->name()), QString::fromStdString(user->name())))
return RespInIgnoreList; return Response::RespInIgnoreList;
if (spectator) { if (spectator) {
if (!spectatorsAllowed) if (!spectatorsAllowed)
return RespSpectatorsNotAllowed; return Response::RespSpectatorsNotAllowed;
} }
} }
if (!spectator && (gameStarted || (getPlayerCount() >= getMaxPlayers()))) if (!spectator && (gameStarted || (getPlayerCount() >= getMaxPlayers())))
return RespGameFull; return Response::RespGameFull;
return RespOk; return Response::RespOk;
} }
bool Server_Game::containsUser(const QString &userName) const bool Server_Game::containsUser(const QString &userName) const
@ -233,7 +268,7 @@ bool Server_Game::containsUser(const QString &userName) const
QMapIterator<int, Server_Player *> playerIterator(players); QMapIterator<int, Server_Player *> playerIterator(players);
while (playerIterator.hasNext()) while (playerIterator.hasNext())
if (playerIterator.next().value()->getUserInfo()->getName() == userName) if (playerIterator.next().value()->getUserInfo()->name() == userName.toStdString())
return true; return true;
return false; return false;
} }
@ -245,13 +280,17 @@ Server_Player *Server_Game::addPlayer(Server_ProtocolHandler *handler, bool spec
const QList<int> &keyList = players.keys(); const QList<int> &keyList = players.keys();
int playerId = keyList.isEmpty() ? 0 : (keyList.last() + 1); 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()); 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); players.insert(playerId, newPlayer);
if (newPlayer->getUserInfo()->getName() == creatorInfo->getName()) { if (newPlayer->getUserInfo()->name() == creatorInfo->name()) {
hostId = playerId; hostId = playerId;
sendGameEvent(new Event_GameHostChanged(playerId)); sendGameEventContainer(prepareGameEvent(Event_GameHostChanged(), playerId));
} }
if (broadcastUpdate) if (broadcastUpdate)
@ -268,7 +307,7 @@ void Server_Game::removePlayer(Server_Player *player)
players.remove(player->getPlayerId()); players.remove(player->getPlayerId());
removeArrowsToPlayer(player); removeArrowsToPlayer(player);
sendGameEvent(new Event_Leave(player->getPlayerId())); sendGameEventContainer(prepareGameEvent(Event_Leave(), player->getPlayerId()));
bool playerActive = activePlayer == player->getPlayerId(); bool playerActive = activePlayer == player->getPlayerId();
bool playerHost = hostId == player->getPlayerId(); bool playerHost = hostId == player->getPlayerId();
bool spectator = player->getSpectator(); bool spectator = player->getSpectator();
@ -289,7 +328,7 @@ void Server_Game::removePlayer(Server_Player *player)
} }
if (newHostId != -1) { if (newHostId != -1) {
hostId = newHostId; hostId = newHostId;
sendGameEvent(new Event_GameHostChanged(hostId)); sendGameEventContainer(prepareGameEvent(Event_GameHostChanged(), hostId));
} }
} }
stopGameIfFinished(); stopGameIfFinished();
@ -319,7 +358,10 @@ void Server_Game::removeArrowsToPlayer(Server_Player *player)
toDelete.append(a); toDelete.append(a);
} }
for (int i = 0; i < toDelete.size(); ++i) { 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()); p->deleteArrow(toDelete[i]->getId());
} }
} }
@ -334,7 +376,8 @@ bool Server_Game::kickPlayer(int playerId)
if (!playerToKick) if (!playerToKick)
return false; return false;
sendGameEventToPlayer(playerToKick, new Event_Kicked); playerToKick->sendGameEvent(prepareGameEvent(Event_Kicked(), -1));
removePlayer(playerToKick); removePlayer(playerToKick);
return true; return true;
@ -345,7 +388,11 @@ void Server_Game::setActivePlayer(int _activePlayer)
QMutexLocker locker(&gameMutex); QMutexLocker locker(&gameMutex);
activePlayer = _activePlayer; activePlayer = _activePlayer;
sendGameEvent(new Event_SetActivePlayer(activePlayer, activePlayer));
Event_SetActivePlayer event;
event.set_active_player_id(activePlayer);
sendGameEventContainer(prepareGameEvent(event, -1));
setActivePhase(0); setActivePhase(0);
} }
@ -359,13 +406,20 @@ void Server_Game::setActivePhase(int _activePhase)
QList<Server_Arrow *> toDelete = player->getArrows().values(); QList<Server_Arrow *> toDelete = player->getArrows().values();
for (int i = 0; i < toDelete.size(); ++i) { for (int i = 0; i < toDelete.size(); ++i) {
Server_Arrow *a = toDelete[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()); player->deleteArrow(a->getId());
} }
} }
activePhase = _activePhase; activePhase = _activePhase;
sendGameEvent(new Event_SetActivePhase(-1, activePhase));
Event_SetActivePhase event;
event.set_phase(activePhase);
sendGameEventContainer(prepareGameEvent(event, -1));
} }
void Server_Game::nextTurn() void Server_Game::nextTurn()
@ -389,163 +443,161 @@ void Server_Game::postConnectionStatusUpdate(Server_Player *player, bool connect
{ {
QMutexLocker locker(&gameMutex); QMutexLocker locker(&gameMutex);
sendGameEvent(new Event_ConnectionStateChanged(player->getPlayerId(), connectionStatus)); Event_ConnectionStateChanged event;
event.set_connected(connectionStatus);
sendGameEventContainer(prepareGameEvent(event, player->getPlayerId()));
} }
QList<ServerInfo_Player *> Server_Game::getGameState(Server_Player *playerWhosAsking) const QList<ServerInfo_Player> Server_Game::getGameState(Server_Player *playerWhosAsking) const
{ {
QMutexLocker locker(&gameMutex); QMutexLocker locker(&gameMutex);
QList<ServerInfo_Player *> result; QList<ServerInfo_Player> result;
QMapIterator<int, Server_Player *> playerIterator(players); QMapIterator<int, Server_Player *> playerIterator(players);
while (playerIterator.hasNext()) { while (playerIterator.hasNext()) {
Server_Player *player = playerIterator.next().value(); 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<ServerInfo_Arrow *> arrowList; QList<ServerInfo_Arrow *> arrowList;
QMapIterator<int, Server_Arrow *> arrowIterator(player->getArrows()); QMapIterator<int, Server_Arrow *> arrowIterator(player->getArrows());
while (arrowIterator.hasNext()) { while (arrowIterator.hasNext()) {
Server_Arrow *arrow = arrowIterator.next().value(); Server_Arrow *arrow = arrowIterator.next().value();
Server_Card *targetCard = qobject_cast<Server_Card *>(arrow->getTargetItem()); Server_Card *targetCard = qobject_cast<Server_Card *>(arrow->getTargetItem());
if (targetCard) ServerInfo_Arrow *arrowInfo = playerInfo.add_arrow_list();
arrowList.append(new ServerInfo_Arrow( arrowInfo->set_id(arrow->getId());
arrow->getId(), arrowInfo->set_start_player_id(arrow->getStartCard()->getZone()->getPlayer()->getPlayerId());
arrow->getStartCard()->getZone()->getPlayer()->getPlayerId(), arrowInfo->set_start_zone(arrow->getStartCard()->getZone()->getName().toStdString());
arrow->getStartCard()->getZone()->getName(), arrowInfo->set_start_card_id(arrow->getStartCard()->getId());
arrow->getStartCard()->getId(), arrowInfo->mutable_arrow_color()->CopyFrom(arrow->getColor().get_color());
targetCard->getZone()->getPlayer()->getPlayerId(), if (targetCard) {
targetCard->getZone()->getName(), arrowInfo->set_target_player_id(targetCard->getZone()->getPlayer()->getPlayerId());
targetCard->getId(), arrowInfo->set_target_zone(targetCard->getZone()->getName().toStdString());
arrow->getColor() arrowInfo->set_target_card_id(targetCard->getId());
)); } else
else arrowInfo->set_target_player_id(qobject_cast<Server_Player *>(arrow->getTargetItem())->getPlayerId());
arrowList.append(new ServerInfo_Arrow(
arrow->getId(),
arrow->getStartCard()->getZone()->getPlayer()->getPlayerId(),
arrow->getStartCard()->getZone()->getName(),
arrow->getStartCard()->getId(),
qobject_cast<Server_Player *>(arrow->getTargetItem())->getPlayerId(),
QString(),
-1,
arrow->getColor()
));
} }
QList<ServerInfo_Counter *> counterList;
QMapIterator<int, Server_Counter *> counterIterator(player->getCounters()); QMapIterator<int, Server_Counter *> counterIterator(player->getCounters());
while (counterIterator.hasNext()) { while (counterIterator.hasNext()) {
Server_Counter *counter = counterIterator.next().value(); 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<ServerInfo_Zone *> zoneList; QList<ServerInfo_Zone *> zoneList;
QMapIterator<QString, Server_CardZone *> zoneIterator(player->getZones()); QMapIterator<QString, Server_CardZone *> zoneIterator(player->getZones());
while (zoneIterator.hasNext()) { while (zoneIterator.hasNext()) {
Server_CardZone *zone = zoneIterator.next().value(); Server_CardZone *zone = zoneIterator.next().value();
QList<ServerInfo_Card *> 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 ( if (
(((playerWhosAsking == player) || (playerWhosAsking->getSpectator() && spectatorsSeeEverything)) && (zone->getType() != HiddenZone)) (((playerWhosAsking == player) || (playerWhosAsking->getSpectator() && spectatorsSeeEverything)) && (zone->getType() != ServerInfo_Zone::HiddenZone))
|| ((playerWhosAsking != player) && (zone->getType() == PublicZone)) || ((playerWhosAsking != player) && (zone->getType() == ServerInfo_Zone::PublicZone))
) { ) {
QListIterator<Server_Card *> cardIterator(zone->cards); QListIterator<Server_Card *> cardIterator(zone->cards);
while (cardIterator.hasNext()) { while (cardIterator.hasNext()) {
Server_Card *card = cardIterator.next(); Server_Card *card = cardIterator.next();
ServerInfo_Card *cardInfo = zoneInfo->add_card_list();
QString displayedName = card->getFaceDown() ? QString() : card->getName(); 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<ServerInfo_CardCounter *> cardCounterList; QList<ServerInfo_CardCounter *> cardCounterList;
QMapIterator<int, int> cardCounterIterator(card->getCounters()); QMapIterator<int, int> cardCounterIterator(card->getCounters());
while (cardCounterIterator.hasNext()) { while (cardCounterIterator.hasNext()) {
cardCounterIterator.next(); 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()) { if (card->getParentCard()) {
attachPlayerId = card->getParentCard()->getZone()->getPlayer()->getPlayerId(); cardInfo->set_attach_player_id(card->getParentCard()->getZone()->getPlayer()->getPlayerId());
attachZone = card->getParentCard()->getZone()->getName(); cardInfo->set_attach_zone(card->getParentCard()->getZone()->getName().toStdString());
attachCardId = card->getParentCard()->getId(); 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; return result;
} }
void Server_Game::sendGameEvent(GameEvent *event, GameEventContext *context, Server_Player *exclude) void Server_Game::sendGameEventContainer(GameEventContainer *cont, GameEventStorageItem::EventRecipients recipients, int privatePlayerId)
{
sendGameEventContainer(new GameEventContainer(QList<GameEvent *>() << event, -1, context), exclude);
}
void Server_Game::sendGameEventContainer(GameEventContainer *cont, Server_Player *exclude, bool excludeOmniscient)
{ {
QMutexLocker locker(&gameMutex); QMutexLocker locker(&gameMutex);
cont->setGameId(gameId); cont->set_game_id(gameId);
QMapIterator<int, Server_Player *> playerIterator(players); QMapIterator<int, Server_Player *> playerIterator(players);
while (playerIterator.hasNext()) { while (playerIterator.hasNext()) {
Server_Player *p = playerIterator.next().value(); Server_Player *p = playerIterator.next().value();
if ((p != exclude) && !(excludeOmniscient && p->getSpectator() && spectatorsSeeEverything)) const bool playerPrivate = (p->getPlayerId() == privatePlayerId) || (p->getSpectator() && spectatorsSeeEverything);
p->sendProtocolItem(cont, false); if ((recipients.testFlag(GameEventStorageItem::SendToPrivate) && playerPrivate) || (recipients.testFlag(GameEventStorageItem::SendToOthers) && !playerPrivate))
} p->sendGameEvent(cont);
delete cont;
}
void Server_Game::sendGameEventContainerOmniscient(GameEventContainer *cont, Server_Player *exclude)
{
QMutexLocker locker(&gameMutex);
cont->setGameId(gameId);
QMapIterator<int, Server_Player *> playerIterator(players);
while (playerIterator.hasNext()) {
Server_Player *p = playerIterator.next().value();
if ((p != exclude) && (p->getSpectator() && spectatorsSeeEverything))
p->sendProtocolItem(cont, false);
} }
delete 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<GameEvent *>() << 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); QMutexLocker locker(&gameMutex);
if (players.isEmpty()) ServerInfo_Game result;
// Game is closing result.set_room_id(room->getId());
return new ServerInfo_Game(room->getId(), getGameId(), QString(), false, 0, getMaxPlayers(), false, QList<GameTypeId *>(), 0, false, 0); result.set_game_id(getGameId());
else { result.set_max_players(getMaxPlayers());
// Game is open if (!players.isEmpty()) {
QList<GameTypeId *> gameTypeList;
for (int i = 0; i < gameTypes.size(); ++i) for (int i = 0; i < gameTypes.size(); ++i)
gameTypeList.append(new GameTypeId(gameTypes[i])); result.add_game_types(gameTypes[i]);
return new ServerInfo_Game( result.set_description(getDescription().toStdString());
room->getId(), result.set_with_password(!getPassword().isEmpty());
getGameId(), result.set_player_count(getPlayerCount());
getDescription(), result.set_started(gameStarted);
!getPassword().isEmpty(), result.mutable_creator_info()->CopyFrom(*getCreatorInfo());
getPlayerCount(), result.set_only_buddies(onlyBuddies);
getMaxPlayers(), result.set_only_registered(onlyRegistered);
gameStarted, result.set_spectators_allowed(getSpectatorsAllowed());
gameTypeList, result.set_spectators_need_password(getSpectatorsNeedPassword());
new ServerInfo_User(getCreatorInfo(), false), result.set_spectators_count(getSpectatorCount());
onlyBuddies,
onlyRegistered,
getSpectatorsAllowed(),
getSpectatorsNeedPassword(),
getSpectatorCount()
);
} }
return result;
} }

View file

@ -28,6 +28,7 @@
#include "protocol.h" #include "protocol.h"
#include "pb/response.pb.h" #include "pb/response.pb.h"
#include "pb/serverinfo_player.pb.h" #include "pb/serverinfo_player.pb.h"
#include "pb/serverinfo_game.pb.h"
class QTimer; class QTimer;
class GameEventContainer; class GameEventContainer;
@ -65,7 +66,7 @@ public:
mutable QMutex gameMutex; mutable QMutex gameMutex;
Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList<int> &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *parent); Server_Game(Server_ProtocolHandler *_creator, int _gameId, const QString &_description, const QString &_password, int _maxPlayers, const QList<int> &_gameTypes, bool _onlyBuddies, bool _onlyRegistered, bool _spectatorsAllowed, bool _spectatorsNeedPassword, bool _spectatorsCanTalk, bool _spectatorsSeeEverything, Server_Room *parent);
~Server_Game(); ~Server_Game();
ServerInfo_Game *getInfo() const; ServerInfo_Game getInfo() const;
int getHostId() const { return hostId; } int getHostId() const { return hostId; }
ServerInfo_User *getCreatorInfo() const { return creatorInfo; } ServerInfo_User *getCreatorInfo() const { return creatorInfo; }
bool getGameStarted() const { return gameStarted; } bool getGameStarted() const { return gameStarted; }
@ -98,14 +99,10 @@ public:
QList<ServerInfo_Player> getGameState(Server_Player *playerWhosAsking) const; QList<ServerInfo_Player> getGameState(Server_Player *playerWhosAsking) const;
GameEventContainer *prepareGameEvent(const ::google::protobuf::Message &gameEvent, int playerId); GameEventContainer *prepareGameEvent(const ::google::protobuf::Message &gameEvent, int playerId, GameEventContext *context = 0);
GameEventContainer *prepareGameEvent(const ::google::protobuf::Message &gameEvent, int playerId, const GameEventContext &context);
GameEventContext prepareGameEventContext(const ::google::protobuf::Message &gameEventContext); GameEventContext prepareGameEventContext(const ::google::protobuf::Message &gameEventContext);
// void sendGameEvent(GameEvent *event, GameEventContext *context = 0, Server_Player *exclude = 0); void sendGameEventContainer(GameEventContainer *cont, GameEventStorageItem::EventRecipients recipients = GameEventStorageItem::SendToPrivate | GameEventStorageItem::SendToOthers, int privatePlayerId = -1);
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);
}; };
#endif #endif

View file

@ -6,12 +6,19 @@
#include "server_game.h" #include "server_game.h"
#include "server_protocolhandler.h" #include "server_protocolhandler.h"
#include "protocol.h" #include "protocol.h"
#include "protocol_items.h"
#include "decklist.h" #include "decklist.h"
#include "pb/response.pb.h"
#include "pb/command_move_card.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 <QDebug> #include <QDebug>
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) : 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(); playerMutex.unlock();
delete userInfo; delete userInfo;
userInfo = 0;
clearZones(); clearZones();
deleteLater(); deleteLater();
} }
void Server_Player::moveToThread(QThread *thread)
{
QObject::moveToThread(thread);
userInfo->moveToThread(thread);
}
int Server_Player::newCardId() int Server_Player::newCardId()
{ {
QMutexLocker locker(&game->gameMutex); QMutexLocker locker(&game->gameMutex);
@ -87,15 +89,15 @@ void Server_Player::setupZones()
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// Create zones // 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); 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(sbZone);
addZone(new Server_CardZone(this, "table", true, PublicZone)); addZone(new Server_CardZone(this, "table", true, ServerInfo_Zone::PublicZone));
addZone(new Server_CardZone(this, "hand", false, PrivateZone)); addZone(new Server_CardZone(this, "hand", false, ServerInfo_Zone::PrivateZone));
addZone(new Server_CardZone(this, "stack", false, PublicZone)); addZone(new Server_CardZone(this, "stack", false, ServerInfo_Zone::PublicZone));
addZone(new Server_CardZone(this, "grave", false, PublicZone)); addZone(new Server_CardZone(this, "grave", false, ServerInfo_Zone::PublicZone));
addZone(new Server_CardZone(this, "rfg", false, 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(0, "life", Color(255, 255, 255), 25, 20));
addCounter(new Server_Counter(1, "w", Color(255, 255, 150), 20, 0)); 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); 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) void Server_Player::setDeck(DeckList *_deck)
@ -244,7 +254,7 @@ bool Server_Player::deleteCounter(int counterId)
return true; return true;
} }
ResponseCode Server_Player::drawCards(BlaContainer *bla, int number) Response::ResponseCode Server_Player::drawCards(GameEventStorage &ges, int number)
{ {
QMutexLocker locker(&game->gameMutex); QMutexLocker locker(&game->gameMutex);
@ -252,51 +262,55 @@ ResponseCode Server_Player::drawCards(BlaContainer *bla, int number)
Server_CardZone *handZone = zones.value("hand"); Server_CardZone *handZone = zones.value("hand");
if (deckZone->cards.size() < number) if (deckZone->cards.size() < number)
number = deckZone->cards.size(); number = deckZone->cards.size();
QList<ServerInfo_Card *> cardListPrivate; Event_DrawCards eventOthers;
QList<ServerInfo_Card *> cardListOmniscient; eventOthers.set_number(number);
Event_DrawCards eventPrivate(eventOthers);
for (int i = 0; i < number; ++i) { for (int i = 0; i < number; ++i) {
Server_Card *card = deckZone->cards.takeFirst(); Server_Card *card = deckZone->cards.takeFirst();
handZone->cards.append(card); handZone->cards.append(card);
lastDrawList.append(card->getId()); 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()); ges.enqueueGameEvent(eventPrivate, playerId, GameEventStorageItem::SendToPrivate, playerId);
bla->enqueueGameEventPublic(new Event_DrawCards(playerId, cardListPrivate.size()), game->getGameId()); ges.enqueueGameEvent(eventOthers, playerId, GameEventStorageItem::SendToOthers);
return RespOk; return Response::RespOk;
} }
ResponseCode Server_Player::undoDraw(BlaContainer *bla) Response::ResponseCode Server_Player::undoDraw(GameEventStorage &ges)
{ {
QMutexLocker locker(&game->gameMutex); QMutexLocker locker(&game->gameMutex);
if (lastDrawList.isEmpty()) if (lastDrawList.isEmpty())
return RespContextError; return Response::RespContextError;
ResponseCode retVal; Response::ResponseCode retVal;
CardToMove *cardToMove = new CardToMove; CardToMove *cardToMove = new CardToMove;
cardToMove->set_card_id(lastDrawList.takeLast()); cardToMove->set_card_id(lastDrawList.takeLast());
retVal = moveCard(bla, zones.value("hand"), QList<const CardToMove *>() << cardToMove, zones.value("deck"), 0, 0, false, true); retVal = moveCard(ges, zones.value("hand"), QList<const CardToMove *>() << cardToMove, zones.value("deck"), 0, 0, false, true);
delete cardToMove; delete cardToMove;
return retVal; return retVal;
} }
ResponseCode Server_Player::moveCard(BlaContainer *bla, const QString &_startZone, const QList<const CardToMove *> &_cards, int targetPlayerId, const QString &_targetZone, int x, int y) Response::ResponseCode Server_Player::moveCard(GameEventStorage &ges, const QString &_startZone, const QList<const CardToMove *> &_cards, int targetPlayerId, const QString &_targetZone, int x, int y)
{ {
QMutexLocker locker(&game->gameMutex); QMutexLocker locker(&game->gameMutex);
Server_CardZone *startzone = getZones().value(_startZone); Server_CardZone *startzone = getZones().value(_startZone);
Server_Player *targetPlayer = game->getPlayers().value(targetPlayerId); Server_Player *targetPlayer = game->getPlayers().value(targetPlayerId);
if (!targetPlayer) if (!targetPlayer)
return RespNameNotFound; return Response::RespNameNotFound;
Server_CardZone *targetzone = targetPlayer->getZones().value(_targetZone); Server_CardZone *targetzone = targetPlayer->getZones().value(_targetZone);
if ((!startzone) || (!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 { class Server_Player::MoveCardCompareFunctor {
@ -320,13 +334,13 @@ public:
} }
}; };
ResponseCode Server_Player::moveCard(BlaContainer *bla, Server_CardZone *startzone, const QList<const CardToMove *> &_cards, Server_CardZone *targetzone, int x, int y, bool fixFreeSpaces, bool undoingDraw) Response::ResponseCode Server_Player::moveCard(GameEventStorage &ges, Server_CardZone *startzone, const QList<const CardToMove *> &_cards, Server_CardZone *targetzone, int x, int y, bool fixFreeSpaces, bool undoingDraw)
{ {
QMutexLocker locker(&game->gameMutex); QMutexLocker locker(&game->gameMutex);
// Disallow controller change to other zones than the table. // Disallow controller change to other zones than the table.
if (((targetzone->getType() != PublicZone) || !targetzone->hasCoords()) && (startzone->getPlayer() != targetzone->getPlayer())) if (((targetzone->getType() != ServerInfo_Zone::PublicZone) || !targetzone->hasCoords()) && (startzone->getPlayer() != targetzone->getPlayer()))
return RespContextError; return Response::RespContextError;
if (!targetzone->hasCoords() && (x == -1)) if (!targetzone->hasCoords() && (x == -1))
x = targetzone->cards.size(); x = targetzone->cards.size();
@ -337,9 +351,9 @@ ResponseCode Server_Player::moveCard(BlaContainer *bla, Server_CardZone *startzo
int position; int position;
Server_Card *card = startzone->getCard(_cards[i]->card_id(), &position); Server_Card *card = startzone->getCard(_cards[i]->card_id(), &position);
if (!card) if (!card)
return RespNameNotFound; return Response::RespNameNotFound;
if (!card->getAttachedCards().isEmpty() && !targetzone->isColumnEmpty(x, y)) if (!card->getAttachedCards().isEmpty() && !targetzone->isColumnEmpty(x, y))
return RespContextError; return Response::RespContextError;
cardsToMove.append(QPair<Server_Card *, int>(card, position)); cardsToMove.append(QPair<Server_Card *, int>(card, position));
cardProperties.insert(card, _cards[i]); 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 // Make a copy of the list because the original one gets modified during the loop
QList<Server_Card *> attachedCards = card->getAttachedCards(); QList<Server_Card *> attachedCards = card->getAttachedCards();
for (int i = 0; i < attachedCards.size(); ++i) 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) { if (startzone != targetzone) {
@ -402,9 +416,12 @@ ResponseCode Server_Player::moveCard(BlaContainer *bla, Server_CardZone *startzo
} }
if (card->getDestroyOnZoneChange() && (startzone->getName() != targetzone->getName())) { if (card->getDestroyOnZoneChange() && (startzone->getName() != targetzone->getName())) {
bla->enqueueGameEventPrivate(new Event_DestroyCard(getPlayerId(), startzone->getName(), card->getId()), game->getGameId(), -1, new Context_MoveCard); Event_DestroyCard event;
bla->enqueueGameEventOmniscient(new Event_DestroyCard(getPlayerId(), startzone->getName(), card->getId()), game->getGameId(), new Context_MoveCard); event.set_zone_name(startzone->getName().toStdString());
bla->enqueueGameEventPublic(new Event_DestroyCard(getPlayerId(), startzone->getName(), card->getId()), game->getGameId(), new Context_MoveCard); event.set_card_id(card->getId());
ges.setGameEventContext(new Context_MoveCard);
ges.enqueueGameEvent(event, playerId);
card->deleteLater(); card->deleteLater();
} else { } else {
if (!targetzone->hasCoords()) { if (!targetzone->hasCoords()) {
@ -415,13 +432,13 @@ ResponseCode Server_Player::moveCard(BlaContainer *bla, Server_CardZone *startzo
targetzone->insertCard(card, newX, y); targetzone->insertCard(card, newX, y);
bool targetBeingLookedAt = (targetzone->getType() != HiddenZone) || (targetzone->getCardsBeingLookedAt() > newX) || (targetzone->getCardsBeingLookedAt() == -1); bool targetBeingLookedAt = (targetzone->getType() != ServerInfo_Zone::HiddenZone) || (targetzone->getCardsBeingLookedAt() > newX) || (targetzone->getCardsBeingLookedAt() == -1);
bool sourceBeingLookedAt = (startzone->getType() != HiddenZone) || (startzone->getCardsBeingLookedAt() > position) || (startzone->getCardsBeingLookedAt() == -1); bool sourceBeingLookedAt = (startzone->getType() != ServerInfo_Zone::HiddenZone) || (startzone->getCardsBeingLookedAt() > position) || (startzone->getCardsBeingLookedAt() == -1);
bool targetHiddenToPlayer = thisCardProperties->face_down() || !targetBeingLookedAt; 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 sourceHiddenToPlayer = card->getFaceDown() || !sourceBeingLookedAt;
bool sourceHiddenToOthers = card->getFaceDown() || (startzone->getType() != PublicZone); bool sourceHiddenToOthers = card->getFaceDown() || (startzone->getType() != ServerInfo_Zone::PublicZone);
QString privateCardName, publicCardName; QString privateCardName, publicCardName;
if (!(sourceHiddenToPlayer && targetHiddenToPlayer)) if (!(sourceHiddenToPlayer && targetHiddenToPlayer))
@ -444,65 +461,85 @@ ResponseCode Server_Player::moveCard(BlaContainer *bla, Server_CardZone *startzo
privateCardName = QString(); privateCardName = QString();
} }
int privatePosition = -1; int privatePosition = -1;
if (startzone->getType() == HiddenZone) if (startzone->getType() == ServerInfo_Zone::HiddenZone)
privatePosition = position; 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<GameEventContext *>(new Context_UndoDraw) : static_cast<GameEventContext *>(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<GameEventContext *>(new Context_UndoDraw) : static_cast<GameEventContext *>(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 // 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, // part of the zone is being looked at. The information is not needed anyway because in hidden zones,
// all cards are equal. // all cards are equal.
if ( if (
((startzone->getType() == HiddenZone) && ((startzone->getCardsBeingLookedAt() > position) || (startzone->getCardsBeingLookedAt() == -1))) ((startzone->getType() == ServerInfo_Zone::HiddenZone) && ((startzone->getCardsBeingLookedAt() > position) || (startzone->getCardsBeingLookedAt() == -1)))
|| (startzone->getType() == PublicZone) || (startzone->getType() == ServerInfo_Zone::PublicZone)
) )
position = -1; 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; newX = -1;
if ((startzone->getType() == PublicZone) || (targetzone->getType() == PublicZone)) eventOthers.set_position(position);
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<GameEventContext *>(new Context_UndoDraw) : static_cast<GameEventContext *>(new Context_MoveCard)); if ((startzone->getType() == ServerInfo_Zone::PublicZone) || (targetzone->getType() == ServerInfo_Zone::PublicZone)) {
else eventOthers.set_card_id(oldCardId);
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<GameEventContext *>(new Context_UndoDraw) : static_cast<GameEventContext *>(new Context_MoveCard)); 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()) 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()); QString ptString = QString::fromStdString(thisCardProperties->pt());
if (!ptString.isEmpty() && !thisCardProperties->face_down()) 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) 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); QMutexLocker locker(&game->gameMutex);
Server_CardZone *zone = card->getZone(); Server_CardZone *zone = card->getZone();
card->setParentCard(0); 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 *cardToMove = new CardToMove;
cardToMove->set_card_id(card->getId()); cardToMove->set_card_id(card->getId());
moveCard(bla, zone, QList<const CardToMove *>() << cardToMove, zone, -1, card->getY(), card->getFaceDown()); moveCard(ges, zone, QList<const CardToMove *>() << cardToMove, zone, -1, card->getY(), card->getFaceDown());
delete cardToMove; 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); QMutexLocker locker(&game->gameMutex);
Server_CardZone *zone = getZones().value(zoneName); Server_CardZone *zone = getZones().value(zoneName);
if (!zone) if (!zone)
return RespNameNotFound; return Response::RespNameNotFound;
if (!zone->hasCoords()) if (!zone->hasCoords())
return RespContextError; return Response::RespContextError;
QString result; QString result;
if (cardId == -1) { if (cardId == -1) {
@ -510,26 +547,31 @@ ResponseCode Server_Player::setCardAttrHelper(BlaContainer *bla, const QString &
while (CardIterator.hasNext()) { while (CardIterator.hasNext()) {
result = CardIterator.next()->setAttribute(attrName, attrValue, true); result = CardIterator.next()->setAttribute(attrName, attrValue, true);
if (result.isNull()) if (result.isNull())
return RespInvalidCommand; return Response::RespInvalidCommand;
} }
} else { } else {
Server_Card *card = zone->getCard(cardId); Server_Card *card = zone->getCard(cardId);
if (!card) if (!card)
return RespNameNotFound; return Response::RespNameNotFound;
result = card->setAttribute(attrName, attrValue, false); result = card->setAttribute(attrName, attrValue, false);
if (result.isNull()) 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()); Event_SetCardAttr event;
bla->enqueueGameEventOmniscient(new Event_SetCardAttr(getPlayerId(), zone->getName(), cardId, attrName, result), game->getGameId()); event.set_zone_name(zone->getName().toStdString());
return RespOk; 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); QMutexLocker locker(&playerMutex);
if (handler) if (handler)
handler->sendProtocolItem(item, deleteItem); handler->sendProtocolItem(*cont);
} }

View file

@ -7,6 +7,8 @@
#include <QMap> #include <QMap>
#include <QMutex> #include <QMutex>
#include "pb/response.pb.h"
class DeckList; class DeckList;
class Server_Game; class Server_Game;
class Server_CardZone; class Server_CardZone;
@ -14,11 +16,11 @@ class Server_Counter;
class Server_Arrow; class Server_Arrow;
class Server_Card; class Server_Card;
class Server_ProtocolHandler; class Server_ProtocolHandler;
class ProtocolItem;
class ServerInfo_User; class ServerInfo_User;
class ServerInfo_PlayerProperties; class ServerInfo_PlayerProperties;
class CommandContainer; class CommandContainer;
class CardToMove; class CardToMove;
class GameEventContainer;
class GameEventStorage; class GameEventStorage;
class Server_Player : public Server_ArrowTarget { class Server_Player : public Server_ArrowTarget {
@ -41,10 +43,9 @@ private:
bool readyStart; bool readyStart;
bool conceded; bool conceded;
public: 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(); ~Server_Player();
void prepareDestroy(); void prepareDestroy();
void moveToThread(QThread *thread);
Server_ProtocolHandler *getProtocolHandler() const { return handler; } Server_ProtocolHandler *getProtocolHandler() const { return handler; }
void setProtocolHandler(Server_ProtocolHandler *_handler) { playerMutex.lock(); handler = _handler; playerMutex.unlock(); } void setProtocolHandler(Server_ProtocolHandler *_handler) { playerMutex.lock(); handler = _handler; playerMutex.unlock(); }
@ -87,7 +88,7 @@ public:
void unattachCard(GameEventStorage &ges, Server_Card *card); void unattachCard(GameEventStorage &ges, Server_Card *card);
Response::ResponseCode setCardAttrHelper(GameEventStorage &ges, const QString &zone, int cardId, const QString &attrName, const QString &attrValue); 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 #endif

View file

@ -77,6 +77,7 @@
#include "pb/event_set_counter.pb.h" #include "pb/event_set_counter.pb.h"
#include "pb/event_dump_zone.pb.h" #include "pb/event_dump_zone.pb.h"
#include "pb/event_stop_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_deck_select.pb.h"
#include "pb/context_concede.pb.h" #include "pb/context_concede.pb.h"
#include "pb/context_ready_start.pb.h" #include "pb/context_ready_start.pb.h"
@ -124,12 +125,25 @@ void Server_ProtocolHandler::prepareDestroy()
gameListMutex.unlock(); gameListMutex.unlock();
delete userInfo; delete userInfo;
QMapIterator<QString, ServerInfo_User *> i(buddyList); }
while (i.hasNext())
delete i.next().value(); void Server_ProtocolHandler::setUserInfo(const ServerInfo_User &_userInfo)
QMapIterator<QString, ServerInfo_User *> j(ignoreList); {
while (j.hasNext()) userInfo = new ServerInfo_User;
delete j.next().value(); 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) 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 Server_ProtocolHandler::processSessionCommandContainer(const CommandContainer &cont, ResponseContainer &rc)
{ {
Response::ResponseCode finalResponseCode = Response::RespOk; 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 // XXX stimmt so nicht, beim alten Kopierkonstruktor wurde hier "true" übergeben
re->mutable_user_info()->CopyFrom(*userInfo); re->mutable_user_info()->CopyFrom(*userInfo);
QList<ServerInfo_User *> _buddyList, _ignoreList;
if (authState == PasswordRight) { if (authState == PasswordRight) {
buddyList = server->getBuddyList(userName); QMapIterator<QString, ServerInfo_User> buddyIterator(server->getBuddyList(userName));
QMapIterator<QString, ServerInfo_User *> buddyIterator(buddyList);
while (buddyIterator.hasNext()) while (buddyIterator.hasNext())
re->add_buddy_list()->CopyFrom(*buddyIterator.next().value()); re->add_buddy_list()->CopyFrom(buddyIterator.next().value());
ignoreList = server->getIgnoreList(userName); QMapIterator<QString, ServerInfo_User> ignoreIterator(server->getIgnoreList(userName));
QMapIterator<QString, ServerInfo_User *> ignoreIterator(ignoreList);
while (ignoreIterator.hasNext()) while (ignoreIterator.hasNext())
re->add_ignore_list()->CopyFrom(*ignoreIterator.next().value()); re->add_ignore_list()->CopyFrom(ignoreIterator.next().value());
} }
server->serverMutex.lock(); server->serverMutex.lock();
@ -573,7 +589,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdMessage(const Command_Message
Server_ProtocolHandler *userHandler = server->getUsers().value(receiver); Server_ProtocolHandler *userHandler = server->getUsers().value(receiver);
if (!userHandler) if (!userHandler)
return Response::RespNameNotFound; return Response::RespNameNotFound;
if (userHandler->getIgnoreList().contains(getUserName())) if (server->isInIgnoreList(receiver, QString::fromStdString(userInfo->name())))
return Response::RespInIgnoreList; return Response::RespInIgnoreList;
Event_UserMessage event; Event_UserMessage event;
@ -856,7 +872,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdDeckSelect(const Command_DeckS
Event_PlayerPropertiesChanged event; Event_PlayerPropertiesChanged event;
event.mutable_player_properties()->CopyFrom(player->getProperties()); event.mutable_player_properties()->CopyFrom(player->getProperties());
ges.enqueueGameEventPublic(event, player->getPlayerId()); ges.enqueueGameEvent(event, player->getPlayerId());
Context_DeckSelect *context = new Context_DeckSelect; Context_DeckSelect *context = new Context_DeckSelect;
context->set_deck_hash(deck->getDeckHash().toStdString()); context->set_deck_hash(deck->getDeckHash().toStdString());
@ -907,7 +923,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdConcede(const Command_Concede
Event_PlayerPropertiesChanged event; Event_PlayerPropertiesChanged event;
event.mutable_player_properties()->CopyFrom(player->getProperties()); event.mutable_player_properties()->CopyFrom(player->getProperties());
ges.enqueueGameEventPublic(event, player->getPlayerId()); ges.enqueueGameEvent(event, player->getPlayerId());
ges.setGameEventContext(new Context_Concede()); ges.setGameEventContext(new Context_Concede());
game->stopGameIfFinished(); game->stopGameIfFinished();
@ -932,7 +948,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdReadyStart(const Command_Ready
Event_PlayerPropertiesChanged event; Event_PlayerPropertiesChanged event;
event.mutable_player_properties()->CopyFrom(player->getProperties()); event.mutable_player_properties()->CopyFrom(player->getProperties());
ges.enqueueGameEventPublic(event, player->getPlayerId()); ges.enqueueGameEvent(event, player->getPlayerId());
ges.setGameEventContext(new Context_ReadyStart()); ges.setGameEventContext(new Context_ReadyStart());
game->startGameIfReady(); game->startGameIfReady();
@ -946,7 +962,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdGameSay(const Command_GameSay
Event_GameSay event; Event_GameSay event;
event.set_message(cmd.message()); event.set_message(cmd.message());
ges.enqueueGameEventPublic(event, player->getPlayerId()); ges.enqueueGameEvent(event, player->getPlayerId());
return Response::RespOk; return Response::RespOk;
} }
@ -963,7 +979,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdShuffle(const Command_Shuffle
player->getZones().value("deck")->shuffle(); player->getZones().value("deck")->shuffle();
ges.enqueueGameEventPublic(Event_Shuffle(), player->getPlayerId()); ges.enqueueGameEvent(Event_Shuffle(), player->getPlayerId());
return Response::RespOk; return Response::RespOk;
} }
@ -1630,7 +1646,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdStopDumpZone(const Command_Sto
return Response::RespOk; 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()) if (player->getSpectator())
return Response::RespFunctionNotAllowed; return Response::RespFunctionNotAllowed;
@ -1664,39 +1680,54 @@ Response::ResponseCode Server_ProtocolHandler::cmdRevealCards(const Command_Reve
cardsToReveal.append(card); 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<ServerInfo_Card *> respCardListPrivate, respCardListOmniscient; QList<ServerInfo_Card *> respCardListPrivate, respCardListOmniscient;
for (int i = 0; i < cardsToReveal.size(); ++i) { for (int i = 0; i < cardsToReveal.size(); ++i) {
Server_Card *card = cardsToReveal[i]; Server_Card *card = cardsToReveal[i];
ServerInfo_Card *cardInfo = eventPrivate.add_cards();
QList<ServerInfo_CardCounter *> 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<ServerInfo_CardCounter *> cardCounterList;
QMapIterator<int, int> cardCounterIterator(card->getCounters()); QMapIterator<int, int> cardCounterIterator(card->getCounters());
while (cardCounterIterator.hasNext()) { while (cardCounterIterator.hasNext()) {
cardCounterIterator.next(); cardCounterIterator.next();
cardCounterListPrivate.append(new ServerInfo_CardCounter(cardCounterIterator.key(), cardCounterIterator.value())); ServerInfo_CardCounter *counterInfo = cardInfo->add_counter_list();
cardCounterListOmniscient.append(new ServerInfo_CardCounter(cardCounterIterator.key(), cardCounterIterator.value())); counterInfo->set_id(cardCounterIterator.key());
counterInfo->set_value(cardCounterIterator.value());
} }
int attachPlayerId = -1;
QString attachZone;
int attachCardId = -1;
if (card->getParentCard()) { if (card->getParentCard()) {
attachPlayerId = card->getParentCard()->getZone()->getPlayer()->getPlayerId(); cardInfo->set_attach_player_id(card->getParentCard()->getZone()->getPlayer()->getPlayerId());
attachZone = card->getParentCard()->getZone()->getName(); cardInfo->set_attach_zone(card->getParentCard()->getZone()->getName().toStdString());
attachCardId = card->getParentCard()->getId(); 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()) if (cmd.has_player_id()) {
bla->enqueueGameEventPublic(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd.card_id(), -1, respCardListOmniscient), game->getGameId()); ges.enqueueGameEvent(eventPrivate, player->getPlayerId(), GameEventStorageItem::SendToPrivate, cmd.player_id());
else { ges.enqueueGameEvent(eventOthers, player->getPlayerId(), GameEventStorageItem::SendToOthers);
bla->enqueueGameEventPublic(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd.card_id(), otherPlayer->getPlayerId()), game->getGameId()); } else
bla->enqueueGameEventPrivate(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd.card_id(), otherPlayer->getPlayerId(), respCardListPrivate), game->getGameId(), otherPlayer->getPlayerId()); ges.enqueueGameEvent(eventPrivate, player->getPlayerId());
bla->enqueueGameEventOmniscient(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd.card_id(), otherPlayer->getPlayerId(), respCardListOmniscient), game->getGameId());
}
return Response::RespOk; return Response::RespOk;
} }

View file

@ -93,10 +93,8 @@ protected:
bool acceptsUserListChanges; bool acceptsUserListChanges;
bool acceptsRoomListChanges; bool acceptsRoomListChanges;
ServerInfo_User *userInfo; ServerInfo_User *userInfo;
QMap<QString, ServerInfo_User *> buddyList, ignoreList;
void prepareDestroy(); void prepareDestroy();
virtual bool getCompressionSupport() const = 0;
int sessionId; int sessionId;
private: private:
QString thisUserName; QString thisUserName;
@ -182,9 +180,7 @@ public:
ServerInfo_User copyUserInfo(bool complete, bool moderatorInfo = false) const; ServerInfo_User copyUserInfo(bool complete, bool moderatorInfo = false) const;
const QString &getUserName() const { return thisUserName; } const QString &getUserName() const { return thisUserName; }
virtual QString getAddress() const = 0; virtual QString getAddress() const = 0;
void setUserInfo(ServerInfo_User *_userInfo) { userInfo = _userInfo; } void setUserInfo(const ServerInfo_User &_userInfo);
const QMap<QString, ServerInfo_User *> &getBuddyList() const { return buddyList; }
const QMap<QString, ServerInfo_User *> &getIgnoreList() const { return ignoreList; }
int getSessionId() const { return sessionId; } int getSessionId() const { return sessionId; }
void setSessionId(int _sessionId) { sessionId = _sessionId; } void setSessionId(int _sessionId) { sessionId = _sessionId; }
@ -197,7 +193,7 @@ public:
void sendProtocolItem(const RoomEvent &item); void sendProtocolItem(const RoomEvent &item);
void sendProtocolItem(ServerMessage::MessageType type, const ::google::protobuf::Message &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 #endif

View file

@ -3,6 +3,12 @@
#include "server_game.h" #include "server_game.h"
#include <QDebug> #include <QDebug>
#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 <google/protobuf/descriptor.h>
Server_Room::Server_Room(int _id, const QString &_name, const QString &_description, bool _autoJoin, const QString &_joinMessage, const QStringList &_gameTypes, Server *parent) 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) : 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<Server *>(parent()); return static_cast<Server *>(parent());
} }
ServerInfo_Room *Server_Room::getInfo(bool complete, bool showGameTypes) const ServerInfo_Room Server_Room::getInfo(bool complete, bool showGameTypes) const
{ {
QMutexLocker locker(&roomMutex); QMutexLocker locker(&roomMutex);
QList<ServerInfo_Game *> gameList; ServerInfo_Room result;
QList<ServerInfo_User *> userList; result.set_room_id(id);
QList<ServerInfo_GameType *> gameTypeList; 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) { if (complete) {
QMapIterator<int, Server_Game *> gameIterator(games); QMapIterator<int, Server_Game *> gameIterator(games);
while (gameIterator.hasNext()) 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) 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) if (complete || showGameTypes)
for (int i = 0; i < gameTypes.size(); ++i) for (int i = 0; i < gameTypes.size(); ++i) {
gameTypeList.append(new ServerInfo_GameType(i, gameTypes[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) void Server_Room::addClient(Server_ProtocolHandler *client)
{ {
QMutexLocker locker(&roomMutex); 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); append(client);
emit roomInfoChanged(); emit roomInfoChanged();
} }
@ -62,13 +87,20 @@ void Server_Room::removeClient(Server_ProtocolHandler *client)
QMutexLocker locker(&roomMutex); QMutexLocker locker(&roomMutex);
removeAt(indexOf(client)); 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(); emit roomInfoChanged();
} }
void Server_Room::say(Server_ProtocolHandler *client, const QString &s) 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) void Server_Room::sendRoomEvent(RoomEvent *event)
@ -76,7 +108,7 @@ void Server_Room::sendRoomEvent(RoomEvent *event)
QMutexLocker locker(&roomMutex); QMutexLocker locker(&roomMutex);
for (int i = 0; i < size(); ++i) for (int i = 0; i < size(); ++i)
at(i)->sendProtocolItem(event, false); at(i)->sendProtocolItem(*event);
delete event; delete event;
} }
@ -84,11 +116,9 @@ void Server_Room::broadcastGameListUpdate(Server_Game *game)
{ {
QMutexLocker locker(&roomMutex); QMutexLocker locker(&roomMutex);
Event_ListGames *event = new Event_ListGames(id, QList<ServerInfo_Game *>() << game->getInfo()); Event_ListGames event;
event.add_game_list()->CopyFrom(game->getInfo());
for (int i = 0; i < size(); i++) sendRoomEvent(prepareRoomEvent(event));
at(i)->sendProtocolItem(event, false);
delete event;
} }
Server_Game *Server_Room::createGame(const QString &description, const QString &password, int maxPlayers, const QList<int> &gameTypes, bool onlyBuddies, bool onlyRegistered, bool spectatorsAllowed, bool spectatorsNeedPassword, bool spectatorsCanTalk, bool spectatorsSeeEverything, Server_ProtocolHandler *creator) Server_Game *Server_Room::createGame(const QString &description, const QString &password, int maxPlayers, const QList<int> &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<int, Server_Game *> gamesIterator(games); QMapIterator<int, Server_Game *> gamesIterator(games);
int result = 0; int result = 0;
while (gamesIterator.hasNext()) while (gamesIterator.hasNext())
if (gamesIterator.next().value()->getCreatorInfo()->getName() == userName) if (gamesIterator.next().value()->getCreatorInfo()->name() == userName.toStdString())
++result; ++result;
return result; return result;
} }
QList<ServerInfo_Game *> Server_Room::getGamesOfUser(const QString &userName) const QList<ServerInfo_Game> Server_Room::getGamesOfUser(const QString &userName) const
{ {
QList<ServerInfo_Game *> result; QList<ServerInfo_Game> result;
QMapIterator<int, Server_Game *> gamesIterator(games); QMapIterator<int, Server_Game *> gamesIterator(games);
while (gamesIterator.hasNext()) { while (gamesIterator.hasNext()) {
Server_Game *game = gamesIterator.next().value(); Server_Game *game = gamesIterator.next().value();

View file

@ -2,6 +2,7 @@
port=4747 port=4747
statusupdate=15000 statusupdate=15000
logfile=server.log logfile=server.log
name="My Cockatrice server"
id=1 id=1
threaded=0 threaded=0

View file

@ -29,6 +29,9 @@
#include "server_logger.h" #include "server_logger.h"
#include "main.h" #include "main.h"
#include "passwordhasher.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) void Servatrice_TcpServer::incomingConnection(int socketDescriptor)
{ {
@ -50,8 +53,7 @@ Servatrice::Servatrice(QSettings *_settings, QObject *parent)
connect(pingClock, SIGNAL(timeout()), this, SIGNAL(pingClockTimeout())); connect(pingClock, SIGNAL(timeout()), this, SIGNAL(pingClockTimeout()));
pingClock->start(1000); pingClock->start(1000);
ProtocolItem::initializeHash(); serverName = settings->value("server/name").toString();
serverId = settings->value("server/id", 0).toInt(); serverId = settings->value("server/id", 0).toInt();
int statusUpdateTime = settings->value("server/statusupdate").toInt(); int statusUpdateTime = settings->value("server/statusupdate").toInt();
statusUpdateClock = new QTimer(this); statusUpdateClock = new QTimer(this);
@ -245,7 +247,54 @@ bool Servatrice::userExists(const QString &user)
} else return false; } 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(); QString name = query.value(0).toString();
int is_admin = query.value(1).toInt(); 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) else if (is_admin == 2)
userLevel |= ServerInfo_User::IsModerator; userLevel |= ServerInfo_User::IsModerator;
return new ServerInfo_User( ServerInfo_User result;
name, result.set_name(name.toStdString());
userLevel, result.set_user_level(userLevel);
QString(), result.set_real_name(realName.toStdString());
realName, result.set_gender(gender);
gender, result.set_country(country.toStdString());
country, result.set_avatar_bmp(avatarBmp.data(), avatarBmp.size());
avatarBmp return result;
);
} }
ServerInfo_User *Servatrice::getUserData(const QString &name) ServerInfo_User Servatrice::getUserData(const QString &name)
{ {
QMutexLocker locker(&dbMutex); QMutexLocker locker(&dbMutex);
const QString method = settings->value("authentication/method").toString(); 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") { if (method == "sql") {
checkSql(); 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.prepare("select name, admin, realname, gender, country, avatar_bmp from " + dbPrefix + "_users where name = :name and active = 1");
query.bindValue(":name", name); query.bindValue(":name", name);
if (!execSqlQuery(query)) if (!execSqlQuery(query))
return new ServerInfo_User(name, ServerInfo_User::IsUser); return result;
if (query.next()) if (query.next())
return evalUserQueryResult(query, true); return evalUserQueryResult(query, true);
else else
return new ServerInfo_User(name, ServerInfo_User::IsUser); return result;
} else } else
return new ServerInfo_User(name, ServerInfo_User::IsUser); return result;
} }
int Servatrice::getUsersWithAddress(const QHostAddress &address) const int Servatrice::getUsersWithAddress(const QHostAddress &address) const
@ -337,10 +388,10 @@ void Servatrice::endSession(int sessionId)
execSqlQuery(query); execSqlQuery(query);
} }
QMap<QString, ServerInfo_User *> Servatrice::getBuddyList(const QString &name) QMap<QString, ServerInfo_User> Servatrice::getBuddyList(const QString &name)
{ {
QMutexLocker locker(&dbMutex); QMutexLocker locker(&dbMutex);
QMap<QString, ServerInfo_User *> result; QMap<QString, ServerInfo_User> result;
const QString method = settings->value("authentication/method").toString(); const QString method = settings->value("authentication/method").toString();
if (method == "sql") { if (method == "sql") {
@ -353,17 +404,17 @@ QMap<QString, ServerInfo_User *> Servatrice::getBuddyList(const QString &name)
return result; return result;
while (query.next()) { while (query.next()) {
ServerInfo_User *temp = evalUserQueryResult(query, false); const ServerInfo_User &temp = evalUserQueryResult(query, false);
result.insert(temp->getName(), temp); result.insert(QString::fromStdString(temp.name()), temp);
} }
} }
return result; return result;
} }
QMap<QString, ServerInfo_User *> Servatrice::getIgnoreList(const QString &name) QMap<QString, ServerInfo_User> Servatrice::getIgnoreList(const QString &name)
{ {
QMutexLocker locker(&dbMutex); QMutexLocker locker(&dbMutex);
QMap<QString, ServerInfo_User *> result; QMap<QString, ServerInfo_User> result;
const QString method = settings->value("authentication/method").toString(); const QString method = settings->value("authentication/method").toString();
if (method == "sql") { if (method == "sql") {
@ -376,8 +427,8 @@ QMap<QString, ServerInfo_User *> Servatrice::getIgnoreList(const QString &name)
return result; return result;
while (query.next()) { while (query.next()) {
ServerInfo_User *temp = evalUserQueryResult(query, false); ServerInfo_User temp = evalUserQueryResult(query, false);
result.insert(temp->getName(), temp); result.insert(QString::fromStdString(temp.name()), temp);
} }
} }
return result; return result;
@ -394,12 +445,13 @@ void Servatrice::updateLoginMessage()
if (query.next()) { if (query.next()) {
loginMessage = query.value(0).toString(); 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<QString, Server_ProtocolHandler *> usersIterator(users); QMapIterator<QString, Server_ProtocolHandler *> usersIterator(users);
while (usersIterator.hasNext()) { while (usersIterator.hasNext())
usersIterator.next().value()->sendProtocolItem(event, false); usersIterator.next().value()->sendProtocolItem(*se);
} delete se;
delete event;
} }
} }
@ -467,15 +519,21 @@ void Servatrice::shutdownTimeout()
--shutdownMinutes; --shutdownMinutes;
GenericEvent *event; SessionEvent *se;
if (shutdownMinutes) if (shutdownMinutes) {
event = new Event_ServerShutdown(shutdownReason, shutdownMinutes); Event_ServerShutdown event;
else event.set_reason(shutdownReason.toStdString());
event = new Event_ConnectionClosed("server_shutdown"); 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) for (int i = 0; i < clients.size(); ++i)
clients[i]->sendProtocolItem(event, false); clients[i]->sendProtocolItem(*se);
delete event; delete se;
if (!shutdownMinutes) if (!shutdownMinutes)
deleteLater(); deleteLater();

View file

@ -51,13 +51,14 @@ private slots:
void statusUpdate(); void statusUpdate();
void shutdownTimeout(); void shutdownTimeout();
public: public:
QMutex dbMutex; mutable QMutex dbMutex;
static const QString versionString; static const QString versionString;
Servatrice(QSettings *_settings, QObject *parent = 0); Servatrice(QSettings *_settings, QObject *parent = 0);
~Servatrice(); ~Servatrice();
bool openDatabase(); bool openDatabase();
void checkSql(); void checkSql();
bool execSqlQuery(QSqlQuery &query); bool execSqlQuery(QSqlQuery &query);
QString getServerName() const { return serverName; }
QString getLoginMessage() const { return loginMessage; } QString getLoginMessage() const { return loginMessage; }
bool getGameShouldPing() const { return true; } bool getGameShouldPing() const { return true; }
int getMaxGameInactivityTime() const { return maxGameInactivityTime; } int getMaxGameInactivityTime() const { return maxGameInactivityTime; }
@ -70,13 +71,16 @@ public:
bool getThreaded() const { return threaded; } bool getThreaded() const { return threaded; }
QString getDbPrefix() const { return dbPrefix; } QString getDbPrefix() const { return dbPrefix; }
void updateLoginMessage(); void updateLoginMessage();
ServerInfo_User *getUserData(const QString &name); ServerInfo_User getUserData(const QString &name);
int getUsersWithAddress(const QHostAddress &address) const; int getUsersWithAddress(const QHostAddress &address) const;
QMap<QString, ServerInfo_User *> getBuddyList(const QString &name); QMap<QString, ServerInfo_User> getBuddyList(const QString &name);
QMap<QString, ServerInfo_User *> getIgnoreList(const QString &name); QMap<QString, ServerInfo_User> 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 scheduleShutdown(const QString &reason, int minutes);
void incTxBytes(quint64 num); void incTxBytes(quint64 num);
void incRxBytes(quint64 num); void incRxBytes(quint64 num);
int getUserIdInDB(const QString &name);
protected: protected:
int startSession(const QString &userName, const QString &address); int startSession(const QString &userName, const QString &address);
void endSession(int sessionId); void endSession(int sessionId);
@ -85,6 +89,7 @@ protected:
private: private:
QTimer *pingClock, *statusUpdateClock; QTimer *pingClock, *statusUpdateClock;
QTcpServer *tcpServer; QTcpServer *tcpServer;
QString serverName;
QString loginMessage; QString loginMessage;
QString dbPrefix; QString dbPrefix;
QSettings *settings; QSettings *settings;
@ -95,7 +100,7 @@ private:
quint64 txBytes, rxBytes; quint64 txBytes, rxBytes;
int maxGameInactivityTime, maxPlayerInactivityTime; int maxGameInactivityTime, maxPlayerInactivityTime;
int maxUsersPerAddress, messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval, maxGamesPerUser; int maxUsersPerAddress, messageCountingInterval, maxMessageCountPerInterval, maxMessageSizePerInterval, maxGamesPerUser;
ServerInfo_User *evalUserQueryResult(const QSqlQuery &query, bool complete); ServerInfo_User evalUserQueryResult(const QSqlQuery &query, bool complete);
QString shutdownReason; QString shutdownReason;
int shutdownMinutes; int shutdownMinutes;

View file

@ -18,15 +18,12 @@
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/ ***************************************************************************/
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include <QtSql> #include <QtSql>
#include <QHostAddress> #include <QHostAddress>
#include <QDebug> #include <QDebug>
#include "serversocketinterface.h" #include "serversocketinterface.h"
#include "servatrice.h" #include "servatrice.h"
#include "protocol.h" #include "protocol.h"
#include "protocol_items.h"
#include "decklist.h" #include "decklist.h"
#include "server_player.h" #include "server_player.h"
#include "main.h" #include "main.h"
@ -38,32 +35,43 @@
#include "pb/command_deck_new_dir.pb.h" #include "pb/command_deck_new_dir.pb.h"
#include "pb/command_deck_del_dir.pb.h" #include "pb/command_deck_del_dir.pb.h"
#include "pb/command_deck_del.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 <string> #include <string>
#include <iostream> #include <iostream>
ServerSocketInterface::ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent) 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(readyRead()), this, SLOT(readClient()));
connect(socket, SIGNAL(disconnected()), this, SLOT(deleteLater())); connect(socket, SIGNAL(disconnected()), this, SLOT(deleteLater()));
connect(socket, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(catchSocketError(QAbstractSocket::SocketError))); 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(); Event_ServerIdentification identEvent;
xmlWriter->writeStartElement("cockatrice_server_stream"); identEvent.set_server_name(servatrice->getServerName().toStdString());
xmlWriter->writeAttribute("version", QString::number(ProtocolItem::protocolVersion)); identEvent.set_server_version(Servatrice::versionString.toStdString());
flushXmlBuffer(); identEvent.set_protocol_version(protocolVersion);
SessionEvent *identSe = prepareSessionEvent(identEvent);
sendProtocolItem(*identSe);
delete identSe;
int maxUsers = _server->getMaxUsersPerAddress(); int maxUsers = _server->getMaxUsersPerAddress();
if ((maxUsers > 0) && (_server->getUsersWithAddress(socket->peerAddress()) >= maxUsers)) { 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(); deleteLater();
} else }
sendProtocolItem(new Event_ServerMessage(Servatrice::versionString));
server->addClient(this); server->addClient(this);
} }
@ -74,23 +82,20 @@ ServerSocketInterface::~ServerSocketInterface()
prepareDestroy(); prepareDestroy();
flushXmlBuffer(); flushOutputBuffer();
delete xmlWriter;
delete xmlReader;
delete socket; delete socket;
socket = 0; socket = 0;
delete topLevelItem;
} }
void ServerSocketInterface::flushXmlBuffer() void ServerSocketInterface::flushOutputBuffer()
{ {
QMutexLocker locker(&xmlBufferMutex); QMutexLocker locker(&outputBufferMutex);
if (xmlBuffer.isEmpty()) if (outputBuffer.isEmpty())
return; return;
servatrice->incTxBytes(xmlBuffer.size()); servatrice->incTxBytes(outputBuffer.size());
socket->write(xmlBuffer.toUtf8()); socket->write(outputBuffer);
socket->flush(); socket->flush();
xmlBuffer.clear(); outputBuffer.clear();
} }
void ServerSocketInterface::readClient() void ServerSocketInterface::readClient()
@ -131,52 +136,46 @@ void ServerSocketInterface::catchSocketError(QAbstractSocket::SocketError socket
deleteLater(); 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); QMutexLocker locker(&outputBufferMutex);
if (deleteItem) outputBuffer.append(buf);
delete item; emit outputBufferChanged();
emit xmlBufferChanged();
} }
int ServerSocketInterface::getUserIdInDB(const QString &name) const Response::ResponseCode ServerSocketInterface::cmdAddToList(const Command_AddToList &cmd, ResponseContainer &rc)
{
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)
{ {
if (authState != PasswordRight) if (authState != PasswordRight)
return RespFunctionNotAllowed; return Response::RespFunctionNotAllowed;
QString list = QString::fromStdString(cmd.list()); QString list = QString::fromStdString(cmd.list());
QString user = QString::fromStdString(cmd.user_name()); QString user = QString::fromStdString(cmd.user_name());
if ((list != "buddy") && (list != "ignore")) if ((list != "buddy") && (list != "ignore"))
return RespContextError; return Response::RespContextError;
if ((list == "buddy") && buddyList.contains(user)) if (list == "buddy")
return RespContextError; if (servatrice->isInBuddyList(QString::fromStdString(userInfo->name()), user))
if ((list == "ignore") && ignoreList.contains(user)) return Response::RespContextError;
return RespContextError; if (list == "ignore")
if (servatrice->isInIgnoreList(QString::fromStdString(userInfo->name()), user))
return Response::RespContextError;
int id1 = getUserIdInDB(userInfo->getName()); int id1 = servatrice->getUserIdInDB(QString::fromStdString(userInfo->name()));
int id2 = getUserIdInDB(user); int id2 = servatrice->getUserIdInDB(user);
if (id2 < 0) if (id2 < 0)
return RespNameNotFound; return Response::RespNameNotFound;
if (id1 == id2) if (id1 == id2)
return RespContextError; return Response::RespContextError;
QMutexLocker locker(&servatrice->dbMutex); QMutexLocker locker(&servatrice->dbMutex);
QSqlQuery query; QSqlQuery query;
@ -184,38 +183,38 @@ ResponseCode ServerSocketInterface::cmdAddToList(const Command_AddToList &cmd, B
query.bindValue(":id1", id1); query.bindValue(":id1", id1);
query.bindValue(":id2", id2); query.bindValue(":id2", id2);
if (!servatrice->execSqlQuery(query)) if (!servatrice->execSqlQuery(query))
return RespInternalError; return Response::RespInternalError;
ServerInfo_User *info = servatrice->getUserData(user); Event_AddToList *event = new Event_AddToList;
if (list == "buddy") event->set_list_name(cmd.list());
buddyList.insert(info->getName(), info); event->mutable_user_info()->CopyFrom(servatrice->getUserData(user));
else if (list == "ignore") rc.enqueuePreResponseItem(ServerMessage::SESSION_EVENT, event);
ignoreList.insert(info->getName(), info);
bla->enqueueItem(new Event_AddToList(list, new ServerInfo_User(info))); return Response::RespOk;
return RespOk;
} }
ResponseCode ServerSocketInterface::cmdRemoveFromList(const Command_RemoveFromList &cmd, BlaContainer *bla) Response::ResponseCode ServerSocketInterface::cmdRemoveFromList(const Command_RemoveFromList &cmd, ResponseContainer &rc)
{ {
if (authState != PasswordRight) if (authState != PasswordRight)
return RespFunctionNotAllowed; return Response::RespFunctionNotAllowed;
QString list = QString::fromStdString(cmd.list()); QString list = QString::fromStdString(cmd.list());
QString user = QString::fromStdString(cmd.user_name()); QString user = QString::fromStdString(cmd.user_name());
if ((list != "buddy") && (list != "ignore")) if ((list != "buddy") && (list != "ignore"))
return RespContextError; return Response::RespContextError;
if ((list == "buddy") && !buddyList.contains(user)) if (list == "buddy")
return RespContextError; if (!servatrice->isInBuddyList(QString::fromStdString(userInfo->name()), user))
if ((list == "ignore") && !ignoreList.contains(user)) return Response::RespContextError;
return RespContextError; if (list == "ignore")
if (!servatrice->isInIgnoreList(QString::fromStdString(userInfo->name()), user))
return Response::RespContextError;
int id1 = getUserIdInDB(userInfo->getName()); int id1 = servatrice->getUserIdInDB(QString::fromStdString(userInfo->name()));
int id2 = getUserIdInDB(user); int id2 = servatrice->getUserIdInDB(user);
if (id2 < 0) if (id2 < 0)
return RespNameNotFound; return Response::RespNameNotFound;
QMutexLocker locker(&servatrice->dbMutex); QMutexLocker locker(&servatrice->dbMutex);
QSqlQuery query; QSqlQuery query;
@ -223,18 +222,14 @@ ResponseCode ServerSocketInterface::cmdRemoveFromList(const Command_RemoveFromLi
query.bindValue(":id1", id1); query.bindValue(":id1", id1);
query.bindValue(":id2", id2); query.bindValue(":id2", id2);
if (!servatrice->execSqlQuery(query)) if (!servatrice->execSqlQuery(query))
return RespInternalError; return Response::RespInternalError;
if (list == "buddy") { Event_RemoveFromList *event = new Event_RemoveFromList;
delete buddyList.value(user); event->set_list_name(cmd.list());
buddyList.remove(user); event->set_user_name(cmd.user_name());
} else if (list == "ignore") { rc.enqueuePreResponseItem(ServerMessage::SESSION_EVENT, event);
delete ignoreList.value(user);
ignoreList.remove(user);
}
bla->enqueueItem(new Event_RemoveFromList(list, user)); return Response::RespOk;
return RespOk;
} }
int ServerSocketInterface::getDeckPathId(int basePathId, QStringList path) 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.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(":id_parent", basePathId);
query.bindValue(":name", path.takeFirst()); query.bindValue(":name", path.takeFirst());
query.bindValue(":user", userInfo->getName()); query.bindValue(":user", QString::fromStdString(userInfo->name()));
if (!servatrice->execSqlQuery(query)) if (!servatrice->execSqlQuery(query))
return -1; return -1;
if (!query.next()) if (!query.next())
@ -265,7 +260,7 @@ int ServerSocketInterface::getDeckPathId(const QString &path)
{ {
return getDeckPathId(0, path.split("/")); return getDeckPathId(0, path.split("/"));
} }
/*
bool ServerSocketInterface::deckListHelper(DeckList_Directory *folder) bool ServerSocketInterface::deckListHelper(DeckList_Directory *folder)
{ {
QMutexLocker locker(&servatrice->dbMutex); QMutexLocker locker(&servatrice->dbMutex);
@ -296,50 +291,50 @@ bool ServerSocketInterface::deckListHelper(DeckList_Directory *folder)
return true; return true;
} }
*/
// CHECK AUTHENTICATION! // CHECK AUTHENTICATION!
// Also check for every function that data belonging to other users cannot be accessed. // 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) if (authState != PasswordRight)
return RespFunctionNotAllowed; return Response::RespFunctionNotAllowed;
servatrice->checkSql(); servatrice->checkSql();
DeckList_Directory *root = new DeckList_Directory(QString()); /* DeckList_Directory *root = new DeckList_Directory(QString());
QSqlQuery query; QSqlQuery query;
if (!deckListHelper(root)) if (!deckListHelper(root))
return RespContextError; return Response::RespContextError;
ProtocolResponse *resp = new Response_DeckList(-1, RespOk, root); ProtocolResponse *resp = new Response_DeckList(-1, RespOk, root);
if (getCompressionSupport()) if (getCompressionSupport())
resp->setCompressed(true); resp->setCompressed(true);
bla->setResponse(resp); 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) if (authState != PasswordRight)
return RespFunctionNotAllowed; return Response::RespFunctionNotAllowed;
servatrice->checkSql(); servatrice->checkSql();
int folderId = getDeckPathId(QString::fromStdString(cmd.path())); int folderId = getDeckPathId(QString::fromStdString(cmd.path()));
if (folderId == -1) if (folderId == -1)
return RespNameNotFound; return Response::RespNameNotFound;
QMutexLocker locker(&servatrice->dbMutex); QMutexLocker locker(&servatrice->dbMutex);
QSqlQuery query; QSqlQuery query;
query.prepare("insert into " + servatrice->getDbPrefix() + "_decklist_folders (id_parent, user, name) values(:id_parent, :user, :name)"); query.prepare("insert into " + servatrice->getDbPrefix() + "_decklist_folders (id_parent, user, name) values(:id_parent, :user, :name)");
query.bindValue(":id_parent", folderId); 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())); query.bindValue(":name", QString::fromStdString(cmd.dir_name()));
if (!servatrice->execSqlQuery(query)) if (!servatrice->execSqlQuery(query))
return RespContextError; return Response::RespContextError;
return RespOk; return Response::RespOk;
} }
void ServerSocketInterface::deckDelDirHelper(int basePathId) void ServerSocketInterface::deckDelDirHelper(int basePathId)
@ -364,24 +359,24 @@ void ServerSocketInterface::deckDelDirHelper(int basePathId)
servatrice->execSqlQuery(query); 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) if (authState != PasswordRight)
return RespFunctionNotAllowed; return Response::RespFunctionNotAllowed;
servatrice->checkSql(); servatrice->checkSql();
int basePathId = getDeckPathId(QString::fromStdString(cmd.path())); int basePathId = getDeckPathId(QString::fromStdString(cmd.path()));
if (basePathId == -1) if (basePathId == -1)
return RespNameNotFound; return Response::RespNameNotFound;
deckDelDirHelper(basePathId); 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) if (authState != PasswordRight)
return RespFunctionNotAllowed; return Response::RespFunctionNotAllowed;
servatrice->checkSql(); 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.prepare("select id from " + servatrice->getDbPrefix() + "_decklist_files where id = :id and user = :user");
query.bindValue(":id", cmd.deck_id()); query.bindValue(":id", cmd.deck_id());
query.bindValue(":user", userInfo->getName()); query.bindValue(":user", QString::fromStdString(userInfo->name()));
servatrice->execSqlQuery(query); servatrice->execSqlQuery(query);
if (!query.next()) if (!query.next())
return RespNameNotFound; return Response::RespNameNotFound;
query.prepare("delete from " + servatrice->getDbPrefix() + "_decklist_files where id = :id"); query.prepare("delete from " + servatrice->getDbPrefix() + "_decklist_files where id = :id");
query.bindValue(":id", cmd.deck_id()); query.bindValue(":id", cmd.deck_id());
servatrice->execSqlQuery(query); 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) if (authState != PasswordRight)
return RespFunctionNotAllowed; return Response::RespFunctionNotAllowed;
servatrice->checkSql(); servatrice->checkSql();
if (!cmd.has_deck_list()) if (!cmd.has_deck_list())
return RespInvalidData; return Response::RespInvalidData;
int folderId = getDeckPathId(QString::fromStdString(cmd.path())); int folderId = getDeckPathId(QString::fromStdString(cmd.path()));
if (folderId == -1) if (folderId == -1)
return RespNameNotFound; return Response::RespNameNotFound;
QString deckStr = QString::fromStdString(cmd.deck_list()); QString deckStr = QString::fromStdString(cmd.deck_list());
DeckList deck(deckStr); DeckList deck(deckStr);
@ -426,13 +421,13 @@ ResponseCode ServerSocketInterface::cmdDeckUpload(const Command_DeckUpload &cmd,
QSqlQuery query; 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.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(":id_folder", folderId);
query.bindValue(":user", userInfo->getName()); query.bindValue(":user", QString::fromStdString(userInfo->name()));
query.bindValue(":name", deckName); query.bindValue(":name", deckName);
query.bindValue(":content", deckStr); query.bindValue(":content", deckStr);
servatrice->execSqlQuery(query); servatrice->execSqlQuery(query);
bla->setResponse(new Response_DeckUpload(-1, RespOk, new DeckList_File(deckName, query.lastInsertId().toInt(), QDateTime::currentDateTime()))); // bla->setResponse(new Response_DeckUpload(-1, RespOk, new DeckList_File(deckName, query.lastInsertId().toInt(), QDateTime::currentDateTime())));
return RespNothing; return Response::RespNothing;
} }
DeckList *ServerSocketInterface::getDeckFromDatabase(int deckId) 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.prepare("select content from " + servatrice->getDbPrefix() + "_decklist_files where id = :id and user = :user");
query.bindValue(":id", deckId); query.bindValue(":id", deckId);
query.bindValue(":user", userInfo->getName()); query.bindValue(":user", QString::fromStdString(userInfo->name()));
servatrice->execSqlQuery(query); servatrice->execSqlQuery(query);
if (!query.next()) if (!query.next())
throw RespNameNotFound; throw Response::RespNameNotFound;
QXmlStreamReader deckReader(query.value(0).toString()); QXmlStreamReader deckReader(query.value(0).toString());
DeckList *deck = new DeckList; DeckList *deck = new DeckList;
@ -456,25 +451,30 @@ DeckList *ServerSocketInterface::getDeckFromDatabase(int deckId)
return deck; return deck;
} }
ResponseCode ServerSocketInterface::cmdDeckDownload(const Command_DeckDownload &cmd, BlaContainer *bla) Response::ResponseCode ServerSocketInterface::cmdDeckDownload(const Command_DeckDownload &cmd, ResponseContainer &rc)
{ {
if (authState != PasswordRight) if (authState != PasswordRight)
return RespFunctionNotAllowed; return Response::RespFunctionNotAllowed;
DeckList *deck; DeckList *deck;
try { try {
deck = getDeckFromDatabase(cmd.deck_id()); deck = getDeckFromDatabase(cmd.deck_id());
} catch(ResponseCode r) { } catch(Response::ResponseCode r) {
return 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. // MODERATOR FUNCTIONS.
// May be called by admins and moderators. Permission is checked by the calling function. // 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 userName = QString::fromStdString(cmd.user_name());
QString address = QString::fromStdString(cmd.address()); 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.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(":user_name", userName);
query.bindValue(":ip_address", address); 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(":minutes", minutes);
query.bindValue(":reason", QString::fromStdString(cmd.reason()) + "\n"); query.bindValue(":reason", QString::fromStdString(cmd.reason()) + "\n");
servatrice->execSqlQuery(query); servatrice->execSqlQuery(query);
@ -493,24 +493,28 @@ ResponseCode ServerSocketInterface::cmdBanFromServer(const Command_BanFromServer
ServerSocketInterface *user = static_cast<ServerSocketInterface *>(server->getUsers().value(userName)); ServerSocketInterface *user = static_cast<ServerSocketInterface *>(server->getUsers().value(userName));
if (user) { 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(); user->deleteLater();
} }
return RespOk; return Response::RespOk;
} }
// ADMIN FUNCTIONS. // ADMIN FUNCTIONS.
// Permission is checked by the calling function. // 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(); 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()); servatrice->scheduleShutdown(QString::fromStdString(cmd.reason()), cmd.minutes());
return RespOk; return Response::RespOk;
} }

View file

@ -27,11 +27,7 @@
class QTcpSocket; class QTcpSocket;
class Servatrice; class Servatrice;
class QXmlStreamReader;
class QXmlStreamWriter;
class DeckList; class DeckList;
class TopLevelProtocolItem;
class QByteArray;
class ServerSocketInterface : public Server_ProtocolHandler class ServerSocketInterface : public Server_ProtocolHandler
{ {
@ -39,51 +35,41 @@ class ServerSocketInterface : public Server_ProtocolHandler
private slots: private slots:
void readClient(); void readClient();
void catchSocketError(QAbstractSocket::SocketError socketError); void catchSocketError(QAbstractSocket::SocketError socketError);
// void processProtocolItem(ProtocolItem *item); void flushOutputBuffer();
void flushXmlBuffer();
signals: signals:
void xmlBufferChanged(); void outputBufferChanged();
private: private:
QMutex xmlBufferMutex; QMutex outputBufferMutex;
Servatrice *servatrice; Servatrice *servatrice;
QTcpSocket *socket; QTcpSocket *socket;
QXmlStreamWriter *xmlWriter;
QXmlStreamReader *xmlReader;
QString xmlBuffer;
TopLevelProtocolItem *topLevelItem;
bool compressionSupport;
QByteArray inputBuffer; QByteArray inputBuffer, outputBuffer;
bool messageInProgress; bool messageInProgress;
int messageLength; int messageLength;
int getUserIdInDB(const QString &name) const; Response::ResponseCode cmdAddToList(const Command_AddToList &cmd, ResponseContainer &rc);
Response::ResponseCode cmdRemoveFromList(const Command_RemoveFromList &cmd, ResponseContainer &rc);
ResponseCode cmdAddToList(const Command_AddToList &cmd, BlaContainer *bla);
ResponseCode cmdRemoveFromList(const Command_RemoveFromList &cmd, BlaContainer *bla);
int getDeckPathId(int basePathId, QStringList path); int getDeckPathId(int basePathId, QStringList path);
int getDeckPathId(const QString &path); int getDeckPathId(const QString &path);
bool deckListHelper(DeckList_Directory *folder); // bool deckListHelper(DeckList_Directory *folder);
ResponseCode cmdDeckList(const Command_DeckList &cmd, BlaContainer *bla); Response::ResponseCode cmdDeckList(const Command_DeckList &cmd, ResponseContainer &rc);
ResponseCode cmdDeckNewDir(const Command_DeckNewDir &cmd, BlaContainer *bla); Response::ResponseCode cmdDeckNewDir(const Command_DeckNewDir &cmd, ResponseContainer &rc);
void deckDelDirHelper(int basePathId); void deckDelDirHelper(int basePathId);
ResponseCode cmdDeckDelDir(const Command_DeckDelDir &cmd, BlaContainer *bla); Response::ResponseCode cmdDeckDelDir(const Command_DeckDelDir &cmd, ResponseContainer &rc);
ResponseCode cmdDeckDel(const Command_DeckDel &cmd, BlaContainer *bla); Response::ResponseCode cmdDeckDel(const Command_DeckDel &cmd, ResponseContainer &rc);
ResponseCode cmdDeckUpload(const Command_DeckUpload &cmd, BlaContainer *bla); Response::ResponseCode cmdDeckUpload(const Command_DeckUpload &cmd, ResponseContainer &rc);
DeckList *getDeckFromDatabase(int deckId); DeckList *getDeckFromDatabase(int deckId);
ResponseCode cmdDeckDownload(const Command_DeckDownload &cmd, BlaContainer *bla); Response::ResponseCode cmdDeckDownload(const Command_DeckDownload &cmd, ResponseContainer &rc);
ResponseCode cmdBanFromServer(const Command_BanFromServer &cmd, BlaContainer *bla); Response::ResponseCode cmdBanFromServer(const Command_BanFromServer &cmd, ResponseContainer &rc);
ResponseCode cmdShutdownServer(const Command_ShutdownServer &cmd, BlaContainer *bla); Response::ResponseCode cmdShutdownServer(const Command_ShutdownServer &cmd, ResponseContainer &rc);
ResponseCode cmdUpdateServerMessage(const Command_UpdateServerMessage &cmd, BlaContainer *bla); Response::ResponseCode cmdUpdateServerMessage(const Command_UpdateServerMessage &cmd, ResponseContainer &rc);
protected:
bool getCompressionSupport() const { return compressionSupport; }
public: public:
ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent = 0); ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent = 0);
~ServerSocketInterface(); ~ServerSocketInterface();
QHostAddress getPeerAddress() const { return socket->peerAddress(); } QHostAddress getPeerAddress() const { return socket->peerAddress(); }
QString getAddress() const { return socket->peerAddress().toString(); } QString getAddress() const { return socket->peerAddress().toString(); }
void sendProtocolItem(ProtocolItem *item, bool deleteItem = true); void transmitProtocolItem(const ServerMessage &item);
}; };
#endif #endif