summaryrefslogtreecommitdiffstats
path: root/src/network/access
diff options
context:
space:
mode:
Diffstat (limited to 'src/network/access')
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp42
-rw-r--r--src/network/access/qnetworkaccessmanager.h3
-rw-r--r--src/network/access/qnetworkaccessmanager_p.h2
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp44
-rw-r--r--src/network/access/qnetworkreplyhttpimpl_p.h7
-rw-r--r--src/network/access/qnetworkrequest.cpp65
-rw-r--r--src/network/access/qnetworkrequest.h18
7 files changed, 166 insertions, 15 deletions
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 76b95b5823..3e1e6d8be8 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -1240,7 +1240,7 @@ void QNetworkAccessManager::connectToHostEncrypted(const QString &hostName, quin
// There is no way to enable SPDY/HTTP2 via a request, so we need to check
// the ssl configuration whether SPDY/HTTP2 is allowed here.
if (sslConfiguration.allowedNextProtocols().contains(QSslConfiguration::ALPNProtocolHTTP2))
- request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true);
+ request.setAttribute(QNetworkRequest::Http2AllowedAttribute, true);
else if (sslConfiguration.allowedNextProtocols().contains(QSslConfiguration::NextProtocolSpdy3_0))
request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true);
@@ -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<const QNetworkSession> getNetworkSession(const QNetworkAccessManager *manager);
#endif
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index 8ac81d1780..a13c2b144c 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -461,6 +461,7 @@ QNetworkReplyHttpImplPrivate::QNetworkReplyHttpImplPrivate()
, preMigrationDownloaded(-1)
, bytesDownloaded(0)
, bytesBuffered(0)
+ , transferTimeout(nullptr)
, downloadBufferReadPosition(0)
, downloadBufferCurrentSize(0)
, downloadZerocopyBuffer(nullptr)
@@ -777,7 +778,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq
if (request.attribute(QNetworkRequest::SpdyAllowedAttribute).toBool())
httpRequest.setSPDYAllowed(true);
- if (request.attribute(QNetworkRequest::HTTP2AllowedAttribute).toBool())
+ if (request.attribute(QNetworkRequest::Http2AllowedAttribute).toBool())
httpRequest.setHTTP2Allowed(true);
if (request.attribute(QNetworkRequest::Http2DirectAttribute).toBool()) {
@@ -1067,6 +1068,7 @@ void QNetworkReplyHttpImplPrivate::replyDownloadData(QByteArray d)
if (!isHttpRedirectResponse()) {
buffer.append(d);
bytesDownloaded += d.size();
+ setupTransferTimeout();
}
bytesBuffered += d.size();
@@ -1280,15 +1282,15 @@ void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QList<QPair<QByte
}
q->setAttribute(QNetworkRequest::HttpPipeliningWasUsedAttribute, pu);
- const QVariant http2Allowed = request.attribute(QNetworkRequest::HTTP2AllowedAttribute);
+ const QVariant http2Allowed = request.attribute(QNetworkRequest::Http2AllowedAttribute);
const QVariant http2Direct = request.attribute(QNetworkRequest::Http2DirectAttribute);
if ((http2Allowed.isValid() && http2Allowed.toBool())
|| (http2Direct.isValid() && http2Direct.toBool())) {
- q->setAttribute(QNetworkRequest::HTTP2WasUsedAttribute, spdyWasUsed);
+ q->setAttribute(QNetworkRequest::Http2WasUsedAttribute, spdyWasUsed);
q->setAttribute(QNetworkRequest::SpdyWasUsedAttribute, false);
} else {
q->setAttribute(QNetworkRequest::SpdyWasUsedAttribute, spdyWasUsed);
- q->setAttribute(QNetworkRequest::HTTP2WasUsedAttribute, false);
+ q->setAttribute(QNetworkRequest::Http2WasUsedAttribute, false);
}
// reconstruct the HTTP header
@@ -1401,6 +1403,7 @@ void QNetworkReplyHttpImplPrivate::replyDownloadProgressSlot(qint64 bytesReceive
return;
bytesDownloaded = bytesReceived;
+ setupTransferTimeout();
downloadBufferCurrentSize = bytesReceived;
@@ -1857,7 +1860,6 @@ bool QNetworkReplyHttpImplPrivate::startWaitForSession(QSharedPointer<QNetworkSe
void QNetworkReplyHttpImplPrivate::_q_startOperation()
{
Q_Q(QNetworkReplyHttpImpl);
-
if (state == Working) // ensure this function is only being called once
return;
@@ -1897,6 +1899,7 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation()
}
#endif // QT_NO_BEARERMANAGEMENT
+ setupTransferTimeout();
if (synchronous) {
state = Finished;
q_func()->setFinished(true);
@@ -2033,6 +2036,31 @@ void QNetworkReplyHttpImplPrivate::_q_bufferOutgoingData()
}
}
+void QNetworkReplyHttpImplPrivate::_q_transferTimedOut()
+{
+ Q_Q(QNetworkReplyHttpImpl);
+ q->abort();
+}
+
+void QNetworkReplyHttpImplPrivate::setupTransferTimeout()
+{
+ Q_Q(QNetworkReplyHttpImpl);
+ if (!transferTimeout) {
+ transferTimeout = new QTimer(q);
+ QObject::connect(transferTimeout, SIGNAL(timeout()),
+ q, SLOT(_q_transferTimedOut()),
+ Qt::QueuedConnection);
+ }
+ transferTimeout->stop();
+ if (request.transferTimeout()) {
+ transferTimeout->setSingleShot(true);
+ transferTimeout->setInterval(request.transferTimeout());
+ QMetaObject::invokeMethod(transferTimeout, "start",
+ Qt::QueuedConnection);
+
+ }
+}
+
#ifndef QT_NO_BEARERMANAGEMENT
void QNetworkReplyHttpImplPrivate::_q_networkSessionConnected()
{
@@ -2115,6 +2143,8 @@ void QNetworkReplyHttpImplPrivate::emitReplyUploadProgress(qint64 bytesSent, qin
if (isFinished)
return;
+ setupTransferTimeout();
+
if (!emitAllUploadProgressSignals) {
//choke signal emissions, except the first and last signals which are unconditional
if (uploadProgressSignalChoke.isValid()) {
@@ -2126,7 +2156,6 @@ void QNetworkReplyHttpImplPrivate::emitReplyUploadProgress(qint64 bytesSent, qin
uploadProgressSignalChoke.start();
}
}
-
emit q->uploadProgress(bytesSent, bytesTotal);
}
@@ -2159,7 +2188,8 @@ void QNetworkReplyHttpImplPrivate::_q_finished()
void QNetworkReplyHttpImplPrivate::finished()
{
Q_Q(QNetworkReplyHttpImpl);
-
+ if (transferTimeout)
+ transferTimeout->stop();
if (state == Finished || state == Aborted || state == WaitingForSession)
return;
diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h
index ef69ce0653..dec0c4c589 100644
--- a/src/network/access/qnetworkreplyhttpimpl_p.h
+++ b/src/network/access/qnetworkreplyhttpimpl_p.h
@@ -59,6 +59,7 @@
#include "QtCore/qdatetime.h"
#include "QtCore/qsharedpointer.h"
#include "QtCore/qscopedpointer.h"
+#include "QtCore/qtimer.h"
#include "qatomic.h"
#include <QtNetwork/QNetworkCacheMetaData>
@@ -100,6 +101,7 @@ public:
Q_PRIVATE_SLOT(d_func(), void _q_cacheLoadReadyRead())
Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingData())
Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingDataFinished())
+ Q_PRIVATE_SLOT(d_func(), void _q_transferTimedOut())
#ifndef QT_NO_BEARERMANAGEMENT
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionConnected())
Q_PRIVATE_SLOT(d_func(), void _q_networkSessionFailed())
@@ -181,6 +183,9 @@ public:
void _q_cacheSaveDeviceAboutToClose();
+ void _q_transferTimedOut();
+ void setupTransferTimeout();
+
#ifndef QT_NO_BEARERMANAGEMENT
void _q_networkSessionConnected();
void _q_networkSessionFailed();
@@ -250,6 +255,8 @@ public:
qint64 bytesDownloaded;
qint64 bytesBuffered;
+ QTimer *transferTimeout;
+
// Only used when the "zero copy" style is used.
// Please note that the whole "zero copy" download buffer API is private right now. Do not use it.
qint64 downloadBufferReadPosition;
diff --git a/src/network/access/qnetworkrequest.cpp b/src/network/access/qnetworkrequest.cpp
index 118fb6b1fb..e03d844af9 100644
--- a/src/network/access/qnetworkrequest.cpp
+++ b/src/network/access/qnetworkrequest.cpp
@@ -277,23 +277,30 @@ QT_BEGIN_NAMESPACE
Indicates whether the QNetworkAccessManager code is
allowed to use SPDY with this request. This applies only
to SSL requests, and depends on the server supporting SPDY.
+ Obsolete, use Http2 instead of Spdy.
\value SpdyWasUsedAttribute
Replies only, type: QMetaType::Bool
Indicates whether SPDY was used for receiving
- this reply.
+ this reply. Obsolete, use Http2 instead of Spdy.
- \value HTTP2AllowedAttribute
+ \value Http2AllowedAttribute
Requests only, type: QMetaType::Bool (default: false)
Indicates whether the QNetworkAccessManager code is
allowed to use HTTP/2 with this request. This applies
to SSL requests or 'cleartext' HTTP/2.
- \value HTTP2WasUsedAttribute
+ \value Http2WasUsedAttribute
Replies only, type: QMetaType::Bool (default: false)
Indicates whether HTTP/2 was used for receiving this reply.
(This value was introduced in 5.9.)
+ \value HTTP2AllowedAttribute
+ Obsolete alias for Http2AllowedAttribute.
+
+ \value HTTP2WasUsedAttribute
+ Obsolete alias for Http2WasUsedAttribute.
+
\value EmitAllUploadProgressSignalsAttribute
Requests only, type: QMetaType::Bool (default: false)
Indicates whether all upload signals should be emitted.
@@ -329,7 +336,7 @@ QT_BEGIN_NAMESPACE
server supports HTTP/2. The attribute works with SSL or 'cleartext'
HTTP/2. If a server turns out to not support HTTP/2, when HTTP/2 direct
was specified, QNetworkAccessManager gives up, without attempting to
- fall back to HTTP/1.1. If both HTTP2AllowedAttribute and
+ fall back to HTTP/1.1. If both Http2AllowedAttribute and
Http2DirectAttribute are set, Http2DirectAttribute takes priority.
(This value was introduced in 5.11.)
@@ -418,6 +425,18 @@ QT_BEGIN_NAMESPACE
based on some app-specific configuration.
*/
+/*!
+ \enum QNetworkRequest::TransferTimeoutConstant
+ \since 5.15
+
+ A constant that can be used for enabling transfer
+ timeouts with a preset value.
+
+ \value TransferTimeoutPreset The transfer timeout in milliseconds.
+ Used if setTimeout() is called
+ without an argument.
+ */
+
class QNetworkRequestPrivate: public QSharedData, public QNetworkHeadersPrivate
{
public:
@@ -428,6 +447,7 @@ public:
, sslConfiguration(0)
#endif
, maxRedirectsAllowed(maxRedirectCount)
+ , transferTimeout(0)
{ qRegisterMetaType<QNetworkRequest>(); }
~QNetworkRequestPrivate()
{
@@ -452,6 +472,7 @@ public:
#if QT_CONFIG(http)
h2Configuration = other.h2Configuration;
#endif
+ transferTimeout = other.transferTimeout;
}
inline bool operator==(const QNetworkRequestPrivate &other) const
@@ -465,6 +486,7 @@ public:
#if QT_CONFIG(http)
&& h2Configuration == other.h2Configuration
#endif
+ && transferTimeout == other.transferTimeout
;
// don't compare cookedHeaders
}
@@ -479,6 +501,7 @@ public:
#if QT_CONFIG(http)
QHttp2Configuration h2Configuration;
#endif
+ int transferTimeout;
};
/*!
@@ -902,6 +925,40 @@ void QNetworkRequest::setHttp2Configuration(const QHttp2Configuration &configura
{
d->h2Configuration = configuration;
}
+
+/*!
+ \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.
+
+ \sa setTransferTimeout
+*/
+int QNetworkRequest::transferTimeout()
+{
+ return d->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.
+
+ \sa transferTimeout
+*/
+void QNetworkRequest::setTransferTimeout(int timeout)
+{
+ d->transferTimeout = timeout;
+}
#endif // QT_CONFIG(http) || defined(Q_CLANG_QDOC)
static QByteArray headerName(QNetworkRequest::KnownHeaders header)
diff --git a/src/network/access/qnetworkrequest.h b/src/network/access/qnetworkrequest.h
index e09ff8aaae..5d9969bd9b 100644
--- a/src/network/access/qnetworkrequest.h
+++ b/src/network/access/qnetworkrequest.h
@@ -89,12 +89,18 @@ public:
DownloadBufferAttribute, // internal
SynchronousRequestAttribute, // internal
BackgroundRequestAttribute,
+#if QT_DEPRECATED_SINCE(5, 15)
SpdyAllowedAttribute,
SpdyWasUsedAttribute,
- EmitAllUploadProgressSignalsAttribute,
+#endif // QT_DEPRECATED_SINCE(5, 15)
+ EmitAllUploadProgressSignalsAttribute = BackgroundRequestAttribute + 3,
FollowRedirectsAttribute,
- HTTP2AllowedAttribute,
- HTTP2WasUsedAttribute,
+ Http2AllowedAttribute,
+ Http2WasUsedAttribute,
+#if QT_DEPRECATED_SINCE(5, 15)
+ HTTP2AllowedAttribute Q_DECL_ENUMERATOR_DEPRECATED_X("Use Http2AllowedAttribute") = Http2AllowedAttribute,
+ HTTP2WasUsedAttribute Q_DECL_ENUMERATOR_DEPRECATED_X("Use Http2WasUsedAttribute"),
+#endif // QT_DEPRECATED_SINCE(5, 15)
OriginalContentLengthAttribute,
RedirectPolicyAttribute,
Http2DirectAttribute,
@@ -128,6 +134,9 @@ public:
UserVerifiedRedirectPolicy
};
+ enum TransferTimeoutConstant {
+ TransferTimeoutPreset = 30000
+ };
QNetworkRequest();
explicit QNetworkRequest(const QUrl &url);
@@ -179,6 +188,9 @@ public:
#if QT_CONFIG(http) || defined(Q_CLANG_QDOC)
QHttp2Configuration http2Configuration() const;
void setHttp2Configuration(const QHttp2Configuration &configuration);
+
+ int transferTimeout();
+ void setTransferTimeout(int timeout = TransferTimeoutPreset);
#endif // QT_CONFIG(http) || defined(Q_CLANG_QDOC)
private:
QSharedDataPointer<QNetworkRequestPrivate> d;