src/network/access/qhttpnetworkreply.cpp
branchRCL_3
changeset 8 3f74d0d4af4c
parent 4 3b1da2848fc7
--- 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<QSslSocket*>(d->connectionChannel->socket);
+    if (!sslSocket)
+        return QSslConfiguration();
+
+    return sslSocket->sslConfiguration();
 }
 
 void QHttpNetworkReply::setSslConfiguration(const QSslConfiguration &config)