diff -r dee5afe5301f -r 3f74d0d4af4c src/network/access/qhttpnetworkreply.cpp --- a/src/network/access/qhttpnetworkreply.cpp Mon Mar 15 12:43:09 2010 +0200 +++ b/src/network/access/qhttpnetworkreply.cpp Thu Apr 08 14:19:33 2010 +0300 @@ -219,7 +219,7 @@ { } -void QHttpNetworkReplyPrivate::clear() +void QHttpNetworkReplyPrivate::clearHttpLayerInformation() { state = NothingDoneState; statusCode = 100; @@ -229,15 +229,22 @@ currentChunkSize = 0; currentChunkRead = 0; connectionCloseEnabled = true; - connection = 0; #ifndef QT_NO_COMPRESS if (initInflate) inflateEnd(&inflateStrm); #endif initInflate = false; streamEnd = false; + fields.clear(); +} + +// TODO: Isn't everything HTTP layer related? We don't need to set connection and connectionChannel to 0 at all +void QHttpNetworkReplyPrivate::clear() +{ + connection = 0; + connectionChannel = 0; autoDecompress = false; - fields.clear(); + clearHttpLayerInformation(); } // QHttpNetworkReplyPrivate @@ -423,13 +430,26 @@ 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; - while (socket->bytesAvailable()) { + do { + haveRead = socket->read(&c, 1); + if (haveRead == -1) + return -1; // unexpected EOF + else if (haveRead == 0) + break; // read more later + + bytes++; + // 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 +462,6 @@ } break; } else { - c = 0; - int haveRead = socket->read(&c, 1); - if (haveRead == -1) - return -1; - bytes += haveRead; fragment.append(c); } @@ -456,8 +471,7 @@ fragment.clear(); return -1; } - - } + } while (haveRead == 1); return bytes; } @@ -500,20 +514,46 @@ 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; + + // there is another case: We have no headers. Then the fragment equals just the line ending + if ((fragment.length() == 2 && fragment.endsWith("\r\n")) + || (fragment.length() == 1 && fragment.endsWith("\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); @@ -775,9 +815,15 @@ QSslConfiguration QHttpNetworkReply::sslConfiguration() const { Q_D(const QHttpNetworkReply); - if (d->connection) - return d->connection->d_func()->sslConfiguration(*this); - return QSslConfiguration(); + + if (!d->connectionChannel) + return QSslConfiguration(); + + QSslSocket *sslSocket = qobject_cast(d->connectionChannel->socket); + if (!sslSocket) + return QSslConfiguration(); + + return sslSocket->sslConfiguration(); } void QHttpNetworkReply::setSslConfiguration(const QSslConfiguration &config)