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 <andrew.knight@intopalo.com>
This commit is contained in:
Oliver Wolff 2015-06-23 12:59:34 +02:00
parent 111ee58c06
commit 055cbaafd6
2 changed files with 48 additions and 27 deletions

View File

@ -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();
hr = d->connectOp->put_Completed(Callback<IAsyncActionCompletedHandler>(
d, &QNativeSocketEnginePrivate::handleConnectToHost).Get());
Q_ASSERT_SUCCEEDED(hr);
d->socketState = QAbstractSocket::ConnectedState;
emit connectionReady();
// 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<IAsyncInfo> 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<QSslSocket *>(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<IInputStream> stream;

View File

@ -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<ABI::Windows::Storage::Streams::IBuffer *, UINT32> *asyncInfo, ABI::Windows::Foundation::AsyncStatus);
};