winrt: fix callbacks by moving them to the xaml thread

Change-Id: I7b4f007107e21c02646140acd5ebe5745ca79bce
Reviewed-by: Maurice Kalinowski <maurice.kalinowski@theqtcompany.com>
This commit is contained in:
Oliver Wolff 2016-04-06 10:42:05 +02:00
parent 09487deeae
commit 14399b427c

View File

@ -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<IAsyncActionCompletedHandler>(
hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
return d->connectOp->put_Completed(Callback<IAsyncActionCompletedHandler>(
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<IHostName> hostAddress;
hr = QEventDispatcherWinRT::runOnXamlThread([address, d, port, this]() {
HRESULT hr;
ComPtr<IHostName> hostAddress;
if (address != QHostAddress::Any && address != QHostAddress::AnyIPv4 && address != QHostAddress::AnyIPv6) {
ComPtr<IHostNameFactory> hostNameFactory;
hr = GetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Networking_HostName).Get(),
&hostNameFactory);
Q_ASSERT_SUCCEEDED(hr);
const QString addressString = address.toString();
HStringReference addressRef(reinterpret_cast<LPCWSTR>(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<LPCWSTR>(portQString.utf16()));
ComPtr<IAsyncAction> 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<IHostNameFactory> 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<LPCWSTR>(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<LPCWSTR>(portQString.utf16()));
ComPtr<IAsyncAction> 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<ClientConnectedHandler>(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<IAsyncActionCompletedHandler>(d, &QNativeSocketEnginePrivate::handleBindCompleted).Get());
Q_ASSERT_SUCCEEDED(hr);
hr = QWinRTFunctions::await(op);
hr = op->put_Completed(Callback<IAsyncActionCompletedHandler>(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<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get());
hr = QEventDispatcherWinRT::runOnXamlThread([d, op]() {
return op->put_Completed(Callback<SocketReadCompletedHandler>(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<IInputStream> stream;
hr = d->tcpSocket()->get_InputStream(&stream);
RETURN_VOID_IF_FAILED("Failed to get socket input stream");
hr = QEventDispatcherWinRT::runOnXamlThread([d]() {
ComPtr<IInputStream> stream;
HRESULT hr = d->tcpSocket()->get_InputStream(&stream);
RETURN_HR_IF_FAILED("QNativeSocketEngine::establishRead: Failed to get socket input stream");
ComPtr<IBuffer> buffer;
hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer);
Q_ASSERT_SUCCEEDED(hr);
ComPtr<IBuffer> buffer;
hr = g->bufferFactory->Create(READ_BUFFER_SIZE, &buffer);
RETURN_HR_IF_FAILED("QNativeSocketEngine::establishRead: Failed to create buffer");
ComPtr<IAsyncBufferOperation> 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<SocketReadCompletedHandler>(d, &QNativeSocketEnginePrivate::handleReadyRead).Get());
ComPtr<IAsyncBufferOperation> 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<SocketReadCompletedHandler>(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<DatagramReceivedHandler>(this, &QNativeSocketEnginePrivate::handleNewDatagram).Get(), &connectionToken);
hr = QEventDispatcherWinRT::runOnXamlThread([this]() {
HRESULT hr = udpSocket()->add_MessageReceived(Callback<DatagramReceivedHandler>(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<SocketReadCompletedHandler>(this, &QNativeSocketEnginePrivate::handleReadyRead).Get());
hr = QEventDispatcherWinRT::runOnXamlThread([op, this]() {
return op->put_Completed(Callback<SocketReadCompletedHandler>(this, &QNativeSocketEnginePrivate::handleReadyRead).Get());
});
if (FAILED(hr)) {
qErrnoWarning(hr, "handleReadyRead(): Failed to set socket read callback (%s).",
socketDescription(q).constData());