summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/network/access/qnetworkaccessbackend.cpp24
-rw-r--r--src/network/access/qnetworkaccessbackend_p.h4
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp79
-rw-r--r--src/network/access/qnetworkaccessmanager.h6
-rw-r--r--src/network/access/qnetworkaccessmanager_p.h11
-rw-r--r--src/network/access/qnetworkreply.cpp4
-rw-r--r--src/network/access/qnetworkreply.h1
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp29
8 files changed, 134 insertions, 24 deletions
diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp
index c712fffece..22df248a16 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 62ac736738..08a8a2af65 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 b8edefad24..3f8ef01f5f 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 82bbd0303d..14aaf7817b 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 b6a266c912..b9e3964983 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 0a8ea5d03a..e299b5b8c1 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 5be4cce264..b39557a082 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 f097a2bf3f..7eca323761 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...