diff options
author | Markus Goetz <Markus.Goetz@nokia.com> | 2011-02-24 10:19:36 (GMT) |
---|---|---|
committer | Markus Goetz <Markus.Goetz@nokia.com> | 2011-02-24 10:58:04 (GMT) |
commit | 473ff22f9d84c407c5a2011defcf07f19527a056 (patch) | |
tree | 57ab3f6553c5d40269bf0acdd3dc4594d40f8c65 | |
parent | f46cf4384f74b6b17674db8abdcdae7d492ff0f7 (diff) | |
download | Qt-473ff22f9d84c407c5a2011defcf07f19527a056.zip Qt-473ff22f9d84c407c5a2011defcf07f19527a056.tar.gz Qt-473ff22f9d84c407c5a2011defcf07f19527a056.tar.bz2 |
QNAM HTTP: Be more strict with HTTP channel state
This fixes a case where finished() and finishedWithError()
were both emitted for a single reply.
Reviewed-by: Peter Hartmann
-rw-r--r-- | src/network/access/qhttpnetworkconnection.cpp | 6 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkconnectionchannel.cpp | 35 |
2 files changed, 30 insertions, 11 deletions
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp index e94b099..3502113 100644 --- a/src/network/access/qhttpnetworkconnection.cpp +++ b/src/network/access/qhttpnetworkconnection.cpp @@ -286,7 +286,13 @@ void QHttpNetworkConnectionPrivate::emitReplyError(QAbstractSocket *socket, int i = indexOf(socket); // remove the corrupt data if any reply->d_func()->eraseData(); + + // Clean the channel channels[i].close(); + channels[i].reply = 0; + channels[i].request = QHttpNetworkRequest(); + channels[i].requeueCurrentlyPipelinedRequests(); + // send the next request QMetaObject::invokeMethod(q, "_q_startNextRequest", Qt::QueuedConnection); } diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index a26ba8a..41bc64a 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -476,7 +476,8 @@ void QHttpNetworkConnectionChannel::_q_receiveReply() } #ifndef QT_NO_COMPRESS else if (!expand(false)) { // expand a chunk if possible - return; // ### expand failed + // If expand() failed we can just return, it had already called connection->emitReplyError() + return; } #endif } @@ -645,28 +646,38 @@ void QHttpNetworkConnectionChannel::allDone() { #ifndef QT_NO_COMPRESS // expand the whole data. - if (reply->d_func()->expectContent() && reply->d_func()->autoDecompress && !reply->d_func()->streamEnd) - expand(true); // ### if expand returns false, its an error + if (reply->d_func()->expectContent() && reply->d_func()->autoDecompress && !reply->d_func()->streamEnd) { + bool expandResult = expand(true); + // If expand() failed we can just return, it had already called connection->emitReplyError() + if (!expandResult) + return; + } #endif + + if (!reply) { + qWarning() << "QHttpNetworkConnectionChannel::allDone() called without reply. Please report at http://bugreports.qt.nokia.com/"; + return; + } + // while handling 401 & 407, we might reset the status code, so save this. bool emitFinished = reply->d_func()->shouldEmitSignals(); - handleStatus(); - // ### at this point there should be no more data on the socket - // close if server requested bool connectionCloseEnabled = reply->d_func()->isConnectionCloseEnabled(); - if (connectionCloseEnabled) - close(); + detectPipeliningSupport(); + + handleStatus(); + // handleStatus() might have removed the reply because it already called connection->emitReplyError() + // queue the finished signal, this is required since we might send new requests from // slot connected to it. The socket will not fire readyRead signal, if we are already // in the slot connected to readyRead - if (emitFinished) + if (reply && emitFinished) QMetaObject::invokeMethod(reply, "finished", Qt::QueuedConnection); + + // reset the reconnection attempts after we receive a complete reply. // in case of failures, each channel will attempt two reconnects before emitting error. reconnectAttempts = 2; - detectPipeliningSupport(); - // now the channel can be seen as free/idle again, all signal emissions for the reply have been done this->state = QHttpNetworkConnectionChannel::IdleState; @@ -717,6 +728,8 @@ void QHttpNetworkConnectionChannel::allDone() // leading whitespace. QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } else if (alreadyPipelinedRequests.isEmpty()) { + if (connectionCloseEnabled) + close(); if (qobject_cast<QHttpNetworkConnection*>(connection)) QMetaObject::invokeMethod(connection, "_q_startNextRequest", Qt::QueuedConnection); } |