diff options
author | Jason Barron <jbarron@trolltech.com> | 2009-06-30 09:21:56 (GMT) |
---|---|---|
committer | Jason Barron <jbarron@trolltech.com> | 2009-06-30 09:21:56 (GMT) |
commit | 197df24edfe095a10e2bf65116796e027fea44e2 (patch) | |
tree | 4ffb08f614b550298663f90297c9e559ecb47a3c /src/network/access/qhttpnetworkconnection.cpp | |
parent | 1e84894225e31adf80a7a33da7f655fb5c38ea0e (diff) | |
parent | e3c1039d4d10aa383a1f681e7dd9c1129d22d8ca (diff) | |
download | Qt-197df24edfe095a10e2bf65116796e027fea44e2.zip Qt-197df24edfe095a10e2bf65116796e027fea44e2.tar.gz Qt-197df24edfe095a10e2bf65116796e027fea44e2.tar.bz2 |
Merge commit 'qt/master-stable' into 4.6-merged
Conflicts:
.gitignore
configure.exe
src/corelib/concurrent/qtconcurrentthreadengine.h
src/corelib/global/qnamespace.h
src/gui/graphicsview/qgraphicssceneevent.h
src/gui/kernel/qapplication.cpp
src/gui/kernel/qapplication.h
src/gui/kernel/qapplication_p.h
src/gui/kernel/qapplication_qws.cpp
src/gui/kernel/qwidget.h
src/gui/painting/qpaintengine_raster.cpp
src/gui/text/qfontdatabase.cpp
src/network/access/qnetworkaccesshttpbackend.cpp
tests/auto/network-settings.h
tests/auto/qscriptjstestsuite/qscriptjstestsuite.pro
tests/auto/qvariant/tst_qvariant.cpp
Diffstat (limited to 'src/network/access/qhttpnetworkconnection.cpp')
-rw-r--r-- | src/network/access/qhttpnetworkconnection.cpp | 163 |
1 files changed, 111 insertions, 52 deletions
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 359cab9..1085640 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** Contact: Qt Software Information (qt-info@nokia.com) +** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the QtNetwork module of the Qt Toolkit. ** @@ -34,7 +34,7 @@ ** met: http://www.gnu.org/copyleft/gpl.html. ** ** If you are unsure which license is appropriate for your use, please -** contact the sales department at qt-sales@nokia.com. +** contact the sales department at http://www.qtsoftware.com/contact. ** $QT_END_LICENSE$ ** ****************************************************************************/ @@ -115,12 +115,15 @@ void QHttpNetworkConnectionPrivate::connectSignals(QAbstractSocket *socket) #ifndef QT_NO_OPENSSL QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket); - QObject::connect(sslSocket, SIGNAL(encrypted()), - q, SLOT(_q_encrypted()), - Qt::DirectConnection); - QObject::connect(sslSocket, SIGNAL(sslErrors(const QList<QSslError>&)), - q, SLOT(_q_sslErrors(const QList<QSslError>&)), - Qt::DirectConnection); + if (sslSocket) { + // won't be a sslSocket if encrypt is false + QObject::connect(sslSocket, SIGNAL(encrypted()), + q, SLOT(_q_encrypted()), + Qt::DirectConnection); + QObject::connect(sslSocket, SIGNAL(sslErrors(const QList<QSslError>&)), + q, SLOT(_q_sslErrors(const QList<QSslError>&)), + Qt::DirectConnection); + } #endif } @@ -128,10 +131,14 @@ void QHttpNetworkConnectionPrivate::init() { for (int i = 0; i < channelCount; ++i) { #ifndef QT_NO_OPENSSL - channels[i].socket = new QSslSocket; + if (encrypt) + channels[i].socket = new QSslSocket; + else + channels[i].socket = new QTcpSocket; #else channels[i].socket = new QTcpSocket; #endif + connectSignals(channels[i].socket); } } @@ -169,30 +176,43 @@ bool QHttpNetworkConnectionPrivate::isSocketReading(QAbstractSocket *socket) con } -void QHttpNetworkConnectionPrivate::appendData(QHttpNetworkReply &reply, const QByteArray &fragment, bool compressed) +void QHttpNetworkConnectionPrivate::appendUncompressedData(QHttpNetworkReply &reply, const QByteArray &fragment) +{ + char *dst = reply.d_func()->responseData.reserve(fragment.size()); + qMemCopy(dst, fragment.constData(), fragment.size()); +} + +void QHttpNetworkConnectionPrivate::appendCompressedData(QHttpNetworkReply &reply, const QByteArray &fragment) +{ + reply.d_func()->compressedData.append(fragment); +} + +qint64 QHttpNetworkConnectionPrivate::uncompressedBytesAvailable(const QHttpNetworkReply &reply) const { - QByteArray *ba = (compressed) ? &reply.d_func()->compressedData : &reply.d_func()->responseData; - ba->append(fragment); - return; + return reply.d_func()->responseData.size(); } -qint64 QHttpNetworkConnectionPrivate::bytesAvailable(const QHttpNetworkReply &reply, bool compressed) const +qint64 QHttpNetworkConnectionPrivate::uncompressedBytesAvailableNextBlock(const QHttpNetworkReply &reply) const { - const QByteArray *ba = (compressed) ? &reply.d_func()->compressedData : &reply.d_func()->responseData; - return ba->size(); + return reply.d_func()->responseData.nextDataBlockSize(); } -qint64 QHttpNetworkConnectionPrivate::read(QHttpNetworkReply &reply, QByteArray &data, qint64 maxSize, bool compressed) +qint64 QHttpNetworkConnectionPrivate::compressedBytesAvailable(const QHttpNetworkReply &reply) const { - QByteArray *ba = (compressed) ? &reply.d_func()->compressedData : &reply.d_func()->responseData; - if (maxSize == -1 || maxSize >= ba->size()) { + return reply.d_func()->compressedData.size(); +} + +qint64 QHttpNetworkConnectionPrivate::read(QHttpNetworkReply &reply, QByteArray &data, qint64 maxSize) +{ + QRingBuffer *rb = &reply.d_func()->responseData; + if (maxSize == -1 || maxSize >= rb->size()) { // read the whole data - data = *ba; - ba->clear(); + data = rb->readAll(); + rb->clear(); } else { // read only the requested length - data = ba->mid(0, maxSize); - ba->remove(0, maxSize); + data.resize(maxSize); + rb->read(data.data(), maxSize); } return data.size(); } @@ -406,8 +426,9 @@ bool QHttpNetworkConnectionPrivate::sendRequest(QAbstractSocket *socket) #ifndef QT_NO_OPENSSL QSslSocket *sslSocket = qobject_cast<QSslSocket*>(socket); - while ((sslSocket->encryptedBytesToWrite() + sslSocket->bytesToWrite()) <= socketBufferFill - && channels[i].bytesTotal != channels[i].written) + // if it is really an ssl socket, check more than just bytesToWrite() + while ((socket->bytesToWrite() + (sslSocket ? sslSocket->encryptedBytesToWrite() : 0)) + <= socketBufferFill && channels[i].bytesTotal != channels[i].written) #else while (socket->bytesToWrite() <= socketBufferFill && channels[i].bytesTotal != channels[i].written) @@ -518,12 +539,14 @@ bool QHttpNetworkConnectionPrivate::expand(QAbstractSocket *socket, QHttpNetwork Q_ASSERT(socket); Q_ASSERT(reply); - qint64 total = bytesAvailable(*reply, true); + qint64 total = compressedBytesAvailable(*reply); if (total >= CHUNK || dataComplete) { int i = indexOf(socket); // uncompress the data QByteArray content, inflated; - read(*reply, content, -1, true); + content = reply->d_func()->compressedData; + reply->d_func()->compressedData.clear(); + int ret = Z_OK; if (content.size()) ret = reply->d_func()->gunzipBodyPartially(content, inflated); @@ -531,7 +554,7 @@ bool QHttpNetworkConnectionPrivate::expand(QAbstractSocket *socket, QHttpNetwork if (ret >= retCheck) { if (inflated.size()) { reply->d_func()->totalProgress += inflated.size(); - appendData(*reply, inflated, false); + appendUncompressedData(*reply, inflated); if (shouldEmitSignals(reply)) { emit reply->readyRead(); // make sure that the reply is valid @@ -628,32 +651,58 @@ void QHttpNetworkConnectionPrivate::receiveReply(QAbstractSocket *socket, QHttpN } break; case QHttpNetworkReplyPrivate::ReadingDataState: { - QBuffer fragment; - fragment.open(QIODevice::WriteOnly); - bytes = reply->d_func()->readBody(socket, &fragment); - if (bytes) { - appendData(*reply, fragment.data(), reply->d_func()->autoDecompress); - if (!reply->d_func()->autoDecompress) { - reply->d_func()->totalProgress += fragment.size(); - if (shouldEmitSignals(reply)) { - emit reply->readyRead(); - // make sure that the reply is valid - if (channels[i].reply != reply) - return; - // emit dataReadProgress signal (signal is currently not connected - // to the rest of QNAM) since readProgress of the - // QNonContiguousByteDevice is used - emit reply->dataReadProgress(reply->d_func()->totalProgress, reply->d_func()->bodyLength); - // make sure that the reply is valid - if (channels[i].reply != reply) - return; - } + if (!reply->d_func()->isChunked() && !reply->d_func()->autoDecompress + && reply->d_func()->bodyLength > 0) { + // bulk files like images should fulfill these properties and + // we can therefore save on memory copying + bytes = reply->d_func()->readBodyFast(socket, &reply->d_func()->responseData); + reply->d_func()->totalProgress += bytes; + if (shouldEmitSignals(reply)) { + emit reply->readyRead(); + // make sure that the reply is valid + if (channels[i].reply != reply) + return; + emit reply->dataReadProgress(reply->d_func()->totalProgress, reply->d_func()->bodyLength); + // make sure that the reply is valid + if (channels[i].reply != reply) + return; } + } + else + { + // use the traditional slower reading (for compressed encoding, chunked encoding, + // no content-length etc) + QBuffer fragment; + fragment.open(QIODevice::WriteOnly); + bytes = reply->d_func()->readBody(socket, &fragment); + if (bytes) { + if (reply->d_func()->autoDecompress) + appendCompressedData(*reply, fragment.data()); + else + appendUncompressedData(*reply, fragment.data()); + + if (!reply->d_func()->autoDecompress) { + reply->d_func()->totalProgress += fragment.size(); + if (shouldEmitSignals(reply)) { + emit reply->readyRead(); + // make sure that the reply is valid + if (channels[i].reply != reply) + return; + // emit dataReadProgress signal (signal is currently not connected + // to the rest of QNAM) since readProgress of the + // QNonContiguousByteDevice is used + emit reply->dataReadProgress(reply->d_func()->totalProgress, reply->d_func()->bodyLength); + // make sure that the reply is valid + if (channels[i].reply != reply) + return; + } + } #ifndef QT_NO_COMPRESS - else if (!expand(socket, reply, false)) { // expand a chunk if possible - return; // ### expand failed - } + else if (!expand(socket, reply, false)) { // expand a chunk if possible + return; // ### expand failed + } #endif + } } if (reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) break; @@ -1014,7 +1063,8 @@ void QHttpNetworkConnectionPrivate::removeReply(QHttpNetworkReply *reply) for (int i = 0; i < channelCount; ++i) { if (channels[i].reply == reply) { channels[i].reply = 0; - closeChannel(i); + if (reply->d_func()->connectionCloseEnabled()) + closeChannel(i); QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); return; } @@ -1357,6 +1407,9 @@ void QHttpNetworkConnectionPrivate::_q_sslErrors(const QList<QSslError> &errors) QSslConfiguration QHttpNetworkConnectionPrivate::sslConfiguration(const QHttpNetworkReply &reply) const { + if (!encrypt) + return QSslConfiguration(); + for (int i = 0; i < channelCount; ++i) if (channels[i].reply == &reply) return static_cast<QSslSocket *>(channels[0].socket)->sslConfiguration(); @@ -1366,6 +1419,9 @@ QSslConfiguration QHttpNetworkConnectionPrivate::sslConfiguration(const QHttpNet void QHttpNetworkConnection::setSslConfiguration(const QSslConfiguration &config) { Q_D(QHttpNetworkConnection); + if (!d->encrypt) + return; + // set the config on all channels for (int i = 0; i < d->channelCount; ++i) static_cast<QSslSocket *>(d->channels[i].socket)->setSslConfiguration(config); @@ -1374,6 +1430,9 @@ void QHttpNetworkConnection::setSslConfiguration(const QSslConfiguration &config void QHttpNetworkConnection::ignoreSslErrors(int channel) { Q_D(QHttpNetworkConnection); + if (!d->encrypt) + return; + if (channel == -1) { // ignore for all channels for (int i = 0; i < d->channelCount; ++i) { static_cast<QSslSocket *>(d->channels[i].socket)->ignoreSslErrors(); |