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

dynamic compression support

parent cc795a2d
......@@ -21,12 +21,13 @@ private:
ResponseCode cmdBanFromServer(Command_BanFromServer * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; }
ResponseCode cmdShutdownServer(Command_ShutdownServer * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; }
ResponseCode cmdUpdateServerMessage(Command_UpdateServerMessage * /*cmd*/, CommandContainer * /*cont*/) { return RespFunctionNotAllowed; }
protected:
bool getCompressionSupport() const { return false; }
public:
LocalServerInterface(LocalServer *_server);
~LocalServerInterface();
void sendProtocolItem(ProtocolItem *item, bool deleteItem = true);
signals:
void itemToClient(ProtocolItem *item);
public slots:
......
......@@ -83,6 +83,7 @@ void RemoteClient::readData()
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 *)));
......
......@@ -74,7 +74,7 @@ TopLevelProtocolItem::TopLevelProtocolItem()
bool TopLevelProtocolItem::readCurrentItem(QXmlStreamReader *xml)
{
if (currentItem) {
if (currentItem->readElement(xml)) {
if (currentItem->read(xml)) {
emit protocolItemReceived(currentItem);
currentItem = 0;
}
......@@ -92,6 +92,8 @@ bool TopLevelProtocolItem::readElement(QXmlStreamReader *xml)
currentItem = dynamic_cast<ProtocolItem *>(getNewItem(childName + childSubType));
if (!currentItem)
currentItem = new ProtocolItem_Invalid;
if (xml->attributes().value("comp").toString().toInt() == 1)
currentItem->setCompressed(true);
readCurrentItem(xml);
}
......
#include "serializable_item.h"
#include <QXmlStreamReader>
#include <QXmlStreamWriter>
#include <QDebug>
#include <QBuffer>
QHash<QString, SerializableItem::NewItemFunction> SerializableItem::itemNameHash;
SerializableItem *SerializableItem::getNewItem(const QString &name)
......@@ -16,6 +17,32 @@ void SerializableItem::registerSerializableItem(const QString &name, NewItemFunc
itemNameHash.insert(name, func);
}
bool SerializableItem::read(QXmlStreamReader *xml)
{
if (!compressed)
return readElement(xml);
if (xml->isEndElement() && (xml->name() == itemType)) {
QByteArray uncompressedData = "<d>" + qUncompress(QByteArray::fromBase64(compressedData)) + "</d>";
compressedData.clear();
QBuffer compressedBuffer(&uncompressedData);
compressedBuffer.open(QIODevice::ReadOnly);
QXmlStreamReader *xml2 = new QXmlStreamReader(&compressedBuffer);
while (!xml2->atEnd()) {
xml2->readNext();
if (xml2->name() == "d")
continue;
readElement(xml2);
}
delete xml2;
compressedBuffer.close();
return readElement(xml);
} else {
compressedData.append(xml->text().toString());
return false;
}
}
bool SerializableItem::readElement(QXmlStreamReader *xml)
{
if (xml->isEndElement() && (xml->name() == itemType))
......@@ -31,7 +58,19 @@ void SerializableItem::write(QXmlStreamWriter *xml)
xml->writeStartElement(itemType);
if (!itemSubType.isEmpty())
xml->writeAttribute("type", itemSubType);
writeElement(xml);
if (compressed) {
xml->writeAttribute("comp", "1");
QBuffer compressBuffer;
compressBuffer.open(QIODevice::WriteOnly);
QXmlStreamWriter *xml2 = new QXmlStreamWriter(&compressBuffer);
writeElement(xml2);
delete xml2;
compressBuffer.close();
xml->writeCharacters(qCompress(compressBuffer.data()).toBase64());
} else
writeElement(xml);
xml->writeEndElement();
}
......@@ -47,7 +86,7 @@ SerializableItem_Map::~SerializableItem_Map()
bool SerializableItem_Map::readElement(QXmlStreamReader *xml)
{
if (currentItem) {
if (currentItem->readElement(xml))
if (currentItem->read(xml))
currentItem = 0;
return false;
} else if (firstItem)
......@@ -57,6 +96,7 @@ bool SerializableItem_Map::readElement(QXmlStreamReader *xml)
else if (xml->isStartElement()) {
QString childName = xml->name().toString();
QString childSubType = xml->attributes().value("type").toString();
bool childCompressed = xml->attributes().value("comp").toString().toInt() == 1;
currentItem = itemMap.value(childName);
if (!currentItem) {
currentItem = getNewItem(childName + childSubType);
......@@ -64,7 +104,8 @@ bool SerializableItem_Map::readElement(QXmlStreamReader *xml)
if (!currentItem)
currentItem = new SerializableItem_Invalid(childName);
}
if (currentItem->readElement(xml))
currentItem->setCompressed(childCompressed);
if (currentItem->read(xml))
currentItem = 0;
}
return SerializableItem::readElement(xml);
......
......@@ -15,6 +15,10 @@ class QXmlStreamWriter;
class SerializableItem : public QObject {
Q_OBJECT
private:
bool compressed;
QByteArray compressedData;
QXmlStreamReader *compressedReader;
protected:
typedef SerializableItem *(*NewItemFunction)();
static QHash<QString, NewItemFunction> itemNameHash;
......@@ -23,7 +27,7 @@ protected:
bool firstItem;
public:
SerializableItem(const QString &_itemType, const QString &_itemSubType = QString())
: QObject(), itemType(_itemType), itemSubType(_itemSubType), firstItem(true) { }
: QObject(), compressed(false), itemType(_itemType), itemSubType(_itemSubType), firstItem(true) { }
static void registerSerializableItem(const QString &name, NewItemFunction func);
static SerializableItem *getNewItem(const QString &name);
const QString &getItemType() const { return itemType; }
......@@ -31,6 +35,8 @@ public:
virtual bool readElement(QXmlStreamReader *xml);
virtual void writeElement(QXmlStreamWriter *xml) = 0;
virtual bool isEmpty() const = 0;
void setCompressed(bool _compressed) { compressed = _compressed; }
bool read(QXmlStreamReader *xml);
void write(QXmlStreamWriter *xml);
};
......
......@@ -286,7 +286,10 @@ ResponseCode Server_ProtocolHandler::cmdLogin(Command_Login *cmd, CommandContain
if (authState == WouldOverwriteOldSession)
return RespWouldOverwriteOldSession;
enqueueProtocolItem(new Event_ServerMessage(server->getLoginMessage()));
ProtocolItem *serverMessage = new Event_ServerMessage(server->getLoginMessage());
if (getCompressionSupport())
serverMessage->setCompressed(true);
enqueueProtocolItem(serverMessage);
QList<ServerInfo_User *> _buddyList, _ignoreList;
if (authState == PasswordRight) {
......@@ -303,7 +306,10 @@ ResponseCode Server_ProtocolHandler::cmdLogin(Command_Login *cmd, CommandContain
_ignoreList.append(new ServerInfo_User(ignoreIterator.next().value()));
}
cont->setResponse(new Response_Login(cont->getCmdId(), RespOk, new ServerInfo_User(userInfo, true), _buddyList, _ignoreList));
ProtocolResponse *resp = new Response_Login(cont->getCmdId(), RespOk, new ServerInfo_User(userInfo, true), _buddyList, _ignoreList);
if (getCompressionSupport())
resp->setCompressed(true);
cont->setResponse(resp);
return RespNothing;
}
......@@ -395,7 +401,10 @@ ResponseCode Server_ProtocolHandler::cmdJoinRoom(Command_JoinRoom *cmd, CommandC
}
}
cont->setResponse(new Response_JoinRoom(cont->getCmdId(), RespOk, r->getInfo(true)));
ServerInfo_Room *info = r->getInfo(true);
if (getCompressionSupport())
info->setCompressed(true);
cont->setResponse(new Response_JoinRoom(cont->getCmdId(), RespOk, info));
return RespNothing;
}
......@@ -444,7 +453,10 @@ ResponseCode Server_ProtocolHandler::cmdListUsers(Command_ListUsers * /*cmd*/, C
acceptsUserListChanges = true;
cont->setResponse(new Response_ListUsers(cont->getCmdId(), RespOk, resultList));
ProtocolResponse *resp = new Response_ListUsers(cont->getCmdId(), RespOk, resultList);
if (getCompressionSupport())
resp->setCompressed(true);
cont->setResponse(resp);
return RespNothing;
}
......
......@@ -30,6 +30,7 @@ protected:
QMap<QString, ServerInfo_User *> buddyList, ignoreList;
void prepareDestroy();
virtual bool getCompressionSupport() const = 0;
private:
QList<ProtocolItem *> itemQueue;
QList<int> messageSizeOverTime, messageCountOverTime;
......
......@@ -33,7 +33,7 @@
#include "server_logger.h"
ServerSocketInterface::ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent)
: Server_ProtocolHandler(_server, parent), servatrice(_server), socket(_socket), topLevelItem(0)
: Server_ProtocolHandler(_server, parent), servatrice(_server), socket(_socket), topLevelItem(0), compressionSupport(false)
{
xmlWriter = new QXmlStreamWriter(&xmlBuffer);
xmlReader = new QXmlStreamReader;
......@@ -101,6 +101,8 @@ void ServerSocketInterface::readClient()
if (topLevelItem)
topLevelItem->readElement(xmlReader);
else if (xmlReader->isStartElement() && (xmlReader->name().toString() == "cockatrice_client_stream")) {
if (xmlReader->attributes().value("comp").toString().toInt() == 1)
compressionSupport = true;
topLevelItem = new TopLevelProtocolItem;
connect(topLevelItem, SIGNAL(protocolItemReceived(ProtocolItem *)), this, SLOT(processProtocolItem(ProtocolItem *)));
}
......@@ -295,7 +297,10 @@ ResponseCode ServerSocketInterface::cmdDeckList(Command_DeckList * /*cmd*/, Comm
if (!deckListHelper(root))
return RespContextError;
cont->setResponse(new Response_DeckList(cont->getCmdId(), RespOk, root));
ProtocolResponse *resp = new Response_DeckList(cont->getCmdId(), RespOk, root);
if (getCompressionSupport())
resp->setCompressed(true);
cont->setResponse(resp);
return RespNothing;
}
......
......@@ -51,6 +51,7 @@ private:
QXmlStreamReader *xmlReader;
QString xmlBuffer;
TopLevelProtocolItem *topLevelItem;
bool compressionSupport;
int getUserIdInDB(const QString &name) const;
ResponseCode cmdAddToList(Command_AddToList *cmd, CommandContainer *cont);
......@@ -69,6 +70,8 @@ private:
ResponseCode cmdBanFromServer(Command_BanFromServer *cmd, CommandContainer *cont);
ResponseCode cmdShutdownServer(Command_ShutdownServer *cmd, CommandContainer *cont);
ResponseCode cmdUpdateServerMessage(Command_UpdateServerMessage *cmd, CommandContainer *cont);
protected:
bool getCompressionSupport() const { return compressionSupport; }
public:
ServerSocketInterface(Servatrice *_server, QTcpSocket *_socket, QObject *parent = 0);
~ServerSocketInterface();
......
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