summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
authorAaron McCarthy <aaron.mccarthy@nokia.com>2010-02-12 01:14:49 (GMT)
committerAaron McCarthy <aaron.mccarthy@nokia.com>2010-02-12 03:05:30 (GMT)
commitcc1268a6cbc9797e2a9137f7a0389f3d144a8c0a (patch)
tree60b38471ee1e8fc66a93978f599dca6f12b2a870 /src/network
parentcb9cf8fbe9dd54c011490ee814c0692e61b729df (diff)
downloadQt-cc1268a6cbc9797e2a9137f7a0389f3d144a8c0a.zip
Qt-cc1268a6cbc9797e2a9137f7a0389f3d144a8c0a.tar.gz
Qt-cc1268a6cbc9797e2a9137f7a0389f3d144a8c0a.tar.bz2
Move http resume code into http backend.
Adds two new virtual functions to QNetworkAccessBackend: bool canResume() const; and void setResumeOffset(quint64) canResume() is used to query the existing backend if resuming is supported for the current request. setResumeOffset() is used to set an additional offset which should be applied when the backend posts the request. The default implementation of canResume() returns false (resuming not supported). The default implementation of setResumeOffset() does nothing.
Diffstat (limited to 'src/network')
-rw-r--r--src/network/access/qnetworkaccessbackend_p.h4
-rw-r--r--src/network/access/qnetworkaccesshttpbackend.cpp48
-rw-r--r--src/network/access/qnetworkaccesshttpbackend_p.h5
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp21
4 files changed, 60 insertions, 18 deletions
diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h
index 830ec7e..eab011c 100644
--- a/src/network/access/qnetworkaccessbackend_p.h
+++ b/src/network/access/qnetworkaccessbackend_p.h
@@ -162,6 +162,10 @@ public:
// This will possibly enable buffering of the upload data.
virtual bool needsResetableUploadData() { return false; }
+ // Returns true if backend is able to resume downloads.
+ virtual bool canResume() const { return false; }
+ virtual void setResumeOffset(quint64 offset) { Q_UNUSED(offset); }
+
protected:
// Create the device used for reading the upload data
QNonContiguousByteDevice* createUploadByteDevice();
diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp
index 8e02723..aa6a820 100644
--- a/src/network/access/qnetworkaccesshttpbackend.cpp
+++ b/src/network/access/qnetworkaccesshttpbackend.cpp
@@ -296,6 +296,7 @@ QNetworkAccessHttpBackend::QNetworkAccessHttpBackend()
#ifndef QT_NO_OPENSSL
, pendingSslConfiguration(0), pendingIgnoreAllSslErrors(false)
#endif
+ , resumeOffset(0)
{
}
@@ -533,6 +534,28 @@ void QNetworkAccessHttpBackend::postRequest()
httpRequest.setUrl(url());
QList<QByteArray> headers = request().rawHeaderList();
+ if (resumeOffset != 0) {
+ if (headers.contains("Range")) {
+ // Need to adjust resume offset for user specified range
+
+ headers.removeOne("Range");
+
+ // We've already verified that requestRange starts with "bytes=", see canResume.
+ QByteArray requestRange = request().rawHeader("Range").mid(6);
+
+ int index = requestRange.indexOf('-');
+
+ quint64 requestStartOffset = requestRange.left(index).toULongLong();
+ quint64 requestEndOffset = requestRange.mid(index + 1).toULongLong();
+
+ requestRange = "bytes=" + QByteArray::number(resumeOffset + requestStartOffset) +
+ '-' + QByteArray::number(requestEndOffset);
+
+ httpRequest.setHeaderField("Range", requestRange);
+ } else {
+ httpRequest.setHeaderField("Range", "bytes=" + QByteArray::number(resumeOffset) + '-');
+ }
+ }
foreach (const QByteArray &header, headers)
httpRequest.setHeaderField(header, request().rawHeader(header));
@@ -1108,6 +1131,31 @@ QNetworkCacheMetaData QNetworkAccessHttpBackend::fetchCacheMetaData(const QNetwo
return metaData;
}
+bool QNetworkAccessHttpBackend::canResume() const
+{
+ // Only GET operation supports resuming.
+ if (operation() != QNetworkAccessManager::GetOperation)
+ return false;
+
+ // Can only resume if server/resource supports Range header.
+ if (httpReply->headerField("Accept-Ranges", "none") == "none")
+ return false;
+
+ // We only support resuming for byte ranges.
+ if (request().hasRawHeader("Range")) {
+ QByteArray range = request().rawHeader("Range");
+ if (!range.startsWith("bytes="))
+ return false;
+ }
+
+ return true;
+}
+
+void QNetworkAccessHttpBackend::setResumeOffset(quint64 offset)
+{
+ resumeOffset = offset;
+}
+
QT_END_NAMESPACE
#endif // QT_NO_HTTP
diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h
index 0eaf003..e5cc0ab 100644
--- a/src/network/access/qnetworkaccesshttpbackend_p.h
+++ b/src/network/access/qnetworkaccesshttpbackend_p.h
@@ -99,6 +99,9 @@ public:
// we return true since HTTP needs to send PUT/POST data again after having authenticated
bool needsResetableUploadData() { return true; }
+ bool canResume() const;
+ void setResumeOffset(quint64 offset);
+
private slots:
void replyReadyRead();
void replyFinished();
@@ -120,6 +123,8 @@ private:
QList<QSslError> pendingIgnoreSslErrorsList;
#endif
+ quint64 resumeOffset;
+
void disconnectFromHttp();
void setupConnection();
void validateCache(QHttpNetworkRequest &httpRequest, bool &loadedFromCache);
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index 7f66b25..2906caa 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -497,15 +497,6 @@ void QNetworkReplyImplPrivate::appendDownstreamData(QByteDataBuffer &data)
QPointer<QNetworkReplyImpl> qq = q;
QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
- if (totalSize.isNull()) {
- RawHeadersList::ConstIterator it = findRawHeader("Content-Range");
- if (it != rawHeaders.constEnd()) {
- int index = it->second.lastIndexOf('/');
- if (index != -1)
- totalSize = it->second.mid(index + 1).toLongLong() - preMigrationDownloaded;
- }
- }
-
if (preMigrationDownloaded != Q_INT64_C(-1))
totalSize = totalSize.toLongLong() + preMigrationDownloaded;
pauseNotificationHandling();
@@ -812,8 +803,8 @@ bool QNetworkReplyImplPrivate::migrateBackend()
if (state == Finished || state == Aborted)
return true;
- // Resume only supported by http backend, not migrating.
- if (!qobject_cast<QNetworkAccessHttpBackend *>(backend))
+ // Backend does not support resuming download.
+ if (!backend->canResume())
return false;
// Request has outgoing data, not migrating.
@@ -824,11 +815,6 @@ bool QNetworkReplyImplPrivate::migrateBackend()
if (copyDevice)
return true;
- // Range header is not supported by server/resource, can't migrate.
- RawHeadersList::ConstIterator it = findRawHeader("Accept-Ranges");
- if (it == rawHeaders.constEnd() || it->second == "none")
- return false;
-
state = QNetworkReplyImplPrivate::Reconnecting;
if (backend) {
@@ -841,13 +827,12 @@ bool QNetworkReplyImplPrivate::migrateBackend()
preMigrationDownloaded = bytesDownloaded;
- request.setRawHeader("Range", "bytes=" + QByteArray::number(preMigrationDownloaded) + '-');
-
backend = manager->d_func()->findBackend(operation, request);
if (backend) {
backend->setParent(q);
backend->reply = this;
+ backend->setResumeOffset(bytesDownloaded);
}
if (qobject_cast<QNetworkAccessHttpBackend *>(backend)) {