QNam: only init channels when needed.
authorMartin Petersson <Martin.Petersson@nokia.com>
Thu, 1 Mar 2012 09:36:38 +0000 (10:36 +0100)
committerQt by Nokia <qt-info@nokia.com>
Tue, 13 Mar 2012 09:11:22 +0000 (10:11 +0100)
Each channel will create a socket that will allocate memory for the
read and write buffers. This change will instead initialize
channels only when they are needed.

Change-Id: I112b4c7b944a7dd345414f06260c92803394eaed
Reviewed-by: Shane Kearns <shane.kearns@accenture.com>
src/network/access/qhttpnetworkconnection.cpp
src/network/access/qhttpnetworkconnectionchannel.cpp
src/network/access/qhttpnetworkconnectionchannel_p.h

index 6aa3a5a..95b81c4 100644 (file)
@@ -123,8 +123,8 @@ void QHttpNetworkConnectionPrivate::init()
         //push session down to channels
         channels[i].networkSession = networkSession;
 #endif
-        channels[i].init();
     }
+
     delayedConnectionTimer.setSingleShot(true);
     QObject::connect(&delayedConnectionTimer, SIGNAL(timeout()), q, SLOT(_q_connectDelayedChannel()));
 }
@@ -135,12 +135,14 @@ void QHttpNetworkConnectionPrivate::pauseConnection()
 
     // Disable all socket notifiers
     for (int i = 0; i < channelCount; i++) {
+        if (channels[i].socket) {
 #ifndef QT_NO_SSL
-        if (encrypt)
-            QSslSocketPrivate::pauseSocketNotifiers(static_cast<QSslSocket*>(channels[i].socket));
-        else
+            if (encrypt)
+                QSslSocketPrivate::pauseSocketNotifiers(static_cast<QSslSocket*>(channels[i].socket));
+            else
 #endif
-            QAbstractSocketPrivate::pauseSocketNotifiers(channels[i].socket);
+                QAbstractSocketPrivate::pauseSocketNotifiers(channels[i].socket);
+        }
     }
 }
 
@@ -149,16 +151,18 @@ void QHttpNetworkConnectionPrivate::resumeConnection()
     state = RunningState;
     // Enable all socket notifiers
     for (int i = 0; i < channelCount; i++) {
+        if (channels[i].socket) {
 #ifndef QT_NO_SSL
-        if (encrypt)
-            QSslSocketPrivate::resumeSocketNotifiers(static_cast<QSslSocket*>(channels[i].socket));
-        else
+            if (encrypt)
+                QSslSocketPrivate::resumeSocketNotifiers(static_cast<QSslSocket*>(channels[i].socket));
+            else
 #endif
-            QAbstractSocketPrivate::resumeSocketNotifiers(channels[i].socket);
+                QAbstractSocketPrivate::resumeSocketNotifiers(channels[i].socket);
 
-        // Resume pending upload if needed
-        if (channels[i].state == QHttpNetworkConnectionChannel::WritingState)
-            QMetaObject::invokeMethod(&channels[i], "_q_uploadDataReadyRead", Qt::QueuedConnection);
+            // Resume pending upload if needed
+            if (channels[i].state == QHttpNetworkConnectionChannel::WritingState)
+                QMetaObject::invokeMethod(&channels[i], "_q_uploadDataReadyRead", Qt::QueuedConnection);
+        }
     }
 
     // queue _q_startNextRequest
@@ -346,11 +350,15 @@ void QHttpNetworkConnectionPrivate::emitReplyError(QAbstractSocket *socket,
                                                    QNetworkReply::NetworkError errorCode)
 {
     Q_Q(QHttpNetworkConnection);
-    if (socket && reply) {
+
+    int i = 0;
+    if (socket)
+        i = indexOf(socket);
+
+    if (reply) {
         // this error matters only to this reply
         reply->d_func()->errorString = errorDetail(errorCode, socket);
         emit reply->finishedWithError(errorCode, reply->d_func()->errorString);
-        int i = indexOf(socket);
         // remove the corrupt data if any
         reply->d_func()->eraseData();
 
@@ -358,7 +366,8 @@ void QHttpNetworkConnectionPrivate::emitReplyError(QAbstractSocket *socket,
         channels[i].close();
         channels[i].reply = 0;
         channels[i].request = QHttpNetworkRequest();
-        channels[i].requeueCurrentlyPipelinedRequests();
+        if (socket)
+            channels[i].requeueCurrentlyPipelinedRequests();
 
         // send the next request
         QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection);
@@ -582,9 +591,9 @@ void QHttpNetworkConnectionPrivate::requeueRequest(const HttpMessagePair &pair)
 
 bool QHttpNetworkConnectionPrivate::dequeueRequest(QAbstractSocket *socket)
 {
-    Q_ASSERT(socket);
-
-    int i = indexOf(socket);
+    int i = 0;
+    if (socket)
+        i = indexOf(socket);
 
     if (!highPriorityQueue.isEmpty()) {
         // remove from queue before sendRequest! else we might pipeline the same request again
@@ -740,15 +749,15 @@ bool QHttpNetworkConnectionPrivate::fillPipeline(QList<HttpMessagePair> &queue,
 }
 
 
-QString QHttpNetworkConnectionPrivate::errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket* socket,
-                                                   const QString &extraDetail)
+QString QHttpNetworkConnectionPrivate::errorDetail(QNetworkReply::NetworkError errorCode, QAbstractSocket *socket, const QString &extraDetail)
 {
-    Q_ASSERT(socket);
-
     QString errorString;
     switch (errorCode) {
     case QNetworkReply::HostNotFoundError:
-        errorString = QCoreApplication::translate("QHttp", "Host %1 not found").arg(socket->peerName());
+        if (socket)
+            errorString = QCoreApplication::translate("QHttp", "Host %1 not found").arg(socket->peerName());
+        else
+            errorString = QCoreApplication::translate("QHttp", "Host %1 not found").arg(hostName);
         break;
     case QNetworkReply::ConnectionRefusedError:
         errorString = QCoreApplication::translate("QHttp", "Connection refused");
@@ -891,9 +900,11 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
         return;
     // try to get a free AND connected socket
     for (int i = 0; i < channelCount; ++i) {
-        if (!channels[i].reply && !channels[i].isSocketBusy() && channels[i].socket->state() == QAbstractSocket::ConnectedState) {
-            if (dequeueRequest(channels[i].socket))
-                channels[i].sendRequest();
+        if (channels[i].socket) {
+            if (!channels[i].reply && !channels[i].isSocketBusy() && channels[i].socket->state() == QAbstractSocket::ConnectedState) {
+                if (dequeueRequest(channels[i].socket))
+                    channels[i].sendRequest();
+            }
         }
     }
 
@@ -908,7 +919,7 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
     if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty())
         return;
     for (int i = 0; i < channelCount; i++)
-        if (channels[i].socket->state() == QAbstractSocket::ConnectedState)
+        if (channels[i].socket && channels[i].socket->state() == QAbstractSocket::ConnectedState)
             fillPipeline(channels[i].socket);
 
     // If there is not already any connected channels we need to connect a new one.
@@ -916,11 +927,19 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
     // connected or not. This is to reuse connected channels before we connect new once.
     int queuedRequest = highPriorityQueue.count() + lowPriorityQueue.count();
     for (int i = 0; i < channelCount; ++i) {
-        if ((channels[i].socket->state() == QAbstractSocket::ConnectingState) || (channels[i].socket->state() == QAbstractSocket::HostLookupState))
-            queuedRequest--;
-        if ( queuedRequest <=0 )
-            break;
-        if (!channels[i].reply && !channels[i].isSocketBusy() && (channels[i].socket->state() == QAbstractSocket::UnconnectedState)) {
+        bool connectChannel = false;
+        if (channels[i].socket) {
+            if ((channels[i].socket->state() == QAbstractSocket::ConnectingState) || (channels[i].socket->state() == QAbstractSocket::HostLookupState))
+                queuedRequest--;
+            if ( queuedRequest <=0 )
+                break;
+            if (!channels[i].reply && !channels[i].isSocketBusy() && (channels[i].socket->state() == QAbstractSocket::UnconnectedState))
+                connectChannel = true;
+        } else { // not previously used channel
+            connectChannel = true;
+        }
+
+        if (connectChannel) {
             if (networkLayerState == IPv4)
                 channels[i].networkLayerPreference = QAbstractSocket::IPv4Protocol;
             else if (networkLayerState == IPv6)
@@ -928,6 +947,9 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
             channels[i].ensureConnection();
             queuedRequest--;
         }
+
+        if ( queuedRequest <=0 )
+            break;
     }
 }
 
@@ -958,8 +980,8 @@ void QHttpNetworkConnectionPrivate::startHostInfoLookup()
 #ifndef QT_NO_NETWORKPROXY
     if (networkProxy.capabilities() & QNetworkProxy::HostNameLookupCapability) {
         lookupHost = networkProxy.hostName();
-    } else if (channels[0].socket->proxy().capabilities() & QNetworkProxy::HostNameLookupCapability) {
-        lookupHost = channels[0].socket->proxy().hostName();
+    } else if (channels[0].proxy.capabilities() & QNetworkProxy::HostNameLookupCapability) {
+        lookupHost = channels[0].proxy.hostName();
     }
 #endif
     QHostAddress temp;
@@ -1169,13 +1191,13 @@ void QHttpNetworkConnection::setTransparentProxy(const QNetworkProxy &networkPro
 {
     Q_D(QHttpNetworkConnection);
     for (int i = 0; i < d->channelCount; ++i)
-        d->channels[i].socket->setProxy(networkProxy);
+        d->channels[i].setProxy(networkProxy);
 }
 
 QNetworkProxy QHttpNetworkConnection::transparentProxy() const
 {
     Q_D(const QHttpNetworkConnection);
-    return d->channels[0].socket->proxy();
+    return d->channels[0].proxy;
 }
 #endif
 
@@ -1190,7 +1212,7 @@ void QHttpNetworkConnection::setSslConfiguration(const QSslConfiguration &config
 
     // set the config on all channels
     for (int i = 0; i < d->channelCount; ++i)
-        static_cast<QSslSocket *>(d->channels[i].socket)->setSslConfiguration(config);
+        d->channels[i].setSslConfiguration(config);
 }
 
 void QHttpNetworkConnection::ignoreSslErrors(int channel)
@@ -1201,13 +1223,11 @@ void QHttpNetworkConnection::ignoreSslErrors(int channel)
 
     if (channel == -1) { // ignore for all channels
         for (int i = 0; i < d->channelCount; ++i) {
-            static_cast<QSslSocket *>(d->channels[i].socket)->ignoreSslErrors();
-            d->channels[i].ignoreAllSslErrors = true;
+            d->channels[i].ignoreSslErrors();
         }
 
     } else {
-        static_cast<QSslSocket *>(d->channels[channel].socket)->ignoreSslErrors();
-        d->channels[channel].ignoreAllSslErrors = true;
+        d->channels[channel].ignoreSslErrors();
     }
 }
 
@@ -1219,13 +1239,11 @@ void QHttpNetworkConnection::ignoreSslErrors(const QList<QSslError> &errors, int
 
     if (channel == -1) { // ignore for all channels
         for (int i = 0; i < d->channelCount; ++i) {
-            static_cast<QSslSocket *>(d->channels[i].socket)->ignoreSslErrors(errors);
-            d->channels[i].ignoreSslErrorsList = errors;
+            d->channels[i].ignoreSslErrors(errors);
         }
 
     } else {
-        static_cast<QSslSocket *>(d->channels[channel].socket)->ignoreSslErrors(errors);
-        d->channels[channel].ignoreSslErrorsList = errors;
+        d->channels[channel].ignoreSslErrors(errors);
     }
 }
 
index 3991bff..a009222 100644 (file)
@@ -65,6 +65,7 @@ QT_BEGIN_NAMESPACE
 QHttpNetworkConnectionChannel::QHttpNetworkConnectionChannel()
     : socket(0)
     , ssl(false)
+    , isInitialized(false)
     , state(IdleState)
     , reply(0)
     , written(0)
@@ -152,19 +153,38 @@ void QHttpNetworkConnectionChannel::init()
         QObject::connect(sslSocket, SIGNAL(encryptedBytesWritten(qint64)),
                          this, SLOT(_q_encryptedBytesWritten(qint64)),
                          Qt::DirectConnection);
+
+        if (ignoreAllSslErrors)
+            sslSocket->ignoreSslErrors();
+
+        if (!ignoreSslErrorsList.isEmpty())
+            sslSocket->ignoreSslErrors(ignoreSslErrorsList);
+
+        if (!sslConfiguration.isNull())
+           sslSocket->setSslConfiguration(sslConfiguration);
     }
+
 #endif
+
+#ifndef QT_NO_NETWORKPROXY
+    if (proxy.type() != QNetworkProxy::NoProxy)
+        socket->setProxy(proxy);
+#endif
+    isInitialized = true;
 }
 
 
 void QHttpNetworkConnectionChannel::close()
 {
-    if (socket->state() == QAbstractSocket::UnconnectedState)
+    if (!socket)
+        state = QHttpNetworkConnectionChannel::IdleState;
+    else if (socket->state() == QAbstractSocket::UnconnectedState)
         state = QHttpNetworkConnectionChannel::IdleState;
     else
         state = QHttpNetworkConnectionChannel::ClosingState;
 
-    socket->close();
+    if (socket)
+        socket->close();
 }
 
 
@@ -527,6 +547,9 @@ void QHttpNetworkConnectionChannel::handleUnexpectedEOF()
 
 bool QHttpNetworkConnectionChannel::ensureConnection()
 {
+    if (!isInitialized)
+        init();
+
     QAbstractSocket::SocketState socketState = socket->state();
 
     // resend this request after we receive the disconnected signal
@@ -835,6 +858,46 @@ bool QHttpNetworkConnectionChannel::resetUploadData()
     }
 }
 
+#ifndef QT_NO_NETWORKPROXY
+
+void QHttpNetworkConnectionChannel::setProxy(const QNetworkProxy &networkProxy)
+{
+    if (socket)
+        socket->setProxy(networkProxy);
+
+    proxy = networkProxy;
+}
+
+#endif
+
+#ifndef QT_NO_SSL
+
+void QHttpNetworkConnectionChannel::ignoreSslErrors()
+{
+    if (socket)
+        static_cast<QSslSocket *>(socket)->ignoreSslErrors();
+
+    ignoreAllSslErrors = true;
+}
+
+
+void QHttpNetworkConnectionChannel::ignoreSslErrors(const QList<QSslError> &errors)
+{
+    if (socket)
+        static_cast<QSslSocket *>(socket)->ignoreSslErrors(errors);
+
+    ignoreSslErrorsList = errors;
+}
+
+void QHttpNetworkConnectionChannel::setSslConfiguration(const QSslConfiguration &config)
+{
+    if (socket)
+        static_cast<QSslSocket *>(socket)->setSslConfiguration(config);
+
+    sslConfiguration = config;
+}
+
+#endif
 
 void QHttpNetworkConnectionChannel::pipelineInto(HttpMessagePair &pair)
 {
index 7da9b51..2648cba 100644 (file)
@@ -72,6 +72,7 @@
 #ifndef QT_NO_SSL
 #    include <QtNetwork/qsslsocket.h>
 #    include <QtNetwork/qsslerror.h>
+#    include <QtNetwork/qsslconfiguration.h>
 #else
 #   include <QtNetwork/qtcpsocket.h>
 #endif
@@ -100,6 +101,7 @@ public:
     };
     QAbstractSocket *socket;
     bool ssl;
+    bool isInitialized;
     ChannelState state;
     QHttpNetworkRequest request; // current request
     QHttpNetworkReply *reply; // current reply for this request
@@ -118,6 +120,10 @@ public:
 #ifndef QT_NO_SSL
     bool ignoreAllSslErrors;
     QList<QSslError> ignoreSslErrorsList;
+    QSslConfiguration sslConfiguration;
+    void ignoreSslErrors();
+    void ignoreSslErrors(const QList<QSslError> &errors);
+    void setSslConfiguration(const QSslConfiguration &config);
 #endif
 #ifndef QT_NO_BEARERMANAGEMENT
     QSharedPointer<QNetworkSession> networkSession;
@@ -144,6 +150,11 @@ public:
     void setConnection(QHttpNetworkConnection *c);
     QPointer<QHttpNetworkConnection> connection;
 
+#ifndef QT_NO_NETWORKPROXY
+    QNetworkProxy proxy;
+    void setProxy(const QNetworkProxy &networkProxy);
+#endif
+
     void init();
     void close();