diff --git a/harbour-weechatrelay.pro b/harbour-weechatrelay.pro index 25dc45f..b746dcc 100644 --- a/harbour-weechatrelay.pro +++ b/harbour-weechatrelay.pro @@ -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 diff --git a/src/weechat/hdata.cpp b/src/weechat/hdata.cpp deleted file mode 100644 index 65d883b..0000000 --- a/src/weechat/hdata.cpp +++ /dev/null @@ -1,6 +0,0 @@ -#include "hdata.h" - -Hdata::Hdata(QObject *parent) : - QObject(parent) -{ -} diff --git a/src/weechat/hdata.h b/src/weechat/hdata.h deleted file mode 100644 index e2cbd35..0000000 --- a/src/weechat/hdata.h +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef HDATA_H -#define HDATA_H - -#include - -class Hdata : public QObject -{ - Q_OBJECT -public: - explicit Hdata(QObject *parent = 0); - -signals: - -public slots: - -}; - -#endif // HDATA_H diff --git a/src/weechatprotocolhandler.cpp b/src/weechatprotocolhandler.cpp index 1cc5dc1..6005887 100644 --- a/src/weechatprotocolhandler.cpp +++ b/src/weechatprotocolhandler.cpp @@ -6,6 +6,9 @@ #include #include +#include +#include +#include #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(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 WeeChatProtocolHandler::handleHashTable(QDataStream* data) +QVariantHash WeeChatProtocolHandler::handleHashTable(QDataStream* data) { - QHash ret; + QVariantHash ret; // The hashtable first contains the types for the key and value Type keyType = readType(data); @@ -285,21 +205,84 @@ QHash WeeChatProtocolHandler::handleHashTable(QDataStream* da return ret; } -std::pair 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 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(key, value); + return QPair(key, value); } -std::pair > WeeChatProtocolHandler::handleInfoList(QDataStream* data) +QPair 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 values; + QVariantHash values; for (qint32 i = 0; i < length; ++i) { QString key = handleString(data); @@ -308,12 +291,12 @@ std::pair > WeeChatProtocolHandler::handleInfo values.insert(key, value); } - return std::pair >(name, values); + return QPair(name, values); } -QList WeeChatProtocolHandler::handleArray(QDataStream* data) +QVariantList WeeChatProtocolHandler::handleArray(QDataStream* data) { - QList 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()); +} diff --git a/src/weechatprotocolhandler.h b/src/weechatprotocolhandler.h index 9b8e2d9..5b7599c 100644 --- a/src/weechatprotocolhandler.h +++ b/src/weechatprotocolhandler.h @@ -7,11 +7,14 @@ #ifndef WEECHATPROTOCOLHANDLER_H #define WEECHATPROTOCOLHANDLER_H +#include "protocolhandler.h" + #include #include #include #include -#include "protocolhandler.h" +#include +#include 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 handleInfo(QDataStream* data); + static QPair 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 handleHashTable(QDataStream* data); - // TODO: Hdata - std::pair handleInfo(QDataStream* data); - std::pair> handleInfoList(QDataStream* data); - QList 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;