From 45b0f1be686cfba8dcecb9be5c875cae59c69276 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Fri, 5 Jun 2020 09:24:37 +0200 Subject: Remove winrt MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Macros and the await helper function from qfunctions_winrt(_p).h are needed in other Qt modules which use UWP APIs on desktop windows. Task-number: QTBUG-84434 Change-Id: Ice09c11436ad151c17bdccd2c7defadd08c13925 Reviewed-by: Tor Arne Vestbø --- src/network/socket/qabstractsocket.cpp | 9 +- src/network/socket/qabstractsocketengine.cpp | 4 - src/network/socket/qlocalserver.cpp | 2 +- src/network/socket/qlocalsocket.cpp | 2 +- src/network/socket/qnativesocketengine.cpp | 2 +- src/network/socket/qnativesocketengine_winrt.cpp | 1815 ---------------------- src/network/socket/qnativesocketengine_winrt_p.h | 243 --- src/network/socket/socket.pri | 17 +- 8 files changed, 10 insertions(+), 2084 deletions(-) delete mode 100644 src/network/socket/qnativesocketengine_winrt.cpp delete mode 100644 src/network/socket/qnativesocketengine_winrt_p.h (limited to 'src/network/socket') diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 03d69d6204..0f9e22d131 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -948,7 +948,7 @@ void QAbstractSocketPrivate::resolveProxy(const QString &hostname, quint16 port) } #endif // !QT_NO_NETWORKPROXY -#if !defined(QT_NO_NETWORKPROXY) || defined(Q_OS_WINRT) +#if !defined(QT_NO_NETWORKPROXY) /*! \internal @@ -990,7 +990,7 @@ void QAbstractSocketPrivate::startConnectingByName(const QString &host) emit q->stateChanged(state); } -#endif // !QT_NO_NETWORKPROXY || Q_OS_WINRT +#endif // !QT_NO_NETWORKPROXY /*! \internal @@ -1713,7 +1713,6 @@ void QAbstractSocket::connectToHost(const QString &hostName, quint16 port, QIODevice::open(openMode); d->readChannelCount = d->writeChannelCount = 0; -#ifndef Q_OS_WINRT d->state = HostLookupState; emit stateChanged(d->state); @@ -1751,10 +1750,6 @@ void QAbstractSocket::connectToHost(const QString &hostName, quint16 port, (d->state == ConnectingState || d->state == HostLookupState) ? " (connection in progress)" : ""); #endif -#else // !Q_OS_WINRT - // On WinRT we should always connect by name. Lookup and proxy handling are done by the API. - d->startConnectingByName(hostName); -#endif } /*! \overload diff --git a/src/network/socket/qabstractsocketengine.cpp b/src/network/socket/qabstractsocketengine.cpp index 44139ff81d..50462fb11f 100644 --- a/src/network/socket/qabstractsocketengine.cpp +++ b/src/network/socket/qabstractsocketengine.cpp @@ -39,11 +39,7 @@ #include "qabstractsocketengine_p.h" -#ifndef Q_OS_WINRT #include "qnativesocketengine_p.h" -#else -#include "qnativesocketengine_winrt_p.h" -#endif #include "qmutex.h" #include "qnetworkproxy.h" diff --git a/src/network/socket/qlocalserver.cpp b/src/network/socket/qlocalserver.cpp index 5ca2db70b9..251b785dfd 100644 --- a/src/network/socket/qlocalserver.cpp +++ b/src/network/socket/qlocalserver.cpp @@ -195,7 +195,7 @@ QLocalServer::SocketOptions QLocalServer::socketOptions() const \l{https://msdn.microsoft.com/en-us/library/windows/desktop/ms740522(v=vs.85).aspx} {Winsock 2 Socket Handle}. - \li With WinRT and on INTEGRITY, the returned value is the + \li On INTEGRITY, the returned value is the QTcpServer socket descriptor and the type is defined by \l{QTcpServer::socketDescriptor}{socketDescriptor}. diff --git a/src/network/socket/qlocalsocket.cpp b/src/network/socket/qlocalsocket.cpp index 60e753e2e2..ab3fcecf66 100644 --- a/src/network/socket/qlocalsocket.cpp +++ b/src/network/socket/qlocalsocket.cpp @@ -135,7 +135,7 @@ QT_BEGIN_NAMESPACE \l{https://msdn.microsoft.com/en-us/library/windows/desktop/ms740522(v=vs.85).aspx} {Winsock 2 Socket Handle}. - \li With WinRT and on INTEGRITY, the returned value is the + \li On INTEGRITY, the returned value is the QTcpSocket socket descriptor and the type is defined by \l{QTcpSocket::socketDescriptor}{socketDescriptor}. diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp index ad625b758e..6667a6b097 100644 --- a/src/network/socket/qnativesocketengine.cpp +++ b/src/network/socket/qnativesocketengine.cpp @@ -195,7 +195,7 @@ QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() : writeNotifier(nullptr), exceptNotifier(nullptr) { -#if defined(Q_OS_WIN) && !defined(Q_OS_WINRT) +#if defined(Q_OS_WIN) QSysInfo::machineHostName(); // this initializes ws2_32.dll #endif } diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp deleted file mode 100644 index 2eb2141fee..0000000000 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ /dev/null @@ -1,1815 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include - -#include "qnativesocketengine_winrt_p.h" - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#ifndef QT_NO_SSL -#include -#endif - -#include -#include -#include -#include -#include -#include -#include - -using namespace Microsoft::WRL; -using namespace Microsoft::WRL::Wrappers; -using namespace ABI::Windows::Foundation; -using namespace ABI::Windows::Foundation::Collections; -using namespace ABI::Windows::Storage::Streams; -using namespace ABI::Windows::Networking; -using namespace ABI::Windows::Networking::Connectivity; -using namespace ABI::Windows::Networking::Sockets; -#if _MSC_VER >= 1900 -using namespace ABI::Windows::Security::EnterpriseData; -#endif - -typedef ITypedEventHandler ClientConnectedHandler; -typedef ITypedEventHandler DatagramReceivedHandler; -typedef IAsyncOperationWithProgressCompletedHandler SocketReadCompletedHandler; -typedef IAsyncOperationWithProgressCompletedHandler SocketWriteCompletedHandler; -typedef IAsyncOperationWithProgress IAsyncBufferOperation; - -QT_BEGIN_NAMESPACE - -Q_LOGGING_CATEGORY(lcNetworkSocket, "qt.network.socket"); -Q_LOGGING_CATEGORY(lcNetworkSocketVerbose, "qt.network.socket.verbose"); - -#if _MSC_VER >= 1900 -static HRESULT qt_winrt_try_create_thread_network_context(QString host, ComPtr &context) -{ - HRESULT hr; - ComPtr protectionPolicyManager; - - hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Security_EnterpriseData_ProtectionPolicyManager).Get(), - &protectionPolicyManager); - RETURN_HR_IF_FAILED("Could not access ProtectionPolicyManager statics."); - - ComPtr hostNameFactory; - hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(), - &hostNameFactory); - RETURN_HR_IF_FAILED("Could not access HostName factory."); - - ComPtr hostName; - HStringReference hostRef(reinterpret_cast(host.utf16()), host.length()); - hr = hostNameFactory->CreateHostName(hostRef.Get(), &hostName); - RETURN_HR_IF_FAILED("Could not create hostname."); - - ComPtr> op; - hr = protectionPolicyManager->GetPrimaryManagedIdentityForNetworkEndpointAsync(hostName.Get(), &op); - RETURN_HR_IF_FAILED("Could not get identity operation."); - - HSTRING hIdentity; - hr = QWinRTFunctions::await(op, &hIdentity); - RETURN_HR_IF_FAILED("Could not wait for identity operation."); - - // Implies there is no need for a network context for this address - if (hIdentity == nullptr) - return S_OK; - - hr = protectionPolicyManager->CreateCurrentThreadNetworkContext(hIdentity, &context); - RETURN_HR_IF_FAILED("Could not create thread network context"); - - return S_OK; -} -#endif // _MSC_VER >= 1900 - -typedef QHash TcpSocketHash; - -struct SocketHandler -{ - SocketHandler() : socketCount(0) {} - qintptr socketCount; - TcpSocketHash pendingTcpSockets; -}; - -Q_GLOBAL_STATIC(SocketHandler, gSocketHandler) - -struct SocketGlobal -{ - SocketGlobal() - { - HRESULT hr; - hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Storage_Streams_Buffer).Get(), - &bufferFactory); - Q_ASSERT_SUCCEEDED(hr); - } - - ComPtr bufferFactory; -}; -Q_GLOBAL_STATIC(SocketGlobal, g) - -#define READ_BUFFER_SIZE 65536 - -static inline QString qt_QStringFromHString(const HString &string) -{ - UINT32 length; - PCWSTR rawString = string.GetRawBuffer(&length); - return QString::fromWCharArray(rawString, length); -} - -class SocketEngineWorker : public QObject -{ - Q_OBJECT -public: - SocketEngineWorker(QNativeSocketEnginePrivate *engine) - : enginePrivate(engine) - { - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << engine; - } - - ~SocketEngineWorker() - { - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; - if (Q_UNLIKELY(initialReadOp)) { - qCDebug(lcNetworkSocket) << Q_FUNC_INFO << "Closing initial read operation"; - ComPtr info; - HRESULT hr = initialReadOp.As(&info); - Q_ASSERT_SUCCEEDED(hr); - if (info) { - hr = info->Cancel(); - Q_ASSERT_SUCCEEDED(hr); - hr = info->Close(); - Q_ASSERT_SUCCEEDED(hr); - } - } - - if (readOp) { - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Closing read operation"; - ComPtr info; - HRESULT hr = readOp.As(&info); - Q_ASSERT_SUCCEEDED(hr); - if (info) { - hr = info->Cancel(); - Q_ASSERT_SUCCEEDED(hr); - hr = info->Close(); - Q_ASSERT_SUCCEEDED(hr); - } - } - - if (connectOp) { - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Closing connect operation"; - ComPtr info; - HRESULT hr = connectOp.As(&info); - Q_ASSERT_SUCCEEDED(hr); - if (info) { - hr = info->Cancel(); - Q_ASSERT_SUCCEEDED(hr); - hr = info->Close(); - Q_ASSERT_SUCCEEDED(hr); - } - } - } - -signals: - void connectOpFinished(bool success, QAbstractSocket::SocketError error, WinRTSocketEngine::ErrorString errorString); - void newDataReceived(); - void socketErrorOccured(QAbstractSocket::SocketError error); - -public: - void startReading() - { - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; - ComPtr buffer; - HRESULT hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer); - Q_ASSERT_SUCCEEDED(hr); - ComPtr stream; - hr = tcpSocket->get_InputStream(&stream); - Q_ASSERT_SUCCEEDED(hr); - hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, initialReadOp.GetAddressOf()); - Q_ASSERT_SUCCEEDED(hr); - enginePrivate->socketState = QAbstractSocket::ConnectedState; - hr = initialReadOp->put_Completed(Callback(this, &SocketEngineWorker::onReadyRead).Get()); - Q_ASSERT_SUCCEEDED(hr); - } - - HRESULT onConnectOpFinished(IAsyncAction *action, AsyncStatus) - { - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; - HRESULT hr = action->GetResults(); - if (FAILED(hr)) { - if (hr == HRESULT_FROM_WIN32(WSAETIMEDOUT)) { - emit connectOpFinished(false, QAbstractSocket::NetworkError, WinRTSocketEngine::ConnectionTimeOutErrorString); - return S_OK; - } else if (hr == HRESULT_FROM_WIN32(WSAEHOSTUNREACH)) { - emit connectOpFinished(false, QAbstractSocket::HostNotFoundError, WinRTSocketEngine::HostUnreachableErrorString); - return S_OK; - } else if (hr == HRESULT_FROM_WIN32(WSAECONNREFUSED)) { - emit connectOpFinished(false, QAbstractSocket::ConnectionRefusedError, WinRTSocketEngine::ConnectionRefusedErrorString); - return S_OK; - } else { - emit connectOpFinished(false, QAbstractSocket::UnknownSocketError, WinRTSocketEngine::UnknownSocketErrorString); - return S_OK; - } - } - - // The callback might be triggered several times if we do not cancel/reset it here - if (connectOp) { - ComPtr info; - hr = connectOp.As(&info); - Q_ASSERT_SUCCEEDED(hr); - if (info) { - hr = info->Cancel(); - Q_ASSERT_SUCCEEDED(hr); - hr = info->Close(); - Q_ASSERT_SUCCEEDED(hr); - } - hr = connectOp.Reset(); - Q_ASSERT_SUCCEEDED(hr); - } - - emit connectOpFinished(true, QAbstractSocket::UnknownSocketError, WinRTSocketEngine::UnknownSocketErrorString); - return S_OK; - } - - HRESULT OnNewDatagramReceived(IDatagramSocket *, IDatagramSocketMessageReceivedEventArgs *args) - { - qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO; - WinRtDatagram datagram; - QHostAddress returnAddress; - ComPtr remoteHost; - HRESULT hr = args->get_RemoteAddress(&remoteHost); - RETURN_OK_IF_FAILED("Could not obtain remote host"); - HString remoteHostString; - hr = remoteHost->get_CanonicalName(remoteHostString.GetAddressOf()); - RETURN_OK_IF_FAILED("Could not obtain remote host's canonical name"); - returnAddress.setAddress(qt_QStringFromHString(remoteHostString)); - datagram.header.senderAddress = returnAddress; - HString remotePort; - hr = args->get_RemotePort(remotePort.GetAddressOf()); - RETURN_OK_IF_FAILED("Could not obtain remote port"); - datagram.header.senderPort = qt_QStringFromHString(remotePort).toInt(); - - ComPtr reader; - hr = args->GetDataReader(&reader); - RETURN_OK_IF_FAILED("Could not obtain data reader"); - quint32 length; - hr = reader->get_UnconsumedBufferLength(&length); - RETURN_OK_IF_FAILED("Could not obtain unconsumed buffer length"); - datagram.data.resize(length); - hr = reader->ReadBytes(length, reinterpret_cast(datagram.data.data())); - RETURN_OK_IF_FAILED("Could not read datagram"); - - QMutexLocker locker(&mutex); - // Notify the engine about new datagrams being present at the next event loop iteration - if (emitDataReceived) - emit newDataReceived(); - pendingDatagrams << datagram; - - return S_OK; - } - - HRESULT onReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status) - { - qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO; - if (asyncInfo == initialReadOp.Get()) { - initialReadOp.Reset(); - } else if (asyncInfo == readOp.Get()) { - readOp.Reset(); - } else { - Q_ASSERT(false); - } - - // A read in UnconnectedState will close the socket and return -1 and thus tell the caller, - // that the connection was closed. The socket cannot be closed here, as the subsequent read - // might fail then. - if (status == Error || status == Canceled) { - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Remote host closed"; - emit socketErrorOccured(QAbstractSocket::RemoteHostClosedError); - return S_OK; - } - - ComPtr buffer; - HRESULT hr = asyncInfo->GetResults(&buffer); - if (FAILED(hr)) { - qErrnoWarning(hr, "Failed to get read results buffer"); - emit socketErrorOccured(QAbstractSocket::UnknownSocketError); - return S_OK; - } - - UINT32 bufferLength; - hr = buffer->get_Length(&bufferLength); - if (FAILED(hr)) { - qErrnoWarning(hr, "Failed to get buffer length"); - emit socketErrorOccured(QAbstractSocket::UnknownSocketError); - return S_OK; - } - // A zero sized buffer length signals, that the remote host closed the connection. The socket - // cannot be closed though, as the following read might have socket descriptor -1 and thus and - // the closing of the socket won't be communicated to the caller. So only the error is set. The - // actual socket close happens inside of read. - if (!bufferLength) { - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Remote host closed"; - emit socketErrorOccured(QAbstractSocket::RemoteHostClosedError); - return S_OK; - } - - ComPtr byteArrayAccess; - hr = buffer.As(&byteArrayAccess); - if (FAILED(hr)) { - qErrnoWarning(hr, "Failed to get cast buffer"); - emit socketErrorOccured(QAbstractSocket::UnknownSocketError); - return S_OK; - } - byte *data; - hr = byteArrayAccess->Buffer(&data); - if (FAILED(hr)) { - qErrnoWarning(hr, "Failed to access buffer data"); - emit socketErrorOccured(QAbstractSocket::UnknownSocketError); - return S_OK; - } - - QByteArray newData(reinterpret_cast(data), qint64(bufferLength)); - - QMutexLocker readLocker(&mutex); - emit newDataReceived(); - pendingData.append(newData); - readLocker.unlock(); - - hr = QEventDispatcherWinRT::runOnXamlThread([buffer, this]() { - UINT32 readBufferLength; - ComPtr stream; - HRESULT hr = tcpSocket->get_InputStream(&stream); - if (FAILED(hr)) { - qErrnoWarning(hr, "Failed to obtain input stream"); - emit socketErrorOccured(QAbstractSocket::UnknownSocketError); - return S_OK; - } - - // Reuse the stream buffer - hr = buffer->get_Capacity(&readBufferLength); - if (FAILED(hr)) { - qErrnoWarning(hr, "Failed to get buffer capacity"); - emit socketErrorOccured(QAbstractSocket::UnknownSocketError); - return S_OK; - } - hr = buffer->put_Length(0); - if (FAILED(hr)) { - qErrnoWarning(hr, "Failed to set buffer length"); - emit socketErrorOccured(QAbstractSocket::UnknownSocketError); - return S_OK; - } - - hr = stream->ReadAsync(buffer.Get(), readBufferLength, InputStreamOptions_Partial, &readOp); - if (FAILED(hr)) { - qErrnoWarning(hr, "onReadyRead(): Could not read into socket stream buffer."); - emit socketErrorOccured(QAbstractSocket::UnknownSocketError); - return S_OK; - } - hr = readOp->put_Completed(Callback(this, &SocketEngineWorker::onReadyRead).Get()); - if (FAILED(hr)) { - qErrnoWarning(hr, "onReadyRead(): Failed to set socket read callback."); - emit socketErrorOccured(QAbstractSocket::UnknownSocketError); - return S_OK; - } - return S_OK; - }); - Q_ASSERT_SUCCEEDED(hr); - return S_OK; - } - - void setTcpSocket(ComPtr socket) { tcpSocket = socket; } - -private: - friend class QNativeSocketEngine; - ComPtr tcpSocket; - - QList pendingDatagrams; - bool emitDataReceived = true; - QByteArray pendingData; - - // Protects pendingData/pendingDatagrams which are accessed from native callbacks - QMutex mutex; - - ComPtr connectOp; - ComPtr> initialReadOp; - ComPtr> readOp; - - QNativeSocketEnginePrivate *enginePrivate; -}; - -static QByteArray socketDescription(const QAbstractSocketEngine *s) -{ - QByteArray result; - if (const QObject *o = s->parent()) { - const QString name = o->objectName(); - if (!name.isEmpty()) { - result += '"'; - result += name.toLocal8Bit(); - result += "\"/"; - } - result += o->metaObject()->className(); - } - return result; -} - -// Common constructs -#define Q_CHECK_VALID_SOCKETLAYER(function, returnValue) do { \ - if (!isValid()) { \ - qWarning(""#function" was called on an uninitialized socket device"); \ - return returnValue; \ - } } while (0) -#define Q_CHECK_INVALID_SOCKETLAYER(function, returnValue) do { \ - if (isValid()) { \ - qWarning(""#function" was called on an already initialized socket device"); \ - return returnValue; \ - } } while (0) -#define Q_CHECK_STATE(function, checkState, returnValue) do { \ - if (d->socketState != (checkState)) { \ - qWarning(""#function" was not called in "#checkState); \ - return (returnValue); \ - } } while (0) -#define Q_CHECK_NOT_STATE(function, checkState, returnValue) do { \ - if (d->socketState == (checkState)) { \ - qWarning(""#function" was called in "#checkState); \ - return (returnValue); \ - } } while (0) -#define Q_CHECK_STATES(function, state1, state2, returnValue) do { \ - if (d->socketState != (state1) && d->socketState != (state2)) { \ - qWarning(""#function" was called" \ - " not in "#state1" or "#state2); \ - return (returnValue); \ - } } while (0) -#define Q_CHECK_STATES3(function, state1, state2, state3, returnValue) do { \ - if (d->socketState != (state1) && d->socketState != (state2) && d->socketState != (state3)) { \ - qWarning(""#function" was called" \ - " not in "#state1", "#state2" or "#state3); \ - return (returnValue); \ - } } while (0) -#define Q_CHECK_TYPE(function, type, returnValue) do { \ - if (d->socketType != (type)) { \ - qWarning(#function" was called by a" \ - " socket other than "#type""); \ - return (returnValue); \ - } } while (0) -#define Q_TR(a) QT_TRANSLATE_NOOP(QNativeSocketEngine, a) - -template -static AsyncStatus opStatus(const ComPtr &op) -{ - ComPtr info; - HRESULT hr = op.As(&info); - Q_ASSERT_SUCCEEDED(hr); - AsyncStatus status; - hr = info->get_Status(&status); - Q_ASSERT_SUCCEEDED(hr); - return status; -} - -static qint64 writeIOStream(ComPtr stream, const char *data, qint64 len) -{ - qCDebug(lcNetworkSocket) << Q_FUNC_INFO << data << len; - ComPtr buffer; - HRESULT hr = g->bufferFactory->Create(len, &buffer); - Q_ASSERT_SUCCEEDED(hr); - hr = buffer->put_Length(len); - Q_ASSERT_SUCCEEDED(hr); - ComPtr byteArrayAccess; - hr = buffer.As(&byteArrayAccess); - Q_ASSERT_SUCCEEDED(hr); - byte *bytes; - hr = byteArrayAccess->Buffer(&bytes); - Q_ASSERT_SUCCEEDED(hr); - memcpy(bytes, data, len); - ComPtr> op; - hr = stream->WriteAsync(buffer.Get(), &op); - RETURN_IF_FAILED("Failed to write to stream", return -1); - UINT32 bytesWritten; - hr = QWinRTFunctions::await(op, &bytesWritten); - RETURN_IF_FAILED("Failed to write to stream", return -1); - return bytesWritten; -} - -QNativeSocketEngine::QNativeSocketEngine(QObject *parent) - : QAbstractSocketEngine(*new QNativeSocketEnginePrivate(), parent) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << parent; - qRegisterMetaType(); - qRegisterMetaType(); - Q_D(QNativeSocketEngine); -#ifndef QT_NO_SSL - if (parent) - d->sslSocket = qobject_cast(parent->parent()); -#endif - - connect(this, &QNativeSocketEngine::connectionReady, - this, &QNativeSocketEngine::connectionNotification, Qt::QueuedConnection); - connect(this, &QNativeSocketEngine::readReady, - this, &QNativeSocketEngine::processReadReady, Qt::QueuedConnection); - connect(this, &QNativeSocketEngine::writeReady, - this, &QNativeSocketEngine::writeNotification, Qt::QueuedConnection); - connect(d->worker, &SocketEngineWorker::connectOpFinished, - this, &QNativeSocketEngine::handleConnectOpFinished, Qt::QueuedConnection); - connect(d->worker, &SocketEngineWorker::newDataReceived, this, &QNativeSocketEngine::handleNewData, Qt::QueuedConnection); - connect(d->worker, &SocketEngineWorker::socketErrorOccured, - this, &QNativeSocketEngine::handleTcpError, Qt::QueuedConnection); -} - -QNativeSocketEngine::~QNativeSocketEngine() -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; - close(); -} - -bool QNativeSocketEngine::initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << type << protocol; - Q_D(QNativeSocketEngine); - if (isValid()) - close(); - - // Create the socket - if (!d->createNewSocket(type, protocol)) - return false; - - if (type == QAbstractSocket::UdpSocket) { - // Set the broadcasting flag if it's a UDP socket. - if (!setOption(BroadcastSocketOption, 1)) { - d->setError(QAbstractSocket::UnsupportedSocketOperationError, - WinRTSocketEngine::BroadcastingInitFailedErrorString); - close(); - return false; - } - - // Set some extra flags that are interesting to us, but accept failure - setOption(ReceivePacketInformation, 1); - setOption(ReceiveHopLimit, 1); - } - - - // Make sure we receive out-of-band data - if (type == QAbstractSocket::TcpSocket - && !setOption(ReceiveOutOfBandData, 1)) { - qWarning("QNativeSocketEngine::initialize unable to inline out-of-band data"); - } - - - d->socketType = type; - d->socketProtocol = protocol; - return true; -} - -bool QNativeSocketEngine::initialize(qintptr socketDescriptor, QAbstractSocket::SocketState socketState) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << socketDescriptor << socketState; - Q_D(QNativeSocketEngine); - - if (isValid()) - close(); - - // Currently, only TCP sockets are initialized this way. - IStreamSocket *socket = gSocketHandler->pendingTcpSockets.take(socketDescriptor); - d->socketDescriptor = qintptr(socket); - d->socketType = QAbstractSocket::TcpSocket; - - if (!d->socketDescriptor || !d->fetchConnectionParameters()) { - d->setError(QAbstractSocket::UnsupportedSocketOperationError, - WinRTSocketEngine::InvalidSocketErrorString); - d->socketDescriptor = -1; - return false; - } - - // Start processing incoming data - if (d->socketType == QAbstractSocket::TcpSocket) { - HRESULT hr = QEventDispatcherWinRT::runOnXamlThread([d, socket, this]() { - d->worker->setTcpSocket(socket); - d->worker->startReading(); - return S_OK; - }); - if (FAILED(hr)) - return false; - } else { - d->socketState = socketState; - } - - return true; -} - -qintptr QNativeSocketEngine::socketDescriptor() const -{ - Q_D(const QNativeSocketEngine); - return d->socketDescriptor; -} - -bool QNativeSocketEngine::isValid() const -{ - Q_D(const QNativeSocketEngine); - return d->socketDescriptor != -1; -} - -bool QNativeSocketEngine::connectToHost(const QHostAddress &address, quint16 port) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << address << port; - Q_D(QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::connectToHost(), false); - Q_CHECK_STATES3(QNativeSocketEngine::connectToHost(), QAbstractSocket::BoundState, - QAbstractSocket::UnconnectedState, QAbstractSocket::ConnectingState, false); - const QString addressString = address.toString(); - return connectToHostByName(addressString, port); -} - -bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << name << port; - Q_D(QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::connectToHostByName(), false); - Q_CHECK_STATES3(QNativeSocketEngine::connectToHostByName(), QAbstractSocket::BoundState, - QAbstractSocket::UnconnectedState, QAbstractSocket::ConnectingState, false); - HRESULT hr; - -#if _MSC_VER >= 1900 - ComPtr networkContext; - if (!qEnvironmentVariableIsEmpty("QT_WINRT_USE_THREAD_NETWORK_CONTEXT")) { - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Creating network context"; - hr = qt_winrt_try_create_thread_network_context(name, networkContext); - if (FAILED(hr)) { - setError(QAbstractSocket::ConnectionRefusedError, QLatin1String("Could not create thread network context.")); - d->socketState = QAbstractSocket::ConnectedState; - return true; - } - } -#endif // _MSC_VER >= 1900 - - HStringReference hostNameRef(reinterpret_cast(name.utf16())); - ComPtr hostNameFactory; - hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(), - &hostNameFactory); - Q_ASSERT_SUCCEEDED(hr); - ComPtr remoteHost; - hr = hostNameFactory->CreateHostName(hostNameRef.Get(), &remoteHost); - RETURN_FALSE_IF_FAILED("QNativeSocketEngine::connectToHostByName: Could not create hostname."); - - const QString portString = QString::number(port); - HStringReference portReference(reinterpret_cast(portString.utf16())); - if (d->socketType == QAbstractSocket::TcpSocket) - hr = d->tcpSocket()->ConnectAsync(remoteHost.Get(), portReference.Get(), &d->worker->connectOp); - else if (d->socketType == QAbstractSocket::UdpSocket) - hr = d->udpSocket()->ConnectAsync(remoteHost.Get(), portReference.Get(), &d->worker->connectOp); - if (hr == E_ACCESSDENIED) { - qErrnoWarning(hr, "QNativeSocketEngine::connectToHostByName: Unable to connect to host (%s:%hu/%s). " - "Please check your manifest capabilities.", - qPrintable(name), port, socketDescription(this).constData()); - return false; - } - Q_ASSERT_SUCCEEDED(hr); - -#if _MSC_VER >= 1900 - if (networkContext != nullptr) { - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "Closing network context"; - ComPtr networkContextCloser; - hr = networkContext.As(&networkContextCloser); - Q_ASSERT_SUCCEEDED(hr); - hr = networkContextCloser->Close(); - Q_ASSERT_SUCCEEDED(hr); - } -#endif // _MSC_VER >= 1900 - - d->socketState = QAbstractSocket::ConnectingState; - QEventDispatcherWinRT::runOnXamlThread([d, &hr]() { - hr = d->worker->connectOp->put_Completed(Callback( - d->worker, &SocketEngineWorker::onConnectOpFinished).Get()); - RETURN_OK_IF_FAILED("connectToHostByName: Could not register \"connectOp\" callback"); - return S_OK; - }); - if (FAILED(hr)) - return false; - - return d->socketState == QAbstractSocket::ConnectedState; -} - -bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << address << port; - Q_D(QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bind(), false); - Q_CHECK_STATE(QNativeSocketEngine::bind(), QAbstractSocket::UnconnectedState, false); - - HRESULT hr; - // runOnXamlThread may only return S_OK (will assert otherwise) so no need to check its result. - // hr is set inside the lambda though. If an error occurred hr will point that out. - bool specificErrorSet = false; - QEventDispatcherWinRT::runOnXamlThread([address, d, &hr, port, &specificErrorSet, this]() { - ComPtr hostAddress; - - if (address != QHostAddress::Any && address != QHostAddress::AnyIPv4 && address != QHostAddress::AnyIPv6) { - ComPtr hostNameFactory; - hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(), - &hostNameFactory); - RETURN_OK_IF_FAILED("QNativeSocketEngine::bind: Could not obtain hostname factory"); - const QString addressString = address.toString(); - HStringReference addressRef(reinterpret_cast(addressString.utf16())); - hr = hostNameFactory->CreateHostName(addressRef.Get(), &hostAddress); - RETURN_OK_IF_FAILED("QNativeSocketEngine::bind: Could not create hostname."); - } - - QString portQString = port ? QString::number(port) : QString(); - HStringReference portString(reinterpret_cast(portQString.utf16())); - - ComPtr op; - if (d->socketType == QAbstractSocket::TcpSocket) { - if (!d->tcpListener) { - hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_StreamSocketListener).Get(), - &d->tcpListener); - RETURN_OK_IF_FAILED("QNativeSocketEngine::bind: Could not create tcp listener"); - } - - hr = d->tcpListener->add_ConnectionReceived( - Callback(d, &QNativeSocketEnginePrivate::handleClientConnection).Get(), - &d->connectionToken); - RETURN_OK_IF_FAILED("QNativeSocketEngine::bind: Could not register client connection callback"); - hr = d->tcpListener->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); - } else if (d->socketType == QAbstractSocket::UdpSocket) { - hr = d->udpSocket()->BindEndpointAsync(hostAddress.Get(), portString.Get(), &op); - } - if (hr == E_ACCESSDENIED) { - qErrnoWarning(hr, "Unable to bind socket (%s:%hu/%s). Please check your manifest capabilities.", - qPrintable(address.toString()), port, socketDescription(this).constData()); - d->setError(QAbstractSocket::SocketAccessError, - WinRTSocketEngine::AccessErrorString); - d->socketState = QAbstractSocket::UnconnectedState; - specificErrorSet = true; - return S_OK; - } - RETURN_OK_IF_FAILED("QNativeSocketEngine::bind: Unable to bind socket"); - - hr = QWinRTFunctions::await(op); - if (hr == 0x80072741) { // The requested address is not valid in its context - d->setError(QAbstractSocket::SocketAddressNotAvailableError, - WinRTSocketEngine::AddressNotAvailableErrorString); - d->socketState = QAbstractSocket::UnconnectedState; - specificErrorSet = true; - return S_OK; - // Only one usage of each socket address (protocol/network address/port) is normally permitted - } else if (hr == 0x80072740) { - d->setError(QAbstractSocket::AddressInUseError, - WinRTSocketEngine::AddressInuseErrorString); - d->socketState = QAbstractSocket::UnconnectedState; - specificErrorSet = true; - return S_OK; - } - RETURN_OK_IF_FAILED("QNativeSocketEngine::bind: Could not wait for bind to finish"); - return S_OK; - }); - if (FAILED(hr)) { - if (!specificErrorSet) { - d->setError(QAbstractSocket::UnknownSocketError, - WinRTSocketEngine::UnknownSocketErrorString); - d->socketState = QAbstractSocket::UnconnectedState; - } - return false; - } - - d->socketState = QAbstractSocket::BoundState; - return d->fetchConnectionParameters(); -} - -bool QNativeSocketEngine::listen() -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; - Q_D(QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::listen(), false); - Q_CHECK_STATE(QNativeSocketEngine::listen(), QAbstractSocket::BoundState, false); -#if QT_CONFIG(sctp) - Q_CHECK_TYPES(QNativeSocketEngine::listen(), QAbstractSocket::TcpSocket, - QAbstractSocket::SctpSocket, false); -#else - Q_CHECK_TYPE(QNativeSocketEngine::listen(), QAbstractSocket::TcpSocket, false); -#endif - - if (d->tcpListener && d->socketDescriptor != -1) { - d->socketState = QAbstractSocket::ListeningState; - return true; - } - return false; -} - -int QNativeSocketEngine::accept() -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; - Q_D(QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::accept(), -1); - Q_CHECK_STATE(QNativeSocketEngine::accept(), QAbstractSocket::ListeningState, -1); -#if QT_CONFIG(sctp) - Q_CHECK_TYPES(QNativeSocketEngine::accept(), QAbstractSocket::TcpSocket, - QAbstractSocket::SctpSocket, -1); -#else - Q_CHECK_TYPE(QNativeSocketEngine::accept(), QAbstractSocket::TcpSocket, -1); -#endif - - if (d->socketDescriptor == -1 || d->pendingConnections.isEmpty()) { - d->setError(QAbstractSocket::TemporaryError, WinRTSocketEngine::TemporaryErrorString); - return -1; - } - - if (d->socketType == QAbstractSocket::TcpSocket) { - IStreamSocket *socket = d->pendingConnections.takeFirst(); - - SocketHandler *handler = gSocketHandler(); - handler->pendingTcpSockets.insert(++handler->socketCount, socket); - return handler->socketCount; - } - - return -1; -} - -void QNativeSocketEngine::close() -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; - Q_D(QNativeSocketEngine); - - if (d->closingDown) - return; - - if (d->pendingReadNotification) { - // We use QPointer here to see if this QNativeSocketEngine was deleted as a result of - // finishing and cleaning up a network request when calling "processReadReady". - QPointer alive(this); - processReadReady(); - if (alive.isNull()) - return; - } - - d->closingDown = true; - - d->notifyOnRead = false; - d->notifyOnWrite = false; - d->notifyOnException = false; - d->emitReadReady = false; - - HRESULT hr; - if (d->socketType == QAbstractSocket::TcpSocket) { - hr = QEventDispatcherWinRT::runOnXamlThread([d]() { - HRESULT hr; - // To close the connection properly (not with a hard reset) all pending read operation have to - // be finished or cancelled. The API isn't available on Windows 8.1 though. - ComPtr socket3; - hr = d->tcpSocket()->QueryInterface(IID_PPV_ARGS(&socket3)); - Q_ASSERT_SUCCEEDED(hr); - - ComPtr action; - hr = socket3->CancelIOAsync(&action); - Q_ASSERT_SUCCEEDED(hr); - hr = QWinRTFunctions::await(action, QWinRTFunctions::YieldThread, 5000); - // If there is no pending IO (no read established before) the function will fail with - // "function was called at an unexpected time" which is fine. - // Timeout is fine as well. The result will be the socket being hard reset instead of - // being closed gracefully - if (hr != E_ILLEGAL_METHOD_CALL && hr != ERROR_TIMEOUT) - Q_ASSERT_SUCCEEDED(hr); - return S_OK; - }); - Q_ASSERT_SUCCEEDED(hr); - } - - if (d->socketDescriptor != -1) { - ComPtr socket; - if (d->socketType == QAbstractSocket::TcpSocket) { - hr = d->tcpSocket()->QueryInterface(IID_PPV_ARGS(&socket)); - Q_ASSERT_SUCCEEDED(hr); - hr = d->tcpSocket()->Release(); - Q_ASSERT_SUCCEEDED(hr); - } else if (d->socketType == QAbstractSocket::UdpSocket) { - hr = d->udpSocket()->QueryInterface(IID_PPV_ARGS(&socket)); - Q_ASSERT_SUCCEEDED(hr); - hr = d->udpSocket()->Release(); - Q_ASSERT_SUCCEEDED(hr); - } - - if (socket) { - hr = socket->Close(); - Q_ASSERT_SUCCEEDED(hr); - } - d->socketDescriptor = -1; - } - d->socketState = QAbstractSocket::UnconnectedState; - d->hasSetSocketError = false; - d->localPort = 0; - d->localAddress.clear(); - d->peerPort = 0; - d->peerAddress.clear(); - d->inboundStreamCount = d->outboundStreamCount = 0; -} - -bool QNativeSocketEngine::joinMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface) -{ - Q_D(QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::joinMulticastGroup(), false); - Q_CHECK_STATE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::BoundState, false); - Q_CHECK_TYPE(QNativeSocketEngine::joinMulticastGroup(), QAbstractSocket::UdpSocket, false); - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << groupAddress << iface; - Q_UNIMPLEMENTED(); - return false; -} - -bool QNativeSocketEngine::leaveMulticastGroup(const QHostAddress &groupAddress, const QNetworkInterface &iface) -{ - Q_D(QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::leaveMulticastGroup(), false); - Q_CHECK_STATE(QNativeSocketEngine::leaveMulticastGroup(), QAbstractSocket::BoundState, false); - Q_CHECK_TYPE(QNativeSocketEngine::leaveMulticastGroup(), QAbstractSocket::UdpSocket, false); - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << groupAddress << iface; - Q_UNIMPLEMENTED(); - return false; -} - -QNetworkInterface QNativeSocketEngine::multicastInterface() const -{ - Q_D(const QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::multicastInterface(), QNetworkInterface()); - Q_CHECK_TYPE(QNativeSocketEngine::multicastInterface(), QAbstractSocket::UdpSocket, QNetworkInterface()); - Q_UNIMPLEMENTED(); - return QNetworkInterface(); -} - -bool QNativeSocketEngine::setMulticastInterface(const QNetworkInterface &iface) -{ - Q_D(QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::setMulticastInterface(), false); - Q_CHECK_TYPE(QNativeSocketEngine::setMulticastInterface(), QAbstractSocket::UdpSocket, false); - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << iface; - Q_UNIMPLEMENTED(); - return false; -} - -qint64 QNativeSocketEngine::bytesAvailable() const -{ - Q_D(const QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::bytesAvailable(), -1); - Q_CHECK_NOT_STATE(QNativeSocketEngine::bytesAvailable(), QAbstractSocket::UnconnectedState, -1); - if (d->socketType != QAbstractSocket::TcpSocket) - return -1; - - QMutexLocker locker(&d->worker->mutex); - const qint64 bytesAvailable = d->worker->pendingData.length(); - - qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << bytesAvailable; - return bytesAvailable; -} - -qint64 QNativeSocketEngine::read(char *data, qint64 maxlen) -{ - qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << maxlen; - Q_D(QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::read(), -1); - Q_CHECK_STATES(QNativeSocketEngine::read(), QAbstractSocket::ConnectedState, QAbstractSocket::BoundState, -1); - if (d->socketType != QAbstractSocket::TcpSocket) - return -1; - - // There will be a read notification when the socket was closed by the remote host. If that - // happens and there isn't anything left in the buffer, we have to return -1 in order to signal - // the closing of the socket. - QMutexLocker mutexLocker(&d->worker->mutex); - if (d->worker->pendingData.isEmpty() && d->socketState != QAbstractSocket::ConnectedState) { - close(); - return -1; - } - - QByteArray readData; - const int copyLength = qMin(maxlen, qint64(d->worker->pendingData.length())); - if (maxlen >= d->worker->pendingData.length()) { - qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << "Reading full buffer"; - readData = d->worker->pendingData; - d->worker->pendingData.clear(); - d->emitReadReady = true; - } else { - qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << "Reading part of the buffer (" - << copyLength << "of" << d->worker->pendingData.length() << "bytes"; - readData = d->worker->pendingData.left(maxlen); - d->worker->pendingData.remove(0, maxlen); - if (d->notifyOnRead) { - d->pendingReadNotification = true; - emit readReady(); - } - } - mutexLocker.unlock(); - - memcpy(data, readData, copyLength); - qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << "Read" << copyLength << "bytes"; - return copyLength; -} - -qint64 QNativeSocketEngine::write(const char *data, qint64 len) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << data << len; - Q_D(QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::write(), -1); - Q_CHECK_STATE(QNativeSocketEngine::write(), QAbstractSocket::ConnectedState, -1); - - HRESULT hr = E_FAIL; - ComPtr stream; - if (d->socketType == QAbstractSocket::TcpSocket) - hr = d->tcpSocket()->get_OutputStream(&stream); - else if (d->socketType == QAbstractSocket::UdpSocket) - hr = d->udpSocket()->get_OutputStream(&stream); - Q_ASSERT_SUCCEEDED(hr); - - qint64 bytesWritten = writeIOStream(stream, data, len); - if (bytesWritten < 0) - d->setError(QAbstractSocket::SocketAccessError, WinRTSocketEngine::AccessErrorString); - else if (bytesWritten > 0 && d->notifyOnWrite) - emit writeReady(); - - return bytesWritten; -} - -qint64 QNativeSocketEngine::readDatagram(char *data, qint64 maxlen, QIpPacketHeader *header, - PacketHeaderOptions) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << maxlen; -#ifndef QT_NO_UDPSOCKET - Q_D(QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::readDatagram(), -1); - Q_CHECK_STATES(QNativeSocketEngine::readDatagram(), QAbstractSocket::BoundState, - QAbstractSocket::ConnectedState, -1); - - QMutexLocker locker(&d->worker->mutex); - if (d->socketType != QAbstractSocket::UdpSocket || d->worker->pendingDatagrams.isEmpty()) { - if (header) - header->clear(); - return -1; - } - - WinRtDatagram datagram = d->worker->pendingDatagrams.takeFirst(); - if (header) - *header = datagram.header; - - QByteArray readOrigin; - if (maxlen < datagram.data.length()) - readOrigin = datagram.data.left(maxlen); - else - readOrigin = datagram.data; - if (d->worker->pendingDatagrams.isEmpty()) { - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << "That's all folks"; - d->worker->emitDataReceived = true; - d->emitReadReady = true; - } - - locker.unlock(); - memcpy(data, readOrigin, qMin(maxlen, qint64(datagram.data.length()))); - return readOrigin.length(); -#else - Q_UNUSED(data) - Q_UNUSED(maxlen) - Q_UNUSED(header) - return -1; -#endif // QT_NO_UDPSOCKET -} - -qint64 QNativeSocketEngine::writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << data << len; -#ifndef QT_NO_UDPSOCKET - Q_D(QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::writeDatagram(), -1); - Q_CHECK_STATES(QNativeSocketEngine::writeDatagram(), QAbstractSocket::BoundState, - QAbstractSocket::ConnectedState, -1); - - if (d->socketType != QAbstractSocket::UdpSocket) - return -1; - - ComPtr remoteHost; - ComPtr hostNameFactory; - - HRESULT hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(), - &hostNameFactory); - Q_ASSERT_SUCCEEDED(hr); - const QString addressString = header.destinationAddress.toString(); - HStringReference hostNameRef(reinterpret_cast(addressString.utf16())); - hr = hostNameFactory->CreateHostName(hostNameRef.Get(), &remoteHost); - RETURN_IF_FAILED("QNativeSocketEngine::writeDatagram: Could not create hostname.", return -1); - - ComPtr> streamOperation; - ComPtr stream; - const QString portString = QString::number(header.destinationPort); - HStringReference portRef(reinterpret_cast(portString.utf16())); - hr = d->udpSocket()->GetOutputStreamAsync(remoteHost.Get(), portRef.Get(), &streamOperation); - Q_ASSERT_SUCCEEDED(hr); - - hr = QWinRTFunctions::await(streamOperation, stream.GetAddressOf()); - Q_ASSERT_SUCCEEDED(hr); - - return writeIOStream(stream, data, len); -#else - Q_UNUSED(data) - Q_UNUSED(len) - Q_UNUSED(header) - return -1; -#endif // QT_NO_UDPSOCKET -} - -bool QNativeSocketEngine::hasPendingDatagrams() const -{ - Q_D(const QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::hasPendingDatagrams(), false); - Q_CHECK_NOT_STATE(QNativeSocketEngine::hasPendingDatagrams(), QAbstractSocket::UnconnectedState, false); - Q_CHECK_TYPE(QNativeSocketEngine::hasPendingDatagrams(), QAbstractSocket::UdpSocket, false); - - QMutexLocker locker(&d->worker->mutex); - return d->worker->pendingDatagrams.length() > 0; -} - -qint64 QNativeSocketEngine::pendingDatagramSize() const -{ - Q_D(const QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::pendingDatagramSize(), -1); - Q_CHECK_TYPE(QNativeSocketEngine::pendingDatagramSize(), QAbstractSocket::UdpSocket, -1); - - QMutexLocker locker(&d->worker->mutex); - if (d->worker->pendingDatagrams.isEmpty()) - return -1; - - return d->worker->pendingDatagrams.at(0).data.length(); -} - -qint64 QNativeSocketEngine::bytesToWrite() const -{ - return 0; -} - -qint64 QNativeSocketEngine::receiveBufferSize() const -{ - Q_D(const QNativeSocketEngine); - return d->option(QAbstractSocketEngine::ReceiveBufferSocketOption); -} - -void QNativeSocketEngine::setReceiveBufferSize(qint64 bufferSize) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << bufferSize; - Q_D(QNativeSocketEngine); - d->setOption(QAbstractSocketEngine::ReceiveBufferSocketOption, bufferSize); -} - -qint64 QNativeSocketEngine::sendBufferSize() const -{ - Q_D(const QNativeSocketEngine); - return d->option(QAbstractSocketEngine::SendBufferSocketOption); -} - -void QNativeSocketEngine::setSendBufferSize(qint64 bufferSize) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << bufferSize; - Q_D(QNativeSocketEngine); - d->setOption(QAbstractSocketEngine::SendBufferSocketOption, bufferSize); -} - -int QNativeSocketEngine::option(QAbstractSocketEngine::SocketOption option) const -{ - Q_D(const QNativeSocketEngine); - return d->option(option); -} - -bool QNativeSocketEngine::setOption(QAbstractSocketEngine::SocketOption option, int value) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << option << value; - Q_D(QNativeSocketEngine); - return d->setOption(option, value); -} - -bool QNativeSocketEngine::waitForRead(int msecs, bool *timedOut) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << msecs; - Q_D(QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForRead(), false); - Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForRead(), - QAbstractSocket::UnconnectedState, false); - - if (timedOut) - *timedOut = false; - - QElapsedTimer timer; - timer.start(); - while (msecs > timer.elapsed()) { - // Servers with active connections are ready for reading - if (!d->currentConnections.isEmpty()) - return true; - - // If we are a client, we are ready to read if our buffer has data - QMutexLocker locker(&d->worker->mutex); - if (!d->worker->pendingData.isEmpty()) - return true; - - // Nothing to do, wait for more events - d->eventLoop.processEvents(); - } - - d->setError(QAbstractSocket::SocketTimeoutError, - WinRTSocketEngine::TimeOutErrorString); - - if (timedOut) - *timedOut = true; - return false; -} - -bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << msecs; - Q_UNUSED(timedOut); - Q_D(QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForWrite(), false); - Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForWrite(), - QAbstractSocket::UnconnectedState, false); - - if (d->socketState == QAbstractSocket::ConnectingState) { - HRESULT hr = QWinRTFunctions::await(d->worker->connectOp, QWinRTFunctions::ProcessMainThreadEvents); - if (SUCCEEDED(hr)) { - handleConnectOpFinished(true, QAbstractSocket::UnknownSocketError, WinRTSocketEngine::UnknownSocketErrorString); - return true; - } - } - return false; -} - -bool QNativeSocketEngine::waitForReadOrWrite(bool *readyToRead, bool *readyToWrite, bool checkRead, bool checkWrite, int msecs, bool *timedOut) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << checkRead << checkWrite << msecs; - Q_D(QNativeSocketEngine); - Q_CHECK_VALID_SOCKETLAYER(QNativeSocketEngine::waitForReadOrWrite(), false); - Q_CHECK_NOT_STATE(QNativeSocketEngine::waitForReadOrWrite(), - QAbstractSocket::UnconnectedState, false); - - Q_UNUSED(readyToRead); - Q_UNUSED(readyToWrite); - Q_UNUSED(timedOut); - return false; -} - -bool QNativeSocketEngine::isReadNotificationEnabled() const -{ - Q_D(const QNativeSocketEngine); - return d->notifyOnRead; -} - -void QNativeSocketEngine::setReadNotificationEnabled(bool enable) -{ - qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << enable; - Q_D(QNativeSocketEngine); - d->notifyOnRead = enable; -} - -bool QNativeSocketEngine::isWriteNotificationEnabled() const -{ - Q_D(const QNativeSocketEngine); - return d->notifyOnWrite; -} - -void QNativeSocketEngine::setWriteNotificationEnabled(bool enable) -{ - qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << enable; - Q_D(QNativeSocketEngine); - d->notifyOnWrite = enable; - if (enable && d->socketState == QAbstractSocket::ConnectedState) { - if (bytesToWrite()) - return; // will be emitted as a result of bytes written - writeNotification(); - } -} - -bool QNativeSocketEngine::isExceptionNotificationEnabled() const -{ - Q_D(const QNativeSocketEngine); - return d->notifyOnException; -} - -void QNativeSocketEngine::setExceptionNotificationEnabled(bool enable) -{ - qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << enable; - Q_D(QNativeSocketEngine); - d->notifyOnException = enable; -} - -void QNativeSocketEngine::establishRead() -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; - Q_D(QNativeSocketEngine); - - HRESULT hr; - hr = QEventDispatcherWinRT::runOnXamlThread([d]() { - d->worker->setTcpSocket(d->tcpSocket()); - d->worker->startReading(); - return S_OK; - }); - Q_ASSERT_SUCCEEDED(hr); -} - -void QNativeSocketEngine::handleConnectOpFinished(bool success, QAbstractSocket::SocketError error, WinRTSocketEngine::ErrorString errorString) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << success << error << errorString; - Q_D(QNativeSocketEngine); - disconnect(d->worker, &SocketEngineWorker::connectOpFinished, - this, &QNativeSocketEngine::handleConnectOpFinished); - if (!success) { - d->setError(error, errorString); - d->socketState = QAbstractSocket::UnconnectedState; - close(); - return; - } - - d->socketState = QAbstractSocket::ConnectedState; - d->fetchConnectionParameters(); - emit connectionReady(); - - if (d->socketType != QAbstractSocket::TcpSocket) - return; - -#ifndef QT_NO_SSL - // Delay the reader so that the SSL socket can upgrade - if (d->sslSocket) - QObject::connect(qobject_cast(d->sslSocket), &QSslSocket::encrypted, this, &QNativeSocketEngine::establishRead); - else -#endif - establishRead(); -} - -void QNativeSocketEngine::handleNewData() -{ - qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO; - Q_D(QNativeSocketEngine); - - if (d->notifyOnRead && d->emitReadReady) { - if (d->socketType == QAbstractSocket::UdpSocket && !d->worker->emitDataReceived) - return; - qCDebug(lcNetworkSocketVerbose) << this << Q_FUNC_INFO << "Emitting readReady"; - d->pendingReadNotification = true; - emit readReady(); - d->worker->emitDataReceived = false; - d->emitReadReady = false; - } -} - -void QNativeSocketEngine::handleTcpError(QAbstractSocket::SocketError error) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << error; - Q_D(QNativeSocketEngine); - WinRTSocketEngine::ErrorString errorString; - switch (error) { - case QAbstractSocket::RemoteHostClosedError: - errorString = WinRTSocketEngine::RemoteHostClosedErrorString; - break; - default: - errorString = WinRTSocketEngine::UnknownSocketErrorString; - } - - d->setError(error, errorString); - close(); -} - -void QNativeSocketEngine::processReadReady() -{ - Q_D(QNativeSocketEngine); - if (d->closingDown) - return; - - d->pendingReadNotification = false; - readNotification(); -} - -bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType socketType, QAbstractSocket::NetworkLayerProtocol &socketProtocol) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << socketType << socketProtocol; - Q_UNUSED(socketProtocol); - HRESULT hr; - - switch (socketType) { - case QAbstractSocket::TcpSocket: { - ComPtr socket; - hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_StreamSocket).Get(), &socket); - RETURN_FALSE_IF_FAILED("createNewSocket: Could not create socket instance"); - socketDescriptor = qintptr(socket.Detach()); - break; - } - case QAbstractSocket::UdpSocket: { - ComPtr socket; - hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &socket); - RETURN_FALSE_IF_FAILED("createNewSocket: Could not create socket instance"); - socketDescriptor = qintptr(socket.Detach()); - QEventDispatcherWinRT::runOnXamlThread([&hr, this]() { - hr = udpSocket()->add_MessageReceived(Callback(worker, &SocketEngineWorker::OnNewDatagramReceived).Get(), &connectionToken); - if (FAILED(hr)) { - qErrnoWarning(hr, "createNewSocket: Could not add \"message received\" callback"); - return hr; - } - return S_OK; - }); - if (FAILED(hr)) - return false; - break; - } - default: - qWarning("Invalid socket type"); - return false; - } - - this->socketType = socketType; - - // Make the socket nonblocking. - if (!setOption(QAbstractSocketEngine::NonBlockingSocketOption, 1)) { - setError(QAbstractSocket::UnsupportedSocketOperationError, WinRTSocketEngine::NonBlockingInitFailedErrorString); - q_func()->close(); - return false; - } - - return true; -} - -QNativeSocketEnginePrivate::QNativeSocketEnginePrivate() - : QAbstractSocketEnginePrivate() - , notifyOnRead(true) - , notifyOnWrite(true) - , notifyOnException(false) - , closingDown(false) - , socketDescriptor(-1) - , worker(new SocketEngineWorker(this)) - , sslSocket(nullptr) - , connectionToken( { -1 } ) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; -} - -QNativeSocketEnginePrivate::~QNativeSocketEnginePrivate() -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; - if (socketDescriptor == -1 || connectionToken.value == -1) - return; - - HRESULT hr; - if (socketType == QAbstractSocket::UdpSocket) - hr = udpSocket()->remove_MessageReceived(connectionToken); - else if (socketType == QAbstractSocket::TcpSocket) - hr = tcpListener->remove_ConnectionReceived(connectionToken); - Q_ASSERT_SUCCEEDED(hr); - - worker->deleteLater(); -} - -void QNativeSocketEnginePrivate::setError(QAbstractSocket::SocketError error, WinRTSocketEngine::ErrorString errorString) const -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << error << errorString; - if (hasSetSocketError) { - // Only set socket errors once for one engine; expect the - // socket to recreate its engine after an error. Note: There's - // one exception: SocketError(11) bypasses this as it's purely - // a temporary internal error condition. - // Another exception is the way the waitFor*() functions set - // an error when a timeout occurs. After the call to setError() - // they reset the hasSetSocketError to false - return; - } - if (error != QAbstractSocket::SocketError(11)) - hasSetSocketError = true; - - socketError = error; - - switch (errorString) { - case WinRTSocketEngine::NonBlockingInitFailedErrorString: - socketErrorString = QNativeSocketEngine::tr("Unable to initialize non-blocking socket"); - break; - case WinRTSocketEngine::BroadcastingInitFailedErrorString: - socketErrorString = QNativeSocketEngine::tr("Unable to initialize broadcast socket"); - break; - // should not happen anymore - case WinRTSocketEngine::NoIpV6ErrorString: - socketErrorString = QNativeSocketEngine::tr("Attempt to use IPv6 socket on a platform with no IPv6 support"); - break; - case WinRTSocketEngine::RemoteHostClosedErrorString: - socketErrorString = QNativeSocketEngine::tr("The remote host closed the connection"); - break; - case WinRTSocketEngine::TimeOutErrorString: - socketErrorString = QNativeSocketEngine::tr("Network operation timed out"); - break; - case WinRTSocketEngine::ResourceErrorString: - socketErrorString = QNativeSocketEngine::tr("Out of resources"); - break; - case WinRTSocketEngine::OperationUnsupportedErrorString: - socketErrorString = QNativeSocketEngine::tr("Unsupported socket operation"); - break; - case WinRTSocketEngine::ProtocolUnsupportedErrorString: - socketErrorString = QNativeSocketEngine::tr("Protocol type not supported"); - break; - case WinRTSocketEngine::InvalidSocketErrorString: - socketErrorString = QNativeSocketEngine::tr("Invalid socket descriptor"); - break; - case WinRTSocketEngine::HostUnreachableErrorString: - socketErrorString = QNativeSocketEngine::tr("Host unreachable"); - break; - case WinRTSocketEngine::NetworkUnreachableErrorString: - socketErrorString = QNativeSocketEngine::tr("Network unreachable"); - break; - case WinRTSocketEngine::AccessErrorString: - socketErrorString = QNativeSocketEngine::tr("Permission denied"); - break; - case WinRTSocketEngine::ConnectionTimeOutErrorString: - socketErrorString = QNativeSocketEngine::tr("Connection timed out"); - break; - case WinRTSocketEngine::ConnectionRefusedErrorString: - socketErrorString = QNativeSocketEngine::tr("Connection refused"); - break; - case WinRTSocketEngine::AddressInuseErrorString: - socketErrorString = QNativeSocketEngine::tr("The bound address is already in use"); - break; - case WinRTSocketEngine::AddressNotAvailableErrorString: - socketErrorString = QNativeSocketEngine::tr("The address is not available"); - break; - case WinRTSocketEngine::AddressProtectedErrorString: - socketErrorString = QNativeSocketEngine::tr("The address is protected"); - break; - case WinRTSocketEngine::DatagramTooLargeErrorString: - socketErrorString = QNativeSocketEngine::tr("Datagram was too large to send"); - break; - case WinRTSocketEngine::SendDatagramErrorString: - socketErrorString = QNativeSocketEngine::tr("Unable to send a message"); - break; - case WinRTSocketEngine::ReceiveDatagramErrorString: - socketErrorString = QNativeSocketEngine::tr("Unable to receive a message"); - break; - case WinRTSocketEngine::WriteErrorString: - socketErrorString = QNativeSocketEngine::tr("Unable to write"); - break; - case WinRTSocketEngine::ReadErrorString: - socketErrorString = QNativeSocketEngine::tr("Network error"); - break; - case WinRTSocketEngine::PortInuseErrorString: - socketErrorString = QNativeSocketEngine::tr("Another socket is already listening on the same port"); - break; - case WinRTSocketEngine::NotSocketErrorString: - socketErrorString = QNativeSocketEngine::tr("Operation on non-socket"); - break; - case WinRTSocketEngine::InvalidProxyTypeString: - socketErrorString = QNativeSocketEngine::tr("The proxy type is invalid for this operation"); - break; - case WinRTSocketEngine::TemporaryErrorString: - socketErrorString = QNativeSocketEngine::tr("Temporary error"); - break; - case WinRTSocketEngine::UnknownSocketErrorString: - socketErrorString = QNativeSocketEngine::tr("Unknown error"); - break; - } -} - -int QNativeSocketEnginePrivate::option(QAbstractSocketEngine::SocketOption opt) const -{ - ComPtr control; - if (socketType == QAbstractSocket::TcpSocket) { - if (FAILED(tcpSocket()->get_Control(&control))) { - qWarning("QNativeSocketEnginePrivate::option: Could not obtain socket control"); - return -1; - } - } - switch (opt) { - case QAbstractSocketEngine::NonBlockingSocketOption: - case QAbstractSocketEngine::BroadcastSocketOption: - case QAbstractSocketEngine::ReceiveOutOfBandData: - return 1; - case QAbstractSocketEngine::SendBufferSocketOption: - if (socketType == QAbstractSocket::UdpSocket) - return -1; - - UINT32 bufferSize; - if (FAILED(control->get_OutboundBufferSizeInBytes(&bufferSize))) { - qWarning("Could not obtain OutboundBufferSizeInBytes information vom socket control"); - return -1; - } - return bufferSize; - case QAbstractSocketEngine::LowDelayOption: - if (socketType == QAbstractSocket::UdpSocket) - return -1; - - boolean noDelay; - if (FAILED(control->get_NoDelay(&noDelay))) { - qWarning("Could not obtain NoDelay information from socket control"); - return -1; - } - return noDelay; - case QAbstractSocketEngine::KeepAliveOption: - if (socketType == QAbstractSocket::UdpSocket) - return -1; - - boolean keepAlive; - if (FAILED(control->get_KeepAlive(&keepAlive))) { - qWarning("Could not obtain KeepAlive information from socket control"); - return -1; - } - return keepAlive; - case QAbstractSocketEngine::ReceiveBufferSocketOption: - case QAbstractSocketEngine::AddressReusable: - case QAbstractSocketEngine::BindExclusively: - case QAbstractSocketEngine::MulticastTtlOption: - case QAbstractSocketEngine::MulticastLoopbackOption: - case QAbstractSocketEngine::TypeOfServiceOption: - case QAbstractSocketEngine::MaxStreamsSocketOption: - case QAbstractSocketEngine::PathMtuInformation: - default: - return -1; - } - return -1; -} - -bool QNativeSocketEnginePrivate::setOption(QAbstractSocketEngine::SocketOption opt, int v) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO << opt << v; - ComPtr control; - if (socketType == QAbstractSocket::TcpSocket) { - if (FAILED(tcpSocket()->get_Control(&control))) { - qWarning("QNativeSocketEnginePrivate::setOption: Could not obtain socket control"); - return false; - } - } - switch (opt) { - case QAbstractSocketEngine::NonBlockingSocketOption: - case QAbstractSocketEngine::BroadcastSocketOption: - case QAbstractSocketEngine::ReceiveOutOfBandData: - return v != 0; - case QAbstractSocketEngine::SendBufferSocketOption: - if (socketType == QAbstractSocket::UdpSocket) - return false; - - if (FAILED(control->put_OutboundBufferSizeInBytes(v))) { - qWarning("Could not set OutboundBufferSizeInBytes"); - return false; - } - return true; - case QAbstractSocketEngine::LowDelayOption: { - if (socketType == QAbstractSocket::UdpSocket) - return false; - - boolean noDelay = v; - if (FAILED(control->put_NoDelay(noDelay))) { - qWarning("Could not obtain NoDelay information from socket control"); - return false; - } - return true; - } - case QAbstractSocketEngine::KeepAliveOption: { - if (socketType == QAbstractSocket::UdpSocket - || socketState != QAbstractSocket::UnconnectedState) - return false; - - boolean keepAlive = v; - if (FAILED(control->put_KeepAlive(keepAlive))) { - qWarning("Could not set KeepAlive value"); - return false; - } - return true; - } - case QAbstractSocketEngine::ReceiveBufferSocketOption: - case QAbstractSocketEngine::AddressReusable: - case QAbstractSocketEngine::BindExclusively: - case QAbstractSocketEngine::MulticastTtlOption: - case QAbstractSocketEngine::MulticastLoopbackOption: - case QAbstractSocketEngine::TypeOfServiceOption: - case QAbstractSocketEngine::MaxStreamsSocketOption: - case QAbstractSocketEngine::PathMtuInformation: - default: - return false; - } - return false; -} - -bool QNativeSocketEnginePrivate::fetchConnectionParameters() -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; - localPort = 0; - localAddress.clear(); - peerPort = 0; - peerAddress.clear(); - inboundStreamCount = outboundStreamCount = 0; - - HRESULT hr; - if (socketType == QAbstractSocket::TcpSocket) { - ComPtr hostName; - HString tmpHString; - ComPtr info; - hr = tcpSocket()->get_Information(&info); - Q_ASSERT_SUCCEEDED(hr); - hr = info->get_LocalAddress(&hostName); - Q_ASSERT_SUCCEEDED(hr); - if (hostName) { - hr = hostName->get_CanonicalName(tmpHString.GetAddressOf()); - Q_ASSERT_SUCCEEDED(hr); - localAddress.setAddress(qt_QStringFromHString(tmpHString)); - hr = info->get_LocalPort(tmpHString.GetAddressOf()); - Q_ASSERT_SUCCEEDED(hr); - localPort = qt_QStringFromHString(tmpHString).toInt(); - } - if (!localPort && tcpListener) { - ComPtr listenerInfo = 0; - hr = tcpListener->get_Information(&listenerInfo); - Q_ASSERT_SUCCEEDED(hr); - hr = listenerInfo->get_LocalPort(tmpHString.GetAddressOf()); - Q_ASSERT_SUCCEEDED(hr); - localPort = qt_QStringFromHString(tmpHString).toInt(); - localAddress = QHostAddress::Any; - } - info->get_RemoteAddress(&hostName); - if (hostName) { - hr = hostName->get_CanonicalName(tmpHString.GetAddressOf()); - Q_ASSERT_SUCCEEDED(hr); - peerAddress.setAddress(qt_QStringFromHString(tmpHString)); - hr = info->get_RemotePort(tmpHString.GetAddressOf()); - Q_ASSERT_SUCCEEDED(hr); - peerPort = qt_QStringFromHString(tmpHString).toInt(); - inboundStreamCount = outboundStreamCount = 1; - } - } else if (socketType == QAbstractSocket::UdpSocket) { - ComPtr hostName; - HString tmpHString; - ComPtr info; - hr = udpSocket()->get_Information(&info); - Q_ASSERT_SUCCEEDED(hr); - hr = info->get_LocalAddress(&hostName); - Q_ASSERT_SUCCEEDED(hr); - if (hostName) { - hr = hostName->get_CanonicalName(tmpHString.GetAddressOf()); - Q_ASSERT_SUCCEEDED(hr); - localAddress.setAddress(qt_QStringFromHString(tmpHString)); - hr = info->get_LocalPort(tmpHString.GetAddressOf()); - Q_ASSERT_SUCCEEDED(hr); - localPort = qt_QStringFromHString(tmpHString).toInt(); - } - - hr = info->get_RemoteAddress(&hostName); - Q_ASSERT_SUCCEEDED(hr); - if (hostName) { - hr = hostName->get_CanonicalName(tmpHString.GetAddressOf()); - Q_ASSERT_SUCCEEDED(hr); - peerAddress.setAddress(qt_QStringFromHString(tmpHString)); - hr = info->get_RemotePort(tmpHString.GetAddressOf()); - Q_ASSERT_SUCCEEDED(hr); - peerPort = qt_QStringFromHString(tmpHString).toInt(); - inboundStreamCount = outboundStreamCount = 1; - } - } - return true; -} - -HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener *listener, IStreamSocketListenerConnectionReceivedEventArgs *args) -{ - qCDebug(lcNetworkSocket) << this << Q_FUNC_INFO; - Q_Q(QNativeSocketEngine); - Q_UNUSED(listener) - IStreamSocket *socket; - args->get_Socket(&socket); - pendingConnections.append(socket); - emit q->connectionReady(); - if (notifyOnRead) - emit q->readReady(); - return S_OK; -} - -QT_END_NAMESPACE - -#include "qnativesocketengine_winrt.moc" diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h deleted file mode 100644 index e1fe58bb97..0000000000 --- a/src/network/socket/qnativesocketengine_winrt_p.h +++ /dev/null @@ -1,243 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2016 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QNATIVESOCKETENGINE_WINRT_P_H -#define QNATIVESOCKETENGINE_WINRT_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists for the convenience -// of the QLibrary class. This header file may change from -// version to version without notice, or even be removed. -// -// We mean it. -// - -#include -#include -#include -#include -#include -#include -#include "QtNetwork/qhostaddress.h" -#include "private/qabstractsocketengine_p.h" -#include -#include - -QT_BEGIN_NAMESPACE - -Q_DECLARE_LOGGING_CATEGORY(lcNetworkSocket) -Q_DECLARE_LOGGING_CATEGORY(lcNetworkSocketVerbose) - -namespace WinRTSocketEngine { - enum ErrorString { - NonBlockingInitFailedErrorString, - BroadcastingInitFailedErrorString, - NoIpV6ErrorString, - RemoteHostClosedErrorString, - TimeOutErrorString, - ResourceErrorString, - OperationUnsupportedErrorString, - ProtocolUnsupportedErrorString, - InvalidSocketErrorString, - HostUnreachableErrorString, - NetworkUnreachableErrorString, - AccessErrorString, - ConnectionTimeOutErrorString, - ConnectionRefusedErrorString, - AddressInuseErrorString, - AddressNotAvailableErrorString, - AddressProtectedErrorString, - DatagramTooLargeErrorString, - SendDatagramErrorString, - ReceiveDatagramErrorString, - WriteErrorString, - ReadErrorString, - PortInuseErrorString, - NotSocketErrorString, - InvalidProxyTypeString, - TemporaryErrorString, - - UnknownSocketErrorString = -1 - }; -} - -class QNativeSocketEnginePrivate; -class SocketEngineWorker; - -struct WinRtDatagram { - QByteArray data; - QIpPacketHeader header; -}; - -class Q_AUTOTEST_EXPORT QNativeSocketEngine : public QAbstractSocketEngine -{ - Q_OBJECT -public: - QNativeSocketEngine(QObject *parent = 0); - ~QNativeSocketEngine(); - - bool initialize(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol protocol = QAbstractSocket::IPv4Protocol); - bool initialize(qintptr socketDescriptor, QAbstractSocket::SocketState socketState = QAbstractSocket::ConnectedState); - - qintptr socketDescriptor() const; - - bool isValid() const; - - bool connectToHost(const QHostAddress &address, quint16 port); - bool connectToHostByName(const QString &name, quint16 port); - bool bind(const QHostAddress &address, quint16 port); - bool listen(); - int accept(); - void close(); - -#ifndef QT_NO_NETWORKINTERFACE - bool joinMulticastGroup(const QHostAddress &groupAddress, - const QNetworkInterface &iface); - bool leaveMulticastGroup(const QHostAddress &groupAddress, - const QNetworkInterface &iface); - QNetworkInterface multicastInterface() const; - bool setMulticastInterface(const QNetworkInterface &iface); -#endif - - qint64 bytesAvailable() const; - - qint64 read(char *data, qint64 maxlen); - qint64 write(const char *data, qint64 len); - - qint64 readDatagram(char *data, qint64 maxlen, QIpPacketHeader * = 0, PacketHeaderOptions = WantNone); - qint64 writeDatagram(const char *data, qint64 len, const QIpPacketHeader &header); - bool hasPendingDatagrams() const; - qint64 pendingDatagramSize() const; - - qint64 bytesToWrite() const; - - qint64 receiveBufferSize() const; - void setReceiveBufferSize(qint64 bufferSize); - - qint64 sendBufferSize() const; - void setSendBufferSize(qint64 bufferSize); - - int option(SocketOption option) const; - bool setOption(SocketOption option, int value); - - bool waitForRead(int msecs = 30000, bool *timedOut = 0); - bool waitForWrite(int msecs = 30000, bool *timedOut = 0); - bool waitForReadOrWrite(bool *readyToRead, bool *readyToWrite, - bool checkRead, bool checkWrite, - int msecs = 30000, bool *timedOut = 0); - - bool isReadNotificationEnabled() const; - void setReadNotificationEnabled(bool enable); - bool isWriteNotificationEnabled() const; - void setWriteNotificationEnabled(bool enable); - bool isExceptionNotificationEnabled() const; - void setExceptionNotificationEnabled(bool enable); - -signals: - void connectionReady(); - void readReady(); - void writeReady(); - void newDatagramReceived(const WinRtDatagram &datagram); - -private slots: - void establishRead(); - void handleConnectOpFinished(bool success, QAbstractSocket::SocketError error, - WinRTSocketEngine::ErrorString errorString); - void handleNewData(); - void handleTcpError(QAbstractSocket::SocketError error); - void processReadReady(); - -private: - Q_DECLARE_PRIVATE(QNativeSocketEngine) - Q_DISABLE_COPY_MOVE(QNativeSocketEngine) -}; - -class QNativeSocketEnginePrivate : public QAbstractSocketEnginePrivate -{ - Q_DECLARE_PUBLIC(QNativeSocketEngine) -public: - QNativeSocketEnginePrivate(); - ~QNativeSocketEnginePrivate(); - - qintptr socketDescriptor; - SocketEngineWorker *worker; - - bool notifyOnRead, notifyOnWrite, notifyOnException; - QAtomicInt closingDown; - - void setError(QAbstractSocket::SocketError error, WinRTSocketEngine::ErrorString errorString) const; - - // native functions - int option(QNativeSocketEngine::SocketOption option) const; - bool setOption(QNativeSocketEngine::SocketOption option, int value); - - bool createNewSocket(QAbstractSocket::SocketType type, QAbstractSocket::NetworkLayerProtocol &protocol); - - bool checkProxy(const QHostAddress &address); - bool fetchConnectionParameters(); - -private: - inline ABI::Windows::Networking::Sockets::IStreamSocket *tcpSocket() const - { return reinterpret_cast(socketDescriptor); } - inline ABI::Windows::Networking::Sockets::IDatagramSocket *udpSocket() const - { return reinterpret_cast(socketDescriptor); } - Microsoft::WRL::ComPtr tcpListener; - - QList pendingConnections; - QList currentConnections; - QEventLoop eventLoop; - QAbstractSocket *sslSocket; - EventRegistrationToken connectionToken; - - bool emitReadReady = true; - bool pendingReadNotification = false; - - HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener, - ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args); -}; - -QT_END_NAMESPACE - -Q_DECLARE_METATYPE(WinRtDatagram) -Q_DECLARE_METATYPE(WinRTSocketEngine::ErrorString) - -#endif // QNATIVESOCKETENGINE_WINRT_P_H diff --git a/src/network/socket/socket.pri b/src/network/socket/socket.pri index c3a98ea31a..67325ac70f 100644 --- a/src/network/socket/socket.pri +++ b/src/network/socket/socket.pri @@ -43,10 +43,8 @@ qtConfig(sctp) { socket/qsctpsocket.cpp } -!winrt { - SOURCES += socket/qnativesocketengine.cpp - HEADERS += socket/qnativesocketengine_p.h -} +SOURCES += socket/qnativesocketengine.cpp +HEADERS += socket/qnativesocketengine_p.h unix { SOURCES += socket/qnativesocketengine_unix.cpp @@ -57,13 +55,8 @@ unix { # invalid C/C++ code otherwise. msvc: QMAKE_MOC_OPTIONS += -D_WINSOCK_DEPRECATED_NO_WARNINGS -win32:!winrt:SOURCES += socket/qnativesocketengine_win.cpp -win32:!winrt: QMAKE_USE_PRIVATE += advapi32 - -winrt { - SOURCES += socket/qnativesocketengine_winrt.cpp - HEADERS += socket/qnativesocketengine_winrt_p.h -} +win32: SOURCES += socket/qnativesocketengine_win.cpp +win32: QMAKE_USE_PRIVATE += advapi32 qtConfig(localserver) { HEADERS += socket/qlocalserver.h \ @@ -73,7 +66,7 @@ qtConfig(localserver) { SOURCES += socket/qlocalsocket.cpp \ socket/qlocalserver.cpp - integrity|winrt { + integrity { SOURCES += socket/qlocalsocket_tcp.cpp \ socket/qlocalserver_tcp.cpp DEFINES += QT_LOCALSOCKET_TCP -- cgit v1.2.3