From b52a3a415c3dbb4cb5d20d8a93d39817fe05856e Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Mon, 23 Nov 2015 21:47:30 +0100 Subject: [PATCH] Connectivity: Improve reconnecting after network change/disconnect #4167 --- src/gui/application.cpp | 17 ++++++++++++++++- src/gui/application.h | 3 +++ src/libsync/abstractnetworkjob.h | 2 ++ src/libsync/connectionvalidator.cpp | 6 ++++++ src/libsync/connectionvalidator.h | 3 +++ 5 files changed, 30 insertions(+), 1 deletion(-) diff --git a/src/gui/application.cpp b/src/gui/application.cpp index add9add91..62ccea911 100644 --- a/src/gui/application.cpp +++ b/src/gui/application.cpp @@ -177,11 +177,15 @@ Application::Application(int &argc, char **argv) : // startup procedure. connect(&_checkConnectionTimer, SIGNAL(timeout()), this, SLOT(slotCheckConnection())); - _checkConnectionTimer.setInterval(32 * 1000); // check for connection every 32 seconds. + _checkConnectionTimer.setInterval(ConnectionValidator::defaultCallingIntervalMsec()); // check for connection every 32 seconds. _checkConnectionTimer.start(); // Also check immediately QTimer::singleShot( 0, this, SLOT( slotCheckConnection() )); + // Can't use onlineStateChanged because it is always true on modern systems because of many interfaces + connect(&_networkConfigurationManager, SIGNAL(configurationChanged(QNetworkConfiguration)), + this, SLOT(slotSystemOnlineConfigurationChanged(QNetworkConfiguration))); + // Update checks UpdaterScheduler *updaterScheduler = new UpdaterScheduler(this); connect(updaterScheduler, SIGNAL(updaterAnnouncement(QString, QString)), @@ -234,6 +238,17 @@ void Application::slotCleanup() _gui->deleteLater(); } +// FIXME: This is not ideal yet since a ConnectionValidator might already be running and is in +// progress of timing out in some seconds. +// Maybe we need 2 validators, one triggered by timer, one by network configuration changes? +void Application::slotSystemOnlineConfigurationChanged(QNetworkConfiguration cnf) +{ + if (cnf.state() & QNetworkConfiguration::Active) { + //qDebug() << "Trying fast reconnect"; + QMetaObject::invokeMethod(this, "slotCheckConnection", Qt::QueuedConnection); + } +} + void Application::slotCheckConnection() { auto list = AccountManager::instance()->accounts(); diff --git a/src/gui/application.h b/src/gui/application.h index 538120918..0dec628fe 100644 --- a/src/gui/application.h +++ b/src/gui/application.h @@ -20,6 +20,7 @@ #include #include #include +#include #include "qtsingleapplication.h" @@ -87,6 +88,7 @@ protected slots: void slotAccountStateAdded(AccountState *accountState); void slotAccountStateRemoved(AccountState *accountState); void slotCrash(); + void slotSystemOnlineConfigurationChanged(QNetworkConfiguration); private: void setHelp(); @@ -111,6 +113,7 @@ private: ClientProxy _proxy; + QNetworkConfigurationManager _networkConfigurationManager; QTimer _checkConnectionTimer; #if defined(WITH_CRASHREPORTER) diff --git a/src/libsync/abstractnetworkjob.h b/src/libsync/abstractnetworkjob.h index 08e71cf8b..039732f00 100644 --- a/src/libsync/abstractnetworkjob.h +++ b/src/libsync/abstractnetworkjob.h @@ -57,6 +57,8 @@ public: QByteArray responseTimestamp(); quint64 duration(); + qint64 timeoutMsec() { return _timer.interval(); } + public slots: void setTimeout(qint64 msec); void resetTimeout(); diff --git a/src/libsync/connectionvalidator.cpp b/src/libsync/connectionvalidator.cpp index 651a9b396..ca4e79705 100644 --- a/src/libsync/connectionvalidator.cpp +++ b/src/libsync/connectionvalidator.cpp @@ -23,6 +23,10 @@ namespace OCC { +// Make sure the timeout for this job is less than how often we get called +// This makes sure we get tried often enough without "ConnectionValidator already running" +static qint64 timeoutToUseMsec = qMax(qint64(1000), ConnectionValidator::defaultCallingIntervalMsec() - 5*1000); + ConnectionValidator::ConnectionValidator(AccountPtr account, QObject *parent) : QObject(parent), _account(account), @@ -99,6 +103,7 @@ void ConnectionValidator::systemProxyLookupDone(const QNetworkProxy &proxy) { void ConnectionValidator::slotCheckServerAndAuth() { CheckServerJob *checkJob = new CheckServerJob(_account, this); + checkJob->setTimeout(timeoutToUseMsec); checkJob->setIgnoreCredentialFailure(true); connect(checkJob, SIGNAL(instanceFound(QUrl,QVariantMap)), SLOT(slotStatusFound(QUrl,QVariantMap))); connect(checkJob, SIGNAL(networkError(QNetworkReply*)), SLOT(slotNoStatusFound(QNetworkReply*))); @@ -165,6 +170,7 @@ void ConnectionValidator::checkAuthentication() // continue in slotAuthCheck here :-) qDebug() << "# Check whether authenticated propfind works."; PropfindJob *job = new PropfindJob(_account, "/", this); + job->setTimeout(timeoutToUseMsec); job->setProperties(QList() << "getlastmodified"); connect(job, SIGNAL(result(QVariantMap)), SLOT(slotAuthSuccess())); connect(job, SIGNAL(networkError(QNetworkReply*)), SLOT(slotAuthFailed(QNetworkReply*))); diff --git a/src/libsync/connectionvalidator.h b/src/libsync/connectionvalidator.h index bff1b7e9f..eb57a293d 100644 --- a/src/libsync/connectionvalidator.h +++ b/src/libsync/connectionvalidator.h @@ -84,6 +84,9 @@ public: static QString statusString( Status ); + // How often should the Application ask this object to check for the connection? + static qint64 defaultCallingIntervalMsec() { return 32 * 1000;} + public slots: /// Checks the server and the authentication. void checkServerAndAuth();