Commit d3b96b1a authored by Max-Wilhelm Bruker's avatar Max-Wilhelm Bruker
Browse files

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

parent 10018280
message SessionEvent {
enum SessionEventType {
SERVER_IDENTIFICATION = 500;
SERVER_MESSAGE = 1000;
SERVER_SHUTDOWN = 1001;
CONNECTION_CLOSED = 1002;
......
#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")
......
......@@ -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
static const int protocolVersion = 13;
class GameEventStorageItem {
public:
enum EventRecipient { SendToPrivate = 0x01, SendToOthers = 0x02};
Q_DECLARE_FLAGS(EventRecipients, EventRecipient)
private:
bool receiverMayDelete;
::google::protobuf::Message *event;
int playerId;
EventRecipients recipients;
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; }
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)); }
......
......@@ -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)
......
......@@ -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;
......
......@@ -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);
}
}
......
......@@ -22,6 +22,7 @@
#include <QList>
#include <QString>
#include <QMap>
#include "pb/serverinfo_zone.pb.h"
class Server_Card;
......
This diff is collapsed.
......@@ -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
......@@ -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);
}
......@@ -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
......@@ -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];
QList<ServerInfo_CardCounter *> cardCounterListPrivate, cardCounterListOmniscient;
ServerInfo_Card *cardInfo = eventPrivate.add_cards();
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;
}
......@@ -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
......@@ -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();
......
......@@ -2,6 +2,7 @@
port=4747
statusupdate=15000
logfile=server.log
name="My Cockatrice server"
id=1
threaded=0
......
......@@ -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();
......
......@@ -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;
......
......@@ -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)
{
QMutexLocker locker(&xmlBufferMutex);
item->write(xmlWriter);
if (deleteItem)
delete item;
emit xmlBufferChanged();
}
int ServerSocketInterface::getUserIdInDB(const QString &name) const
void ServerSocketInterface::transmitProtocolItem(const ServerMessage &item)
{
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();
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);
QMutexLocker locker(&outputBufferMutex);
outputBuffer.append(buf);
emit outputBufferChanged();
}
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;
int id1 = getUserIdInDB(userInfo->getName());
int id2 = getUserIdInDB(user);
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 = 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;
if ((list == "buddy") && !buddyList.contains(user))
return RespContextError;
if ((list == "ignore") && !ignoreList.contains(user))
return RespContextError;
return Response::RespContextError;
int id1 = getUserIdInDB(userInfo->getName());
int id2 = getUserIdInDB(user);
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 = 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;
if (list == "buddy") {
delete buddyList.value(user);
buddyList.remove(user);
} else if (list == "ignore") {
delete ignoreList.value(user);
ignoreList.remove(user);
}
return Response::RespInternalError;
bla->enqueueItem(new Event_RemoveFromList(list, user));
return RespOk;
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);
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;
}
......@@ -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
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment