From 14399b427cdb7662cbca6aa89443521301507b41 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Wed, 6 Apr 2016 10:42:05 +0200 Subject: [PATCH] winrt: fix callbacks by moving them to the xaml thread Change-Id: I7b4f007107e21c02646140acd5ebe5745ca79bce Reviewed-by: Maurice Kalinowski --- .../socket/qnativesocketengine_winrt.cpp | 120 ++++++++++-------- 1 file changed, 68 insertions(+), 52 deletions(-) diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 35b7d5474b..d1ebd19cca 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -298,8 +298,10 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port) Q_ASSERT_SUCCEEDED(hr); d->socketState = QAbstractSocket::ConnectingState; - hr = d->connectOp->put_Completed(Callback( + hr = QEventDispatcherWinRT::runOnXamlThread([d]() { + return d->connectOp->put_Completed(Callback( d, &QNativeSocketEnginePrivate::handleConnectToHost).Get()); + }); Q_ASSERT_SUCCEEDED(hr); return d->socketState == QAbstractSocket::ConnectedState; @@ -309,50 +311,53 @@ bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) { Q_D(QNativeSocketEngine); HRESULT hr; - ComPtr hostAddress; + hr = QEventDispatcherWinRT::runOnXamlThread([address, d, port, this]() { + HRESULT hr; + ComPtr hostAddress; - if (address != QHostAddress::Any && address != QHostAddress::AnyIPv4 && address != QHostAddress::AnyIPv6) { - ComPtr hostNameFactory; - hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(), - &hostNameFactory); - Q_ASSERT_SUCCEEDED(hr); - const QString addressString = address.toString(); - HStringReference addressRef(reinterpret_cast(addressString.utf16())); - hr = hostNameFactory->CreateHostName(addressRef.Get(), &hostAddress); - RETURN_FALSE_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); - Q_ASSERT_SUCCEEDED(hr); + if (address != QHostAddress::Any && address != QHostAddress::AnyIPv4 && address != QHostAddress::AnyIPv6) { + ComPtr hostNameFactory; + hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(), + &hostNameFactory); + RETURN_HR_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_HR_IF_FAILED("QNativeSocketEngine::bind: Could not create hostname."); } - hr = QEventDispatcherWinRT::runOnXamlThread([d]() { - return d->tcpListener->add_ConnectionReceived( + 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_HR_IF_FAILED("QNativeSocketEngine::bind: Could not create tcp listener"); + } + + hr = d->tcpListener->add_ConnectionReceived( Callback(d, &QNativeSocketEnginePrivate::handleClientConnection).Get(), &d->connectionToken); - }); - Q_ASSERT_SUCCEEDED(hr); - 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()); - return false; - } - Q_ASSERT_SUCCEEDED(hr); + RETURN_HR_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()); + return hr; + } + RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Unable to bind socket"); - hr = op->put_Completed(Callback(d, &QNativeSocketEnginePrivate::handleBindCompleted).Get()); - Q_ASSERT_SUCCEEDED(hr); - hr = QWinRTFunctions::await(op); + hr = op->put_Completed(Callback(d, &QNativeSocketEnginePrivate::handleBindCompleted).Get()); + RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not register bind callback"); + hr = QWinRTFunctions::await(op); + RETURN_HR_IF_FAILED("QNativeSocketEngine::bind: Could not wait for bind to finish"); + return S_OK; + }); Q_ASSERT_SUCCEEDED(hr); d->socketState = QAbstractSocket::BoundState; @@ -404,7 +409,9 @@ int QNativeSocketEngine::accept() socketDescription(this).constData()); return -1; } - hr = op->put_Completed(Callback(d, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + hr = QEventDispatcherWinRT::runOnXamlThread([d, op]() { + return op->put_Completed(Callback(d, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + }); if (FAILED(hr)) { qErrnoWarning(hr, "accept(): Failed to set socket read callback (%s).", socketDescription(this).constData()); @@ -774,18 +781,22 @@ void QNativeSocketEngine::establishRead() Q_D(QNativeSocketEngine); HRESULT hr; - ComPtr stream; - hr = d->tcpSocket()->get_InputStream(&stream); - RETURN_VOID_IF_FAILED("Failed to get socket input stream"); + hr = QEventDispatcherWinRT::runOnXamlThread([d]() { + ComPtr stream; + HRESULT hr = d->tcpSocket()->get_InputStream(&stream); + RETURN_HR_IF_FAILED("QNativeSocketEngine::establishRead: Failed to get socket input stream"); - ComPtr buffer; - hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer); - Q_ASSERT_SUCCEEDED(hr); + ComPtr buffer; + hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer); + RETURN_HR_IF_FAILED("QNativeSocketEngine::establishRead: Failed to create buffer"); - ComPtr op; - hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, &op); - RETURN_VOID_IF_FAILED("Failed to initiate socket read"); - hr = op->put_Completed(Callback(d, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + ComPtr op; + hr = stream->ReadAsync(buffer.Get(), READ_BUFFER_SIZE, InputStreamOptions_Partial, &op); + RETURN_HR_IF_FAILED("QNativeSocketEngine::establishRead: Failed to initiate socket read"); + hr = op->put_Completed(Callback(d, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + RETURN_HR_IF_FAILED("QNativeSocketEngine::establishRead: Failed to register read callback"); + return S_OK; + }); Q_ASSERT_SUCCEEDED(hr); } @@ -807,7 +818,10 @@ bool QNativeSocketEnginePrivate::createNewSocket(QAbstractSocket::SocketType soc hr = RoActivateInstance(HString::MakeReference(RuntimeClass_Windows_Networking_Sockets_DatagramSocket).Get(), &socket); Q_ASSERT_SUCCEEDED(hr); socketDescriptor = qintptr(socket.Detach()); - hr = udpSocket()->add_MessageReceived(Callback(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &connectionToken); + hr = QEventDispatcherWinRT::runOnXamlThread([this]() { + HRESULT hr = udpSocket()->add_MessageReceived(Callback(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &connectionToken); + return hr; + }); Q_ASSERT_SUCCEEDED(hr); break; } @@ -1297,7 +1311,9 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async socketDescription(q).constData()); return S_OK; } - hr = op->put_Completed(Callback(this, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + hr = QEventDispatcherWinRT::runOnXamlThread([op, this]() { + return op->put_Completed(Callback(this, &QNativeSocketEnginePrivate::handleReadyRead).Get()); + }); if (FAILED(hr)) { qErrnoWarning(hr, "handleReadyRead(): Failed to set socket read callback (%s).", socketDescription(q).constData());