summaryrefslogtreecommitdiffstats
path: root/tests/auto/network
diff options
context:
space:
mode:
authorUlf Hermann <ulf.hermann@theqtcompany.com>2015-09-25 13:23:46 +0200
committerMarkus Goetz (Woboq GmbH) <markus@woboq.com>2015-11-05 08:40:57 +0000
commit7aba75ffc52e5dce4b3ada12668611be2ad6787e (patch)
treebea89e4b84b9bc3af82410a66de9e0e3977f3610 /tests/auto/network
parentc69f75426d004d7cdadf51ea06238fef98493ec7 (diff)
Don't let closed http sockets pass as valid connections
A QAbstractSocket can be close()'d at any time, independently of its current connection state. being closed means that we cannot use it to read or write data, but internally it might still have some data to send or receive, for example to an http server. We can even get a connected() signal after close()'ing the socket. We need to catch this condition and mark any pending data not yet written to the socket for resending. (cherry picked from commit 0df5d079290b4c3b13e58e9397fabdc1dfdba96b) Task-number: QTBUG-48326 Change-Id: I67d9ad36f7288c9c6bef51aa6253d7b187737601 Reviewed-by: Ulf Hermann <ulf.hermann@theqtcompany.com> Reviewed-by: Markus Goetz (Woboq GmbH) <markus@woboq.com>
Diffstat (limited to 'tests/auto/network')
-rw-r--r--tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp54
1 files changed, 54 insertions, 0 deletions
diff --git a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
index 5d072af6d5..0d188a8fec 100644
--- a/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
+++ b/tests/auto/network/access/qhttpnetworkconnection/tst_qhttpnetworkconnection.cpp
@@ -36,6 +36,7 @@
#include "private/qhttpnetworkconnection_p.h"
#include "private/qnoncontiguousbytedevice_p.h"
#include <QAuthenticator>
+#include <QTcpServer>
#include "../../../network-settings.h"
@@ -106,6 +107,8 @@ private Q_SLOTS:
void getAndThenDeleteObject();
void getAndThenDeleteObject_data();
+
+ void overlappingCloseAndWrite();
};
tst_QHttpNetworkConnection::tst_QHttpNetworkConnection()
@@ -1112,6 +1115,57 @@ void tst_QHttpNetworkConnection::getAndThenDeleteObject()
}
}
+class TestTcpServer : public QTcpServer
+{
+ Q_OBJECT
+public:
+ TestTcpServer() : errorCodeReports(0)
+ {
+ connect(this, &QTcpServer::newConnection, this, &TestTcpServer::onNewConnection);
+ QVERIFY(listen(QHostAddress::LocalHost));
+ }
+
+ int errorCodeReports;
+
+public slots:
+ void onNewConnection()
+ {
+ QTcpSocket *socket = nextPendingConnection();
+ if (!socket)
+ return;
+ // close socket instantly!
+ connect(socket, &QTcpSocket::readyRead, socket, &QTcpSocket::close);
+ }
+
+ void onReply(QNetworkReply::NetworkError code)
+ {
+ QCOMPARE(code, QNetworkReply::RemoteHostClosedError);
+ ++errorCodeReports;
+ }
+};
+
+void tst_QHttpNetworkConnection::overlappingCloseAndWrite()
+{
+ // server accepts connections, but closes the socket instantly
+ TestTcpServer server;
+ QNetworkAccessManager accessManager;
+
+ // ten requests are scheduled. All should result in an RemoteHostClosed...
+ QUrl url;
+ url.setScheme(QStringLiteral("http"));
+ url.setHost(server.serverAddress().toString());
+ url.setPort(server.serverPort());
+ for (int i = 0; i < 10; ++i) {
+ QNetworkRequest request(url);
+ QNetworkReply *reply = accessManager.get(request);
+ // Not using Qt5 connection syntax here because of overly baroque syntax to discern between
+ // different error() methods.
+ QObject::connect(reply, SIGNAL(error(QNetworkReply::NetworkError)),
+ &server, SLOT(onReply(QNetworkReply::NetworkError)));
+ }
+
+ QTRY_COMPARE(server.errorCodeReports, 10);
+}
QTEST_MAIN(tst_QHttpNetworkConnection)