winrt: Properly handle when a remote host closes a tcp connection.
Task-number: QTBUG-48476 Change-Id: I1933dfe7e73330a8f0d5ac8d3d7a834e0d77270a Reviewed-by: Andrew Knight <andrew.knight@intopalo.com> Reviewed-by: Samuel Nevala <samuel.nevala@intopalo.com> Reviewed-by: Maurice Kalinowski <maurice.kalinowski@theqtcompany.com>
This commit is contained in:
parent
49640d417f
commit
ffa7b050a1
@ -420,6 +420,16 @@ void QNativeSocketEngine::close()
|
|||||||
{
|
{
|
||||||
Q_D(QNativeSocketEngine);
|
Q_D(QNativeSocketEngine);
|
||||||
|
|
||||||
|
if (d->closingDown)
|
||||||
|
return;
|
||||||
|
|
||||||
|
d->closingDown = true;
|
||||||
|
|
||||||
|
|
||||||
|
d->notifyOnRead = false;
|
||||||
|
d->notifyOnWrite = false;
|
||||||
|
d->notifyOnException = false;
|
||||||
|
|
||||||
if (d->connectOp) {
|
if (d->connectOp) {
|
||||||
ComPtr<IAsyncInfo> info;
|
ComPtr<IAsyncInfo> info;
|
||||||
d->connectOp.As(&info);
|
d->connectOp.As(&info);
|
||||||
@ -440,7 +450,6 @@ void QNativeSocketEngine::close()
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (socket) {
|
if (socket) {
|
||||||
d->closingDown = true;
|
|
||||||
socket->Close();
|
socket->Close();
|
||||||
d->socketDescriptor = -1;
|
d->socketDescriptor = -1;
|
||||||
}
|
}
|
||||||
@ -498,6 +507,14 @@ qint64 QNativeSocketEngine::read(char *data, qint64 maxlen)
|
|||||||
if (d->socketType != QAbstractSocket::TcpSocket)
|
if (d->socketType != QAbstractSocket::TcpSocket)
|
||||||
return -1;
|
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.
|
||||||
|
if (d->readBytes.pos() == d->readBytes.size() && d->socketState != QAbstractSocket::ConnectedState) {
|
||||||
|
close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
QMutexLocker mutexLocker(&d->readMutex);
|
QMutexLocker mutexLocker(&d->readMutex);
|
||||||
return d->readBytes.read(data, maxlen);
|
return d->readBytes.read(data, maxlen);
|
||||||
}
|
}
|
||||||
@ -1184,8 +1201,16 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async
|
|||||||
if (wasDeleted || isDeletingChildren)
|
if (wasDeleted || isDeletingChildren)
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
if (status == Error || status == Canceled)
|
// 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) {
|
||||||
|
setError(QAbstractSocket::NetworkError, RemoteHostClosedErrorString);
|
||||||
|
socketState = QAbstractSocket::UnconnectedState;
|
||||||
|
if (notifyOnRead)
|
||||||
|
emit q->readReady();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
ComPtr<IBuffer> buffer;
|
ComPtr<IBuffer> buffer;
|
||||||
HRESULT hr = asyncInfo->GetResults(&buffer);
|
HRESULT hr = asyncInfo->GetResults(&buffer);
|
||||||
@ -1194,7 +1219,13 @@ HRESULT QNativeSocketEnginePrivate::handleReadyRead(IAsyncBufferOperation *async
|
|||||||
UINT32 bufferLength;
|
UINT32 bufferLength;
|
||||||
hr = buffer->get_Length(&bufferLength);
|
hr = buffer->get_Length(&bufferLength);
|
||||||
Q_ASSERT_SUCCEEDED(hr);
|
Q_ASSERT_SUCCEEDED(hr);
|
||||||
|
// 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) {
|
if (!bufferLength) {
|
||||||
|
setError(QAbstractSocket::NetworkError, RemoteHostClosedErrorString);
|
||||||
|
socketState = QAbstractSocket::UnconnectedState;
|
||||||
if (notifyOnRead)
|
if (notifyOnRead)
|
||||||
emit q->readReady();
|
emit q->readReady();
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
Loading…
Reference in New Issue
Block a user