From 36e277e91732d6d75fb6d9cb691fe9c0f83f6178 Mon Sep 17 00:00:00 2001 From: Ville Voutilainen Date: Wed, 23 Oct 2019 17:21:49 +0300 Subject: [PATCH] Add a transfer timeout at QNAM level as well MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Task-number: QTBUG-3443 Change-Id: Idc4d3c9b1ace69bd8b6456506778116a3e8a5490 Reviewed-by: MÃ¥rten Nordheim --- src/network/access/qnetworkaccessmanager.cpp | 40 +++++++++++++++++++ src/network/access/qnetworkaccessmanager.h | 3 ++ src/network/access/qnetworkaccessmanager_p.h | 2 + .../qnetworkreply/tst_qnetworkreply.cpp | 26 ++++++++++++ 4 files changed, 71 insertions(+) diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 98c82c81ae..3e1e6d8be8 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1404,6 +1404,11 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, redirectPolicy()); } +#if QT_CONFIG(http) + if (!req.transferTimeout()) + req.setTransferTimeout(transferTimeout()); +#endif + if (autoDeleteReplies() && req.attribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute).isNull()) { req.setAttribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute, true); @@ -1713,6 +1718,41 @@ void QNetworkAccessManager::setAutoDeleteReplies(bool shouldAutoDelete) d_func()->autoDeleteReplies = shouldAutoDelete; } +/*! + \since 5.15 + + Returns the timeout used for transfers, in milliseconds. + + This timeout is zero if setTransferTimeout() hasn't been + called, which means that the timeout is not used. +*/ +int QNetworkAccessManager::transferTimeout() +{ + return d_func()->transferTimeout; +} + +/*! + \since 5.15 + + Sets \a timeout as the transfer timeout in milliseconds. + + Transfers are aborted if no bytes are transferred before + the timeout expires. Zero means no timer is set. If no + argument is provided, the timeout is + QNetworkRequest::TransferTimeoutPreset. If this function + is not called, the timeout is disabled and has the + value zero. The request-specific non-zero timeouts set for + the requests that are executed override this value. This means + that if QNetworkAccessManager has an enabled timeout, it needs + to be disabled to execute a request without a timeout. + + \sa transferTimeout() +*/ +void QNetworkAccessManager::setTransferTimeout(int timeout) +{ + d_func()->transferTimeout = timeout; +} + void QNetworkAccessManagerPrivate::_q_replyFinished() { Q_Q(QNetworkAccessManager); diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index 98498d07d2..6db4094a8e 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -170,6 +170,9 @@ public: bool autoDeleteReplies() const; void setAutoDeleteReplies(bool autoDelete); + int transferTimeout(); + void setTransferTimeout(int timeout = QNetworkRequest::TransferTimeoutPreset); + Q_SIGNALS: #ifndef QT_NO_NETWORKPROXY void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator); diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index 67ea2094b3..d558f61eed 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -229,6 +229,8 @@ public: bool autoDeleteReplies = false; + int transferTimeout = 0; + #ifndef QT_NO_BEARERMANAGEMENT Q_AUTOTEST_EXPORT static const QWeakPointer getNetworkSession(const QNetworkAccessManager *manager); #endif diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index 3bc6717d58..c523b0c20e 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -9369,6 +9369,19 @@ void tst_QNetworkReply::getWithTimeout() QCOMPARE(spy2.count(), 1); QVERIFY(reply2->error() == QNetworkReply::OperationCanceledError); + + request.setTransferTimeout(0); + manager.setTransferTimeout(1000); + + QNetworkReplyPtr reply3(manager.get(request)); + QSignalSpy spy3(reply3.data(), SIGNAL(error(QNetworkReply::NetworkError))); + + QCOMPARE(waitForFinish(reply3), int(Failure)); + + QCOMPARE(spy3.count(), 1); + QVERIFY(reply3->error() == QNetworkReply::OperationCanceledError); + + manager.setTransferTimeout(0); } void tst_QNetworkReply::postWithTimeout() @@ -9396,6 +9409,19 @@ void tst_QNetworkReply::postWithTimeout() QCOMPARE(spy2.count(), 1); QVERIFY(reply2->error() == QNetworkReply::OperationCanceledError); + + request.setTransferTimeout(0); + manager.setTransferTimeout(1000); + + QNetworkReplyPtr reply3(manager.post(request, postData)); + QSignalSpy spy3(reply3.data(), SIGNAL(error(QNetworkReply::NetworkError))); + + QCOMPARE(waitForFinish(reply3), int(Failure)); + + QCOMPARE(spy3.count(), 1); + QVERIFY(reply3->error() == QNetworkReply::OperationCanceledError); + + manager.setTransferTimeout(0); } // NOTE: This test must be last testcase in tst_qnetworkreply!