diff options
Diffstat (limited to 'src/network/access')
-rw-r--r-- | src/network/access/qnetworkaccessbackend.cpp | 24 | ||||
-rw-r--r-- | src/network/access/qnetworkaccessbackend_p.h | 4 | ||||
-rw-r--r-- | src/network/access/qnetworkaccessmanager.cpp | 79 | ||||
-rw-r--r-- | src/network/access/qnetworkaccessmanager.h | 6 | ||||
-rw-r--r-- | src/network/access/qnetworkaccessmanager_p.h | 11 | ||||
-rw-r--r-- | src/network/access/qnetworkreply.cpp | 4 | ||||
-rw-r--r-- | src/network/access/qnetworkreply.h | 1 | ||||
-rw-r--r-- | src/network/access/qnetworkreplyimpl.cpp | 29 |
8 files changed, 134 insertions, 24 deletions
diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp index c712fff..22df248 100644 --- a/src/network/access/qnetworkaccessbackend.cpp +++ b/src/network/access/qnetworkaccessbackend.cpp @@ -49,7 +49,6 @@ #include "qnetworkaccesscachebackend_p.h" #include "qabstractnetworkcache.h" -#include "qnetworksession.h" #include "qhostinfo.h" #include "private/qnoncontiguousbytedevice_p.h" @@ -345,22 +344,20 @@ void QNetworkAccessBackend::sslErrors(const QList<QSslError> &errors) void QNetworkAccessBackend::start() { - qDebug() << "Checking for localhost"; QHostInfo hostInfo = QHostInfo::fromName(reply->url.host()); foreach (const QHostAddress &address, hostInfo.addresses()) { if (address == QHostAddress::LocalHost || address == QHostAddress::LocalHostIPv6) { // Don't need session for local host access. - qDebug() << "Access is to localhost"; open(); return; } } - qDebug() << "Connecting session signals"; connect(manager->session, SIGNAL(opened()), this, SLOT(sessionOpened())); + connect(manager->session, SIGNAL(error(QNetworkSession::SessionError)), + this, SLOT(sessionError(QNetworkSession::SessionError))); - qDebug() << "Open session if required"; if (!manager->session->isOpen()) manager->session->open(); else @@ -369,25 +366,12 @@ void QNetworkAccessBackend::start() void QNetworkAccessBackend::sessionOpened() { - manager->sendDebugMessage(QLatin1String("Session opened")); - qDebug() << "Session opened, calling open()"; open(); } -void QNetworkAccessBackend::preferredConfigurationChanged(const QNetworkConfiguration &config, - bool isSeamless) +void QNetworkAccessBackend::sessionError(QNetworkSession::SessionError error) { - QString message = QString::fromLatin1("preferredConfiguirationChanged %1 %2") - .arg(config.name()) .arg(isSeamless); - - manager->sendDebugMessage(message); - manager->session->ignore(); -} - -void QNetworkAccessBackend::newConfigurationActivated() -{ - manager->sendDebugMessage(QLatin1String("newConfigurationActivated")); - manager->session->reject(); + manager->sendDebugMessage(QString::fromLatin1("Session error %1").arg(error)); } QT_END_NAMESPACE diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h index 62ac736..08a8a2a 100644 --- a/src/network/access/qnetworkaccessbackend_p.h +++ b/src/network/access/qnetworkaccessbackend_p.h @@ -54,6 +54,7 @@ // #include "qnetworkreplyimpl_p.h" +#include "QtNetwork/qnetworksession.h" #include "QtCore/qobject.h" QT_BEGIN_NAMESPACE @@ -189,8 +190,7 @@ protected slots: private slots: void sessionOpened(); - void preferredConfigurationChanged(const QNetworkConfiguration &config, bool isSeamless); - void newConfigurationActivated(); + void sessionError(QNetworkSession::SessionError error); private: friend class QNetworkAccessManager; diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index b8edefa..3f8ef01 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -351,6 +351,17 @@ QNetworkAccessManager::QNetworkAccessManager(QObject *parent) QNetworkConfigurationManager manager; d_func()->session = new QNetworkSession(manager.defaultConfiguration(), this); + + connect(d_func()->session, SIGNAL(opened()), this, SLOT(_q_sessionOpened())); + connect(d_func()->session, SIGNAL(closed()), this, SLOT(_q_sessionClosed())); + connect(d_func()->session, SIGNAL(stateChanged(QNetworkSession::State)), + this, SLOT(_q_sessionStateChanged(QNetworkSession::State))); + connect(d_func()->session, SIGNAL(error(QNetworkSession::SessionError)), + this, SLOT(_q_sessionError(QNetworkSession::SessionError))); + connect(d_func()->session, SIGNAL(newConfigurationActivated()), + this, SLOT(_q_sessionNewConfigurationActivated())); + connect(d_func()->session, SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool)), + this, SLOT(_q_sessionPreferredConfigurationChanged(QNetworkConfiguration,bool))); } /*! @@ -792,6 +803,20 @@ void QNetworkAccessManagerPrivate::_q_replyFinished() QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender()); if (reply) emit q->finished(reply); + + if (deferredMigration) { + bool repliesPending = false; + foreach (QObject *child, q->children()) { + if (child != reply && child->inherits("QNetworkReply")) { + repliesPending = true; + break; + } + } + if (!repliesPending) { + emit q->debugMessage(QLatin1String("Migrating as there are no pending replies.")); + session->migrate(); + } + } } void QNetworkAccessManagerPrivate::_q_replySslErrors(const QList<QSslError> &errors) @@ -1044,6 +1069,60 @@ QNetworkAccessManagerPrivate::~QNetworkAccessManagerPrivate() { } +void QNetworkAccessManagerPrivate::_q_sessionOpened() +{ + Q_Q(QNetworkAccessManager); +} + +void QNetworkAccessManagerPrivate::_q_sessionClosed() +{ + Q_Q(QNetworkAccessManager); + + emit q->debugMessage(QLatin1String("Session Closed")); +} + +void QNetworkAccessManagerPrivate::_q_sessionError(QNetworkSession::SessionError error) +{ + Q_Q(QNetworkAccessManager); + + emit q->debugMessage(QString::fromLatin1("Session error %1").arg(error)); +} + +void QNetworkAccessManagerPrivate::_q_sessionStateChanged(QNetworkSession::State state) +{ + Q_Q(QNetworkAccessManager); +} + +void QNetworkAccessManagerPrivate::_q_sessionNewConfigurationActivated() +{ + Q_Q(QNetworkAccessManager); + + foreach (QObject *child, q->children()) { + QNetworkReply *reply = qobject_cast<QNetworkReply *>(child); + if (reply) { + emit q->debugMessage(QString::fromLatin1("Unexpected reply for %1").arg(reply->url().toString())); + } + } + + session->accept(); +} + +void QNetworkAccessManagerPrivate::_q_sessionPreferredConfigurationChanged(const QNetworkConfiguration &config, bool isSeamless) +{ + Q_Q(QNetworkAccessManager); + + deferredMigration = false; + foreach (QObject *child, q->children()) { + if (child->inherits("QNetworkReply")) { + deferredMigration = true; + break; + } + } + + if (!deferredMigration) + session->migrate(); +} + QT_END_NAMESPACE #include "moc_qnetworkaccessmanager.cpp" diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index 82bbd03..14aaf78 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -129,6 +129,12 @@ private: Q_DECLARE_PRIVATE(QNetworkAccessManager) Q_PRIVATE_SLOT(d_func(), void _q_replyFinished()) Q_PRIVATE_SLOT(d_func(), void _q_replySslErrors(QList<QSslError>)) + Q_PRIVATE_SLOT(d_func(), void _q_sessionOpened()) + Q_PRIVATE_SLOT(d_func(), void _q_sessionClosed()) + Q_PRIVATE_SLOT(d_func(), void _q_sessionError(QNetworkSession::SessionError)) + Q_PRIVATE_SLOT(d_func(), void _q_sessionStateChanged(QNetworkSession::State)) + Q_PRIVATE_SLOT(d_func(), void _q_sessionNewConfigurationActivated()) + Q_PRIVATE_SLOT(d_func(), void _q_sessionPreferredConfigurationChanged(QNetworkConfiguration,bool)) }; QT_END_NAMESPACE diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index b6a266c..b9e3964 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -76,7 +76,8 @@ public: proxyFactory(0), #endif cookieJarCreated(false), - session(0) + session(0), + deferredMigration(false) { } ~QNetworkAccessManagerPrivate(); @@ -107,6 +108,13 @@ public: emit q->debugMessage(message); } + void _q_sessionOpened(); + void _q_sessionClosed(); + void _q_sessionError(QNetworkSession::SessionError error); + void _q_sessionStateChanged(QNetworkSession::State state); + void _q_sessionNewConfigurationActivated(); + void _q_sessionPreferredConfigurationChanged(const QNetworkConfiguration &config, bool isSeamless); + // this is the cache for storing downloaded files QAbstractNetworkCache *networkCache; @@ -121,6 +129,7 @@ public: bool cookieJarCreated; QNetworkSession *session; + bool deferredMigration; // this cache can be used by individual backends to cache e.g. their TCP connections to a server // and use the connections for multiple requests. diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp index 0a8ea5d..e299b5b 100644 --- a/src/network/access/qnetworkreply.cpp +++ b/src/network/access/qnetworkreply.cpp @@ -125,6 +125,10 @@ QNetworkReplyPrivate::QNetworkReplyPrivate() encrypted channel could not be established. The sslErrors() signal should have been emitted. + \value TemporaryNetworkFailureError the connection was broken due + to disconnection from the network, however the system has initiated + roaming to another access point. The request should be resubmitted. + \value ProxyConnectionRefusedError the connection to the proxy server was refused (the proxy server is not accepting requests) diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h index 5be4cce..b39557a 100644 --- a/src/network/access/qnetworkreply.h +++ b/src/network/access/qnetworkreply.h @@ -77,6 +77,7 @@ public: TimeoutError, OperationCanceledError, SslHandshakeFailedError, + TemporaryNetworkFailureError, UnknownNetworkError = 99, // proxy errors (101-199): diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index f097a2b..7eca323 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -47,6 +47,7 @@ #include "QtCore/qdatetime.h" #include "QtNetwork/qsslconfiguration.h" #include "qnetworkaccesshttpbackend_p.h" +#include "qnetworkaccessmanager_p.h" #include <QtCore/QCoreApplication> @@ -516,7 +517,33 @@ void QNetworkReplyImplPrivate::finished() emit q->uploadProgress(0, 0); resumeNotificationHandling(); - completeCacheSave(); + if (manager->d_func()->session->state() == QNetworkSession::Roaming) { + // only content with a known size will fail with a temporary network failure error + if (!totalSize.isNull()) { + qDebug() << "Connection broke during download."; + qDebug() << "Don't worry, we've already started roaming :)"; + + if (bytesDownloaded == totalSize) { + qDebug() << "Luckily download has already finished."; + } else { + qDebug() << "Download hasn't finished"; + + if (q->bytesAvailable() == bytesDownloaded) { + qDebug() << "User hasn't read data from reply, we could continue after reconnect."; + error(QNetworkReply::TemporaryNetworkFailureError, q->tr("Temporary network failure.")); + } else if (q->bytesAvailable() < bytesDownloaded) { + qDebug() << "User has already read data from reply."; + error(QNetworkReply::TemporaryNetworkFailureError, q->tr("Temporary network failure.")); + } + } + } + } + + // if we don't know the total size of or we received everything save the cache + if (totalSize.isNull() || totalSize == -1 || bytesDownloaded == totalSize) + completeCacheSave(); + else + qDebug() << "Not saving cache."; // note: might not be a good idea, since users could decide to delete us // which would delete the backend too... |