diff options
author | Aaron McCarthy <aaron.mccarthy@nokia.com> | 2010-02-12 01:14:49 (GMT) |
---|---|---|
committer | Aaron McCarthy <aaron.mccarthy@nokia.com> | 2010-02-12 03:05:30 (GMT) |
commit | cc1268a6cbc9797e2a9137f7a0389f3d144a8c0a (patch) | |
tree | 60b38471ee1e8fc66a93978f599dca6f12b2a870 /src/network | |
parent | cb9cf8fbe9dd54c011490ee814c0692e61b729df (diff) | |
download | Qt-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.h | 4 | ||||
-rw-r--r-- | src/network/access/qnetworkaccesshttpbackend.cpp | 48 | ||||
-rw-r--r-- | src/network/access/qnetworkaccesshttpbackend_p.h | 5 | ||||
-rw-r--r-- | src/network/access/qnetworkreplyimpl.cpp | 21 |
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)) { |