From 68370cf03c2e03ee3c04f5cfde057851ec7ec633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 1 Oct 2021 13:11:41 +0200 Subject: [PATCH] wasm: implement host lookup for socket tunneling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Emscripten implements support for tunneling TCP and UDP sockets through a WebSockets connection. This support is implement for the BSD sockets API, which means that Qt’s existing socket classes can be used, with some adjustments. For example, the flow for making a TCP connection to example.com:1515 can look like this: 1) The application resolves “example.com”. Emscripten creates an internal mapping to a private IP and returns that IP: 172.29.1.0. 2) The application connects to 172.29.1.0:1515. Emscripten makes a WebSocket connection to example.com:1515, and forwards the TCP data over this connection 3) On example.com:1515, a WebSockify intermediate server accepts the WebScoket connection and forwards the TCP data to the target sever, as specified by the WebSockify configuration. Emscripten’s local getaddrinfo() implementation is fast, which means don’t need caching or the thread pool. Instead, special-case lookupHostImpl() for Q_OS_WASM. The implementation calls QHostInfoAgent::lookup() and then posts resultReady using QHostInfoResult. Change-Id: Iaf31efb701ae7cc11752a63cc6b8346d4f09107e Reviewed-by: Lorn Potter (cherry picked from commit 76d12eea2252c5e537dff15b103bdc1f925cf760) --- src/network/kernel/qhostinfo.cpp | 22 +++++++++++++++++++++- src/network/kernel/qhostinfo_p.h | 1 - src/network/socket/qnativesocketengine.cpp | 2 ++ 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/network/kernel/qhostinfo.cpp b/src/network/kernel/qhostinfo.cpp index 6f508fb59b0..a089351d60a 100644 --- a/src/network/kernel/qhostinfo.cpp +++ b/src/network/kernel/qhostinfo.cpp @@ -59,7 +59,7 @@ # include # include # include -# if defined(AI_ADDRCONFIG) +# if defined(AI_ADDRCONFIG) && !defined(Q_OS_WASM) # define Q_ADDRCONFIG AI_ADDRCONFIG # endif #elif defined Q_OS_WIN @@ -378,12 +378,17 @@ QHostInfo QHostInfo::fromName(const QString &name) qDebug("QHostInfo::fromName(\"%s\")",name.toLatin1().constData()); #endif +#ifdef Q_OS_WASM + return QHostInfoAgent::lookup(name); +#else QHostInfo hostInfo = QHostInfoAgent::fromName(name); QHostInfoLookupManager* manager = theHostInfoLookupManager(); manager->cache.put(name, hostInfo); return hostInfo; +#endif } + QHostInfo QHostInfoAgent::reverseLookup(const QHostAddress &address) { QHostInfo results; @@ -801,6 +806,20 @@ int QHostInfo::lookupHostImpl(const QString &name, return id; } +#ifdef Q_OS_WASM + // Resolve the host name directly without using a thread or cache, + // since Emscripten's host lookup is fast. Emscripten maintains an internal + // mapping of hosts and addresses for the purposes of WebSocket socket + // tunnelling, and does not perform an actual host lookup. + QHostInfo hostInfo = QHostInfoAgent::lookup(name); + hostInfo.setLookupId(id); + + QHostInfoResult result(receiver, slotObj); + if (receiver && member) + QObject::connect(&result, SIGNAL(resultsReady(QHostInfo)), + receiver, member, Qt::QueuedConnection); + result.postResultsReady(hostInfo); +#else QHostInfoLookupManager *manager = theHostInfoLookupManager(); if (Q_LIKELY(manager)) { @@ -827,6 +846,7 @@ int QHostInfo::lookupHostImpl(const QString &name, receiver, member, Qt::QueuedConnection); manager->scheduleLookup(runnable); } +#endif // Q_OS_WASM return id; } diff --git a/src/network/kernel/qhostinfo_p.h b/src/network/kernel/qhostinfo_p.h index cc34d575b26..b10b7651484 100644 --- a/src/network/kernel/qhostinfo_p.h +++ b/src/network/kernel/qhostinfo_p.h @@ -118,7 +118,6 @@ class QHostInfoAgent { public: static QHostInfo fromName(const QString &hostName); -private: static QHostInfo lookup(const QString &hostName); static QHostInfo reverseLookup(const QHostAddress &address); }; diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp index f70e34c3755..dfc8d96821f 100644 --- a/src/network/socket/qnativesocketengine.cpp +++ b/src/network/socket/qnativesocketengine.cpp @@ -476,11 +476,13 @@ bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType socketType, QAb } +#ifndef Q_OS_WASM // Make sure we receive out-of-band data if (socketType == QAbstractSocket::TcpSocket && !setOption(ReceiveOutOfBandData, 1)) { qWarning("QNativeSocketEngine::initialize unable to inline out-of-band data"); } +#endif // Before Qt 4.6, we always set the send and receive buffer size to 49152 as // this was found to be an optimal value. However, modern OS