Change Hdata from QObject to QVariantHash, combine all parsing to WCPH
This commit is contained in:
parent
4a9eeb850b
commit
56d7c58ac0
5 changed files with 230 additions and 141 deletions
|
@ -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
|
||||
|
|
|
@ -1,6 +0,0 @@
|
|||
#include "hdata.h"
|
||||
|
||||
Hdata::Hdata(QObject *parent) :
|
||||
QObject(parent)
|
||||
{
|
||||
}
|
|
@ -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
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue