From 58e1465cb0042899063124ded827f52dd92b8b42 Mon Sep 17 00:00:00 2001 From: Samuel Gaist Date: Mon, 26 Sep 2016 23:38:37 +0200 Subject: [PATCH] Add configurable connect timeout for QAbstractSocket The aim of this patch is to allow the configuration of the connect timeout used by QAbstractSocket that is currently hardcoded to 30 seconds. Using QNetworkConfiguration for this allows to adapt the timeout per network configuration (e.g. 2G vs wired lan) [ChangeLog][QtNetwork] The connect timeout from QAbstractSocket is now configurable through QNetworkConfiguration. Change-Id: I1dc4051be2c74f925f7a9e0a9ccef332efc2e370 Reviewed-by: Lorn Potter --- src/network/bearer/qnetworkconfiguration.cpp | 38 +++++++++++++++++++ src/network/bearer/qnetworkconfiguration.h | 3 ++ src/network/bearer/qnetworkconfiguration_p.h | 6 ++- src/network/socket/qabstractsocket.cpp | 31 +++++++++++---- .../tst_qnetworkconfiguration.cpp | 16 ++++++++ 5 files changed, 85 insertions(+), 9 deletions(-) diff --git a/src/network/bearer/qnetworkconfiguration.cpp b/src/network/bearer/qnetworkconfiguration.cpp index 533a27357c..d2feffb316 100644 --- a/src/network/bearer/qnetworkconfiguration.cpp +++ b/src/network/bearer/qnetworkconfiguration.cpp @@ -325,6 +325,44 @@ bool QNetworkConfiguration::isValid() const return d->isValid; } +/*! + \since 5.9 + + Returns the connect timeout of this configuration. + + \sa setConnectTimeout +*/ +int QNetworkConfiguration::connectTimeout() const +{ + if (!d) + return QNetworkConfigurationPrivate::DefaultTimeout; + QMutexLocker locker(&d->mutex); + return d->timeout; +} + +/*! + \since 5.9 + + Sets the connect timeout of this configuration. + This allows control of the timeout used by \c QAbstractSocket + to establish a connection. + + \warning This will have no effect if the bearer plugin doesn't have + the CanStartAndStopInterfaces capability. + + Returns true if succeeded. + + \sa connectTimeout +*/ +bool QNetworkConfiguration::setConnectTimeout(int timeout) +{ + if (!d) + return false; + QMutexLocker locker(&d->mutex); + d->timeout = timeout; + return true; +} + /*! Returns the current state of the configuration. */ diff --git a/src/network/bearer/qnetworkconfiguration.h b/src/network/bearer/qnetworkconfiguration.h index 208f9f4692..e7b74034fc 100644 --- a/src/network/bearer/qnetworkconfiguration.h +++ b/src/network/bearer/qnetworkconfiguration.h @@ -120,6 +120,9 @@ public: QString name() const; bool isValid() const; + int connectTimeout() const; + bool setConnectTimeout(int timeout); + private: friend class QNetworkConfigurationPrivate; friend class QNetworkConfigurationManager; diff --git a/src/network/bearer/qnetworkconfiguration_p.h b/src/network/bearer/qnetworkconfiguration_p.h index 12d9676b59..2fdb490ea0 100644 --- a/src/network/bearer/qnetworkconfiguration_p.h +++ b/src/network/bearer/qnetworkconfiguration_p.h @@ -69,7 +69,8 @@ public: type(QNetworkConfiguration::Invalid), purpose(QNetworkConfiguration::UnknownPurpose), bearerType(QNetworkConfiguration::BearerUnknown), - isValid(false), roamingSupported(false) + isValid(false), roamingSupported(false), + timeout(DefaultTimeout) {} virtual ~QNetworkConfigurationPrivate() { @@ -91,6 +92,9 @@ public: bool isValid; bool roamingSupported; + int timeout; + + static Q_CONSTEXPR int DefaultTimeout = 30000; private: Q_DISABLE_COPY(QNetworkConfigurationPrivate) diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 741bd9a52d..6b773e2be9 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -491,7 +491,6 @@ #ifndef QABSTRACTSOCKET_BUFFERSIZE #define QABSTRACTSOCKET_BUFFERSIZE 32768 #endif -#define QT_CONNECT_TIMEOUT 30000 #define QT_TRANSFER_TIMEOUT 120000 QT_BEGIN_NAMESPACE @@ -1137,7 +1136,15 @@ void QAbstractSocketPrivate::_q_connectToNextAddress() q, SLOT(_q_abortConnectionAttempt()), Qt::DirectConnection); } - connectTimer->start(QT_CONNECT_TIMEOUT); + int connectTimeout = QNetworkConfigurationPrivate::DefaultTimeout; +#ifndef QT_NO_BEARERMANAGEMENT + QSharedPointer networkSession = qvariant_cast< QSharedPointer >(q->property("_q_networksession")); + if (networkSession) { + QNetworkConfiguration networkConfiguration = networkSession->configuration(); + connectTimeout = networkConfiguration.connectTimeout(); + } +#endif + connectTimer->start(connectTimeout); } // Wait for a write notification that will eventually call @@ -2095,6 +2102,10 @@ bool QAbstractSocket::waitForConnected(int msecs) QElapsedTimer stopWatch; stopWatch.start(); +#ifndef QT_NO_BEARERMANAGEMENT + QSharedPointer networkSession = qvariant_cast< QSharedPointer >(property("_q_networksession")); +#endif + if (d->state == HostLookupState) { #if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocket::waitForConnected(%i) doing host name lookup", msecs); @@ -2102,10 +2113,7 @@ bool QAbstractSocket::waitForConnected(int msecs) QHostInfo::abortHostLookup(d->hostLookupId); d->hostLookupId = -1; #ifndef QT_NO_BEARERMANAGEMENT - QSharedPointer networkSession; - QVariant v(property("_q_networksession")); - if (v.isValid()) { - networkSession = qvariant_cast< QSharedPointer >(v); + if (networkSession) { d->_q_startConnecting(QHostInfoPrivate::fromName(d->hostName, networkSession)); } else #endif @@ -2123,14 +2131,21 @@ bool QAbstractSocket::waitForConnected(int msecs) if (state() == UnconnectedState) return false; // connect not im progress anymore! + int connectTimeout = QNetworkConfigurationPrivate::DefaultTimeout; +#ifndef QT_NO_BEARERMANAGEMENT + if (networkSession) { + QNetworkConfiguration networkConfiguration = networkSession->configuration(); + connectTimeout = networkConfiguration.connectTimeout(); + } +#endif bool timedOut = true; #if defined (QABSTRACTSOCKET_DEBUG) int attempt = 1; #endif while (state() == ConnectingState && (msecs == -1 || stopWatch.elapsed() < msecs)) { int timeout = qt_subtract_from_timeout(msecs, stopWatch.elapsed()); - if (msecs != -1 && timeout > QT_CONNECT_TIMEOUT) - timeout = QT_CONNECT_TIMEOUT; + if (msecs != -1 && timeout > connectTimeout) + timeout = connectTimeout; #if defined (QABSTRACTSOCKET_DEBUG) qDebug("QAbstractSocket::waitForConnected(%i) waiting %.2f secs for connection attempt #%i", msecs, timeout / 1000.0, attempt++); diff --git a/tests/auto/network/bearer/qnetworkconfiguration/tst_qnetworkconfiguration.cpp b/tests/auto/network/bearer/qnetworkconfiguration/tst_qnetworkconfiguration.cpp index 0a52dd0388..6ca881d38a 100644 --- a/tests/auto/network/bearer/qnetworkconfiguration/tst_qnetworkconfiguration.cpp +++ b/tests/auto/network/bearer/qnetworkconfiguration/tst_qnetworkconfiguration.cpp @@ -53,6 +53,7 @@ private slots: void comparison(); void children(); void isRoamingAvailable(); + void connectTimeout(); #endif }; @@ -181,6 +182,21 @@ void tst_QNetworkConfiguration::isRoamingAvailable() } } } + +void tst_QNetworkConfiguration::connectTimeout() +{ + QNetworkConfigurationManager manager; + QList configs = manager.allConfigurations(); + + foreach (QNetworkConfiguration networkConfiguration, configs) { + QCOMPARE(networkConfiguration.connectTimeout(), 30000); + + bool result = networkConfiguration.setConnectTimeout(100); + QVERIFY(result); + + QCOMPARE(networkConfiguration.connectTimeout(), 100); + } +} #endif QTEST_MAIN(tst_QNetworkConfiguration)