summaryrefslogtreecommitdiff
path: root/src/webchannel/qmetaobjectpublisher.cpp
diff options
context:
space:
mode:
authorMilian Wolff <milian.wolff@kdab.com>2014-02-05 17:44:03 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2014-03-21 15:59:25 +0100
commit48e814442e6e8507aacd16362b44d5754c059228 (patch)
tree592f3916bf2e5dc18d57a62c3baf1ba0ae2bbf09 /src/webchannel/qmetaobjectpublisher.cpp
parente3e4d6a18d63537459f0e616360e53e816927f76 (diff)
downloadqtwebchannel-48e814442e6e8507aacd16362b44d5754c059228.tar.gz
Send response data only to target client.
Before, the response was sent to all clients in a broad-cast and had to be filtered on the client-side. This required additional client identification data to be added to all requests and responses. Now, we keep track of the transport and transport-internal client and only send the response to that client. This is very benefitial for multi-client setups but also reduces traffic for single-client setups and thus their performance. Change-Id: Ia1ef5e031b0058222083d352a8aa28a7d566a6ca Reviewed-by: Simon Hausmann <simon.hausmann@digia.com>
Diffstat (limited to 'src/webchannel/qmetaobjectpublisher.cpp')
-rw-r--r--src/webchannel/qmetaobjectpublisher.cpp55
1 files changed, 29 insertions, 26 deletions
diff --git a/src/webchannel/qmetaobjectpublisher.cpp b/src/webchannel/qmetaobjectpublisher.cpp
index d06fe98..2914714 100644
--- a/src/webchannel/qmetaobjectpublisher.cpp
+++ b/src/webchannel/qmetaobjectpublisher.cpp
@@ -41,6 +41,7 @@
#include "qmetaobjectpublisher_p.h"
#include "qwebchannel.h"
+#include "qwebchannel_p.h"
#include <QEvent>
#include <QJsonDocument>
@@ -336,27 +337,27 @@ void QMetaObjectPublisher::sendPendingPropertyUpdates()
setClientIsIdle(false);
}
-bool QMetaObjectPublisher::invokeMethod(QObject *const object, const int methodIndex,
- const QJsonArray &args, const QJsonValue &id)
+QByteArray QMetaObjectPublisher::invokeMethod(QObject *const object, const int methodIndex,
+ const QJsonArray &args, const QJsonValue &id)
{
const QMetaMethod &method = object->metaObject()->method(methodIndex);
if (method.name() == QByteArrayLiteral("deleteLater")) {
// invoke `deleteLater` on wrapped QObject indirectly
deleteWrappedObject(object);
- return true;
+ return QByteArray();
} else if (!method.isValid()) {
qWarning() << "Cannot invoke unknown method of index" << methodIndex << "on object" << object << '.';
- return false;
+ return QByteArray();
} else if (method.access() != QMetaMethod::Public) {
qWarning() << "Cannot invoke non-public method" << method.name() << "on object" << object << '.';
- return false;
+ return QByteArray();
} else if (method.methodType() != QMetaMethod::Method && method.methodType() != QMetaMethod::Slot) {
qWarning() << "Cannot invoke non-public method" << method.name() << "on object" << object << '.';
- return false;
+ return QByteArray();
} else if (args.size() > 10) {
qWarning() << "Cannot invoke method" << method.name() << "on object" << object << "with more than 10 arguments, as that is not supported by QMetaMethod::invoke.";
- return false;
+ return QByteArray();
} else if (args.size() > method.parameterCount()) {
qWarning() << "Ignoring additional arguments while invoking method" << method.name() << "on object" << object << ':'
<< args.size() << "arguments given, but method only takes" << method.parameterCount() << '.';
@@ -388,9 +389,7 @@ bool QMetaObjectPublisher::invokeMethod(QObject *const object, const int methodI
arguments[5], arguments[6], arguments[7], arguments[8], arguments[9]);
// and send the return value to the client
- webChannel->respond(id, wrapResult(returnValue));
-
- return true;
+ return generateJSONMessage(id, wrapResult(returnValue), true);
}
void QMetaObjectPublisher::signalEmitted(const QObject *object, const int signalIndex, const QVariantList &arguments)
@@ -486,70 +485,74 @@ void QMetaObjectPublisher::deleteWrappedObject(QObject *object) const
object->deleteLater();
}
-bool QMetaObjectPublisher::handleRequest(const QJsonObject &message)
+QByteArray QMetaObjectPublisher::handleRequest(const QJsonObject &message)
{
if (!message.contains(KEY_DATA)) {
- return false;
+ return QByteArray();
}
const QJsonObject &payload = message.value(KEY_DATA).toObject();
if (!payload.contains(KEY_TYPE)) {
- return false;
+ return QByteArray();
}
const Type type = toType(payload.value(KEY_TYPE));
if (type == TypeIdle) {
setClientIsIdle(true);
- return true;
+ return QByteArray();
} else if (type == TypeInit) {
if (!blockUpdates) {
initializeClients();
} else {
pendingInit = true;
}
- return true;
+ return QByteArray();
} else if (type == TypeDebug) {
static QTextStream out(stdout);
out << "DEBUG: " << payload.value(KEY_MESSAGE).toString() << endl;
- return true;
+ return QByteArray();
} else if (payload.contains(KEY_OBJECT)) {
const QString &objectName = payload.value(KEY_OBJECT).toString();
QObject *object = registeredObjects.value(objectName);
if (!object) {
qWarning() << "Unknown object encountered" << objectName;
- return false;
+ return QByteArray();
}
if (type == TypeInvokeMethod) {
return invokeMethod(object, payload.value(KEY_METHOD).toInt(-1), payload.value(KEY_ARGS).toArray(), message.value(KEY_ID));
} else if (type == TypeConnectToSignal) {
signalHandler.connectTo(object, payload.value(KEY_SIGNAL).toInt(-1));
- return true;
+ return QByteArray();
} else if (type == TypeDisconnectFromSignal) {
signalHandler.disconnectFrom(object, payload.value(KEY_SIGNAL).toInt(-1));
- return true;
+ return QByteArray();
} else if (type == TypeSetProperty) {
const int propertyIdx = payload.value(KEY_PROPERTY).toInt(-1);
QMetaProperty property = object->metaObject()->property(propertyIdx);
if (!property.isValid()) {
qWarning() << "Cannot set unknown property" << payload.value(KEY_PROPERTY) << "of object" << objectName;
- return false;
+ return QByteArray();
} else if (!object->metaObject()->property(propertyIdx).write(object, payload.value(KEY_VALUE).toVariant())) {
qWarning() << "Could not write value " << payload.value(KEY_VALUE)
<< "to property" << property.name() << "of object" << objectName;
- return false;
+ return QByteArray();
}
- return true;
+ return QByteArray();
}
}
- return false;
+ return QByteArray();
}
-void QMetaObjectPublisher::handleMessage(const QString &message)
+void QMetaObjectPublisher::handleMessage(const QString &message, QWebChannelTransportInterface *transport, int clientId)
{
const QJsonDocument doc = QJsonDocument::fromJson(message.toUtf8());
- if (doc.isObject()) {
- handleRequest(doc.object());
+ if (!doc.isObject()) {
+ return;
+ }
+ const QByteArray &response = handleRequest(doc.object());
+ if (!response.isEmpty()) {
+ transport->sendMessage(response, clientId);
}
}