diff options
Diffstat (limited to 'src/plugins/bearer')
20 files changed, 444 insertions, 342 deletions
diff --git a/src/plugins/bearer/bearer.pro b/src/plugins/bearer/bearer.pro index 00be80e..f95e8af 100644 --- a/src/plugins/bearer/bearer.pro +++ b/src/plugins/bearer/bearer.pro @@ -1,14 +1,18 @@ TEMPLATE = subdirs -!maemo6:contains(QT_CONFIG, dbus) { - SUBDIRS += networkmanager generic +contains(QT_CONFIG, dbus) { + contains(QT_CONFIG, icd) { + SUBDIRS += icd + } else { + SUBDIRS += networkmanager generic + } } + #win32:SUBDIRS += nla win32:SUBDIRS += generic win32:!wince*:SUBDIRS += nativewifi macx:contains(QT_CONFIG, corewlan):SUBDIRS += corewlan macx:SUBDIRS += generic symbian:SUBDIRS += symbian -maemo6:contains(QT_CONFIG, dbus):SUBDIRS += icd isEmpty(SUBDIRS):SUBDIRS += generic diff --git a/src/plugins/bearer/corewlan/corewlan.pro b/src/plugins/bearer/corewlan/corewlan.pro index 50c72b2..9786c03 100644 --- a/src/plugins/bearer/corewlan/corewlan.pro +++ b/src/plugins/bearer/corewlan/corewlan.pro @@ -6,7 +6,7 @@ LIBS += -framework Foundation -framework SystemConfiguration contains(QT_CONFIG, corewlan) { isEmpty(QMAKE_MAC_SDK)|contains(QMAKE_MAC_SDK, "/Developer/SDKs/MacOSX10.6.sdk") { - LIBS += -framework CoreWLAN + LIBS += -framework CoreWLAN -framework Security DEFINES += MAC_SDK_10_6 } } diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.h b/src/plugins/bearer/corewlan/qcorewlanengine.h index 76574a8..5e93193 100644 --- a/src/plugins/bearer/corewlan/qcorewlanengine.h +++ b/src/plugins/bearer/corewlan/qcorewlanengine.h @@ -78,8 +78,6 @@ public: QNetworkConfigurationPrivatePointer defaultConfiguration(); - bool getWifiInterfaces(); - bool requiresPolling() const; private Q_SLOTS: @@ -95,16 +93,16 @@ private: SCDynamicStoreRef storeSession; CFRunLoopSourceRef runloopSource; - bool hasWifi; protected: - QMap<QString, QMap<QString,QString> > userProfiles; + QMap<QString, QMap<QString,QString> > userProfiles; void startNetworkChangeLoop(); void getUserConfigurations(); QString getNetworkNameFromSsid(const QString &ssid); QString getSsidFromNetworkName(const QString &name); + QStringList foundNetwork(const QString &id, const QString &ssid, const QNetworkConfiguration::StateFlags state, const QString &interfaceName); }; QT_END_NAMESPACE diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm index 60c6fbd..a366d00 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> @@ -65,8 +67,6 @@ #include <private/qt_cocoa_helpers_mac_p.h> #include "private/qcore_mac_p.h" -QMap <QString, QString> networkInterfaces; - @interface QNSListener : NSObject { NSNotificationCenter *center; @@ -84,6 +84,8 @@ QMap <QString, QString> networkInterfaces; @end @implementation QNSListener +@synthesize engine; + - (id) init { [locker lock]; @@ -126,12 +128,6 @@ QNSListener *listener = 0; QT_BEGIN_NAMESPACE - -static QString qGetInterfaceType(const QString &interfaceString) -{ - return networkInterfaces.value(interfaceString, QLatin1String("WLAN")); -} - void networkChangeCallback(SCDynamicStoreRef/* store*/, CFArrayRef changedKeys, void *info) { for ( long i = 0; i < CFArrayGetCount(changedKeys); i++) { @@ -189,85 +185,147 @@ void QCoreWlanEngine::connectToId(const QString &id) QMacCocoaAutoReleasePool pool; QString interfaceString = getInterfaceFromId(id); - if(networkInterfaces.value(interfaceString) == "WLAN") { - CWInterface *wifiInterface = [CWInterface interfaceWithName: qt_mac_QStringToNSString(interfaceString)]; - - if([wifiInterface power]) { - NSError *err = nil; - NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0]; - - 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) { - QString thisName = getSsidFromNetworkName(id); - if(thisName.isEmpty()) { - wantedSsid = qt_mac_QStringToNSString(id); - } else { - wantedSsid = qt_mac_QStringToNSString(thisName); - } - okToProceed = false; - [params setValue: [array objectAtIndex:i] forKey:kCWAssocKey8021XProfile]; - break; - } - } - } + CWInterface *wifiInterface = + [CWInterface interfaceWithName: qt_mac_QStringToNSString(interfaceString)]; - if(okToProceed) { - NSUInteger index = 0; + if ([wifiInterface power]) { + NSError *err = nil; + NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0]; - CWConfiguration *userConfig = [ wifiInterface configuration]; - NSSet *remNets = [userConfig rememberedNetworks]; - NSEnumerator *enumerator = [remNets objectEnumerator]; - CWWirelessProfile *wProfile; + QString wantedSsid; - while ((wProfile = [enumerator nextObject])) { - const QString idCheck = QString::number(qHash(QLatin1String("corewlan:") + qt_mac_NSStringToQString([wProfile ssid]))); + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); - if(id == idCheck) { - wantedSsid = [wProfile ssid]; - [params setValue: [wProfile passphrase] forKey: kCWAssocKeyPassphrase]; - break; - } - index++; + const QString idHash = QString::number(qHash(QLatin1String("corewlan:") + ptr->name)); + const QString idHash2 = QString::number(qHash(QLatin1String("corewlan:") + getNetworkNameFromSsid(ptr->name))); + + bool using8021X = false; + if (idHash2 != id) { + NSArray *array = [CW8021XProfile allUser8021XProfiles]; + + for (NSUInteger i = 0; i < [array count]; ++i) { + const QString networkNameHashCheck = QString::number(qHash(QLatin1String("corewlan:") + qt_mac_NSStringToQString([[array objectAtIndex:i] userDefinedName]))); + + const QString ssidHash = QString::number(qHash(QLatin1String("corewlan:") + qt_mac_NSStringToQString([[array objectAtIndex:i] ssid]))); + + if (id == networkNameHashCheck || id == ssidHash) { + const QString thisName = getSsidFromNetworkName(id); + if (thisName.isEmpty()) + wantedSsid = id; + else + wantedSsid = thisName; + + [params setValue: [array objectAtIndex:i] forKey:kCWAssocKey8021XProfile]; + using8021X = true; + break; } } + } - NSDictionary *parametersDict = nil; - NSArray *apArray = [NSMutableArray arrayWithArray:[wifiInterface scanForNetworksWithParameters:parametersDict error:&err]]; + if (!using8021X) { + QString wantedNetwork; + QMapIterator<QString, QMap<QString,QString> > i(userProfiles); + while (i.hasNext()) { + i.next(); + wantedNetwork = i.key(); + const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") + wantedNetwork)); + if (id == networkNameHash) { + wantedSsid = getSsidFromNetworkName(wantedNetwork); + break; + } + } + } + NSDictionary *scanParameters = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:YES], kCWScanKeyMerge, + [NSNumber numberWithInteger:100], kCWScanKeyRestTime, + qt_mac_QStringToNSString(wantedSsid), kCWScanKeySSID, + nil]; + + NSArray *scanArray = [NSArray arrayWithArray:[wifiInterface scanForNetworksWithParameters:scanParameters error:&err]]; + + if(!err) { + for(uint row=0; row < [scanArray count]; row++ ) { + CWNetwork *apNetwork = [scanArray objectAtIndex:row]; + + if(wantedSsid == qt_mac_NSStringToQString([apNetwork ssid])) { + + if(!using8021X) { + SecKeychainAttribute attributes[3]; + + NSString *account = [apNetwork ssid]; + NSString *keyKind = @"AirPort network password"; + NSString *keyName = account; + + attributes[0].tag = kSecAccountItemAttr; + attributes[0].data = (void *)[account UTF8String]; + attributes[0].length = [account length]; + + attributes[1].tag = kSecDescriptionItemAttr; + attributes[1].data = (void *)[keyKind UTF8String]; + attributes[1].length = [keyKind length]; + + attributes[2].tag = kSecLabelItemAttr; + attributes[2].data = (void *)[keyName UTF8String]; + attributes[2].length = [keyName length]; + + SecKeychainAttributeList attributeList = {3,attributes}; + + SecKeychainSearchRef searchRef; + OSErr result = SecKeychainSearchCreateFromAttributes(NULL, kSecGenericPasswordItemClass, &attributeList, &searchRef); + + NSString *password = @""; + SecKeychainItemRef searchItem; + + if (SecKeychainSearchCopyNext(searchRef, &searchItem) == noErr) { + UInt32 realPasswordLength; + SecKeychainAttribute attributesW[8]; + attributesW[0].tag = kSecAccountItemAttr; + SecKeychainAttributeList listW = {1,attributesW}; + char *realPassword; + OSStatus status = SecKeychainItemCopyContent(searchItem, NULL, &listW, &realPasswordLength,(void **)&realPassword); + + if (status == noErr) { + if (realPassword != NULL) { + + QByteArray pBuf; + pBuf.resize(realPasswordLength); + pBuf.prepend(realPassword); + pBuf.insert(realPasswordLength,'\0'); + + password = [NSString stringWithUTF8String:pBuf]; + } + SecKeychainItemFreeContent(&listW, realPassword); + } + + CFRelease(searchItem); + } else { + qDebug() << "SecKeychainSearchCopyNext error"; + } + [params setValue: password forKey: kCWAssocKeyPassphrase]; + } // end using8021X - if(!err) { - for(uint row=0; row < [apArray count]; row++ ) { - CWNetwork *apNetwork = [apArray objectAtIndex:row]; - if([[apNetwork ssid] compare:wantedSsid] == NSOrderedSame) { - bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err]; + bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err]; + + if(!err) { if(!result) { emit connectionError(id, ConnectError); } else { return; } + } else { + qDebug() <<"associate ERROR"<< qt_mac_NSStringToQString([err localizedDescription ]); } } - } else { - qDebug() <<"ERROR"<< qt_mac_NSStringToQString([err localizedDescription ]); - } - - emit connectionError(id, InterfaceLookupError); + } //end scan network } else { - // not wifi + qDebug() <<"scan ERROR"<< qt_mac_NSStringToQString([err localizedDescription ]); } - locker.unlock(); emit connectionError(id, InterfaceLookupError); - locker.relock(); } - emit connectionError(id, OperationNotSupported); + + locker.unlock(); + emit connectionError(id, InterfaceLookupError); } void QCoreWlanEngine::disconnectFromId(const QString &id) @@ -275,24 +333,17 @@ void QCoreWlanEngine::disconnectFromId(const QString &id) QMutexLocker locker(&mutex); QString interfaceString = getInterfaceFromId(id); - if(networkInterfaces.value(getInterfaceFromId(id)) == "WLAN") { //wifi only for now -#if defined(MAC_SDK_10_6) - QMacCocoaAutoReleasePool pool; - CWInterface *wifiInterface = [CWInterface interfaceWithName: qt_mac_QStringToNSString(interfaceString)]; - [wifiInterface disassociate]; - if([[wifiInterface interfaceState]intValue] != kCWInterfaceStateInactive) { - locker.unlock(); - emit connectionError(id, DisconnectionError); - locker.relock(); - } - return; -#endif - } else { + QMacCocoaAutoReleasePool pool; - } + CWInterface *wifiInterface = + [CWInterface interfaceWithName: qt_mac_QStringToNSString(interfaceString)]; - locker.unlock(); - emit connectionError(id, OperationNotSupported); + [wifiInterface disassociate]; + if ([[wifiInterface interfaceState]intValue] != kCWInterfaceStateInactive) { + locker.unlock(); + emit connectionError(id, DisconnectionError); + locker.relock(); + } } void QCoreWlanEngine::requestUpdate() @@ -305,81 +356,15 @@ void QCoreWlanEngine::doRequestUpdate() { QMutexLocker locker(&mutex); - getWifiInterfaces(); + QMacCocoaAutoReleasePool pool; QStringList previous = accessPointConfigurations.keys(); - QMapIterator<QString, QString> i(networkInterfaces); - while (i.hasNext()) { - i.next(); - if (i.value() == QLatin1String("WLAN")) { - QStringList added = scanForSsids(i.key()); - while (!added.isEmpty()) { - previous.removeAll(added.takeFirst()); - } - } - - QNetworkInterface interface = QNetworkInterface::interfaceFromName(i.key()); - - if (!interface.isValid()) - continue; - - uint identifier; - if (interface.index()) - identifier = qHash(QLatin1String("corewlan:") + QString::number(interface.index())); - else - identifier = qHash(QLatin1String("corewlan:") + interface.hardwareAddress()); - - const QString id = QString::number(identifier); - - previous.removeAll(id); - - QString name = interface.humanReadableName(); - if (name.isEmpty()) - name = interface.name(); - - QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined; - - if (interface.flags() && QNetworkInterface::IsRunning) - state = QNetworkConfiguration::Defined; - - if (!interface.addressEntries().isEmpty()) - state = QNetworkConfiguration::Active; - - if (accessPointConfigurations.contains(id)) { //handle only scanned AP's - QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); - - bool changed = false; - - ptr->mutex.lock(); - - if (!ptr->isValid) { - ptr->isValid = true; - changed = true; - } - - if (ptr->name != name) { - ptr->name = name; - changed = true; - } - - if (ptr->id != id) { - ptr->id = id; - changed = true; - } - - if (ptr->state != state) { - ptr->state = state; - changed = true; - } - - ptr->mutex.unlock(); - - if (changed) { - locker.unlock(); - emit configurationChanged(ptr); - locker.relock(); - } + NSArray *wifiInterfaces = [CWInterface supportedInterfaces]; + for (uint row = 0; row < [wifiInterfaces count]; ++row) { + foreach (const QString &interface, + scanForSsids(qt_mac_NSStringToQString([wifiInterfaces objectAtIndex:row]))) { + previous.removeAll(interface); } } @@ -413,13 +398,16 @@ QStringList QCoreWlanEngine::scanForSsids(const QString &interfaceName) if([currentInterface power]) { NSError *err = nil; - NSDictionary *parametersDict = nil; + NSDictionary *parametersDict = [NSDictionary dictionaryWithObjectsAndKeys: + [NSNumber numberWithBool:YES], kCWScanKeyMerge, + [NSNumber numberWithInt:kCWScanTypeFast], kCWScanKeyScanType, // get the networks in the scan cache + [NSNumber numberWithInteger:100], kCWScanKeyRestTime, nil]; NSArray* apArray = [currentInterface scanForNetworksWithParameters:parametersDict error:&err]; CWNetwork *apNetwork; if (!err) { - for(uint row=0; row < [apArray count]; row++ ) { + for(uint row=0; row < [apArray count]; row++ ) { apNetwork = [apArray objectAtIndex:row]; const QString networkSsid = qt_mac_NSStringToQString([apNetwork ssid]); @@ -441,106 +429,109 @@ QStringList QCoreWlanEngine::scanForSsids(const QString &interfaceName) state = QNetworkConfiguration::Undefined; } } + found.append(foundNetwork(id, networkSsid, state, interfaceName)); - if (accessPointConfigurations.contains(id)) { - QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); - - bool changed = false; - - ptr->mutex.lock(); - - if (!ptr->isValid) { - ptr->isValid = true; - changed = true; - } - - if (ptr->name != networkSsid) { - ptr->name = networkSsid; - changed = true; - } - - if (ptr->id != id) { - ptr->id = id; - changed = true; - } - - if (ptr->state != state) { - ptr->state = state; - changed = true; - } - - ptr->mutex.unlock(); - - if (changed) { - locker.unlock(); - emit configurationChanged(ptr); - locker.relock(); - } - addedConfigs << networkSsid; - } else { - QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate); - - found.append(id); - ptr->name = networkSsid; - ptr->isValid = true; - ptr->id = id; - ptr->state = state; - ptr->type = QNetworkConfiguration::InternetAccessPoint; - ptr->bearer = QLatin1String("WLAN"); - - accessPointConfigurations.insert(ptr->id, ptr); - configurationInterface.insert(ptr->id, interfaceName); - - locker.unlock(); - emit configurationAdded(ptr); - locker.relock(); - addedConfigs << networkSsid; - } - } - } - } + } //end row + } //end error + } // endwifi power // add known configurations that are not around. QMapIterator<QString, QMap<QString,QString> > i(userProfiles); while (i.hasNext()) { i.next(); + QString networkName = i.key(); - if(!addedConfigs.contains(networkName)) { + const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkName)); + + if(!found.contains(id)) { + QString networkSsid = getSsidFromNetworkName(networkName); + const QString ssidId = QString::number(qHash(QLatin1String("corewlan:") + networkSsid)); + QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined; QString interfaceName; QMapIterator<QString, QString> ij(i.value()); while (ij.hasNext()) { ij.next(); interfaceName = ij.value(); } - QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate); - const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkName)); - found.append(id); - - ptr->name = networkName; - ptr->isValid = true; - ptr->id = id; - ptr->bearer = QLatin1String("WLAN"); - ptr->type = QNetworkConfiguration::InternetAccessPoint; - QString ssid = getSsidFromNetworkName(networkName); if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { - if( ssid == qt_mac_NSStringToQString([currentInterface ssid])) { - ptr->state = QNetworkConfiguration::Active; + if( networkSsid == qt_mac_NSStringToQString([currentInterface ssid])) { + state = QNetworkConfiguration::Active; } } - - if(!ptr->state) { - if( addedConfigs.contains(ssid)) { - ptr->state = QNetworkConfiguration::Discovered; + if(state == QNetworkConfiguration::Undefined) { + if( userProfiles.contains(networkName) + && found.contains(ssidId)) { + state = QNetworkConfiguration::Discovered; } } - if(!ptr->state) { - ptr->state = QNetworkConfiguration::Defined; + if(state == QNetworkConfiguration::Undefined) { + state = QNetworkConfiguration::Defined; } - accessPointConfigurations.insert(ptr->id, ptr); - configurationInterface.insert(ptr->id, interfaceName); + + found.append(foundNetwork(id, networkName, state, interfaceName)); + } + } + return found; +} + +QStringList QCoreWlanEngine::foundNetwork(const QString &id, const QString &name, const QNetworkConfiguration::StateFlags state, const QString &interfaceName) +{ + QStringList found; + QMutexLocker locker(&mutex); + if (accessPointConfigurations.contains(id)) { + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); + + bool changed = false; + + ptr->mutex.lock(); + + if (!ptr->isValid) { + ptr->isValid = true; + changed = true; + } + + if (ptr->name != name) { + ptr->name = name; + changed = true; + } + + if (ptr->id != id) { + ptr->id = id; + changed = true; + } + + if (ptr->state != state) { + ptr->state = state; + changed = true; + } + + ptr->mutex.unlock(); + + if (changed) { + locker.unlock(); + emit configurationChanged(ptr); + locker.relock(); } + found.append(id); + } else { + QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate); + + ptr->name = name; + ptr->isValid = true; + ptr->id = id; + ptr->state = state; + ptr->type = QNetworkConfiguration::InternetAccessPoint; + ptr->bearer = QLatin1String("WLAN"); + + accessPointConfigurations.insert(ptr->id, ptr); + configurationInterface.insert(ptr->id, interfaceName); + + locker.unlock(); + emit configurationAdded(ptr); + locker.relock(); + found.append(id); } return found; } @@ -573,20 +564,6 @@ bool QCoreWlanEngine::isKnownSsid(const QString &ssid) return false; } -bool QCoreWlanEngine::getWifiInterfaces() -{ - QMutexLocker locker(&mutex); - - networkInterfaces.clear(); - QMacCocoaAutoReleasePool pool; - - NSArray *wifiInterfaces = [CWInterface supportedInterfaces]; - for(uint row=0; row < [wifiInterfaces count]; row++ ) { - networkInterfaces.insert( qt_mac_NSStringToQString([wifiInterfaces objectAtIndex:row]),"WLAN"); - } - return true; -} - QNetworkSession::State QCoreWlanEngine::sessionStateForId(const QString &id) { QMutexLocker locker(&mutex); @@ -692,16 +669,15 @@ 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()) { ij.next(); - const QString idCheck = QString::number(qHash(QLatin1String("corewlan:") +i.key())); - if(name == i.key() || name == idCheck) { + const QString networkNameHash = QString::number(qHash(QLatin1String("corewlan:") +i.key())); + if(name == i.key() || name == networkNameHash) { return ij.key(); } - } + } } return QString(); } @@ -718,9 +694,7 @@ QString QCoreWlanEngine::getNetworkNameFromSsid(const QString &ssid) if(ij.key() == ssid) { return i.key(); } - } - return map.key(ssid); } return QString(); } @@ -735,10 +709,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); - CFDictionaryRef airportPlist = (const __CFDictionary*)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"]; @@ -748,7 +722,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); } } @@ -782,7 +756,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..d65025b 100644 --- a/src/plugins/bearer/generic/qgenericengine.cpp +++ b/src/plugins/bearer/generic/qgenericengine.cpp @@ -66,6 +66,7 @@ QT_BEGIN_NAMESPACE +#ifndef QT_NO_NETWORKINTERFACE static QString qGetInterfaceType(const QString &interface) { #ifdef Q_OS_WIN32 @@ -139,6 +140,7 @@ static QString qGetInterfaceType(const QString &interface) return QLatin1String("Unknown"); } +#endif QGenericEngine::QGenericEngine(QObject *parent) : QBearerEngineImpl(parent) @@ -180,6 +182,7 @@ void QGenericEngine::requestUpdate() void QGenericEngine::doRequestUpdate() { +#ifndef QT_NO_NETWORKINTERFACE QMutexLocker locker(&mutex); // Immediately after connecting with a wireless access point @@ -203,7 +206,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; @@ -221,8 +224,8 @@ void QGenericEngine::doRequestUpdate() if (name.isEmpty()) name = interface.name(); - QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Discovered; - if (interface.flags() & QNetworkInterface::IsUp) + QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Defined; + if((interface.flags() & QNetworkInterface::IsUp) && !interface.addressEntries().isEmpty()) state |= QNetworkConfiguration::Active; if (accessPointConfigurations.contains(id)) { @@ -290,6 +293,8 @@ void QGenericEngine::doRequestUpdate() } locker.unlock(); +#endif + emit updateCompleted(); } diff --git a/src/plugins/bearer/icd/icd.pro b/src/plugins/bearer/icd/icd.pro index 5eaf5af..f411de2 100644 --- a/src/plugins/bearer/icd/icd.pro +++ b/src/plugins/bearer/icd/icd.pro @@ -3,8 +3,8 @@ include(../../qpluginbase.pri) QT += network dbus -CONFIG += link_pkgconfig -PKGCONFIG += glib-2.0 dbus-glib-1 gconf-2.0 osso-ic conninet +QMAKE_CXXFLAGS += $$QT_CFLAGS_ICD +LIBS += $$QT_LIBS_ICD HEADERS += qicdengine.h \ monitor.h \ diff --git a/src/plugins/bearer/icd/qicdengine.cpp b/src/plugins/bearer/icd/qicdengine.cpp index 5e9dc0a..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 { @@ -417,7 +417,8 @@ QNetworkConfigurationManager::Capabilities QIcdEngine::capabilities() const { return QNetworkConfigurationManager::CanStartAndStopInterfaces | QNetworkConfigurationManager::DataStatistics | - QNetworkConfigurationManager::ForcedRoaming; + QNetworkConfigurationManager::ForcedRoaming | + QNetworkConfigurationManager::NetworkSessionRequired; } QNetworkSessionPrivate *QIcdEngine::createSessionBackend() diff --git a/src/plugins/bearer/icd/qnetworksession_impl.cpp b/src/plugins/bearer/icd/qnetworksession_impl.cpp index a2ae65c..5bf95dc 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()) { @@ -1110,7 +1110,7 @@ void QNetworkSessionPrivateImpl::reject() { } - +#ifndef QT_NO_NETWORKINTERFACE QNetworkInterface QNetworkSessionPrivateImpl::currentInterface() const { if (!publicConfig.isValid() || state != QNetworkSession::Connected) @@ -1121,7 +1121,7 @@ QNetworkInterface QNetworkSessionPrivateImpl::currentInterface() const return QNetworkInterface::interfaceFromName(currentNetworkInterface); } - +#endif void QNetworkSessionPrivateImpl::setSessionProperty(const QString& key, const QVariant& value) { diff --git a/src/plugins/bearer/icd/qnetworksession_impl.h b/src/plugins/bearer/icd/qnetworksession_impl.h index 587e6dc..c02faac 100644 --- a/src/plugins/bearer/icd/qnetworksession_impl.h +++ b/src/plugins/bearer/icd/qnetworksession_impl.h @@ -56,11 +56,6 @@ #include <QtNetwork/private/qnetworksession_p.h> #include <QtNetwork/qnetworkconfigmanager.h> -//#include "qnetworkconfigmanager_maemo_p.h" -//#include "qnetworksession.h" - -//#include <qnetworksession.h> -//#include <QNetworkInterface> #include <QtCore/qdatetime.h> #include <icd/dbus_api.h> @@ -90,7 +85,9 @@ public: //notification hooks to discover future state changes. void syncStateWithInterface(); +#ifndef QT_NO_NETWORKINTERFACE QNetworkInterface currentInterface() const; +#endif QVariant sessionProperty(const QString& key) const; void setSessionProperty(const QString& key, const QVariant& value); diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp index d7e315a..28ee38e 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp @@ -91,6 +91,15 @@ QNetworkManagerEngine::QNetworkManagerEngine(QObject *parent) connect(userSettings, SIGNAL(newConnection(QDBusObjectPath)), this, SLOT(newConnection(QDBusObjectPath))); + QMetaObject::invokeMethod(this, "init", Qt::QueuedConnection); +} + +QNetworkManagerEngine::~QNetworkManagerEngine() +{ +} + +void QNetworkManagerEngine::init() +{ // Get current list of access points. foreach (const QDBusObjectPath &devicePath, interface->getDevices()) deviceAdded(devicePath); @@ -113,10 +122,6 @@ QNetworkManagerEngine::QNetworkManagerEngine(QObject *parent) } } -QNetworkManagerEngine::~QNetworkManagerEngine() -{ -} - bool QNetworkManagerEngine::networkManagerAvailable() const { QMutexLocker locker(&mutex); @@ -146,7 +151,7 @@ QString QNetworkManagerEngine::getInterfaceFromId(const QString &id) continue; QNetworkManagerInterfaceDevice device(devices.at(0).path()); - return device.networkInterface().name(); + return device.networkInterface(); } } diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h index 05a1429..af3f450 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h @@ -70,6 +70,8 @@ public: QNetworkManagerEngine(QObject *parent = 0); ~QNetworkManagerEngine(); + Q_INVOKABLE void init(); + bool networkManagerAvailable() const; QString getInterfaceFromId(const QString &id); diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp index d23bb0d..a20370b 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp @@ -353,9 +353,9 @@ QString QNetworkManagerInterfaceDevice::udi() const return d->connectionInterface->property("Udi").toString(); } -QNetworkInterface QNetworkManagerInterfaceDevice::networkInterface() const +QString QNetworkManagerInterfaceDevice::networkInterface() const { - return QNetworkInterface::interfaceFromName(d->connectionInterface->property("Interface").toString()); + return d->connectionInterface->property("Interface").toString(); } quint32 QNetworkManagerInterfaceDevice::ip4Address() const diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h index 048f628..95f5b4a 100644 --- a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h @@ -59,8 +59,6 @@ #include <QtDBus/QDBusInterface> #include <QtDBus/QDBusMessage> #include <QtDBus/QDBusReply> -#include <QNetworkInterface> - #include <QtDBus/QDBusPendingCallWatcher> #include <QtDBus/QDBusObjectPath> @@ -215,7 +213,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,11 +246,11 @@ class QNetworkManagerInterfaceDevice : public QObject public: - QNetworkManagerInterfaceDevice(const QString &deviceObjectPath, QObject *parent = 0); + explicit QNetworkManagerInterfaceDevice(const QString &deviceObjectPath, QObject *parent = 0); ~QNetworkManagerInterfaceDevice(); QString udi() const; - QNetworkInterface networkInterface() const; + QString networkInterface() const; QDBusInterface *connectionInterface() const; quint32 ip4Address() const; quint32 state() const; @@ -277,7 +275,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 +310,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 +342,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 +402,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 +430,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/qnetworksession_impl.cpp b/src/plugins/bearer/qnetworksession_impl.cpp index db1759c..33cce69 100644 --- a/src/plugins/bearer/qnetworksession_impl.cpp +++ b/src/plugins/bearer/qnetworksession_impl.cpp @@ -49,8 +49,6 @@ #include <QtCore/qdebug.h> #include <QtCore/qmutex.h> -#include <QtNetwork/qnetworkinterface.h> - QT_BEGIN_NAMESPACE static QBearerEngineImpl *getEngineFromId(const QString &id) @@ -218,6 +216,7 @@ void QNetworkSessionPrivateImpl::reject() { } +#ifndef QT_NO_NETWORKINTERFACE QNetworkInterface QNetworkSessionPrivateImpl::currentInterface() const { if (!publicConfig.isValid() || !engine || state != QNetworkSession::Connected) @@ -229,6 +228,7 @@ QNetworkInterface QNetworkSessionPrivateImpl::currentInterface() const return QNetworkInterface(); return QNetworkInterface::interfaceFromName(interface); } +#endif QVariant QNetworkSessionPrivateImpl::sessionProperty(const QString &key) const { diff --git a/src/plugins/bearer/qnetworksession_impl.h b/src/plugins/bearer/qnetworksession_impl.h index c644174..3becbf0 100644 --- a/src/plugins/bearer/qnetworksession_impl.h +++ b/src/plugins/bearer/qnetworksession_impl.h @@ -83,7 +83,9 @@ public: //notification hooks to discover future state changes. void syncStateWithInterface(); +#ifndef QT_NO_NETWORKINTERFACE QNetworkInterface currentInterface() const; +#endif QVariant sessionProperty(const QString& key) const; void setSessionProperty(const QString& key, const QVariant& value); diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp index 0737942..512ea51 100644 --- a/src/plugins/bearer/symbian/qnetworksession_impl.cpp +++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp @@ -152,6 +152,7 @@ void QNetworkSessionPrivateImpl::syncStateWithInterface() } } +#ifndef QT_NO_NETWORKINTERFACE QNetworkInterface QNetworkSessionPrivateImpl::interface(TUint iapId) const { QString interfaceName; @@ -189,7 +190,9 @@ QNetworkInterface QNetworkSessionPrivateImpl::interface(TUint iapId) const return QNetworkInterface::interfaceFromName(interfaceName); } +#endif +#ifndef QT_NO_NETWORKINTERFACE QNetworkInterface QNetworkSessionPrivateImpl::currentInterface() const { if (!publicConfig.isValid() || state != QNetworkSession::Connected) { @@ -198,6 +201,7 @@ QNetworkInterface QNetworkSessionPrivateImpl::currentInterface() const return activeInterface; } +#endif QVariant QNetworkSessionPrivateImpl::sessionProperty(const QString& /*key*/) const { @@ -241,15 +245,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) { @@ -300,7 +313,9 @@ void QNetworkSessionPrivateImpl::open() if (connInfo().iIapId == symbianConfig->numericId) { if (iConnection.Attach(connInfo, RConnection::EAttachTypeNormal) == KErrNone) { activeConfig = publicConfig; +#ifndef QT_NO_NETWORKINTERFACE activeInterface = interface(symbianConfig->numericId); +#endif connected = ETrue; startTime = QDateTime::currentDateTime(); if (iDynamicSetdefaultif) { @@ -450,15 +465,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 +843,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(); @@ -835,7 +884,9 @@ void QNetworkSessionPrivateImpl::RunL() toSymbianConfig(privateConfiguration(activeConfig)); symbianConfig->mutex.lock(); +#ifndef QT_NO_NETWORKINTERFACE activeInterface = interface(symbianConfig->numericId); +#endif if (publicConfig.type() == QNetworkConfiguration::UserChoice) { serviceConfig = QNetworkConfigurationManager() .configurationFromIdentifier(symbianConfig->serviceNetworkPtr->id); @@ -893,9 +944,11 @@ bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint SymbianNetworkConfigurationPrivate *symbianConfig = toSymbianConfig(privateConfiguration(activeConfig)); +#ifndef QT_NO_NETWORKINTERFACE symbianConfig->mutex.lock(); activeInterface = interface(symbianConfig->numericId); symbianConfig->mutex.unlock(); +#endif #ifdef SNAP_FUNCTIONALITY_AVAILABLE if (iDynamicSetdefaultif) { diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h index 98d4222..9a57eae 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: @@ -90,7 +89,9 @@ public: //notification hooks to discover future state changes. void syncStateWithInterface(); +#ifndef QT_NO_NETWORKINTERFACE QNetworkInterface currentInterface() const; +#endif QVariant sessionProperty(const QString& key) const; void setSessionProperty(const QString& key, const QVariant& value); @@ -138,12 +139,16 @@ private: void handleSymbianConnectionStatusChange(TInt aConnectionStatus, TInt aError, TUint accessPointId = 0); QNetworkConfiguration bestConfigFromSNAP(const QNetworkConfiguration& snapConfig) const; QNetworkConfiguration activeConfiguration(TUint32 iapId = 0) const; +#ifndef QT_NO_NETWORKINTERFACE QNetworkInterface interface(TUint iapId) const; +#endif private: // data SymbianEngine *engine; +#ifndef QT_NO_NETWORKINTERFACE mutable QNetworkInterface activeInterface; +#endif QDateTime startTime; diff --git a/src/plugins/bearer/symbian/symbian.pro b/src/plugins/bearer/symbian/symbian.pro index 9613def..f915570 100644 --- a/src/plugins/bearer/symbian/symbian.pro +++ b/src/plugins/bearer/symbian/symbian.pro @@ -10,14 +10,16 @@ SOURCES += symbianengine.cpp \ qnetworksession_impl.cpp \ main.cpp -exists($${EPOCROOT}epoc32/release/winscw/udeb/cmmanager.lib)| \ -exists($${EPOCROOT}epoc32/release/armv5/lib/cmmanager.lib) { - message("Building with SNAP support") - DEFINES += SNAP_FUNCTIONALITY_AVAILABLE - LIBS += -lcmmanager -} else { - message("Building without SNAP support") - LIBS += -lapengine +symbian { + exists($${EPOCROOT}epoc32/release/winscw/udeb/cmmanager.lib)| \ + exists($${EPOCROOT}epoc32/release/armv5/lib/cmmanager.lib) { + message("Building with SNAP support") + DEFINES += SNAP_FUNCTIONALITY_AVAILABLE + LIBS += -lcmmanager + } else { + message("Building without SNAP support") + LIBS += -lapengine + } } INCLUDEPATH += $$APP_LAYER_SYSTEMINCLUDE diff --git a/src/plugins/bearer/symbian/symbianengine.cpp b/src/plugins/bearer/symbian/symbianengine.cpp index 980892a..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; @@ -184,7 +197,8 @@ QNetworkConfigurationManager::Capabilities SymbianEngine::capabilities() const capFlags = QNetworkConfigurationManager::CanStartAndStopInterfaces | QNetworkConfigurationManager::DirectConnectionRouting | QNetworkConfigurationManager::SystemSessionSupport | - QNetworkConfigurationManager::DataStatistics; + QNetworkConfigurationManager::DataStatistics | + QNetworkConfigurationManager::NetworkSessionRequired; #ifdef SNAP_FUNCTIONALITY_AVAILABLE capFlags |= QNetworkConfigurationManager::ApplicationLevelRoaming | @@ -230,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; @@ -737,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); @@ -873,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) { @@ -880,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: @@ -1014,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; |