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/decklist.h \
../common/protocol.h \
../common/protocol_items.h \
../common/protocol_datastructures.h \
../common/rng_abstract.h \
../common/rng_sfmt.h \
../common/server.h \
@ -170,12 +168,9 @@ SOURCES += src/abstractcounter.cpp \
src/localclient.cpp \
src/priceupdater.cpp \
src/soundengine.cpp \
src/pending_command.cpp \
../common/serializable_item.cpp \
../common/decklist.cpp \
../common/protocol.cpp \
../common/protocol_items.cpp \
../common/protocol_datastructures.cpp \
../common/rng_abstract.cpp \
../common/rng_sfmt.cpp \
../common/sfmt/SFMT.c \

View file

@ -1,9 +1,19 @@
#include "abstractclient.h"
#include "protocol.h"
#include "protocol_items.h"
#include "pending_command.h"
#include "pb/commands.pb.h"
#include "pb/event_server_identification.pb.h"
#include "pb/event_server_message.pb.h"
#include "pb/event_server_shutdown.pb.h"
#include "pb/event_connection_closed.pb.h"
#include "pb/event_user_message.pb.h"
#include "pb/event_list_rooms.pb.h"
#include "pb/event_add_to_list.pb.h"
#include "pb/event_remove_from_list.pb.h"
#include "pb/event_user_joined.pb.h"
#include "pb/event_user_left.pb.h"
#include "pb/event_game_joined.pb.h"
#include <google/protobuf/descriptor.h>
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);
if (response) {
const int cmdId = response->getCmdId();
PendingCommand *pend = pendingCommands.value(cmdId, 0);
if (!pend)
return;
pendingCommands.remove(cmdId);
pend->processResponse(response);
if (response->getReceiverMayDelete())
delete response;
pend->deleteLater();
return;
}
GenericEvent *genericEvent = qobject_cast<GenericEvent *>(item);
if (genericEvent) {
switch (genericEvent->getItemId()) {
case ItemId_Event_ConnectionClosed: emit connectionClosedEventReceived(static_cast<Event_ConnectionClosed *>(item)); break;
case ItemId_Event_ServerShutdown: emit serverShutdownEventReceived(static_cast<Event_ServerShutdown *>(item)); break;
case ItemId_Event_AddToList: emit addToListEventReceived(static_cast<Event_AddToList *>(item)); 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;
case ItemId_Event_UserLeft: emit userLeftEventReceived(static_cast<Event_UserLeft *>(item)); break;
case ItemId_Event_ServerMessage: emit serverMessageEventReceived(static_cast<Event_ServerMessage *>(item)); break;
case ItemId_Event_ListRooms: emit listRoomsEventReceived(static_cast<Event_ListRooms *>(item)); break;
case ItemId_Event_GameJoined: emit gameJoinedEventReceived(static_cast<Event_GameJoined *>(item)); break;
case ItemId_Event_Message: emit messageEventReceived(static_cast<Event_Message *>(item)); break;
switch (item.message_type()) {
case ServerMessage::RESPONSE: {
const Response &response = item.response();
const int cmdId = response.cmd_id();
PendingCommand *pend = pendingCommands.value(cmdId, 0);
if (!pend)
return;
pendingCommands.remove(cmdId);
pend->processResponse(response);
pend->deleteLater();
break;
}
case ServerMessage::SESSION_EVENT: {
const SessionEvent &event = item.session_event();
std::vector< const ::google::protobuf::FieldDescriptor * > fieldList;
event.GetReflection()->ListFields(event, &fieldList);
int num = 0;
for (unsigned int j = 0; j < fieldList.size(); ++j)
if (fieldList[j]->is_extension()) {
num = fieldList[j]->number();
break;
}
switch ((SessionEvent::SessionEventType) num) {
case SessionEvent::SERVER_IDENTIFICATION: emit serverIdentificationEventReceived(event.GetExtension(Event_ServerIdentification::ext)); break;
case SessionEvent::SERVER_MESSAGE: emit serverMessageEventReceived(event.GetExtension(Event_ServerMessage::ext)); break;
case SessionEvent::SERVER_SHUTDOWN: emit serverShutdownEventReceived(event.GetExtension(Event_ServerShutdown::ext)); break;
case SessionEvent::CONNECTION_CLOSED: emit connectionClosedEventReceived(event.GetExtension(Event_ConnectionClosed::ext)); break;
case SessionEvent::USER_MESSAGE: emit userMessageEventReceived(event.GetExtension(Event_UserMessage::ext)); break;
case SessionEvent::LIST_ROOMS: emit listRoomsEventReceived(event.GetExtension(Event_ListRooms::ext)); break;
case SessionEvent::ADD_TO_LIST: emit addToListEventReceived(event.GetExtension(Event_AddToList::ext)); break;
case SessionEvent::REMOVE_FROM_LIST: emit removeFromListEventReceived(event.GetExtension(Event_RemoveFromList::ext)); break;
case SessionEvent::USER_JOINED: emit userJoinedEventReceived(event.GetExtension(Event_UserJoined::ext)); break;
case SessionEvent::USER_LEFT: emit userLeftEventReceived(event.GetExtension(Event_UserLeft::ext)); break;
case SessionEvent::GAME_JOINED: emit gameJoinedEventReceived(event.GetExtension(Event_GameJoined::ext)); break;
}
break;
}
case ServerMessage::GAME_EVENT_CONTAINER: {
emit gameEventContainerReceived(item.game_event_container());
break;
}
case ServerMessage::ROOM_EVENT: {
emit roomEventReceived(item.room_event());
break;
}
if (genericEvent->getReceiverMayDelete())
delete genericEvent;
return;
}
GameEventContainer *gameEventContainer = qobject_cast<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 <QVariant>
#include <google/protobuf/message.h>
#include "protocol_datastructures.h"
#include "pb/response.pb.h"
#include "pb/serverinfo_user.pb.h"
class PendingCommand;
class CommandContainer;
class ProtocolItem;
class ProtocolResponse;
class TopLevelProtocolItem;
class CommandContainer;
class RoomEvent;
class GameEventContainer;
class ServerMessage;
class Event_ServerIdentification;
class Event_AddToList;
class Event_RemoveFromList;
class Event_UserJoined;
@ -21,7 +19,7 @@ class Event_UserLeft;
class Event_ServerMessage;
class Event_ListRooms;
class Event_GameJoined;
class Event_Message;
class Event_UserMessage;
class Event_ConnectionClosed;
class Event_ServerShutdown;
@ -38,30 +36,31 @@ class AbstractClient : public QObject {
Q_OBJECT
signals:
void statusChanged(ClientStatus _status);
void serverError(ResponseCode resp);
void serverError(Response::ResponseCode resp);
// Room events
void roomEventReceived(RoomEvent *event);
void roomEventReceived(const RoomEvent &event);
// Game events
void gameEventContainerReceived(GameEventContainer *event);
// Generic events
void connectionClosedEventReceived(Event_ConnectionClosed *event);
void serverShutdownEventReceived(Event_ServerShutdown *event);
void addToListEventReceived(Event_AddToList *event);
void removeFromListEventReceived(Event_RemoveFromList *event);
void userJoinedEventReceived(Event_UserJoined *event);
void userLeftEventReceived(Event_UserLeft *event);
void serverMessageEventReceived(Event_ServerMessage *event);
void listRoomsEventReceived(Event_ListRooms *event);
void gameJoinedEventReceived(Event_GameJoined *event);
void messageEventReceived(Event_Message *event);
void userInfoChanged(ServerInfo_User *userInfo);
void buddyListReceived(const QList<ServerInfo_User *> &buddyList);
void ignoreListReceived(const QList<ServerInfo_User *> &ignoreList);
void gameEventContainerReceived(const GameEventContainer &event);
// Session events
void serverIdentificationEventReceived(const Event_ServerIdentification &event);
void connectionClosedEventReceived(const Event_ConnectionClosed &event);
void serverShutdownEventReceived(const Event_ServerShutdown &event);
void addToListEventReceived(const Event_AddToList &event);
void removeFromListEventReceived(const Event_RemoveFromList &event);
void userJoinedEventReceived(const Event_UserJoined &event);
void userLeftEventReceived(const Event_UserLeft &event);
void serverMessageEventReceived(const Event_ServerMessage &event);
void listRoomsEventReceived(const Event_ListRooms &event);
void gameJoinedEventReceived(const Event_GameJoined &event);
void userMessageEventReceived(const Event_UserMessage &event);
void userInfoChanged(const ServerInfo_User &userInfo);
void buddyListReceived(const QList<ServerInfo_User> &buddyList);
void ignoreListReceived(const QList<ServerInfo_User> &ignoreList);
private:
int nextCmdId;
protected slots:
void processProtocolItem(ProtocolItem *item);
void processProtocolItem(const ServerMessage &item);
protected:
QMap<int, PendingCommand *> pendingCommands;
ClientStatus status;

View file

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

View file

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

View file

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

View file

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

View file

@ -20,7 +20,9 @@ LocalServerInterface *LocalServer::newConnection()
return lsi;
}
ServerInfo_User *LocalServer::getUserData(const QString &name)
ServerInfo_User LocalServer::getUserData(const QString &name)
{
return new ServerInfo_User(name);
ServerInfo_User result;
result.set_name(name.toStdString());
return result;
}

View file

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

View file

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

View file

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

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

View file

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

View file

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

View file

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

View file

@ -51,7 +51,7 @@ void MainWindow::updateTabMenu(QMenu *menu)
void MainWindow::processConnectionClosedEvent(Event_ConnectionClosed *event)
{
QString reason = event->getReason();
/* QString reason = event->getReason();
client->disconnectFromServer();
QString reasonStr;
if (reason == "too_many_connections")
@ -63,11 +63,13 @@ void MainWindow::processConnectionClosedEvent(Event_ConnectionClosed *event)
else
reasonStr = tr("Unknown reason.");
QMessageBox::critical(this, tr("Connection closed"), tr("The server has terminated your connection.\nReason: %1").arg(reasonStr));
*/
}
void MainWindow::processServerShutdownEvent(Event_ServerShutdown *event)
{
QMessageBox::information(this, tr("Scheduled server shutdown"), tr("The server is going to be restarted in %n minute(s).\nAll running games will be lost.\nReason for shutdown: %1", "", event->getMinutes()).arg(event->getReason()));
/* QMessageBox::information(this, tr("Scheduled server shutdown"), tr("The server is going to be restarted in %n minute(s).\nAll running games will be lost.\nReason for shutdown: %1", "", event->getMinutes()).arg(event->getReason()));
* */
}
void MainWindow::statusChanged(ClientStatus _status)
@ -199,11 +201,11 @@ void MainWindow::serverTimeout()
QMessageBox::critical(this, tr("Error"), tr("Server timeout"));
}
void MainWindow::serverError(ResponseCode r)
void MainWindow::serverError(Response::ResponseCode r)
{
switch (r) {
case RespWrongPassword: QMessageBox::critical(this, tr("Error"), tr("Invalid login data.")); break;
case RespWouldOverwriteOldSession: QMessageBox::critical(this, tr("Error"), tr("There is already an active session using this user name.\nPlease close that session first and re-login.")); break;
case Response::RespWrongPassword: QMessageBox::critical(this, tr("Error"), tr("Invalid login data.")); break;
case Response::RespWouldOverwriteOldSession: QMessageBox::critical(this, tr("Error"), tr("There is already an active session using this user name.\nPlease close that session first and re-login.")); break;
default: ;
}
}
@ -302,7 +304,7 @@ MainWindow::MainWindow(QWidget *parent)
client = new RemoteClient(this);
connect(client, SIGNAL(connectionClosedEventReceived(Event_ConnectionClosed *)), this, SLOT(processConnectionClosedEvent(Event_ConnectionClosed *)));
connect(client, SIGNAL(serverShutdownEventReceived(Event_ServerShutdown *)), this, SLOT(processServerShutdownEvent(Event_ServerShutdown *)));
connect(client, SIGNAL(serverError(ResponseCode)), this, SLOT(serverError(ResponseCode)));
connect(client, SIGNAL(serverError(Response::ResponseCode)), this, SLOT(serverError(Response::ResponseCode)));
connect(client, SIGNAL(socketError(const QString &)), this, SLOT(socketError(const QString &)));
connect(client, SIGNAL(serverTimeout()), this, SLOT(serverTimeout()));
connect(client, SIGNAL(statusChanged(ClientStatus)), this, SLOT(statusChanged(ClientStatus)));

View file

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

View file

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

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 {
enum SessionEventType {
SERVER_IDENTIFICATION = 500;
SERVER_MESSAGE = 1000;
SERVER_SHUTDOWN = 1001;
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)
: ProtocolResponse(_cmdId, _responseCode, "deck_download")

View file

@ -6,66 +6,70 @@
#include <QHash>
#include <QObject>
#include <QVariant>
#include "serializable_item.h"
#include <QPair>
#include <google/protobuf/message.h>
#include "pb/server_message.pb.h"
class QXmlStreamReader;
class QXmlStreamWriter;
class QXmlStreamAttributes;
class ProtocolResponse;
class DeckList;
class GameEvent;
class GameEventContainer;
class GameEventContext;
class MoveCardToZone;
class ProtocolItem : public SerializableItem_Map {
Q_OBJECT
private:
bool receiverMayDelete;
static const int protocolVersion = 13;
class GameEventStorageItem {
public:
static const int protocolVersion = 13;
virtual int getItemId() const = 0;
bool getReceiverMayDelete() const { return receiverMayDelete; }
void setReceiverMayDelete(bool _receiverMayDelete) { receiverMayDelete = _receiverMayDelete; }
ProtocolItem(const QString &_itemType, const QString &_itemSubType);
bool isEmpty() const { return false; }
enum EventRecipient { SendToPrivate = 0x01, SendToOthers = 0x02};
Q_DECLARE_FLAGS(EventRecipients, EventRecipient)
private:
::google::protobuf::Message *event;
int playerId;
EventRecipients recipients;
public:
GameEventStorageItem(const ::google::protobuf::Message &_event, int _playerId, EventRecipients _recipients)
: event(_event.New()), playerId(_playerId), recipients(_recipients)
{
event->CopyFrom(_event);
}
~GameEventStorageItem()
{
delete event;
}
const ::google::protobuf::Message &getEvent() const { return *event; }
int getPlayerId() const { return playerId; }
EventRecipients getRecipients() const { return recipients; }
};
// ----------------
// --- COMMANDS ---
// ----------------
Q_DECLARE_OPERATORS_FOR_FLAGS(GameEventStorageItem::EventRecipients)
class GameEventStorage {
private:
::google::protobuf::Message *gameEventContext;
GameEventContainer *gameEventQueuePublic;
GameEventContainer *gameEventQueueOmniscient;
GameEventContainer *gameEventQueuePrivate;
QList<GameEventStorageItem *> gameEventList;
int privatePlayerId;
public:
GameEventStorage();
~GameEventStorage();
GameEventStorage()
: gameEventContext(0)
{
}
~GameEventStorage()
{
delete gameEventContext;
for (int i = 0; i < gameEventList.size(); ++i)
delete gameEventList[i];
}
void setGameEventContext(::google::protobuf::Message *_gameEventContext) { gameEventContext = _gameEventContext; }
::google::protobuf::Message *getGameEventContext() const { return gameEventContext; }
GameEventContainer *getGameEventQueuePublic() const { return gameEventQueuePublic; }
void enqueueGameEventPublic(const ::google::protobuf::Message &event, int playerId);
GameEventContainer *getGameEventQueueOmniscient() const { return gameEventQueueOmniscient; }
void enqueueGameEventOmniscient(const ::google::protobuf::Message &event, int playerId);
GameEventContainer *getGameEventQueuePrivate() const { return gameEventQueuePrivate; }
void enqueueGameEventPrivate(const ::google::protobuf::Message &event, int playerId);
// XXX - DRAN DENKEN, dass privatePlayerId gesetzt wird
int getPrivatePlayerId() const { return privatePlayerId; }
void enqueueGameEvent(const ::google::protobuf::Message &event, int playerId);
void enqueueGameEvent(const ::google::protobuf::Message &event, int playerId, GameEventStorageItem::EventRecipients recipients = GameEventStorageItem::SendToPrivate | GameEventStorageItem::SendToOthers, int _privatePlayerId = -1)
{
gameEventList.append(new GameEventStorageItem(event, playerId, recipients));
if (_privatePlayerId != -1)
privatePlayerId = _privatePlayerId;
}
};
class ResponseContainer {
@ -74,7 +78,14 @@ private:
QList<QPair<ServerMessage::MessageType, ::google::protobuf::Message *> > preResponseQueue, postResponseQueue;
public:
ResponseContainer() : responseExtension(0) { }
~ResponseContainer() { /* XXX responseExtension und Inhalt beider Listen löschen */ }
~ResponseContainer()
{
delete responseExtension;
for (int i = 0; i < preResponseQueue.size(); ++i)
delete preResponseQueue[i].second;
for (int i = 0; i < postResponseQueue.size(); ++i)
delete postResponseQueue[i].second;
}
void setResponseExtension(::google::protobuf::Message *_responseExtension) { responseExtension = _responseExtension; }
::google::protobuf::Message *getResponseExtension() const { return responseExtension; }
void enqueuePreResponseItem(ServerMessage::MessageType type, ::google::protobuf::Message *item) { preResponseQueue.append(qMakePair(type, item)); }

View file

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

View file

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

View file

@ -26,7 +26,7 @@
#include "server_game.h"
#include "pb/command_move_card.pb.h"
Server_CardZone::Server_CardZone(Server_Player *_player, const QString &_name, bool _has_coords, ZoneType _type)
Server_CardZone::Server_CardZone(Server_Player *_player, const QString &_name, bool _has_coords, ServerInfo_Zone::ZoneType _type)
: player(_player), name(_name), has_coords(_has_coords), type(_type), cardsBeingLookedAt(0)
{
}
@ -62,7 +62,7 @@ Server_Card *Server_CardZone::getCard(int id, int *position)
{
QMutexLocker locker(&player->getGame()->gameMutex);
if (type != HiddenZone) {
if (type != ServerInfo_Zone::HiddenZone) {
QListIterator<Server_Card *> CardIterator(cards);
int i = 0;
while (CardIterator.hasNext()) {
@ -160,7 +160,7 @@ bool Server_CardZone::isColumnEmpty(int x, int y) const
return !coordMap.contains((x / 3) * 3);
}
void Server_CardZone::moveCard(BlaContainer *bla, QMap<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);
@ -168,13 +168,13 @@ void Server_CardZone::moveCard(BlaContainer *bla, QMap<int, Server_Card *> &coor
CardToMove *cardToMove = new CardToMove;
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;
coordMap.insert(y * 10000 + x, card);
}
void Server_CardZone::fixFreeSpaces(BlaContainer *bla)
void Server_CardZone::fixFreeSpaces(GameEventStorage &ges)
{
QMutexLocker locker(&player->getGame()->gameMutex);
@ -193,15 +193,15 @@ void Server_CardZone::fixFreeSpaces(BlaContainer *bla)
if (!coordMap.contains(y * 10000 + baseX)) {
if (coordMap.contains(y * 10000 + baseX + 1))
moveCard(bla, coordMap, coordMap.value(y * 10000 + baseX + 1), baseX, y);
moveCard(ges, coordMap, coordMap.value(y * 10000 + baseX + 1), baseX, y);
else if (coordMap.contains(y * 10000 + baseX + 2)) {
moveCard(bla, coordMap, coordMap.value(y * 10000 + baseX + 2), baseX, y);
moveCard(ges, coordMap, coordMap.value(y * 10000 + baseX + 2), baseX, y);
continue;
} else
continue;
}
if (!coordMap.contains(y * 10000 + baseX + 1) && coordMap.contains(y * 10000 + baseX + 2))
moveCard(bla, coordMap, coordMap.value(y * 10000 + baseX + 2), baseX + 1, y);
moveCard(ges, coordMap, coordMap.value(y * 10000 + baseX + 2), baseX + 1, y);
}
}

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -77,6 +77,7 @@
#include "pb/event_set_counter.pb.h"
#include "pb/event_dump_zone.pb.h"
#include "pb/event_stop_dump_zone.pb.h"
#include "pb/event_reveal_cards.pb.h"
#include "pb/context_deck_select.pb.h"
#include "pb/context_concede.pb.h"
#include "pb/context_ready_start.pb.h"
@ -124,12 +125,25 @@ void Server_ProtocolHandler::prepareDestroy()
gameListMutex.unlock();
delete userInfo;
QMapIterator<QString, ServerInfo_User *> i(buddyList);
while (i.hasNext())
delete i.next().value();
QMapIterator<QString, ServerInfo_User *> j(ignoreList);
while (j.hasNext())
delete j.next().value();
}
void Server_ProtocolHandler::setUserInfo(const ServerInfo_User &_userInfo)
{
userInfo = new ServerInfo_User;
userInfo->CopyFrom(_userInfo);
}
ServerInfo_User Server_ProtocolHandler::copyUserInfo(bool complete, bool moderatorInfo) const
{
ServerInfo_User result;
if (userInfo) {
result.CopyFrom(*userInfo);
if (!moderatorInfo)
result.clear_address();
if (!complete)
result.clear_avatar_bmp();
}
return result;
}
void Server_ProtocolHandler::playerRemovedFromGame(Server_Game *game)
@ -186,6 +200,13 @@ void Server_ProtocolHandler::sendProtocolItem(ServerMessage::MessageType type, c
}
}
SessionEvent *Server_ProtocolHandler::prepareSessionEvent(const ::google::protobuf::Message &sessionEvent)
{
SessionEvent *event = new SessionEvent;
event->GetReflection()->MutableMessage(event, sessionEvent.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(sessionEvent);
return event;
}
Response::ResponseCode Server_ProtocolHandler::processSessionCommandContainer(const CommandContainer &cont, ResponseContainer &rc)
{
Response::ResponseCode finalResponseCode = Response::RespOk;
@ -499,19 +520,14 @@ Response::ResponseCode Server_ProtocolHandler::cmdLogin(const Command_Login &cmd
// XXX stimmt so nicht, beim alten Kopierkonstruktor wurde hier "true" übergeben
re->mutable_user_info()->CopyFrom(*userInfo);
QList<ServerInfo_User *> _buddyList, _ignoreList;
if (authState == PasswordRight) {
buddyList = server->getBuddyList(userName);
QMapIterator<QString, ServerInfo_User *> buddyIterator(buddyList);
QMapIterator<QString, ServerInfo_User> buddyIterator(server->getBuddyList(userName));
while (buddyIterator.hasNext())
re->add_buddy_list()->CopyFrom(*buddyIterator.next().value());
re->add_buddy_list()->CopyFrom(buddyIterator.next().value());
ignoreList = server->getIgnoreList(userName);
QMapIterator<QString, ServerInfo_User *> ignoreIterator(ignoreList);
QMapIterator<QString, ServerInfo_User> ignoreIterator(server->getIgnoreList(userName));
while (ignoreIterator.hasNext())
re->add_ignore_list()->CopyFrom(*ignoreIterator.next().value());
re->add_ignore_list()->CopyFrom(ignoreIterator.next().value());
}
server->serverMutex.lock();
@ -573,7 +589,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdMessage(const Command_Message
Server_ProtocolHandler *userHandler = server->getUsers().value(receiver);
if (!userHandler)
return Response::RespNameNotFound;
if (userHandler->getIgnoreList().contains(getUserName()))
if (server->isInIgnoreList(receiver, QString::fromStdString(userInfo->name())))
return Response::RespInIgnoreList;
Event_UserMessage event;
@ -856,7 +872,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdDeckSelect(const Command_DeckS
Event_PlayerPropertiesChanged event;
event.mutable_player_properties()->CopyFrom(player->getProperties());
ges.enqueueGameEventPublic(event, player->getPlayerId());
ges.enqueueGameEvent(event, player->getPlayerId());
Context_DeckSelect *context = new Context_DeckSelect;
context->set_deck_hash(deck->getDeckHash().toStdString());
@ -907,7 +923,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdConcede(const Command_Concede
Event_PlayerPropertiesChanged event;
event.mutable_player_properties()->CopyFrom(player->getProperties());
ges.enqueueGameEventPublic(event, player->getPlayerId());
ges.enqueueGameEvent(event, player->getPlayerId());
ges.setGameEventContext(new Context_Concede());
game->stopGameIfFinished();
@ -932,7 +948,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdReadyStart(const Command_Ready
Event_PlayerPropertiesChanged event;
event.mutable_player_properties()->CopyFrom(player->getProperties());
ges.enqueueGameEventPublic(event, player->getPlayerId());
ges.enqueueGameEvent(event, player->getPlayerId());
ges.setGameEventContext(new Context_ReadyStart());
game->startGameIfReady();
@ -946,7 +962,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdGameSay(const Command_GameSay
Event_GameSay event;
event.set_message(cmd.message());
ges.enqueueGameEventPublic(event, player->getPlayerId());
ges.enqueueGameEvent(event, player->getPlayerId());
return Response::RespOk;
}
@ -963,7 +979,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdShuffle(const Command_Shuffle
player->getZones().value("deck")->shuffle();
ges.enqueueGameEventPublic(Event_Shuffle(), player->getPlayerId());
ges.enqueueGameEvent(Event_Shuffle(), player->getPlayerId());
return Response::RespOk;
}
@ -1630,7 +1646,7 @@ Response::ResponseCode Server_ProtocolHandler::cmdStopDumpZone(const Command_Sto
return Response::RespOk;
}
Response::ResponseCode Server_ProtocolHandler::cmdRevealCards(const Command_RevealCards &cmd, Server_Game *game, Server_Player *player, ResponseContainer &rc, GameEventStorage &ges)
Response::ResponseCode Server_ProtocolHandler::cmdRevealCards(const Command_RevealCards &cmd, Server_Game *game, Server_Player *player, ResponseContainer & /*rc*/, GameEventStorage &ges)
{
if (player->getSpectator())
return Response::RespFunctionNotAllowed;
@ -1664,39 +1680,54 @@ Response::ResponseCode Server_ProtocolHandler::cmdRevealCards(const Command_Reve
cardsToReveal.append(card);
}
Event_RevealCards eventOthers;
eventOthers.set_zone_name(zone->getName().toStdString());
if (cmd.has_card_id())
eventOthers.set_card_id(cmd.card_id());
if (cmd.has_player_id())
eventOthers.set_other_player_id(cmd.player_id());
Event_RevealCards eventPrivate(eventOthers);
QList<ServerInfo_Card *> respCardListPrivate, respCardListOmniscient;
for (int i = 0; i < cardsToReveal.size(); ++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());
while (cardCounterIterator.hasNext()) {
cardCounterIterator.next();
cardCounterListPrivate.append(new ServerInfo_CardCounter(cardCounterIterator.key(), cardCounterIterator.value()));
cardCounterListOmniscient.append(new ServerInfo_CardCounter(cardCounterIterator.key(), cardCounterIterator.value()));
ServerInfo_CardCounter *counterInfo = cardInfo->add_counter_list();
counterInfo->set_id(cardCounterIterator.key());
counterInfo->set_value(cardCounterIterator.value());
}
int attachPlayerId = -1;
QString attachZone;
int attachCardId = -1;
if (card->getParentCard()) {
attachPlayerId = card->getParentCard()->getZone()->getPlayer()->getPlayerId();
attachZone = card->getParentCard()->getZone()->getName();
attachCardId = card->getParentCard()->getId();
cardInfo->set_attach_player_id(card->getParentCard()->getZone()->getPlayer()->getPlayerId());
cardInfo->set_attach_zone(card->getParentCard()->getZone()->getName().toStdString());
cardInfo->set_attach_card_id(card->getParentCard()->getId());
}
if (cmd.has_player_id())
respCardListPrivate.append(new ServerInfo_Card(card->getId(), card->getName(), card->getX(), card->getY(), card->getFaceDown(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), card->getDoesntUntap(), cardCounterListPrivate, attachPlayerId, attachZone, attachCardId));
respCardListOmniscient.append(new ServerInfo_Card(card->getId(), card->getName(), card->getX(), card->getY(), card->getFaceDown(), card->getTapped(), card->getAttacking(), card->getColor(), card->getPT(), card->getAnnotation(), card->getDestroyOnZoneChange(), card->getDoesntUntap(), cardCounterListOmniscient, attachPlayerId, attachZone, attachCardId));
}
if (!cmd.has_player_id())
bla->enqueueGameEventPublic(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd.card_id(), -1, respCardListOmniscient), game->getGameId());
else {
bla->enqueueGameEventPublic(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd.card_id(), otherPlayer->getPlayerId()), game->getGameId());
bla->enqueueGameEventPrivate(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd.card_id(), otherPlayer->getPlayerId(), respCardListPrivate), game->getGameId(), otherPlayer->getPlayerId());
bla->enqueueGameEventOmniscient(new Event_RevealCards(player->getPlayerId(), zone->getName(), cmd.card_id(), otherPlayer->getPlayerId(), respCardListOmniscient), game->getGameId());
}
if (cmd.has_player_id()) {
ges.enqueueGameEvent(eventPrivate, player->getPlayerId(), GameEventStorageItem::SendToPrivate, cmd.player_id());
ges.enqueueGameEvent(eventOthers, player->getPlayerId(), GameEventStorageItem::SendToOthers);
} else
ges.enqueueGameEvent(eventPrivate, player->getPlayerId());
return Response::RespOk;
}

View file

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

View file

@ -3,6 +3,12 @@
#include "server_game.h"
#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)
: 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());
}
ServerInfo_Room *Server_Room::getInfo(bool complete, bool showGameTypes) const
ServerInfo_Room Server_Room::getInfo(bool complete, bool showGameTypes) const
{
QMutexLocker locker(&roomMutex);
QList<ServerInfo_Game *> gameList;
QList<ServerInfo_User *> userList;
QList<ServerInfo_GameType *> gameTypeList;
ServerInfo_Room result;
result.set_room_id(id);
result.set_name(name.toStdString());
result.set_description(description.toStdString());
result.set_game_count(games.size());
result.set_player_count(size());
result.set_auto_join(autoJoin);
if (complete) {
QMapIterator<int, Server_Game *> gameIterator(games);
while (gameIterator.hasNext())
gameList.append(gameIterator.next().value()->getInfo());
result.add_game_list()->CopyFrom(gameIterator.next().value()->getInfo());
for (int i = 0; i < size(); ++i)
userList.append(new ServerInfo_User(at(i)->getUserInfo(), false));
result.add_user_list()->CopyFrom(at(i)->copyUserInfo(false));
}
if (complete || showGameTypes)
for (int i = 0; i < gameTypes.size(); ++i)
gameTypeList.append(new ServerInfo_GameType(i, gameTypes[i]));
for (int i = 0; i < gameTypes.size(); ++i) {
ServerInfo_GameType *gameTypeInfo = result.add_gametype_list();
gameTypeInfo->set_game_type_id(i);
gameTypeInfo->set_description(gameTypes[i].toStdString());
}
return new ServerInfo_Room(id, name, description, games.size(), size(), autoJoin, gameList, userList, gameTypeList);
return result;
}
RoomEvent *Server_Room::prepareRoomEvent(const ::google::protobuf::Message &roomEvent)
{
RoomEvent *event = new RoomEvent;
event->set_room_id(id);
event->GetReflection()->MutableMessage(event, roomEvent.GetDescriptor()->FindExtensionByName("ext"))->CopyFrom(roomEvent);
return event;
}
void Server_Room::addClient(Server_ProtocolHandler *client)
{
QMutexLocker locker(&roomMutex);
sendRoomEvent(new Event_JoinRoom(id, new ServerInfo_User(client->getUserInfo(), false)));
Event_JoinRoom event;
event.mutable_user_info()->CopyFrom(client->copyUserInfo(false));
sendRoomEvent(prepareRoomEvent(event));
append(client);
emit roomInfoChanged();
}
@ -62,13 +87,20 @@ void Server_Room::removeClient(Server_ProtocolHandler *client)
QMutexLocker locker(&roomMutex);
removeAt(indexOf(client));
sendRoomEvent(new Event_LeaveRoom(id, client->getUserInfo()->getName()));
Event_LeaveRoom event;
event.set_name(client->getUserInfo()->name());
sendRoomEvent(prepareRoomEvent(event));
emit roomInfoChanged();
}
void Server_Room::say(Server_ProtocolHandler *client, const QString &s)
{
sendRoomEvent(new Event_RoomSay(id, client->getUserInfo()->getName(), s));
Event_RoomSay event;
event.set_name(client->getUserInfo()->name());
event.set_message(s.toStdString());
sendRoomEvent(prepareRoomEvent(event));
}
void Server_Room::sendRoomEvent(RoomEvent *event)
@ -76,7 +108,7 @@ void Server_Room::sendRoomEvent(RoomEvent *event)
QMutexLocker locker(&roomMutex);
for (int i = 0; i < size(); ++i)
at(i)->sendProtocolItem(event, false);
at(i)->sendProtocolItem(*event);
delete event;
}
@ -84,11 +116,9 @@ void Server_Room::broadcastGameListUpdate(Server_Game *game)
{
QMutexLocker locker(&roomMutex);
Event_ListGames *event = new Event_ListGames(id, QList<ServerInfo_Game *>() << game->getInfo());
for (int i = 0; i < size(); i++)
at(i)->sendProtocolItem(event, false);
delete event;
Event_ListGames event;
event.add_game_list()->CopyFrom(game->getInfo());
sendRoomEvent(prepareRoomEvent(event));
}
Server_Game *Server_Room::createGame(const QString &description, const QString &password, int maxPlayers, const QList<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);
int result = 0;
while (gamesIterator.hasNext())
if (gamesIterator.next().value()->getCreatorInfo()->getName() == userName)
if (gamesIterator.next().value()->getCreatorInfo()->name() == userName.toStdString())
++result;
return result;
}
QList<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);
while (gamesIterator.hasNext()) {
Server_Game *game = gamesIterator.next().value();

View file

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

View file

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

View file

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

View file

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

View file

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