diff options
Diffstat (limited to 'src/network/access/qnetworkreplyhttpimpl.cpp')
-rw-r--r-- | src/network/access/qnetworkreplyhttpimpl.cpp | 130 |
1 files changed, 62 insertions, 68 deletions
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index 94235a48dd..6bf3c56db2 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -1,31 +1,37 @@ /**************************************************************************** ** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ +** Copyright (C) 2016 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtNetwork module of the Qt Toolkit. ** -** $QT_BEGIN_LICENSE:LGPL21$ +** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms -** and conditions see http://www.qt.io/terms-conditions. For further -** information use the contact form at http://www.qt.io/contact-us. +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 or version 3 as published by the Free -** Software Foundation and appearing in the file LICENSE.LGPLv21 and -** LICENSE.LGPLv3 included in the packaging of this file. Please review the -** following information to ensure the GNU Lesser General Public License -** requirements will be met: https://www.gnu.org/licenses/lgpl.html and -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** -** As a special exception, The Qt Company gives you certain additional -** rights. These rights are described in The Qt Company LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** @@ -290,7 +296,7 @@ qint64 QNetworkReplyHttpImpl::bytesAvailable() const // if we load from cache device if (d->cacheLoadDevice) { - return QNetworkReply::bytesAvailable() + d->cacheLoadDevice->bytesAvailable() + d->downloadMultiBuffer.byteAmount(); + return QNetworkReply::bytesAvailable() + d->cacheLoadDevice->bytesAvailable(); } // zerocopy buffer @@ -299,7 +305,7 @@ qint64 QNetworkReplyHttpImpl::bytesAvailable() const } // normal buffer - return QNetworkReply::bytesAvailable() + d->downloadMultiBuffer.byteAmount(); + return QNetworkReply::bytesAvailable(); } bool QNetworkReplyHttpImpl::isSequential () const @@ -323,12 +329,6 @@ qint64 QNetworkReplyHttpImpl::readData(char* data, qint64 maxlen) if (d->cacheLoadDevice) { // FIXME bytesdownloaded, position etc? - // There is something already in the buffer we buffered before because the user did not read() - // anything, so we read there first: - if (!d->downloadMultiBuffer.isEmpty()) { - return d->downloadMultiBuffer.read(data, maxlen); - } - qint64 ret = d->cacheLoadDevice->read(data, maxlen); return ret; } @@ -345,25 +345,14 @@ qint64 QNetworkReplyHttpImpl::readData(char* data, qint64 maxlen) } // normal buffer - if (d->downloadMultiBuffer.isEmpty()) { - if (d->state == d->Finished || d->state == d->Aborted) - return -1; - return 0; - } - - if (maxlen == 1) { - // optimization for getChar() - *data = d->downloadMultiBuffer.getChar(); - if (readBufferSize()) - emit readBufferFreed(1); - return 1; - } + if (d->state == d->Finished || d->state == d->Aborted) + return -1; - maxlen = qMin<qint64>(maxlen, d->downloadMultiBuffer.byteAmount()); - qint64 bytesRead = d->downloadMultiBuffer.read(data, maxlen); + qint64 wasBuffered = d->bytesBuffered; + d->bytesBuffered = 0; if (readBufferSize()) - emit readBufferFreed(bytesRead); - return bytesRead; + emit readBufferFreed(wasBuffered); + return 0; } void QNetworkReplyHttpImpl::setReadBufferSize(qint64 size) @@ -381,12 +370,12 @@ bool QNetworkReplyHttpImpl::canReadLine () const return true; if (d->cacheLoadDevice) - return d->cacheLoadDevice->canReadLine() || d->downloadMultiBuffer.canReadLine(); + return d->cacheLoadDevice->canReadLine(); if (d->downloadZerocopyBuffer) return memchr(d->downloadZerocopyBuffer + d->downloadBufferReadPosition, '\n', d->downloadBufferCurrentSize - d->downloadBufferReadPosition); - return d->downloadMultiBuffer.canReadLine(); + return false; } #ifndef QT_NO_SSL @@ -438,6 +427,7 @@ QNetworkReplyHttpImplPrivate::QNetworkReplyHttpImplPrivate() , resumeOffset(0) , preMigrationDownloaded(-1) , bytesDownloaded(0) + , bytesBuffered(0) , downloadBufferReadPosition(0) , downloadBufferCurrentSize(0) , downloadZerocopyBuffer(0) @@ -642,7 +632,8 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq QNetworkProxy transparentProxy, cacheProxy; // FIXME the proxy stuff should be done in the HTTP thread - foreach (const QNetworkProxy &p, managerPrivate->queryProxy(QNetworkProxyQuery(newHttpRequest.url()))) { + const auto proxies = managerPrivate->queryProxy(QNetworkProxyQuery(newHttpRequest.url())); + for (const QNetworkProxy &p : proxies) { // use the first proxy that works // for non-encrypted connections, any transparent or HTTP proxy // for encrypted, only transparent proxies @@ -722,10 +713,11 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq QList<QByteArray> headers = newHttpRequest.rawHeaderList(); if (resumeOffset != 0) { - if (headers.contains("Range")) { + const int rangeIndex = headers.indexOf("Range"); + if (rangeIndex != -1) { // Need to adjust resume offset for user specified range - headers.removeOne("Range"); + headers.removeAt(rangeIndex); // We've already verified that requestRange starts with "bytes=", see canResume. QByteArray requestRange = newHttpRequest.rawHeader("Range").mid(6); @@ -744,7 +736,7 @@ void QNetworkReplyHttpImplPrivate::postRequest(const QNetworkRequest &newHttpReq } } - foreach (const QByteArray &header, headers) + for (const QByteArray &header : qAsConst(headers)) httpRequest.setHeaderField(header, newHttpRequest.rawHeader(header)); if (newHttpRequest.attribute(QNetworkRequest::HttpPipeliningAllowedAttribute).toBool()) @@ -990,7 +982,7 @@ void QNetworkReplyHttpImplPrivate::initCacheSaveDevice() q->connect(cacheSaveDevice, SIGNAL(aboutToClose()), SLOT(_q_cacheSaveDeviceAboutToClose())); if (!cacheSaveDevice || (cacheSaveDevice && !cacheSaveDevice->isOpen())) { - if (cacheSaveDevice && !cacheSaveDevice->isOpen()) + if (Q_UNLIKELY(cacheSaveDevice && !cacheSaveDevice->isOpen())) qCritical("QNetworkReplyImpl: network cache returned a device that is not open -- " "class %s probably needs to be fixed", managerPrivate->networkCache->metaObject()->className()); @@ -1046,10 +1038,11 @@ void QNetworkReplyHttpImplPrivate::replyDownloadData(QByteArray d) cacheSaveDevice->write(item.constData(), item.size()); if (!isHttpRedirectResponse()) - downloadMultiBuffer.append(item); + buffer.append(item); bytesWritten += item.size(); } + bytesBuffered += bytesWritten; pendingDownloadDataCopy.clear(); QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader); @@ -1159,11 +1152,10 @@ void QNetworkReplyHttpImplPrivate::checkForRedirect(const int statusCode) } } -void QNetworkReplyHttpImplPrivate::replyDownloadMetaData - (QList<QPair<QByteArray,QByteArray> > hm, - int sc,QString rp,bool pu, - QSharedPointer<char> db, - qint64 contentLength, bool spdyWasUsed) +void QNetworkReplyHttpImplPrivate::replyDownloadMetaData(const QList<QPair<QByteArray,QByteArray> > &hm, + int sc, const QString &rp, bool pu, + QSharedPointer<char> db, + qint64 contentLength, bool spdyWasUsed) { Q_Q(QNetworkReplyHttpImpl); Q_UNUSED(contentLength); @@ -1506,8 +1498,8 @@ QNetworkCacheMetaData QNetworkReplyHttpImplPrivate::fetchCacheMetaData(const QNe cacheHeaders.setAllRawHeaders(metaData.rawHeaders()); QNetworkHeadersPrivate::RawHeadersList::ConstIterator it; - QList<QByteArray> newHeaders = q->rawHeaderList(); - foreach (QByteArray header, newHeaders) { + const QList<QByteArray> newHeaders = q->rawHeaderList(); + for (QByteArray header : newHeaders) { QByteArray originalHeader = header; header = header.toLower(); bool hop_by_hop = @@ -1730,7 +1722,7 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation() // ensure this function is only being called once if (state == Working) { - qDebug("QNetworkReplyImpl::_q_startOperation was called more than once"); + qDebug() << "QNetworkReplyHttpImplPrivate::_q_startOperation was called more than once" << url; return; } state = Working; @@ -1823,9 +1815,8 @@ void QNetworkReplyHttpImplPrivate::_q_cacheLoadReadyRead() // If there are still bytes available in the cacheLoadDevice then the user did not read // in response to the readyRead() signal. This means we have to load from the cacheLoadDevice // and buffer that stuff. This is needed to be able to properly emit finished() later. - while (cacheLoadDevice->bytesAvailable() && !isHttpRedirectResponse()) { - downloadMultiBuffer.append(cacheLoadDevice->readAll()); - } + while (cacheLoadDevice->bytesAvailable() && !isHttpRedirectResponse()) + buffer.append(cacheLoadDevice->readAll()); if (cacheLoadDevice->isSequential()) { // check if end and we can read the EOF -1 @@ -2131,15 +2122,18 @@ void QNetworkReplyHttpImplPrivate::_q_metaDataChanged() Q_Q(QNetworkReplyHttpImpl); // 1. do we have cookies? // 2. are we allowed to set them? - if (cookedHeaders.contains(QNetworkRequest::SetCookieHeader) && manager - && (static_cast<QNetworkRequest::LoadControl> - (request.attribute(QNetworkRequest::CookieSaveControlAttribute, - QNetworkRequest::Automatic).toInt()) == QNetworkRequest::Automatic)) { - QList<QNetworkCookie> cookies = - qvariant_cast<QList<QNetworkCookie> >(cookedHeaders.value(QNetworkRequest::SetCookieHeader)); - QNetworkCookieJar *jar = manager->cookieJar(); - if (jar) - jar->setCookiesFromUrl(cookies, url); + if (manager) { + const auto it = cookedHeaders.constFind(QNetworkRequest::SetCookieHeader); + if (it != cookedHeaders.cend() + && request.attribute(QNetworkRequest::CookieSaveControlAttribute, + QNetworkRequest::Automatic).toInt() == QNetworkRequest::Automatic) { + QNetworkCookieJar *jar = manager->cookieJar(); + if (jar) { + QList<QNetworkCookie> cookies = + qvariant_cast<QList<QNetworkCookie> >(it.value()); + jar->setCookiesFromUrl(cookies, url); + } + } } emit q->metaDataChanged(); } @@ -2207,7 +2201,7 @@ void QNetworkReplyHttpImplPrivate::setCachingEnabled(bool enable) return; // nothing to do either! if (enable) { - if (bytesDownloaded) { + if (Q_UNLIKELY(bytesDownloaded)) { qDebug() << "setCachingEnabled: " << bytesDownloaded << " bytesDownloaded"; // refuse to enable in this case qCritical("QNetworkReplyImpl: backend error: caching was enabled after some bytes had been written"); |