QHttpSocketEngine: ensure pending EOF triggers a notification
When the remote peer closed the connection, a read notification needs to always be emitted, otherwise the higher layer does not get the disconnected signal. From the other side, underlying QAbstractSocket object could temporarily disable notifications from the engine at any time. To avoid possible blocking of the socket, take a pending EOF into account when the read notifications are re-enabled. Change-Id: Iac9d4e2f790530be3500baf5a2000f1f63df5cc2 Reviewed-by: Ulf Hermann <ulf.hermann@theqtcompany.com>
This commit is contained in:
parent
5243696528
commit
294111e25a
@ -439,8 +439,11 @@ void QHttpSocketEngine::setReadNotificationEnabled(bool enable)
|
||||
d->readNotificationEnabled = enable;
|
||||
if (enable) {
|
||||
// Enabling read notification can trigger a notification.
|
||||
if (bytesAvailable())
|
||||
if (bytesAvailable()) {
|
||||
slotSocketReadNotification();
|
||||
} else if (d->socket && d->socket->state() == QAbstractSocket::UnconnectedState) {
|
||||
emitReadNotification();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,6 +72,7 @@ private slots:
|
||||
void downloadBigFile();
|
||||
// void tcpLoopbackPerformance();
|
||||
void passwordAuth();
|
||||
void ensureEofTriggersNotification();
|
||||
|
||||
protected slots:
|
||||
void tcpSocketNonBlocking_hostFound();
|
||||
@ -739,5 +740,51 @@ void tst_QHttpSocketEngine::passwordAuth()
|
||||
|
||||
//----------------------------------------------------------------------------------
|
||||
|
||||
void tst_QHttpSocketEngine::ensureEofTriggersNotification()
|
||||
{
|
||||
QList<QByteArray> serverData;
|
||||
// Set the handshake and server response data
|
||||
serverData << "HTTP/1.0 200 Connection established\r\n\r\n" << "0";
|
||||
MiniHttpServer server(serverData);
|
||||
|
||||
QTcpSocket socket;
|
||||
connect(&socket, SIGNAL(connected()), SLOT(exitLoopSlot()));
|
||||
socket.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, server.serverAddress().toString(),
|
||||
server.serverPort()));
|
||||
socket.connectToHost("0.1.2.3", 12345);
|
||||
|
||||
QTestEventLoop::instance().enterLoop(5);
|
||||
if (QTestEventLoop::instance().timeout())
|
||||
QFAIL("Connect timed out");
|
||||
|
||||
QCOMPARE(socket.state(), QTcpSocket::ConnectedState);
|
||||
// Disable read notification on server response
|
||||
socket.setReadBufferSize(1);
|
||||
socket.putChar(0);
|
||||
|
||||
// Wait for the response
|
||||
connect(&socket, SIGNAL(readyRead()), SLOT(exitLoopSlot()));
|
||||
QTestEventLoop::instance().enterLoop(5);
|
||||
if (QTestEventLoop::instance().timeout())
|
||||
QFAIL("Read timed out");
|
||||
|
||||
QCOMPARE(socket.state(), QTcpSocket::ConnectedState);
|
||||
QCOMPARE(socket.bytesAvailable(), 1);
|
||||
// Trigger a read notification
|
||||
socket.readAll();
|
||||
// Check for pending EOF at input
|
||||
QCOMPARE(socket.bytesAvailable(), 0);
|
||||
QCOMPARE(socket.state(), QTcpSocket::ConnectedState);
|
||||
|
||||
// Try to read EOF
|
||||
connect(&socket, SIGNAL(disconnected()), SLOT(exitLoopSlot()));
|
||||
QTestEventLoop::instance().enterLoop(5);
|
||||
if (QTestEventLoop::instance().timeout())
|
||||
QFAIL("Disconnect timed out");
|
||||
|
||||
// Check that it's closed
|
||||
QCOMPARE(socket.state(), QTcpSocket::UnconnectedState);
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QHttpSocketEngine)
|
||||
#include "tst_qhttpsocketengine.moc"
|
||||
|
Loading…
Reference in New Issue
Block a user