summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--examples/network/bearercloud/cloud.h2
-rw-r--r--examples/network/bearermonitor/sessionwidget.h2
-rw-r--r--src/network/bearer/qnetworksession.h2
-rw-r--r--src/plugins/bearer/corewlan/qcorewlanengine.h3
-rw-r--r--src/plugins/bearer/corewlan/qcorewlanengine.mm21
-rw-r--r--src/plugins/bearer/generic/qgenericengine.cpp2
-rw-r--r--src/plugins/bearer/icd/qicdengine.cpp2
-rw-r--r--src/plugins/bearer/icd/qnetworksession_impl.cpp2
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerservice.h16
-rw-r--r--src/plugins/bearer/symbian/qnetworksession_impl.cpp67
-rw-r--r--src/plugins/bearer/symbian/qnetworksession_impl.h7
-rw-r--r--src/plugins/bearer/symbian/symbianengine.cpp79
-rw-r--r--src/plugins/bearer/symbian/symbianengine.h6
-rw-r--r--tests/auto/qnetworksession/test/tst_qnetworksession.cpp255
14 files changed, 375 insertions, 91 deletions
diff --git a/examples/network/bearercloud/cloud.h b/examples/network/bearercloud/cloud.h
index 38f8aff..5d4e52a 100644
--- a/examples/network/bearercloud/cloud.h
+++ b/examples/network/bearercloud/cloud.h
@@ -56,7 +56,7 @@ class Cloud : public QObject, public QGraphicsItem
Q_INTERFACES(QGraphicsItem)
public:
- Cloud(const QNetworkConfiguration &config, QGraphicsItem *parent = 0);
+ explicit Cloud(const QNetworkConfiguration &config, QGraphicsItem *parent = 0);
~Cloud();
enum { Type = UserType + 1 };
diff --git a/examples/network/bearermonitor/sessionwidget.h b/examples/network/bearermonitor/sessionwidget.h
index cc9c067..ae5cc96 100644
--- a/examples/network/bearermonitor/sessionwidget.h
+++ b/examples/network/bearermonitor/sessionwidget.h
@@ -53,7 +53,7 @@ class SessionWidget : public QWidget, public Ui_SessionWidget
Q_OBJECT
public:
- SessionWidget(const QNetworkConfiguration &config, QWidget *parent = 0);
+ explicit SessionWidget(const QNetworkConfiguration &config, QWidget *parent = 0);
~SessionWidget();
void timerEvent(QTimerEvent *);
diff --git a/src/network/bearer/qnetworksession.h b/src/network/bearer/qnetworksession.h
index e65c177..1f25088 100644
--- a/src/network/bearer/qnetworksession.h
+++ b/src/network/bearer/qnetworksession.h
@@ -81,7 +81,7 @@ public:
InvalidConfigurationError
};
- QNetworkSession(const QNetworkConfiguration& connConfig, QObject* parent =0);
+ explicit QNetworkSession(const QNetworkConfiguration& connConfig, QObject* parent =0);
virtual ~QNetworkSession();
bool isOpen() const;
diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.h b/src/plugins/bearer/corewlan/qcorewlanengine.h
index 76574a8..ece2c60 100644
--- a/src/plugins/bearer/corewlan/qcorewlanengine.h
+++ b/src/plugins/bearer/corewlan/qcorewlanengine.h
@@ -95,11 +95,10 @@ private:
SCDynamicStoreRef storeSession;
CFRunLoopSourceRef runloopSource;
-
bool hasWifi;
protected:
- QMap<QString, QMap<QString,QString> > userProfiles;
+ QMap<QString, QMap<QString,QString> > userProfiles;
void startNetworkChangeLoop();
void getUserConfigurations();
diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm
index 5a13de9..e3778f1 100644
--- a/src/plugins/bearer/corewlan/qcorewlanengine.mm
+++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm
@@ -50,11 +50,13 @@
#include <QtCore/qstringlist.h>
#include <QtCore/qdebug.h>
+
#include <QDir>
#include <CoreWLAN/CoreWLAN.h>
#include <CoreWLAN/CWInterface.h>
#include <CoreWLAN/CWNetwork.h>
#include <CoreWLAN/CWNetwork.h>
+#include <CoreWLAN/CW8021XProfile.h>
#include <Foundation/NSEnumerator.h>
#include <Foundation/NSKeyValueObserving.h>
@@ -194,14 +196,14 @@ void QCoreWlanEngine::connectToId(const QString &id)
NSString *wantedSsid = 0;
bool okToProceed = true;
+
if(getNetworkNameFromSsid(id) != id) {
NSArray *array = [CW8021XProfile allUser8021XProfiles];
for (NSUInteger i=0; i<[array count]; ++i) {
const QString idCheck = QString::number(qHash(QLatin1String("corewlan:") + qt_mac_NSStringToQString([[array objectAtIndex:i] userDefinedName])));
const QString idCheck2 = QString::number(qHash(QLatin1String("corewlan:") + qt_mac_NSStringToQString([[array objectAtIndex:i] ssid])));
- if(id == idCheck
- || id == idCheck2) {
+ if (id == idCheck || id == idCheck2) {
QString thisName = getSsidFromNetworkName(id);
if(thisName.isEmpty()) {
wantedSsid = qt_mac_QStringToNSString(id);
@@ -263,6 +265,8 @@ void QCoreWlanEngine::connectToId(const QString &id)
emit connectionError(id, InterfaceLookupError);
locker.relock();
}
+
+ locker.unlock();
emit connectionError(id, OperationNotSupported);
}
@@ -415,7 +419,6 @@ QStringList QCoreWlanEngine::scanForSsids(const QString &interfaceName)
if (!err) {
for(uint row=0; row < [apArray count]; row++ ) {
-
apNetwork = [apArray objectAtIndex:row];
const QString networkSsid = qt_mac_NSStringToQString([apNetwork ssid]);
@@ -501,6 +504,7 @@ QStringList QCoreWlanEngine::scanForSsids(const QString &interfaceName)
while (i.hasNext()) {
i.next();
QString networkName = i.key();
+
if(!addedConfigs.contains(networkName)) {
QString interfaceName;
QMapIterator<QString, QString> ij(i.value());
@@ -688,7 +692,6 @@ QString QCoreWlanEngine::getSsidFromNetworkName(const QString &name)
QMapIterator<QString, QMap<QString,QString> > i(userProfiles);
while (i.hasNext()) {
i.next();
-
QMap<QString,QString> map = i.value();
QMapIterator<QString, QString> ij(i.value());
while (ij.hasNext()) {
@@ -697,7 +700,7 @@ QString QCoreWlanEngine::getSsidFromNetworkName(const QString &name)
if(name == i.key() || name == idCheck) {
return ij.key();
}
- }
+ }
}
return QString();
}
@@ -731,10 +734,10 @@ void QCoreWlanEngine::getUserConfigurations()
for(uint row=0; row < [wifiInterfaces count]; row++ ) {
CWInterface *wifiInterface = [CWInterface interfaceWithName: [wifiInterfaces objectAtIndex:row]];
-
+ NSString *nsInterfaceName = [wifiInterface name];
// add user configured system networks
SCDynamicStoreRef dynRef = SCDynamicStoreCreate(kCFAllocatorSystemDefault, (CFStringRef)@"Qt corewlan", nil, nil);
- NSDictionary * airportPlist = (NSDictionary *)SCDynamicStoreCopyValue(dynRef, (CFStringRef)[NSString stringWithFormat:@"Setup:/Network/Interface/%@/AirPort", [wifiInterface name]]);
+ NSDictionary * airportPlist = (NSDictionary *)SCDynamicStoreCopyValue(dynRef, (CFStringRef)[NSString stringWithFormat:@"Setup:/Network/Interface/%@/AirPort", nsInterfaceName]);
CFRelease(dynRef);
NSDictionary *prefNetDict = [airportPlist objectForKey:@"PreferredNetworks"];
@@ -744,7 +747,7 @@ void QCoreWlanEngine::getUserConfigurations()
QString thisSsid = qt_mac_NSStringToQString(ssidkey);
if(!userProfiles.contains(thisSsid)) {
QMap <QString,QString> map;
- map.insert(thisSsid, qt_mac_NSStringToQString([wifiInterface name]));
+ map.insert(thisSsid, qt_mac_NSStringToQString(nsInterfaceName));
userProfiles.insert(thisSsid, map);
}
}
@@ -778,7 +781,7 @@ void QCoreWlanEngine::getUserConfigurations()
if(!userProfiles.contains(networkName)
&& !ssid.isEmpty()) {
QMap<QString,QString> map;
- map.insert(ssid, qt_mac_NSStringToQString([wifiInterface name]));
+ map.insert(ssid, qt_mac_NSStringToQString(nsInterfaceName));
userProfiles.insert(networkName, map);
}
}
diff --git a/src/plugins/bearer/generic/qgenericengine.cpp b/src/plugins/bearer/generic/qgenericengine.cpp
index dfc74f2..c1de4e0 100644
--- a/src/plugins/bearer/generic/qgenericengine.cpp
+++ b/src/plugins/bearer/generic/qgenericengine.cpp
@@ -203,7 +203,7 @@ void QGenericEngine::doRequestUpdate()
if (interface.flags() & QNetworkInterface::IsLoopBack)
continue;
- // ignore WLAN interface handled in seperate engine
+ // ignore WLAN interface handled in separate engine
if (qGetInterfaceType(interface.name()) == QLatin1String("WLAN"))
continue;
diff --git a/src/plugins/bearer/icd/qicdengine.cpp b/src/plugins/bearer/icd/qicdengine.cpp
index f70a209..7a4cb9d 100644
--- a/src/plugins/bearer/icd/qicdengine.cpp
+++ b/src/plugins/bearer/icd/qicdengine.cpp
@@ -335,7 +335,7 @@ void QIcdEngine::doRequestUpdate()
locker.relock();
}
- if (!ap.scan.network_type.startsWith("WLAN"))
+ if (!ap.scan.network_type.startsWith(QLatin1String("WLAN")))
continue; // not a wlan AP
}
} else {
diff --git a/src/plugins/bearer/icd/qnetworksession_impl.cpp b/src/plugins/bearer/icd/qnetworksession_impl.cpp
index a2ae65c..06e0529 100644
--- a/src/plugins/bearer/icd/qnetworksession_impl.cpp
+++ b/src/plugins/bearer/icd/qnetworksession_impl.cpp
@@ -391,7 +391,7 @@ quint64 QNetworkSessionPrivateImpl::getStatistics(bool sent) const
return 0;
}
- foreach (Maemo::IcdStatisticsResult res, stats_results) {
+ foreach (const Maemo::IcdStatisticsResult &res, stats_results) {
if (res.params.network_attrs & ICD_NW_ATTR_IAPNAME) {
/* network_id is the IAP UUID */
if (QString(res.params.network_id.data()) == activeConfig.identifier()) {
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h
index 048f628..ecca537 100644
--- a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h
@@ -215,7 +215,7 @@ public:
Q_DECLARE_FLAGS(ApSecurityFlags, ApSecurityFlag);
- QNetworkManagerInterfaceAccessPoint(const QString &dbusPathName, QObject *parent = 0);
+ explicit QNetworkManagerInterfaceAccessPoint(const QString &dbusPathName, QObject *parent = 0);
~QNetworkManagerInterfaceAccessPoint();
QDBusInterface *connectionInterface() const;
@@ -248,7 +248,7 @@ class QNetworkManagerInterfaceDevice : public QObject
public:
- QNetworkManagerInterfaceDevice(const QString &deviceObjectPath, QObject *parent = 0);
+ explicit QNetworkManagerInterfaceDevice(const QString &deviceObjectPath, QObject *parent = 0);
~QNetworkManagerInterfaceDevice();
QString udi() const;
@@ -277,7 +277,8 @@ class QNetworkManagerInterfaceDeviceWired : public QObject
public:
- QNetworkManagerInterfaceDeviceWired(const QString &ifaceDevicePath, QObject *parent = 0);
+ explicit QNetworkManagerInterfaceDeviceWired(const QString &ifaceDevicePath,
+ QObject *parent = 0);
~QNetworkManagerInterfaceDeviceWired();
QDBusInterface *connectionInterface() const;
@@ -311,7 +312,8 @@ public:
Rsn = 0x20
};
- QNetworkManagerInterfaceDeviceWireless(const QString &ifaceDevicePath, QObject *parent = 0);
+ explicit QNetworkManagerInterfaceDeviceWireless(const QString &ifaceDevicePath,
+ QObject *parent = 0);
~QNetworkManagerInterfaceDeviceWireless();
QDBusObjectPath path() const;
@@ -342,7 +344,7 @@ class QNetworkManagerSettings : public QObject
public:
- QNetworkManagerSettings(const QString &settingsService, QObject *parent = 0);
+ explicit QNetworkManagerSettings(const QString &settingsService, QObject *parent = 0);
~QNetworkManagerSettings();
QDBusInterface *connectionInterface() const;
@@ -402,7 +404,7 @@ public:
Activated = 2
};
- QNetworkManagerConnectionActive(const QString &dbusPathName, QObject *parent = 0);
+ explicit QNetworkManagerConnectionActive(const QString &dbusPathName, QObject *parent = 0);
~ QNetworkManagerConnectionActive();
QDBusInterface *connectionInterface() const;
@@ -430,7 +432,7 @@ class QNetworkManagerIp4Config : public QObject
Q_OBJECT
public:
- QNetworkManagerIp4Config(const QString &dbusPathName, QObject *parent = 0);
+ explicit QNetworkManagerIp4Config(const QString &dbusPathName, QObject *parent = 0);
~QNetworkManagerIp4Config();
QStringList domains() const;
diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp
index 0737942..8910efe 100644
--- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp
+++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp
@@ -241,15 +241,24 @@ void QNetworkSessionPrivateImpl::open()
// => RConnection::ProgressNotification will be used for IAP/SNAP monitoring
iConnectionMonitor.CancelNotifications();
- // Configuration must be at least in Discovered - state for connecting purposes.
- if ((publicConfig.state() & QNetworkConfiguration::Discovered) !=
- QNetworkConfiguration::Discovered) {
+ // Configuration may have been invalidated after session creation by platform
+ // (e.g. configuration has been deleted).
+ if (!publicConfig.isValid()) {
newState(QNetworkSession::Invalid);
iError = QNetworkSession::InvalidConfigurationError;
emit QNetworkSessionPrivate::error(iError);
syncStateWithInterface();
return;
}
+ // If opening a (un)defined configuration, session emits error and enters
+ // NotAvailable -state.
+ if (publicConfig.state() == QNetworkConfiguration::Undefined ||
+ publicConfig.state() == QNetworkConfiguration::Defined) {
+ newState(QNetworkSession::NotAvailable);
+ iError = QNetworkSession::InvalidConfigurationError;
+ emit QNetworkSessionPrivate::error(iError);
+ return;
+ }
TInt error = iSocketServ.Connect();
if (error != KErrNone) {
@@ -450,15 +459,49 @@ void QNetworkSessionPrivateImpl::close(bool allowSignals)
void QNetworkSessionPrivateImpl::stop()
{
- if (!isOpen) {
- return;
+ if (!isOpen &&
+ publicConfig.isValid() &&
+ publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
+ // If the publicConfig is type of IAP, enumerate through connections at
+ // connection monitor. If publicConfig is active in that list, stop it.
+ // Otherwise there is nothing to stop. Note: because this QNetworkSession is not open,
+ // activeConfig is not usable.
+ TUint count;
+ TRequestStatus status;
+ iConnectionMonitor.GetConnectionCount(count, status);
+ User::WaitForRequest(status);
+ if (status.Int() != KErrNone) {
+ return;
+ }
+ TUint numSubConnections; // Not used but needed by GetConnectionInfo i/f
+ TUint connectionId;
+ for (TInt i = 1; i <= count; ++i) {
+ // Get (connection monitor's assigned) connection ID
+ TInt ret = iConnectionMonitor.GetConnectionInfo(i, connectionId, numSubConnections);
+ if (ret == KErrNone) {
+ SymbianNetworkConfigurationPrivate *symbianConfig =
+ toSymbianConfig(privateConfiguration(publicConfig));
+
+ QMutexLocker configLocker(&symbianConfig->mutex);
+
+ // See if connection Id matches with our Id. If so, stop() it.
+ if (symbianConfig->connectionId == connectionId) {
+ ret = iConnectionMonitor.SetBoolAttribute(connectionId,
+ 0, // subConnectionId don't care
+ KConnectionStop,
+ ETrue);
+ }
+ }
+ }
+ } else if (isOpen) {
+ // Since we are open, use RConnection to stop the interface
+ isOpen = false;
+ newState(QNetworkSession::Closing);
+ iConnection.Stop(RConnection::EStopAuthoritative);
+ isOpen = true;
+ close(false);
+ emit closed();
}
- isOpen = false;
- newState(QNetworkSession::Closing);
- iConnection.Stop(RConnection::EStopAuthoritative);
- isOpen = true;
- close(false);
- emit closed();
}
void QNetworkSessionPrivateImpl::migrate()
@@ -794,7 +837,7 @@ void QNetworkSessionPrivateImpl::RunL()
TInt statusCode = iStatus.Int();
switch (statusCode) {
- case KErrNone: // Connection created succesfully
+ case KErrNone: // Connection created successfully
{
TInt error = KErrNone;
QNetworkConfiguration newActiveConfig = activeConfiguration();
diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h
index 98d4222..35e2c58 100644
--- a/src/plugins/bearer/symbian/qnetworksession_impl.h
+++ b/src/plugins/bearer/symbian/qnetworksession_impl.h
@@ -72,12 +72,11 @@ QT_BEGIN_NAMESPACE
class ConnectionProgressNotifier;
class SymbianEngine;
+class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate, public CActive,
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
-class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate, public CActive, public MMobilityProtocolResp,
- public MConnectionMonitorObserver
-#else
-class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate, public CActive, public MConnectionMonitorObserver
+ public MMobilityProtocolResp,
#endif
+ public MConnectionMonitorObserver
{
Q_OBJECT
public:
diff --git a/src/plugins/bearer/symbian/symbianengine.cpp b/src/plugins/bearer/symbian/symbianengine.cpp
index 4d65b80..440f463 100644
--- a/src/plugins/bearer/symbian/symbianengine.cpp
+++ b/src/plugins/bearer/symbian/symbianengine.cpp
@@ -45,6 +45,16 @@
#include <commdb.h>
#include <cdbcols.h>
#include <d32dbms.h>
+#include <QEventLoop>
+#include <QTimer>
+#include <QTime> // For randgen seeding
+#include <QtCore> // For randgen seeding
+
+// #define QT_BEARERMGMT_CONFIGMGR_DEBUG
+
+#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
+#include <QDebug>
+#endif
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
#include <cmdestination.h>
@@ -100,10 +110,15 @@ QString SymbianNetworkConfigurationPrivate::bearerName() const
}
SymbianEngine::SymbianEngine(QObject *parent)
-: QBearerEngine(parent), CActive(CActive::EPriorityIdle), iFirstUpdate(true), iInitOk(true)
+: QBearerEngine(parent), CActive(CActive::EPriorityIdle), iFirstUpdate(true), iInitOk(true),
+ iIgnoringUpdates(false), iTimeToWait(0), iIgnoreEventLoop(0)
{
CActiveScheduler::Add(this);
+ // Seed the randomgenerator
+ qsrand(QTime(0,0,0).secsTo(QTime::currentTime()) + QCoreApplication::applicationPid());
+ iIgnoreEventLoop = new QEventLoop(this);
+
TRAPD(error, ipCommsDB = CCommsDatabase::NewL(EDatabaseTypeIAP));
if (error != KErrNone) {
iInitOk = false;
@@ -138,9 +153,7 @@ SymbianEngine::SymbianEngine(QObject *parent)
updateConfigurations();
updateStatesToSnaps();
-
updateAvailableAccessPoints(); // On first time updates synchronously (without WLAN scans)
-
// Start monitoring IAP and/or SNAP changes in Symbian CommsDB
startCommsDatabaseNotifications();
iFirstUpdate = false;
@@ -231,7 +244,7 @@ void SymbianEngine::updateConfigurationsL()
QList<QString> knownConfigs = accessPointConfigurations.keys();
QList<QString> knownSnapConfigs = snapConfigurations.keys();
-
+
#ifdef SNAP_FUNCTIONALITY_AVAILABLE
// S60 version is >= Series60 3rd Edition Feature Pack 2
TInt error = KErrNone;
@@ -738,8 +751,7 @@ void SymbianEngine::updateStatesToSnaps()
QMutexLocker locker(&mutex);
// Go through SNAPs and set correct state to SNAPs
- QList<QString> snapConfigIdents = snapConfigurations.keys();
- foreach (QString iface, snapConfigIdents) {
+ foreach (const QString &iface, snapConfigurations.keys()) {
bool discovered = false;
bool active = false;
QNetworkConfigurationPrivatePointer ptr = snapConfigurations.value(iface);
@@ -874,6 +886,13 @@ void SymbianEngine::RunL()
{
QMutexLocker locker(&mutex);
+ if (iIgnoringUpdates) {
+#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
+ qDebug("CommsDB event handling postponed (postpone-timer running because IAPs/SNAPs were updated very recently).");
+#endif
+ return;
+ }
+
if (iStatus != KErrCancel) {
RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int());
switch (event) {
@@ -881,16 +900,32 @@ void SymbianEngine::RunL()
case RDbNotifier::ECommit: /** A transaction has been committed. */
case RDbNotifier::ERollback: /** A transaction has been rolled back */
case RDbNotifier::ERecover: /** The database has been recovered */
- // Note that if further database events occur while a client is handling
- // a request completion, the notifier records the most significant database
- // event and this is signalled as soon as the client issues the next
- // RequestNotification() request.
- // => Stop recording notifications
- stopCommsDatabaseNotifications();
- TRAPD(error, updateConfigurationsL());
- if (error == KErrNone) {
- updateStatesToSnaps();
+#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
+ qDebug("CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int());
+#endif
+ iIgnoringUpdates = true;
+ // Other events than ECommit get lower priority. In practice with those events,
+ // we delay_before_updating methods, whereas
+ // with ECommit we _update_before_delaying the reaction to next event.
+ // Few important notes: 1) listening to only ECommit does not seem to be adequate,
+ // but updates will be missed. Hence other events are reacted upon too.
+ // 2) RDbNotifier records the most significant event, and that will be returned once
+ // we issue new RequestNotification, and hence updates will not be missed even
+ // when we are 'not reacting to them' for few seconds.
+ if (event == RDbNotifier::ECommit) {
+ TRAPD(error, updateConfigurationsL());
+ if (error == KErrNone) {
+ updateStatesToSnaps();
+ }
+ waitRandomTime();
+ } else {
+ waitRandomTime();
+ TRAPD(error, updateConfigurationsL());
+ if (error == KErrNone) {
+ updateStatesToSnaps();
+ }
}
+ iIgnoringUpdates = false; // Wait time done, allow updating again
iWaitingCommsDatabaseNotifications = true;
break;
default:
@@ -1015,6 +1050,20 @@ void SymbianEngine::EventL(const CConnMonEventBase& aEvent)
}
}
+// Waits for 1..4 seconds.
+void SymbianEngine::waitRandomTime()
+{
+ iTimeToWait = (qAbs(qrand()) % 5) * 1000;
+ if (iTimeToWait < 1000) {
+ iTimeToWait = 1000;
+ }
+#ifdef QT_BEARERMGMT_CONFIGMGR_DEBUG
+ qDebug("QNetworkConfigurationManager waiting random time: %d ms", iTimeToWait);
+#endif
+ QTimer::singleShot(iTimeToWait, iIgnoreEventLoop, SLOT(quit()));
+ iIgnoreEventLoop->exec();
+}
+
QNetworkConfigurationPrivatePointer SymbianEngine::dataByConnectionId(TUint aConnectionId)
{
QMutexLocker locker(&mutex);
diff --git a/src/plugins/bearer/symbian/symbianengine.h b/src/plugins/bearer/symbian/symbianengine.h
index e6af908..2e7ae60 100644
--- a/src/plugins/bearer/symbian/symbianengine.h
+++ b/src/plugins/bearer/symbian/symbianengine.h
@@ -53,6 +53,7 @@
#endif
class CCommsDatabase;
+class QEventLoop;
QT_BEGIN_NAMESPACE
class QTimer;
@@ -148,6 +149,7 @@ private:
void accessPointScanningReady(TBool scanSuccessful, TConnMonIapInfo iapInfo);
void startCommsDatabaseNotifications();
void stopCommsDatabaseNotifications();
+ void waitRandomTime();
QNetworkConfigurationPrivatePointer defaultConfigurationL();
TBool GetS60PlatformVersion(TUint& aMajor, TUint& aMinor) const;
@@ -170,8 +172,10 @@ private: // Data
TBool iOnline;
TBool iInitOk;
TBool iUpdateGoingOn;
+ TBool iIgnoringUpdates;
+ TUint iTimeToWait;
+ QEventLoop* iIgnoreEventLoop;
-
AccessPointsAvailabilityScanner* ipAccessPointsAvailabilityScanner;
friend class QNetworkSessionPrivate;
diff --git a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp
index 4b56f77..c08120c 100644
--- a/tests/auto/qnetworksession/test/tst_qnetworksession.cpp
+++ b/tests/auto/qnetworksession/test/tst_qnetworksession.cpp
@@ -42,6 +42,7 @@
#include <QtTest/QtTest>
#include <QLocalServer>
#include <QLocalSocket>
+#include <QTimer>
#include "../../qbearertestcommon.h"
#include <qnetworkconfigmanager.h>
#include <qnetworksession.h>
@@ -53,6 +54,9 @@
QT_USE_NAMESPACE
+// Can be used to configure tests that require manual attention (such as roaming)
+//#define QNETWORKSESSION_MANUAL_TESTS 1
+
Q_DECLARE_METATYPE(QNetworkConfiguration)
Q_DECLARE_METATYPE(QNetworkConfiguration::Type);
Q_DECLARE_METATYPE(QNetworkSession::State);
@@ -75,6 +79,9 @@ private slots:
void repeatedOpenClose();
void roamingErrorCodes();
+
+ void sessionStop_data();
+ void sessionStop();
void sessionProperties_data();
void sessionProperties();
@@ -106,6 +113,7 @@ private:
// Helper functions
bool openSession(QNetworkSession *session);
bool closeSession(QNetworkSession *session, bool lastSessionOnConfiguration = true);
+void updateConfigurations();
QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfiguration::Type configType);
void tst_QNetworkSession::initTestCase()
@@ -226,14 +234,13 @@ void tst_QNetworkSession::cleanupTestCase()
void tst_QNetworkSession::invalidSession()
{
- // Verify that session created with invalid configuration remains in invalid state
+ // 1. Verify that session created with invalid configuration remains in invalid state
QNetworkSession session(QNetworkConfiguration(), 0);
QVERIFY(!session.isOpen());
QVERIFY(session.state() == QNetworkSession::Invalid);
QVERIFY(session.error() == QNetworkSession::InvalidConfigurationError);
- // Verify that opening session with invalid configuration both 1) emits invalidconfigurationerror
- // and 2) sets session's state as invalid.
+ // 2. Verify that opening session with invalid configuration both 1) emits invalidconfigurationerror and 2) sets session's state as invalid.
QSignalSpy errorSpy(&session, SIGNAL(error(QNetworkSession::SessionError)));
session.open();
session.waitForOpened(1000); // Should bail out right away
@@ -244,24 +251,56 @@ void tst_QNetworkSession::invalidSession()
QVERIFY(session.error() == QNetworkSession::InvalidConfigurationError);
QVERIFY(session.state() == QNetworkSession::Invalid);
- // Check same thing with a config from platform (there are subtle differences
- // because emtpy configuration does not have private pointer). Test with config
- // in '(un)defined' state
- QList<QNetworkConfiguration> allConfigs = manager.allConfigurations();
- foreach(QNetworkConfiguration config, allConfigs) {
- if ((config.state() & QNetworkConfiguration::Discovered) != QNetworkConfiguration::Discovered) {
- QNetworkSession session2(config);
- QSignalSpy errorSpy2(&session2, SIGNAL(error(QNetworkSession::SessionError)));
- session2.open();
- session2.waitForOpened(1000); // Should bail out right away
- QVERIFY(errorSpy2.count() == 1);
- QNetworkSession::SessionError error2 =
- qvariant_cast<QNetworkSession::SessionError> (errorSpy2.first().at(0));
- QVERIFY(error2 == QNetworkSession::InvalidConfigurationError);
- QVERIFY(session2.state() == QNetworkSession::Invalid);
- break; // Once is enough
- }
+#ifdef QNETWORKSESSION_MANUAL_TESTS
+ QNetworkConfiguration definedConfig = suitableConfiguration("WLAN",QNetworkConfiguration::InternetAccessPoint);
+ if (definedConfig.isValid()) {
+ // 3. Verify that opening a session with defined configuration emits error and enters notavailable-state
+ // TODO these timer waits should be changed to waiting appropriate signals, now these wait excessively
+ qDebug() << "Shutdown WLAN IAP (waiting 60 seconds): " << definedConfig.name();
+ QTest::qWait(60000);
+ // Shutting down WLAN should bring back to defined -state.
+ QVERIFY((definedConfig.state() & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined);
+ QNetworkSession definedSession(definedConfig);
+ QSignalSpy errorSpy(&definedSession, SIGNAL(error(QNetworkSession::SessionError)));
+ QNetworkSession::SessionError sessionError;
+
+ definedSession.open();
+
+ QVERIFY(definedConfig.isValid()); // Session remains valid
+ QVERIFY(definedSession.state() == QNetworkSession::NotAvailable); // State is not available because WLAN is not in coverage
+ QVERIFY(!errorSpy.isEmpty()); // Session tells with error about invalidated configuration
+ sessionError = qvariant_cast<QNetworkSession::SessionError> (errorSpy.first().at(0));
+ qDebug() << "Error code is: " << sessionError;
+ QVERIFY(sessionError == QNetworkSession::InvalidConfigurationError);
+
+ qDebug() << "Turn the WLAN IAP back on (waiting 60 seconds): " << definedConfig.name();
+ QTest::qWait(60000);
+ updateConfigurations();
+
+ QVERIFY(definedConfig.state() == QNetworkConfiguration::Discovered);
}
+
+ QNetworkConfiguration invalidatedConfig = suitableConfiguration("WLAN",QNetworkConfiguration::InternetAccessPoint);
+ if (invalidatedConfig.isValid()) {
+ // 4. Verify that invalidating a session after its successfully configured works
+ QNetworkSession invalidatedSession(invalidatedConfig);
+ QSignalSpy errorSpy(&invalidatedSession, SIGNAL(error(QNetworkSession::SessionError)));
+ QNetworkSession::SessionError sessionError;
+
+ qDebug() << "Delete the WLAN IAP from phone now (waiting 60 seconds): " << invalidatedConfig.name();
+ QTest::qWait(60000);
+
+ invalidatedSession.open();
+ QVERIFY(!invalidatedConfig.isValid());
+ QVERIFY(invalidatedSession.state() == QNetworkSession::Invalid);
+ QVERIFY(!errorSpy.isEmpty());
+
+ sessionError = qvariant_cast<QNetworkSession::SessionError> (errorSpy.first().at(0));
+ QVERIFY(sessionError == QNetworkSession::InvalidConfigurationError);
+ qDebug() << "Add the WLAN IAP back (waiting 60 seconds): " << invalidatedConfig.name();
+ QTest::qWait(60000);
+ }
+#endif
}
void tst_QNetworkSession::sessionProperties_data()
@@ -382,7 +421,6 @@ void tst_QNetworkSession::repeatedOpenClose() {
}
void tst_QNetworkSession::roamingErrorCodes() {
-
#ifndef Q_OS_SYMBIAN
QSKIP("Roaming supported on Symbian.", SkipAll);
#else
@@ -410,8 +448,9 @@ void tst_QNetworkSession::roamingErrorCodes() {
QVERIFY(iapSession.state() == QNetworkSession::Disconnected);
QVERIFY(adminIapSession.state() == QNetworkSession::Disconnected);
#endif // Q_OS_SYMBIAN
- /*
- // Check for roaming error. Challenging to automate, therefore commented out.
+
+#ifdef QNETWORKSESSION_MANUAL_TESTS
+ // Check for roaming error.
// Case requires that you have controllable WLAN in Internet SNAP (only).
QNetworkConfiguration snapConfig = suitableConfiguration("bearer_not_relevant_with_snaps", QNetworkConfiguration::ServiceNetwork);
if (!snapConfig.isValid()) {
@@ -439,7 +478,144 @@ void tst_QNetworkSession::roamingErrorCodes() {
error = qvariant_cast<QNetworkSession::SessionError>(errorSpy2.first().at(0));
QVERIFY(error == QNetworkSession::SessionAbortedError);
QVERIFY(iapSession2.state() == QNetworkSession::Disconnected);
- */
+#endif
+}
+
+
+void tst_QNetworkSession::sessionStop_data() {
+ QTest::addColumn<QString>("bearerType");
+ QTest::addColumn<QNetworkConfiguration::Type>("configurationType");
+
+ QTest::newRow("SNAP") << "bearer_type_not_relevant_with_SNAPs" << QNetworkConfiguration::ServiceNetwork;
+ QTest::newRow("WLAN_IAP") << "WLAN" << QNetworkConfiguration::InternetAccessPoint;
+ QTest::newRow("Cellular_IAP") << "cellular" << QNetworkConfiguration::InternetAccessPoint;
+}
+
+void tst_QNetworkSession::sessionStop()
+{
+#ifndef Q_OS_SYMBIAN
+ QSKIP("Testcase contains mainly Symbian specific checks, because it is only platform to really support interface (IAP-level) Stop.", SkipAll);
+#endif
+ QFETCH(QString, bearerType);
+ QFETCH(QNetworkConfiguration::Type, configurationType);
+
+ int configWaitdelayInMs = 2000;
+
+ QNetworkConfiguration config = suitableConfiguration(bearerType, configurationType);
+ if (!config.isValid()) {
+ QSKIP("No suitable configurations, skipping this round of session stop test.", SkipSingle);
+ }
+ qDebug() << "Using following configuration to open and stop a session: " << config.name();
+
+ QNetworkSession openedSession(config);
+ QNetworkSession closedSession(config);
+ QNetworkSession innocentSession(config);
+ QNetworkConfigurationManager mgr;
+
+ QSignalSpy closedSessionOpenedSpy(&closedSession, SIGNAL(opened()));
+ QSignalSpy closedSessionClosedSpy(&closedSession, SIGNAL(closed()));
+ QSignalSpy closedSessionStateChangedSpy(&closedSession, SIGNAL(stateChanged(QNetworkSession::State)));
+ QSignalSpy closedErrorSpy(&closedSession, SIGNAL(error(QNetworkSession::SessionError)));
+
+ QSignalSpy innocentSessionClosedSpy(&innocentSession, SIGNAL(closed()));
+ QSignalSpy innocentSessionStateChangedSpy(&innocentSession, SIGNAL(stateChanged(QNetworkSession::State)));
+ QSignalSpy innocentErrorSpy(&innocentSession, SIGNAL(error(QNetworkSession::SessionError)));
+ QNetworkSession::SessionError sessionError;
+
+ // 1. Verify that stopping an opened session works (the simplest usecase).
+ qDebug("----------1. Verify that stopping an opened session works (the simplest usecase)");
+ QSignalSpy configChangeSpy(&mgr, SIGNAL(configurationChanged(QNetworkConfiguration)));
+ QVERIFY(openSession(&openedSession));
+ qDebug("Waiting for %d ms to get all configurationChange signals from platform.", configWaitdelayInMs);
+ // Clear signals caused by opening
+ closedSessionOpenedSpy.clear();
+ closedSessionClosedSpy.clear();
+ closedSessionStateChangedSpy.clear();
+ closedErrorSpy.clear();
+ openedSession.stop();
+
+ QVERIFY(openedSession.state() == QNetworkSession::Disconnected);
+ QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals
+ QVERIFY(config.state() != QNetworkConfiguration::Active);
+
+ // 2. Verify that stopping a session based on non-connected configuration does nothing
+ qDebug("----------2. Verify that stopping a session based on non-connected configuration does nothing");
+ QNetworkSession::State closedSessionOriginalState = closedSession.state();
+ // Clear all possible signals
+ configChangeSpy.clear();
+ closedSessionOpenedSpy.clear();
+ closedSessionClosedSpy.clear();
+ closedSessionStateChangedSpy.clear();
+ closedErrorSpy.clear();
+
+ closedSession.stop();
+ qDebug("Waiting for %d ms to get all configurationChange signals from platform.", configWaitdelayInMs);
+ QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals
+
+ QVERIFY(closedSessionOpenedSpy.isEmpty());
+ QVERIFY(closedSessionClosedSpy.isEmpty());
+ QVERIFY(closedSessionStateChangedSpy.isEmpty());
+ QVERIFY(closedErrorSpy.isEmpty());
+ QVERIFY(closedSession.state() == closedSessionOriginalState); // State remains
+
+ // 3. Check that stopping a opened session affects also other opened session based on the same configuration.
+ if (config.type() == QNetworkConfiguration::InternetAccessPoint) {
+ qDebug("----------3. Check that stopping a opened session affects also other opened session based on the same configuration.");
+ QVERIFY(openSession(&openedSession));
+ QVERIFY(openSession(&innocentSession));
+
+ configChangeSpy.clear();
+ innocentSessionClosedSpy.clear();
+ innocentSessionStateChangedSpy.clear();
+ innocentErrorSpy.clear();
+
+ openedSession.stop();
+ qDebug("Waiting for %d ms to get all configurationChange signals from platform.", configWaitdelayInMs);
+ QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals
+
+ QVERIFY(!innocentSessionClosedSpy.isEmpty());
+ QVERIFY(!innocentSessionStateChangedSpy.isEmpty());
+ QVERIFY(!innocentErrorSpy.isEmpty());
+ QVERIFY(innocentSession.state() == QNetworkSession::Disconnected);
+ QVERIFY(openedSession.state() == QNetworkSession::Disconnected);
+ sessionError = qvariant_cast<QNetworkSession::SessionError>(innocentErrorSpy.first().at(0));
+ QVERIFY(sessionError == QNetworkSession::SessionAbortedError);
+
+ innocentSessionClosedSpy.clear();
+ innocentSessionStateChangedSpy.clear();
+ innocentErrorSpy.clear();
+ } else {
+ qDebug("----------3. Skip for SNAP configuration.");
+ }
+ // 4. Check that stopping a non-opened session stops the other session based on the
+ // same configuration if configuration is IAP. Stopping closed SNAP session has no impact on other opened SNAP session.
+ if (config.type() == QNetworkConfiguration::ServiceNetwork) {
+ qDebug("----------4. Skip for SNAP configuration.");
+ } else if (config.type() == QNetworkConfiguration::InternetAccessPoint) {
+ qDebug("----------4. Check that stopping a non-opened session stops the other session based on the same configuration");
+ QVERIFY(openSession(&innocentSession));
+ qDebug("Waiting for %d ms after open to make sure all platform indications are propagated", configWaitdelayInMs);
+ QTest::qWait(configWaitdelayInMs);
+ closedSession.stop();
+ qDebug("Waiting for %d ms to get all configurationChange signals from platform..", configWaitdelayInMs);
+ QTest::qWait(configWaitdelayInMs); // Wait to get all relevant configurationChange() signals
+
+ QVERIFY(!innocentSessionClosedSpy.isEmpty());
+ QVERIFY(!innocentSessionStateChangedSpy.isEmpty());
+ QVERIFY(!innocentErrorSpy.isEmpty());
+ QVERIFY(innocentSession.state() == QNetworkSession::Disconnected);
+ QVERIFY(closedSession.state() == QNetworkSession::Disconnected);
+ sessionError = qvariant_cast<QNetworkSession::SessionError>(innocentErrorSpy.first().at(0));
+ QVERIFY(sessionError == QNetworkSession::SessionAbortedError);
+ QVERIFY(config.state() == QNetworkConfiguration::Discovered);
+ }
+
+ // 5. Sanity check that stopping invalid session does not crash
+ qDebug("----------5. Sanity check that stopping invalid session does not crash");
+ QNetworkSession invalidSession(QNetworkConfiguration(), 0);
+ QVERIFY(invalidSession.state() == QNetworkSession::Invalid);
+ invalidSession.stop();
+ QVERIFY(invalidSession.state() == QNetworkSession::Invalid);
}
void tst_QNetworkSession::userChoiceSession_data()
@@ -796,14 +972,13 @@ void tst_QNetworkSession::sessionOpenCloseStop()
state = qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(0).at(0));
if (state == QNetworkSession::Roaming) {
QTRY_VERIFY(!errorSpy.isEmpty() || stateChangedSpy.count() > 1);
- if (stateChangedSpy.count() > 1) {
- state = qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(1).at(0));
- if (state == QNetworkSession::Connected) {
- roamedSuccessfully = true;
- QTRY_VERIFY(session2.state() == QNetworkSession::Disconnected);
- }
+ if (stateChangedSpy.count() > 1 &&
+ qvariant_cast<QNetworkSession::State>(stateChangedSpy.at(1).at(0)) ==
+ QNetworkSession::Connected) {
+ roamedSuccessfully = true;
}
}
+
if (roamedSuccessfully) {
QString configId = session.sessionProperty("ActiveConfiguration").toString();
QNetworkConfiguration config = manager.configurationFromIdentifier(configId);
@@ -838,8 +1013,9 @@ void tst_QNetworkSession::sessionOpenCloseStop()
}
QTRY_VERIFY(!sessionClosedSpy.isEmpty());
- QVERIFY(session.state() == QNetworkSession::Disconnected);
- QVERIFY(session2.state() == QNetworkSession::Disconnected);
+
+ QTRY_VERIFY(session.state() == QNetworkSession::Disconnected);
+ QTRY_VERIFY(session2.state() == QNetworkSession::Disconnected);
}
QVERIFY(errorSpy2.isEmpty());
@@ -1059,6 +1235,7 @@ void tst_QNetworkSession::outOfProcessSession()
// Ignores configurations in other than 'discovered' -state. Returns invalid (QNetworkConfiguration())
// if none found.
QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfiguration::Type configType) {
+
// Refresh configurations and derive configurations matching given parameters.
QNetworkConfigurationManager mgr;
QSignalSpy updateSpy(&mgr, SIGNAL(updateCompleted()));
@@ -1099,6 +1276,15 @@ QNetworkConfiguration suitableConfiguration(QString bearerType, QNetworkConfigur
}
}
+// A convinience-function: updates configurations and waits that they are updated.
+void updateConfigurations()
+{
+ QNetworkConfigurationManager mgr;
+ QSignalSpy updateSpy(&mgr, SIGNAL(updateCompleted()));
+ mgr.updateConfigurations();
+ QTRY_NOOP(updateSpy.count() == 1);
+}
+
// A convinience function for test-cases: opens the given configuration and return
// true if it was done gracefully.
bool openSession(QNetworkSession *session) {
@@ -1198,8 +1384,8 @@ bool closeSession(QNetworkSession *session, bool lastSessionOnConfiguration) {
return false;
}
if (lastSessionOnConfiguration &&
- session->configuration().state() != QNetworkConfiguration::Discovered) {
- qDebug("tst_QNetworkSession::closeSession() failure: session's configuration is not back in 'Discovered' -state.");
+ session->configuration().state() == QNetworkConfiguration::Active) {
+ qDebug("tst_QNetworkSession::closeSession() failure: session's configuration is still in active state.");
return false;
}
return true;
@@ -1270,4 +1456,3 @@ void tst_QNetworkSession::sessionAutoClose()
QTEST_MAIN(tst_QNetworkSession)
#include "tst_qnetworksession.moc"
-