Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/core/core.pri
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ HEADERS += \
$$PWD/zrpcmanager.h \
$$PWD/zrpcrequest.h \
$$PWD/statusreasons.h \
$$PWD/jsonpointer.h \
$$PWD/inspectdata.h \
$$PWD/cors.h \
$$PWD/simplehttpserver.h \
Expand Down Expand Up @@ -119,6 +120,7 @@ SOURCES += \
$$PWD/zrpcmanager.cpp \
$$PWD/zrpcrequest.cpp \
$$PWD/statusreasons.cpp \
$$PWD/jsonpointer.cpp \
$$PWD/cors.cpp \
$$PWD/simplehttpserver.cpp \
$$PWD/stats.cpp \
Expand Down
File renamed without changes.
File renamed without changes.
39 changes: 39 additions & 0 deletions src/core/packet/wscontrolpacket.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,9 @@ Variant WsControlPacket::toVariant() const {
case Item::Refresh:
typeStr = "refresh";
break;
case Item::AutoRespond:
typeStr = "auto-respond";
break;
case Item::Close:
typeStr = "close";
break;
Expand Down Expand Up @@ -261,6 +264,15 @@ Variant WsControlPacket::toVariant() const {
if (!item.keepAliveMode.isEmpty())
vitem["keep-alive-mode"] = item.keepAliveMode;

if (!item.matchContentType.isEmpty())
vitem["match-content-type"] = item.matchContentType;

if (!item.matchContent.isNull())
vitem["match-content"] = item.matchContent;

if (!item.matchContentPtr.isEmpty())
vitem["match-content-ptr"] = item.matchContentPtr;

vitems += vitem;
}

Expand Down Expand Up @@ -321,6 +333,8 @@ bool WsControlPacket::fromVariant(const Variant &in) {
item.type = Item::Subscribe;
else if (typeStr == "refresh")
item.type = Item::Refresh;
else if (typeStr == "auto-respond")
item.type = Item::AutoRespond;
else if (typeStr == "close")
item.type = Item::Close;
else if (typeStr == "detach")
Expand Down Expand Up @@ -463,6 +477,31 @@ bool WsControlPacket::fromVariant(const Variant &in) {
item.keepAliveMode = keepAliveMode;
}

if (vitem.contains("match-content-type")) {
if (typeId(vitem["match-content-type"]) != VariantType::ByteArray)
return false;

QByteArray matchContentType = vitem["match-content-type"].toByteArray();
if (!matchContentType.isEmpty())
item.matchContentType = matchContentType;
}

if (vitem.contains("match-content")) {
if (typeId(vitem["match-content"]) != VariantType::ByteArray)
return false;

item.matchContent = vitem["match-content"].toByteArray();
}

if (vitem.contains("match-content-ptr")) {
if (typeId(vitem["match-content-ptr"]) != VariantType::ByteArray)
return false;

QByteArray matchContentPtr = vitem["match-content-ptr"].toByteArray();
if (!matchContentPtr.isEmpty())
item.matchContentPtr = matchContentPtr;
}

items += item;
}

Expand Down
4 changes: 4 additions & 0 deletions src/core/packet/wscontrolpacket.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ class WsControlPacket {
Send,
KeepAliveSetup,
Refresh,
AutoRespond,
Close,
Detach,
Ack
Expand All @@ -68,6 +69,9 @@ class WsControlPacket {
int ttl;
int timeout;
QByteArray keepAliveMode;
QByteArray matchContentType;
QByteArray matchContent;
QByteArray matchContentPtr;

Item()
: type((Type)-1),
Expand Down
30 changes: 29 additions & 1 deletion src/core/wscontrol.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,38 @@
#ifndef WSCONTROL_H
#define WSCONTROL_H

#include "websocket.h"

namespace WsControl {

enum KeepAliveMode { NoKeepAlive, Idle, Interval };

}
class AutoRespondConfig {
public:
WebSocket::Frame::Type matchType;
QByteArray matchContent;
QByteArray matchContentPtr;
WebSocket::Frame::Type type;
QByteArray content;

AutoRespondConfig() : matchType((WebSocket::Frame::Type)-1), type((WebSocket::Frame::Type)-1) {}

/// Returns true if the config has no matching criteria.
bool isEmpty() const { return (((int)matchType) < 0 && matchContent.isNull()); }

/// Returns true if the config has matching critera and response data.
bool isEnabled() const { return (!isEmpty() && (((int)type) >= 0 || !content.isNull())); }

/// Returns true if this config has the same matching criteria as `other`.
bool matches(const AutoRespondConfig &other) {
return (matchType == other.matchType &&
((matchContent.isNull() && other.matchContent.isNull()) ||
(!matchContent.isNull() && !other.matchContent.isNull() &&
matchContent == other.matchContent)) &&
matchContentPtr == other.matchContentPtr);
}
};

} // namespace WsControl

#endif
2 changes: 0 additions & 2 deletions src/handler/handler.pri
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
HEADERS += \
$$PWD/deferred.h \
$$PWD/variantutil.h \
$$PWD/jsonpointer.h \
$$PWD/jsonpatch.h \
$$PWD/detectrule.h \
$$PWD/lastids.h \
Expand Down Expand Up @@ -32,7 +31,6 @@ HEADERS += \
SOURCES += \
$$PWD/deferred.cpp \
$$PWD/variantutil.cpp \
$$PWD/jsonpointer.cpp \
$$PWD/jsonpatch.cpp \
$$PWD/sessionrequest.cpp \
$$PWD/requeststate.cpp \
Expand Down
78 changes: 46 additions & 32 deletions src/handler/handlerengine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,21 @@ static QList<PublishItem> parseItems(const VariantList &vitems, bool *ok = 0,
return out;
}

static QByteArray messageTypeToContentType(WsControlMessage::MessageType t) {
switch (t) {
case WsControlMessage::Text:
return "text";
case WsControlMessage::Binary:
return "binary";
case WsControlMessage::Ping:
return "ping";
case WsControlMessage::Pong:
return "pong";
default:
return QByteArray();
}
}

class InspectWorker : public Deferred {
public:
std::unique_ptr<ZrpcRequest> req;
Expand Down Expand Up @@ -2486,23 +2501,9 @@ class HandlerEngine::Private {
i.type = WsControlPacket::Item::KeepAliveSetup;

if (!cm.content.isNull()) {
QByteArray contentType;
switch (cm.messageType) {
case WsControlMessage::Text:
contentType = "text";
break;
case WsControlMessage::Binary:
contentType = "binary";
break;
case WsControlMessage::Ping:
contentType = "ping";
break;
case WsControlMessage::Pong:
contentType = "pong";
break;
default:
QByteArray contentType = messageTypeToContentType(cm.messageType);
if (contentType.isNull())
continue; // Unrecognized type, ignore
}

s->keepAliveType = contentType;
s->keepAliveMessage = cm.content;
Expand All @@ -2520,29 +2521,42 @@ class HandlerEngine::Private {

outItems += i;
} else if (cm.type == WsControlMessage::SendDelayed) {
QByteArray contentType;
switch (cm.messageType) {
case WsControlMessage::Text:
contentType = "text";
break;
case WsControlMessage::Binary:
contentType = "binary";
break;
case WsControlMessage::Ping:
contentType = "ping";
break;
case WsControlMessage::Pong:
contentType = "pong";
break;
default:
QByteArray contentType = messageTypeToContentType(cm.messageType);
if (contentType.isNull())
continue; // Unrecognized type, ignore
}

int timeout = (cm.timeout > 0 ? cm.timeout : DEFAULT_WS_SENDDELAYED_TIMEOUT);

s->sendDelayed(contentType, cm.content, timeout);
} else if (cm.type == WsControlMessage::FlushDelayed) {
s->flushDelayed();
} else if (cm.type == WsControlMessage::AutoRespond) {
WsControlPacket::Item i;
i.cid = item.cid;
i.type = WsControlPacket::Item::AutoRespond;

QByteArray matchContentType;
QByteArray contentType;

if (cm.matchMessageType >= 0) {
matchContentType = messageTypeToContentType(cm.matchMessageType);
if (matchContentType.isNull())
continue; // Unrecognized type, ignore
}

if (cm.messageType >= 0) {
contentType = messageTypeToContentType(cm.messageType);
if (contentType.isNull())
continue; // Unrecognized type, ignore
}

i.matchContentType = matchContentType;
i.matchContentPtr = cm.matchContentPtr.toUtf8();
i.matchContent = cm.matchContent;
i.contentType = contentType;
i.message = cm.content;

outItems += i;
}
} else if (item.type == WsControlPacket::Item::NeedKeepAlive) {
if (!s->keepAliveMessage.isNull()) {
Expand Down
55 changes: 55 additions & 0 deletions src/handler/variantutil.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -237,6 +237,61 @@ QString getString(const Variant &in, const QString &parentName, const QString &c
return str;
}

QByteArray getBytes(const Variant &in, const QString &parentName, const QString &childName,
const QString &childBinName, bool required, bool *ok, QString *errorMessage,
bool *isBin) {
QByteArray out;

QString pn = !parentName.isEmpty() ? parentName : QString("object");

if (keyedObjectContains(in, childBinName)) {
if (isBin)
*isBin = true;

Variant vcontentBin = keyedObjectGetValue(in, childBinName);

if (typeId(in) == VariantType::Map) // JSON input
{
if (typeId(vcontentBin) != VariantType::String) {
setError(ok, errorMessage,
QString("%1 contains '%2' with wrong type").arg(pn, childBinName));
return QByteArray();
}

out = QByteArray::fromBase64(vcontentBin.toString().toUtf8());
} else {
if (typeId(vcontentBin) != VariantType::ByteArray) {
setError(ok, errorMessage,
QString("%1 contains '%2' with wrong type").arg(pn, childBinName));
return QByteArray();
}

out = vcontentBin.toByteArray();
}
} else if (keyedObjectContains(in, childName)) {
if (isBin)
*isBin = false;

Variant vcontent = keyedObjectGetValue(in, childName);
if (typeId(vcontent) == VariantType::ByteArray)
out = vcontent.toByteArray();
else if (typeId(vcontent) == VariantType::String)
out = vcontent.toString().toUtf8();
else {
setError(ok, errorMessage,
QString("%1 contains '%2' with wrong type").arg(pn, childName));
return QByteArray();
}
} else if (required) {
setError(ok, errorMessage,
QString("%1 does not contain '%2' nor '%3'").arg(pn, childName, childBinName));
return QByteArray();
}

setSuccess(ok, errorMessage);
return out;
}

bool convertToJsonStyleInPlace(Variant *in) {
// Hash -> Map
// ByteArray (UTF-8) -> String
Expand Down
3 changes: 3 additions & 0 deletions src/handler/variantutil.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ VariantList getList(const Variant &in, const QString &parentName, const QString
QString getString(const Variant &in, bool *ok = 0);
QString getString(const Variant &in, const QString &parentName, const QString &childName,
bool required, bool *ok = 0, QString *errorMessage = 0);
QByteArray getBytes(const Variant &in, const QString &parentName, const QString &childName,
const QString &childBinName, bool required, bool *ok = 0,
QString *errorMessage = 0, bool *isBin = 0);

// Return true if item modified
bool convertToJsonStyleInPlace(Variant *in);
Expand Down
Loading
Loading