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 <lorn.potter@canonical.com>
bb10
Samuel Gaist 2016-09-26 23:38:37 +02:00
parent a0551ae610
commit 58e1465cb0
5 changed files with 85 additions and 9 deletions

View File

@ -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.
*/

View File

@ -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;

View File

@ -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)

View File

@ -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<QNetworkSession> networkSession = qvariant_cast< QSharedPointer<QNetworkSession> >(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<QNetworkSession> networkSession = qvariant_cast< QSharedPointer<QNetworkSession> >(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<QNetworkSession> networkSession;
QVariant v(property("_q_networksession"));
if (v.isValid()) {
networkSession = qvariant_cast< QSharedPointer<QNetworkSession> >(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++);

View File

@ -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<QNetworkConfiguration> 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)