From f7eb78d6b7cc0e07275ab64bec2743c5b2c0705f Mon Sep 17 00:00:00 2001 From: Aaron McCarthy Date: Thu, 3 Dec 2009 15:00:24 +1000 Subject: Convert CoreWlan engine into a plugin. --- src/network/bearer/bearer.pri | 13 - src/network/bearer/qcorewlanengine_mac.mm | 461 ------------------------- src/network/bearer/qcorewlanengine_mac_p.h | 101 ------ src/network/bearer/qnetworkconfigmanager_p.cpp | 23 +- src/network/bearer/qnetworkconfigmanager_p.h | 2 +- src/network/bearer/qnetworksession_p.cpp | 13 - src/plugins/bearer/bearer.pro | 1 + src/plugins/bearer/corewlan/corewlan.pro | 21 ++ src/plugins/bearer/corewlan/main.cpp | 88 +++++ src/plugins/bearer/corewlan/qcorewlanengine.h | 91 +++++ src/plugins/bearer/corewlan/qcorewlanengine.mm | 459 ++++++++++++++++++++++++ 11 files changed, 672 insertions(+), 601 deletions(-) delete mode 100644 src/network/bearer/qcorewlanengine_mac.mm delete mode 100644 src/network/bearer/qcorewlanengine_mac_p.h create mode 100644 src/plugins/bearer/corewlan/corewlan.pro create mode 100644 src/plugins/bearer/corewlan/main.cpp create mode 100644 src/plugins/bearer/corewlan/qcorewlanengine.h create mode 100644 src/plugins/bearer/corewlan/qcorewlanengine.mm diff --git a/src/network/bearer/bearer.pri b/src/network/bearer/bearer.pri index 9476239..5bae333 100644 --- a/src/network/bearer/bearer.pri +++ b/src/network/bearer/bearer.pri @@ -81,18 +81,5 @@ symbian { bearer/qnetworksessionengine.cpp contains(QT_CONFIG, networkmanager):DEFINES += BACKEND_NM - - macx { - HEADERS += bearer/qcorewlanengine_mac_p.h - SOURCES+= bearer/qcorewlanengine_mac.mm - LIBS += -framework Foundation -framework SystemConfiguration - - contains(corewlan_enabled, yes) { - isEmpty(QMAKE_MAC_SDK)|contains(QMAKE_MAC_SDK, "/Developer/SDKs/MacOSX10.6.sdk") { - LIBS += -framework CoreWLAN - DEFINES += MAC_SDK_10_6 - } - } - } } diff --git a/src/network/bearer/qcorewlanengine_mac.mm b/src/network/bearer/qcorewlanengine_mac.mm deleted file mode 100644 index 2455f86..0000000 --- a/src/network/bearer/qcorewlanengine_mac.mm +++ /dev/null @@ -1,461 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#include "qcorewlanengine_mac_p.h" -#include "qnetworkconfiguration_p.h" - -#include -#include -#include -#include - -#include - -#if defined(MAC_SDK_10_6) //not much functionality without this -#include -#include -#include -#include -#endif - -#include -#include -#include - -#include -QMap networkInterfaces; - -QT_BEGIN_NAMESPACE - -Q_GLOBAL_STATIC(QCoreWlanEngine, coreWlanEngine) - -inline QString cfstringRefToQstring(CFStringRef cfStringRef) { -// return QString([cfStringRef UTF8String]); - QString retVal; - CFIndex maxLength = 2 * CFStringGetLength(cfStringRef) + 1/*zero term*/; // max UTF8 - char *cstring = new char[maxLength]; - if (CFStringGetCString(CFStringRef(cfStringRef), cstring, maxLength, kCFStringEncodingUTF8)) { - retVal = QString::fromUtf8(cstring); - } - delete cstring; - return retVal; -} - -inline CFStringRef qstringToCFStringRef(const QString &string) -{ - return CFStringCreateWithCharacters(0, reinterpret_cast(string.unicode()), - string.length()); -} - -inline NSString *qstringToNSString(const QString &qstr) -{ return [reinterpret_cast(qstringToCFStringRef(qstr)) autorelease]; } - -inline QString nsstringToQString(const NSString *nsstr) -{ return cfstringRefToQstring(reinterpret_cast(nsstr)); } - -inline QStringList nsarrayToQStringList(void *nsarray) -{ - QStringList result; - NSArray *array = static_cast(nsarray); - for (NSUInteger i=0; i<[array count]; ++i) - result << nsstringToQString([array objectAtIndex:i]); - return result; -} - -static QString qGetInterfaceType(const QString &interfaceString) -{ - return networkInterfaces.value(interfaceString); -} - -QCoreWlanEngine::QCoreWlanEngine(QObject *parent) -: QNetworkSessionEngine(parent) -{ - getAllScInterfaces(); - connect(&pollTimer, SIGNAL(timeout()), this, SIGNAL(configurationsChanged())); - pollTimer.setInterval(10000); -} - -QCoreWlanEngine::~QCoreWlanEngine() -{ -} - -QList QCoreWlanEngine::getWifiConfigurations() -{ - QMapIterator i(networkInterfaces); - while (i.hasNext()) { - i.next(); - QString interfaceName = i.key(); - if (i.value() == "WLAN") { - if(!isWifiReady(interfaceName)) { - qWarning() << "wifi not powered on"; - return QList(); - } else { - // QList profs = getWlanProfiles(interfaceName); - scanForSsids(interfaceName); - } - } else { - - } - } - return QList (); -} - -QList QCoreWlanEngine::getConfigurations(bool *ok) -{ - if (ok) - *ok = true; - NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; - - QList foundConfigurations; - QList wificonfigs = getWifiConfigurations(); - - uint identifier; - QMapIterator i(networkInterfaces); - while (i.hasNext()) { - i.next(); - if (i.value() == "WLAN") { - QList fetchedConfigurations = scanForSsids(i.key()); - for (int i = 0; i < fetchedConfigurations.count(); ++i) { - - QNetworkConfigurationPrivate *config = new QNetworkConfigurationPrivate; - config->name = fetchedConfigurations.at(i)->name; - config->isValid = fetchedConfigurations.at(i)->isValid; - config->id = fetchedConfigurations.at(i)->id; - - config->state = fetchedConfigurations.at(i)->state; - config->type = fetchedConfigurations.at(i)->type; - config->roamingSupported = fetchedConfigurations.at(i)->roamingSupported; - config->purpose = fetchedConfigurations.at(i)->purpose; - config->internet = fetchedConfigurations.at(i)->internet; - config->serviceInterface = fetchedConfigurations.at(i)->serviceInterface; - - identifier = config->name.toUInt(); - configurationInterface[identifier] = config->serviceInterface.name(); - foundConfigurations.append(config); - } - } - - QNetworkInterface interface = QNetworkInterface::interfaceFromName(i.key()); - QNetworkConfigurationPrivate *cpPriv = new QNetworkConfigurationPrivate; - const QString humanReadableName = interface.humanReadableName(); - cpPriv->name = humanReadableName.isEmpty() ? interface.name() : humanReadableName; - cpPriv->isValid = true; - - if (interface.index()) - identifier = interface.index(); - else - identifier = qHash(interface.hardwareAddress()); - - cpPriv->id = QString::number(identifier); - cpPriv->type = QNetworkConfiguration::InternetAccessPoint; - cpPriv->state = QNetworkConfiguration::Undefined; - - if (interface.flags() & QNetworkInterface::IsRunning) { - cpPriv->state = QNetworkConfiguration::Defined; - cpPriv->internet = true; - } - if ( !interface.addressEntries().isEmpty()) { - cpPriv->state |= QNetworkConfiguration::Active; - cpPriv->internet = true; - } - configurationInterface[identifier] = interface.name(); - foundConfigurations.append(cpPriv); - } - [autoreleasepool release]; - pollTimer.start(); - return foundConfigurations; -} - -QString QCoreWlanEngine::getInterfaceFromId(const QString &id) -{ - return configurationInterface.value(id.toUInt()); -} - -bool QCoreWlanEngine::hasIdentifier(const QString &id) -{ - return configurationInterface.contains(id.toUInt()); -} - -QString QCoreWlanEngine::bearerName(const QString &id) -{ - QString interface = getInterfaceFromId(id); - - if (interface.isEmpty()) - return QString(); - - return qGetInterfaceType(interface); -} - -void QCoreWlanEngine::connectToId(const QString &id) -{ - NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; - QString interfaceString = getInterfaceFromId(id); - - if(networkInterfaces.value(interfaceString) == "WLAN") { -#if defined(MAC_SDK_10_6) - CWInterface *wifiInterface = [CWInterface interfaceWithName: qstringToNSString(interfaceString)]; - CWConfiguration *userConfig = [ wifiInterface configuration]; - - NSSet *remNets = [userConfig rememberedNetworks]; //CWWirelessProfile - - NSEnumerator *enumerator = [remNets objectEnumerator]; - CWWirelessProfile *wProfile; - NSUInteger index=0; - while ((wProfile = [enumerator nextObject])) { //CWWirelessProfile - - if(id == nsstringToQString([wProfile ssid])) { - CW8021XProfile *user8021XProfile = nil; - user8021XProfile = [ wProfile user8021XProfile]; - - NSError *err = nil; - NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0]; - - if(user8021XProfile) { - [params setValue: user8021XProfile forKey:kCWAssocKey8021XProfile]; - } else { - [params setValue: [wProfile passphrase] forKey: kCWAssocKeyPassphrase]; - } - - NSDictionary *parametersDict = nil; - NSArray* apArray = [NSMutableArray arrayWithArray:[wifiInterface scanForNetworksWithParameters:parametersDict error:&err]]; - if(!err) { - for(uint row=0; row < [apArray count]; row++ ) { - CWNetwork *apNetwork = [apArray objectAtIndex:row]; - if([[apNetwork ssid] compare:[wProfile ssid]] == NSOrderedSame) { - bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err]; - if(!result) { - qWarning() <<"ERROR"<< nsstringToQString([err localizedDescription ]); - emit connectionError(id, ConnectError); - } else { - [autoreleasepool release]; - return; - } - } - } - } - } - index++; - } - emit connectionError(id, InterfaceLookupError); -#endif - } else { - // not wifi - } - emit connectionError(id, OperationNotSupported); - [autoreleasepool release]; -} - -void QCoreWlanEngine::disconnectFromId(const QString &id) -{ - QString interfaceString = getInterfaceFromId(id); - if(networkInterfaces.value(getInterfaceFromId(id)) == "WLAN") { //wifi only for now -#if defined(MAC_SDK_10_6) - NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; - CWInterface *wifiInterface = [CWInterface interfaceWithName: qstringToNSString(interfaceString)]; - [wifiInterface disassociate]; - if([[wifiInterface interfaceState]intValue] != kCWInterfaceStateInactive) { - emit connectionError(id, DisconnectionError); - } - [autoreleasepool release]; - return; -#endif - } else { - - } - emit connectionError(id, OperationNotSupported); -} - -void QCoreWlanEngine::requestUpdate() -{ - getAllScInterfaces(); - emit configurationsChanged(); -} - -QCoreWlanEngine *QCoreWlanEngine::instance() -{ - return coreWlanEngine(); -} - -QList QCoreWlanEngine::scanForSsids(const QString &interfaceName) -{ - QList foundConfigs; -#if defined(MAC_SDK_10_6) - NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; - - CWInterface *currentInterface = [CWInterface interfaceWithName:qstringToNSString(interfaceName)]; - NSError *err = nil; - NSDictionary *parametersDict = nil; - NSArray* apArray = [NSMutableArray arrayWithArray:[currentInterface scanForNetworksWithParameters:parametersDict error:&err]]; - - if(!err) { - for(uint row=0; row < [apArray count]; row++ ) { - CWNetwork *apNetwork = [apArray objectAtIndex:row]; - QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); - QString networkSsid = nsstringToQString([apNetwork ssid]); - cpPriv->name = networkSsid; - cpPriv->isValid = true; - cpPriv->id = networkSsid; - cpPriv->internet = true; - cpPriv->type = QNetworkConfiguration::InternetAccessPoint; - cpPriv->serviceInterface = QNetworkInterface::interfaceFromName(nsstringToQString([[CWInterface interface] name])); - - CWWirelessProfile *networkProfile = apNetwork.wirelessProfile; - CW8021XProfile *userNetworkProfile = networkProfile.user8021XProfile; - if(!userNetworkProfile) { - } else { - qWarning() <<"Has profile!" ; - } - - if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { - QString interfaceSsidString = nsstringToQString( [currentInterface ssid]); - if( cpPriv->name == interfaceSsidString) { - cpPriv->state |= QNetworkConfiguration::Active; - } - } else { - if(isKnownSsid(cpPriv->serviceInterface.name(), networkSsid)) { - cpPriv->state = QNetworkConfiguration::Discovered; - } else { - cpPriv->state = QNetworkConfiguration::Defined; - } - } - if(!cpPriv->state) { - cpPriv->state = QNetworkConfiguration::Undefined; - } - if([[apNetwork securityMode ] intValue]== kCWSecurityModeOpen) - cpPriv->purpose = QNetworkConfiguration::PublicPurpose; - else - cpPriv->purpose = QNetworkConfiguration::PrivatePurpose; - foundConfigs.append(cpPriv); - } - } else { - qWarning() << "ERROR scanning for ssids" << nsstringToQString([err localizedDescription]) - < QCoreWlanEngine::getWlanProfiles(const QString &interfaceName) -{ - Q_UNUSED(interfaceName) -#if defined(MAC_SDK_10_6) -// for( CW8021XProfile *each8021XProfile in [CW8021XProfile allUser8021XProfiles] ) { -// qWarning() << "Profile name" << nsstringToQString([each8021XProfile ssid]); -// } - -#endif - return QList (); -} - -bool QCoreWlanEngine::getAllScInterfaces() -{ - networkInterfaces.clear(); - NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; - - CFArrayRef interfaces = SCNetworkInterfaceCopyAll(); - if (interfaces != NULL) { - CFIndex interfaceCount; - CFIndex interfaceIndex; - interfaceCount = CFArrayGetCount(interfaces); - for (interfaceIndex = 0; interfaceIndex < interfaceCount; interfaceIndex++) { - - CFStringRef bsdName; - CFTypeRef thisInterface = CFArrayGetValueAtIndex(interfaces, interfaceIndex); - bsdName = SCNetworkInterfaceGetBSDName((SCNetworkInterfaceRef)thisInterface); - QString interfaceName = cfstringRefToQstring(bsdName); - QString typeStr; - CFStringRef type = SCNetworkInterfaceGetInterfaceType((SCNetworkInterfaceRef)thisInterface); - if ( CFEqual(type, kSCNetworkInterfaceTypeIEEE80211)) { - typeStr = "WLAN"; -// } else if (CFEqual(type, kSCNetworkInterfaceTypeBluetooth)) { -// typeStr = "Bluetooth"; - } else if(CFEqual(type, kSCNetworkInterfaceTypeEthernet)) { - typeStr = "Ethernet"; - } else if(CFEqual(type, kSCNetworkInterfaceTypeFireWire)) { - typeStr = "Ethernet"; //ok a bit fudged - } - if(!networkInterfaces.contains(interfaceName) && !typeStr.isEmpty()) { - networkInterfaces.insert(interfaceName,typeStr); - } - } - } - CFRelease(interfaces); - - [autoreleasepool release]; - return true; -} - -#include "moc_qcorewlanengine_mac_p.cpp" - -QT_END_NAMESPACE - diff --git a/src/network/bearer/qcorewlanengine_mac_p.h b/src/network/bearer/qcorewlanengine_mac_p.h deleted file mode 100644 index d6454ca..0000000 --- a/src/network/bearer/qcorewlanengine_mac_p.h +++ /dev/null @@ -1,101 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). -** All rights reserved. -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** This file is part of the QtNetwork module of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** No Commercial Usage -** This file contains pre-release code and may not be distributed. -** You may use this file in accordance with the terms and conditions -** contained in the Technology Preview License Agreement accompanying -** this package. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 2.1 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** If you have questions regarding the use of this file, please contact -** Nokia at qt-info@nokia.com. -** -** -** -** -** -** -** -** -** $QT_END_LICENSE$ -** -****************************************************************************/ - -#ifndef QCOREWLANENGINE_P_H -#define QCOREWLANENGINE_P_H - -// -// W A R N I N G -// ------------- -// -// This file is not part of the Qt API. It exists purely as an -// implementation detail. This header file may change from version to -// version without notice, or even be removed. -// -// We mean it. -// - -#include "qnetworksessionengine_p.h" -#include -#include - -QT_BEGIN_NAMESPACE - -class QNetworkConfigurationPrivate; - -class QCoreWlanEngine : public QNetworkSessionEngine -{ - Q_OBJECT - -public: - QCoreWlanEngine(QObject *parent = 0); - ~QCoreWlanEngine(); - - QList getConfigurations(bool *ok = 0); - QString getInterfaceFromId(const QString &id); - bool hasIdentifier(const QString &id); - - QString bearerName(const QString &id); - - void connectToId(const QString &id); - void disconnectFromId(const QString &id); - - void requestUpdate(); - - static QCoreWlanEngine *instance(); - static bool getAllScInterfaces(); - -private: - bool isWifiReady(const QString &dev); - QMap configurationInterface; - QTimer pollTimer; - QList scanForSsids(const QString &interfaceName); - - QList getWlanProfiles(const QString &interfaceName); - - QList getWifiConfigurations(); - bool isKnownSsid(const QString &interfaceName, const QString &ssid); -}; - -QT_END_NAMESPACE - -#endif - diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp index c35edbf..f8e0d7b 100644 --- a/src/network/bearer/qnetworkconfigmanager_p.cpp +++ b/src/network/bearer/qnetworkconfigmanager_p.cpp @@ -40,11 +40,6 @@ ****************************************************************************/ #include "qnetworkconfigmanager_p.h" - -#ifdef Q_OS_DARWIN -#include "qcorewlanengine_mac_p.h" -#endif - #include "qbearerplugin.h" #include @@ -229,10 +224,17 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations() QStringList keys = l->keys(); #if defined (Q_OS_DARWIN) - coreWifi = QCoreWlanEngine::instance(); - if (coreWifi) { - connect(coreWifi, SIGNAL(configurationsChanged()), - this, SLOT(updateConfigurations())); + coreWifi = 0; + if (keys.contains(QLatin1String("corewlan"))) { + QBearerEnginePlugin *coreWlanPlugin = + qobject_cast(l->instance(QLatin1String("corewlan"))); + if (coreWlanPlugin) { + coreWifi = coreWlanPlugin->create(QLatin1String("corewlan")); + if (coreWifi) { + connect(coreWifi, SIGNAL(configurationsChanged()), + this, SLOT(updateConfigurations())); + } + } } #else #ifdef BACKEND_NM @@ -473,7 +475,4 @@ void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate() #endif } -#include "moc_qnetworkconfigmanager_p.cpp" - QT_END_NAMESPACE - diff --git a/src/network/bearer/qnetworkconfigmanager_p.h b/src/network/bearer/qnetworkconfigmanager_p.h index 5d0df18..95358bc 100644 --- a/src/network/bearer/qnetworkconfigmanager_p.h +++ b/src/network/bearer/qnetworkconfigmanager_p.h @@ -146,7 +146,7 @@ private: QNetworkSessionEngine *nmWifi; #endif #ifdef Q_OS_DARWIN - QCoreWlanEngine *coreWifi; + QNetworkSessionEngine *coreWifi; #endif uint onlineConfigurations; diff --git a/src/network/bearer/qnetworksession_p.cpp b/src/network/bearer/qnetworksession_p.cpp index 3c9054b..df0ad3e 100644 --- a/src/network/bearer/qnetworksession_p.cpp +++ b/src/network/bearer/qnetworksession_p.cpp @@ -44,29 +44,18 @@ #include "qnetworksessionengine_p.h" #include "qnetworkconfigmanager_p.h" -#ifdef Q_OS_DARWIN -#include "qcorewlanengine_mac_p.h" -#endif #include #include #include #include -#undef interface - QT_BEGIN_NAMESPACE static QNetworkSessionEngine *getEngineFromId(const QString &id) { QNetworkConfigurationManagerPrivate *priv = qNetworkConfigurationManagerPrivate(); -#ifdef Q_OS_DARWIN - QCoreWlanEngine *coreWifi = QCoreWlanEngine::instance(); - if (coreWifi && coreWifi->hasIdentifier(id)) - return coreWifi; - -#endif QNetworkSessionEngine *engine = priv->configurationEngine.value(id); if (engine && engine->hasIdentifier(id)) return engine; @@ -498,6 +487,4 @@ if(serviceName.isEmpty()) } #endif -#include "moc_qnetworksession_p.cpp" QT_END_NAMESPACE - diff --git a/src/plugins/bearer/bearer.pro b/src/plugins/bearer/bearer.pro index 80d6f4b..58d2613 100644 --- a/src/plugins/bearer/bearer.pro +++ b/src/plugins/bearer/bearer.pro @@ -4,3 +4,4 @@ SUBDIRS += generic contains(QT_CONFIG, dbus):contains(QT_CONFIG, networkmanager):SUBDIRS += networkmanager win32:SUBDIRS += nla win32:!wince*:SUBDIRS += nativewifi +macx:SUBDIRS += corewlan diff --git a/src/plugins/bearer/corewlan/corewlan.pro b/src/plugins/bearer/corewlan/corewlan.pro new file mode 100644 index 0000000..ffac6df --- /dev/null +++ b/src/plugins/bearer/corewlan/corewlan.pro @@ -0,0 +1,21 @@ +TARGET = qcorewlanbearer +include(../../qpluginbase.pri) + +QT += network +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 + DEFINES += MAC_SDK_10_6 + } +} + +DEFINES += BEARER_ENGINE + +HEADERS += qcorewlanengine.h +SOURCES += qcorewlanengine.mm main.cpp + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/bearer +target.path += $$[QT_INSTALL_PLUGINS]/bearer +INSTALLS += target diff --git a/src/plugins/bearer/corewlan/main.cpp b/src/plugins/bearer/corewlan/main.cpp new file mode 100644 index 0000000..c0d1efe --- /dev/null +++ b/src/plugins/bearer/corewlan/main.cpp @@ -0,0 +1,88 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcorewlanengine.h" + +#include + +#include + +QT_BEGIN_NAMESPACE + +class QCoreWlanEnginePlugin : public QBearerEnginePlugin +{ +public: + QCoreWlanEnginePlugin(); + ~QCoreWlanEnginePlugin(); + + QStringList keys() const; + QBearerEngine *create(const QString &key) const; +}; + +QCoreWlanEnginePlugin::QCoreWlanEnginePlugin() +{ +} + +QCoreWlanEnginePlugin::~QCoreWlanEnginePlugin() +{ +} + +QStringList QCoreWlanEnginePlugin::keys() const +{ + qDebug() << Q_FUNC_INFO; + + return QStringList() << QLatin1String("corewlan"); +} + +QBearerEngine *QCoreWlanEnginePlugin::create(const QString &key) const +{ + qDebug() << Q_FUNC_INFO; + + if (key == QLatin1String("corewlan")) + return new QCoreWlanEngine; + else + return 0; +} + +Q_EXPORT_STATIC_PLUGIN(QCoreWlanEnginePlugin) +Q_EXPORT_PLUGIN2(qcorewlanbearer, QCoreWlanEnginePlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.h b/src/plugins/bearer/corewlan/qcorewlanengine.h new file mode 100644 index 0000000..7ccfeea --- /dev/null +++ b/src/plugins/bearer/corewlan/qcorewlanengine.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCOREWLANENGINE_P_H +#define QCOREWLANENGINE_P_H + +#include + +#include +#include + +QT_BEGIN_NAMESPACE + +class QNetworkConfigurationPrivate; + +class QCoreWlanEngine : public QNetworkSessionEngine +{ + Q_OBJECT + +public: + QCoreWlanEngine(QObject *parent = 0); + ~QCoreWlanEngine(); + + QList getConfigurations(bool *ok = 0); + QString getInterfaceFromId(const QString &id); + bool hasIdentifier(const QString &id); + + QString bearerName(const QString &id); + + void connectToId(const QString &id); + void disconnectFromId(const QString &id); + + void requestUpdate(); + + static QCoreWlanEngine *instance(); + static bool getAllScInterfaces(); + +private: + bool isWifiReady(const QString &dev); + QMap configurationInterface; + QTimer pollTimer; + QList scanForSsids(const QString &interfaceName); + + QList getWlanProfiles(const QString &interfaceName); + + QList getWifiConfigurations(); + bool isKnownSsid(const QString &interfaceName, const QString &ssid); +}; + +QT_END_NAMESPACE + +#endif + diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm new file mode 100644 index 0000000..9dea217 --- /dev/null +++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm @@ -0,0 +1,459 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcorewlanengine.h" + +#include + +#include +#include +#include +#include + +#include + +#if defined(MAC_SDK_10_6) //not much functionality without this +#include +#include +#include +#include +#endif + +#include +#include +#include + +#include +QMap networkInterfaces; + +QT_BEGIN_NAMESPACE + +Q_GLOBAL_STATIC(QCoreWlanEngine, coreWlanEngine) + +inline QString cfstringRefToQstring(CFStringRef cfStringRef) { +// return QString([cfStringRef UTF8String]); + QString retVal; + CFIndex maxLength = 2 * CFStringGetLength(cfStringRef) + 1/*zero term*/; // max UTF8 + char *cstring = new char[maxLength]; + if (CFStringGetCString(CFStringRef(cfStringRef), cstring, maxLength, kCFStringEncodingUTF8)) { + retVal = QString::fromUtf8(cstring); + } + delete cstring; + return retVal; +} + +inline CFStringRef qstringToCFStringRef(const QString &string) +{ + return CFStringCreateWithCharacters(0, reinterpret_cast(string.unicode()), + string.length()); +} + +inline NSString *qstringToNSString(const QString &qstr) +{ return [reinterpret_cast(qstringToCFStringRef(qstr)) autorelease]; } + +inline QString nsstringToQString(const NSString *nsstr) +{ return cfstringRefToQstring(reinterpret_cast(nsstr)); } + +inline QStringList nsarrayToQStringList(void *nsarray) +{ + QStringList result; + NSArray *array = static_cast(nsarray); + for (NSUInteger i=0; i<[array count]; ++i) + result << nsstringToQString([array objectAtIndex:i]); + return result; +} + +static QString qGetInterfaceType(const QString &interfaceString) +{ + return networkInterfaces.value(interfaceString); +} + +QCoreWlanEngine::QCoreWlanEngine(QObject *parent) +: QNetworkSessionEngine(parent) +{ + getAllScInterfaces(); + connect(&pollTimer, SIGNAL(timeout()), this, SIGNAL(configurationsChanged())); + pollTimer.setInterval(10000); +} + +QCoreWlanEngine::~QCoreWlanEngine() +{ +} + +QList QCoreWlanEngine::getWifiConfigurations() +{ + QMapIterator i(networkInterfaces); + while (i.hasNext()) { + i.next(); + QString interfaceName = i.key(); + if (i.value() == "WLAN") { + if(!isWifiReady(interfaceName)) { + qWarning() << "wifi not powered on"; + return QList(); + } else { + // QList profs = getWlanProfiles(interfaceName); + scanForSsids(interfaceName); + } + } else { + + } + } + return QList (); +} + +QList QCoreWlanEngine::getConfigurations(bool *ok) +{ + if (ok) + *ok = true; + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + + QList foundConfigurations; + QList wificonfigs = getWifiConfigurations(); + + uint identifier; + QMapIterator i(networkInterfaces); + while (i.hasNext()) { + i.next(); + if (i.value() == "WLAN") { + QList fetchedConfigurations = scanForSsids(i.key()); + for (int i = 0; i < fetchedConfigurations.count(); ++i) { + + QNetworkConfigurationPrivate *config = new QNetworkConfigurationPrivate; + config->name = fetchedConfigurations.at(i)->name; + config->isValid = fetchedConfigurations.at(i)->isValid; + config->id = fetchedConfigurations.at(i)->id; + + config->state = fetchedConfigurations.at(i)->state; + config->type = fetchedConfigurations.at(i)->type; + config->roamingSupported = fetchedConfigurations.at(i)->roamingSupported; + config->purpose = fetchedConfigurations.at(i)->purpose; + config->internet = fetchedConfigurations.at(i)->internet; + config->serviceInterface = fetchedConfigurations.at(i)->serviceInterface; + + identifier = config->name.toUInt(); + configurationInterface[identifier] = config->serviceInterface.name(); + foundConfigurations.append(config); + } + } + + QNetworkInterface interface = QNetworkInterface::interfaceFromName(i.key()); + QNetworkConfigurationPrivate *cpPriv = new QNetworkConfigurationPrivate; + const QString humanReadableName = interface.humanReadableName(); + cpPriv->name = humanReadableName.isEmpty() ? interface.name() : humanReadableName; + cpPriv->isValid = true; + + if (interface.index()) + identifier = interface.index(); + else + identifier = qHash(interface.hardwareAddress()); + + cpPriv->id = QString::number(identifier); + cpPriv->type = QNetworkConfiguration::InternetAccessPoint; + cpPriv->state = QNetworkConfiguration::Undefined; + + if (interface.flags() & QNetworkInterface::IsRunning) { + cpPriv->state = QNetworkConfiguration::Defined; + cpPriv->internet = true; + } + if ( !interface.addressEntries().isEmpty()) { + cpPriv->state |= QNetworkConfiguration::Active; + cpPriv->internet = true; + } + configurationInterface[identifier] = interface.name(); + foundConfigurations.append(cpPriv); + } + [autoreleasepool release]; + pollTimer.start(); + return foundConfigurations; +} + +QString QCoreWlanEngine::getInterfaceFromId(const QString &id) +{ + return configurationInterface.value(id.toUInt()); +} + +bool QCoreWlanEngine::hasIdentifier(const QString &id) +{ + return configurationInterface.contains(id.toUInt()); +} + +QString QCoreWlanEngine::bearerName(const QString &id) +{ + QString interface = getInterfaceFromId(id); + + if (interface.isEmpty()) + return QString(); + + return qGetInterfaceType(interface); +} + +void QCoreWlanEngine::connectToId(const QString &id) +{ + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + QString interfaceString = getInterfaceFromId(id); + + if(networkInterfaces.value(interfaceString) == "WLAN") { +#if defined(MAC_SDK_10_6) + CWInterface *wifiInterface = [CWInterface interfaceWithName: qstringToNSString(interfaceString)]; + CWConfiguration *userConfig = [ wifiInterface configuration]; + + NSSet *remNets = [userConfig rememberedNetworks]; //CWWirelessProfile + + NSEnumerator *enumerator = [remNets objectEnumerator]; + CWWirelessProfile *wProfile; + NSUInteger index=0; + while ((wProfile = [enumerator nextObject])) { //CWWirelessProfile + + if(id == nsstringToQString([wProfile ssid])) { + CW8021XProfile *user8021XProfile = nil; + user8021XProfile = [ wProfile user8021XProfile]; + + NSError *err = nil; + NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0]; + + if(user8021XProfile) { + [params setValue: user8021XProfile forKey:kCWAssocKey8021XProfile]; + } else { + [params setValue: [wProfile passphrase] forKey: kCWAssocKeyPassphrase]; + } + + NSDictionary *parametersDict = nil; + NSArray* apArray = [NSMutableArray arrayWithArray:[wifiInterface scanForNetworksWithParameters:parametersDict error:&err]]; + if(!err) { + for(uint row=0; row < [apArray count]; row++ ) { + CWNetwork *apNetwork = [apArray objectAtIndex:row]; + if([[apNetwork ssid] compare:[wProfile ssid]] == NSOrderedSame) { + bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err]; + if(!result) { + qWarning() <<"ERROR"<< nsstringToQString([err localizedDescription ]); + emit connectionError(id, ConnectError); + } else { + [autoreleasepool release]; + return; + } + } + } + } + } + index++; + } + emit connectionError(id, InterfaceLookupError); +#endif + } else { + // not wifi + } + emit connectionError(id, OperationNotSupported); + [autoreleasepool release]; +} + +void QCoreWlanEngine::disconnectFromId(const QString &id) +{ + QString interfaceString = getInterfaceFromId(id); + if(networkInterfaces.value(getInterfaceFromId(id)) == "WLAN") { //wifi only for now +#if defined(MAC_SDK_10_6) + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + CWInterface *wifiInterface = [CWInterface interfaceWithName: qstringToNSString(interfaceString)]; + [wifiInterface disassociate]; + if([[wifiInterface interfaceState]intValue] != kCWInterfaceStateInactive) { + emit connectionError(id, DisconnectionError); + } + [autoreleasepool release]; + return; +#endif + } else { + + } + emit connectionError(id, OperationNotSupported); +} + +void QCoreWlanEngine::requestUpdate() +{ + getAllScInterfaces(); + emit configurationsChanged(); +} + +QCoreWlanEngine *QCoreWlanEngine::instance() +{ + return coreWlanEngine(); +} + +QList QCoreWlanEngine::scanForSsids(const QString &interfaceName) +{ + QList foundConfigs; +#if defined(MAC_SDK_10_6) + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + + CWInterface *currentInterface = [CWInterface interfaceWithName:qstringToNSString(interfaceName)]; + NSError *err = nil; + NSDictionary *parametersDict = nil; + NSArray* apArray = [NSMutableArray arrayWithArray:[currentInterface scanForNetworksWithParameters:parametersDict error:&err]]; + + if(!err) { + for(uint row=0; row < [apArray count]; row++ ) { + CWNetwork *apNetwork = [apArray objectAtIndex:row]; + QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); + QString networkSsid = nsstringToQString([apNetwork ssid]); + cpPriv->name = networkSsid; + cpPriv->isValid = true; + cpPriv->id = networkSsid; + cpPriv->internet = true; + cpPriv->type = QNetworkConfiguration::InternetAccessPoint; + cpPriv->serviceInterface = QNetworkInterface::interfaceFromName(nsstringToQString([[CWInterface interface] name])); + + CWWirelessProfile *networkProfile = apNetwork.wirelessProfile; + CW8021XProfile *userNetworkProfile = networkProfile.user8021XProfile; + if(!userNetworkProfile) { + } else { + qWarning() <<"Has profile!" ; + } + + if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { + QString interfaceSsidString = nsstringToQString( [currentInterface ssid]); + if( cpPriv->name == interfaceSsidString) { + cpPriv->state |= QNetworkConfiguration::Active; + } + } else { + if(isKnownSsid(cpPriv->serviceInterface.name(), networkSsid)) { + cpPriv->state = QNetworkConfiguration::Discovered; + } else { + cpPriv->state = QNetworkConfiguration::Defined; + } + } + if(!cpPriv->state) { + cpPriv->state = QNetworkConfiguration::Undefined; + } + if([[apNetwork securityMode ] intValue]== kCWSecurityModeOpen) + cpPriv->purpose = QNetworkConfiguration::PublicPurpose; + else + cpPriv->purpose = QNetworkConfiguration::PrivatePurpose; + foundConfigs.append(cpPriv); + } + } else { + qWarning() << "ERROR scanning for ssids" << nsstringToQString([err localizedDescription]) + < QCoreWlanEngine::getWlanProfiles(const QString &interfaceName) +{ + Q_UNUSED(interfaceName) +#if defined(MAC_SDK_10_6) +// for( CW8021XProfile *each8021XProfile in [CW8021XProfile allUser8021XProfiles] ) { +// qWarning() << "Profile name" << nsstringToQString([each8021XProfile ssid]); +// } + +#endif + return QList (); +} + +bool QCoreWlanEngine::getAllScInterfaces() +{ + networkInterfaces.clear(); + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + + CFArrayRef interfaces = SCNetworkInterfaceCopyAll(); + if (interfaces != NULL) { + CFIndex interfaceCount; + CFIndex interfaceIndex; + interfaceCount = CFArrayGetCount(interfaces); + for (interfaceIndex = 0; interfaceIndex < interfaceCount; interfaceIndex++) { + + CFStringRef bsdName; + CFTypeRef thisInterface = CFArrayGetValueAtIndex(interfaces, interfaceIndex); + bsdName = SCNetworkInterfaceGetBSDName((SCNetworkInterfaceRef)thisInterface); + QString interfaceName = cfstringRefToQstring(bsdName); + QString typeStr; + CFStringRef type = SCNetworkInterfaceGetInterfaceType((SCNetworkInterfaceRef)thisInterface); + if ( CFEqual(type, kSCNetworkInterfaceTypeIEEE80211)) { + typeStr = "WLAN"; +// } else if (CFEqual(type, kSCNetworkInterfaceTypeBluetooth)) { +// typeStr = "Bluetooth"; + } else if(CFEqual(type, kSCNetworkInterfaceTypeEthernet)) { + typeStr = "Ethernet"; + } else if(CFEqual(type, kSCNetworkInterfaceTypeFireWire)) { + typeStr = "Ethernet"; //ok a bit fudged + } + if(!networkInterfaces.contains(interfaceName) && !typeStr.isEmpty()) { + networkInterfaces.insert(interfaceName,typeStr); + } + } + } + CFRelease(interfaces); + + [autoreleasepool release]; + return true; +} + +QT_END_NAMESPACE -- cgit v0.12