From ff25691d00d634068c6389f8f1607d7cc95ac5be Mon Sep 17 00:00:00 2001 From: Martin Petersson Date: Thu, 1 Mar 2012 10:36:38 +0100 Subject: QNam: only init channels when needed. Each channel will create a socket that will allocate memory for the read and write buffers. QNam generaly inits 6 sockets for each connection. That means that by default 12 such buffers are created. This will instead initialize channels when they are needed. Change-Id: Ie3f2cf789e084fd3d17d3b2a9bb3d3a4370b3da4 Reviewed-by: Shane Kearns --- src/network/access/qhttpnetworkconnection.cpp | 106 ++++++++++++--------- .../access/qhttpnetworkconnectionchannel.cpp | 67 ++++++++++++- .../access/qhttpnetworkconnectionchannel_p.h | 11 +++ 3 files changed, 138 insertions(+), 46 deletions(-) (limited to 'src') diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 6aa3a5a5f4..890072eb7e 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -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(channels[i].socket)); - else + if (encrypt) + QSslSocketPrivate::pauseSocketNotifiers(static_cast(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(channels[i].socket)); - else + if (encrypt) + QSslSocketPrivate::resumeSocketNotifiers(static_cast(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 &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,7 +1191,7 @@ 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 @@ -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(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(d->channels[i].socket)->ignoreSslErrors(); - d->channels[i].ignoreAllSslErrors = true; + d->channels[i].ignoreSslErrors(); } } else { - static_cast(d->channels[channel].socket)->ignoreSslErrors(); - d->channels[channel].ignoreAllSslErrors = true; + d->channels[channel].ignoreSslErrors(); } } @@ -1219,13 +1239,11 @@ void QHttpNetworkConnection::ignoreSslErrors(const QList &errors, int if (channel == -1) { // ignore for all channels for (int i = 0; i < d->channelCount; ++i) { - static_cast(d->channels[i].socket)->ignoreSslErrors(errors); - d->channels[i].ignoreSslErrorsList = errors; + d->channels[i].ignoreSslErrors(errors); } } else { - static_cast(d->channels[channel].socket)->ignoreSslErrors(errors); - d->channels[channel].ignoreSslErrorsList = errors; + d->channels[channel].ignoreSslErrors(errors); } } diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 3991bffa47..a009222bd5 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -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(socket)->ignoreSslErrors(); + + ignoreAllSslErrors = true; +} + + +void QHttpNetworkConnectionChannel::ignoreSslErrors(const QList &errors) +{ + if (socket) + static_cast(socket)->ignoreSslErrors(errors); + + ignoreSslErrorsList = errors; +} + +void QHttpNetworkConnectionChannel::setSslConfiguration(const QSslConfiguration &config) +{ + if (socket) + static_cast(socket)->setSslConfiguration(config); + + sslConfiguration = config; +} + +#endif void QHttpNetworkConnectionChannel::pipelineInto(HttpMessagePair &pair) { diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index 7da9b514d6..2648cba2a5 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -72,6 +72,7 @@ #ifndef QT_NO_SSL # include # include +# include #else # include #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 ignoreSslErrorsList; + QSslConfiguration sslConfiguration; + void ignoreSslErrors(); + void ignoreSslErrors(const QList &errors); + void setSslConfiguration(const QSslConfiguration &config); #endif #ifndef QT_NO_BEARERMANAGEMENT QSharedPointer networkSession; @@ -144,6 +150,11 @@ public: void setConnection(QHttpNetworkConnection *c); QPointer connection; +#ifndef QT_NO_NETWORKPROXY + QNetworkProxy proxy; + void setProxy(const QNetworkProxy &networkProxy); +#endif + void init(); void close(); -- cgit v1.2.3