summaryrefslogtreecommitdiffstats
path: root/src/network/access/qhttpnetworkconnection.cpp
diff options
context:
space:
mode:
authorMarkus Goetz <Markus.Goetz@nokia.com>2010-10-19 14:16:38 (GMT)
committerMarkus Goetz <Markus.Goetz@nokia.com>2010-10-27 12:40:27 (GMT)
commit07fd031d29198cc5a0d6f1da6bb8fea29274fa06 (patch)
tree58f2354fa24407590b5eea2dd4e02c9ae8c1bb95 /src/network/access/qhttpnetworkconnection.cpp
parentf706263856085df62507414ff0bcbadeca6dcfe5 (diff)
downloadQt-07fd031d29198cc5a0d6f1da6bb8fea29274fa06.zip
Qt-07fd031d29198cc5a0d6f1da6bb8fea29274fa06.tar.gz
Qt-07fd031d29198cc5a0d6f1da6bb8fea29274fa06.tar.bz2
QNAM HTTP: Pause sockets while emitting to user code.
This is needed because user code might display a dialog which spins an event loop and could make the sockets readyRead() fire. This event loop recursion is not desired as it can lead to nasty bugs when the state is messed up. Reviewed-by: Peter Hartmann Reviewed-by: Prasanth Task-Number: QTBUG-13234
Diffstat (limited to 'src/network/access/qhttpnetworkconnection.cpp')
-rw-r--r--src/network/access/qhttpnetworkconnection.cpp82
1 files changed, 46 insertions, 36 deletions
diff --git a/src/network/access/qhttpnetworkconnection.cpp b/src/network/access/qhttpnetworkconnection.cpp
index 32881b2..f8f7620 100644
--- a/src/network/access/qhttpnetworkconnection.cpp
+++ b/src/network/access/qhttpnetworkconnection.cpp
@@ -45,6 +45,7 @@
#include <private/qnetworkrequest_p.h>
#include <private/qobject_p.h>
#include <private/qauthenticator_p.h>
+#include <private/qabstractsocket_p.h>
#include <qnetworkproxy.h>
#include <qauthenticator.h>
@@ -56,6 +57,7 @@
#ifndef QT_NO_HTTP
#ifndef QT_NO_OPENSSL
+# include <private/qsslsocket_p.h>
# include <QtNetwork/qsslkey.h>
# include <QtNetwork/qsslcipher.h>
# include <QtNetwork/qsslconfiguration.h>
@@ -79,9 +81,9 @@ const int QHttpNetworkConnectionPrivate::defaultRePipelineLength = 2;
QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &hostName, quint16 port, bool encrypt)
-: hostName(hostName), port(port), encrypt(encrypt),
- channelCount(defaultChannelCount),
- pendingAuthSignal(false), pendingProxyAuthSignal(false)
+: state(RunningState),
+ hostName(hostName), port(port), encrypt(encrypt),
+ channelCount(defaultChannelCount)
#ifndef QT_NO_NETWORKPROXY
, networkProxy(QNetworkProxy::NoProxy)
#endif
@@ -90,9 +92,9 @@ QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(const QString &host
}
QHttpNetworkConnectionPrivate::QHttpNetworkConnectionPrivate(quint16 channelCount, const QString &hostName, quint16 port, bool encrypt)
-: hostName(hostName), port(port), encrypt(encrypt),
- channelCount(channelCount),
- pendingAuthSignal(false), pendingProxyAuthSignal(false)
+: state(RunningState),
+ hostName(hostName), port(port), encrypt(encrypt),
+ channelCount(channelCount)
#ifndef QT_NO_NETWORKPROXY
, networkProxy(QNetworkProxy::NoProxy)
#endif
@@ -121,6 +123,37 @@ void QHttpNetworkConnectionPrivate::init()
}
}
+void QHttpNetworkConnectionPrivate::pauseConnection()
+{
+ state = PausedState;
+
+ // Disable all socket notifiers
+ for (int i = 0; i < channelCount; i++) {
+ if (encrypt)
+ QSslSocketPrivate::pauseSocketNotifiers(static_cast<QSslSocket*>(channels[i].socket));
+ else
+ QAbstractSocketPrivate::pauseSocketNotifiers(channels[i].socket);
+ }
+}
+
+void QHttpNetworkConnectionPrivate::resumeConnection()
+{
+ state = RunningState;
+ // Enable all socket notifiers
+ for (int i = 0; i < channelCount; i++) {
+ if (encrypt)
+ QSslSocketPrivate::resumeSocketNotifiers(static_cast<QSslSocket*>(channels[i].socket));
+ else
+ QAbstractSocketPrivate::resumeSocketNotifiers(channels[i].socket);
+ }
+
+ // Resume uploads
+ // FIXME
+
+ // queue _q_startNextRequest
+ QMetaObject::invokeMethod(this->q_func(), "_q_startNextRequest", Qt::QueuedConnection);
+}
+
int QHttpNetworkConnectionPrivate::indexOf(QAbstractSocket *socket) const
{
for (int i = 0; i < channelCount; ++i)
@@ -315,35 +348,19 @@ bool QHttpNetworkConnectionPrivate::handleAuthenticateChallenge(QAbstractSocket
priv->parseHttpResponse(fields, isProxy);
if (priv->phase == QAuthenticatorPrivate::Done) {
- if ((isProxy && pendingProxyAuthSignal) ||(!isProxy && pendingAuthSignal)) {
- // drop the request
- reply->d_func()->eraseData();
- channels[i].close();
- channels[i].lastStatus = 0;
- channels[i].state = QHttpNetworkConnectionChannel::Wait4AuthState;
- return false;
- }
- // cannot use this socket until the slot returns
- channels[i].state = QHttpNetworkConnectionChannel::WaitingState;
- socket->blockSignals(true);
+ pauseConnection();
if (!isProxy) {
- pendingAuthSignal = true;
emit q->authenticationRequired(reply->request(), auth, q);
- pendingAuthSignal = false;
#ifndef QT_NO_NETWORKPROXY
} else {
- pendingProxyAuthSignal = true;
emit q->proxyAuthenticationRequired(networkProxy, auth, q);
- pendingProxyAuthSignal = false;
#endif
}
- socket->blockSignals(false);
- // socket free to use
- channels[i].state = QHttpNetworkConnectionChannel::IdleState;
+ resumeConnection();
+
if (priv->phase != QAuthenticatorPrivate::Done) {
// send any pending requests
copyCredentials(i, auth, isProxy);
- QMetaObject::invokeMethod(q, "_q_restartAuthPendingRequests", Qt::QueuedConnection);
}
}
// - Changing values in QAuthenticator will reset the 'phase'. Therefore if it is still "Done"
@@ -729,6 +746,10 @@ void QHttpNetworkConnectionPrivate::removeReply(QHttpNetworkReply *reply)
// although it is called _q_startNextRequest, it will actually start multiple requests when possible
void QHttpNetworkConnectionPrivate::_q_startNextRequest()
{
+ // If the QHttpNetworkConnection is currently paused then bail out immediatly
+ if (state == PausedState)
+ return;
+
//resend the necessary ones.
for (int i = 0; i < channelCount; ++i) {
if (channels[i].resendCurrent) {
@@ -779,17 +800,6 @@ void QHttpNetworkConnectionPrivate::_q_startNextRequest()
fillPipeline(channels[i].socket);
}
-void QHttpNetworkConnectionPrivate::_q_restartAuthPendingRequests()
-{
- // send the request using the idle socket
- for (int i = 0 ; i < channelCount; ++i) {
- if (channels[i].state == QHttpNetworkConnectionChannel::Wait4AuthState) {
- channels[i].state = QHttpNetworkConnectionChannel::IdleState;
- if (channels[i].reply)
- channels[i].sendRequest();
- }
- }
-}
void QHttpNetworkConnectionPrivate::readMoreLater(QHttpNetworkReply *reply)
{