diff options
author | Aaron McCarthy <aaron.mccarthy@nokia.com> | 2010-01-05 23:43:39 (GMT) |
---|---|---|
committer | Aaron McCarthy <aaron.mccarthy@nokia.com> | 2010-01-05 23:43:39 (GMT) |
commit | f5459734441c102c9e8209fad8f0e6dff8377f7e (patch) | |
tree | cb1e329c41669cc5bbbb02ad7068da3e898de8d4 /src/plugins | |
parent | b2fc251bb4628a06282d1dcaeda79222b300b912 (diff) | |
parent | 4ef1103e6b399cb9421fb001f81af47bca20d2a7 (diff) | |
download | Qt-f5459734441c102c9e8209fad8f0e6dff8377f7e.zip Qt-f5459734441c102c9e8209fad8f0e6dff8377f7e.tar.gz Qt-f5459734441c102c9e8209fad8f0e6dff8377f7e.tar.bz2 |
Merge commit '554e022396eff5bd7b93e070cf9bbb3257945f0b' into bearermanagement/integration-3
Diffstat (limited to 'src/plugins')
28 files changed, 5764 insertions, 1 deletions
diff --git a/src/plugins/bearer/bearer.pro b/src/plugins/bearer/bearer.pro new file mode 100644 index 0000000..58d2613 --- /dev/null +++ b/src/plugins/bearer/bearer.pro @@ -0,0 +1,7 @@ +TEMPLATE = subdirs + +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..ac04e95 --- /dev/null +++ b/src/plugins/bearer/corewlan/corewlan.pro @@ -0,0 +1,19 @@ +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 + } +} + +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..ce0611e --- /dev/null +++ b/src/plugins/bearer/corewlan/main.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 <QtNetwork/qbearerplugin.h> + +#include <QtCore/qdebug.h> + +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 +{ + return QStringList() << QLatin1String("corewlan"); +} + +QBearerEngine *QCoreWlanEnginePlugin::create(const QString &key) const +{ + 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..45a5ee9 --- /dev/null +++ b/src/plugins/bearer/corewlan/qcorewlanengine.h @@ -0,0 +1,93 @@ +/**************************************************************************** +** +** 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_H +#define QCOREWLANENGINE_H + +#include <QtNetwork/private/qnetworksessionengine_p.h> + +#include <QMap> +#include <QTimer> + +QT_BEGIN_NAMESPACE + +class QNetworkConfigurationPrivate; + +class QCoreWlanEngine : public QNetworkSessionEngine +{ + Q_OBJECT + +public: + QCoreWlanEngine(QObject *parent = 0); + ~QCoreWlanEngine(); + + 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(); + + QNetworkSession::State sessionStateForId(const QString &id); + + static bool getAllScInterfaces(); + +private Q_SLOTS: + void doRequestUpdate(); + +private: + bool isWifiReady(const QString &dev); + QMap<QString, QString> configurationInterface; + QTimer pollTimer; + QStringList scanForSsids(const QString &interfaceName); + + bool isKnownSsid(const QString &interfaceName, const QString &ssid); + QList<QNetworkConfigurationPrivate *> foundConfigurations; + +}; + +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..3ceebbd --- /dev/null +++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm @@ -0,0 +1,512 @@ +/**************************************************************************** +** +** 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 <QtNetwork/private/qnetworkconfiguration_p.h> + +#include <QtCore/qthread.h> +#include <QtCore/qmutex.h> +#include <QtCore/qcoreapplication.h> +#include <QtCore/qstringlist.h> + +#include <QtCore/qdebug.h> + +#if defined(MAC_SDK_10_6) //not much functionality without this +#include <CoreWLAN/CoreWLAN.h> +#include <CoreWLAN/CWInterface.h> +#include <CoreWLAN/CWNetwork.h> +#include <CoreWLAN/CWNetwork.h> +#endif + +#include <Foundation/NSEnumerator.h> +#include <Foundation/NSKeyValueObserving.h> +#include <Foundation/NSAutoreleasePool.h> + +#include <SystemConfiguration/SCNetworkConfiguration.h> +QMap <QString, QString> networkInterfaces; + +QT_BEGIN_NAMESPACE + +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<const UniChar *>(string.unicode()), + string.length()); +} + +inline NSString *qstringToNSString(const QString &qstr) +{ return [reinterpret_cast<const NSString *>(qstringToCFStringRef(qstr)) autorelease]; } + +inline QString nsstringToQString(const NSString *nsstr) +{ return cfstringRefToQstring(reinterpret_cast<const CFStringRef>(nsstr)); } + +inline QStringList nsarrayToQStringList(void *nsarray) +{ + QStringList result; + NSArray *array = static_cast<NSArray *>(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, QLatin1String("Unknown")); +} + +QCoreWlanEngine::QCoreWlanEngine(QObject *parent) +: QNetworkSessionEngine(parent) +{ + connect(&pollTimer, SIGNAL(timeout()), this, SLOT(doRequestUpdate())); + pollTimer.setInterval(10000); + doRequestUpdate(); +} + +QCoreWlanEngine::~QCoreWlanEngine() +{ + while (!foundConfigurations.isEmpty()) + delete foundConfigurations.takeFirst(); +} + +QString QCoreWlanEngine::getInterfaceFromId(const QString &id) +{ + return configurationInterface.value(id); +} + +bool QCoreWlanEngine::hasIdentifier(const QString &id) +{ + return configurationInterface.contains(id); +} + +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; + CWNetwork *apNetwork; + NSDictionary *parametersDict; + NSArray* apArray; + + CW8021XProfile *user8021XProfile; + NSError *err; + NSMutableDictionary *params; + + while ((wProfile = [enumerator nextObject])) { //CWWirelessProfile + + if(id == nsstringToQString([wProfile ssid])) { + user8021XProfile = nil; + user8021XProfile = [ wProfile user8021XProfile]; + + err = nil; + params = [NSMutableDictionary dictionaryWithCapacity:0]; + + if(user8021XProfile) { + [params setValue: user8021XProfile forKey:kCWAssocKey8021XProfile]; + } else { + [params setValue: [wProfile passphrase] forKey: kCWAssocKeyPassphrase]; + } + + parametersDict = nil; + apArray = [NSMutableArray arrayWithArray:[wifiInterface scanForNetworksWithParameters:parametersDict error:&err]]; + + if(!err) { + + for(uint row=0; row < [apArray count]; row++ ) { + 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 { + [apNetwork release]; + [autoreleasepool release]; + return; + } + } + } + } + } + index++; + } + [apNetwork release]; + + 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() +{ + pollTimer.stop(); + QTimer::singleShot(0, this, SLOT(doRequestUpdate())); +} + +void QCoreWlanEngine::doRequestUpdate() +{ + getAllScInterfaces(); + + 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)) { + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); + + bool changed = false; + + 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; + } + + if (changed) + emit configurationChanged(ptr); + } else { + QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate); + + ptr->name = name; + ptr->isValid = true; + ptr->id = id; + ptr->state = state; + ptr->type = QNetworkConfiguration::InternetAccessPoint; + + accessPointConfigurations.insert(id, ptr); + configurationInterface.insert(id, interface.name()); + + emit configurationAdded(ptr); + } + } + + while (!previous.isEmpty()) { + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(previous.takeFirst()); + + configurationInterface.remove(ptr->id); + emit configurationRemoved(ptr); + } + + pollTimer.start(); + + emit updateCompleted(); +} + +QStringList QCoreWlanEngine::scanForSsids(const QString &interfaceName) +{ + QStringList found; + +#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 = [currentInterface scanForNetworksWithParameters:parametersDict error:&err]; + + CWNetwork *apNetwork; + if (!err) { + for(uint row=0; row < [apArray count]; row++ ) { + NSAutoreleasePool *looppool = [[NSAutoreleasePool alloc] init]; + + apNetwork = [apArray objectAtIndex:row]; + + const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkSsid)); + found.append(id); + + QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined; + + if ([currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { + if (networkSsid == nsstringToQString([currentInterface ssid])) + state = QNetworkConfiguration::Active; + } else { + if (isKnownSsid(interfaceName, networkSsid)) + state = QNetworkConfiguration::Discovered; + else + state = QNetworkConfiguration::Defined; + } + + if (accessPointConfigurations.contains(id)) { + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); + + bool changed = false; + + 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; + } + + if (changed) + emit configurationChanged(ptr); + } else { + QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate); + + ptr->name = networkSsid; + ptr->isValid = true; + ptr->id = id; + ptr->state = state; + ptr->type = QNetworkConfiguration::InternetAccessPoint; + ptr->bearer = QLatin1String("WLAN"); + + accessPointConfigurations.insert(id, ptr); + configurationInterface.insert(id, interfaceName); + + emit configurationAdded(ptr); + } + [looppool release]; + } + } else { + qWarning() << "ERROR scanning for ssids" << nsstringToQString([err localizedDescription]) + <<nsstringToQString([err domain]); + } + + [autoreleasepool drain]; +#else + Q_UNUSED(interfaceName); +#endif + return found; +} + +bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName) +{ +#if defined(MAC_SDK_10_6) + CWInterface *defaultInterface = [CWInterface interfaceWithName: qstringToNSString(wifiDeviceName)]; + if([defaultInterface power]) + return true; +#else + Q_UNUSED(wifiDeviceName); +#endif + return false; +} + +bool QCoreWlanEngine::isKnownSsid(const QString &interfaceName, const QString &ssid) +{ +#if defined(MAC_SDK_10_6) + CWInterface *wifiInterface = [CWInterface interfaceWithName: qstringToNSString(interfaceName)]; + CWConfiguration *userConfig = [wifiInterface configuration]; + NSSet *remNets = [userConfig rememberedNetworks]; + for (CWWirelessProfile *wProfile in remNets) { + if(ssid == nsstringToQString([wProfile ssid])) + return true; + } +#else + Q_UNUSED(interfaceName); + Q_UNUSED(ssid); +#endif + return false; +} + +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++) { + NSAutoreleasePool *looppool = [[NSAutoreleasePool alloc] init]; + + 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); + } + [looppool release]; + } + } + CFRelease(interfaces); + + [autoreleasepool drain]; + return true; +} + +QNetworkSession::State QCoreWlanEngine::sessionStateForId(const QString &id) +{ + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); + + if (!ptr) + return QNetworkSession::Invalid; + + if (!ptr->isValid) { + return QNetworkSession::Invalid; + } else if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { + return QNetworkSession::Connected; + } else if ((ptr->state & QNetworkConfiguration::Discovered) == + QNetworkConfiguration::Discovered) { + return QNetworkSession::Disconnected; + } else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) { + return QNetworkSession::NotAvailable; + } else if ((ptr->state & QNetworkConfiguration::Undefined) == + QNetworkConfiguration::Undefined) { + return QNetworkSession::NotAvailable; + } + + return QNetworkSession::Invalid; +} + +QT_END_NAMESPACE diff --git a/src/plugins/bearer/generic/generic.pro b/src/plugins/bearer/generic/generic.pro new file mode 100644 index 0000000..0015041 --- /dev/null +++ b/src/plugins/bearer/generic/generic.pro @@ -0,0 +1,12 @@ +TARGET = qgenericbearer +include(../../qpluginbase.pri) + +QT += network + +HEADERS += qgenericengine.h \ + ../platformdefs_win.h +SOURCES += qgenericengine.cpp main.cpp + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/bearer +target.path += $$[QT_INSTALL_PLUGINS]/bearer +INSTALLS += target diff --git a/src/plugins/bearer/generic/main.cpp b/src/plugins/bearer/generic/main.cpp new file mode 100644 index 0000000..a7df023 --- /dev/null +++ b/src/plugins/bearer/generic/main.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 "qgenericengine.h" + +#include <QtNetwork/qbearerplugin.h> + +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +class QGenericEnginePlugin : public QBearerEnginePlugin +{ +public: + QGenericEnginePlugin(); + ~QGenericEnginePlugin(); + + QStringList keys() const; + QBearerEngine *create(const QString &key) const; +}; + +QGenericEnginePlugin::QGenericEnginePlugin() +{ +} + +QGenericEnginePlugin::~QGenericEnginePlugin() +{ +} + +QStringList QGenericEnginePlugin::keys() const +{ + return QStringList() << QLatin1String("generic"); +} + +QBearerEngine *QGenericEnginePlugin::create(const QString &key) const +{ + if (key == QLatin1String("generic")) + return new QGenericEngine; + else + return 0; +} + +Q_EXPORT_STATIC_PLUGIN(QGenericEnginePlugin) +Q_EXPORT_PLUGIN2(qgenericbearer, QGenericEnginePlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/bearer/generic/qgenericengine.cpp b/src/plugins/bearer/generic/qgenericengine.cpp new file mode 100644 index 0000000..9294fad --- /dev/null +++ b/src/plugins/bearer/generic/qgenericengine.cpp @@ -0,0 +1,318 @@ +/**************************************************************************** +** +** 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 "qgenericengine.h" + +#include <QtNetwork/private/qnetworkconfiguration_p.h> + +#include <QtCore/qthread.h> +#include <QtCore/qmutex.h> +#include <QtCore/qcoreapplication.h> +#include <QtCore/qstringlist.h> + +#include <QtCore/qdebug.h> + +#ifdef Q_OS_WIN +#include "../platformdefs_win.h" +#endif + +#ifdef Q_OS_LINUX +#include <sys/socket.h> +#include <sys/ioctl.h> +#include <net/if.h> +#include <net/if_arp.h> +#endif + + +static QString qGetInterfaceType(const QString &interface) +{ +#ifdef Q_OS_WIN32 + unsigned long oid; + DWORD bytesWritten; + + NDIS_MEDIUM medium; + NDIS_PHYSICAL_MEDIUM physicalMedium; + + HANDLE handle = CreateFile((TCHAR *)QString("\\\\.\\%1").arg(interface).utf16(), 0, + FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + if (handle == INVALID_HANDLE_VALUE) + return QLatin1String("Unknown"); + + oid = OID_GEN_MEDIA_SUPPORTED; + bytesWritten = 0; + bool result = DeviceIoControl(handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof(oid), + &medium, sizeof(medium), &bytesWritten, 0); + if (!result) { + CloseHandle(handle); + return QLatin1String("Unknown"); + } + + oid = OID_GEN_PHYSICAL_MEDIUM; + bytesWritten = 0; + result = DeviceIoControl(handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof(oid), + &physicalMedium, sizeof(physicalMedium), &bytesWritten, 0); + if (!result) { + CloseHandle(handle); + + if (medium == NdisMedium802_3) + return QLatin1String("Ethernet"); + else + return QLatin1String("Unknown"); + } + + CloseHandle(handle); + + if (medium == NdisMedium802_3) { + switch (physicalMedium) { + case NdisPhysicalMediumWirelessLan: + return QLatin1String("WLAN"); + case NdisPhysicalMediumBluetooth: + return QLatin1String("Bluetooth"); + case NdisPhysicalMediumWiMax: + return QLatin1String("WiMAX"); + default: +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug() << "Physical Medium" << physicalMedium; +#endif + return QLatin1String("Ethernet"); + } + } + +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug() << medium << physicalMedium; +#endif +#elif defined(Q_OS_LINUX) + int sock = socket(AF_INET, SOCK_DGRAM, 0); + + ifreq request; + strncpy(request.ifr_name, interface.toLocal8Bit().data(), sizeof(request.ifr_name)); + if (ioctl(sock, SIOCGIFHWADDR, &request) >= 0) { + switch (request.ifr_hwaddr.sa_family) { + case ARPHRD_ETHER: + return QLatin1String("Ethernet"); + } + } + + close(sock); +#else + Q_UNUSED(interface); +#endif + + return QLatin1String("Unknown"); +} + +QGenericEngine::QGenericEngine(QObject *parent) +: QNetworkSessionEngine(parent) +{ + connect(&pollTimer, SIGNAL(timeout()), this, SLOT(doRequestUpdate())); + pollTimer.setInterval(10000); + doRequestUpdate(); +} + +QGenericEngine::~QGenericEngine() +{ +} + +QString QGenericEngine::getInterfaceFromId(const QString &id) +{ + return configurationInterface.value(id); +} + +bool QGenericEngine::hasIdentifier(const QString &id) +{ + return configurationInterface.contains(id); +} + +/*QString QGenericEngine::bearerName(const QString &id) +{ + QString interface = getInterfaceFromId(id); + + if (interface.isEmpty()) + return QLatin1String("Unknown"); + + return qGetInterfaceType(interface); +}*/ + +void QGenericEngine::connectToId(const QString &id) +{ + emit connectionError(id, OperationNotSupported); +} + +void QGenericEngine::disconnectFromId(const QString &id) +{ + emit connectionError(id, OperationNotSupported); +} + +void QGenericEngine::requestUpdate() +{ + pollTimer.stop(); + QTimer::singleShot(0, this, SLOT(doRequestUpdate())); +} + +void QGenericEngine::doRequestUpdate() +{ + // Immediately after connecting with a wireless access point + // QNetworkInterface::allInterfaces() will sometimes return an empty list. Calling it again a + // second time results in a non-empty list. If we loose interfaces we will end up removing + // network configurations which will break current sessions. + QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces(); + if (interfaces.isEmpty()) + interfaces = QNetworkInterface::allInterfaces(); + + QStringList previous = accessPointConfigurations.keys(); + + // create configuration for each interface + while (!interfaces.isEmpty()) { + QNetworkInterface interface = interfaces.takeFirst(); + + if (!interface.isValid()) + continue; + + // ignore loopback interface + if (interface.flags() & QNetworkInterface::IsLoopBack) + continue; + + // ignore WLAN interface handled in seperate engine + if (qGetInterfaceType(interface.name()) == QLatin1String("WLAN")) + continue; + + uint identifier; + if (interface.index()) + identifier = qHash(QLatin1String("generic:") + QString::number(interface.index())); + else + identifier = qHash(QLatin1String("generic:") + 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::Discovered; + if (interface.flags() & QNetworkInterface::IsUp) + state |= QNetworkConfiguration::Active; + + if (accessPointConfigurations.contains(id)) { + QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = + accessPointConfigurations.value(id); + + bool changed = false; + + 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; + } + + if (changed) + emit configurationChanged(ptr); + } else { + QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate); + + ptr->name = name; + ptr->isValid = true; + ptr->id = id; + ptr->state = state; + ptr->type = QNetworkConfiguration::InternetAccessPoint; + ptr->bearer = qGetInterfaceType(interface.name()); + + accessPointConfigurations.insert(id, ptr); + configurationInterface.insert(id, interface.name()); + + emit configurationAdded(ptr); + } + } + + while (!previous.isEmpty()) { + QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = + accessPointConfigurations.take(previous.takeFirst()); + + configurationInterface.remove(ptr->id); + emit configurationRemoved(ptr); + } + + pollTimer.start(); + + emit updateCompleted(); +} + +QNetworkSession::State QGenericEngine::sessionStateForId(const QString &id) +{ + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); + + if (!ptr) + return QNetworkSession::Invalid; + + if (!ptr->isValid) { + return QNetworkSession::Invalid; + } else if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { + return QNetworkSession::Connected; + } else if ((ptr->state & QNetworkConfiguration::Discovered) == + QNetworkConfiguration::Discovered) { + return QNetworkSession::Disconnected; + } else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) { + return QNetworkSession::NotAvailable; + } else if ((ptr->state & QNetworkConfiguration::Undefined) == + QNetworkConfiguration::Undefined) { + return QNetworkSession::NotAvailable; + } + + return QNetworkSession::Invalid; +} + +QT_END_NAMESPACE + diff --git a/src/plugins/bearer/generic/qgenericengine.h b/src/plugins/bearer/generic/qgenericengine.h new file mode 100644 index 0000000..a671ceb --- /dev/null +++ b/src/plugins/bearer/generic/qgenericengine.h @@ -0,0 +1,85 @@ +/**************************************************************************** +** +** 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 QGENERICENGINE_H +#define QGENERICENGINE_H + +#include <QtNetwork/private/qnetworksessionengine_p.h> + +#include <QMap> +#include <QTimer> + +QT_BEGIN_NAMESPACE + +class QNetworkConfigurationPrivate; + +class QGenericEngine : public QNetworkSessionEngine +{ + Q_OBJECT + +public: + QGenericEngine(QObject *parent = 0); + ~QGenericEngine(); + + 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(); + + QNetworkSession::State sessionStateForId(const QString &id); + +private Q_SLOTS: + void doRequestUpdate(); + +private: + QMap<QString, QString> configurationInterface; + QTimer pollTimer; +}; + +QT_END_NAMESPACE + +#endif + diff --git a/src/plugins/bearer/nativewifi/main.cpp b/src/plugins/bearer/nativewifi/main.cpp new file mode 100644 index 0000000..64ed73d --- /dev/null +++ b/src/plugins/bearer/nativewifi/main.cpp @@ -0,0 +1,139 @@ +/**************************************************************************** +** +** 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 "qnativewifiengine.h" +#include "platformdefs.h" + +#include <QtCore/qmutex.h> +#include <QtCore/private/qmutexpool_p.h> +#include <QtCore/qlibrary.h> + +#include <QtNetwork/qbearerplugin.h> + +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +static void resolveLibrary() +{ + static volatile bool triedResolve = false; + + if (!triedResolve) { +#ifndef QT_NO_THREAD + QMutexLocker locker(QMutexPool::globalInstanceGet(&local_WlanOpenHandle)); +#endif + + if (!triedResolve) { + local_WlanOpenHandle = (WlanOpenHandleProto) + QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanOpenHandle"); + local_WlanRegisterNotification = (WlanRegisterNotificationProto) + QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanRegisterNotification"); + local_WlanEnumInterfaces = (WlanEnumInterfacesProto) + QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanEnumInterfaces"); + local_WlanGetAvailableNetworkList = (WlanGetAvailableNetworkListProto) + QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanGetAvailableNetworkList"); + local_WlanQueryInterface = (WlanQueryInterfaceProto) + QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanQueryInterface"); + local_WlanConnect = (WlanConnectProto) + QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanConnect"); + local_WlanDisconnect = (WlanDisconnectProto) + QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanDisconnect"); + local_WlanScan = (WlanScanProto) + QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanScan"); + local_WlanFreeMemory = (WlanFreeMemoryProto) + QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanFreeMemory"); + local_WlanCloseHandle = (WlanCloseHandleProto) + QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanCloseHandle"); + + triedResolve = true; + } + } +} + +class QNativeWifiEnginePlugin : public QBearerEnginePlugin +{ +public: + QNativeWifiEnginePlugin(); + ~QNativeWifiEnginePlugin(); + + QStringList keys() const; + QBearerEngine *create(const QString &key) const; +}; + +QNativeWifiEnginePlugin::QNativeWifiEnginePlugin() +{ +} + +QNativeWifiEnginePlugin::~QNativeWifiEnginePlugin() +{ +} + +QStringList QNativeWifiEnginePlugin::keys() const +{ + return QStringList() << QLatin1String("nativewifi"); +} + +QBearerEngine *QNativeWifiEnginePlugin::create(const QString &key) const +{ + if (key != QLatin1String("nativewifi")) + return 0; + + resolveLibrary(); + + // native wifi dll not available + if (!local_WlanOpenHandle) + return 0; + + QNativeWifiEngine *engine = new QNativeWifiEngine; + + // could not initialise subsystem + if (engine && !engine->available()) { + delete engine; + return 0; + } + + return engine; +} + +Q_EXPORT_STATIC_PLUGIN(QNativeWifiEnginePlugin) +Q_EXPORT_PLUGIN2(qnativewifibearer, QNativeWifiEnginePlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/bearer/nativewifi/nativewifi.pro b/src/plugins/bearer/nativewifi/nativewifi.pro new file mode 100644 index 0000000..583edd4 --- /dev/null +++ b/src/plugins/bearer/nativewifi/nativewifi.pro @@ -0,0 +1,11 @@ +TARGET = qnativewifibearer +include(../../qpluginbase.pri) + +QT += network + +HEADERS += qnativewifiengine.h platformdefs.h +SOURCES += qnativewifiengine.cpp main.cpp + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/bearer +target.path += $$[QT_INSTALL_PLUGINS]/bearer +INSTALLS += target diff --git a/src/plugins/bearer/nativewifi/platformdefs.h b/src/plugins/bearer/nativewifi/platformdefs.h new file mode 100644 index 0000000..38fbae4 --- /dev/null +++ b/src/plugins/bearer/nativewifi/platformdefs.h @@ -0,0 +1,322 @@ +/**************************************************************************** +** +** 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 PLATFORMDEFS_H +#define PLATFORMDEFS_H + +#include <wtypes.h> +#undef interface + +#define WLAN_MAX_NAME_LENGTH 256 +#define WLAN_MAX_PHY_TYPE_NUMBER 8 +#define WLAN_NOTIFICATION_SOURCE_ALL 0x0000ffff +#define WLAN_AVAILABLE_NETWORK_CONNECTED 1 +#define WLAN_AVAILABLE_NETWORK_HAS_PROFILE 2 +#define DOT11_SSID_MAX_LENGTH 32 + +struct WLAN_NOTIFICATION_DATA { + DWORD NotificationSource; + DWORD NotificationCode; + GUID InterfaceGuid; + DWORD dwDataSize; + PVOID pData; +}; + +enum WLAN_INTERFACE_STATE { + wlan_interface_state_not_ready = 0, + wlan_interface_state_connected, + wlan_interface_state_ad_hoc_network_formed, + wlan_interface_state_disconnecting, + wlan_interface_state_disconnected, + wlan_interface_state_associating, + wlan_interface_state_discovering, + wlan_interface_state_authenticating +}; + +struct WLAN_INTERFACE_INFO { + GUID InterfaceGuid; + WCHAR strInterfaceDescription[WLAN_MAX_NAME_LENGTH]; + WLAN_INTERFACE_STATE isState; +}; + +struct WLAN_INTERFACE_INFO_LIST { + DWORD dwNumberOfItems; + DWORD dwIndex; + WLAN_INTERFACE_INFO InterfaceInfo[1]; +}; + +struct DOT11_SSID { + ULONG uSSIDLength; + UCHAR ucSSID[DOT11_SSID_MAX_LENGTH]; +}; + +struct NDIS_OBJECT_HEADER { + UCHAR Type; + UCHAR Revision; + USHORT Size; +}; + +typedef UCHAR DOT11_MAC_ADDRESS[6]; +struct DOT11_BSSID_LIST { + NDIS_OBJECT_HEADER Header; + ULONG uNumberOfEntries; + ULONG uTotalNumOfEntries; + DOT11_MAC_ADDRESS BSSIDs[1]; +}; + +enum DOT11_BSS_TYPE { + dot11_BSS_type_infrastructure = 1, + dot11_BSS_type_independent = 2, + dot11_BSS_type_any = 3 +}; + +enum DOT11_PHY_TYPE { + dot11_phy_type_unknown = 0, + dot11_phy_type_any = dot11_phy_type_unknown, + dot11_phy_type_fhss = 1, + dot11_phy_type_dsss = 2, + dot11_phy_type_irbaseband = 3, + dot11_phy_type_ofdm = 4, + dot11_phy_type_hrdsss = 5, + dot11_phy_type_erp = 6, + dot11_phy_type_ht = 7, + dot11_phy_type_IHV_start = 0x80000000, + dot11_phy_type_IHV_end = 0xffffffff +}; + +enum DOT11_AUTH_ALGORITHM { + DOT11_AUTH_ALGO_80211_OPEN = 1, + DOT11_AUTH_ALGO_80211_SHARED_KEY = 2, + DOT11_AUTH_ALGO_WPA = 3, + DOT11_AUTH_ALGO_WPA_PSK = 4, + DOT11_AUTH_ALGO_WPA_NONE = 5, + DOT11_AUTH_ALGO_RSNA = 6, + DOT11_AUTH_ALGO_RSNA_PSK = 7, + DOT11_AUTH_ALGO_IHV_START = 0x80000000, + DOT11_AUTH_ALGO_IHV_END = 0xffffffff +}; + +enum DOT11_CIPHER_ALGORITHM { + DOT11_CIPHER_ALGO_NONE = 0x00, + DOT11_CIPHER_ALGO_WEP40 = 0x01, + DOT11_CIPHER_ALGO_TKIP = 0x02, + DOT11_CIPHER_ALGO_CCMP = 0x04, + DOT11_CIPHER_ALGO_WEP104 = 0x05, + DOT11_CIPHER_ALGO_WPA_USE_GROUP = 0x100, + DOT11_CIPHER_ALGO_RSN_USE_GROUP = 0x100, + DOT11_CIPHER_ALGO_WEP = 0x101, + DOT11_CIPHER_ALGO_IHV_START = 0x80000000, + DOT11_CIPHER_ALGO_IHV_END = 0xffffffff +}; + +struct WLAN_AVAILABLE_NETWORK { + WCHAR strProfileName[WLAN_MAX_NAME_LENGTH]; + DOT11_SSID dot11Ssid; + DOT11_BSS_TYPE dot11BssType; + ULONG uNumberOfBssids; + BOOL bNetworkConnectable; + DWORD wlanNotConnectableReason; + ULONG uNumberOfPhyTypes; + DOT11_PHY_TYPE dot11PhyTypes[WLAN_MAX_PHY_TYPE_NUMBER]; + BOOL bMorePhyTypes; + ULONG wlanSignalQuality; + BOOL bSecurityEnabled; + DOT11_AUTH_ALGORITHM dot11DefaultAuthAlgorithm; + DOT11_CIPHER_ALGORITHM dot11DefaultCipherAlgorithm; + DWORD dwFlags; + DWORD dwReserved; +}; + +struct WLAN_AVAILABLE_NETWORK_LIST { + DWORD dwNumberOfItems; + DWORD dwIndex; + WLAN_AVAILABLE_NETWORK Network[1]; +}; + +enum WLAN_INTF_OPCODE { + wlan_intf_opcode_autoconf_start = 0x000000000, + wlan_intf_opcode_autoconf_enabled, + wlan_intf_opcode_background_scan_enabled, + wlan_intf_opcode_media_streaming_mode, + wlan_intf_opcode_radio_state, + wlan_intf_opcode_bss_type, + wlan_intf_opcode_interface_state, + wlan_intf_opcode_current_connection, + wlan_intf_opcode_channel_number, + wlan_intf_opcode_supported_infrastructure_auth_cipher_pairs, + wlan_intf_opcode_supported_adhoc_auth_cipher_pairs, + wlan_intf_opcode_supported_country_or_region_string_list, + wlan_intf_opcode_current_operation_mode, + wlan_intf_opcode_supported_safe_mode, + wlan_intf_opcode_certified_safe_mode, + wlan_intf_opcode_autoconf_end = 0x0fffffff, + wlan_intf_opcode_msm_start = 0x10000100, + wlan_intf_opcode_statistics, + wlan_intf_opcode_rssi, + wlan_intf_opcode_msm_end = 0x1fffffff, + wlan_intf_opcode_security_start = 0x20010000, + wlan_intf_opcode_security_end = 0x2fffffff, + wlan_intf_opcode_ihv_start = 0x30000000, + wlan_intf_opcode_ihv_end = 0x3fffffff +}; + +enum WLAN_OPCODE_VALUE_TYPE { + wlan_opcode_value_type_query_only = 0, + wlan_opcode_value_type_set_by_group_policy, + wlan_opcode_value_type_set_by_user, + wlan_opcode_value_type_invalid +}; + +enum WLAN_CONNECTION_MODE { + wlan_connection_mode_profile = 0, + wlan_connection_mode_temporary_profile, + wlan_connection_mode_discovery_secure, + wlan_connection_mode_discovery_unsecure, + wlan_connection_mode_auto, + wlan_connection_mode_invalid +}; + +struct WLAN_CONNECTION_PARAMETERS { + WLAN_CONNECTION_MODE wlanConnectionMode; + LPCWSTR strProfile; + DOT11_SSID *pDot11Ssid; + DOT11_BSSID_LIST *pDesiredBssidList; + DOT11_BSS_TYPE dot11BssType; + DWORD dwFlags; +}; + +struct WLAN_RAW_DATA { + DWORD dwDataSize; + BYTE DataBlob[1]; +}; + +enum WLAN_NOTIFICATION_ACM { + wlan_notification_acm_start = 0, + wlan_notification_acm_autoconf_enabled, + wlan_notification_acm_autoconf_disabled, + wlan_notification_acm_background_scan_enabled, + wlan_notification_acm_background_scan_disabled, + wlan_notification_acm_bss_type_change, + wlan_notification_acm_power_setting_change, + wlan_notification_acm_scan_complete, + wlan_notification_acm_scan_fail, + wlan_notification_acm_connection_start, + wlan_notification_acm_connection_complete, + wlan_notification_acm_connection_attempt_fail, + wlan_notification_acm_filter_list_change, + wlan_notification_acm_interface_arrival, + wlan_notification_acm_interface_removal, + wlan_notification_acm_profile_change, + wlan_notification_acm_profile_name_change, + wlan_notification_acm_profiles_exhausted, + wlan_notification_acm_network_not_available, + wlan_notification_acm_network_available, + wlan_notification_acm_disconnecting, + wlan_notification_acm_disconnected, + wlan_notification_acm_adhoc_network_state_change, + wlan_notification_acm_end +}; + +struct WLAN_ASSOCIATION_ATTRIBUTES { + DOT11_SSID dot11Ssid; + DOT11_BSS_TYPE dot11BssType; + DOT11_MAC_ADDRESS dot11Bssid; + DOT11_PHY_TYPE dot11PhyType; + ULONG uDot11PhyIndex; + ULONG wlanSignalQuality; + ULONG ulRxRate; + ULONG ulTxRate; +}; + +struct WLAN_SECURITY_ATTRIBUTES { + BOOL bSecurityEnabled; + BOOL bOneXEnabled; + DOT11_AUTH_ALGORITHM dot11AuthAlgorithm; + DOT11_CIPHER_ALGORITHM dot11CipherAlgorithm; +}; + +struct WLAN_CONNECTION_ATTRIBUTES { + WLAN_INTERFACE_STATE isState; + WLAN_CONNECTION_MODE wlanConnectionMode; + WCHAR strProfileName[WLAN_MAX_NAME_LENGTH]; + WLAN_ASSOCIATION_ATTRIBUTES wlanAssociationAttributes; + WLAN_SECURITY_ATTRIBUTES wlanSecurityAttributes; +}; + +typedef void (WINAPI *WLAN_NOTIFICATION_CALLBACK)(WLAN_NOTIFICATION_DATA *, PVOID); + +typedef DWORD (WINAPI *WlanOpenHandleProto) + (DWORD dwClientVersion, PVOID pReserved, PDWORD pdwNegotiatedVersion, PHANDLE phClientHandle); +typedef DWORD (WINAPI *WlanRegisterNotificationProto) + (HANDLE hClientHandle, DWORD dwNotifSource, BOOL bIgnoreDuplicate, + WLAN_NOTIFICATION_CALLBACK funcCallback, PVOID pCallbackContext, + PVOID pReserved, PDWORD pdwPrevNotifSource); +typedef DWORD (WINAPI *WlanEnumInterfacesProto) + (HANDLE hClientHandle, PVOID pReserved, WLAN_INTERFACE_INFO_LIST **ppInterfaceList); +typedef DWORD (WINAPI *WlanGetAvailableNetworkListProto) + (HANDLE hClientHandle, const GUID* pInterfaceGuid, DWORD dwFlags, PVOID pReserved, + WLAN_AVAILABLE_NETWORK_LIST **ppAvailableNetworkList); +typedef DWORD (WINAPI *WlanQueryInterfaceProto) + (HANDLE hClientHandle, const GUID *pInterfaceGuid, WLAN_INTF_OPCODE OpCode, PVOID pReserved, + PDWORD pdwDataSize, PVOID *ppData, WLAN_OPCODE_VALUE_TYPE *pWlanOpcodeValueType); +typedef DWORD (WINAPI *WlanConnectProto) + (HANDLE hClientHandle, const GUID *pInterfaceGuid, + const WLAN_CONNECTION_PARAMETERS *pConnectionParameters, PVOID pReserved); +typedef DWORD (WINAPI *WlanDisconnectProto) + (HANDLE hClientHandle, const GUID *pInterfaceGuid, PVOID pReserved); +typedef DWORD (WINAPI *WlanScanProto) + (HANDLE hClientHandle, const GUID *pInterfaceGuid, const DOT11_SSID *pDot11Ssid, + const WLAN_RAW_DATA *pIeData, PVOID pReserved); +typedef VOID (WINAPI *WlanFreeMemoryProto)(PVOID pMemory); +typedef DWORD (WINAPI *WlanCloseHandleProto)(HANDLE hClientHandle, PVOID pReserved); + +extern WlanOpenHandleProto local_WlanOpenHandle; +extern WlanRegisterNotificationProto local_WlanRegisterNotification; +extern WlanEnumInterfacesProto local_WlanEnumInterfaces; +extern WlanGetAvailableNetworkListProto local_WlanGetAvailableNetworkList; +extern WlanQueryInterfaceProto local_WlanQueryInterface; +extern WlanConnectProto local_WlanConnect; +extern WlanDisconnectProto local_WlanDisconnect; +extern WlanScanProto local_WlanScan; +extern WlanFreeMemoryProto local_WlanFreeMemory; +extern WlanCloseHandleProto local_WlanCloseHandle; + +#endif // PLATFORMDEFS_H diff --git a/src/plugins/bearer/nativewifi/qnativewifiengine.cpp b/src/plugins/bearer/nativewifi/qnativewifiengine.cpp new file mode 100644 index 0000000..0050770 --- /dev/null +++ b/src/plugins/bearer/nativewifi/qnativewifiengine.cpp @@ -0,0 +1,464 @@ +/**************************************************************************** +** +** 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 "qnativewifiengine.h" +#include "platformdefs.h" + +#include <QtNetwork/private/qnetworkconfiguration_p.h> + +#include <QtCore/qstringlist.h> + +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +WlanOpenHandleProto local_WlanOpenHandle = 0; +WlanRegisterNotificationProto local_WlanRegisterNotification = 0; +WlanEnumInterfacesProto local_WlanEnumInterfaces = 0; +WlanGetAvailableNetworkListProto local_WlanGetAvailableNetworkList = 0; +WlanQueryInterfaceProto local_WlanQueryInterface = 0; +WlanConnectProto local_WlanConnect = 0; +WlanDisconnectProto local_WlanDisconnect = 0; +WlanScanProto local_WlanScan = 0; +WlanFreeMemoryProto local_WlanFreeMemory = 0; +WlanCloseHandleProto local_WlanCloseHandle = 0; + +void qNotificationCallback(WLAN_NOTIFICATION_DATA *data, QNativeWifiEngine *d) +{ + Q_UNUSED(d); + + switch (data->NotificationCode) { + case wlan_notification_acm_connection_complete: + case wlan_notification_acm_disconnected: + QMetaObject::invokeMethod(d, "scanComplete", Qt::QueuedConnection); + break; + default: + qDebug() << "wlan unknown notification"; + } +} + +QNativeWifiEngine::QNativeWifiEngine(QObject *parent) +: QNetworkSessionEngine(parent), handle(0) +{ + DWORD clientVersion; + + DWORD result = local_WlanOpenHandle(1, 0, &clientVersion, &handle); + if (result != ERROR_SUCCESS) { + if (result != ERROR_SERVICE_NOT_ACTIVE) + qWarning("%s: WlanOpenHandle failed with error %ld\n", __FUNCTION__, result); + + return; + } + + result = local_WlanRegisterNotification(handle, WLAN_NOTIFICATION_SOURCE_ALL, true, + WLAN_NOTIFICATION_CALLBACK(qNotificationCallback), + this, 0, 0); + if (result != ERROR_SUCCESS) + qWarning("%s: WlanRegisterNotification failed with error %ld\n", __FUNCTION__, result); + + // On Windows XP SP2 and SP3 only connection and disconnection notifications are available. + // We need to poll for changes in available wireless networks. + connect(&pollTimer, SIGNAL(timeout()), this, SLOT(scanComplete())); + pollTimer.setInterval(10000); + scanComplete(); +} + +QNativeWifiEngine::~QNativeWifiEngine() +{ + local_WlanCloseHandle(handle, 0); +} + +void QNativeWifiEngine::scanComplete() +{ + QStringList previous = accessPointConfigurations.keys(); + + // enumerate interfaces + WLAN_INTERFACE_INFO_LIST *interfaceList; + DWORD result = local_WlanEnumInterfaces(handle, 0, &interfaceList); + if (result != ERROR_SUCCESS) { + qWarning("%s: WlanEnumInterfaces failed with error %ld\n", __FUNCTION__, result); + return; + } + + for (unsigned int i = 0; i < interfaceList->dwNumberOfItems; ++i) { + const WLAN_INTERFACE_INFO &interface = interfaceList->InterfaceInfo[i]; + + WLAN_AVAILABLE_NETWORK_LIST *networkList; + result = local_WlanGetAvailableNetworkList(handle, &interface.InterfaceGuid, + 3, 0, &networkList); + if (result != ERROR_SUCCESS) { + qWarning("%s: WlanGetAvailableNetworkList failed with error %ld\n", + __FUNCTION__, result); + continue; + } + + QStringList seenNetworks; + + for (unsigned int j = 0; j < networkList->dwNumberOfItems; ++j) { + WLAN_AVAILABLE_NETWORK &network = networkList->Network[j]; + + QString networkName; + + if (network.strProfileName[0] != 0) { + networkName = QString::fromWCharArray(network.strProfileName); + } else { + networkName = QByteArray(reinterpret_cast<char *>(network.dot11Ssid.ucSSID), + network.dot11Ssid.uSSIDLength); + } + + const QString id = QString::number(qHash(QLatin1String("WLAN:") + networkName)); + + previous.removeAll(id); + + QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined; + + if (!(network.dwFlags & WLAN_AVAILABLE_NETWORK_HAS_PROFILE)) + state = QNetworkConfiguration::Undefined; + + if (network.strProfileName[0] != 0) { + if (network.bNetworkConnectable) { + if (network.dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED) + state = QNetworkConfiguration::Active; + else + state = QNetworkConfiguration::Discovered; + } else { + state = QNetworkConfiguration::Defined; + } + } + + if (seenNetworks.contains(networkName)) + continue; + else + seenNetworks.append(networkName); + + if (accessPointConfigurations.contains(id)) { + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); + + bool changed = false; + + if (!ptr->isValid) { + ptr->isValid = true; + changed = true; + } + + if (ptr->name != networkName) { + ptr->name = networkName; + changed = true; + } + + if (ptr->state != state) { + ptr->state = state; + changed = true; + } + + if (changed) + emit configurationChanged(ptr); + } else { + QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate); + + ptr->name = networkName; + ptr->isValid = true; + ptr->id = id; + ptr->state = state; + ptr->type = QNetworkConfiguration::InternetAccessPoint; + ptr->bearer = QLatin1String("WLAN"); + + accessPointConfigurations.insert(id, ptr); + + emit configurationAdded(ptr); + } + } + + local_WlanFreeMemory(networkList); + } + + local_WlanFreeMemory(interfaceList); + + while (!previous.isEmpty()) { + QNetworkConfigurationPrivatePointer ptr = + accessPointConfigurations.take(previous.takeFirst()); + + emit configurationRemoved(ptr); + } + + pollTimer.start(); + + emit updateCompleted(); +} + +QString QNativeWifiEngine::getInterfaceFromId(const QString &id) +{ + // enumerate interfaces + WLAN_INTERFACE_INFO_LIST *interfaceList; + DWORD result = local_WlanEnumInterfaces(handle, 0, &interfaceList); + if (result != ERROR_SUCCESS) { + qWarning("%s: WlanEnumInterfaces failed with error %ld\n", __FUNCTION__, result); + return QString(); + } + + for (unsigned int i = 0; i < interfaceList->dwNumberOfItems; ++i) { + const WLAN_INTERFACE_INFO &interface = interfaceList->InterfaceInfo[i]; + + DWORD dataSize; + WLAN_CONNECTION_ATTRIBUTES *connectionAttributes; + result = local_WlanQueryInterface(handle, &interface.InterfaceGuid, + wlan_intf_opcode_current_connection, 0, &dataSize, + reinterpret_cast<PVOID *>(&connectionAttributes), 0); + if (result != ERROR_SUCCESS) { + if (result != ERROR_INVALID_STATE) + qWarning("%s: WlanQueryInterface failed with error %ld\n", __FUNCTION__, result); + + continue; + } + + if (qHash(QLatin1String("WLAN:") + + QString::fromWCharArray(connectionAttributes->strProfileName)) == id.toUInt()) { + QString guid("{%1-%2-%3-%4%5-%6%7%8%9%10%11}"); + + guid = guid.arg(interface.InterfaceGuid.Data1, 8, 16, QChar('0')); + guid = guid.arg(interface.InterfaceGuid.Data2, 4, 16, QChar('0')); + guid = guid.arg(interface.InterfaceGuid.Data3, 4, 16, QChar('0')); + for (int i = 0; i < 8; ++i) + guid = guid.arg(interface.InterfaceGuid.Data4[i], 2, 16, QChar('0')); + + local_WlanFreeMemory(connectionAttributes); + local_WlanFreeMemory(interfaceList); + + return guid.toUpper(); + } + + local_WlanFreeMemory(connectionAttributes); + } + + local_WlanFreeMemory(interfaceList); + + return QString(); +} + +bool QNativeWifiEngine::hasIdentifier(const QString &id) +{ + // enumerate interfaces + WLAN_INTERFACE_INFO_LIST *interfaceList; + DWORD result = local_WlanEnumInterfaces(handle, 0, &interfaceList); + if (result != ERROR_SUCCESS) { + qWarning("%s: WlanEnumInterfaces failed with error %ld\n", __FUNCTION__, result); + return false; + } + + for (unsigned int i = 0; i < interfaceList->dwNumberOfItems; ++i) { + const WLAN_INTERFACE_INFO &interface = interfaceList->InterfaceInfo[i]; + + WLAN_AVAILABLE_NETWORK_LIST *networkList; + result = local_WlanGetAvailableNetworkList(handle, &interface.InterfaceGuid, + 3, 0, &networkList); + if (result != ERROR_SUCCESS) { + qWarning("%s: WlanGetAvailableNetworkList failed with error %ld\n", + __FUNCTION__, result); + continue; + } + + for (unsigned int j = 0; j < networkList->dwNumberOfItems; ++j) { + WLAN_AVAILABLE_NETWORK &network = networkList->Network[j]; + + QString networkName; + + if (network.strProfileName[0] != 0) { + networkName = QString::fromWCharArray(network.strProfileName); + } else { + networkName = QByteArray(reinterpret_cast<char *>(network.dot11Ssid.ucSSID), + network.dot11Ssid.uSSIDLength); + } + + if (qHash(QLatin1String("WLAN:") + networkName) == id.toUInt()) { + local_WlanFreeMemory(networkList); + local_WlanFreeMemory(interfaceList); + return true; + } + } + + local_WlanFreeMemory(networkList); + } + + local_WlanFreeMemory(interfaceList); + + return false; +} + +/*QString QNativeWifiEngine::bearerName(const QString &) +{ + return QLatin1String("WLAN"); +}*/ + +void QNativeWifiEngine::connectToId(const QString &id) +{ + WLAN_INTERFACE_INFO_LIST *interfaceList; + DWORD result = local_WlanEnumInterfaces(handle, 0, &interfaceList); + if (result != ERROR_SUCCESS) { + qWarning("%s: WlanEnumInterfaces failed with error %ld\n", __FUNCTION__, result); + emit connectionError(id, InterfaceLookupError); + return; + } + + QString profile; + + for (unsigned int i = 0; i < interfaceList->dwNumberOfItems; ++i) { + const WLAN_INTERFACE_INFO &interface = interfaceList->InterfaceInfo[i]; + + WLAN_AVAILABLE_NETWORK_LIST *networkList; + result = local_WlanGetAvailableNetworkList(handle, &interface.InterfaceGuid, + 3, 0, &networkList); + if (result != ERROR_SUCCESS) { + qWarning("%s: WlanGetAvailableNetworkList failed with error %ld\n", + __FUNCTION__, result); + continue; + } + + for (unsigned int j = 0; j < networkList->dwNumberOfItems; ++j) { + WLAN_AVAILABLE_NETWORK &network = networkList->Network[j]; + + profile = QString::fromWCharArray(network.strProfileName); + + if (qHash(QLatin1String("WLAN:") + profile) == id.toUInt()) + break; + else + profile.clear(); + } + + local_WlanFreeMemory(networkList); + + if (!profile.isEmpty()) { + WLAN_CONNECTION_PARAMETERS parameters; + parameters.wlanConnectionMode = wlan_connection_mode_profile; + parameters.strProfile = reinterpret_cast<LPCWSTR>(profile.utf16()); + parameters.pDot11Ssid = 0; + parameters.pDesiredBssidList = 0; + parameters.dot11BssType = dot11_BSS_type_any; + parameters.dwFlags = 0; + + DWORD result = local_WlanConnect(handle, &interface.InterfaceGuid, ¶meters, 0); + if (result != ERROR_SUCCESS) { + qWarning("%s: WlanConnect failed with error %ld\n", __FUNCTION__, result); + emit connectionError(id, ConnectError); + break; + } + + break; + } + } + + local_WlanFreeMemory(interfaceList); + + if (profile.isEmpty()) + emit connectionError(id, InterfaceLookupError); +} + +void QNativeWifiEngine::disconnectFromId(const QString &id) +{ + QString interface = getInterfaceFromId(id); + + if (interface.isEmpty()) { + emit connectionError(id, InterfaceLookupError); + return; + } + + QStringList split = interface.mid(1, interface.length() - 2).split('-'); + + GUID guid; + guid.Data1 = split.at(0).toUInt(0, 16); + guid.Data2 = split.at(1).toUShort(0, 16); + guid.Data3 = split.at(2).toUShort(0, 16); + guid.Data4[0] = split.at(3).left(2).toUShort(0, 16); + guid.Data4[1] = split.at(3).right(2).toUShort(0, 16); + for (int i = 0; i < 6; ++i) + guid.Data4[i + 2] = split.at(4).mid(i*2, 2).toUShort(0, 16); + + DWORD result = local_WlanDisconnect(handle, &guid, 0); + if (result != ERROR_SUCCESS) { + qWarning("%s: WlanDisconnect failed with error %ld\n", __FUNCTION__, result); + emit connectionError(id, DisconnectionError); + return; + } +} + +void QNativeWifiEngine::requestUpdate() +{ + // enumerate interfaces + WLAN_INTERFACE_INFO_LIST *interfaceList; + DWORD result = local_WlanEnumInterfaces(handle, 0, &interfaceList); + if (result != ERROR_SUCCESS) { + qWarning("%s: WlanEnumInterfaces failed with error %ld\n", __FUNCTION__, result); + return; + } + + for (unsigned int i = 0; i < interfaceList->dwNumberOfItems; ++i) { + result = local_WlanScan(handle, &interfaceList->InterfaceInfo[i].InterfaceGuid, 0, 0, 0); + if (result != ERROR_SUCCESS) + qWarning("%s: WlanScan failed with error %ld\n", __FUNCTION__, result); + } + + local_WlanFreeMemory(interfaceList); +} + +QNetworkSession::State QNativeWifiEngine::sessionStateForId(const QString &id) +{ + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); + + if (!ptr) + return QNetworkSession::Invalid; + + if (!ptr->isValid) { + return QNetworkSession::Invalid; + } else if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { + return QNetworkSession::Connected; + } else if ((ptr->state & QNetworkConfiguration::Discovered) == + QNetworkConfiguration::Discovered) { + return QNetworkSession::Disconnected; + } else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) { + return QNetworkSession::NotAvailable; + } else if ((ptr->state & QNetworkConfiguration::Undefined) == + QNetworkConfiguration::Undefined) { + return QNetworkSession::NotAvailable; + } + + return QNetworkSession::Invalid; +} + +QT_END_NAMESPACE diff --git a/src/plugins/bearer/nativewifi/qnativewifiengine.h b/src/plugins/bearer/nativewifi/qnativewifiengine.h new file mode 100644 index 0000000..511a6a4 --- /dev/null +++ b/src/plugins/bearer/nativewifi/qnativewifiengine.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** 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 QNATIVEWIFIENGINE_P_H +#define QNATIVEWIFIENGINE_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 <QtNetwork/private/qnetworksessionengine_p.h> + +#include <QtCore/qtimer.h> + +QT_BEGIN_NAMESPACE + +class QNetworkConfigurationPrivate; +struct WLAN_NOTIFICATION_DATA; + +class QNativeWifiEngine : public QNetworkSessionEngine +{ + Q_OBJECT + +public: + QNativeWifiEngine(QObject *parent = 0); + ~QNativeWifiEngine(); + + 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(); + + QNetworkSession::State sessionStateForId(const QString &id); + + inline bool available() const { return handle != 0; } + +public Q_SLOTS: + void scanComplete(); + +private: + QTimer pollTimer; + + Qt::HANDLE handle; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/bearer/networkmanager/main.cpp b/src/plugins/bearer/networkmanager/main.cpp new file mode 100644 index 0000000..b561415 --- /dev/null +++ b/src/plugins/bearer/networkmanager/main.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 "qnetworkmanagerengine.h" + +#include <QtNetwork/qbearerplugin.h> + +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +class QNetworkManagerEnginePlugin : public QBearerEnginePlugin +{ +public: + QNetworkManagerEnginePlugin(); + ~QNetworkManagerEnginePlugin(); + + QStringList keys() const; + QBearerEngine *create(const QString &key) const; +}; + +QNetworkManagerEnginePlugin::QNetworkManagerEnginePlugin() +{ +} + +QNetworkManagerEnginePlugin::~QNetworkManagerEnginePlugin() +{ +} + +QStringList QNetworkManagerEnginePlugin::keys() const +{ + return QStringList() << QLatin1String("networkmanager"); +} + +QBearerEngine *QNetworkManagerEnginePlugin::create(const QString &key) const +{ + if (key == QLatin1String("networkmanager")) + return new QNetworkManagerEngine; + else + return 0; +} + +Q_EXPORT_STATIC_PLUGIN(QNetworkManagerEnginePlugin) +Q_EXPORT_PLUGIN2(qnmbearer, QNetworkManagerEnginePlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/bearer/networkmanager/networkmanager.pro b/src/plugins/bearer/networkmanager/networkmanager.pro new file mode 100644 index 0000000..57f7ca7 --- /dev/null +++ b/src/plugins/bearer/networkmanager/networkmanager.pro @@ -0,0 +1,19 @@ +TARGET = qnmbearer +include(../../qpluginbase.pri) + +QT += network dbus + +DEFINES += BACKEND_NM + +HEADERS += qnmdbushelper.h \ + qnetworkmanagerservice.h \ + qnetworkmanagerengine.h + +SOURCES += main.cpp \ + qnmdbushelper.cpp \ + qnetworkmanagerservice.cpp \ + qnetworkmanagerengine.cpp + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/bearer +target.path += $$[QT_INSTALL_PLUGINS]/bearer +INSTALLS += target diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp new file mode 100644 index 0000000..20dee1f --- /dev/null +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp @@ -0,0 +1,671 @@ +/**************************************************************************** +** +** 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 "qnetworkmanagerengine.h" +#include "qnetworkmanagerservice.h" + +#include <QtNetwork/private/qnetworkconfiguration_p.h> + +#include <QtNetwork/qnetworksession.h> + +#include <QtCore/qdebug.h> + +#include <NetworkManager/NetworkManager.h> +#include <QtDBus> +#include <QDBusConnection> +#include <QDBusError> +#include <QDBusInterface> +#include <QDBusMessage> +#include <QDBusReply> + +QT_BEGIN_NAMESPACE + +QNetworkManagerEngine::QNetworkManagerEngine(QObject *parent) +: QNetworkSessionEngine(parent), + interface(new QNetworkManagerInterface(this)), + systemSettings(new QNetworkManagerSettings(NM_DBUS_SERVICE_SYSTEM_SETTINGS, this)), + userSettings(new QNetworkManagerSettings(NM_DBUS_SERVICE_USER_SETTINGS, this)) +{ + interface->setConnections(); + connect(interface, SIGNAL(deviceAdded(QDBusObjectPath)), + this, SLOT(deviceAdded(QDBusObjectPath))); + connect(interface, SIGNAL(deviceRemoved(QDBusObjectPath)), + this, SLOT(deviceRemoved(QDBusObjectPath))); +#if 0 + connect(interface, SIGNAL(stateChanged(const QString,quint32)), + this, SIGNAL(configurationsChanged())); +#endif + connect(interface, SIGNAL(activationFinished(QDBusPendingCallWatcher*)), + this, SLOT(activationFinished(QDBusPendingCallWatcher*))); + connect(interface, SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)), + this, SLOT(interfacePropertiesChanged(QString,QMap<QString,QVariant>))); + + qDBusRegisterMetaType<QNmSettingsMap>(); + + systemSettings->setConnections(); + connect(systemSettings, SIGNAL(newConnection(QDBusObjectPath)), + this, SLOT(newConnection(QDBusObjectPath))); + + userSettings->setConnections(); + connect(userSettings, SIGNAL(newConnection(QDBusObjectPath)), + this, SLOT(newConnection(QDBusObjectPath))); + + // Get current list of access points. + foreach (const QDBusObjectPath &devicePath, interface->getDevices()) + deviceAdded(devicePath); + + // Get connections. + foreach (const QDBusObjectPath &settingsPath, systemSettings->listConnections()) + newConnection(settingsPath, systemSettings); + foreach (const QDBusObjectPath &settingsPath, userSettings->listConnections()) + newConnection(settingsPath, userSettings); + + // Get active connections. + foreach (const QDBusObjectPath &acPath, interface->activeConnections()) { + QNetworkManagerConnectionActive *activeConnection = + new QNetworkManagerConnectionActive(acPath.path()); + activeConnections.insert(acPath.path(), activeConnection); + + activeConnection->setConnections(); + connect(activeConnection, SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)), + this, SLOT(activeConnectionPropertiesChanged(QString,QMap<QString,QVariant>))); + } +} + +QNetworkManagerEngine::~QNetworkManagerEngine() +{ +} + +void QNetworkManagerEngine::doRequestUpdate() +{ + emit updateCompleted(); +} + +QString QNetworkManagerEngine::getInterfaceFromId(const QString &id) +{ + foreach (const QDBusObjectPath &acPath, interface->activeConnections()) { + QNetworkManagerConnectionActive activeConnection(acPath.path()); + + const QString identifier = QString::number(qHash(activeConnection.serviceName() + ' ' + + activeConnection.connection().path())); + + if (id == identifier) { + QList<QDBusObjectPath> devices = activeConnection.devices(); + + if (devices.isEmpty()) + continue; + + if (devices.count() > 1) + qDebug() << "multiple network interfaces for" << id; + + QNetworkManagerInterfaceDevice device(devices.at(0).path()); + return device.interface().name(); + } + } + + return QString(); +} + +bool QNetworkManagerEngine::hasIdentifier(const QString &id) +{ + if (connectionFromId(id)) + return true; + + for (int i = 0; i < accessPoints.count(); ++i) { + QNetworkManagerInterfaceAccessPoint *accessPoint = accessPoints.at(i); + + const QString identifier = + QString::number(qHash(accessPoint->connectionInterface()->path())); + + if (id == identifier) + return true; + } + + return false; +} + +QString QNetworkManagerEngine::bearerName(const QString &id) +{ + QNetworkManagerSettingsConnection *connection = connectionFromId(id); + + if (!connection) + return QString(); + + QNmSettingsMap map = connection->getSettings(); + const QString connectionType = map.value("connection").value("type").toString(); + + if (connectionType == "802-3-ethernet") + return QLatin1String("Ethernet"); + else if (connectionType == "802-11-wireless") + return QLatin1String("WLAN"); + else if (connectionType == "gsm") + return QLatin1String("2G"); + else if (connectionType == "cdma") + return QLatin1String("CDMA2000"); + else + return QString(); +} + +void QNetworkManagerEngine::connectToId(const QString &id) +{ + QNetworkManagerSettingsConnection *connection = connectionFromId(id); + + if (!connection) + return; + + QNmSettingsMap map = connection->getSettings(); + const QString connectionType = map.value("connection").value("type").toString(); + + QString dbusDevicePath; + foreach (const QDBusObjectPath &devicePath, interface->getDevices()) { + QNetworkManagerInterfaceDevice device(devicePath.path()); + if (device.deviceType() == DEVICE_TYPE_802_3_ETHERNET && + connectionType == QLatin1String("802-3-ethernet")) { + dbusDevicePath = devicePath.path(); + break; + } else if (device.deviceType() == DEVICE_TYPE_802_11_WIRELESS && + connectionType == QLatin1String("802-11-wireless")) { + dbusDevicePath = devicePath.path(); + break; + } + } + + const QString service = connection->connectionInterface()->service(); + const QString settingsPath = connection->connectionInterface()->path(); + + interface->activateConnection(service, QDBusObjectPath(settingsPath), + QDBusObjectPath(dbusDevicePath), QDBusObjectPath("/")); +} + +void QNetworkManagerEngine::disconnectFromId(const QString &id) +{ + foreach (const QDBusObjectPath &acPath, interface->activeConnections()) { + QNetworkManagerConnectionActive activeConnection(acPath.path()); + + const QString identifier = QString::number(qHash(activeConnection.serviceName() + ' ' + + activeConnection.connection().path())); + + if (id == identifier && accessPointConfigurations.contains(id)) { + interface->deactivateConnection(acPath); + break; + } + } +} + +void QNetworkManagerEngine::requestUpdate() +{ + QTimer::singleShot(0, this, SLOT(doRequestUpdate())); +} + +void QNetworkManagerEngine::interfacePropertiesChanged(const QString &path, + const QMap<QString, QVariant> &properties) +{ + QMapIterator<QString, QVariant> i(properties); + while (i.hasNext()) { + i.next(); + + if (i.key() == QLatin1String("ActiveConnections")) { + // Active connections changed, update configurations. + + QList<QDBusObjectPath> activeConnections = + qdbus_cast<QList<QDBusObjectPath> >(i.value().value<QDBusArgument>()); + + QStringList identifiers = accessPointConfigurations.keys(); + foreach (const QString &id, identifiers) + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); + + QStringList priorActiveConnections = this->activeConnections.keys(); + + foreach (const QDBusObjectPath &acPath, activeConnections) { + priorActiveConnections.removeOne(acPath.path()); + QNetworkManagerConnectionActive *activeConnection = + this->activeConnections.value(acPath.path()); + if (!activeConnection) { + activeConnection = new QNetworkManagerConnectionActive(acPath.path()); + this->activeConnections.insert(acPath.path(), activeConnection); + + activeConnection->setConnections(); + connect(activeConnection, SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)), + this, SLOT(activeConnectionPropertiesChanged(QString,QMap<QString,QVariant>))); + } + + const QString id = QString::number(qHash(activeConnection->serviceName() + ' ' + + activeConnection->connection().path())); + + identifiers.removeOne(id); + + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); + if (ptr) { + if (activeConnection->state() == 2 && + ptr->state != QNetworkConfiguration::Active) { + ptr->state = QNetworkConfiguration::Active; + emit configurationChanged(ptr); + } + } + } + + while (!priorActiveConnections.isEmpty()) + delete this->activeConnections.take(priorActiveConnections.takeFirst()); + + while (!identifiers.isEmpty()) { + // These configurations are not active + QNetworkConfigurationPrivatePointer ptr = + accessPointConfigurations.value(identifiers.takeFirst()); + + if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { + ptr->state = QNetworkConfiguration::Discovered; + emit configurationChanged(ptr); + } + } + } + } +} + +void QNetworkManagerEngine::activeConnectionPropertiesChanged(const QString &path, + const QMap<QString, QVariant> &properties) +{ + QNetworkManagerConnectionActive *activeConnection = activeConnections.value(path); + + if (!activeConnection) + return; + + const QString id = QString::number(qHash(activeConnection->serviceName() + ' ' + + activeConnection->connection().path())); + + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); + if (ptr) { + if (activeConnection->state() == 2 && + ptr->state != QNetworkConfiguration::Active) { + ptr->state = QNetworkConfiguration::Active; + emit configurationChanged(ptr); + } + } +} + +void QNetworkManagerEngine::devicePropertiesChanged(const QString &path, + const QMap<QString, QVariant> &properties) +{ + qDebug() << Q_FUNC_INFO << path; + qDebug() << properties; +} + +void QNetworkManagerEngine::deviceAdded(const QDBusObjectPath &path) +{ + QNetworkManagerInterfaceDevice device(path.path()); + if (device.deviceType() == DEVICE_TYPE_802_11_WIRELESS) { + QNetworkManagerInterfaceDeviceWireless *wirelessDevice = + new QNetworkManagerInterfaceDeviceWireless(device.connectionInterface()->path()); + wirelessDevices.insert(path.path(), wirelessDevice); + + wirelessDevice->setConnections(); + connect(wirelessDevice, SIGNAL(accessPointAdded(QString,QDBusObjectPath)), + this, SLOT(newAccessPoint(QString,QDBusObjectPath))); + connect(wirelessDevice, SIGNAL(accessPointRemoved(QString,QDBusObjectPath)), + this, SLOT(removeAccessPoint(QString,QDBusObjectPath))); + connect(wirelessDevice, SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)), + this, SLOT(devicePropertiesChanged(QString,QMap<QString,QVariant>))); + + foreach (const QDBusObjectPath &apPath, wirelessDevice->getAccessPoints()) + newAccessPoint(QString(), apPath); + } +} + +void QNetworkManagerEngine::deviceRemoved(const QDBusObjectPath &path) +{ + delete wirelessDevices.value(path.path()); +} + +void QNetworkManagerEngine::newConnection(const QDBusObjectPath &path, + QNetworkManagerSettings *settings) +{ + if (!settings) + settings = qobject_cast<QNetworkManagerSettings *>(sender()); + + if (!settings) + return; + + QNetworkManagerSettingsConnection *connection = + new QNetworkManagerSettingsConnection(settings->connectionInterface()->service(), + path.path()); + connections.append(connection); + + connect(connection, SIGNAL(removed(QString)), this, SLOT(removeConnection(QString))); + connect(connection, SIGNAL(updated(const QNmSettingsMap&)), + this, SLOT(updateConnection(const QNmSettingsMap&))); + + const QString service = connection->connectionInterface()->service(); + const QString settingsPath = connection->connectionInterface()->path(); + + QNetworkConfigurationPrivate *cpPriv = + parseConnection(service, settingsPath, connection->getSettings()); + + // Check if connection is active. + foreach (const QDBusObjectPath &acPath, interface->activeConnections()) { + QNetworkManagerConnectionActive activeConnection(acPath.path()); + + if (activeConnection.serviceName() == service && + activeConnection.connection().path() == settingsPath && + activeConnection.state() == 2) { + cpPriv->state |= QNetworkConfiguration::Active; + break; + } + } + + QNetworkConfigurationPrivatePointer ptr(cpPriv); + accessPointConfigurations.insert(ptr->id, ptr); + emit configurationAdded(ptr); +} + +void QNetworkManagerEngine::removeConnection(const QString &path) +{ + QNetworkManagerSettingsConnection *connection = + qobject_cast<QNetworkManagerSettingsConnection *>(sender()); + if (!connection) + return; + + connections.removeAll(connection); + + const QString id = QString::number(qHash(connection->connectionInterface()->service() + ' ' + + connection->connectionInterface()->path())); + + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(id); + ptr->isValid = false; + emit configurationRemoved(ptr); +} + +void QNetworkManagerEngine::updateConnection(const QNmSettingsMap &settings) +{ + QNetworkManagerSettingsConnection *connection = + qobject_cast<QNetworkManagerSettingsConnection *>(sender()); + if (!connection) + return; + + const QString service = connection->connectionInterface()->service(); + const QString settingsPath = connection->connectionInterface()->path(); + + qDebug() << "Should parse connection directly into existing configuration"; + QNetworkConfigurationPrivate *cpPriv = parseConnection(service, settingsPath, settings); + + // Check if connection is active. + foreach (const QDBusObjectPath &acPath, interface->activeConnections()) { + QNetworkManagerConnectionActive activeConnection(acPath.path()); + + if (activeConnection.serviceName() == service && + activeConnection.connection().path() == settingsPath && + activeConnection.state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) { + cpPriv->state |= QNetworkConfiguration::Active; + break; + } + } + + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(cpPriv->id); + + ptr->isValid = cpPriv->isValid; + ptr->name = cpPriv->name; + ptr->id = cpPriv->id; + ptr->state = cpPriv->state; + + emit configurationChanged(ptr); + delete cpPriv; +} + +void QNetworkManagerEngine::activationFinished(QDBusPendingCallWatcher *watcher) +{ + QDBusPendingReply<QDBusObjectPath> reply = *watcher; + if (reply.isError()) { + qDebug() << "error connecting NM connection"; + } else { + QDBusObjectPath result = reply.value(); + + QNetworkManagerConnectionActive activeConnection(result.path()); + + const QString id = QString::number(qHash(activeConnection.serviceName() + ' ' + + activeConnection.connection().path())); + + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); + if (ptr) { + if (activeConnection.state() == 2 && + ptr->state != QNetworkConfiguration::Active) { + ptr->state = QNetworkConfiguration::Active; + emit configurationChanged(ptr); + } + } + } +} + +void QNetworkManagerEngine::newAccessPoint(const QString &path, const QDBusObjectPath &objectPath) +{ + QNetworkManagerInterfaceAccessPoint *accessPoint = + new QNetworkManagerInterfaceAccessPoint(objectPath.path()); + accessPoints.append(accessPoint); + + accessPoint->setConnections(); + connect(accessPoint, SIGNAL(propertiesChanged(QMap<QString,QVariant>)), + this, SLOT(updateAccessPoint(QMap<QString,QVariant>))); + + // Check if configuration for this SSID already exists. + for (int i = 0; i < accessPoints.count(); ++i) { + if (accessPoint != accessPoints.at(i) && + accessPoint->ssid() == accessPoints.at(i)->ssid()) { + return; + } + } + + // Check if configuration exists for connection. + for (int i = 0; i < connections.count(); ++i) { + QNetworkManagerSettingsConnection *connection = connections.at(i); + + if (accessPoint->ssid() == connection->getSsid()) { + const QString service = connection->connectionInterface()->service(); + const QString settingsPath = connection->connectionInterface()->path(); + const QString connectionId = QString::number(qHash(service + ' ' + settingsPath)); + + QNetworkConfigurationPrivatePointer ptr = + accessPointConfigurations.value(connectionId); + ptr->state = QNetworkConfiguration::Discovered; + emit configurationChanged(ptr); + return; + } + } + + // New access point. + QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate); + + ptr->name = accessPoint->ssid(); + ptr->isValid = true; + ptr->id = QString::number(qHash(objectPath.path())); + ptr->type = QNetworkConfiguration::InternetAccessPoint; + ptr->purpose = QNetworkConfiguration::PublicPurpose; + ptr->state = QNetworkConfiguration::Undefined; + ptr->bearer = QLatin1String("WLAN"); + + accessPointConfigurations.insert(ptr->id, ptr); + emit configurationAdded(ptr); +} + +void QNetworkManagerEngine::removeAccessPoint(const QString &path, + const QDBusObjectPath &objectPath) +{ + for (int i = 0; i < accessPoints.count(); ++i) { + QNetworkManagerInterfaceAccessPoint *accessPoint = accessPoints.at(i); + + if (accessPoint->connectionInterface()->path() == objectPath.path()) { + accessPoints.removeOne(accessPoint); + + if (configuredAccessPoints.contains(accessPoint)) { + // find connection and change state to Defined + configuredAccessPoints.removeOne(accessPoint); + qDebug() << "At least one connection is no longer discovered."; + } else { + // emit configurationRemoved(cpPriv); + qDebug() << "An unconfigured wifi access point was removed."; + } + + break; + } + } +} + +void QNetworkManagerEngine::updateAccessPoint(const QMap<QString, QVariant> &map) +{ + QNetworkManagerInterfaceAccessPoint *accessPoint = + qobject_cast<QNetworkManagerInterfaceAccessPoint *>(sender()); + if (!accessPoint) + return; + + qDebug() << "update access point" << accessPoint; +} + +QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QString &service, + const QString &settingsPath, + const QNmSettingsMap &map) +{ + QNetworkConfigurationPrivate *cpPriv = new QNetworkConfigurationPrivate; + cpPriv->name = map.value("connection").value("id").toString(); + cpPriv->isValid = true; + cpPriv->id = QString::number(qHash(service + ' ' + settingsPath)); + cpPriv->type = QNetworkConfiguration::InternetAccessPoint; + + cpPriv->purpose = QNetworkConfiguration::PublicPurpose; + + cpPriv->state = QNetworkConfiguration::Defined; + + const QString connectionType = map.value("connection").value("type").toString(); + + if (connectionType == QLatin1String("802-3-ethernet")) { + cpPriv->bearer = QLatin1String("Ethernet"); + + foreach (const QDBusObjectPath &devicePath, interface->getDevices()) { + QNetworkManagerInterfaceDevice device(devicePath.path()); + if (device.deviceType() == DEVICE_TYPE_802_3_ETHERNET) { + QNetworkManagerInterfaceDeviceWired wiredDevice(device.connectionInterface()->path()); + if (wiredDevice.carrier()) { + cpPriv->state |= QNetworkConfiguration::Discovered; + break; + } + + } + } + } else if (connectionType == QLatin1String("802-11-wireless")) { + cpPriv->bearer = QLatin1String("WLAN"); + + const QString connectionSsid = map.value("802-11-wireless").value("ssid").toString(); + + for (int i = 0; i < accessPoints.count(); ++i) { + if (connectionSsid == accessPoints.at(i)->ssid()) { + cpPriv->state |= QNetworkConfiguration::Discovered; + if (!configuredAccessPoints.contains(accessPoints.at(i))) { + configuredAccessPoints.append(accessPoints.at(i)); + + const QString accessPointId = + QString::number(qHash(accessPoints.at(i)->connectionInterface()->path())); + QNetworkConfigurationPrivatePointer ptr = + accessPointConfigurations.take(accessPointId); + emit configurationRemoved(ptr); + } + break; + } + } + } else if (connectionType == "gsm") { + cpPriv->bearer = QLatin1String("2G"); + } else if (connectionType == "cdma") { + cpPriv->bearer = QLatin1String("CDMA2000"); + } + + return cpPriv; +} + +QNetworkManagerSettingsConnection *QNetworkManagerEngine::connectionFromId(const QString &id) const +{ + for (int i = 0; i < connections.count(); ++i) { + QNetworkManagerSettingsConnection *connection = connections.at(i); + const QString service = connection->connectionInterface()->service(); + const QString settingsPath = connection->connectionInterface()->path(); + + const QString identifier = QString::number(qHash(service + ' ' + settingsPath)); + + if (id == identifier) + return connection; + } + + return 0; +} + +QNetworkSession::State QNetworkManagerEngine::sessionStateForId(const QString &id) +{ + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); + + if (!ptr) + return QNetworkSession::Invalid; + + if (!ptr->isValid) + return QNetworkSession::Invalid; + + foreach (const QString &acPath, activeConnections.keys()) { + QNetworkManagerConnectionActive *activeConnection = activeConnections.value(acPath); + + const QString identifier = QString::number(qHash(activeConnection->serviceName() + ' ' + + activeConnection->connection().path())); + + if (id == identifier) { + switch (activeConnection->state()) { + case 0: + return QNetworkSession::Disconnected; + case 1: + return QNetworkSession::Connecting; + case 2: + return QNetworkSession::Connected; + } + } + } + + if ((ptr->state & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) + return QNetworkSession::Disconnected; + else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) + return QNetworkSession::NotAvailable; + else if ((ptr->state & QNetworkConfiguration::Undefined) == QNetworkConfiguration::Undefined) + return QNetworkSession::NotAvailable; + + return QNetworkSession::Invalid; +} + +QT_END_NAMESPACE + diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h new file mode 100644 index 0000000..1636c91 --- /dev/null +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h @@ -0,0 +1,127 @@ +/**************************************************************************** +** +** 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 QNETWORKMANAGERENGINE_P_H +#define QNETWORKMANAGERENGINE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of the QLibrary class. This header file may change from +// version to version without notice, or even be removed. +// +// We mean it. +// + +#include <QtNetwork/private/qnetworksessionengine_p.h> + +#include "qnetworkmanagerservice.h" + +#include <QMap> +#include <QVariant> + +QT_BEGIN_NAMESPACE + +class QNetworkManagerEngine : public QNetworkSessionEngine +{ + Q_OBJECT + +public: + QNetworkManagerEngine(QObject *parent = 0); + ~QNetworkManagerEngine(); + + 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(); + + QNetworkSession::State sessionStateForId(const QString &id); + +private Q_SLOTS: + void interfacePropertiesChanged(const QString &path, + const QMap<QString, QVariant> &properties); + void activeConnectionPropertiesChanged(const QString &path, + const QMap<QString, QVariant> &properties); + void devicePropertiesChanged(const QString &path, + const QMap<QString, QVariant> &properties); + + void deviceAdded(const QDBusObjectPath &path); + void deviceRemoved(const QDBusObjectPath &path); + + void newConnection(const QDBusObjectPath &path, QNetworkManagerSettings *settings = 0); + void removeConnection(const QString &path); + void updateConnection(const QNmSettingsMap &settings); + void activationFinished(QDBusPendingCallWatcher *watcher); + + void newAccessPoint(const QString &path, const QDBusObjectPath &objectPath); + void removeAccessPoint(const QString &path, const QDBusObjectPath &objectPath); + void updateAccessPoint(const QMap<QString, QVariant> &map); + + void doRequestUpdate(); + +private: + QNetworkConfigurationPrivate *parseConnection(const QString &service, + const QString &settingsPath, + const QNmSettingsMap &map); + QNetworkManagerSettingsConnection *connectionFromId(const QString &id) const; + +private: + QNetworkManagerInterface *interface; + QNetworkManagerSettings *systemSettings; + QNetworkManagerSettings *userSettings; + QHash<QString, QNetworkManagerInterfaceDeviceWireless *> wirelessDevices; + QHash<QString, QNetworkManagerConnectionActive *> activeConnections; + QList<QNetworkManagerSettingsConnection *> connections; + QList<QNetworkManagerInterfaceAccessPoint *> accessPoints; + QList<QNetworkManagerInterfaceAccessPoint *> configuredAccessPoints; +}; + +QT_END_NAMESPACE + +#endif + diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp new file mode 100644 index 0000000..3843f27 --- /dev/null +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp @@ -0,0 +1,1048 @@ +/**************************************************************************** +** +** 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 <QObject> +#include <QList> +#include <QtDBus> +#include <QDBusConnection> +#include <QDBusError> +#include <QDBusInterface> +#include <QDBusMessage> +#include <QDBusReply> +#include <QDBusPendingCallWatcher> +#include <QDBusObjectPath> +#include <QDBusPendingCall> + +#include <NetworkManager/NetworkManager.h> + +#include "qnmdbushelper.h" +#include "qnetworkmanagerservice.h" + +//Q_DECLARE_METATYPE(QList<uint>) +QT_BEGIN_NAMESPACE + +static QDBusConnection dbusConnection = QDBusConnection::systemBus(); +//static QDBusInterface iface(NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, dbusConnection); + +class QNetworkManagerInterfacePrivate +{ +public: + QDBusInterface *connectionInterface; + bool valid; +}; + +QNetworkManagerInterface::QNetworkManagerInterface(QObject *parent) + : QObject(parent), nmDBusHelper(0) +{ + d = new QNetworkManagerInterfacePrivate(); + d->connectionInterface = new QDBusInterface(NM_DBUS_SERVICE, + NM_DBUS_PATH, + NM_DBUS_INTERFACE, + dbusConnection); + if (!d->connectionInterface->isValid()) { + qWarning() << "Could not find NetworkManager"; + d->valid = false; + return; + } + d->valid = true; + nmDBusHelper = new QNmDBusHelper; + connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(const QString &,QMap<QString,QVariant>)), + this,SIGNAL(propertiesChanged( const QString &, QMap<QString,QVariant>))); + connect(nmDBusHelper,SIGNAL(pathForStateChanged(const QString &, quint32)), + this, SIGNAL(stateChanged(const QString&, quint32))); + +} + +QNetworkManagerInterface::~QNetworkManagerInterface() +{ + if (nmDBusHelper) + delete nmDBusHelper; + delete d->connectionInterface; + delete d; +} + +bool QNetworkManagerInterface::isValid() +{ + return d->valid; +} + +bool QNetworkManagerInterface::setConnections() +{ + if(!isValid() ) + return false; + bool allOk = false; + if (!dbusConnection.connect(NM_DBUS_SERVICE, + NM_DBUS_PATH, + NM_DBUS_INTERFACE, + "PropertiesChanged", + nmDBusHelper,SLOT(slotPropertiesChanged( QMap<QString,QVariant>)))) { + allOk = true; + } + if (!dbusConnection.connect(NM_DBUS_SERVICE, + NM_DBUS_PATH, + NM_DBUS_INTERFACE, + "DeviceAdded", + this,SIGNAL(deviceAdded(QDBusObjectPath)))) { + allOk = true; + } + if (!dbusConnection.connect(NM_DBUS_SERVICE, + NM_DBUS_PATH, + NM_DBUS_INTERFACE, + "DeviceRemoved", + this,SIGNAL(deviceRemoved(QDBusObjectPath)))) { + allOk = true; + } + + return allOk; +} + +QDBusInterface *QNetworkManagerInterface::connectionInterface() const +{ + return d->connectionInterface; +} + +QList <QDBusObjectPath> QNetworkManagerInterface::getDevices() const +{ + QDBusReply<QList<QDBusObjectPath> > reply = d->connectionInterface->call("GetDevices"); + return reply.value(); +} + +void QNetworkManagerInterface::activateConnection( const QString &serviceName, + QDBusObjectPath connectionPath, + QDBusObjectPath devicePath, + QDBusObjectPath specificObject) +{ + QDBusPendingCall pendingCall = d->connectionInterface->asyncCall("ActivateConnection", + QVariant(serviceName), + QVariant::fromValue(connectionPath), + QVariant::fromValue(devicePath), + QVariant::fromValue(specificObject)); + + QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(pendingCall, this); + connect(callWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)), + this, SIGNAL(activationFinished(QDBusPendingCallWatcher*))); +} + +void QNetworkManagerInterface::deactivateConnection(QDBusObjectPath connectionPath) const +{ + d->connectionInterface->call("DeactivateConnection", QVariant::fromValue(connectionPath)); +} + +bool QNetworkManagerInterface::wirelessEnabled() const +{ + return d->connectionInterface->property("WirelessEnabled").toBool(); +} + +bool QNetworkManagerInterface::wirelessHardwareEnabled() const +{ + return d->connectionInterface->property("WirelessHardwareEnabled").toBool(); +} + +QList <QDBusObjectPath> QNetworkManagerInterface::activeConnections() const +{ + QVariant prop = d->connectionInterface->property("ActiveConnections"); + return prop.value<QList<QDBusObjectPath> >(); +} + +quint32 QNetworkManagerInterface::state() +{ + return d->connectionInterface->property("State").toUInt(); +} + +///////////// +class QNetworkManagerInterfaceAccessPointPrivate +{ +public: + QDBusInterface *connectionInterface; + QString path; + bool valid; +}; + +QNetworkManagerInterfaceAccessPoint::QNetworkManagerInterfaceAccessPoint(const QString &dbusPathName, QObject *parent) + : QObject(parent), nmDBusHelper(0) +{ + d = new QNetworkManagerInterfaceAccessPointPrivate(); + d->path = dbusPathName; + d->connectionInterface = new QDBusInterface(NM_DBUS_SERVICE, + d->path, + NM_DBUS_INTERFACE_ACCESS_POINT, + dbusConnection); + if (!d->connectionInterface->isValid()) { + d->valid = false; + qWarning() << "Could not find InterfaceAccessPoint"; + return; + } + d->valid = true; + +} + +QNetworkManagerInterfaceAccessPoint::~QNetworkManagerInterfaceAccessPoint() +{ + if (nmDBusHelper) + delete nmDBusHelper; + delete d->connectionInterface; + delete d; +} + +bool QNetworkManagerInterfaceAccessPoint::isValid() +{ + return d->valid; +} + +bool QNetworkManagerInterfaceAccessPoint::setConnections() +{ + if(!isValid() ) + return false; + + bool allOk = false; + if (nmDBusHelper) + delete nmDBusHelper; + nmDBusHelper = 0; + nmDBusHelper = new QNmDBusHelper; + connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(const QString &,QMap<QString,QVariant>)), + this,SIGNAL(propertiesChanged( const QString &, QMap<QString,QVariant>))); + + if(dbusConnection.connect(NM_DBUS_SERVICE, + d->path, + NM_DBUS_INTERFACE_ACCESS_POINT, + "PropertiesChanged", + nmDBusHelper,SLOT(slotPropertiesChanged( QMap<QString,QVariant>))) ) { + allOk = true; + + } + return allOk; +} + +QDBusInterface *QNetworkManagerInterfaceAccessPoint::connectionInterface() const +{ + return d->connectionInterface; +} + +quint32 QNetworkManagerInterfaceAccessPoint::flags() const +{ + return d->connectionInterface->property("Flags").toUInt(); +} + +quint32 QNetworkManagerInterfaceAccessPoint::wpaFlags() const +{ + return d->connectionInterface->property("WpaFlags").toUInt(); +} + +quint32 QNetworkManagerInterfaceAccessPoint::rsnFlags() const +{ + return d->connectionInterface->property("RsnFlags").toUInt(); +} + +QString QNetworkManagerInterfaceAccessPoint::ssid() const +{ + return d->connectionInterface->property("Ssid").toString(); +} + +quint32 QNetworkManagerInterfaceAccessPoint::frequency() const +{ + return d->connectionInterface->property("Frequency").toUInt(); +} + +QString QNetworkManagerInterfaceAccessPoint::hwAddress() const +{ + return d->connectionInterface->property("HwAddress").toString(); +} + +quint32 QNetworkManagerInterfaceAccessPoint::mode() const +{ + return d->connectionInterface->property("Mode").toUInt(); +} + +quint32 QNetworkManagerInterfaceAccessPoint::maxBitrate() const +{ + return d->connectionInterface->property("MaxBitrate").toUInt(); +} + +quint32 QNetworkManagerInterfaceAccessPoint::strength() const +{ + return d->connectionInterface->property("Strength").toUInt(); +} + +///////////// +class QNetworkManagerInterfaceDevicePrivate +{ +public: + QDBusInterface *connectionInterface; + QString path; + bool valid; +}; + +QNetworkManagerInterfaceDevice::QNetworkManagerInterfaceDevice(const QString &deviceObjectPath, QObject *parent) + : QObject(parent), nmDBusHelper(0) +{ + d = new QNetworkManagerInterfaceDevicePrivate(); + d->path = deviceObjectPath; + d->connectionInterface = new QDBusInterface(NM_DBUS_SERVICE, + d->path, + NM_DBUS_INTERFACE_DEVICE, + dbusConnection); + if (!d->connectionInterface->isValid()) { + d->valid = false; + qWarning() << "Could not find NetworkManager"; + return; + } + d->valid = true; +} + +QNetworkManagerInterfaceDevice::~QNetworkManagerInterfaceDevice() +{ + if (nmDBusHelper) + delete nmDBusHelper; + delete d->connectionInterface; + delete d; +} + +bool QNetworkManagerInterfaceDevice::isValid() +{ + return d->valid; +} + +bool QNetworkManagerInterfaceDevice::setConnections() +{ + if(!isValid() ) + return false; + + bool allOk = false; + if (nmDBusHelper) + delete nmDBusHelper; + nmDBusHelper = 0; + nmDBusHelper = new QNmDBusHelper; + connect(nmDBusHelper,SIGNAL(pathForStateChanged(const QString &, quint32)), + this, SIGNAL(stateChanged(const QString&, quint32))); + if(dbusConnection.connect(NM_DBUS_SERVICE, + d->path, + NM_DBUS_INTERFACE_DEVICE, + "StateChanged", + nmDBusHelper,SLOT(deviceStateChanged(quint32)))) { + allOk = true; + } + return allOk; +} + +QDBusInterface *QNetworkManagerInterfaceDevice::connectionInterface() const +{ + return d->connectionInterface; +} + +QString QNetworkManagerInterfaceDevice::udi() const +{ + return d->connectionInterface->property("Udi").toString(); +} + +QNetworkInterface QNetworkManagerInterfaceDevice::interface() const +{ + return QNetworkInterface::interfaceFromName(d->connectionInterface->property("Interface").toString()); +} + +quint32 QNetworkManagerInterfaceDevice::ip4Address() const +{ + return d->connectionInterface->property("Ip4Address").toUInt(); +} + +quint32 QNetworkManagerInterfaceDevice::state() const +{ + return d->connectionInterface->property("State").toUInt(); +} + +quint32 QNetworkManagerInterfaceDevice::deviceType() const +{ + return d->connectionInterface->property("DeviceType").toUInt(); +} + +QDBusObjectPath QNetworkManagerInterfaceDevice::ip4config() const +{ + QVariant prop = d->connectionInterface->property("Ip4Config"); + return prop.value<QDBusObjectPath>(); +} + +///////////// +class QNetworkManagerInterfaceDeviceWiredPrivate +{ +public: + QDBusInterface *connectionInterface; + QString path; + bool valid; +}; + +QNetworkManagerInterfaceDeviceWired::QNetworkManagerInterfaceDeviceWired(const QString &ifaceDevicePath, QObject *parent) + : QObject(parent), nmDBusHelper(0) +{ + d = new QNetworkManagerInterfaceDeviceWiredPrivate(); + d->path = ifaceDevicePath; + d->connectionInterface = new QDBusInterface(NM_DBUS_SERVICE, + d->path, + NM_DBUS_INTERFACE_DEVICE_WIRED, + dbusConnection, parent); + if (!d->connectionInterface->isValid()) { + d->valid = false; + qWarning() << "Could not find InterfaceDeviceWired"; + return; + } + d->valid = true; +} + +QNetworkManagerInterfaceDeviceWired::~QNetworkManagerInterfaceDeviceWired() +{ + if (nmDBusHelper) + delete nmDBusHelper; + delete d->connectionInterface; + delete d; +} + +bool QNetworkManagerInterfaceDeviceWired::isValid() +{ + + return d->valid; +} + +bool QNetworkManagerInterfaceDeviceWired::setConnections() +{ + if(!isValid() ) + return false; + + bool allOk = false; + + if (nmDBusHelper) + delete nmDBusHelper; + nmDBusHelper = 0; + nmDBusHelper = new QNmDBusHelper; + connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(const QString &,QMap<QString,QVariant>)), + this,SIGNAL(propertiesChanged( const QString &, QMap<QString,QVariant>))); + if(dbusConnection.connect(NM_DBUS_SERVICE, + d->path, + NM_DBUS_INTERFACE_DEVICE_WIRED, + "PropertiesChanged", + nmDBusHelper,SLOT(slotPropertiesChanged( QMap<QString,QVariant>))) ) { + allOk = true; + } + return allOk; +} + +QDBusInterface *QNetworkManagerInterfaceDeviceWired::connectionInterface() const +{ + return d->connectionInterface; +} + +QString QNetworkManagerInterfaceDeviceWired::hwAddress() const +{ + return d->connectionInterface->property("HwAddress").toString(); +} + +quint32 QNetworkManagerInterfaceDeviceWired::speed() const +{ + return d->connectionInterface->property("Speed").toUInt(); +} + +bool QNetworkManagerInterfaceDeviceWired::carrier() const +{ + return d->connectionInterface->property("Carrier").toBool(); +} + +///////////// +class QNetworkManagerInterfaceDeviceWirelessPrivate +{ +public: + QDBusInterface *connectionInterface; + QString path; + bool valid; +}; + +QNetworkManagerInterfaceDeviceWireless::QNetworkManagerInterfaceDeviceWireless(const QString &ifaceDevicePath, QObject *parent) + : QObject(parent), nmDBusHelper(0) +{ + d = new QNetworkManagerInterfaceDeviceWirelessPrivate(); + d->path = ifaceDevicePath; + d->connectionInterface = new QDBusInterface(NM_DBUS_SERVICE, + d->path, + NM_DBUS_INTERFACE_DEVICE_WIRELESS, + dbusConnection, parent); + if (!d->connectionInterface->isValid()) { + d->valid = false; + qWarning() << "Could not find InterfaceDeviceWireless"; + return; + } + d->valid = true; +} + +QNetworkManagerInterfaceDeviceWireless::~QNetworkManagerInterfaceDeviceWireless() +{ + if (nmDBusHelper) + delete nmDBusHelper; + delete d->connectionInterface; + delete d; +} + +bool QNetworkManagerInterfaceDeviceWireless::isValid() +{ + return d->valid; +} + +bool QNetworkManagerInterfaceDeviceWireless::setConnections() +{ + if(!isValid() ) + return false; + + bool allOk = false; + if (nmDBusHelper) + delete nmDBusHelper; + nmDBusHelper = 0; + nmDBusHelper = new QNmDBusHelper; + connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(const QString &,QMap<QString,QVariant>)), + this,SIGNAL(propertiesChanged( const QString &, QMap<QString,QVariant>))); + + connect(nmDBusHelper, SIGNAL(pathForAccessPointAdded(const QString &,QDBusObjectPath)), + this,SIGNAL(accessPointAdded(const QString &,QDBusObjectPath))); + + connect(nmDBusHelper, SIGNAL(pathForAccessPointRemoved(const QString &,QDBusObjectPath)), + this,SIGNAL(accessPointRemoved(const QString &,QDBusObjectPath))); + + if(!dbusConnection.connect(NM_DBUS_SERVICE, + d->path, + NM_DBUS_INTERFACE_DEVICE_WIRELESS, + "AccessPointAdded", + nmDBusHelper, SLOT(slotAccessPointAdded( QDBusObjectPath )))) { + allOk = true; + } + + + if(!dbusConnection.connect(NM_DBUS_SERVICE, + d->path, + NM_DBUS_INTERFACE_DEVICE_WIRELESS, + "AccessPointRemoved", + nmDBusHelper, SLOT(slotAccessPointRemoved( QDBusObjectPath )))) { + allOk = true; + } + + + if(!dbusConnection.connect(NM_DBUS_SERVICE, + d->path, + NM_DBUS_INTERFACE_DEVICE_WIRELESS, + "PropertiesChanged", + nmDBusHelper,SLOT(slotPropertiesChanged( QMap<QString,QVariant>)))) { + allOk = true; + } + + return allOk; +} + +QDBusInterface *QNetworkManagerInterfaceDeviceWireless::connectionInterface() const +{ + return d->connectionInterface; +} + +QList <QDBusObjectPath> QNetworkManagerInterfaceDeviceWireless::getAccessPoints() +{ + QDBusReply<QList<QDBusObjectPath> > reply = d->connectionInterface->call("GetAccessPoints"); + return reply.value(); +} + +QString QNetworkManagerInterfaceDeviceWireless::hwAddress() const +{ + return d->connectionInterface->property("HwAddress").toString(); +} + +quint32 QNetworkManagerInterfaceDeviceWireless::mode() const +{ + return d->connectionInterface->property("Mode").toUInt(); +} + +quint32 QNetworkManagerInterfaceDeviceWireless::bitrate() const +{ + return d->connectionInterface->property("Bitrate").toUInt(); +} + +QDBusObjectPath QNetworkManagerInterfaceDeviceWireless::activeAccessPoint() const +{ + return d->connectionInterface->property("ActiveAccessPoint").value<QDBusObjectPath>(); +} + +quint32 QNetworkManagerInterfaceDeviceWireless::wirelessCapabilities() const +{ + return d->connectionInterface->property("WirelelessCapabilities").toUInt(); +} + +///////////// +class QNetworkManagerSettingsPrivate +{ +public: + QDBusInterface *connectionInterface; + QString path; + bool valid; +}; + +QNetworkManagerSettings::QNetworkManagerSettings(const QString &settingsService, QObject *parent) + : QObject(parent) +{ + d = new QNetworkManagerSettingsPrivate(); + d->path = settingsService; + d->connectionInterface = new QDBusInterface(settingsService, + NM_DBUS_PATH_SETTINGS, + NM_DBUS_IFACE_SETTINGS, + dbusConnection); + if (!d->connectionInterface->isValid()) { + d->valid = false; + qWarning() << "Could not find NetworkManagerSettings"; + return; + } + d->valid = true; +} + +QNetworkManagerSettings::~QNetworkManagerSettings() +{ + delete d->connectionInterface; + delete d; +} + +bool QNetworkManagerSettings::isValid() +{ + return d->valid; +} + +bool QNetworkManagerSettings::setConnections() +{ + bool allOk = false; + + if (!dbusConnection.connect(d->path, NM_DBUS_PATH_SETTINGS, + NM_DBUS_IFACE_SETTINGS, "NewConnection", + this, SIGNAL(newConnection(QDBusObjectPath)))) { + allOk = true; + } + + return allOk; +} + +QList <QDBusObjectPath> QNetworkManagerSettings::listConnections() +{ + QDBusReply<QList<QDBusObjectPath> > reply = d->connectionInterface->call("ListConnections"); + return reply.value(); +} + +QDBusInterface *QNetworkManagerSettings::connectionInterface() const +{ + return d->connectionInterface; +} + + +///////////// +class QNetworkManagerSettingsConnectionPrivate +{ +public: + QDBusInterface *connectionInterface; + QString path; + QString service; + QNmSettingsMap settingsMap; + bool valid; +}; + +QNetworkManagerSettingsConnection::QNetworkManagerSettingsConnection(const QString &settingsService, const QString &connectionObjectPath, QObject *parent) + : QObject(parent), nmDBusHelper(0) +{ + qDBusRegisterMetaType<QNmSettingsMap>(); + d = new QNetworkManagerSettingsConnectionPrivate(); + d->path = connectionObjectPath; + d->service = settingsService; + d->connectionInterface = new QDBusInterface(settingsService, + d->path, + NM_DBUS_IFACE_SETTINGS_CONNECTION, + dbusConnection, parent); + if (!d->connectionInterface->isValid()) { + qWarning() << "Could not find NetworkManagerSettingsConnection"; + d->valid = false; + return; + } + d->valid = true; + QDBusReply< QNmSettingsMap > rep = d->connectionInterface->call("GetSettings"); + d->settingsMap = rep.value(); +} + +QNetworkManagerSettingsConnection::~QNetworkManagerSettingsConnection() +{ + if (nmDBusHelper) + delete nmDBusHelper; + delete d->connectionInterface; + delete d; +} + +bool QNetworkManagerSettingsConnection::isValid() +{ + return d->valid; +} + +bool QNetworkManagerSettingsConnection::setConnections() +{ + if(!isValid() ) + return false; + + bool allOk = false; + if(!dbusConnection.connect(d->service, d->path, + NM_DBUS_IFACE_SETTINGS_CONNECTION, "Updated", + this, SIGNAL(updated(QNmSettingsMap)))) { + allOk = true; + } else { + QDBusError error = dbusConnection.lastError(); + qDebug() << error.name() << error.message() << error.type(); + } + + if (nmDBusHelper) + delete nmDBusHelper; + nmDBusHelper = 0; + nmDBusHelper = new QNmDBusHelper; + connect(nmDBusHelper, SIGNAL(pathForSettingsRemoved(const QString &)), + this,SIGNAL(removed( const QString &))); + + if (!dbusConnection.connect(d->service, d->path, + NM_DBUS_IFACE_SETTINGS_CONNECTION, "Removed", + nmDBusHelper, SIGNAL(slotSettingsRemoved()))) { + allOk = true; + } + + return allOk; +} +//QNetworkManagerSettingsConnection::update(QNmSettingsMap map) +//{ +// d->connectionInterface->call("Update", QVariant::fromValue(map)); +//} + +QDBusInterface *QNetworkManagerSettingsConnection::connectionInterface() const +{ + return d->connectionInterface; +} + +QNmSettingsMap QNetworkManagerSettingsConnection::getSettings() +{ + QDBusReply< QNmSettingsMap > rep = d->connectionInterface->call("GetSettings"); + d->settingsMap = rep.value(); + return d->settingsMap; +} + +NMDeviceType QNetworkManagerSettingsConnection::getType() +{ + QNmSettingsMap::const_iterator i = d->settingsMap.find("connection"); + while (i != d->settingsMap.end() && i.key() == "connection") { + QMap<QString,QVariant> innerMap = i.value(); + QMap<QString,QVariant>::const_iterator ii = innerMap.find("type"); + while (ii != innerMap.end() && ii.key() == "type") { + QString devType = ii.value().toString(); + if (devType == "802-3-ethernet") { + return DEVICE_TYPE_802_3_ETHERNET; + } + if (devType == "802-11-wireless") { + return DEVICE_TYPE_802_11_WIRELESS; + } + ii++; + } + i++; + } + return DEVICE_TYPE_UNKNOWN; +} + +bool QNetworkManagerSettingsConnection::isAutoConnect() +{ + QNmSettingsMap::const_iterator i = d->settingsMap.find("connection"); + while (i != d->settingsMap.end() && i.key() == "connection") { + QMap<QString,QVariant> innerMap = i.value(); + QMap<QString,QVariant>::const_iterator ii = innerMap.find("autoconnect"); + while (ii != innerMap.end() && ii.key() == "autoconnect") { + return ii.value().toBool(); + ii++; + } + i++; + } + return true; //default networkmanager is autoconnect +} + +quint64 QNetworkManagerSettingsConnection::getTimestamp() +{ + QNmSettingsMap::const_iterator i = d->settingsMap.find("connection"); + while (i != d->settingsMap.end() && i.key() == "connection") { + QMap<QString,QVariant> innerMap = i.value(); + QMap<QString,QVariant>::const_iterator ii = innerMap.find("timestamp"); + while (ii != innerMap.end() && ii.key() == "timestamp") { + return ii.value().toUInt(); + ii++; + } + i++; + } + return 0; +} + +QString QNetworkManagerSettingsConnection::getId() +{ + QNmSettingsMap::const_iterator i = d->settingsMap.find("connection"); + while (i != d->settingsMap.end() && i.key() == "connection") { + QMap<QString,QVariant> innerMap = i.value(); + QMap<QString,QVariant>::const_iterator ii = innerMap.find("id"); + while (ii != innerMap.end() && ii.key() == "id") { + return ii.value().toString(); + ii++; + } + i++; + } + return QString(); +} + +QString QNetworkManagerSettingsConnection::getUuid() +{ + QNmSettingsMap::const_iterator i = d->settingsMap.find("connection"); + while (i != d->settingsMap.end() && i.key() == "connection") { + QMap<QString,QVariant> innerMap = i.value(); + QMap<QString,QVariant>::const_iterator ii = innerMap.find("uuid"); + while (ii != innerMap.end() && ii.key() == "uuid") { + return ii.value().toString(); + ii++; + } + i++; + } + // is no uuid, return the connection path + return d->connectionInterface->path(); +} + +QString QNetworkManagerSettingsConnection::getSsid() +{ + QNmSettingsMap::const_iterator i = d->settingsMap.find("802-11-wireless"); + while (i != d->settingsMap.end() && i.key() == "802-11-wireless") { + QMap<QString,QVariant> innerMap = i.value(); + QMap<QString,QVariant>::const_iterator ii = innerMap.find("ssid"); + while (ii != innerMap.end() && ii.key() == "ssid") { + return ii.value().toString(); + ii++; + } + i++; + } + return QString(); +} + +QString QNetworkManagerSettingsConnection::getMacAddress() +{ + if(getType() == DEVICE_TYPE_802_3_ETHERNET) { + QNmSettingsMap::const_iterator i = d->settingsMap.find("802-3-ethernet"); + while (i != d->settingsMap.end() && i.key() == "802-3-ethernet") { + QMap<QString,QVariant> innerMap = i.value(); + QMap<QString,QVariant>::const_iterator ii = innerMap.find("mac-address"); + while (ii != innerMap.end() && ii.key() == "mac-address") { + return ii.value().toString(); + ii++; + } + i++; + } + } + + else if(getType() == DEVICE_TYPE_802_11_WIRELESS) { + QNmSettingsMap::const_iterator i = d->settingsMap.find("802-11-wireless"); + while (i != d->settingsMap.end() && i.key() == "802-11-wireless") { + QMap<QString,QVariant> innerMap = i.value(); + QMap<QString,QVariant>::const_iterator ii = innerMap.find("mac-address"); + while (ii != innerMap.end() && ii.key() == "mac-address") { + return ii.value().toString(); + ii++; + } + i++; + } + } + return QString(); +} + +QStringList QNetworkManagerSettingsConnection::getSeenBssids() +{ + if(getType() == DEVICE_TYPE_802_11_WIRELESS) { + QNmSettingsMap::const_iterator i = d->settingsMap.find("802-11-wireless"); + while (i != d->settingsMap.end() && i.key() == "802-11-wireless") { + QMap<QString,QVariant> innerMap = i.value(); + QMap<QString,QVariant>::const_iterator ii = innerMap.find("seen-bssids"); + while (ii != innerMap.end() && ii.key() == "seen-bssids") { + return ii.value().toStringList(); + ii++; + } + i++; + } + } + return QStringList(); +} + +///////////// +class QNetworkManagerConnectionActivePrivate +{ +public: + QDBusInterface *connectionInterface; + QString path; + bool valid; +}; + +QNetworkManagerConnectionActive::QNetworkManagerConnectionActive( const QString &activeConnectionObjectPath, QObject *parent) + : QObject(parent), nmDBusHelper(0) +{ + d = new QNetworkManagerConnectionActivePrivate(); + d->path = activeConnectionObjectPath; + d->connectionInterface = new QDBusInterface(NM_DBUS_SERVICE, + d->path, + NM_DBUS_INTERFACE_ACTIVE_CONNECTION, + dbusConnection, parent); + if (!d->connectionInterface->isValid()) { + d->valid = false; + qWarning() << "Could not find NetworkManagerSettingsConnection"; + return; + } + d->valid = true; +} + +QNetworkManagerConnectionActive::~QNetworkManagerConnectionActive() +{ + if (nmDBusHelper) + delete nmDBusHelper; + delete d->connectionInterface; + delete d; +} + +bool QNetworkManagerConnectionActive::isValid() +{ + return d->valid; +} + +bool QNetworkManagerConnectionActive::setConnections() +{ + if(!isValid() ) + return false; + + bool allOk = false; + if (nmDBusHelper) + delete nmDBusHelper; + nmDBusHelper = 0; + nmDBusHelper = new QNmDBusHelper; + connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(const QString &,QMap<QString,QVariant>)), + this,SIGNAL(propertiesChanged( const QString &, QMap<QString,QVariant>))); + if(dbusConnection.connect(NM_DBUS_SERVICE, + d->path, + NM_DBUS_INTERFACE_ACTIVE_CONNECTION, + "PropertiesChanged", + nmDBusHelper,SLOT(slotPropertiesChanged( QMap<QString,QVariant>))) ) { + allOk = true; + } + + return allOk; +} + +QDBusInterface *QNetworkManagerConnectionActive::connectionInterface() const +{ + return d->connectionInterface; +} + +QString QNetworkManagerConnectionActive::serviceName() const +{ + return d->connectionInterface->property("ServiceName").toString(); +} + +QDBusObjectPath QNetworkManagerConnectionActive::connection() const +{ + QVariant prop = d->connectionInterface->property("Connection"); + return prop.value<QDBusObjectPath>(); +} + +QDBusObjectPath QNetworkManagerConnectionActive::specificObject() const +{ + QVariant prop = d->connectionInterface->property("SpecificObject"); + return prop.value<QDBusObjectPath>(); +} + +QList<QDBusObjectPath> QNetworkManagerConnectionActive::devices() const +{ + QVariant prop = d->connectionInterface->property("Devices"); + return prop.value<QList<QDBusObjectPath> >(); +} + +quint32 QNetworkManagerConnectionActive::state() const +{ + return d->connectionInterface->property("State").toUInt(); +} + +bool QNetworkManagerConnectionActive::defaultRoute() const +{ + return d->connectionInterface->property("Default").toBool(); +} + + +//// +class QNetworkManagerIp4ConfigPrivate +{ +public: + QDBusInterface *connectionInterface; + QString path; + bool valid; +}; + +QNetworkManagerIp4Config::QNetworkManagerIp4Config( const QString &deviceObjectPath, QObject *parent) + : QObject(parent) +{ + d = new QNetworkManagerIp4ConfigPrivate(); + d->path = deviceObjectPath; + d->connectionInterface = new QDBusInterface(NM_DBUS_SERVICE, + d->path, + NM_DBUS_INTERFACE_IP4_CONFIG, + dbusConnection, parent); + if (!d->connectionInterface->isValid()) { + d->valid = false; + qWarning() << "Could not find NetworkManagerIp4Config"; + return; + } + d->valid = true; +} + +QNetworkManagerIp4Config::~QNetworkManagerIp4Config() +{ + delete d->connectionInterface; + delete d; +} + +bool QNetworkManagerIp4Config::isValid() +{ + return d->valid; +} + +QStringList QNetworkManagerIp4Config::domains() const +{ + return d->connectionInterface->property("Domains").toStringList(); +} + +QT_END_NAMESPACE diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h new file mode 100644 index 0000000..dbed01e --- /dev/null +++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h @@ -0,0 +1,397 @@ +/**************************************************************************** +** +** 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 QNETWORKMANAGERSERVICE_H +#define QNETWORKMANAGERSERVICE_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 <NetworkManager/NetworkManager.h> +#include <QtDBus> +#include <QDBusConnection> +#include <QDBusError> +#include <QDBusInterface> +#include <QDBusMessage> +#include <QDBusReply> +#include <QNetworkInterface> + + +#include <QDBusPendingCallWatcher> +#include "qnmdbushelper.h" + +QT_BEGIN_NAMESPACE + +typedef QMap< QString, QMap<QString,QVariant> > QNmSettingsMap; +typedef QList<quint32> ServerThing; + +Q_DECLARE_METATYPE(QNmSettingsMap) +Q_DECLARE_METATYPE(ServerThing) + +class QNetworkManagerInterfacePrivate; +class QNetworkManagerInterface : public QObject +{ + Q_OBJECT + +public: + + QNetworkManagerInterface(QObject *parent = 0); + ~QNetworkManagerInterface(); + + QList <QDBusObjectPath> getDevices() const; + void activateConnection(const QString &serviceName, QDBusObjectPath connection, QDBusObjectPath device, QDBusObjectPath specificObject); + void deactivateConnection(QDBusObjectPath connectionPath) const; + + QDBusObjectPath path() const; + QDBusInterface *connectionInterface() const; + + bool wirelessEnabled() const; + bool wirelessHardwareEnabled() const; + QList <QDBusObjectPath> activeConnections() const; + quint32 state(); + bool setConnections(); + bool isValid(); + +Q_SIGNALS: + void deviceAdded(QDBusObjectPath); + void deviceRemoved(QDBusObjectPath); + void propertiesChanged( const QString &, QMap<QString,QVariant>); + void stateChanged(const QString&, quint32); + void activationFinished(QDBusPendingCallWatcher*); + +private Q_SLOTS: +private: +// Q_DISABLE_COPY(QNetworkManagerInterface); ?? + QNetworkManagerInterfacePrivate *d; + QNmDBusHelper *nmDBusHelper; +}; //end QNetworkManagerInterface + +//////// +class QNetworkManagerInterfaceAccessPointPrivate; +class QNetworkManagerInterfaceAccessPoint : public QObject +{ + Q_OBJECT + +public: + + // NM_DEVICE_STATE + enum DeviceState { + Unknown = 0, + Unmanaged, + Unavailable, + Disconnected, + Prepare, + Config, + NeedAuthentication, + IpConfig, + Activated, + Failed + }; + + enum ApFlag { + ApNone = 0x0, + Privacy = 0x1 + }; + + Q_DECLARE_FLAGS(ApFlags, ApFlag); + + enum ApSecurityFlag { + ApSecurityNone = 0x0, + PairWep40 = 0x1, + PairWep104 = 0x2, + PairTkip = 0x4, + PairCcmp = 0x8, + GroupWep40 = 0x10, + GroupWep104 = 0x20, + GroupTkip = 0x40, + GroupCcmp = 0x80, + KeyPsk = 0x100, + Key8021x = 0x200 + }; + + Q_DECLARE_FLAGS(ApSecurityFlags, ApSecurityFlag); + + QNetworkManagerInterfaceAccessPoint(const QString &dbusPathName, QObject *parent = 0); + ~QNetworkManagerInterfaceAccessPoint(); + + QDBusInterface *connectionInterface() const; + + quint32 flags() const; + quint32 wpaFlags() const; + quint32 rsnFlags() const; + QString ssid() const; + quint32 frequency() const; + QString hwAddress() const; + quint32 mode() const; + quint32 maxBitrate() const; + quint32 strength() const; + bool setConnections(); + bool isValid(); + +Q_SIGNALS: + void propertiesChanged(QMap <QString,QVariant>); + void propertiesChanged( const QString &, QMap<QString,QVariant>); +private: + QNetworkManagerInterfaceAccessPointPrivate *d; + QNmDBusHelper *nmDBusHelper; + +}; //end QNetworkManagerInterfaceAccessPoint + +//////// +class QNetworkManagerInterfaceDevicePrivate; +class QNetworkManagerInterfaceDevice : public QObject +{ + Q_OBJECT + +public: + + QNetworkManagerInterfaceDevice(const QString &deviceObjectPath, QObject *parent = 0); + ~QNetworkManagerInterfaceDevice(); + + QString udi() const; + QNetworkInterface interface() const; + QDBusInterface *connectionInterface() const; + quint32 ip4Address() const; + quint32 state() const; + quint32 deviceType() const; + + QDBusObjectPath ip4config() const; + bool setConnections(); + bool isValid(); + +Q_SIGNALS: + void stateChanged(const QString &, quint32); + +private: + QNetworkManagerInterfaceDevicePrivate *d; + QNmDBusHelper *nmDBusHelper; +}; //end QNetworkManagerInterfaceDevice + +//////// +class QNetworkManagerInterfaceDeviceWiredPrivate; +class QNetworkManagerInterfaceDeviceWired : public QObject +{ + Q_OBJECT + +public: + + QNetworkManagerInterfaceDeviceWired(const QString &ifaceDevicePath, QObject *parent = 0); + ~QNetworkManagerInterfaceDeviceWired(); + + QDBusInterface *connectionInterface() const; + QString hwAddress() const; + quint32 speed() const; + bool carrier() const; + bool setConnections(); + bool isValid(); + +Q_SIGNALS: + void propertiesChanged( const QString &, QMap<QString,QVariant>); +private: + QNetworkManagerInterfaceDeviceWiredPrivate *d; + QNmDBusHelper *nmDBusHelper; +}; // end QNetworkManagerInterfaceDeviceWired + +//// +class QNetworkManagerInterfaceDeviceWirelessPrivate; +class QNetworkManagerInterfaceDeviceWireless : public QObject +{ + Q_OBJECT + +public: + + enum DeviceCapability { + None = 0x0, + Wep40 = 0x1, + Wep104 = 0x2, + Tkip = 0x4, + Ccmp = 0x8, + Wpa = 0x10, + Rsn = 0x20 + }; + + QNetworkManagerInterfaceDeviceWireless(const QString &ifaceDevicePath, QObject *parent = 0); + ~QNetworkManagerInterfaceDeviceWireless(); + + QDBusObjectPath path() const; + QList <QDBusObjectPath> getAccessPoints(); + QDBusInterface *connectionInterface() const; + + QString hwAddress() const; + quint32 mode() const; + quint32 bitrate() const; + QDBusObjectPath activeAccessPoint() const; + quint32 wirelessCapabilities() const; + bool setConnections(); + bool isValid(); + +Q_SIGNALS: + void propertiesChanged( const QString &, QMap<QString,QVariant>); + void accessPointAdded(const QString &,QDBusObjectPath); + void accessPointRemoved(const QString &,QDBusObjectPath); +private: + QNetworkManagerInterfaceDeviceWirelessPrivate *d; + QNmDBusHelper *nmDBusHelper; +}; // end QNetworkManagerInterfaceDeviceWireless + +//// +class QNetworkManagerSettingsPrivate; +class QNetworkManagerSettings : public QObject +{ + Q_OBJECT + +public: + + QNetworkManagerSettings(const QString &settingsService, QObject *parent = 0); + ~QNetworkManagerSettings(); + + QDBusInterface *connectionInterface() const; + QList <QDBusObjectPath> listConnections(); + bool setConnections(); + bool isValid(); + +Q_SIGNALS: + void newConnection(QDBusObjectPath); +private: + QNetworkManagerSettingsPrivate *d; +}; //end QNetworkManagerSettings + +//// +class QNetworkManagerSettingsConnectionPrivate; +class QNetworkManagerSettingsConnection : public QObject +{ + Q_OBJECT + +public: + + QNetworkManagerSettingsConnection(const QString &settingsService, const QString &connectionObjectPath, QObject *parent = 0); + ~QNetworkManagerSettingsConnection(); + + QDBusInterface *connectionInterface() const; + QNmSettingsMap getSettings(); + // void update(QNmSettingsMap map); + bool setConnections(); + NMDeviceType getType(); + bool isAutoConnect(); + quint64 getTimestamp(); + QString getId(); + QString getUuid(); + QString getSsid(); + QString getMacAddress(); + QStringList getSeenBssids(); + bool isValid(); + +Q_SIGNALS: + + void updated(const QNmSettingsMap &settings); + void removed(const QString &path); + +private: + QNmDBusHelper *nmDBusHelper; + QNetworkManagerSettingsConnectionPrivate *d; +}; //end QNetworkManagerSettingsConnection + +//// +class QNetworkManagerConnectionActivePrivate; +class QNetworkManagerConnectionActive : public QObject +{ + Q_OBJECT + +public: + + enum ActiveConnectionState { + Unknown = 0, + Activating = 1, + Activated = 2 + }; + + QNetworkManagerConnectionActive(const QString &dbusPathName, QObject *parent = 0); + ~ QNetworkManagerConnectionActive(); + + QDBusInterface *connectionInterface() const; + QString serviceName() const; + QDBusObjectPath connection() const; + QDBusObjectPath specificObject() const; + QList<QDBusObjectPath> devices() const; + quint32 state() const; + bool defaultRoute() const; + bool setConnections(); + bool isValid(); + + +Q_SIGNALS: + void propertiesChanged(QList<QDBusObjectPath>); + void propertiesChanged( const QString &, QMap<QString,QVariant>); +private: + QNetworkManagerConnectionActivePrivate *d; + QNmDBusHelper *nmDBusHelper; +}; //QNetworkManagerConnectionActive + +//// +class QNetworkManagerIp4ConfigPrivate; +class QNetworkManagerIp4Config : public QObject +{ + Q_OBJECT + +public: + QNetworkManagerIp4Config(const QString &dbusPathName, QObject *parent = 0); + ~QNetworkManagerIp4Config(); + + // QList<quint32> nameservers(); + QStringList domains() const; + bool isValid(); + + private: + QNetworkManagerIp4ConfigPrivate *d; +}; +//// + +QT_END_NAMESPACE + +#endif //QNETWORKMANAGERSERVICE_H diff --git a/src/plugins/bearer/networkmanager/qnmdbushelper.cpp b/src/plugins/bearer/networkmanager/qnmdbushelper.cpp new file mode 100644 index 0000000..f93a63d --- /dev/null +++ b/src/plugins/bearer/networkmanager/qnmdbushelper.cpp @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + +// this class is for helping qdbus get stuff + +#include "qnmdbushelper.h" + +#include <NetworkManager/NetworkManager.h> + +#include <QDBusError> +#include <QDBusInterface> +#include <QDBusMessage> +#include <QDBusReply> + +#include <QDebug> + +QT_BEGIN_NAMESPACE + +void QNmDBusHelper::deviceStateChanged(quint32 state) + { + QDBusMessage msg = this->message(); + if(state == NM_DEVICE_STATE_ACTIVATED + || state == NM_DEVICE_STATE_DISCONNECTED + || state == NM_DEVICE_STATE_UNAVAILABLE + || state == NM_DEVICE_STATE_FAILED) { + emit pathForStateChanged(msg.path(), state); + } + } + +void QNmDBusHelper::slotAccessPointAdded(QDBusObjectPath path) +{ + if(path.path().length() > 2) { + QDBusMessage msg = this->message(); + emit pathForAccessPointAdded(msg.path(), path); + } +} + +void QNmDBusHelper::slotAccessPointRemoved(QDBusObjectPath path) +{ + if(path.path().length() > 2) { + QDBusMessage msg = this->message(); + emit pathForAccessPointRemoved(msg.path(), path); + } +} + +void QNmDBusHelper::slotPropertiesChanged(QMap<QString,QVariant> map) +{ + QDBusMessage msg = this->message(); + QMapIterator<QString, QVariant> i(map); + while (i.hasNext()) { + i.next(); + if( i.key() == "State") { //state only applies to device interfaces + quint32 state = i.value().toUInt(); + if( state == NM_DEVICE_STATE_ACTIVATED + || state == NM_DEVICE_STATE_DISCONNECTED + || state == NM_DEVICE_STATE_UNAVAILABLE + || state == NM_DEVICE_STATE_FAILED) { + emit pathForPropertiesChanged( msg.path(), map); + } + } else if( i.key() == "ActiveAccessPoint") { + emit pathForPropertiesChanged(msg.path(), map); + // qWarning() << __PRETTY_FUNCTION__ << i.key() << ": " << i.value().value<QDBusObjectPath>().path(); + // } else if( i.key() == "Strength") + // qWarning() << __PRETTY_FUNCTION__ << i.key() << ": " << i.value().toUInt(); + // else + // qWarning() << __PRETTY_FUNCTION__ << i.key() << ": " << i.value(); + } else if (i.key() == "ActiveConnections") { + emit pathForPropertiesChanged(msg.path(), map); + } + } +} + +void QNmDBusHelper::slotSettingsRemoved() +{ + QDBusMessage msg = this->message(); + emit pathForSettingsRemoved(msg.path()); +} + +QT_END_NAMESPACE diff --git a/src/plugins/bearer/networkmanager/qnmdbushelper.h b/src/plugins/bearer/networkmanager/qnmdbushelper.h new file mode 100644 index 0000000..410b69f --- /dev/null +++ b/src/plugins/bearer/networkmanager/qnmdbushelper.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** 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 QNMDBUSHELPERPRIVATE_H +#define QNMDBUSHELPERPRIVATE_H + +#include <QDBusObjectPath> +#include <QDBusContext> +#include <QMap> + +QT_BEGIN_NAMESPACE + +class QNmDBusHelper: public QObject, protected QDBusContext + { + Q_OBJECT + public: + + public slots: + void deviceStateChanged(quint32); + void slotAccessPointAdded( QDBusObjectPath ); + void slotAccessPointRemoved( QDBusObjectPath ); + void slotPropertiesChanged( QMap<QString,QVariant>); + void slotSettingsRemoved(); + +Q_SIGNALS: + void pathForStateChanged(const QString &, quint32); + void pathForAccessPointAdded(const QString &, QDBusObjectPath ); + void pathForAccessPointRemoved(const QString &, QDBusObjectPath ); + void pathForPropertiesChanged(const QString &, QMap<QString,QVariant>); + void pathForSettingsRemoved(const QString &); +}; + +QT_END_NAMESPACE + +#endif// QNMDBUSHELPERPRIVATE_H diff --git a/src/plugins/bearer/nla/main.cpp b/src/plugins/bearer/nla/main.cpp new file mode 100644 index 0000000..541d2c5 --- /dev/null +++ b/src/plugins/bearer/nla/main.cpp @@ -0,0 +1,84 @@ +/**************************************************************************** +** +** 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 "qnlaengine.h" + +#include <QtNetwork/qbearerplugin.h> + +#include <QtCore/qdebug.h> + +QT_BEGIN_NAMESPACE + +class QNlaEnginePlugin : public QBearerEnginePlugin +{ +public: + QNlaEnginePlugin(); + ~QNlaEnginePlugin(); + + QStringList keys() const; + QBearerEngine *create(const QString &key) const; +}; + +QNlaEnginePlugin::QNlaEnginePlugin() +{ +} + +QNlaEnginePlugin::~QNlaEnginePlugin() +{ +} + +QStringList QNlaEnginePlugin::keys() const +{ + return QStringList() << QLatin1String("nla"); +} + +QBearerEngine *QNlaEnginePlugin::create(const QString &key) const +{ + if (key == QLatin1String("nla")) + return new QNlaEngine; + else + return 0; +} + +Q_EXPORT_STATIC_PLUGIN(QNlaEnginePlugin) +Q_EXPORT_PLUGIN2(qnlabearer, QNlaEnginePlugin) + +QT_END_NAMESPACE diff --git a/src/plugins/bearer/nla/nla.pro b/src/plugins/bearer/nla/nla.pro new file mode 100644 index 0000000..62a920a --- /dev/null +++ b/src/plugins/bearer/nla/nla.pro @@ -0,0 +1,18 @@ +TARGET = qnlabearer +include(../../qpluginbase.pri) + +QT += network + +!wince* { + LIBS += -lWs2_32 +} else { + LIBS += -lWs2 +} + +HEADERS += qnlaengine.h \ + ../platformdefs_win.h +SOURCES += qnlaengine.cpp main.cpp + +QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/bearer +target.path += $$[QT_INSTALL_PLUGINS]/bearer +INSTALLS += target diff --git a/src/plugins/bearer/nla/qnlaengine.cpp b/src/plugins/bearer/nla/qnlaengine.cpp new file mode 100644 index 0000000..51897f0 --- /dev/null +++ b/src/plugins/bearer/nla/qnlaengine.cpp @@ -0,0 +1,636 @@ +/**************************************************************************** +** +** 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 "qnlaengine.h" +#include <QtNetwork/private/qnetworkconfiguration_p.h> + +#include <QtCore/qthread.h> +#include <QtCore/qmutex.h> +#include <QtCore/qcoreapplication.h> +#include <QtCore/qstringlist.h> + +#include <QtCore/qdebug.h> + +#include "../platformdefs_win.h" + +QT_BEGIN_NAMESPACE + +QWindowsSockInit2::QWindowsSockInit2() +: version(0) +{ + //### should we try for 2.2 on all platforms ?? + WSAData wsadata; + + // IPv6 requires Winsock v2.0 or better. + if (WSAStartup(MAKEWORD(2,0), &wsadata) != 0) { + qWarning("QBearerManagementAPI: WinSock v2.0 initialization failed."); + } else { + version = 0x20; + } +} + +QWindowsSockInit2::~QWindowsSockInit2() +{ + WSACleanup(); +} + +#ifdef BEARER_MANAGEMENT_DEBUG +static void printBlob(NLA_BLOB *blob) +{ + qDebug() << "==== BEGIN NLA_BLOB ===="; + + qDebug() << "type:" << blob->header.type; + qDebug() << "size:" << blob->header.dwSize; + qDebug() << "next offset:" << blob->header.nextOffset; + + switch (blob->header.type) { + case NLA_RAW_DATA: + qDebug() << "Raw Data"; + qDebug() << '\t' << blob->data.rawData; + break; + case NLA_INTERFACE: + qDebug() << "Interface"; + qDebug() << "\ttype:" << blob->data.interfaceData.dwType; + qDebug() << "\tspeed:" << blob->data.interfaceData.dwSpeed; + qDebug() << "\tadapter:" << blob->data.interfaceData.adapterName; + break; + case NLA_802_1X_LOCATION: + qDebug() << "802.1x Location"; + qDebug() << '\t' << blob->data.locationData.information; + break; + case NLA_CONNECTIVITY: + qDebug() << "Connectivity"; + qDebug() << "\ttype:" << blob->data.connectivity.type; + qDebug() << "\tinternet:" << blob->data.connectivity.internet; + break; + case NLA_ICS: + qDebug() << "ICS"; + qDebug() << "\tspeed:" << blob->data.ICS.remote.speed; + qDebug() << "\ttype:" << blob->data.ICS.remote.type; + qDebug() << "\tstate:" << blob->data.ICS.remote.state; + qDebug() << "\tmachine name:" << blob->data.ICS.remote.machineName; + qDebug() << "\tshared adapter name:" << blob->data.ICS.remote.sharedAdapterName; + break; + default: + qDebug() << "UNKNOWN BLOB TYPE"; + } + + qDebug() << "===== END NLA_BLOB ====="; +} +#endif + +static QString qGetInterfaceType(const QString &interface) +{ +#ifdef Q_OS_WINCE + Q_UNUSED(interface) +#else + unsigned long oid; + DWORD bytesWritten; + + NDIS_MEDIUM medium; + NDIS_PHYSICAL_MEDIUM physicalMedium; + + HANDLE handle = CreateFile((TCHAR *)QString(QLatin1String("\\\\.\\%1")).arg(interface).utf16(), + 0, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + if (handle == INVALID_HANDLE_VALUE) + return QLatin1String("Unknown"); + + oid = OID_GEN_MEDIA_SUPPORTED; + bytesWritten = 0; + bool result = DeviceIoControl(handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof(oid), + &medium, sizeof(medium), &bytesWritten, 0); + if (!result) { + CloseHandle(handle); + return QLatin1String("Unknown"); + } + + oid = OID_GEN_PHYSICAL_MEDIUM; + bytesWritten = 0; + result = DeviceIoControl(handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof(oid), + &physicalMedium, sizeof(physicalMedium), &bytesWritten, 0); + if (!result) { + CloseHandle(handle); + + if (medium == NdisMedium802_3) + return QLatin1String("Ethernet"); + else + return QLatin1String("Unknown"); + } + + CloseHandle(handle); + + if (medium == NdisMedium802_3) { + switch (physicalMedium) { + case NdisPhysicalMediumWirelessLan: + return QLatin1String("WLAN"); + case NdisPhysicalMediumBluetooth: + return QLatin1String("Bluetooth"); + case NdisPhysicalMediumWiMax: + return QLatin1String("WiMAX"); + default: +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug() << "Physical Medium" << physicalMedium; +#endif + return QLatin1String("Ethernet"); + } + } + +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug() << medium << physicalMedium; +#endif + +#endif + + return QLatin1String("Unknown"); +} + +class QNlaThread : public QThread +{ + Q_OBJECT + +public: + QNlaThread(QNlaEngine *parent = 0); + ~QNlaThread(); + + QList<QNetworkConfigurationPrivate *> getConfigurations(); + + void forceUpdate(); + +protected: + virtual void run(); + +private: + void updateConfigurations(QList<QNetworkConfigurationPrivate *> &configs); + DWORD parseBlob(NLA_BLOB *blob, QNetworkConfigurationPrivate *cpPriv) const; + QNetworkConfigurationPrivate *parseQuerySet(const WSAQUERYSET *querySet) const; + void fetchConfigurations(); + +signals: + void networksChanged(); + +private: + QMutex mutex; + HANDLE handle; + bool done; + QList<QNetworkConfigurationPrivate *> fetchedConfigurations; +}; + +QNlaThread::QNlaThread(QNlaEngine *parent) +: QThread(parent), handle(0), done(false) +{ +} + +QNlaThread::~QNlaThread() +{ + mutex.lock(); + + done = true; + + if (handle) { + /* cancel completion event */ + if (WSALookupServiceEnd(handle) == SOCKET_ERROR) + qWarning("WSALookupServiceEnd error %d", WSAGetLastError()); + } + mutex.unlock(); + + wait(); +} + +QList<QNetworkConfigurationPrivate *> QNlaThread::getConfigurations() +{ + QMutexLocker locker(&mutex); + + QList<QNetworkConfigurationPrivate *> foundConfigurations = fetchedConfigurations; + fetchedConfigurations.clear(); + + return foundConfigurations; +} + +void QNlaThread::forceUpdate() +{ + mutex.lock(); + + if (handle) { + /* cancel completion event */ + if (WSALookupServiceEnd(handle) == SOCKET_ERROR) + qWarning("WSALookupServiceEnd error %d", WSAGetLastError()); + handle = 0; + } + mutex.unlock(); +} + +void QNlaThread::run() +{ + WSAEVENT changeEvent = WSACreateEvent(); + if (changeEvent == WSA_INVALID_EVENT) { + qWarning("WSACreateEvent error %d", WSAGetLastError()); + return; + } + + while (true) { + fetchConfigurations(); + + WSAQUERYSET qsRestrictions; + + memset(&qsRestrictions, 0, sizeof(qsRestrictions)); + qsRestrictions.dwSize = sizeof(qsRestrictions); + qsRestrictions.dwNameSpace = NS_NLA; + + mutex.lock(); + if (done) { + mutex.unlock(); + break; + } + int result = WSALookupServiceBegin(&qsRestrictions, LUP_RETURN_ALL, &handle); + mutex.unlock(); + + if (result == SOCKET_ERROR) { + qWarning("%s: WSALookupServiceBegin error %d", __FUNCTION__, WSAGetLastError()); + break; + } + + WSACOMPLETION completion; + WSAOVERLAPPED overlapped; + + memset(&overlapped, 0, sizeof(overlapped)); + overlapped.hEvent = changeEvent; + + memset(&completion, 0, sizeof(completion)); + completion.Type = NSP_NOTIFY_EVENT; + completion.Parameters.Event.lpOverlapped = &overlapped; + + DWORD bytesReturned = 0; + result = WSANSPIoctl(handle, SIO_NSP_NOTIFY_CHANGE, 0, 0, 0, 0, + &bytesReturned, &completion); + if (result == SOCKET_ERROR) { + int error = WSAGetLastError(); + if (error != WSA_IO_PENDING) { + qWarning("WSANSPIoctl error %d", error); + break; + } + } + +#ifndef Q_OS_WINCE + // Not interested in unrelated IO completion events + // although we also don't want to block them + while (WaitForSingleObjectEx(changeEvent, WSA_INFINITE, true) != WAIT_IO_COMPLETION && + handle) + { + } +#else + WaitForSingleObject(changeEvent, WSA_INFINITE); +#endif + + mutex.lock(); + if (handle) { + result = WSALookupServiceEnd(handle); + if (result == SOCKET_ERROR) { + qWarning("WSALookupServiceEnd error %d", WSAGetLastError()); + mutex.unlock(); + break; + } + handle = 0; + } + mutex.unlock(); + } + + WSACloseEvent(changeEvent); +} + +void QNlaThread::updateConfigurations(QList<QNetworkConfigurationPrivate *> &configs) +{ + mutex.lock(); + + while (!fetchedConfigurations.isEmpty()) + delete fetchedConfigurations.takeFirst(); + + fetchedConfigurations = configs; + + mutex.unlock(); + + emit networksChanged(); +} + +DWORD QNlaThread::parseBlob(NLA_BLOB *blob, QNetworkConfigurationPrivate *cpPriv) const +{ +#ifdef BEARER_MANAGEMENT_DEBUG + printBlob(blob); +#endif + + switch (blob->header.type) { + case NLA_RAW_DATA: +#ifdef BEARER_MANAGEMENT_DEBUG + qWarning("%s: unhandled header type NLA_RAW_DATA", __FUNCTION__); +#endif + break; + case NLA_INTERFACE: + cpPriv->state = QNetworkConfiguration::Active; + if (QNlaEngine *engine = qobject_cast<QNlaEngine *>(parent())) { + engine->configurationInterface[cpPriv->id.toUInt()] = + QString::fromLatin1(blob->data.interfaceData.adapterName); + } + break; + case NLA_802_1X_LOCATION: +#ifdef BEARER_MANAGEMENT_DEBUG + qWarning("%s: unhandled header type NLA_802_1X_LOCATION", __FUNCTION__); +#endif + break; + case NLA_CONNECTIVITY: + if (blob->data.connectivity.internet == NLA_INTERNET_YES) + cpPriv->internet = true; + else + cpPriv->internet = false; +#ifdef BEARER_MANAGEMENT_DEBUG + qWarning("%s: unhandled header type NLA_CONNECTIVITY", __FUNCTION__); +#endif + break; + case NLA_ICS: +#ifdef BEARER_MANAGEMENT_DEBUG + qWarning("%s: unhandled header type NLA_ICS", __FUNCTION__); +#endif + break; + default: +#ifdef BEARER_MANAGEMENT_DEBUG + qWarning("%s: unhandled header type %d", __FUNCTION__, blob->header.type); +#endif + ; + } + + return blob->header.nextOffset; +} + +QNetworkConfigurationPrivate *QNlaThread::parseQuerySet(const WSAQUERYSET *querySet) const +{ + QNetworkConfigurationPrivate *cpPriv = new QNetworkConfigurationPrivate; + + cpPriv->name = QString::fromWCharArray(querySet->lpszServiceInstanceName); + cpPriv->isValid = true; + cpPriv->id = QString::number(qHash(QLatin1String("NLA:") + cpPriv->name)); + cpPriv->state = QNetworkConfiguration::Defined; + cpPriv->type = QNetworkConfiguration::InternetAccessPoint; + +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug() << "size:" << querySet->dwSize; + qDebug() << "service instance name:" << QString::fromUtf16(querySet->lpszServiceInstanceName); + qDebug() << "service class id:" << querySet->lpServiceClassId; + qDebug() << "version:" << querySet->lpVersion; + qDebug() << "comment:" << QString::fromUtf16(querySet->lpszComment); + qDebug() << "namespace:" << querySet->dwNameSpace; + qDebug() << "namespace provider id:" << querySet->lpNSProviderId; + qDebug() << "context:" << QString::fromUtf16(querySet->lpszContext); + qDebug() << "number of protocols:" << querySet->dwNumberOfProtocols; + qDebug() << "protocols:" << querySet->lpafpProtocols; + qDebug() << "query string:" << QString::fromUtf16(querySet->lpszQueryString); + qDebug() << "number of cs addresses:" << querySet->dwNumberOfCsAddrs; + qDebug() << "cs addresses:" << querySet->lpcsaBuffer; + qDebug() << "output flags:" << querySet->dwOutputFlags; +#endif + + if (querySet->lpBlob) { +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug() << "blob size:" << querySet->lpBlob->cbSize; + qDebug() << "blob data:" << querySet->lpBlob->pBlobData; +#endif + + DWORD offset = 0; + do { + NLA_BLOB *blob = reinterpret_cast<NLA_BLOB *>(querySet->lpBlob->pBlobData + offset); + DWORD nextOffset = parseBlob(blob, cpPriv); + if (nextOffset == offset) + break; + else + offset = nextOffset; + } while (offset != 0 && offset < querySet->lpBlob->cbSize); + } + + if (QNlaEngine *engine = qobject_cast<QNlaEngine *>(parent())) + cpPriv->bearer = engine->bearerName(cpPriv->id); + + return cpPriv; +} + +void QNlaThread::fetchConfigurations() +{ + QList<QNetworkConfigurationPrivate *> foundConfigurations; + + WSAQUERYSET qsRestrictions; + HANDLE hLookup = 0; + + memset(&qsRestrictions, 0, sizeof(qsRestrictions)); + qsRestrictions.dwSize = sizeof(qsRestrictions); + qsRestrictions.dwNameSpace = NS_NLA; + + int result = WSALookupServiceBegin(&qsRestrictions, LUP_RETURN_ALL | LUP_DEEP, &hLookup); + if (result == SOCKET_ERROR) { + qWarning("%s: WSALookupServiceBegin error %d", __FUNCTION__, WSAGetLastError()); + mutex.lock(); + fetchedConfigurations.clear(); + mutex.unlock(); + } + + char buffer[0x10000]; + while (result == 0) { + DWORD bufferLength = sizeof(buffer); + result = WSALookupServiceNext(hLookup, LUP_RETURN_ALL, + &bufferLength, reinterpret_cast<WSAQUERYSET *>(buffer)); + + if (result == SOCKET_ERROR) { + int error = WSAGetLastError(); + + if (error == WSA_E_NO_MORE) + break; + + if (error == WSAEFAULT) { + qDebug() << "buffer not big enough" << bufferLength; + break; + } + + qWarning("WSALookupServiceNext error %d", WSAGetLastError()); + break; + } + + QNetworkConfigurationPrivate *cpPriv = + parseQuerySet(reinterpret_cast<WSAQUERYSET *>(buffer)); + + foundConfigurations.append(cpPriv); + } + + if (hLookup) { + result = WSALookupServiceEnd(hLookup); + if (result == SOCKET_ERROR) { + qWarning("WSALookupServiceEnd error %d", WSAGetLastError()); + } + } + + updateConfigurations(foundConfigurations); +} + +QNlaEngine::QNlaEngine(QObject *parent) +: QNetworkSessionEngine(parent), nlaThread(0) +{ + nlaThread = new QNlaThread(this); + connect(nlaThread, SIGNAL(networksChanged()), + this, SLOT(networksChanged())); + nlaThread->start(); + + qApp->processEvents(QEventLoop::ExcludeUserInputEvents); +} + +QNlaEngine::~QNlaEngine() +{ + delete nlaThread; +} + +void QNlaEngine::networksChanged() +{ + QStringList previous = accessPointConfigurations.keys(); + + QList<QNetworkConfigurationPrivate *> foundConfigurations = nlaThread->getConfigurations(); + while (!foundConfigurations.isEmpty()) { + QNetworkConfigurationPrivate *cpPriv = foundConfigurations.takeFirst(); + + previous.removeAll(cpPriv->id); + + if (accessPointConfigurations.contains(cpPriv->id)) { + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(cpPriv->id); + + bool changed = false; + + if (ptr->isValid != cpPriv->isValid) { + ptr->isValid = cpPriv->isValid; + changed = true; + } + + if (ptr->name != cpPriv->name) { + ptr->name = cpPriv->name; + changed = true; + } + + if (ptr->state != cpPriv->state) { + ptr->state = cpPriv->state; + changed = true; + } + + if (changed) + emit configurationChanged(ptr); + + delete cpPriv; + } else { + QNetworkConfigurationPrivatePointer ptr(cpPriv); + + accessPointConfigurations.insert(ptr->id, ptr); + + emit configurationAdded(ptr); + } + } + + while (!previous.isEmpty()) { + QNetworkConfigurationPrivatePointer ptr = + accessPointConfigurations.take(previous.takeFirst()); + + emit configurationRemoved(ptr); + } + + emit updateCompleted(); +} + +QString QNlaEngine::getInterfaceFromId(const QString &id) +{ + return configurationInterface.value(id.toUInt()); +} + +bool QNlaEngine::hasIdentifier(const QString &id) +{ + return configurationInterface.contains(id.toUInt()); +} + +QString QNlaEngine::bearerName(const QString &id) +{ + QString interface = getInterfaceFromId(id); + + if (interface.isEmpty()) + return QString(); + + return qGetInterfaceType(interface); +} + +void QNlaEngine::connectToId(const QString &id) +{ + emit connectionError(id, OperationNotSupported); +} + +void QNlaEngine::disconnectFromId(const QString &id) +{ + emit connectionError(id, OperationNotSupported); +} + +void QNlaEngine::requestUpdate() +{ + nlaThread->forceUpdate(); +} + +QNetworkSession::State QNlaEngine::sessionStateForId(const QString &id) +{ + QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id); + + if (!ptr) + return QNetworkSession::Invalid; + + if (!ptr->isValid) { + return QNetworkSession::Invalid; + } else if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { + return QNetworkSession::Connected; + } else if ((ptr->state & QNetworkConfiguration::Discovered) == + QNetworkConfiguration::Discovered) { + return QNetworkSession::Disconnected; + } else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) { + return QNetworkSession::NotAvailable; + } else if ((ptr->state & QNetworkConfiguration::Undefined) == + QNetworkConfiguration::Undefined) { + return QNetworkSession::NotAvailable; + } + + return QNetworkSession::Invalid; +} + +#include "qnlaengine.moc" +QT_END_NAMESPACE + diff --git a/src/plugins/bearer/nla/qnlaengine.h b/src/plugins/bearer/nla/qnlaengine.h new file mode 100644 index 0000000..dd038d1 --- /dev/null +++ b/src/plugins/bearer/nla/qnlaengine.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** 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 QNLAENGINE_P_H +#define QNLAENGINE_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 <QtNetwork/private/qnetworksessionengine_p.h> +#include <QtNetwork/private/qnativesocketengine_p.h> + +#include <QMap> + +QT_BEGIN_NAMESPACE + +class QNetworkConfigurationPrivate; +class QNlaThread; + +class QWindowsSockInit2 +{ +public: + QWindowsSockInit2(); + ~QWindowsSockInit2(); + int version; +}; + +class QNlaEngine : public QNetworkSessionEngine +{ + Q_OBJECT + + friend class QNlaThread; + +public: + QNlaEngine(QObject *parent = 0); + ~QNlaEngine(); + + 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(); + + QNetworkSession::State sessionStateForId(const QString &id); + +private Q_SLOTS: + void networksChanged(); + +private: + QWindowsSockInit2 winSock; + QNlaThread *nlaThread; + QMap<uint, QString> configurationInterface; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/bearer/platformdefs_win.h b/src/plugins/bearer/platformdefs_win.h new file mode 100644 index 0000000..f2f44a1 --- /dev/null +++ b/src/plugins/bearer/platformdefs_win.h @@ -0,0 +1,134 @@ +/**************************************************************************** +** +** 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 QPLATFORMDEFS_WIN_H +#define QPLATFORMDEFS_WIN_H + +#include <winsock2.h> +#include <mswsock.h> +#undef interface +#include <winioctl.h> + +#ifndef NS_NLA + +#define NS_NLA 15 + +enum NLA_BLOB_DATA_TYPE { + NLA_RAW_DATA = 0, + NLA_INTERFACE = 1, + NLA_802_1X_LOCATION = 2, + NLA_CONNECTIVITY = 3, + NLA_ICS = 4 +}; + +enum NLA_CONNECTIVITY_TYPE { + NLA_NETWORK_AD_HOC = 0, + NLA_NETWORK_MANAGED = 1, + NLA_NETWORK_UNMANAGED = 2, + NLA_NETWORK_UNKNOWN = 3 +}; + +enum NLA_INTERNET { + NLA_INTERNET_UNKNOWN = 0, + NLA_INTERNET_NO = 1, + NLA_INTERNET_YES = 2 +}; + +struct NLA_BLOB { + struct { + NLA_BLOB_DATA_TYPE type; + DWORD dwSize; + DWORD nextOffset; + } header; + + union { + // NLA_RAW_DATA + CHAR rawData[1]; + + // NLA_INTERFACE + struct { + DWORD dwType; + DWORD dwSpeed; + CHAR adapterName[1]; + } interfaceData; + + // NLA_802_1X_LOCATION + struct { + CHAR information[1]; + } locationData; + + // NLA_CONNECTIVITY + struct { + NLA_CONNECTIVITY_TYPE type; + NLA_INTERNET internet; + } connectivity; + + // NLA_ICS + struct { + struct { + DWORD speed; + DWORD type; + DWORD state; + WCHAR machineName[256]; + WCHAR sharedAdapterName[256]; + } remote; + } ICS; + } data; +}; +#endif + +enum NDIS_MEDIUM { + NdisMedium802_3 = 0, +}; + +enum NDIS_PHYSICAL_MEDIUM { + NdisPhysicalMediumWirelessLan = 1, + NdisPhysicalMediumBluetooth = 10, + NdisPhysicalMediumWiMax = 12, +}; + +#define OID_GEN_MEDIA_SUPPORTED 0x00010103 +#define OID_GEN_PHYSICAL_MEDIUM 0x00010202 + +#define IOCTL_NDIS_QUERY_GLOBAL_STATS \ + CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD, 0, METHOD_OUT_DIRECT, FILE_ANY_ACCESS) + +#endif diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro index 004b816..d6a426f 100644 --- a/src/plugins/plugins.pro +++ b/src/plugins/plugins.pro @@ -1,6 +1,6 @@ TEMPLATE = subdirs -SUBDIRS *= accessible imageformats sqldrivers iconengines script +SUBDIRS *= accessible imageformats sqldrivers iconengines script bearer unix:!symbian { contains(QT_CONFIG,iconv)|contains(QT_CONFIG,gnu-libiconv):SUBDIRS *= codecs } else { |