summaryrefslogtreecommitdiffstats
path: root/src/network/access/qhttpnetworkconnection.cpp
diff options
context:
space:
mode:
authorJason Barron <jbarron@trolltech.com>2009-06-30 09:21:56 (GMT)
committerJason Barron <jbarron@trolltech.com>2009-06-30 09:21:56 (GMT)
commit197df24edfe095a10e2bf65116796e027fea44e2 (patch)
tree4ffb08f614b550298663f90297c9e559ecb47a3c /src/network/access/qhttpnetworkconnection.cpp
parent1e84894225e31adf80a7a33da7f655fb5c38ea0e (diff)
parente3c1039d4d10aa383a1f681e7dd9c1129d22d8ca (diff)
downloadQt-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.cpp163
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();