diff options
author | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2018-10-02 03:00:53 +0200 |
---|---|---|
committer | Qt Forward Merge Bot <qt_forward_merge_bot@qt-project.org> | 2018-10-02 03:00:53 +0200 |
commit | d1994f088f011a390f1c7b9a6ee09dac7606fbc6 (patch) | |
tree | c940c3aeee2c72dc1d11c25350fc1354797cb711 | |
parent | c36e520c8404b8b37141619101862ab71b343200 (diff) | |
parent | 247373d6501bab94ce1ea0048e390bd910963db9 (diff) | |
download | qtwebsockets-d1994f088f011a390f1c7b9a6ee09dac7606fbc6.tar.gz |
Merge remote-tracking branch 'origin/5.12' into dev
Change-Id: I297fa8021bd7520851d139c16b97671d41156919
-rw-r--r-- | qtwebsockets.pro | 1 | ||||
-rw-r--r-- | src/imports/qmlwebsockets/dependencies.json | 2 | ||||
-rw-r--r-- | src/imports/qmlwebsockets/plugins.qmltypes | 2 | ||||
-rw-r--r-- | src/imports/qmlwebsockets/qmlwebsockets.pro | 2 | ||||
-rw-r--r-- | src/websockets/qwebsocket_p.h | 7 | ||||
-rw-r--r-- | src/websockets/qwebsocket_wasm_p.cpp | 224 |
6 files changed, 99 insertions, 139 deletions
diff --git a/qtwebsockets.pro b/qtwebsockets.pro index 58c33f2..0dcd45b 100644 --- a/qtwebsockets.pro +++ b/qtwebsockets.pro @@ -1 +1,2 @@ +requires(qtHaveModule(network)) load(qt_parts) diff --git a/src/imports/qmlwebsockets/dependencies.json b/src/imports/qmlwebsockets/dependencies.json new file mode 100644 index 0000000..0d4f101 --- /dev/null +++ b/src/imports/qmlwebsockets/dependencies.json @@ -0,0 +1,2 @@ +[ +] diff --git a/src/imports/qmlwebsockets/plugins.qmltypes b/src/imports/qmlwebsockets/plugins.qmltypes index cbbb628..2fb57cd 100644 --- a/src/imports/qmlwebsockets/plugins.qmltypes +++ b/src/imports/qmlwebsockets/plugins.qmltypes @@ -4,7 +4,7 @@ import QtQuick.tooling 1.2 // It is used for QML tooling purposes only. // // This file was auto-generated by: -// 'qmlplugindump -nonrelocatable QtWebSockets 1.1' +// 'qmlplugindump -nonrelocatable -dependencies dependencies.json QtWebSockets 1.1' Module { dependencies: [] diff --git a/src/imports/qmlwebsockets/qmlwebsockets.pro b/src/imports/qmlwebsockets/qmlwebsockets.pro index fa631bd..7b6fc86 100644 --- a/src/imports/qmlwebsockets/qmlwebsockets.pro +++ b/src/imports/qmlwebsockets/qmlwebsockets.pro @@ -12,6 +12,6 @@ SOURCES += qmlwebsockets_plugin.cpp \ OTHER_FILES += qmldir -IMPORT_VERSION = 1.0 +IMPORT_VERSION = 1.1 load(qml_plugin) diff --git a/src/websockets/qwebsocket_p.h b/src/websockets/qwebsocket_p.h index 73f2745..fd631d4 100644 --- a/src/websockets/qwebsocket_p.h +++ b/src/websockets/qwebsocket_p.h @@ -69,6 +69,10 @@ #include "qwebsocketdataprocessor_p.h" #include "qdefaultmaskgenerator_p.h" +#ifdef Q_OS_WASM +#include <emscripten/val.h> +#endif + QT_BEGIN_NAMESPACE class QWebSocketHandshakeRequest; @@ -247,6 +251,9 @@ private: QMap<QString, QString> m_headers; friend class QWebSocketServerPrivate; +#ifdef Q_OS_WASM + emscripten::val socketContext = emscripten::val::null(); +#endif }; QT_END_NAMESPACE diff --git a/src/websockets/qwebsocket_wasm_p.cpp b/src/websockets/qwebsocket_wasm_p.cpp index 7b9f271..2ac61ba 100644 --- a/src/websockets/qwebsocket_wasm_p.cpp +++ b/src/websockets/qwebsocket_wasm_p.cpp @@ -42,92 +42,104 @@ #include <QtCore/qcoreapplication.h> #include <emscripten.h> -#include <emscripten/html5.h> #include <emscripten/bind.h> using namespace emscripten; -QByteArray g_messageArray; -// easiest way to transliterate binary data to js/wasm - -val getBinaryMessage() +static void q_onErrorCallback(val event) { - return val(typed_memory_view(g_messageArray.size(), - reinterpret_cast<const unsigned char *>(g_messageArray.constData()))); -} + val target = event["target"]; -EMSCRIPTEN_BINDINGS(wasm_module) { - function("getBinaryMessage", &getBinaryMessage); + QWebSocketPrivate *wsp = reinterpret_cast<QWebSocketPrivate*>(target["data-context"].as<quintptr>()); + Q_ASSERT (wsp); + + emit wsp->q_func()->error(wsp->error()); } -static void onOpenCallback(void *data) +static void q_onCloseCallback(val event) { - auto handler = reinterpret_cast<QWebSocketPrivate *>(data); - Q_ASSERT (handler); - emit handler->q_func()->connected(); + val target = event["target"]; + + QWebSocketPrivate *wsp = reinterpret_cast<QWebSocketPrivate*>(target["data-context"].as<quintptr>()); + Q_ASSERT (wsp); + + emit wsp->q_func()->disconnected(); } -static void onCloseCallback(void *data, int message) +static void q_onOpenCallback(val event) { - Q_UNUSED(message); - auto handler = reinterpret_cast<QWebSocketPrivate *>(data); - Q_ASSERT (handler); - emit handler->q_func()->disconnected(); + val target = event["target"]; + + QWebSocketPrivate *wsp = reinterpret_cast<QWebSocketPrivate*>(target["data-context"].as<quintptr>()); + Q_ASSERT (wsp); + + emit wsp->q_func()->connected(); } -static void onErrorCallback(void *data, int message) +static void q_onIncomingMessageCallback(val event) { - Q_UNUSED(message); - auto handler = reinterpret_cast<QWebSocketPrivate *>(data); - Q_ASSERT (handler); - emit handler->q_func()->error(handler->error()); + val target = event["target"]; + + if (event["data"].typeOf().as<std::string>() == "string") { + QWebSocketPrivate *wsp = reinterpret_cast<QWebSocketPrivate*>(target["data-context"].as<quintptr>()); + Q_ASSERT (wsp); + + const QString message = QString::fromStdString(event["data"].as<std::string>()); + if (!message.isEmpty()) + wsp->q_func()->textMessageReceived(message); + } else { + val reader = val::global("FileReader").new_(); + reader.set("onload", val::module_property("QWebSocketPrivate_readBlob")); + reader.set("data-context", target["data-context"]); + reader.call<void>("readAsArrayBuffer", event["data"]); + } } -static void onIncomingMessageCallback(void *data, int message, int length, int dataType) +static void q_readBlob(val event) { - QWebSocketPrivate *handler = reinterpret_cast<QWebSocketPrivate *>(data); - Q_ASSERT (handler); - - QWebSocket *webSocket = handler->q_func(); - const char *text = reinterpret_cast<const char *>(message); - - switch (dataType) { - case 0: //string - webSocket->textMessageReceived(QLatin1String(text)); - break; - case 1: //blob - case 2: //arraybuffer - webSocket->binaryMessageReceived(QByteArray::fromRawData(text, length)); - break; - }; + val fileReader = event["target"]; + + QWebSocketPrivate *wsp = reinterpret_cast<QWebSocketPrivate*>(fileReader["data-context"].as<quintptr>()); + Q_ASSERT (wsp); + + // Set up source typed array + val result = fileReader["result"]; // ArrayBuffer + val Uint8Array = val::global("Uint8Array"); + val sourceTypedArray = Uint8Array.new_(result); + + // Allocate and set up destination typed array + const size_t size = result["byteLength"].as<size_t>(); + QByteArray buffer(size, Qt::Uninitialized); + + val destinationTypedArray = Uint8Array.new_(val::module_property("HEAPU8")["buffer"], + reinterpret_cast<quintptr>(buffer.data()), size); + destinationTypedArray.call<void>("set", sourceTypedArray); + + wsp->q_func()->binaryMessageReceived(buffer); +} + + +EMSCRIPTEN_BINDINGS(wasm_module) { + function("QWebSocketPrivate_onErrorCallback", q_onErrorCallback); + function("QWebSocketPrivate_onCloseCallback", q_onCloseCallback); + function("QWebSocketPrivate_onOpenCallback", q_onOpenCallback); + function("QWebSocketPrivate_onIncomingMessageCallback", q_onIncomingMessageCallback); + function("QWebSocketPrivate_readBlob", q_readBlob); } qint64 QWebSocketPrivate::sendTextMessage(const QString &message) { - EM_ASM_ARGS({ - if (window.qWebSocket === undefined) - console.log("cannot find websocket object"); - else - window.qWebSocket.send(Pointer_stringify($0)); - }, message.toLocal8Bit().constData()); - + socketContext.call<void>("send", message.toStdString()); return message.length(); } qint64 QWebSocketPrivate::sendBinaryMessage(const QByteArray &data) { - g_messageArray = data; - EM_ASM({ - if (window.qWebSocket === undefined) { - console.log("cannot find websocket object"); - } else { - var array = Module.getBinaryMessage(); - window.qWebSocket.binaryType = 'arraybuffer'; - window.qWebSocket.send(array); - } - }); - - g_messageArray.clear(); + socketContext.call<void>("send", + val(typed_memory_view(data.size(), + reinterpret_cast<const unsigned char *> + (data.constData())))); + return data.length(); } @@ -136,19 +148,10 @@ void QWebSocketPrivate::close(QWebSocketProtocol::CloseCode closeCode, QString r Q_Q(QWebSocket); m_closeCode = closeCode; m_closeReason = reason; - const quint16 closeReason = (quint16)closeCode; Q_EMIT q->aboutToClose(); - QCoreApplication::processEvents(); - - EM_ASM_ARGS({ - if (window.qWebSocket === undefined) { - console.log("cannot find websocket object"); - } else { - var reasonMessage = Pointer_stringify($0); - window.qWebSocket.close($1, reasonMessage); - window.qWebSocket = undefined; - } - }, reason.toLatin1().data(), closeReason); + + socketContext.call<void>("close", static_cast<quint16>(closeCode), + reason.toLatin1().toStdString()); } void QWebSocketPrivate::open(const QNetworkRequest &request, bool mask) @@ -162,74 +165,21 @@ void QWebSocketPrivate::open(const QNetworkRequest &request, bool mask) return; } - QByteArray urlbytes = url.toString().toUtf8(); + const std::string urlbytes = url.toString().toStdString(); // HTML WebSockets do not support arbitrary request headers, but // do support the WebSocket protocol header. This header is // required for some use cases like MQTT. - QByteArray protocolHeaderValue = request.rawHeader("Sec-WebSocket-Protocol"); - - EM_ASM_ARGS({ - if (window.qWebSocket != undefined) - return; - - var wsUri = Pointer_stringify($0); - var wsProtocol = Pointer_stringify($1); - var handler = $2; - var onOpenCb = $3; - var onCloseCb = $4; - var onErrorCb = $5; - var onIncomingMessageCb = $6; - - window.qWebSocket = wsProtocol.length > 0 - ? new WebSocket(wsUri, wsProtocol) - : new WebSocket(wsUri); - - window.qWebSocket.onopen = function(event) { - Runtime.dynCall('vi', onOpenCb, [handler]); - }; - - window.qWebSocket.onclose = function(event) { - window.qWebSocket = undefined; - Runtime.dynCall('vii', onCloseCb, [handler, event.code]); - }; - - window.qWebSocket.onerror = function(event) { - Runtime.dynCall('vii', onErrorCb, [handler, event.error]); - }; - - window.qWebSocket.onmessage = function(event) { - var outgoingMessage; - var bufferLength = 0; - var dataType; - - if (window.qWebSocket.binaryType == 'arraybuffer' && typeof event.data == 'object') { - - var byteArray = new Uint8Array(event.data); - bufferLength = byteArray.length; - - outgoingMessage = _malloc(byteArray.length); - HEAPU8.set(byteArray, outgoingMessage); - - dataType = 2; - } else if (typeof event.data == 'string') { - dataType = 0; - outgoingMessage = allocate(intArrayFromString(event.data), 'i8', ALLOC_NORMAL); - } else if (window.qWebSocket.binaryType == 'blob') { - var byteArray = new Int8Array($0); - outgoingMessage = new Blob(byteArray.buffer); - dataType = 1; - } - - Runtime.dynCall('viiii', onIncomingMessageCb, [handler, outgoingMessage, bufferLength, dataType]); - _free(outgoingMessage); - }; - - }, urlbytes.constData(), - protocolHeaderValue.data(), - this, - reinterpret_cast<void *>(onOpenCallback), - reinterpret_cast<void *>(onCloseCallback), - reinterpret_cast<void *>(onErrorCallback), - reinterpret_cast<void *>(onIncomingMessageCallback)); + const std::string protocolHeaderValue = request.rawHeader("Sec-WebSocket-Protocol").toStdString(); + val webSocket = val::global("WebSocket"); + + socketContext = !protocolHeaderValue.empty() + ? webSocket.new_(urlbytes, protocolHeaderValue) + : webSocket.new_(urlbytes); + + socketContext.set("onerror", val::module_property("QWebSocketPrivate_onErrorCallback")); + socketContext.set("onclose", val::module_property("QWebSocketPrivate_onCloseCallback")); + socketContext.set("onopen", val::module_property("QWebSocketPrivate_onOpenCallback")); + socketContext.set("onmessage", val::module_property("QWebSocketPrivate_onIncomingMessageCallback")); + socketContext.set("data-context", val(quintptr(reinterpret_cast<void *>(this)))); } |