From cf69144f2b5511c6e4e81bd9da8ee6acd2340e5c Mon Sep 17 00:00:00 2001 From: Aaron McCarthy Date: Mon, 8 Mar 2010 13:04:13 +1000 Subject: Make QNetworkConfigurationManager and QNetworkConfiguration threadsafe. --- src/network/bearer/qbearerengine_p.h | 4 +- src/network/bearer/qnetworkconfigmanager.cpp | 169 +------------------ src/network/bearer/qnetworkconfigmanager_p.cpp | 218 ++++++++++++++++++++++++- src/network/bearer/qnetworkconfigmanager_p.h | 7 +- src/network/bearer/qnetworkconfiguration.cpp | 60 +++++-- src/network/bearer/qnetworkconfiguration_p.h | 22 ++- 6 files changed, 285 insertions(+), 195 deletions(-) (limited to 'src/network/bearer') diff --git a/src/network/bearer/qbearerengine_p.h b/src/network/bearer/qbearerengine_p.h index 028c174eae..fd4bf878b7 100644 --- a/src/network/bearer/qbearerengine_p.h +++ b/src/network/bearer/qbearerengine_p.h @@ -73,7 +73,7 @@ class Q_NETWORK_EXPORT QBearerEngine : public QObject { Q_OBJECT - friend class QNetworkConfigurationManager; + friend class QNetworkConfigurationManagerPrivate; public: QBearerEngine(QObject *parent = 0); @@ -81,8 +81,6 @@ public: virtual bool hasIdentifier(const QString &id) = 0; - virtual void requestUpdate() = 0; - virtual QNetworkConfigurationManager::Capabilities capabilities() const = 0; virtual QNetworkSessionPrivate *createSessionBackend() = 0; diff --git a/src/network/bearer/qnetworkconfigmanager.cpp b/src/network/bearer/qnetworkconfigmanager.cpp index b631cf15d4..e7595a4561 100644 --- a/src/network/bearer/qnetworkconfigmanager.cpp +++ b/src/network/bearer/qnetworkconfigmanager.cpp @@ -212,114 +212,7 @@ QNetworkConfigurationManager::~QNetworkConfigurationManager() */ QNetworkConfiguration QNetworkConfigurationManager::defaultConfiguration() const { - QNetworkConfigurationManagerPrivate *conPriv = connManager(); - - foreach (QBearerEngine *engine, conPriv->engines()) { - QNetworkConfigurationPrivatePointer ptr = engine->defaultConfiguration(); - - if (ptr) { - QNetworkConfiguration config; - config.d = ptr; - return config; - } - } - - // Engines don't have a default configuration. - - // Return first active snap - QNetworkConfigurationPrivatePointer defaultConfiguration; - - foreach (QBearerEngine *engine, conPriv->engines()) { - QHash::Iterator it; - QHash::Iterator end; - - QMutexLocker locker(&engine->mutex); - - for (it = engine->snapConfigurations.begin(), end = engine->snapConfigurations.end(); - it != end; ++it) { - if ((it.value()->state & QNetworkConfiguration::Active) == - QNetworkConfiguration::Active) { - QNetworkConfiguration config; - config.d = it.value(); - return config; - } else if (!defaultConfiguration) { - if ((it.value()->state & QNetworkConfiguration::Discovered) == - QNetworkConfiguration::Discovered) { - defaultConfiguration = it.value(); - } - } - } - } - - // No Active SNAPs return first Discovered SNAP. - if (defaultConfiguration) { - QNetworkConfiguration config; - config.d = defaultConfiguration; - return config; - } - - /* - No Active or Discovered SNAPs, find the perferred access point. - The following priority order is used: - - 1. Active Ethernet - 2. Active WLAN - 3. Active Other - 4. Discovered Ethernet - 5. Discovered WLAN - 6. Discovered Other - */ - - defaultConfiguration.reset(); - - foreach (QBearerEngine *engine, conPriv->engines()) { - QHash::Iterator it; - QHash::Iterator end; - - QMutexLocker locker(&engine->mutex); - - for (it = engine->accessPointConfigurations.begin(), - end = engine->accessPointConfigurations.end(); it != end; ++it) { - - if ((it.value()->state & QNetworkConfiguration::Discovered) == - QNetworkConfiguration::Discovered) { - if (!defaultConfiguration) { - defaultConfiguration = it.value(); - } else { - if (defaultConfiguration->state == it.value()->state) { - if (defaultConfiguration->bearerName() == QLatin1String("Ethernet")) { - // do nothing - } else if (defaultConfiguration->bearerName() == QLatin1String("WLAN")) { - // ethernet beats wlan - if (it.value()->bearerName() == QLatin1String("Ethernet")) - defaultConfiguration = it.value(); - } else { - // ethernet and wlan beats other - if (it.value()->bearerName() == QLatin1String("Ethernet") || - it.value()->bearerName() == QLatin1String("WLAN")) { - defaultConfiguration = it.value(); - } - } - } else { - // active beats discovered - if ((defaultConfiguration->state & QNetworkConfiguration::Active) != - QNetworkConfiguration::Active) { - defaultConfiguration = it.value(); - } - } - } - } - } - } - - // No Active InternetAccessPoint return first Discovered InternetAccessPoint. - if (defaultConfiguration) { - QNetworkConfiguration config; - config.d = defaultConfiguration; - return config; - } - - return QNetworkConfiguration(); + return connManager()->defaultConfiguration(); } /*! @@ -349,37 +242,7 @@ QNetworkConfiguration QNetworkConfigurationManager::defaultConfiguration() const */ QList QNetworkConfigurationManager::allConfigurations(QNetworkConfiguration::StateFlags filter) const { - QList result; - QNetworkConfigurationManagerPrivate* conPriv = connManager(); - - foreach (QBearerEngine *engine, conPriv->engines()) { - QHash::Iterator it; - QHash::Iterator end; - - QMutexLocker locker(&engine->mutex); - - //find all InternetAccessPoints - for (it = engine->accessPointConfigurations.begin(), - end = engine->accessPointConfigurations.end(); it != end; ++it) { - if ((it.value()->state & filter) == filter) { - QNetworkConfiguration pt; - pt.d = it.value(); - result << pt; - } - } - - //find all service networks - for (it = engine->snapConfigurations.begin(), - end = engine->snapConfigurations.end(); it != end; ++it) { - if ((it.value()->state & filter) == filter) { - QNetworkConfiguration pt; - pt.d = it.value(); - result << pt; - } - } - } - - return result; + return connManager()->allConfigurations(filter); } /*! @@ -388,28 +251,9 @@ QList QNetworkConfigurationManager::allConfigurations(QNe \sa QNetworkConfiguration::identifier() */ -QNetworkConfiguration QNetworkConfigurationManager::configurationFromIdentifier(const QString& identifier) const +QNetworkConfiguration QNetworkConfigurationManager::configurationFromIdentifier(const QString &identifier) const { - QNetworkConfigurationManagerPrivate* conPriv = connManager(); - - QNetworkConfiguration item; - - foreach (QBearerEngine *engine, conPriv->engines()) { - QMutexLocker locker(&engine->mutex); - - if (engine->accessPointConfigurations.contains(identifier)) - item.d = engine->accessPointConfigurations.value(identifier); - else if (engine->snapConfigurations.contains(identifier)) - item.d = engine->snapConfigurations.value(identifier); - else if (engine->userChoiceConfigurations.contains(identifier)) - item.d = engine->userChoiceConfigurations.value(identifier); - else - continue; - - return item; - } - - return item; + return connManager()->configurationFromIdentifier(identifier); } /*! @@ -424,10 +268,7 @@ QNetworkConfiguration QNetworkConfigurationManager::configurationFromIdentifier( */ bool QNetworkConfigurationManager::isOnline() const { - QNetworkConfigurationManagerPrivate* conPriv = connManager(); - Q_UNUSED(conPriv); - QList activeConfigs = allConfigurations(QNetworkConfiguration::Active); - return activeConfigs.count() > 0; + return connManager()->isOnline(); } /*! diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp index 9740424bc6..c665fa257b 100644 --- a/src/network/bearer/qnetworkconfigmanager_p.cpp +++ b/src/network/bearer/qnetworkconfigmanager_p.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include QT_BEGIN_NAMESPACE @@ -57,11 +58,10 @@ Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate() : capFlags(0), mutex(QMutex::Recursive), pollTimer(0), forcedPolling(0), firstUpdate(true) { - updateConfigurations(); + qRegisterMetaType("QNetworkConfiguration"); moveToThread(QCoreApplicationPrivate::mainThread()); - foreach (QBearerEngine *engine, sessionEngines) - engine->moveToThread(QCoreApplicationPrivate::mainThread()); + updateConfigurations(); } QNetworkConfigurationManagerPrivate::~QNetworkConfigurationManagerPrivate() @@ -71,6 +71,200 @@ QNetworkConfigurationManagerPrivate::~QNetworkConfigurationManagerPrivate() qDeleteAll(sessionEngines); } +QNetworkConfiguration QNetworkConfigurationManagerPrivate::defaultConfiguration() +{ + QMutexLocker locker(&mutex); + + foreach (QBearerEngine *engine, sessionEngines) { + QNetworkConfigurationPrivatePointer ptr = engine->defaultConfiguration(); + + if (ptr) { + QNetworkConfiguration config; + config.d = ptr; + return config; + } + } + + // Engines don't have a default configuration. + + // Return first active snap + QNetworkConfigurationPrivatePointer defaultConfiguration; + + foreach (QBearerEngine *engine, sessionEngines) { + QHash::Iterator it; + QHash::Iterator end; + + QMutexLocker locker(&engine->mutex); + + for (it = engine->snapConfigurations.begin(), end = engine->snapConfigurations.end(); + it != end; ++it) { + QNetworkConfigurationPrivatePointer ptr = it.value(); + + QMutexLocker configLocker(&ptr->mutex); + + if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { + QNetworkConfiguration config; + config.d = ptr; + return config; + } else if (!defaultConfiguration) { + if ((ptr->state & QNetworkConfiguration::Discovered) == + QNetworkConfiguration::Discovered) { + defaultConfiguration = ptr; + } + } + } + } + + // No Active SNAPs return first Discovered SNAP. + if (defaultConfiguration) { + QNetworkConfiguration config; + config.d = defaultConfiguration; + return config; + } + + /* + No Active or Discovered SNAPs, find the perferred access point. + The following priority order is used: + + 1. Active Ethernet + 2. Active WLAN + 3. Active Other + 4. Discovered Ethernet + 5. Discovered WLAN + 6. Discovered Other + */ + + defaultConfiguration.reset(); + + foreach (QBearerEngine *engine, sessionEngines) { + QHash::Iterator it; + QHash::Iterator end; + + QMutexLocker locker(&engine->mutex); + + for (it = engine->accessPointConfigurations.begin(), + end = engine->accessPointConfigurations.end(); it != end; ++it) { + QNetworkConfigurationPrivatePointer ptr = it.value(); + + const QString bearerName = ptr->bearerName(); + QMutexLocker configLocker(&ptr->mutex); + + if ((ptr->state & QNetworkConfiguration::Discovered) == + QNetworkConfiguration::Discovered) { + if (!defaultConfiguration) { + defaultConfiguration = ptr; + } else { + if (defaultConfiguration->state == ptr->state) { + if (defaultConfiguration->bearerName() == QLatin1String("Ethernet")) { + // do nothing + } else if (defaultConfiguration->bearerName() == QLatin1String("WLAN")) { + // ethernet beats wlan + if (bearerName == QLatin1String("Ethernet")) + defaultConfiguration = ptr; + } else { + // ethernet and wlan beats other + if (bearerName == QLatin1String("Ethernet") || + bearerName == QLatin1String("WLAN")) { + defaultConfiguration = ptr; + } + } + } else { + // active beats discovered + if ((defaultConfiguration->state & QNetworkConfiguration::Active) != + QNetworkConfiguration::Active) { + defaultConfiguration = ptr; + } + } + } + } + } + } + + // No Active InternetAccessPoint return first Discovered InternetAccessPoint. + if (defaultConfiguration) { + QNetworkConfiguration config; + config.d = defaultConfiguration; + return config; + } + + return QNetworkConfiguration(); +} + +QList QNetworkConfigurationManagerPrivate::allConfigurations(QNetworkConfiguration::StateFlags filter) +{ + QList result; + + QMutexLocker locker(&mutex); + + foreach (QBearerEngine *engine, sessionEngines) { + QHash::Iterator it; + QHash::Iterator end; + + QMutexLocker locker(&engine->mutex); + + //find all InternetAccessPoints + for (it = engine->accessPointConfigurations.begin(), + end = engine->accessPointConfigurations.end(); it != end; ++it) { + QNetworkConfigurationPrivatePointer ptr = it.value(); + + QMutexLocker configLocker(&ptr->mutex); + + if ((ptr->state & filter) == filter) { + QNetworkConfiguration pt; + pt.d = ptr; + result << pt; + } + } + + //find all service networks + for (it = engine->snapConfigurations.begin(), + end = engine->snapConfigurations.end(); it != end; ++it) { + QNetworkConfigurationPrivatePointer ptr = it.value(); + + QMutexLocker configLocker(&ptr->mutex); + + if ((ptr->state & filter) == filter) { + QNetworkConfiguration pt; + pt.d = ptr; + result << pt; + } + } + } + + return result; +} + +QNetworkConfiguration QNetworkConfigurationManagerPrivate::configurationFromIdentifier(const QString &identifier) +{ + QNetworkConfiguration item; + + QMutexLocker locker(&mutex); + + foreach (QBearerEngine *engine, sessionEngines) { + QMutexLocker locker(&engine->mutex); + + if (engine->accessPointConfigurations.contains(identifier)) + item.d = engine->accessPointConfigurations.value(identifier); + else if (engine->snapConfigurations.contains(identifier)) + item.d = engine->snapConfigurations.value(identifier); + else if (engine->userChoiceConfigurations.contains(identifier)) + item.d = engine->userChoiceConfigurations.value(identifier); + else + continue; + + return item; + } + + return item; +} + +bool QNetworkConfigurationManagerPrivate::isOnline() +{ + QMutexLocker locker(&mutex); + + return !onlineConfigurations.isEmpty(); +} + void QNetworkConfigurationManagerPrivate::configurationAdded(QNetworkConfigurationPrivatePointer ptr) { QMutexLocker locker(&mutex); @@ -81,10 +275,14 @@ void QNetworkConfigurationManagerPrivate::configurationAdded(QNetworkConfigurati emit configurationAdded(item); } + ptr->mutex.lock(); if (ptr->state == QNetworkConfiguration::Active) { + ptr->mutex.unlock(); onlineConfigurations.insert(ptr->id); if (!firstUpdate && onlineConfigurations.count() == 1) emit onlineStateChanged(true); + } else { + ptr->mutex.unlock(); } } @@ -92,7 +290,9 @@ void QNetworkConfigurationManagerPrivate::configurationRemoved(QNetworkConfigura { QMutexLocker locker(&mutex); + ptr->mutex.lock(); ptr->isValid = false; + ptr->mutex.unlock(); if (!firstUpdate) { QNetworkConfiguration item; @@ -117,10 +317,12 @@ void QNetworkConfigurationManagerPrivate::configurationChanged(QNetworkConfigura bool previous = !onlineConfigurations.isEmpty(); + ptr->mutex.lock(); if (ptr->state == QNetworkConfiguration::Active) onlineConfigurations.insert(ptr->id); else onlineConfigurations.remove(ptr->id); + ptr->mutex.unlock(); bool online = !onlineConfigurations.isEmpty(); @@ -154,6 +356,8 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations() else sessionEngines.append(engine); + engine->moveToThread(QCoreApplicationPrivate::mainThread()); + connect(engine, SIGNAL(updateCompleted()), this, SLOT(updateConfigurations())); connect(engine, SIGNAL(configurationAdded(QNetworkConfigurationPrivatePointer)), @@ -165,7 +369,7 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations() capFlags |= engine->capabilities(); - engine->requestUpdate(); + QMetaObject::invokeMethod(engine, "requestUpdate"); } } @@ -211,7 +415,7 @@ void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate() for (int i = 0; i < sessionEngines.count(); ++i) { updatingEngines.insert(i); - sessionEngines.at(i)->requestUpdate(); + QMetaObject::invokeMethod(sessionEngines.at(i), "requestUpdate"); } } @@ -266,7 +470,7 @@ void QNetworkConfigurationManagerPrivate::pollEngines() if ((forcedPolling && sessionEngines.at(i)->requiresPolling()) || sessionEngines.at(i)->configurationsInUse()) { pollingEngines.insert(i); - sessionEngines.at(i)->requestUpdate(); + QMetaObject::invokeMethod(sessionEngines.at(i), "requestUpdate"); } } } @@ -278,7 +482,7 @@ void QNetworkConfigurationManagerPrivate::enablePolling() ++forcedPolling; if (forcedPolling == 1) - startPolling(); + QMetaObject::invokeMethod(this, "startPolling"); } void QNetworkConfigurationManagerPrivate::disablePolling() diff --git a/src/network/bearer/qnetworkconfigmanager_p.h b/src/network/bearer/qnetworkconfigmanager_p.h index ac8518c2e3..8ec815263a 100644 --- a/src/network/bearer/qnetworkconfigmanager_p.h +++ b/src/network/bearer/qnetworkconfigmanager_p.h @@ -66,11 +66,16 @@ class QTimer; class Q_NETWORK_EXPORT QNetworkConfigurationManagerPrivate : public QObject { Q_OBJECT + public: QNetworkConfigurationManagerPrivate(); virtual ~QNetworkConfigurationManagerPrivate(); QNetworkConfiguration defaultConfiguration(); + QList allConfigurations(QNetworkConfiguration::StateFlags filter); + QNetworkConfiguration configurationFromIdentifier(const QString &identifier); + + bool isOnline(); QNetworkConfigurationManager::Capabilities capFlags; @@ -78,7 +83,7 @@ public: QList engines(); - void startPolling(); + Q_INVOKABLE void startPolling(); void enablePolling(); void disablePolling(); diff --git a/src/network/bearer/qnetworkconfiguration.cpp b/src/network/bearer/qnetworkconfiguration.cpp index c4ba406d92..82669e033a 100644 --- a/src/network/bearer/qnetworkconfiguration.cpp +++ b/src/network/bearer/qnetworkconfiguration.cpp @@ -246,7 +246,11 @@ bool QNetworkConfiguration::operator==(const QNetworkConfiguration& other) const */ QString QNetworkConfiguration::name() const { - return d ? d->name : QString(); + if (!d) + return QString(); + + QMutexLocker locker(&d->mutex); + return d->name; } /*! @@ -255,7 +259,11 @@ QString QNetworkConfiguration::name() const */ QString QNetworkConfiguration::identifier() const { - return d ? d->id : QString(); + if (!d) + return QString(); + + QMutexLocker locker(&d->mutex); + return d->id; } /*! @@ -268,7 +276,11 @@ QString QNetworkConfiguration::identifier() const */ QNetworkConfiguration::Type QNetworkConfiguration::type() const { - return d ? d->type : QNetworkConfiguration::Invalid; + if (!d) + return QNetworkConfiguration::Invalid; + + QMutexLocker locker(&d->mutex); + return d->type; } /*! @@ -283,7 +295,11 @@ QNetworkConfiguration::Type QNetworkConfiguration::type() const */ bool QNetworkConfiguration::isValid() const { - return d ? d->isValid : false; + if (!d) + return false; + + QMutexLocker locker(&d->mutex); + return d->isValid; } /*! @@ -291,7 +307,11 @@ bool QNetworkConfiguration::isValid() const */ QNetworkConfiguration::StateFlags QNetworkConfiguration::state() const { - return d ? d->state : QNetworkConfiguration::Undefined; + if (!d) + return QNetworkConfiguration::Undefined; + + QMutexLocker locker(&d->mutex); + return d->state; } /*! @@ -303,7 +323,11 @@ QNetworkConfiguration::StateFlags QNetworkConfiguration::state() const */ QNetworkConfiguration::Purpose QNetworkConfiguration::purpose() const { - return d ? d->purpose : QNetworkConfiguration::UnknownPurpose; + if (!d) + return QNetworkConfiguration::UnknownPurpose; + + QMutexLocker locker(&d->mutex); + return d->purpose; } /*! @@ -311,7 +335,11 @@ QNetworkConfiguration::Purpose QNetworkConfiguration::purpose() const */ bool QNetworkConfiguration::isRoamingAvailable() const { - return d ? d->roamingSupported : false; + if (!d) + return false; + + QMutexLocker locker(&d->mutex); + return d->roamingSupported; } /*! @@ -322,15 +350,25 @@ bool QNetworkConfiguration::isRoamingAvailable() const QList QNetworkConfiguration::children() const { QList results; - if (type() != QNetworkConfiguration::ServiceNetwork || !isValid() ) + + if (type() != QNetworkConfiguration::ServiceNetwork || !isValid()) return results; + QMutexLocker locker(&d->mutex); + QMutableListIterator iter(d->serviceNetworkMembers); - while(iter.hasNext()) { + while (iter.hasNext()) { QNetworkConfigurationPrivatePointer p = iter.next(); + //if we have an invalid member get rid of it -> was deleted earlier on - if (!p->isValid) - iter.remove(); + { + QMutexLocker childLocker(&p->mutex); + + if (!p->isValid) { + iter.remove(); + continue; + } + } QNetworkConfiguration item; item.d = p; diff --git a/src/network/bearer/qnetworkconfiguration_p.h b/src/network/bearer/qnetworkconfiguration_p.h index 6b40946437..6908277c3e 100644 --- a/src/network/bearer/qnetworkconfiguration_p.h +++ b/src/network/bearer/qnetworkconfiguration_p.h @@ -54,7 +54,9 @@ // #include "qnetworkconfiguration.h" + #include +#include #include QT_BEGIN_NAMESPACE @@ -64,8 +66,9 @@ class QNetworkConfigurationPrivate : public QSharedData { public: QNetworkConfigurationPrivate () - : isValid(false), type(QNetworkConfiguration::Invalid), - roamingSupported(false), purpose(QNetworkConfiguration::UnknownPurpose), internet(false) + : mutex(QMutex::Recursive), type(QNetworkConfiguration::Invalid), + purpose(QNetworkConfiguration::UnknownPurpose), + isValid(false), roamingSupported(false) { } @@ -77,26 +80,27 @@ public: virtual QString bearerName() const { + QMutexLocker locker(&mutex); + return bearer; } - QString bearer; + mutable QMutex mutex; + QString bearer; QString name; - - bool isValid; QString id; + QNetworkConfiguration::StateFlags state; QNetworkConfiguration::Type type; - bool roamingSupported; QNetworkConfiguration::Purpose purpose; - bool internet; - QList serviceNetworkMembers; -private: + bool isValid; + bool roamingSupported; +private: // disallow detaching QNetworkConfigurationPrivate &operator=(const QNetworkConfigurationPrivate &other); QNetworkConfigurationPrivate(const QNetworkConfigurationPrivate &other); -- cgit v1.2.1