diff options
author | Olivier Goffart <olivier.goffart@nokia.com> | 2011-03-15 17:44:28 (GMT) |
---|---|---|
committer | Olivier Goffart <olivier.goffart@nokia.com> | 2011-03-15 17:44:35 (GMT) |
commit | ad0f3996a9674def59766726db34191844d2af0a (patch) | |
tree | d029eeb8b988786a8859f98455e5bc3d9651cb80 /src/network/access | |
parent | c0cd8db0498daaa8151d1f80143b6849016bdc7c (diff) | |
parent | 5e47ee6a97f54f1cdac577f76cd338b40e624f32 (diff) | |
download | Qt-ad0f3996a9674def59766726db34191844d2af0a.zip Qt-ad0f3996a9674def59766726db34191844d2af0a.tar.gz Qt-ad0f3996a9674def59766726db34191844d2af0a.tar.bz2 |
Merge earth-team into master
Diffstat (limited to 'src/network/access')
-rw-r--r-- | src/network/access/qhttpnetworkconnection.cpp | 39 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkconnection_p.h | 2 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkconnectionchannel.cpp | 53 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkconnectionchannel_p.h | 3 |
4 files changed, 66 insertions, 31 deletions
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index 3502113..29ae5b0 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -487,7 +487,7 @@ void QHttpNetworkConnectionPrivate::requeueRequest(const HttpMessagePair &pair) QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); } -void QHttpNetworkConnectionPrivate::dequeueAndSendRequest(QAbstractSocket *socket) +bool QHttpNetworkConnectionPrivate::dequeueRequest(QAbstractSocket *socket) { Q_ASSERT(socket); @@ -500,8 +500,7 @@ void QHttpNetworkConnectionPrivate::dequeueAndSendRequest(QAbstractSocket *socke prepareRequest(messagePair); channels[i].request = messagePair.first; channels[i].reply = messagePair.second; - channels[i].sendRequest(); - return; + return true; } if (!lowPriorityQueue.isEmpty()) { @@ -511,9 +510,9 @@ void QHttpNetworkConnectionPrivate::dequeueAndSendRequest(QAbstractSocket *socke prepareRequest(messagePair); channels[i].request = messagePair.first; channels[i].reply = messagePair.second; - channels[i].sendRequest(); - return; + return true; } + return false; } // this is called from _q_startNextRequest and when a request has been sent down a socket from the channel @@ -765,7 +764,7 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() //resend the necessary ones. for (int i = 0; i < channelCount; ++i) { - if (channels[i].resendCurrent) { + if (channels[i].resendCurrent && (channels[i].state != QHttpNetworkConnectionChannel::ClosingState)) { channels[i].resendCurrent = false; channels[i].state = QHttpNetworkConnectionChannel::IdleState; @@ -784,17 +783,8 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() // 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) { - dequeueAndSendRequest(channels[i].socket); - } - } - - // return fast if there is nothing to do - if (highPriorityQueue.isEmpty() && lowPriorityQueue.isEmpty()) - return; - // try to get a free unconnected socket - for (int i = 0; i < channelCount; ++i) { - if (!channels[i].reply && !channels[i].isSocketBusy()) { - dequeueAndSendRequest(channels[i].socket); + if (dequeueRequest(channels[i].socket)) + channels[i].sendRequest(); } } @@ -811,6 +801,21 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest() for (int i = 0; i < channelCount; i++) if (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. + // We do not pair the channel with the request until we know if it is + // 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) + queuedRequest--; + if ( queuedRequest <=0 ) + break; + if (!channels[i].reply && !channels[i].isSocketBusy() && (channels[i].socket->state() == QAbstractSocket::UnconnectedState)) { + channels[i].ensureConnection(); + queuedRequest--; + } + } } diff --git a/src/network/access/qhttpnetworkconnection_p.h b/src/network/access/qhttpnetworkconnection_p.h index d4748c1..874ea22 100644 --- a/src/network/access/qhttpnetworkconnection_p.h +++ b/src/network/access/qhttpnetworkconnection_p.h @@ -161,7 +161,7 @@ public: QHttpNetworkReply *queueRequest(const QHttpNetworkRequest &request); void requeueRequest(const HttpMessagePair &pair); // e.g. after pipeline broke - void dequeueAndSendRequest(QAbstractSocket *socket); + bool dequeueRequest(QAbstractSocket *socket); void prepareRequest(HttpMessagePair &request); void fillPipeline(QAbstractSocket *socket); diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 41bc64a..23dd518 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -145,10 +145,12 @@ void QHttpNetworkConnectionChannel::init() void QHttpNetworkConnectionChannel::close() { - socket->blockSignals(true); + if (socket->state() == QAbstractSocket::UnconnectedState) + state = QHttpNetworkConnectionChannel::IdleState; + else + state = QHttpNetworkConnectionChannel::ClosingState; + socket->close(); - socket->blockSignals(false); - state = QHttpNetworkConnectionChannel::IdleState; } @@ -500,6 +502,7 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() // called when unexpectedly reading a -1 or when data is expected but socket is closed void QHttpNetworkConnectionChannel::handleUnexpectedEOF() { + Q_ASSERT(reply); if (reconnectAttempts <= 0) { // too many errors reading/receiving/parsing the status, close the socket and emit error requeueCurrentlyPipelinedRequests(); @@ -522,7 +525,8 @@ bool QHttpNetworkConnectionChannel::ensureConnection() // resend this request after we receive the disconnected signal if (socketState == QAbstractSocket::ClosingState) { - resendCurrent = true; + if (reply) + resendCurrent = true; return false; } @@ -644,6 +648,7 @@ bool QHttpNetworkConnectionChannel::expand(bool dataComplete) void QHttpNetworkConnectionChannel::allDone() { + Q_ASSERT(reply); #ifndef QT_NO_COMPRESS // expand the whole data. if (reply->d_func()->expectContent() && reply->d_func()->autoDecompress && !reply->d_func()->streamEnd) { @@ -679,7 +684,8 @@ void QHttpNetworkConnectionChannel::allDone() 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; + if (state != QHttpNetworkConnectionChannel::ClosingState) + state = QHttpNetworkConnectionChannel::IdleState; // if it does not need to be sent again we can set it to 0 // the previous code did not do that and we had problems with accidental re-sending of a @@ -729,7 +735,8 @@ void QHttpNetworkConnectionChannel::allDone() QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } else if (alreadyPipelinedRequests.isEmpty()) { if (connectionCloseEnabled) - close(); + if (socket->state() != QAbstractSocket::UnconnectedState) + close(); if (qobject_cast<QHttpNetworkConnection*>(connection)) QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } @@ -737,6 +744,7 @@ void QHttpNetworkConnectionChannel::allDone() void QHttpNetworkConnectionChannel::detectPipeliningSupport() { + Q_ASSERT(reply); // detect HTTP Pipelining support QByteArray serverHeaderField; if ( @@ -820,6 +828,7 @@ void QHttpNetworkConnectionChannel::handleStatus() bool QHttpNetworkConnectionChannel::resetUploadData() { + Q_ASSERT(reply); QNonContiguousByteDevice* uploadByteDevice = request.uploadByteDevice(); if (!uploadByteDevice) return true; @@ -877,7 +886,8 @@ void QHttpNetworkConnectionChannel::closeAndResendCurrentRequest() { requeueCurrentlyPipelinedRequests(); close(); - resendCurrent = true; + if (reply) + resendCurrent = true; if (qobject_cast<QHttpNetworkConnection*>(connection)) QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } @@ -936,6 +946,12 @@ void QHttpNetworkConnectionChannel::_q_bytesWritten(qint64 bytes) void QHttpNetworkConnectionChannel::_q_disconnected() { + if (state == QHttpNetworkConnectionChannel::ClosingState) { + state = QHttpNetworkConnectionChannel::IdleState; + QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); + return; + } + // read the available data before closing if (isSocketWaiting() || isSocketReading()) { if (reply) { @@ -973,10 +989,10 @@ void QHttpNetworkConnectionChannel::_q_connected() //channels[i].reconnectAttempts = 2; if (!pendingEncrypt) { state = QHttpNetworkConnectionChannel::IdleState; + if (!reply) + connection->d_func()->dequeueRequest(socket); if (reply) sendRequest(); - else - close(); } } @@ -1030,6 +1046,9 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket QPointer<QHttpNetworkConnection> that = connection; QString errorString = connection->d_func()->errorDetail(errorCode, socket, socket->errorString()); + // Need to dequeu the request so that we can emit the error. + if (!reply) + connection->d_func()->dequeueRequest(socket); if (reply) { reply->d_func()->errorString = errorString; emit reply->finishedWithError(errorCode, errorString); @@ -1044,7 +1063,11 @@ void QHttpNetworkConnectionChannel::_q_error(QAbstractSocket::SocketError socket #ifndef QT_NO_NETWORKPROXY void QHttpNetworkConnectionChannel::_q_proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator* auth) { - connection->d_func()->emitProxyAuthenticationRequired(this, proxy, auth); + // Need to dequeue the request before we can emit the error. + if (!reply) + connection->d_func()->dequeueRequest(socket); + if (reply) + connection->d_func()->emitProxyAuthenticationRequired(this, proxy, auth); } #endif @@ -1060,7 +1083,10 @@ void QHttpNetworkConnectionChannel::_q_encrypted() return; // ### error state = QHttpNetworkConnectionChannel::IdleState; pendingEncrypt = false; - sendRequest(); + if (!reply) + connection->d_func()->dequeueRequest(socket); + if (reply) + sendRequest(); } void QHttpNetworkConnectionChannel::_q_sslErrors(const QList<QSslError> &errors) @@ -1071,7 +1097,10 @@ void QHttpNetworkConnectionChannel::_q_sslErrors(const QList<QSslError> &errors) // Also pause the connection because socket notifiers may fire while an user // dialog is displaying connection->d_func()->pauseConnection(); - emit reply->sslErrors(errors); + if (pendingEncrypt && !reply) + connection->d_func()->dequeueRequest(socket); + if (reply) + emit reply->sslErrors(errors); connection->d_func()->resumeConnection(); } diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index 8cbc689..893d75e 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -95,7 +95,8 @@ public: WritingState = 2, // writing the data WaitingState = 4, // waiting for reply ReadingState = 8, // reading the reply - BusyState = (ConnectingState|WritingState|WaitingState|ReadingState) + ClosingState = 16, + BusyState = (ConnectingState|WritingState|WaitingState|ReadingState|ClosingState) }; QAbstractSocket *socket; bool ssl; |