From 055cbaafd6c48ddfd00f918006c0a2ffe3a72f81 Mon Sep 17 00:00:00 2001 From: Oliver Wolff Date: Tue, 23 Jun 2015 12:59:34 +0200 Subject: Fixed connectToHost connectToHost is not meant to be synchronous, but waitForWrite is used internally to wait for the connection to be established. Thus the same logic that is used in the callback has to be applied in there. Task-number: QTBUG-46339 Change-Id: Ia1fb5c1ae609a9942ff4d8fe2f5fab2ef572da0c Reviewed-by: Andrew Knight --- src/network/socket/qnativesocketengine_winrt.cpp | 72 +++++++++++++++--------- src/network/socket/qnativesocketengine_winrt_p.h | 3 +- 2 files changed, 48 insertions(+), 27 deletions(-) (limited to 'src/network') diff --git a/src/network/socket/qnativesocketengine_winrt.cpp b/src/network/socket/qnativesocketengine_winrt.cpp index 5e58ee3895..faea132b86 100644 --- a/src/network/socket/qnativesocketengine_winrt.cpp +++ b/src/network/socket/qnativesocketengine_winrt.cpp @@ -285,23 +285,11 @@ bool QNativeSocketEngine::connectToHostByName(const QString &name, quint16 port) return false; } d->socketState = QAbstractSocket::ConnectingState; - hr = QWinRTFunctions::await(d->connectOp); - RETURN_FALSE_IF_FAILED("Connection could not be established"); - bool connectionErrors = false; - d->handleConnectionErrors(d->connectOp.Get(), &connectionErrors); - if (connectionErrors) - return false; - d->connectOp.Reset(); - - d->socketState = QAbstractSocket::ConnectedState; - emit connectionReady(); + hr = d->connectOp->put_Completed(Callback( + d, &QNativeSocketEnginePrivate::handleConnectToHost).Get()); + Q_ASSERT_SUCCEEDED(hr); - // Delay the reader so that the SSL socket can upgrade - if (d->sslSocket) - connect(d->sslSocket, SIGNAL(encrypted()), SLOT(establishRead())); - else - establishRead(); - return true; + return d->socketState == QAbstractSocket::ConnectedState; } bool QNativeSocketEngine::bind(const QHostAddress &address, quint16 port) @@ -687,6 +675,14 @@ bool QNativeSocketEngine::waitForWrite(int msecs, bool *timedOut) { Q_UNUSED(msecs); Q_UNUSED(timedOut); + Q_D(QNativeSocketEngine); + if (d->socketState == QAbstractSocket::ConnectingState) { + HRESULT hr = QWinRTFunctions::await(d->connectOp, QWinRTFunctions::ProcessMainThreadEvents); + if (SUCCEEDED(hr)) { + d->handleConnectionEstablished(d->connectOp.Get()); + return true; + } + } return false; } @@ -727,7 +723,6 @@ void QNativeSocketEngine::setWriteNotificationEnabled(bool enable) if (bytesToWrite()) return; // will be emitted as a result of bytes written writeNotification(); - d->notifyOnWrite = false; } } @@ -1116,10 +1111,19 @@ HRESULT QNativeSocketEnginePrivate::handleClientConnection(IStreamSocketListener return S_OK; } -void QNativeSocketEnginePrivate::handleConnectionErrors(IAsyncAction *connectAction, bool *errorsOccured) +HRESULT QNativeSocketEnginePrivate::handleConnectToHost(IAsyncAction *action, AsyncStatus) { - bool error = true; - HRESULT hr = connectAction->GetResults(); + handleConnectionEstablished(action); + return S_OK; +} + +void QNativeSocketEnginePrivate::handleConnectionEstablished(IAsyncAction *action) +{ + Q_Q(QNativeSocketEngine); + if (wasDeleted || !connectOp) // Protect against a late callback + return; + + HRESULT hr = action->GetResults(); switch (hr) { case 0x8007274c: // A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond. setError(QAbstractSocket::NetworkError, ConnectionTimeOutErrorString); @@ -1137,13 +1141,29 @@ void QNativeSocketEnginePrivate::handleConnectionErrors(IAsyncAction *connectAct if (FAILED(hr)) { setError(QAbstractSocket::UnknownSocketError, UnknownSocketErrorString); socketState = QAbstractSocket::UnconnectedState; - } else { - error = false; } break; } - if (errorsOccured) - *errorsOccured = error; + + // The callback might be triggered several times if we do not cancel/reset it here + if (connectOp) { + ComPtr info; + connectOp.As(&info); + if (info) { + info->Cancel(); + info->Close(); + } + connectOp.Reset(); + } + + socketState = QAbstractSocket::ConnectedState; + emit q->connectionReady(); + + // Delay the reader so that the SSL socket can upgrade + if (sslSocket) + QObject::connect(qobject_cast(sslSocket), &QSslSocket::encrypted, q, &QNativeSocketEngine::establishRead); + else + q->establishRead(); } HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *asyncInfo, AsyncStatus status) @@ -1163,7 +1183,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async hr = buffer->get_Length(&bufferLength); Q_ASSERT_SUCCEEDED(hr); if (!bufferLength) { - if (q->isReadNotificationEnabled()) + if (notifyOnRead) emit q->readReady(); return S_OK; } @@ -1187,7 +1207,7 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async readBytes.seek(readPos); readMutex.unlock(); - if (q->isReadNotificationEnabled()) + if (notifyOnRead) emit q->readReady(); ComPtr stream; diff --git a/src/network/socket/qnativesocketengine_winrt_p.h b/src/network/socket/qnativesocketengine_winrt_p.h index eb032bc977..8e8448e6a8 100644 --- a/src/network/socket/qnativesocketengine_winrt_p.h +++ b/src/network/socket/qnativesocketengine_winrt_p.h @@ -216,7 +216,8 @@ private: ABI::Windows::Networking::Sockets::IDatagramSocketMessageReceivedEventArgs *args); HRESULT handleClientConnection(ABI::Windows::Networking::Sockets::IStreamSocketListener *tcpListener, ABI::Windows::Networking::Sockets::IStreamSocketListenerConnectionReceivedEventArgs *args); - void handleConnectionErrors(ABI::Windows::Foundation::IAsyncAction *connectAction, bool *errorsOccured); + HRESULT handleConnectToHost(ABI::Windows::Foundation::IAsyncAction *, ABI::Windows::Foundation::AsyncStatus); + void handleConnectionEstablished(ABI::Windows::Foundation::IAsyncAction *action); HRESULT handleReadyRead(ABI::Windows::Foundation::IAsyncOperationWithProgress *asyncInfo, ABI::Windows::Foundation::AsyncStatus); }; -- cgit v1.2.3