summaryrefslogtreecommitdiffstats
path: root/src/network/access
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@nokia.com>2010-02-12 10:49:50 (GMT)
committerThiago Macieira <thiago.macieira@nokia.com>2010-02-12 10:49:50 (GMT)
commit8e309899b8287b67905072927df1e00effc2a13e (patch)
tree6c7bff1a77090c5b39b35a13c88ef876c2535e09 /src/network/access
parentf74029e286e97067ac39086955481bf979af69dc (diff)
parent01245bcabf97dfdfdd23a2ec075b8de3e78bdeb2 (diff)
downloadQt-8e309899b8287b67905072927df1e00effc2a13e.zip
Qt-8e309899b8287b67905072927df1e00effc2a13e.tar.gz
Qt-8e309899b8287b67905072927df1e00effc2a13e.tar.bz2
Merge remote branch 'origin/4.6' into qt-master-from-4.6
Diffstat (limited to 'src/network/access')
-rw-r--r--src/network/access/qhttpnetworkconnectionchannel.cpp27
-rw-r--r--src/network/access/qhttpnetworkreply.cpp68
-rw-r--r--src/network/access/qnetworkcookie.h2
-rw-r--r--src/network/access/qnetworkcookiejar.h2
4 files changed, 65 insertions, 34 deletions
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp
index 70a301d..b0e632a 100644
--- a/src/network/access/qhttpnetworkconnectionchannel.cpp
+++ b/src/network/access/qhttpnetworkconnectionchannel.cpp
@@ -286,7 +286,6 @@ void QHttpNetworkConnectionChannel::_q_receiveReply()
if (!socket->bytesAvailable()) {
if (reply && reply->d_func()->state == QHttpNetworkReplyPrivate::ReadingDataState) {
reply->d_func()->state = QHttpNetworkReplyPrivate::AllDoneState;
- this->state = QHttpNetworkConnectionChannel::IdleState;
allDone();
} else {
// try to reconnect/resend before sending an error.
@@ -305,9 +304,12 @@ void QHttpNetworkConnectionChannel::_q_receiveReply()
while (socket->bytesAvailable()) {
QHttpNetworkReplyPrivate::ReplyState state = reply ? reply->d_func()->state : QHttpNetworkReplyPrivate::AllDoneState;
switch (state) {
- case QHttpNetworkReplyPrivate::NothingDoneState:
- case QHttpNetworkReplyPrivate::ReadingStatusState: {
+ case QHttpNetworkReplyPrivate::NothingDoneState: {
+ // only eat whitespace on the first call
eatWhitespace();
+ state = reply->d_func()->state = QHttpNetworkReplyPrivate::ReadingStatusState;
+ }
+ case QHttpNetworkReplyPrivate::ReadingStatusState: {
qint64 statusBytes = reply->d_func()->readStatus(socket);
if (statusBytes == -1 && reconnectAttempts <= 0) {
// too many errors reading/receiving/parsing the status, close the socket and emit error
@@ -344,7 +346,6 @@ void QHttpNetworkConnectionChannel::_q_receiveReply()
emit reply->headerChanged();
if (!replyPrivate->expectContent()) {
replyPrivate->state = QHttpNetworkReplyPrivate::AllDoneState;
- this->state = QHttpNetworkConnectionChannel::IdleState;
allDone();
return;
}
@@ -421,7 +422,6 @@ void QHttpNetworkConnectionChannel::_q_receiveReply()
// everything done, fall through
}
case QHttpNetworkReplyPrivate::AllDoneState:
- this->state = QHttpNetworkConnectionChannel::IdleState;
allDone();
break;
default:
@@ -567,6 +567,9 @@ void QHttpNetworkConnectionChannel::allDone()
// in case of failures, each channel will attempt two reconnects before emitting error.
reconnectAttempts = 2;
+ // now the channel can be seen as free/idle again, all signal emissions for the reply have been done
+ this->state = QHttpNetworkConnectionChannel::IdleState;
+
detectPipeliningSupport();
// move next from pipeline to current request
@@ -607,19 +610,19 @@ void QHttpNetworkConnectionChannel::allDone()
void QHttpNetworkConnectionChannel::detectPipeliningSupport()
{
// detect HTTP Pipelining support
- QByteArray serverHeaderField = reply->headerField("Server");
+ QByteArray serverHeaderField;
if (
- // check for broken servers in server reply header
- // this is adapted from http://mxr.mozilla.org/firefox/ident?i=SupportsPipelining
- (!serverHeaderField.contains("Microsoft-IIS/4."))
- && (!serverHeaderField.contains("Microsoft-IIS/5."))
- && (!serverHeaderField.contains("Netscape-Enterprise/3."))
// check for HTTP/1.1
- && (reply->d_func()->majorVersion == 1 && reply->d_func()->minorVersion == 1)
+ (reply->d_func()->majorVersion == 1 && reply->d_func()->minorVersion == 1)
// check for not having connection close
&& (!reply->d_func()->isConnectionCloseEnabled())
// check if it is still connected
&& (socket->state() == QAbstractSocket::ConnectedState)
+ // check for broken servers in server reply header
+ // this is adapted from http://mxr.mozilla.org/firefox/ident?i=SupportsPipelining
+ && (serverHeaderField = reply->headerField("Server"), !serverHeaderField.contains("Microsoft-IIS/4."))
+ && (!serverHeaderField.contains("Microsoft-IIS/5."))
+ && (!serverHeaderField.contains("Netscape-Enterprise/3."))
) {
pipeliningSupported = QHttpNetworkConnectionChannel::PipeliningProbablySupported;
} else {
diff --git a/src/network/access/qhttpnetworkreply.cpp b/src/network/access/qhttpnetworkreply.cpp
index a5223d1..512c045 100644
--- a/src/network/access/qhttpnetworkreply.cpp
+++ b/src/network/access/qhttpnetworkreply.cpp
@@ -423,13 +423,26 @@ int QHttpNetworkReplyPrivate::gunzipBodyPartially(QByteArray &compressed, QByteA
qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket)
{
+ if (fragment.isEmpty()) {
+ // reserve bytes for the status line. This is better than always append() which reallocs the byte array
+ fragment.reserve(32);
+ }
+
qint64 bytes = 0;
char c;
+ qint64 haveRead = 0;
+
+ do {
+ haveRead = socket->read(&c, 1);
+ if (haveRead == -1)
+ return -1; // unexpected EOF
+ else if (haveRead == 0)
+ break; // read more later
+
+ bytes++;
- while (socket->bytesAvailable()) {
// allow both CRLF & LF (only) line endings
- if (socket->peek(&c, 1) == 1 && c == '\n') {
- bytes += socket->read(&c, 1); // read the "n"
+ if (c == '\n') {
// remove the CR at the end
if (fragment.endsWith('\r')) {
fragment.truncate(fragment.length()-1);
@@ -442,11 +455,6 @@ qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket)
}
break;
} else {
- c = 0;
- int haveRead = socket->read(&c, 1);
- if (haveRead == -1)
- return -1;
- bytes += haveRead;
fragment.append(c);
}
@@ -456,8 +464,7 @@ qint64 QHttpNetworkReplyPrivate::readStatus(QAbstractSocket *socket)
fragment.clear();
return -1;
}
-
- }
+ } while (haveRead == 1);
return bytes;
}
@@ -500,20 +507,41 @@ bool QHttpNetworkReplyPrivate::parseStatus(const QByteArray &status)
qint64 QHttpNetworkReplyPrivate::readHeader(QAbstractSocket *socket)
{
+ if (fragment.isEmpty()) {
+ // according to http://dev.opera.com/articles/view/mama-http-headers/ the average size of the header
+ // block is 381 bytes.
+ // reserve bytes. This is better than always append() which reallocs the byte array.
+ fragment.reserve(512);
+ }
+
qint64 bytes = 0;
char c = 0;
bool allHeaders = false;
- while (!allHeaders && socket->bytesAvailable()) {
- if (socket->peek(&c, 1) == 1 && c == '\n') {
- // check for possible header endings. As per HTTP rfc,
- // the header endings will be marked by CRLFCRLF. But
- // we will allow CRLFLF, LFLF & CRLFCRLF
- if (fragment.endsWith("\n\r") || fragment.endsWith('\n'))
- allHeaders = true;
+ qint64 haveRead = 0;
+ do {
+ haveRead = socket->read(&c, 1);
+ if (haveRead == 0) {
+ // read more later
+ break;
+ } else if (haveRead == -1) {
+ // connection broke down
+ return -1;
+ } else {
+ fragment.append(c);
+ bytes++;
+
+ if (c == '\n') {
+ // check for possible header endings. As per HTTP rfc,
+ // the header endings will be marked by CRLFCRLF. But
+ // we will allow CRLFCRLF, CRLFLF, LFLF
+ if (fragment.endsWith("\r\n\r\n")
+ || fragment.endsWith("\r\n\n")
+ || fragment.endsWith("\n\n"))
+ allHeaders = true;
+ }
}
- bytes += socket->read(&c, 1);
- fragment.append(c);
- }
+ } while (!allHeaders && haveRead > 0);
+
// we received all headers now parse them
if (allHeaders) {
parseHeader(fragment);
diff --git a/src/network/access/qnetworkcookie.h b/src/network/access/qnetworkcookie.h
index f34396f..3cc4cee 100644
--- a/src/network/access/qnetworkcookie.h
+++ b/src/network/access/qnetworkcookie.h
@@ -114,7 +114,7 @@ Q_NETWORK_EXPORT QDebug operator<<(QDebug, const QNetworkCookie &);
QT_END_NAMESPACE
// ### Qt5 remove this include
-#include "qnetworkcookiejar.h"
+#include <QtNetwork/QNetworkCookieJar>
Q_DECLARE_METATYPE(QNetworkCookie)
Q_DECLARE_METATYPE(QList<QNetworkCookie>)
diff --git a/src/network/access/qnetworkcookiejar.h b/src/network/access/qnetworkcookiejar.h
index 813bf3e..8086f38 100644
--- a/src/network/access/qnetworkcookiejar.h
+++ b/src/network/access/qnetworkcookiejar.h
@@ -46,7 +46,7 @@
#include <QtCore/QUrl>
// ### Qt5 remove this include
-#include "qnetworkcookie.h"
+#include <QtNetwork/QNetworkCookie>
QT_BEGIN_HEADER