Change Hdata from QObject to QVariantHash, combine all parsing to WCPH

This commit is contained in:
Mikko Ahlroth 2014-07-06 23:04:16 +03:00
parent 4a9eeb850b
commit 56d7c58ac0
5 changed files with 230 additions and 141 deletions

View file

@ -17,7 +17,6 @@ SOURCES += src/harbour-weechatrelay.cpp \
src/weechatprotocolhandler.cpp \
src/protocolhandler.cpp \
src/qsslcertificateinfo.cpp \
src/weechat/hdata.cpp \
src/weechat/dynamictypeexception.cpp
OTHER_FILES += qml/harbour-weechatrelay.qml \
@ -44,7 +43,6 @@ HEADERS += \
src/weechatprotocolhandler.h \
src/connectresolver.h \
src/qsslcertificateinfo.h \
src/weechat/hdata.h \
src/weechat/dynamictypeexception.h
QT += network

View file

@ -1,6 +0,0 @@
#include "hdata.h"
Hdata::Hdata(QObject *parent) :
QObject(parent)
{
}

View file

@ -1,18 +0,0 @@
#ifndef HDATA_H
#define HDATA_H
#include <QObject>
class Hdata : public QObject
{
Q_OBJECT
public:
explicit Hdata(QObject *parent = 0);
signals:
public slots:
};
#endif // HDATA_H

View file

@ -6,6 +6,9 @@
#include <QDebug>
#include <QDataStream>
#include <QQmlEngine>
#include <QStringList>
#include <QJsonDocument>
#include "weechatprotocolhandler.h"
#include "weechat/dynamictypeexception.h"
@ -25,90 +28,7 @@ void WeeChatProtocolHandler::initialize(QString password)
}
// Handle incoming data from the socket and emit the appropriate signals
void WeeChatProtocolHandler::handleNewData(RelayConnection* connection)
{
// If we cannot read the amount of bytes we want, skip and retry next time
if (connection->bytesAvailable() < bytesNeeded)
{
qDebug() << connection->bytesAvailable() << " was lower than " << bytesNeeded << "... Skipping.";
return;
}
QDataStream* data = read(connection, bytesNeeded);
if (!readingBody)
{
// The header contains the length of the message and compression specifier
quint32 length;
quint8 compression;
(*data) >> length;
(*data) >> compression;
qDebug() << length << " " << compression;
// The length includes the header
readingBody = true;
bytesNeeded = length - HEADER_BYTES;
}
else
{
handleBody(data);
readingBody = false;
bytesNeeded = HEADER_BYTES;
}
delete data;
data = 0;
emit debugData("");
}
void WeeChatProtocolHandler::sendDebugData(QString string)
{
emitData(string);
}
void WeeChatProtocolHandler::emitData(QString data)
{
ProtocolHandler::emitData(data + "\n");
}
void WeeChatProtocolHandler::handleBody(QDataStream* data)
{
// The first element is the id which will affect how we interpret the rest
char* idData = 0;
(*data) >> idData;
qDebug() << "Id: " << idData;
QString id(idData);
if (id == "_buffer_line_added")
{
handleBufferLineAdded(data);
}
delete idData;
}
// EVENTS
void WeeChatProtocolHandler::handleBufferLineAdded(QDataStream* data)
{
}
void WeeChatProtocolHandler::handleUnknown(QDataStream* data)
{
}
// TYPES
// INDIVIDUAL OBJECT TYPES
QVariant WeeChatProtocolHandler::handleDynamicType(Type type, QDataStream* data)
{
@ -247,7 +167,7 @@ QString WeeChatProtocolHandler::handlePointer(QDataStream* data)
ret.append(static_cast<char>(current));
}
return ret;
return ret.prepend("0x");
}
QDateTime WeeChatProtocolHandler::handleTime(QDataStream* data)
@ -259,9 +179,9 @@ QDateTime WeeChatProtocolHandler::handleTime(QDataStream* data)
return ret.fromMSecsSinceEpoch(timestamp);
}
QHash<QString, QVariant> WeeChatProtocolHandler::handleHashTable(QDataStream* data)
QVariantHash WeeChatProtocolHandler::handleHashTable(QDataStream* data)
{
QHash<QString, QVariant> ret;
QVariantHash ret;
// The hashtable first contains the types for the key and value
Type keyType = readType(data);
@ -285,21 +205,84 @@ QHash<QString, QVariant> WeeChatProtocolHandler::handleHashTable(QDataStream* da
return ret;
}
std::pair<QString, QString> WeeChatProtocolHandler::handleInfo(QDataStream* data)
QVariantHash WeeChatProtocolHandler::handleHdata(QDataStream* data)
{
/*
* A Hdata consists of:
* H-path, a string giving the path to the data
* Keys, a dict of keys and their types (in a string, comma separated)
* Integer count of object sets
* N object sets which themselves consist of:
* * P-path, list of pointers to objects (the same amount as the amount
* of parts in H-path
* * List of objects, with the same keys and types as defined in Keys
*/
QVariantHash hdata;
QVariantList objectSets;
QVariantHash keys;
QString hPath = WeeChatProtocolHandler::handleString(data);
QString keyString = WeeChatProtocolHandler::handleString(data);
QStringList keyList = keyString.split(",");
QStringList orderedKeys;
for (QString keyStr : keyList)
{
QStringList keySplit = keyStr.split(":");
QString keyName = keySplit.at(0);
QString keyTypeStr = keySplit.at(1);
keys.insert(keyName, keyTypeStr);
orderedKeys.append(keyName);
}
qint32 objectSetCount = WeeChatProtocolHandler::handleInt(data);
for (qint32 i = 0; i < objectSetCount; ++i)
{
QVariantHash objectSet;
// The amount of pointers is the amount of parts in H-path,
// separated by /
QVariantList pointers;
int pointerCount = hPath.split("/").size();
for (int r = 0; r < pointerCount; ++r)
{
pointers.append(WeeChatProtocolHandler::handlePointer(data));
}
objectSet.insert(QString("__path"), pointers);
for (QString keyName : orderedKeys)
{
Type type = stringToType(keys.value(keyName).toString());
objectSet.insert(keyName, WeeChatProtocolHandler::handleDynamicType(type, data));
}
objectSets.append(objectSet);
}
hdata.insert("objectSets", objectSets);
hdata.insert("keys", keys);
hdata.insert("hpath", hPath);
return hdata;
}
QPair<QString, QString> WeeChatProtocolHandler::handleInfo(QDataStream* data)
{
// Info consists of a string key and a string value
QString key = handleString(data);
QString value = handleString(data);
return std::pair<QString, QString>(key, value);
return QPair<QString, QString>(key, value);
}
std::pair<QString, QHash<QString, QVariant> > WeeChatProtocolHandler::handleInfoList(QDataStream* data)
QPair<QString, QVariantHash> WeeChatProtocolHandler::handleInfoList(QDataStream* data)
{
// Infolist consists of name, count and then name, type and value for each element
QString name = handleString(data);
qint32 length = handleInt(data);
QHash<QString, QVariant> values;
QVariantHash values;
for (qint32 i = 0; i < length; ++i)
{
QString key = handleString(data);
@ -308,12 +291,12 @@ std::pair<QString, QHash<QString, QVariant> > WeeChatProtocolHandler::handleInfo
values.insert(key, value);
}
return std::pair<QString, QHash<QString, QVariant> >(name, values);
return QPair<QString, QVariantHash>(name, values);
}
QList<QVariant> WeeChatProtocolHandler::handleArray(QDataStream* data)
QVariantList WeeChatProtocolHandler::handleArray(QDataStream* data)
{
QList<QVariant> ret;
QVariantList ret;
// Array consists of type (string), number of elements (int 4 bytes) and data
Type type = readType(data);
@ -334,7 +317,11 @@ WeeChatProtocolHandler::Type WeeChatProtocolHandler::readType(QDataStream* data)
type.append(handleChar(data));
type.append(handleChar(data));
type.append(handleChar(data));
return stringToType(type);
}
WeeChatProtocolHandler::Type WeeChatProtocolHandler::stringToType(QString type)
{
if (type == "chr")
return CHAR;
else if (type == "int")
@ -360,3 +347,122 @@ WeeChatProtocolHandler::Type WeeChatProtocolHandler::readType(QDataStream* data)
else //if (type == "arr")
return ARRAY;
}
// Handle incoming data from the socket and emit the appropriate signals
void WeeChatProtocolHandler::handleNewData(RelayConnection* connection)
{
// If we cannot read the amount of bytes we want, skip and retry next time
if (connection->bytesAvailable() < bytesNeeded)
{
qDebug() << connection->bytesAvailable() << " was lower than " << bytesNeeded << "... Skipping.";
return;
}
QDataStream* data = read(connection, bytesNeeded);
if (!readingBody)
{
// The header contains the length of the message and compression specifier
quint32 length;
quint8 compression;
(*data) >> length;
(*data) >> compression;
qDebug() << length << " " << compression;
// The length includes the header
readingBody = true;
bytesNeeded = length - HEADER_BYTES;
// Attempt to read the body right away
handleNewData(connection);
}
else
{
handleBody(data);
readingBody = false;
bytesNeeded = HEADER_BYTES;
}
delete data;
data = 0;
}
void WeeChatProtocolHandler::sendDebugData(QString string)
{
emitData(string);
}
void WeeChatProtocolHandler::emitData(QString data)
{
ProtocolHandler::emitData(data + "\n");
}
void WeeChatProtocolHandler::handleBody(QDataStream* data)
{
// The first element is the id which will affect how we interpret the rest
char* dataArr = 0;
(*data) >> dataArr;
QString id(dataArr);
qDebug() << "ID: " << id;
// IDs for all event types
if (id == "_pong")
{
handlePong(id, data);
}
else if (id == "_upgrade")
{
handleUpgrade(id, data);
}
else if (id == "_upgrade_ended")
{
handleUpgradeEnded(id, data);
}
else
{
handleDefaultEvent(id, data);
}
delete[] dataArr;
dataArr = 0;
}
// EVENTS
void WeeChatProtocolHandler::handleDefaultEvent(QString id, QDataStream* data)
{
// Type for default events is hda, so skip it
readType(data);
QVariantHash hdata = handleHdata(data);
emit event(id, hdata);
}
void WeeChatProtocolHandler::handlePong(QString id, QDataStream* data)
{
QString response = handleString(data);
emit event(id, response);
}
void WeeChatProtocolHandler::handleUpgrade(QString id, QDataStream* data)
{
// There is no data to read for this message
emit event(id, QVariant());
}
void WeeChatProtocolHandler::handleUpgradeEnded(QString id, QDataStream* data)
{
// There is no data to read for this message
emit event(id, QVariant());
}

View file

@ -7,11 +7,14 @@
#ifndef WEECHATPROTOCOLHANDLER_H
#define WEECHATPROTOCOLHANDLER_H
#include "protocolhandler.h"
#include <utility>
#include <QObject>
#include <QDateTime>
#include <QHash>
#include "protocolhandler.h"
#include <QPair>
#include <QVariant>
class WeeChatProtocolHandler : public ProtocolHandler
{
@ -32,14 +35,35 @@ public:
ARRAY
};
explicit WeeChatProtocolHandler(QObject* parent = 0);
Q_ENUMS(Type)
explicit WeeChatProtocolHandler(QObject* parent = 0);
void initialize(QString password);
// How many bytes at least each message contains
static const qint64 HEADER_BYTES = 5;
// Individual object types
static QVariant handleDynamicType(Type type, QDataStream* data);
static char handleChar(QDataStream* data);
static qint32 handleInt(QDataStream* data);
static qint64 handleLong(QDataStream* data);
static QString handleString(QDataStream* data);
static QByteArray handleBuffer(QDataStream* data);
static QString handlePointer(QDataStream* data);
static QDateTime handleTime(QDataStream* data);
static QVariantHash handleHashTable(QDataStream* data);
static QVariantHash handleHdata(QDataStream* data);
static QPair<QString, QString> handleInfo(QDataStream* data);
static QPair<QString, QVariantHash> handleInfoList(QDataStream* data);
static QVariantList handleArray(QDataStream* data);
static Type readType(QDataStream* data);
static Type stringToType(QString type);
signals:
void event(QString id, QVariant data);
public slots:
void handleNewData(RelayConnection* connection);
@ -50,25 +74,10 @@ protected:
void handleBody(QDataStream* data);
// WeeChat event types
void handleBufferLineAdded(QDataStream* data);
void handleUnknown(QDataStream* data);
// Individual object types
QVariant handleDynamicType(Type type, QDataStream* data);
char handleChar(QDataStream* data);
qint32 handleInt(QDataStream* data);
qint64 handleLong(QDataStream* data);
QString handleString(QDataStream* data);
QByteArray handleBuffer(QDataStream* data);
QString handlePointer(QDataStream* data);
QDateTime handleTime(QDataStream* data);
QHash<QString, QVariant> handleHashTable(QDataStream* data);
// TODO: Hdata
std::pair<QString, QString> handleInfo(QDataStream* data);
std::pair<QString, QHash<QString, QVariant>> handleInfoList(QDataStream* data);
QList<QVariant> handleArray(QDataStream* data);
Type readType(QDataStream* data);
void handlePong(QString id, QDataStream* data);
void handleUpgrade(QString id, QDataStream* data);
void handleUpgradeEnded(QString id, QDataStream* data);
void handleDefaultEvent(QString id, QDataStream* data);
bool readingBody;