summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMarkus Goetz <Markus.Goetz@nokia.com>2009-06-26 13:40:57 (GMT)
committerMarkus Goetz <Markus.Goetz@nokia.com>2009-06-29 09:13:25 (GMT)
commit9daf22e645106d09b32a60e5cfe65672e6b64f91 (patch)
tree0defdd7e4b795c4f763ea6f3ca154fbd052632a6 /src
parentdae562ea1bcc2e65d14f6a4404b7544295f1a910 (diff)
downloadQt-9daf22e645106d09b32a60e5cfe65672e6b64f91.zip
Qt-9daf22e645106d09b32a60e5cfe65672e6b64f91.tar.gz
Qt-9daf22e645106d09b32a60e5cfe65672e6b64f91.tar.bz2
QNAM HTTP Code: Properly use the QRingBuffer for some kind of data.
Use the QRingBuffer properly when reading known-size, non-chunked, non-compressed data from HTTP. Reviewed-by: Thiago Macieira
Diffstat (limited to 'src')
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp76
-rw-r--r--src/network/access/qhttpnetworkreply.cpp26
-rw-r--r--src/network/access/qhttpnetworkreply_p.h1
3 files changed, 75 insertions, 28 deletions
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index 8409660..56caca9 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -649,36 +649,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) {
- 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;
- }
+ 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;
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index 202bdea..72aec99 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -549,6 +549,30 @@ bool QHttpNetworkReplyPrivate::connectionCloseEnabled()
headerField("proxy-connection").toLower().contains("close"));
}
+// note this function can only be used for non-chunked, non-compressed with
+// known content length
+qint64 QHttpNetworkReplyPrivate::readBodyFast(QAbstractSocket *socket, QRingBuffer *rb)
+{
+ quint64 toBeRead = qMin(socket->bytesAvailable(), bodyLength - contentRead);
+ char* dst = rb->reserve(toBeRead);
+ qint64 haveRead = socket->read(dst, toBeRead);
+ if (haveRead == -1) {
+ rb->chop(toBeRead);
+ return 0; // ### error checking here;
+ }
+
+ rb->chop(toBeRead - haveRead);
+
+ if (contentRead + haveRead == bodyLength) {
+ state = AllDoneState;
+ socket->readAll(); // Read the rest to clean (CRLF) ### will break pipelining
+ }
+
+ contentRead += haveRead;
+ return haveRead;
+}
+
+
qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QIODevice *out)
{
qint64 bytes = 0;
@@ -562,7 +586,7 @@ qint64 QHttpNetworkReplyPrivate::readBody(QAbstractSocket *socket, QIODevice *ou
bytes += readReplyBodyRaw(socket, out, socket->bytesAvailable());
}
if (state == AllDoneState)
- socket->readAll(); // Read the rest to clean (CRLF)
+ socket->readAll(); // Read the rest to clean (CRLF) ### will break pipelining
contentRead += bytes;
return bytes;
}
diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h
index 69c9158..26e1047 100644
--- a/src/network/access/qhttpnetworkreply_p.h
+++ b/src/network/access/qhttpnetworkreply_p.h
@@ -160,6 +160,7 @@ public:
qint64 readHeader(QAbstractSocket *socket);
void parseHeader(const QByteArray &header);
qint64 readBody(QAbstractSocket *socket, QIODevice *out);
+ qint64 readBodyFast(QAbstractSocket *socket, QRingBuffer *rb);
bool findChallenge(bool forProxy, QByteArray &challenge) const;
QAuthenticatorPrivate::Method authenticationMethod(bool isProxy) const;
void clear();