summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2010-02-20 05:50:12 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2010-02-20 05:50:12 (GMT)
commit1449a1b84f12d937b56ae2b9f4a3ba3dc704281e (patch)
tree04371e32433d58f19c51de2df2a89193d6914c3c /src/plugins
parent8f10ca802dee1ed110f301191c4a56a85575033c (diff)
parent840dab97ee4bd68dcf75cfd2edd5e58c38040ae1 (diff)
downloadQt-1449a1b84f12d937b56ae2b9f4a3ba3dc704281e.zip
Qt-1449a1b84f12d937b56ae2b9f4a3ba3dc704281e.tar.gz
Qt-1449a1b84f12d937b56ae2b9f4a3ba3dc704281e.tar.bz2
Merge branch 'master' of scm.dev.nokia.troll.no:qt/mobility-staging into master-integration
* 'master' of scm.dev.nokia.troll.no:qt/mobility-staging: (114 commits) Create unit-test in parent directory. Allow QNAM to be created as a global variable. Don't load NetworkManager plugin in NetworkManager is not available. Disable NLA plugin, build generic on win32 and mac. Fix QNetworkSession unit test. Fix segfault. Remove debug output. Make this a warning. Don't block forever if no bearer plugins are loaded. Always build generic plugin when building NetworkManager plugin. Add QT_MODULE headers. Change docs: "phone" -> "device". Remove unused code. Simplify. Optimise iterations over QHash. Use snippets. Reorder members to remove hole. Expand documentation for QNAM::setConfiguration() and friends. Fix build on Windows, typo. Fix build on Windows. ...
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/bearer/bearer.pro14
-rw-r--r--src/plugins/bearer/corewlan/corewlan.pro24
-rw-r--r--src/plugins/bearer/corewlan/main.cpp84
-rw-r--r--src/plugins/bearer/corewlan/qcorewlanengine.h99
-rw-r--r--src/plugins/bearer/corewlan/qcorewlanengine.mm531
-rw-r--r--src/plugins/bearer/generic/generic.pro16
-rw-r--r--src/plugins/bearer/generic/main.cpp84
-rw-r--r--src/plugins/bearer/generic/qgenericengine.cpp323
-rw-r--r--src/plugins/bearer/generic/qgenericengine.h92
-rw-r--r--src/plugins/bearer/icd/icd.pro22
-rw-r--r--src/plugins/bearer/icd/main.cpp84
-rw-r--r--src/plugins/bearer/icd/monitor.cpp116
-rw-r--r--src/plugins/bearer/icd/monitor.h116
-rw-r--r--src/plugins/bearer/icd/qicdengine.cpp416
-rw-r--r--src/plugins/bearer/icd/qicdengine.h122
-rw-r--r--src/plugins/bearer/icd/qnetworksession_impl.cpp1105
-rw-r--r--src/plugins/bearer/icd/qnetworksession_impl.h147
-rw-r--r--src/plugins/bearer/nativewifi/main.cpp139
-rw-r--r--src/plugins/bearer/nativewifi/nativewifi.pro17
-rw-r--r--src/plugins/bearer/nativewifi/platformdefs.h322
-rw-r--r--src/plugins/bearer/nativewifi/qnativewifiengine.cpp481
-rw-r--r--src/plugins/bearer/nativewifi/qnativewifiengine.h104
-rw-r--r--src/plugins/bearer/networkmanager/main.cpp89
-rw-r--r--src/plugins/bearer/networkmanager/networkmanager.pro20
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp797
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerengine.h139
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp1046
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerservice.h397
-rw-r--r--src/plugins/bearer/networkmanager/qnmdbushelper.cpp117
-rw-r--r--src/plugins/bearer/networkmanager/qnmdbushelper.h73
-rw-r--r--src/plugins/bearer/nla/main.cpp84
-rw-r--r--src/plugins/bearer/nla/nla.pro23
-rw-r--r--src/plugins/bearer/nla/qnlaengine.cpp651
-rw-r--r--src/plugins/bearer/nla/qnlaengine.h114
-rw-r--r--src/plugins/bearer/platformdefs_win.h134
-rw-r--r--src/plugins/bearer/qbearerengine_impl.h81
-rw-r--r--src/plugins/bearer/qnetworksession_impl.cpp408
-rw-r--r--src/plugins/bearer/qnetworksession_impl.h130
-rw-r--r--src/plugins/bearer/symbian/main.cpp84
-rw-r--r--src/plugins/bearer/symbian/qnetworksession_impl.cpp1135
-rw-r--r--src/plugins/bearer/symbian/qnetworksession_impl.h196
-rw-r--r--src/plugins/bearer/symbian/symbian.pro37
-rw-r--r--src/plugins/bearer/symbian/symbianengine.cpp955
-rw-r--r--src/plugins/bearer/symbian/symbianengine.h202
-rw-r--r--src/plugins/plugins.pro2
45 files changed, 11371 insertions, 1 deletions
diff --git a/src/plugins/bearer/bearer.pro b/src/plugins/bearer/bearer.pro
new file mode 100644
index 0000000..7ba62b3
--- /dev/null
+++ b/src/plugins/bearer/bearer.pro
@@ -0,0 +1,14 @@
+TEMPLATE = subdirs
+
+!maemo:contains(QT_CONFIG, dbus):contains(QT_CONFIG, networkmanager) {
+ SUBDIRS += networkmanager generic
+}
+#win32:SUBDIRS += nla
+win32:SUBDIRS += generic
+win32:!wince*:SUBDIRS += nativewifi
+macx:SUBDIRS += corewlan
+macx:SUBDIRS += generic
+symbian:SUBDIRS += symbian
+maemo6:contains(QT_CONFIG, dbus):SUBDIRS += icd
+
+isEmpty(SUBDIRS):SUBDIRS += generic
diff --git a/src/plugins/bearer/corewlan/corewlan.pro b/src/plugins/bearer/corewlan/corewlan.pro
new file mode 100644
index 0000000..50c72b2
--- /dev/null
+++ b/src/plugins/bearer/corewlan/corewlan.pro
@@ -0,0 +1,24 @@
+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 \
+ ../qnetworksession_impl.h \
+ ../qbearerengine_impl.h
+
+SOURCES += main.cpp \
+ qcorewlanengine.mm \
+ ../qnetworksession_impl.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..5be8c0e
--- /dev/null
+++ b/src/plugins/bearer/corewlan/main.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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/qbearerplugin_p.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..54f2027
--- /dev/null
+++ b/src/plugins/bearer/corewlan/qcorewlanengine.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "../qbearerengine_impl.h"
+
+#include <QMap>
+#include <QTimer>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkConfigurationPrivate;
+
+class QCoreWlanEngine : public QBearerEngineImpl
+{
+ 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);
+
+ QNetworkConfigurationManager::Capabilities capabilities() const;
+
+ QNetworkSessionPrivate *createSessionBackend();
+
+ QNetworkConfigurationPrivatePointer defaultConfiguration();
+
+ 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..fff65e4
--- /dev/null
+++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm
@@ -0,0 +1,531 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "../qnetworksession_impl.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)
+: QBearerEngineImpl(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;
+ ptr->bearer = qGetInterfaceType(interface.name());
+
+ 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 networkSsid = nsstringToQString([apNetwork ssid]);
+
+ 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;
+}
+
+QNetworkConfigurationManager::Capabilities QCoreWlanEngine::capabilities() const
+{
+ return QNetworkConfigurationManager::ForcedRoaming;
+}
+
+QNetworkSessionPrivate *QCoreWlanEngine::createSessionBackend()
+{
+ return new QNetworkSessionPrivateImpl;
+}
+
+QNetworkConfigurationPrivatePointer QCoreWlanEngine::defaultConfiguration()
+{
+ return QNetworkConfigurationPrivatePointer();
+}
+
+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..1d141fd
--- /dev/null
+++ b/src/plugins/bearer/generic/generic.pro
@@ -0,0 +1,16 @@
+TARGET = qgenericbearer
+include(../../qpluginbase.pri)
+
+QT += network
+
+HEADERS += qgenericengine.h \
+ ../qnetworksession_impl.h \
+ ../qbearerengine_impl.h \
+ ../platformdefs_win.h
+SOURCES += qgenericengine.cpp \
+ ../qnetworksession_impl.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..ba85d93
--- /dev/null
+++ b/src/plugins/bearer/generic/main.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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/qbearerplugin_p.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..dba2c08
--- /dev/null
+++ b/src/plugins/bearer/generic/qgenericengine.cpp
@@ -0,0 +1,323 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "../qnetworksession_impl.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)
+: QBearerEngineImpl(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);
+}
+
+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)) {
+ 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;
+ ptr->bearer = qGetInterfaceType(interface.name());
+
+ 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();
+}
+
+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;
+}
+
+QNetworkConfigurationManager::Capabilities QGenericEngine::capabilities() const
+{
+ return QNetworkConfigurationManager::ForcedRoaming;
+}
+
+QNetworkSessionPrivate *QGenericEngine::createSessionBackend()
+{
+ return new QNetworkSessionPrivateImpl;
+}
+
+QNetworkConfigurationPrivatePointer QGenericEngine::defaultConfiguration()
+{
+ return QNetworkConfigurationPrivatePointer();
+}
+
+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..cd9a976
--- /dev/null
+++ b/src/plugins/bearer/generic/qgenericengine.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "../qbearerengine_impl.h"
+
+#include <QMap>
+#include <QTimer>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkConfigurationPrivate;
+class QNetworkSessionPrivate;
+
+class QGenericEngine : public QBearerEngineImpl
+{
+ 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);
+
+ QNetworkConfigurationManager::Capabilities capabilities() const;
+
+ QNetworkSessionPrivate *createSessionBackend();
+
+ QNetworkConfigurationPrivatePointer defaultConfiguration();
+
+private Q_SLOTS:
+ void doRequestUpdate();
+
+private:
+ QMap<QString, QString> configurationInterface;
+ QTimer pollTimer;
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/plugins/bearer/icd/icd.pro b/src/plugins/bearer/icd/icd.pro
new file mode 100644
index 0000000..5eaf5af
--- /dev/null
+++ b/src/plugins/bearer/icd/icd.pro
@@ -0,0 +1,22 @@
+TARGET = qicdbearer
+include(../../qpluginbase.pri)
+
+QT += network dbus
+
+CONFIG += link_pkgconfig
+PKGCONFIG += glib-2.0 dbus-glib-1 gconf-2.0 osso-ic conninet
+
+HEADERS += qicdengine.h \
+ monitor.h \
+ qnetworksession_impl.h
+
+SOURCES += main.cpp \
+ qicdengine.cpp \
+ monitor.cpp \
+ qnetworksession_impl.cpp
+
+#DEFINES += BEARER_MANAGEMENT_DEBUG
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/bearer
+target.path += $$[QT_INSTALL_PLUGINS]/bearer
+INSTALLS += target
diff --git a/src/plugins/bearer/icd/main.cpp b/src/plugins/bearer/icd/main.cpp
new file mode 100644
index 0000000..b131ccb
--- /dev/null
+++ b/src/plugins/bearer/icd/main.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "qicdengine.h"
+
+#include <QtNetwork/private/qbearerengine_p.h>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QIcdEnginePlugin : public QBearerEnginePlugin
+{
+public:
+ QIcdEnginePlugin();
+ ~QIcdEnginePlugin();
+
+ QStringList keys() const;
+ QBearerEngine *create(const QString &key) const;
+};
+
+QIcdEnginePlugin::QIcdEnginePlugin()
+{
+}
+
+QIcdEnginePlugin::~QIcdEnginePlugin()
+{
+}
+
+QStringList QIcdEnginePlugin::keys() const
+{
+ return QStringList() << QLatin1String("icd");
+}
+
+QBearerEngine *QIcdEnginePlugin::create(const QString &key) const
+{
+ if (key == QLatin1String("icd"))
+ return new QIcdEngine;
+ else
+ return 0;
+}
+
+Q_EXPORT_STATIC_PLUGIN(QIcdEnginePlugin)
+Q_EXPORT_PLUGIN2(qicdbearer, QIcdEnginePlugin)
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/icd/monitor.cpp b/src/plugins/bearer/icd/monitor.cpp
new file mode 100644
index 0000000..0ff45d2
--- /dev/null
+++ b/src/plugins/bearer/icd/monitor.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "monitor.h"
+#include "qicdengine.h"
+
+#include <wlancond.h>
+#include <libicd-network-wlan-dev.h>
+#include <maemo_icd.h>
+#include <iapconf.h>
+
+#define IAP "/system/osso/connectivity/IAP"
+
+static int iap_prefix_len;
+
+/* Notify func that is called when IAP is added or deleted */
+void notify_iap(GConfClient *, guint, GConfEntry *entry, gpointer user_data)
+{
+ const char *key = gconf_entry_get_key(entry);
+ if (key && g_str_has_prefix(key, IAP)) {
+ IapMonitor *ptr = (IapMonitor *)user_data;
+ if (gconf_entry_get_value(entry)) {
+ ptr->iapAdded(key, entry);
+ } else {
+ ptr->iapDeleted(key, entry);
+ }
+ }
+}
+
+
+void IapMonitor::setup(QIcdEngine *d_ptr)
+{
+ if (first_call) {
+ d = d_ptr;
+ iap_prefix_len = strlen(IAP);
+ iap = new Maemo::IAPMonitor(notify_iap, (gpointer)this);
+ first_call = false;
+ }
+}
+
+
+void IapMonitor::cleanup()
+{
+ if (!first_call) {
+ delete iap;
+ timers.removeAll();
+ first_call = true;
+ }
+}
+
+
+void IapMonitor::iapAdded(const char *key, GConfEntry * /*entry*/)
+{
+ //qDebug("Notify called for added element: %s=%s",
+ // gconf_entry_get_key(entry), gconf_value_to_string(gconf_entry_get_value(entry)));
+
+ /* We cannot know when the IAP is fully added to gconf, so a timer is
+ * installed instead. When the timer expires we hope that IAP is added ok.
+ */
+ QString iap_id = QString(key + iap_prefix_len + 1).section('/',0,0);
+ timers.add(iap_id, d);
+}
+
+
+void IapMonitor::iapDeleted(const char *key, GConfEntry * /*entry*/)
+{
+ //qDebug("Notify called for deleted element: %s", gconf_entry_get_key(entry));
+
+ /* We are only interested in IAP deletions so we skip the config entries
+ */
+ if (strstr(key + iap_prefix_len + 1, "/")) {
+ //qDebug("Deleting IAP config %s", key+iap_prefix_len);
+ return;
+ }
+
+ QString iap_id = key + iap_prefix_len + 1;
+ d->deleteConfiguration(iap_id);
+}
diff --git a/src/plugins/bearer/icd/monitor.h b/src/plugins/bearer/icd/monitor.h
new file mode 100644
index 0000000..82b0f36
--- /dev/null
+++ b/src/plugins/bearer/icd/monitor.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 MONITOR_H
+#define MONITOR_H
+
+#include <QtCore/qhash.h>
+#include <QtCore/qtimer.h>
+
+#include <gconf/gconf.h>
+#include <gconf/gconf-client.h>
+
+#include <iapmonitor.h>
+
+class QIcdEngine;
+
+/* The IapAddTimer is a helper class that makes sure we update
+ * the configuration only after all gconf additions to certain
+ * iap are finished (after a certain timeout)
+ */
+class _IapAddTimer : public QObject
+{
+ Q_OBJECT
+
+public:
+ _IapAddTimer() {}
+ ~_IapAddTimer()
+ {
+ if (timer.isActive()) {
+ QObject::disconnect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
+ timer.stop();
+ }
+ }
+
+ void add(QString& iap_id, QIcdEngine *d);
+
+ QString iap_id;
+ QTimer timer;
+ QIcdEngine *d;
+
+public Q_SLOTS:
+ void timeout();
+};
+
+class IapAddTimer {
+ QHash<QString, _IapAddTimer* > timers;
+
+public:
+ IapAddTimer() {}
+ ~IapAddTimer() {}
+
+ void add(QString& iap_id, QIcdEngine *d);
+ void del(QString& iap_id);
+ void removeAll();
+};
+
+class IapMonitor
+{
+public:
+ IapMonitor() : first_call(true) { }
+ friend void notify_iap(GConfClient *, guint,
+ GConfEntry *entry, gpointer user_data);
+
+ void setup(QIcdEngine *d);
+ void cleanup();
+
+private:
+ bool first_call;
+
+ void iapAdded(const char *key, GConfEntry *entry);
+ void iapDeleted(const char *key, GConfEntry *entry);
+
+ Maemo::IAPMonitor *iap;
+ QIcdEngine *d;
+ IapAddTimer timers;
+};
+
+#endif // MONITOR_H
diff --git a/src/plugins/bearer/icd/qicdengine.cpp b/src/plugins/bearer/icd/qicdengine.cpp
new file mode 100644
index 0000000..3233eda
--- /dev/null
+++ b/src/plugins/bearer/icd/qicdengine.cpp
@@ -0,0 +1,416 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "qicdengine.h"
+#include "monitor.h"
+#include "qnetworksession_impl.h"
+
+#include <libicd-network-wlan-dev.h>
+#include <maemo_icd.h>
+#include <iapconf.h>
+
+QT_BEGIN_NAMESPACE
+
+IcdNetworkConfigurationPrivate::IcdNetworkConfigurationPrivate()
+: network_attrs(0), service_attrs(0)
+{
+}
+
+IcdNetworkConfigurationPrivate::~IcdNetworkConfigurationPrivate()
+{
+}
+
+QString IcdNetworkConfigurationPrivate::bearerName() const
+{
+ if (iap_type == QLatin1String("WLAN_INFRA") ||
+ iap_type == QLatin1String("WLAN_ADHOC")) {
+ return QLatin1String("WLAN");
+ } else if (iap_type == QLatin1String("GPRS")) {
+ return QLatin1String("HSPA");
+ } else {
+ return iap_type;
+ }
+}
+
+static inline QString network_attrs_to_security(uint network_attrs)
+{
+ uint cap = 0;
+ nwattr2cap(network_attrs, &cap); /* from libicd-network-wlan-dev.h */
+ if (cap & WLANCOND_OPEN)
+ return "NONE";
+ else if (cap & WLANCOND_WEP)
+ return "WEP";
+ else if (cap & WLANCOND_WPA_PSK)
+ return "WPA_PSK";
+ else if (cap & WLANCOND_WPA_EAP)
+ return "WPA_EAP";
+ return "";
+}
+
+QIcdEngine::QIcdEngine(QObject *parent)
+: QBearerEngine(parent), iapMonitor(new IapMonitor)
+{
+ /* Turn on IAP monitoring */
+ iapMonitor->setup(this);
+
+ doRequestUpdate();
+}
+
+QIcdEngine::~QIcdEngine()
+{
+}
+
+bool QIcdEngine::hasIdentifier(const QString &id)
+{
+ return accessPointConfigurations.contains(id) ||
+ snapConfigurations.contains(id) ||
+ userChoiceConfigurations.contains(id);
+}
+
+void QIcdEngine::requestUpdate()
+{
+ QTimer::singleShot(0, this, SLOT(doRequestUpdate()));
+}
+
+static uint32_t getNetworkAttrs(bool is_iap_id,
+ QString& iap_id,
+ QString& iap_type,
+ QString security_method)
+{
+ guint network_attr = 0;
+ dbus_uint32_t cap = 0;
+
+ if (iap_type == "WLAN_INFRA")
+ cap |= WLANCOND_INFRA;
+ else if (iap_type == "WLAN_ADHOC")
+ cap |= WLANCOND_ADHOC;
+
+ if (security_method.isEmpty() && (cap & (WLANCOND_INFRA | WLANCOND_ADHOC))) {
+ Maemo::IAPConf saved_ap(iap_id);
+ security_method = saved_ap.value("wlan_security").toString();
+ }
+
+ if (!security_method.isEmpty()) {
+ if (security_method == "WEP")
+ cap |= WLANCOND_WEP;
+ else if (security_method == "WPA_PSK")
+ cap |= WLANCOND_WPA_PSK;
+ else if (security_method == "WPA_EAP")
+ cap |= WLANCOND_WPA_EAP;
+ else if (security_method == "NONE")
+ cap |= WLANCOND_OPEN;
+
+ if (cap & (WLANCOND_WPA_PSK | WLANCOND_WPA_EAP)) {
+ Maemo::IAPConf saved_iap(iap_id);
+ bool wpa2_only = saved_iap.value("EAP_wpa2_only_mode").toBool();
+ if (wpa2_only) {
+ cap |= WLANCOND_WPA2;
+ }
+ }
+ }
+
+ cap2nwattr(cap, &network_attr);
+ if (is_iap_id)
+ network_attr |= ICD_NW_ATTR_IAPNAME;
+
+ return (uint32_t)network_attr;
+}
+
+void QIcdEngine::doRequestUpdate()
+{
+ QStringList previous = accessPointConfigurations.keys();
+
+ /* All the scanned access points */
+ QList<Maemo::IcdScanResult> scanned;
+
+ /* We create a default configuration which is a pseudo config */
+ if (!userChoiceConfigurations.contains(OSSO_IAP_ANY)) {
+ QNetworkConfigurationPrivatePointer ptr(new IcdNetworkConfigurationPrivate);
+
+ ptr->name = QLatin1String("UserChoice");
+ ptr->state = QNetworkConfiguration::Discovered;
+ ptr->isValid = true;
+ ptr->id = OSSO_IAP_ANY;
+ ptr->type = QNetworkConfiguration::UserChoice;
+ ptr->purpose = QNetworkConfiguration::UnknownPurpose;
+ ptr->roamingSupported = false;
+
+ userChoiceConfigurations.insert(ptr->id, ptr);
+ emit configurationAdded(ptr);
+ }
+
+ /* We return currently configured IAPs in the first run and do the WLAN
+ * scan in subsequent runs.
+ */
+ QList<QString> all_iaps;
+ Maemo::IAPConf::getAll(all_iaps);
+
+ foreach (QString escaped_iap_id, all_iaps) {
+ QByteArray ssid;
+
+ /* The key that is returned by getAll() needs to be unescaped */
+ gchar *unescaped_id = gconf_unescape_key(escaped_iap_id.toUtf8().data(), -1);
+ QString iap_id = QString((char *)unescaped_id);
+ g_free(unescaped_id);
+
+ previous.removeAll(iap_id);
+
+ Maemo::IAPConf saved_ap(iap_id);
+ bool is_temporary = saved_ap.value("temporary").toBool();
+ if (is_temporary) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "IAP" << iap_id << "is temporary, skipping it.";
+#endif
+ continue;
+ }
+
+ QString iap_type = saved_ap.value("type").toString();
+ if (iap_type.startsWith("WLAN")) {
+ ssid = saved_ap.value("wlan_ssid").toByteArray();
+ if (ssid.isEmpty()) {
+ qWarning() << "Cannot get ssid for" << iap_id;
+ continue;
+ }
+
+ QString security_method = saved_ap.value("wlan_security").toString();
+ } else if (iap_type.isEmpty()) {
+ qWarning() << "IAP" << iap_id << "network type is not set! Skipping it";
+ continue;
+ } else {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "IAP" << iap_id << "network type is" << iap_type;
+#endif
+ ssid.clear();
+ }
+
+ if (!accessPointConfigurations.contains(iap_id)) {
+ IcdNetworkConfigurationPrivate *cpPriv = new IcdNetworkConfigurationPrivate;
+
+ cpPriv->name = saved_ap.value("name").toString();
+ if (cpPriv->name.isEmpty())
+ if (!ssid.isEmpty() && ssid.size() > 0)
+ cpPriv->name = ssid.data();
+ else
+ cpPriv->name = iap_id;
+ cpPriv->isValid = true;
+ cpPriv->id = iap_id;
+ cpPriv->network_id = ssid;
+ cpPriv->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
+ cpPriv->iap_type = iap_type;
+ cpPriv->service_id = saved_ap.value("service_id").toString();
+ cpPriv->service_type = saved_ap.value("service_type").toString();
+ cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
+ cpPriv->state = QNetworkConfiguration::Defined;
+
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ accessPointConfigurations.insert(iap_id, ptr);
+ emit configurationAdded(ptr);
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug("IAP: %s, name: %s, ssid: %s, added to known list",
+ iap_id.toAscii().data(), ptr->name.toAscii().data(),
+ !ssid.isEmpty() ? ssid.data() : "-");
+#endif
+ } else {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug("IAP: %s, ssid: %s, already exists in the known list",
+ iap_id.toAscii().data(), !ssid.isEmpty() ? ssid.data() : "-");
+#endif
+ }
+ }
+
+ if (sender()) {
+ QStringList scannedNetworkTypes;
+ QStringList networkTypesToScan;
+ QString error;
+ Maemo::Icd icd(ICD_SHORT_SCAN_TIMEOUT);
+
+ scannedNetworkTypes = icd.scan(ICD_SCAN_REQUEST_ACTIVE,
+ networkTypesToScan,
+ scanned,
+ error);
+ if (!error.isEmpty()) {
+ qWarning() << "Network scanning failed" << error;
+ } else {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ if (!scanned.isEmpty())
+ qDebug() << "Scan returned" << scanned.size() << "networks";
+ else
+ qDebug() << "Scan returned nothing.";
+#endif
+ }
+ }
+
+ /* This is skipped in the first update as scanned size is zero */
+ if (!scanned.isEmpty()) {
+ for (int i=0; i<scanned.size(); ++i) {
+ const Maemo::IcdScanResult ap = scanned.at(i);
+
+ QByteArray scanned_ssid = ap.scan.network_id;
+
+ if (ap.scan.network_attrs & ICD_NW_ATTR_IAPNAME) {
+ /* The network_id is IAP id, so the IAP is a known one */
+ QString iapid = ap.scan.network_id.data();
+
+ previous.removeAll(iapid);
+
+ if (accessPointConfigurations.contains(iapid)) {
+ QNetworkConfigurationPrivatePointer ptr =
+ accessPointConfigurations.value(iapid);
+
+ bool changed = false;
+
+ if (!ptr->isValid) {
+ ptr->isValid = true;
+ changed = true;
+ }
+
+ if (ptr->state != QNetworkConfiguration::Discovered) {
+ ptr->state = QNetworkConfiguration::Discovered;
+ changed = true;
+ }
+
+ toIcdConfig(ptr)->network_attrs = ap.scan.network_attrs;
+ toIcdConfig(ptr)->service_id = ap.scan.service_id;
+ toIcdConfig(ptr)->service_type = ap.scan.service_type;
+ toIcdConfig(ptr)->service_attrs = ap.scan.service_attrs;
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug("IAP: %s, ssid: %s, discovered",
+ iapid.toAscii().data(), scanned_ssid.data());
+#endif
+
+ if (changed)
+ emit configurationChanged(ptr);
+
+ if (!ap.scan.network_type.startsWith("WLAN"))
+ continue; // not a wlan AP
+ }
+ } else {
+ IcdNetworkConfigurationPrivate *cpPriv = new IcdNetworkConfigurationPrivate;
+
+ QString hrs = scanned_ssid.data();
+
+ cpPriv->name = ap.network_name.isEmpty() ? hrs : ap.network_name;
+ cpPriv->isValid = true;
+ // Note: id is now ssid, it should be set to IAP id if the IAP is saved
+ cpPriv->id = scanned_ssid.data();
+ cpPriv->network_id = scanned_ssid;
+ cpPriv->iap_type = ap.scan.network_type;
+ if (cpPriv->iap_type.isEmpty())
+ cpPriv->iap_type = QLatin1String("WLAN");
+ cpPriv->network_attrs = ap.scan.network_attrs;
+ cpPriv->service_id = ap.scan.service_id;
+ cpPriv->service_type = ap.scan.service_type;
+ cpPriv->service_attrs = ap.scan.service_attrs;
+
+ cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
+ cpPriv->state = QNetworkConfiguration::Undefined;
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "IAP with network id" << cpPriv->id << "was found in the scan.";
+#endif
+
+ previous.removeAll(cpPriv->id);
+
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ accessPointConfigurations.insert(ptr->id, ptr);
+ emit configurationAdded(ptr);
+ }
+ }
+ }
+
+ while (!previous.isEmpty()) {
+ QNetworkConfigurationPrivatePointer ptr =
+ accessPointConfigurations.take(previous.takeFirst());
+
+ emit configurationRemoved(ptr);
+ }
+
+ if (sender())
+ emit updateCompleted();
+}
+
+void QIcdEngine::deleteConfiguration(const QString &iap_id)
+{
+ /* Called when IAPs are deleted in gconf, in this case we do not scan
+ * or read all the IAPs from gconf because it might take too much power
+ * (multiple applications would need to scan and read all IAPs from gconf)
+ */
+ if (accessPointConfigurations.contains(iap_id)) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(iap_id);
+
+ if (ptr) {
+ ptr->isValid = false;
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "IAP" << iap_id << "was removed from storage.";
+#endif
+
+ emit configurationRemoved(ptr);
+ } else {
+ qWarning("Configuration not found for IAP %s", iap_id.toAscii().data());
+ }
+ } else {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug("IAP: %s, already missing from the known list", iap_id.toAscii().data());
+#endif
+ }
+}
+
+QNetworkConfigurationManager::Capabilities QIcdEngine::capabilities() const
+{
+ return QNetworkConfigurationManager::CanStartAndStopInterfaces |
+ QNetworkConfigurationManager::DataStatistics |
+ QNetworkConfigurationManager::ForcedRoaming;
+}
+
+QNetworkSessionPrivate *QIcdEngine::createSessionBackend()
+{
+ return new QNetworkSessionPrivateImpl(this);
+}
+
+QNetworkConfigurationPrivatePointer QIcdEngine::defaultConfiguration()
+{
+ // Here we just return [ANY] request to icd and let the icd decide which IAP to connect.
+ return userChoiceConfigurations.value(OSSO_IAP_ANY);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/icd/qicdengine.h b/src/plugins/bearer/icd/qicdengine.h
new file mode 100644
index 0000000..30b5711
--- /dev/null
+++ b/src/plugins/bearer/icd/qicdengine.h
@@ -0,0 +1,122 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 QICDENGINE_H
+#define QICDENGINE_H
+
+#include <QtNetwork/private/qbearerengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkConfigurationPrivate;
+class IapMonitor;
+
+class IcdNetworkConfigurationPrivate : public QNetworkConfigurationPrivate
+{
+public:
+ IcdNetworkConfigurationPrivate();
+ ~IcdNetworkConfigurationPrivate();
+
+ QString bearerName() const;
+
+ // In Maemo the id field (defined in QNetworkConfigurationPrivate)
+ // is the IAP id (which typically is UUID)
+ QByteArray network_id; // typically WLAN ssid or similar
+ QString iap_type; // is this one WLAN or GPRS
+
+ // Network attributes for this IAP, this is the value returned by icd and
+ // passed to it when connecting.
+ uint32_t network_attrs;
+
+ QString service_type;
+ QString service_id;
+ uint32_t service_attrs;
+};
+
+inline IcdNetworkConfigurationPrivate *toIcdConfig(QNetworkConfigurationPrivatePointer ptr)
+{
+ return static_cast<IcdNetworkConfigurationPrivate *>(ptr.data());
+}
+
+class QIcdEngine : public QBearerEngine
+{
+ Q_OBJECT
+
+ friend class QNetworkSessionPrivateImpl;
+
+public:
+ QIcdEngine(QObject *parent = 0);
+ ~QIcdEngine();
+
+ bool hasIdentifier(const QString &id);
+
+ void requestUpdate();
+
+ QNetworkConfigurationManager::Capabilities capabilities() const;
+
+ QNetworkSessionPrivate *createSessionBackend();
+
+ QNetworkConfigurationPrivatePointer defaultConfiguration();
+
+ void deleteConfiguration(const QString &iap_id);
+
+private:
+ inline void addSessionConfiguration(QNetworkConfigurationPrivatePointer ptr)
+ {
+ accessPointConfigurations.insert(ptr->id, ptr);
+ emit configurationAdded(ptr);
+ }
+
+ inline void changedSessionConfiguration(QNetworkConfigurationPrivatePointer ptr)
+ {
+ emit configurationChanged(ptr);
+ }
+
+private Q_SLOTS:
+ void doRequestUpdate();
+
+private:
+ IapMonitor *iapMonitor;
+};
+
+QT_END_NAMESPACE
+
+#endif // QICDENGINE_H
diff --git a/src/plugins/bearer/icd/qnetworksession_impl.cpp b/src/plugins/bearer/icd/qnetworksession_impl.cpp
new file mode 100644
index 0000000..6cc4a1d
--- /dev/null
+++ b/src/plugins/bearer/icd/qnetworksession_impl.cpp
@@ -0,0 +1,1105 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "qnetworksession_impl.h"
+#include "qicdengine.h"
+
+#include <QHash>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <maemo_icd.h>
+#include <iapconf.h>
+
+#include <sys/types.h>
+#include <ifaddrs.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+QT_BEGIN_NAMESPACE
+
+static QHash<QString, QVariant> properties;
+
+static QString get_network_interface();
+static DBusConnection *dbus_connection;
+static DBusHandlerResult signal_handler(DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data);
+
+#define ICD_DBUS_MATCH "type='signal'," \
+ "interface='" ICD_DBUS_INTERFACE "'," \
+ "path='" ICD_DBUS_PATH "'"
+
+
+static inline DBusConnection *get_dbus_conn(DBusError *error)
+{
+ DBusConnection *conn = dbus_bus_get(DBUS_BUS_SYSTEM, error);
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "Listening to bus" << dbus_bus_get_unique_name(conn);
+#endif
+
+ return conn;
+}
+
+
+/* Helper class that monitors the Icd status messages and
+ * can change the IAP status accordingly. This is a singleton.
+ */
+class IcdListener : public QObject
+{
+ Q_OBJECT
+
+public:
+ IcdListener() : first_call(true) { }
+ friend DBusHandlerResult signal_handler(DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data);
+ void setup(QNetworkSessionPrivateImpl *d);
+ void cleanup();
+ void cleanupSession(QNetworkSessionPrivateImpl *ptr);
+
+ enum IapConnectionStatus {
+ /* The IAP was connected */
+ CONNECTED = 0,
+ /* The IAP was disconnected */
+ DISCONNECTED,
+ /* The IAP is disconnecting */
+ DISCONNECTING,
+ /* The IAP has a network address, but is not yet fully connected */
+ NETWORK_UP
+ };
+
+private:
+ void icdSignalReceived(QString&, QString&, QString&);
+ bool first_call;
+ QHash<QString, QNetworkSessionPrivateImpl *> sessions;
+};
+
+Q_GLOBAL_STATIC(IcdListener, icdListener);
+
+
+static DBusHandlerResult signal_handler(DBusConnection *,
+ DBusMessage *message,
+ void *user_data)
+{
+ if (dbus_message_is_signal(message,
+ ICD_DBUS_INTERFACE,
+ ICD_STATUS_CHANGED_SIG)) {
+
+ IcdListener *icd = (IcdListener *)user_data;
+ DBusError error;
+ dbus_error_init(&error);
+
+ char *iap_id = 0;
+ char *network_type = 0;
+ char *state = 0;
+
+ if (dbus_message_get_args(message, &error,
+ DBUS_TYPE_STRING, &iap_id,
+ DBUS_TYPE_STRING, &network_type,
+ DBUS_TYPE_STRING, &state,
+ DBUS_TYPE_INVALID) == FALSE) {
+ qWarning() << QString("Failed to parse icd status signal: %1").arg(error.message);
+ } else {
+ QString _iap_id(iap_id);
+ QString _network_type(network_type);
+ QString _state(state);
+
+ icd->icdSignalReceived(_iap_id, _network_type, _state);
+ }
+
+ dbus_error_free(&error);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+
+void IcdListener::setup(QNetworkSessionPrivateImpl *d)
+{
+ if (first_call) {
+ // We use the old Icd dbus interface like in ConIC
+ DBusError error;
+ dbus_error_init(&error);
+
+ dbus_connection = get_dbus_conn(&error);
+ if (dbus_error_is_set(&error)) {
+ qWarning() << "Cannot get dbus connection.";
+ dbus_error_free(&error);
+ return;
+ }
+
+ static struct DBusObjectPathVTable icd_vtable;
+ icd_vtable.message_function = signal_handler;
+
+ dbus_bus_add_match(dbus_connection, ICD_DBUS_MATCH, &error);
+ if (dbus_error_is_set(&error)) {
+ qWarning() << "Cannot add match" << ICD_DBUS_MATCH;
+ dbus_error_free(&error);
+ return;
+ }
+
+ if (dbus_connection_register_object_path(dbus_connection,
+ ICD_DBUS_PATH,
+ &icd_vtable,
+ (void*)this) == FALSE) {
+ qWarning() << "Cannot register dbus signal handler, interface"<< ICD_DBUS_INTERFACE << "path" << ICD_DBUS_PATH;
+ dbus_error_free(&error);
+ return;
+ }
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "Listening" << ICD_STATUS_CHANGED_SIG << "signal from" << ICD_DBUS_SERVICE;
+#endif
+ first_call = false;
+ dbus_error_free(&error);
+ }
+
+ QString id = d->activeConfig.identifier();
+ if (!sessions.contains(id)) {
+ QNetworkSessionPrivateImpl *ptr = d;
+ sessions.insert(id, ptr);
+ }
+}
+
+
+void IcdListener::icdSignalReceived(QString& iap_id,
+#ifdef BEARER_MANAGEMENT_DEBUG
+ QString& network_type,
+#else
+ QString&,
+#endif
+ QString& state)
+{
+ if (iap_id == OSSO_IAP_SCAN) // icd sends scan status signals which we will ignore
+ return;
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "Status received:" << iap_id << "type" << network_type << "state" << state;
+#endif
+
+ if (!sessions.contains(iap_id)) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "No session for IAP" << iap_id;
+#endif
+ return;
+ }
+
+ QNetworkSessionPrivateImpl *session = sessions.value(iap_id);
+ QNetworkConfiguration ap_conf =
+ QNetworkConfigurationManager().configurationFromIdentifier(iap_id);
+ if (!ap_conf.isValid()) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "Unknown IAP" << iap_id;
+#endif
+ return;
+ }
+
+ IapConnectionStatus status;
+
+ if (state == "IDLE") {
+ status = DISCONNECTED;
+ } else if (state == "CONNECTED") {
+ status = CONNECTED;
+ } else if (state == "NETWORKUP") {
+ status = NETWORK_UP;
+ } else {
+ //qDebug() << "Unknown state" << state;
+ return;
+ }
+
+ if (status == DISCONNECTED) {
+ if (ap_conf.state() == QNetworkConfiguration::Active) {
+ /* The IAP was just disconnected by Icd */
+ session->updateState(QNetworkSession::Disconnected);
+ } else {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "Got a network disconnect when in state" << ap_conf.state();
+#endif
+ }
+ } else if (status == CONNECTED) {
+ /* The IAP was just connected by Icd */
+ session->updateState(QNetworkSession::Connected);
+ session->updateIdentifier(iap_id);
+
+ if (session->publicConfig.identifier() == OSSO_IAP_ANY) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "IAP" << iap_id << "connected when connecting to" << OSSO_IAP_ANY;
+#endif
+ } else {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "IAP" << iap_id << "connected";
+#endif
+ }
+ }
+
+ return;
+}
+
+
+void IcdListener::cleanup()
+{
+ if (!first_call) {
+ dbus_bus_remove_match(dbus_connection, ICD_DBUS_MATCH, NULL);
+ dbus_connection_unref(dbus_connection);
+ }
+}
+
+
+void IcdListener::cleanupSession(QNetworkSessionPrivateImpl *ptr)
+{
+ if (ptr->publicConfig.type() == QNetworkConfiguration::UserChoice)
+ (void)sessions.take(ptr->activeConfig.identifier());
+ else
+ (void)sessions.take(ptr->publicConfig.identifier());
+}
+
+
+void QNetworkSessionPrivateImpl::cleanupSession(void)
+{
+ icdListener()->cleanupSession(this);
+}
+
+
+void QNetworkSessionPrivateImpl::updateState(QNetworkSession::State newState)
+{
+ if (newState == state)
+ return;
+
+ state = newState;
+
+ if (state == QNetworkSession::Disconnected) {
+ isOpen = false;
+ currentNetworkInterface.clear();
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice)
+ privateConfiguration(activeConfig)->state = QNetworkConfiguration::Defined;
+ privateConfiguration(publicConfig)->state = QNetworkConfiguration::Defined;
+
+ } else if (state == QNetworkSession::Connected) {
+ isOpen = true;
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ privateConfiguration(activeConfig)->state = QNetworkConfiguration::Active;
+ privateConfiguration(activeConfig)->type = QNetworkConfiguration::InternetAccessPoint;
+ }
+ privateConfiguration(publicConfig)->state = QNetworkConfiguration::Active;
+ }
+
+ emit stateChanged(newState);
+}
+
+
+void QNetworkSessionPrivateImpl::updateIdentifier(QString &newId)
+{
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ toIcdConfig(privateConfiguration(activeConfig))->network_attrs |= ICD_NW_ATTR_IAPNAME;
+ privateConfiguration(activeConfig)->id = newId;
+ } else {
+ toIcdConfig(privateConfiguration(publicConfig))->network_attrs |= ICD_NW_ATTR_IAPNAME;
+ if (privateConfiguration(publicConfig)->id != newId) {
+ qWarning() << "Your config id changed from" << privateConfiguration(publicConfig)->id
+ << "to" << newId;
+ privateConfiguration(publicConfig)->id = newId;
+ }
+ }
+}
+
+
+quint64 QNetworkSessionPrivateImpl::getStatistics(bool sent) const
+{
+ /* This could be also implemented by using the Maemo::Icd::statistics()
+ * that gets the statistics data for a specific IAP. Change if
+ * necessary.
+ */
+ Maemo::Icd icd;
+ QList<Maemo::IcdStatisticsResult> stats_results;
+ quint64 counter_rx = 0, counter_tx = 0;
+
+ if (!icd.statistics(stats_results)) {
+ return 0;
+ }
+
+ foreach (Maemo::IcdStatisticsResult res, stats_results) {
+ if (res.params.network_attrs & ICD_NW_ATTR_IAPNAME) {
+ /* network_id is the IAP UUID */
+ if (QString(res.params.network_id.data()) == activeConfig.identifier()) {
+ counter_tx = res.bytes_sent;
+ counter_rx = res.bytes_received;
+ }
+ } else {
+ /* We probably will never get to this branch */
+ if (res.params.network_id == toIcdConfig(privateConfiguration(activeConfig))->network_id) {
+ counter_tx = res.bytes_sent;
+ counter_rx = res.bytes_received;
+ }
+ }
+ }
+
+ if (sent)
+ return counter_tx;
+ else
+ return counter_rx;
+}
+
+
+quint64 QNetworkSessionPrivateImpl::bytesWritten() const
+{
+ return getStatistics(true);
+}
+
+quint64 QNetworkSessionPrivateImpl::bytesReceived() const
+{
+ return getStatistics(false);
+}
+
+quint64 QNetworkSessionPrivateImpl::activeTime() const
+{
+ if (startTime.isNull()) {
+ return 0;
+ }
+ return startTime.secsTo(QDateTime::currentDateTime());
+}
+
+
+QNetworkConfiguration& QNetworkSessionPrivateImpl::copyConfig(QNetworkConfiguration &fromConfig,
+ QNetworkConfiguration &toConfig,
+ bool deepCopy)
+{
+ IcdNetworkConfigurationPrivate *cpPriv;
+ if (deepCopy) {
+ cpPriv = new IcdNetworkConfigurationPrivate;
+ setPrivateConfiguration(toConfig, QNetworkConfigurationPrivatePointer(cpPriv));
+ } else {
+ cpPriv = toIcdConfig(privateConfiguration(toConfig));
+ }
+
+ cpPriv->name = privateConfiguration(fromConfig)->name;
+ cpPriv->isValid = privateConfiguration(fromConfig)->isValid;
+ // Note that we do not copy id field here as the publicConfig does
+ // not contain a valid IAP id.
+ cpPriv->state = privateConfiguration(fromConfig)->state;
+ cpPriv->type = privateConfiguration(fromConfig)->type;
+ cpPriv->roamingSupported = privateConfiguration(fromConfig)->roamingSupported;
+ cpPriv->purpose = privateConfiguration(fromConfig)->purpose;
+ cpPriv->network_id = toIcdConfig(privateConfiguration(fromConfig))->network_id;
+ cpPriv->iap_type = toIcdConfig(privateConfiguration(fromConfig))->iap_type;
+ cpPriv->network_attrs = toIcdConfig(privateConfiguration(fromConfig))->network_attrs;
+ cpPriv->service_type = toIcdConfig(privateConfiguration(fromConfig))->service_type;
+ cpPriv->service_id = toIcdConfig(privateConfiguration(fromConfig))->service_id;
+ cpPriv->service_attrs = toIcdConfig(privateConfiguration(fromConfig))->service_attrs;
+
+ return toConfig;
+}
+
+
+/* This is called by QNetworkSession constructor and it updates the current
+ * state of the configuration.
+ */
+void QNetworkSessionPrivateImpl::syncStateWithInterface()
+{
+ /* Start to listen Icd status messages. */
+ icdListener()->setup(this);
+
+ /* Initially we are not active although the configuration might be in
+ * connected state.
+ */
+ isOpen = false;
+ opened = false;
+
+ connect(&manager, SIGNAL(updateCompleted()), this, SLOT(networkConfigurationsChanged()));
+
+ connect(&manager, SIGNAL(configurationChanged(QNetworkConfiguration)),
+ this, SLOT(configurationChanged(QNetworkConfiguration)));
+
+ state = QNetworkSession::Invalid;
+ lastError = QNetworkSession::UnknownSessionError;
+
+ switch (publicConfig.type()) {
+ case QNetworkConfiguration::InternetAccessPoint:
+ activeConfig = publicConfig;
+ break;
+ case QNetworkConfiguration::ServiceNetwork:
+ serviceConfig = publicConfig;
+ break;
+ case QNetworkConfiguration::UserChoice:
+ // active config will contain correct data after open() has succeeded
+ copyConfig(publicConfig, activeConfig);
+
+ /* We create new configuration that holds the actual configuration
+ * returned by icd. This way publicConfig still contains the
+ * original user specified configuration.
+ *
+ * Note that the new activeConfig configuration is not inserted
+ * to configurationManager as manager class will get the newly
+ * connected configuration from gconf when the IAP is saved.
+ * This configuration manager update is done by IapMonitor class.
+ * If the ANY connection fails in open(), then the configuration
+ * data is not saved to gconf and will not be added to
+ * configuration manager IAP list.
+ */
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug()<<"New configuration created for" << publicConfig.identifier();
+#endif
+ break;
+ default:
+ /* Invalid configuration, no point continuing */
+ return;
+ }
+
+ if (!activeConfig.isValid())
+ return;
+
+ /* Get the initial state from icd */
+ Maemo::Icd icd;
+ QList<Maemo::IcdStateResult> state_results;
+
+ /* Update the active config from first connection, this is ok as icd
+ * supports only one connection anyway.
+ */
+ if (icd.state(state_results) && !state_results.isEmpty()) {
+
+ /* If we did not get full state back, then we are not
+ * connected and can skip the next part.
+ */
+ if (!(state_results.first().params.network_attrs == 0 &&
+ state_results.first().params.network_id.isEmpty())) {
+
+ /* If we try to connect to specific IAP and we get results back
+ * that tell the icd is actually connected to another IAP,
+ * then do not update current state etc.
+ */
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice ||
+ privateConfiguration(publicConfig)->id == state_results.first().params.network_id) {
+
+ switch (state_results.first().state) {
+ case ICD_STATE_DISCONNECTED:
+ state = QNetworkSession::Disconnected;
+ if (privateConfiguration(activeConfig))
+ privateConfiguration(activeConfig)->isValid = true;
+ break;
+ case ICD_STATE_CONNECTING:
+ state = QNetworkSession::Connecting;
+ if (privateConfiguration(activeConfig))
+ privateConfiguration(activeConfig)->isValid = true;
+ break;
+ case ICD_STATE_CONNECTED:
+ {
+ if (!state_results.first().error.isEmpty())
+ break;
+
+ const QString id = state_results.first().params.network_id;
+
+ QNetworkConfiguration config = manager.configurationFromIdentifier(id);
+ if (config.isValid()) {
+ //we don't want the copied data if the config is already known by the manager
+ //just reuse it so that existing references to the old data get the same update
+ setPrivateConfiguration(activeConfig, privateConfiguration(config));
+ }
+
+ QNetworkConfigurationPrivatePointer ptr = privateConfiguration(activeConfig);
+
+ state = QNetworkSession::Connected;
+ toIcdConfig(ptr)->network_id = state_results.first().params.network_id;
+ ptr->id = toIcdConfig(ptr)->network_id;
+ toIcdConfig(ptr)->network_attrs = state_results.first().params.network_attrs;
+ toIcdConfig(ptr)->iap_type = state_results.first().params.network_type;
+ toIcdConfig(ptr)->service_type = state_results.first().params.service_type;
+ toIcdConfig(ptr)->service_id = state_results.first().params.service_id;
+ toIcdConfig(ptr)->service_attrs = state_results.first().params.service_attrs;
+ ptr->type = QNetworkConfiguration::InternetAccessPoint;
+ ptr->state = QNetworkConfiguration::Active;
+ ptr->isValid = true;
+ currentNetworkInterface = get_network_interface();
+
+ Maemo::IAPConf iap_name(privateConfiguration(activeConfig)->id);
+ QString name_value = iap_name.value("name").toString();
+ if (!name_value.isEmpty())
+ privateConfiguration(activeConfig)->name = name_value;
+ else
+ privateConfiguration(activeConfig)->name = privateConfiguration(activeConfig)->id;
+
+
+ // Add the new active configuration to manager or update the old config
+ if (!(engine->accessPointConfigurations.contains(privateConfiguration(activeConfig)->id)))
+ engine->addSessionConfiguration(privateConfiguration(activeConfig));
+ else
+ engine->changedSessionConfiguration(privateConfiguration(activeConfig));
+ }
+ break;
+
+ case ICD_STATE_DISCONNECTING:
+ state = QNetworkSession::Closing;
+ if (privateConfiguration(activeConfig))
+ privateConfiguration(activeConfig)->isValid = true;
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "status_req tells icd is not connected";
+#endif
+ }
+ } else {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "status_req did not return any results from icd";
+#endif
+ }
+
+ networkConfigurationsChanged();
+}
+
+
+void QNetworkSessionPrivateImpl::networkConfigurationsChanged()
+{
+ if (serviceConfig.isValid())
+ updateStateFromServiceNetwork();
+ else
+ updateStateFromActiveConfig();
+}
+
+
+void QNetworkSessionPrivateImpl::updateStateFromServiceNetwork()
+{
+ QNetworkSession::State oldState = state;
+
+ foreach (const QNetworkConfiguration &config, serviceConfig.children()) {
+ if ((config.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active)
+ continue;
+
+ if (activeConfig != config) {
+ activeConfig = config;
+ emit newConfigurationActivated();
+ }
+
+ state = QNetworkSession::Connected;
+ if (state != oldState)
+ emit stateChanged(state);
+
+ return;
+ }
+
+ if (serviceConfig.children().isEmpty())
+ state = QNetworkSession::NotAvailable;
+ else
+ state = QNetworkSession::Disconnected;
+
+ if (state != oldState)
+ emit stateChanged(state);
+}
+
+
+void QNetworkSessionPrivateImpl::clearConfiguration(QNetworkConfiguration &config)
+{
+ toIcdConfig(privateConfiguration(config))->network_id.clear();
+ toIcdConfig(privateConfiguration(config))->iap_type.clear();
+ toIcdConfig(privateConfiguration(config))->network_attrs = 0;
+ toIcdConfig(privateConfiguration(config))->service_type.clear();
+ toIcdConfig(privateConfiguration(config))->service_id.clear();
+ toIcdConfig(privateConfiguration(config))->service_attrs = 0;
+}
+
+
+void QNetworkSessionPrivateImpl::updateStateFromActiveConfig()
+{
+ QNetworkSession::State oldState = state;
+
+ bool newActive = false;
+
+ if (!privateConfiguration(activeConfig))
+ return;
+
+ if (!activeConfig.isValid()) {
+ state = QNetworkSession::Invalid;
+ clearConfiguration(activeConfig);
+ } else if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ state = QNetworkSession::Connected;
+ newActive = opened;
+ } else if ((activeConfig.state() & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) {
+ state = QNetworkSession::Disconnected;
+ } else if ((activeConfig.state() & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
+ state = QNetworkSession::NotAvailable;
+ } else if ((activeConfig.state() & QNetworkConfiguration::Undefined) == QNetworkConfiguration::Undefined) {
+ state = QNetworkSession::NotAvailable;
+ //clearConfiguration(activeConfig);
+ }
+
+ bool oldActive = isOpen;
+ isOpen = newActive;
+
+ if (!oldActive && isOpen)
+ emit quitPendingWaitsForOpened();
+
+ if (oldActive && !isOpen)
+ emit closed();
+
+ if (oldState != state) {
+ emit stateChanged(state);
+
+ if (state == QNetworkSession::Disconnected) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ //qDebug()<<"session aborted error emitted for"<<activeConfig.identifier();
+#endif
+ lastError = QNetworkSession::SessionAbortedError;
+ emit QNetworkSessionPrivate::error(lastError);
+ }
+ }
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ //qDebug()<<"oldState ="<<oldState<<" state ="<<state<<" oldActive ="<<oldActive<<" newActive ="<<newActive<<" opened ="<<opened;
+#endif
+}
+
+
+void QNetworkSessionPrivateImpl::configurationChanged(const QNetworkConfiguration &config)
+{
+ if (serviceConfig.isValid() && (config == serviceConfig || config == activeConfig))
+ updateStateFromServiceNetwork();
+ else if (config == activeConfig)
+ updateStateFromActiveConfig();
+}
+
+
+static QString get_network_interface()
+{
+ Maemo::Icd icd;
+ QList<Maemo::IcdAddressInfoResult> addr_results;
+ uint ret;
+ QString iface;
+
+ ret = icd.addrinfo(addr_results);
+ if (ret == 0) {
+ /* No results */
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "Cannot get addrinfo from icd, are you connected or is icd running?";
+#endif
+ return iface;
+ }
+
+ const char *address = addr_results.first().ip_info.first().address.toAscii().constData();
+ struct in_addr addr;
+ if (inet_aton(address, &addr) == 0) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "address" << address << "invalid";
+#endif
+ return iface;
+ }
+
+ struct ifaddrs *ifaddr, *ifa;
+ int family;
+
+ if (getifaddrs(&ifaddr) == -1) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "getifaddrs() failed";
+#endif
+ return iface;
+ }
+
+ for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+ family = ifa->ifa_addr->sa_family;
+ if (family != AF_INET) {
+ continue; /* Currently only IPv4 is supported by icd dbus interface */
+ }
+ if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == addr.s_addr) {
+ iface = QString(ifa->ifa_name);
+ break;
+ }
+ }
+
+ freeifaddrs(ifaddr);
+ return iface;
+}
+
+
+void QNetworkSessionPrivateImpl::open()
+{
+ if (serviceConfig.isValid()) {
+ lastError = QNetworkSession::OperationNotSupportedError;
+ emit QNetworkSessionPrivate::error(lastError);
+ } else if (!isOpen) {
+
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ /* Caller is trying to connect to default IAP.
+ * At this time we will not know the IAP details so we just
+ * connect and update the active config when the IAP is
+ * connected.
+ */
+ opened = true;
+ state = QNetworkSession::Connecting;
+ emit stateChanged(state);
+ QTimer::singleShot(0, this, SLOT(do_open()));
+ return;
+ }
+
+ /* User is connecting to one specific IAP. If that IAP is not
+ * in discovered state we cannot continue.
+ */
+ if ((activeConfig.state() & QNetworkConfiguration::Discovered) !=
+ QNetworkConfiguration::Discovered) {
+ lastError =QNetworkSession::InvalidConfigurationError;
+ emit QNetworkSessionPrivate::error(lastError);
+ return;
+ }
+ opened = true;
+
+ if ((activeConfig.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active) {
+ state = QNetworkSession::Connecting;
+ emit stateChanged(state);
+
+ QTimer::singleShot(0, this, SLOT(do_open()));
+ return;
+ }
+
+ isOpen = (activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active;
+ if (isOpen)
+ emit quitPendingWaitsForOpened();
+ } else {
+ /* We seem to be active so inform caller */
+ emit quitPendingWaitsForOpened();
+ }
+}
+
+
+void QNetworkSessionPrivateImpl::do_open()
+{
+ icd_connection_flags flags = connectFlags;
+ bool st;
+ QString result;
+ QString iap = publicConfig.identifier();
+
+ if (state == QNetworkSession::Connected) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "Already connected to" << activeConfig.identifier();
+#endif
+ emit stateChanged(QNetworkSession::Connected);
+ emit quitPendingWaitsForOpened();
+ return;
+ }
+
+ Maemo::IcdConnectResult connect_result;
+ Maemo::Icd icd(ICD_LONG_CONNECT_TIMEOUT);
+ QNetworkConfiguration config;
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice)
+ config = activeConfig;
+ else
+ config = publicConfig;
+
+ if (iap == OSSO_IAP_ANY) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "connecting to default IAP" << iap;
+#endif
+ st = icd.connect(flags, connect_result);
+
+ } else {
+
+ QList<Maemo::ConnectParams> params;
+ Maemo::ConnectParams param;
+ param.connect.service_type = toIcdConfig(privateConfiguration(config))->service_type;
+ param.connect.service_attrs = toIcdConfig(privateConfiguration(config))->service_attrs;
+ param.connect.service_id = toIcdConfig(privateConfiguration(config))->service_id;
+ param.connect.network_type = toIcdConfig(privateConfiguration(config))->iap_type;
+ param.connect.network_attrs = toIcdConfig(privateConfiguration(config))->network_attrs;
+ if (toIcdConfig(privateConfiguration(config))->network_attrs & ICD_NW_ATTR_IAPNAME)
+ param.connect.network_id = QByteArray(iap.toLatin1());
+ else
+ param.connect.network_id = toIcdConfig(privateConfiguration(config))->network_id;
+ params.append(param);
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug("connecting to %s/%s/0x%x/%s/0x%x/%s",
+ param.connect.network_id.data(),
+ param.connect.network_type.toAscii().constData(),
+ param.connect.network_attrs,
+ param.connect.service_type.toAscii().constData(),
+ param.connect.service_attrs,
+ param.connect.service_id.toAscii().constData());
+#endif
+ st = icd.connect(flags, params, connect_result);
+ }
+
+ if (st) {
+ result = connect_result.connect.network_id.data();
+ QString connected_iap = result;
+
+ if (connected_iap.isEmpty()) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "connect to"<< iap << "failed, result is empty";
+#endif
+ updateState(QNetworkSession::Disconnected);
+ emit quitPendingWaitsForOpened();
+ emit QNetworkSessionPrivate::error(QNetworkSession::InvalidConfigurationError);
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice)
+ cleanupAnyConfiguration();
+ return;
+ }
+
+ /* If the user tried to connect to some specific connection (foo)
+ * and we were already connected to some other connection (bar),
+ * then we cannot activate this session although icd has a valid
+ * connection to somewhere.
+ */
+ if ((publicConfig.type() != QNetworkConfiguration::UserChoice) &&
+ (connected_iap != config.identifier())) {
+ updateState(QNetworkSession::Disconnected);
+ emit quitPendingWaitsForOpened();
+ emit QNetworkSessionPrivate::error(QNetworkSession::InvalidConfigurationError);
+ return;
+ }
+
+
+ /* Did we connect to non saved IAP? */
+ if (!(toIcdConfig(privateConfiguration(config))->network_attrs & ICD_NW_ATTR_IAPNAME)) {
+ /* Because the connection succeeded, the IAP is now known.
+ */
+ toIcdConfig(privateConfiguration(config))->network_attrs |= ICD_NW_ATTR_IAPNAME;
+ privateConfiguration(config)->id = connected_iap;
+ }
+
+ /* User might have changed the IAP name when a new IAP was saved */
+ Maemo::IAPConf iap_name(privateConfiguration(config)->id);
+ QString name = iap_name.value("name").toString();
+ if (!name.isEmpty())
+ privateConfiguration(config)->name = name;
+
+ toIcdConfig(privateConfiguration(config))->iap_type = connect_result.connect.network_type;
+
+ privateConfiguration(config)->isValid = true;
+ privateConfiguration(config)->state = QNetworkConfiguration::Active;
+ privateConfiguration(config)->type = QNetworkConfiguration::InternetAccessPoint;
+
+ startTime = QDateTime::currentDateTime();
+ updateState(QNetworkSession::Connected);
+
+ currentNetworkInterface = get_network_interface();
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "connected to" << result << config.name() << "at" << currentNetworkInterface;
+#endif
+
+ /* We first check if the configuration already exists in the manager
+ * and if it is not found there, we then insert it. Note that this
+ * is only done for user choice config only because it can be missing
+ * from config manager list.
+ */
+
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ if (!engine->accessPointConfigurations.contains(result)) {
+ engine->addSessionConfiguration(privateConfiguration(config));
+ } else {
+ QNetworkConfigurationPrivatePointer priv =
+ engine->accessPointConfigurations.value(result);
+ QNetworkConfiguration reference;
+ setPrivateConfiguration(reference, priv);
+ copyConfig(config, reference, false);
+ config = reference;
+ activeConfig = reference;
+ engine->changedSessionConfiguration(privateConfiguration(config));
+ }
+ }
+
+ emit quitPendingWaitsForOpened();
+
+ } else {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "connect to"<< iap << "failed, status:" << connect_result.status;
+#endif
+ updateState(QNetworkSession::Disconnected);
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice)
+ cleanupAnyConfiguration();
+ emit quitPendingWaitsForOpened();
+ emit QNetworkSessionPrivate::error(QNetworkSession::UnknownSessionError);
+ }
+}
+
+
+void QNetworkSessionPrivateImpl::cleanupAnyConfiguration()
+{
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug()<<"Removing configuration created for" << activeConfig.identifier();
+#endif
+ activeConfig = publicConfig;
+}
+
+
+void QNetworkSessionPrivateImpl::close()
+{
+ if (serviceConfig.isValid()) {
+ lastError = QNetworkSession::OperationNotSupportedError;
+ emit QNetworkSessionPrivate::error(lastError);
+ } else if (isOpen) {
+ opened = false;
+ isOpen = false;
+ emit closed();
+ }
+}
+
+
+void QNetworkSessionPrivateImpl::stop()
+{
+ if (serviceConfig.isValid()) {
+ lastError = QNetworkSession::OperationNotSupportedError;
+ emit QNetworkSessionPrivate::error(lastError);
+ } else {
+ if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ state = QNetworkSession::Closing;
+ emit stateChanged(state);
+
+ Maemo::Icd icd;
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "stopping session" << publicConfig.identifier();
+#endif
+ icd.disconnect(ICD_CONNECTION_FLAG_APPLICATION_EVENT);
+ startTime = QDateTime();
+
+ /* Note that the state will go disconnected in
+ * updateStateFromActiveConfig() which gets called after
+ * configurationChanged is emitted (below).
+ */
+
+ privateConfiguration(activeConfig)->state = QNetworkConfiguration::Discovered;
+ engine->changedSessionConfiguration(privateConfiguration(activeConfig));
+
+ opened = false;
+ isOpen = false;
+
+ } else {
+ opened = false;
+ isOpen = false;
+ emit closed();
+ }
+ }
+}
+
+
+void QNetworkSessionPrivateImpl::migrate()
+{
+ qWarning("This platform does not support roaming (%s).", __FUNCTION__);
+}
+
+
+void QNetworkSessionPrivateImpl::accept()
+{
+ qWarning("This platform does not support roaming (%s).", __FUNCTION__);
+}
+
+
+void QNetworkSessionPrivateImpl::ignore()
+{
+ qWarning("This platform does not support roaming (%s).", __FUNCTION__);
+}
+
+
+void QNetworkSessionPrivateImpl::reject()
+{
+ qWarning("This platform does not support roaming (%s).", __FUNCTION__);
+}
+
+
+QNetworkInterface QNetworkSessionPrivateImpl::currentInterface() const
+{
+ if (!publicConfig.isValid() || state != QNetworkSession::Connected)
+ return QNetworkInterface();
+
+ if (currentNetworkInterface.isEmpty())
+ return QNetworkInterface();
+
+ return QNetworkInterface::interfaceFromName(currentNetworkInterface);
+}
+
+
+void QNetworkSessionPrivateImpl::setSessionProperty(const QString& key, const QVariant& value)
+{
+ if (value.isValid()) {
+ properties.insert(key, value);
+
+ if (key == "ConnectInBackground") {
+ bool v = value.toBool();
+ if (v)
+ connectFlags = ICD_CONNECTION_FLAG_APPLICATION_EVENT;
+ else
+ connectFlags = ICD_CONNECTION_FLAG_USER_EVENT;
+ }
+ } else {
+ properties.remove(key);
+
+ /* Set default value when property is removed */
+ if (key == "ConnectInBackground")
+ connectFlags = ICD_CONNECTION_FLAG_USER_EVENT;
+ }
+}
+
+
+QVariant QNetworkSessionPrivateImpl::sessionProperty(const QString& key) const
+{
+ return properties.value(key);
+}
+
+
+QString QNetworkSessionPrivateImpl::errorString() const
+{
+ QString errorStr;
+ switch(q->error()) {
+ case QNetworkSession::RoamingError:
+ errorStr = QObject::tr("Roaming error");
+ break;
+ case QNetworkSession::SessionAbortedError:
+ errorStr = QObject::tr("Session aborted by user or system");
+ break;
+ default:
+ case QNetworkSession::UnknownSessionError:
+ errorStr = QObject::tr("Unidentified Error");
+ break;
+ }
+ return errorStr;
+}
+
+
+QNetworkSession::SessionError QNetworkSessionPrivateImpl::error() const
+{
+ return QNetworkSession::UnknownSessionError;
+}
+
+#include "qnetworksession_impl.moc"
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/icd/qnetworksession_impl.h b/src/plugins/bearer/icd/qnetworksession_impl.h
new file mode 100644
index 0000000..b7461dc
--- /dev/null
+++ b/src/plugins/bearer/icd/qnetworksession_impl.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 QNETWORKSESSION_IMPL_H
+#define QNETWORKSESSION_IMPL_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/qnetworksession_p.h>
+#include <QtNetwork/qnetworkconfigmanager.h>
+
+//#include "qnetworkconfigmanager_maemo_p.h"
+//#include "qnetworksession.h"
+
+//#include <qnetworksession.h>
+//#include <QNetworkInterface>
+#include <QtCore/qdatetime.h>
+
+#include <icd/dbus_api.h>
+
+QT_BEGIN_NAMESPACE
+
+class QIcdEngine;
+
+class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate
+{
+ Q_OBJECT
+
+public:
+ QNetworkSessionPrivateImpl(QIcdEngine *engine)
+ : engine(engine), connectFlags(ICD_CONNECTION_FLAG_USER_EVENT)
+ {
+ }
+
+ ~QNetworkSessionPrivateImpl()
+ {
+ cleanupSession();
+ }
+
+ //called by QNetworkSession constructor and ensures
+ //that the state is immediately updated (w/o actually opening
+ //a session). Also this function should take care of
+ //notification hooks to discover future state changes.
+ void syncStateWithInterface();
+
+ QNetworkInterface currentInterface() const;
+ QVariant sessionProperty(const QString& key) const;
+ void setSessionProperty(const QString& key, const QVariant& value);
+
+ void open();
+ void close();
+ void stop();
+
+ void migrate();
+ void accept();
+ void ignore();
+ void reject();
+
+ QString errorString() const; //must return translated string
+ QNetworkSession::SessionError error() const;
+
+ quint64 bytesWritten() const;
+ quint64 bytesReceived() const;
+ quint64 activeTime() const;
+
+private:
+ void updateStateFromServiceNetwork();
+ void updateStateFromActiveConfig();
+
+private Q_SLOTS:
+ void do_open();
+ void networkConfigurationsChanged();
+ void configurationChanged(const QNetworkConfiguration &config);
+
+private:
+ QNetworkConfigurationManager manager;
+ QIcdEngine *engine;
+
+ QNetworkConfiguration& copyConfig(QNetworkConfiguration &fromConfig, QNetworkConfiguration &toConfig, bool deepCopy = true);
+ void clearConfiguration(QNetworkConfiguration &config);
+ void cleanupAnyConfiguration();
+
+ bool opened;
+ icd_connection_flags connectFlags;
+
+ QNetworkSession::SessionError lastError;
+
+ QDateTime startTime;
+ QString currentNetworkInterface;
+ friend class IcdListener;
+ void updateState(QNetworkSession::State);
+ void updateIdentifier(QString &newId);
+ quint64 getStatistics(bool sent) const;
+ void cleanupSession(void);
+};
+
+QT_END_NAMESPACE
+
+#endif //QNETWORKSESSIONPRIVATE_H
+
diff --git a/src/plugins/bearer/nativewifi/main.cpp b/src/plugins/bearer/nativewifi/main.cpp
new file mode 100644
index 0000000..d77462e
--- /dev/null
+++ b/src/plugins/bearer/nativewifi/main.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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/private/qbearerplugin_p.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..f277a04
--- /dev/null
+++ b/src/plugins/bearer/nativewifi/nativewifi.pro
@@ -0,0 +1,17 @@
+TARGET = qnativewifibearer
+include(../../qpluginbase.pri)
+
+QT += network
+
+HEADERS += qnativewifiengine.h \
+ platformdefs.h \
+ ../qnetworksession_impl.h \
+ ../qbearerengine_impl.h
+
+SOURCES += main.cpp \
+ qnativewifiengine.cpp \
+ ../qnetworksession_impl.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..57ae852
--- /dev/null
+++ b/src/plugins/bearer/nativewifi/platformdefs.h
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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..e4ab0aa
--- /dev/null
+++ b/src/plugins/bearer/nativewifi/qnativewifiengine.cpp
@@ -0,0 +1,481 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "../qnetworksession_impl.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:
+ ;
+ }
+}
+
+QNativeWifiEngine::QNativeWifiEngine(QObject *parent)
+: QBearerEngineImpl(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, &parameters, 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;
+}
+
+QNetworkConfigurationManager::Capabilities QNativeWifiEngine::capabilities() const
+{
+ return QNetworkConfigurationManager::ForcedRoaming |
+ QNetworkConfigurationManager::CanStartAndStopInterfaces;
+}
+
+QNetworkSessionPrivate *QNativeWifiEngine::createSessionBackend()
+{
+ return new QNetworkSessionPrivateImpl;
+}
+
+QNetworkConfigurationPrivatePointer QNativeWifiEngine::defaultConfiguration()
+{
+ return QNetworkConfigurationPrivatePointer();
+}
+
+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..a9a9375
--- /dev/null
+++ b/src/plugins/bearer/nativewifi/qnativewifiengine.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "../qbearerengine_impl.h"
+
+#include <QtCore/qtimer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkConfigurationPrivate;
+struct WLAN_NOTIFICATION_DATA;
+
+class QNativeWifiEngine : public QBearerEngineImpl
+{
+ 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);
+
+ QNetworkConfigurationManager::Capabilities capabilities() const;
+
+ QNetworkSessionPrivate *createSessionBackend();
+
+ QNetworkConfigurationPrivatePointer defaultConfiguration();
+
+ 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..6c97a22
--- /dev/null
+++ b/src/plugins/bearer/networkmanager/main.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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/private/qbearerplugin_p.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")) {
+ QNetworkManagerEngine *engine = new QNetworkManagerEngine;
+ if (engine->networkManagerAvailable())
+ return engine;
+ else
+ delete engine;
+ }
+
+ 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..bf0d29a
--- /dev/null
+++ b/src/plugins/bearer/networkmanager/networkmanager.pro
@@ -0,0 +1,20 @@
+TARGET = qnmbearer
+include(../../qpluginbase.pri)
+
+QT += network dbus
+
+HEADERS += qnmdbushelper.h \
+ qnetworkmanagerservice.h \
+ qnetworkmanagerengine.h \
+ ../qnetworksession_impl.h \
+ ../qbearerengine_impl.h
+
+SOURCES += main.cpp \
+ qnmdbushelper.cpp \
+ qnetworkmanagerservice.cpp \
+ qnetworkmanagerengine.cpp \
+ ../qnetworksession_impl.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..4c8928c
--- /dev/null
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
@@ -0,0 +1,797 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "../qnetworksession_impl.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)
+: QBearerEngineImpl(parent),
+ interface(new QNetworkManagerInterface(this)),
+ systemSettings(new QNetworkManagerSettings(NM_DBUS_SERVICE_SYSTEM_SETTINGS, this)),
+ userSettings(new QNetworkManagerSettings(NM_DBUS_SERVICE_USER_SETTINGS, this))
+{
+ if (!interface->isValid())
+ return;
+
+ 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()
+{
+}
+
+bool QNetworkManagerEngine::networkManagerAvailable() const
+{
+ return interface->isValid();
+}
+
+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;
+
+ 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)
+{
+ Q_UNUSED(path)
+
+ 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)
+{
+ Q_UNUSED(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)
+{
+}
+
+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)
+{
+ Q_UNUSED(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();
+
+ 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()) {
+ 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)
+{
+ Q_UNUSED(path)
+
+ 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.
+ if (!accessPoint->ssid().isEmpty()) {
+ 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)
+{
+ Q_UNUSED(path)
+
+ 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);
+ 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::Defined;
+ emit configurationChanged(ptr);
+ return;
+ }
+ }
+ } else {
+ QNetworkConfigurationPrivatePointer ptr =
+ accessPointConfigurations.take(QString::number(qHash(objectPath.path())));
+
+ if (ptr)
+ emit configurationRemoved(ptr);
+ }
+
+ delete accessPoint;
+
+ break;
+ }
+ }
+}
+
+void QNetworkManagerEngine::updateAccessPoint(const QMap<QString, QVariant> &map)
+{
+ Q_UNUSED(map)
+
+ QNetworkManagerInterfaceAccessPoint *accessPoint =
+ qobject_cast<QNetworkManagerInterfaceAccessPoint *>(sender());
+ if (!accessPoint)
+ return;
+
+ 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;
+ }
+ }
+}
+
+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;
+}
+
+quint64 QNetworkManagerEngine::bytesWritten(const QString &id)
+{
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+ if (ptr && (ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ const QString networkInterface = getInterfaceFromId(id);
+ if (!networkInterface.isEmpty()) {
+ const QString devFile = QLatin1String("/sys/class/net/") +
+ networkInterface +
+ QLatin1String("/statistics/tx_bytes");
+
+ quint64 result = Q_UINT64_C(0);
+
+ QFile tx(devFile);
+ if (tx.exists() && tx.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ QTextStream in(&tx);
+ in >> result;
+ tx.close();
+ }
+
+ return result;
+ }
+ }
+
+ return Q_UINT64_C(0);
+}
+
+quint64 QNetworkManagerEngine::bytesReceived(const QString &id)
+{
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+ if (ptr && (ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ const QString networkInterface = getInterfaceFromId(id);
+ if (!networkInterface.isEmpty()) {
+ const QString devFile = QLatin1String("/sys/class/net/") +
+ networkInterface +
+ QLatin1String("/statistics/rx_bytes");
+
+ quint64 result = Q_UINT64_C(0);
+
+ QFile tx(devFile);
+ if (tx.exists() && tx.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ QTextStream in(&tx);
+ in >> result;
+ tx.close();
+ }
+
+ return result;
+ }
+ }
+
+ return Q_UINT64_C(0);
+}
+
+quint64 QNetworkManagerEngine::startTime(const QString &id)
+{
+ QNetworkManagerSettingsConnection *connection = connectionFromId(id);
+ if (connection)
+ return connection->getTimestamp();
+ else
+ return Q_UINT64_C(0);
+}
+
+QNetworkConfigurationManager::Capabilities QNetworkManagerEngine::capabilities() const
+{
+ return QNetworkConfigurationManager::ForcedRoaming |
+ QNetworkConfigurationManager::CanStartAndStopInterfaces;
+}
+
+QNetworkSessionPrivate *QNetworkManagerEngine::createSessionBackend()
+{
+ return new QNetworkSessionPrivateImpl;
+}
+
+QNetworkConfigurationPrivatePointer QNetworkManagerEngine::defaultConfiguration()
+{
+ return QNetworkConfigurationPrivatePointer();
+}
+
+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..ca1f857
--- /dev/null
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "../qbearerengine_impl.h"
+
+#include "qnetworkmanagerservice.h"
+
+#include <QMap>
+#include <QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkManagerEngine : public QBearerEngineImpl
+{
+ Q_OBJECT
+
+public:
+ QNetworkManagerEngine(QObject *parent = 0);
+ ~QNetworkManagerEngine();
+
+ bool networkManagerAvailable() const;
+
+ 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);
+
+ quint64 bytesWritten(const QString &id);
+ quint64 bytesReceived(const QString &id);
+ quint64 startTime(const QString &id);
+
+ QNetworkConfigurationManager::Capabilities capabilities() const;
+
+ QNetworkSessionPrivate *createSessionBackend();
+
+ QNetworkConfigurationPrivatePointer defaultConfiguration();
+
+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..5dc0ea4
--- /dev/null
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp
@@ -0,0 +1,1046 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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()) {
+ 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 NetworkManagerInterfaceDevice";
+ 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();
+ }
+
+ 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..81903ec
--- /dev/null
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h
@@ -0,0 +1,397 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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..d5e20f3
--- /dev/null
+++ b/src/plugins/bearer/networkmanager/qnmdbushelper.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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..862290c
--- /dev/null
+++ b/src/plugins/bearer/networkmanager/qnmdbushelper.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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..479a933
--- /dev/null
+++ b/src/plugins/bearer/nla/main.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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/qbearerplugin_p.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..5148b09
--- /dev/null
+++ b/src/plugins/bearer/nla/nla.pro
@@ -0,0 +1,23 @@
+TARGET = qnlabearer
+include(../../qpluginbase.pri)
+
+QT += network
+
+!wince* {
+ LIBS += -lWs2_32
+} else {
+ LIBS += -lWs2
+}
+
+HEADERS += qnlaengine.h \
+ ../platformdefs_win.h \
+ ../qnetworksession_impl.h \
+ ../qbearerengine_impl.h
+
+SOURCES += main.cpp \
+ qnlaengine.cpp \
+ ../qnetworksession_impl.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..2001c0b
--- /dev/null
+++ b/src/plugins/bearer/nla/qnlaengine.cpp
@@ -0,0 +1,651 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "../qnetworksession_impl.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)
+ 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)
+: QBearerEngineImpl(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;
+}
+
+QNetworkConfigurationManager::Capabilities QNlaEngine::capabilities() const
+{
+ return QNetworkConfigurationManager::ForcedRoaming;
+}
+
+QNetworkSessionPrivate *QNlaEngine::createSessionBackend()
+{
+ return new QNetworkSessionPrivateImpl;
+}
+
+QNetworkConfigurationPrivatePointer QNlaEngine::defaultConfiguration()
+{
+ return QNetworkConfigurationPrivatePointer();
+}
+
+#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..14c5201
--- /dev/null
+++ b/src/plugins/bearer/nla/qnlaengine.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "../qbearerengine_impl.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 QBearerEngineImpl
+{
+ 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);
+
+ QNetworkConfigurationManager::Capabilities capabilities() const;
+
+ QNetworkSessionPrivate *createSessionBackend();
+
+ QNetworkConfigurationPrivatePointer defaultConfiguration();
+
+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..37d099c
--- /dev/null
+++ b/src/plugins/bearer/platformdefs_win.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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/bearer/qbearerengine_impl.h b/src/plugins/bearer/qbearerengine_impl.h
new file mode 100644
index 0000000..740def3
--- /dev/null
+++ b/src/plugins/bearer/qbearerengine_impl.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 QBEARERENGINE_IMPL_H
+#define QBEARERENGINE_IMPL_H
+
+#include <QtNetwork/private/qbearerengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QBearerEngineImpl : public QBearerEngine
+{
+ Q_OBJECT
+
+public:
+ enum ConnectionError {
+ InterfaceLookupError = 0,
+ ConnectError,
+ OperationNotSupported,
+ DisconnectionError,
+ };
+
+ QBearerEngineImpl(QObject *parent = 0) : QBearerEngine(parent) { }
+ ~QBearerEngineImpl() { }
+
+ virtual void connectToId(const QString &id) = 0;
+ virtual void disconnectFromId(const QString &id) = 0;
+
+ virtual QString getInterfaceFromId(const QString &id) = 0;
+
+ virtual QNetworkSession::State sessionStateForId(const QString &id) = 0;
+
+ virtual quint64 bytesWritten(const QString &) { return Q_UINT64_C(0); }
+ virtual quint64 bytesReceived(const QString &) { return Q_UINT64_C(0); }
+ virtual quint64 startTime(const QString &) { return Q_UINT64_C(0); }
+
+Q_SIGNALS:
+ void connectionError(const QString &id, QBearerEngineImpl::ConnectionError error);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/bearer/qnetworksession_impl.cpp b/src/plugins/bearer/qnetworksession_impl.cpp
new file mode 100644
index 0000000..3fe844a
--- /dev/null
+++ b/src/plugins/bearer/qnetworksession_impl.cpp
@@ -0,0 +1,408 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "qnetworksession_impl.h"
+#include "qbearerengine_impl.h"
+
+#include <QtNetwork/qnetworksession.h>
+#include <QtNetwork/private/qnetworkconfigmanager_p.h>
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qmutex.h>
+
+#include <QtNetwork/qnetworkinterface.h>
+
+QT_BEGIN_NAMESPACE
+
+static QBearerEngineImpl *getEngineFromId(const QString &id)
+{
+ QNetworkConfigurationManagerPrivate *priv = qNetworkConfigurationManagerPrivate();
+
+ foreach (QBearerEngine *engine, priv->sessionEngines) {
+ QBearerEngineImpl *engineImpl = qobject_cast<QBearerEngineImpl *>(engine);
+ if (engineImpl && engineImpl->hasIdentifier(id))
+ return engineImpl;
+ }
+
+ return 0;
+}
+
+class QNetworkSessionManagerPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ QNetworkSessionManagerPrivate(QObject *parent = 0);
+ ~QNetworkSessionManagerPrivate();
+
+ void forceSessionClose(const QNetworkConfiguration &config);
+
+Q_SIGNALS:
+ void forcedSessionClose(const QNetworkConfiguration &config);
+};
+
+#include "qnetworksession_impl.moc"
+
+Q_GLOBAL_STATIC(QNetworkSessionManagerPrivate, sessionManager);
+
+QNetworkSessionManagerPrivate::QNetworkSessionManagerPrivate(QObject *parent)
+: QObject(parent)
+{
+}
+
+QNetworkSessionManagerPrivate::~QNetworkSessionManagerPrivate()
+{
+}
+
+void QNetworkSessionManagerPrivate::forceSessionClose(const QNetworkConfiguration &config)
+{
+ emit forcedSessionClose(config);
+}
+
+void QNetworkSessionPrivateImpl::syncStateWithInterface()
+{
+ connect(&manager, SIGNAL(updateCompleted()), this, SLOT(networkConfigurationsChanged()));
+ connect(&manager, SIGNAL(configurationChanged(QNetworkConfiguration)),
+ this, SLOT(configurationChanged(QNetworkConfiguration)));
+ connect(sessionManager(), SIGNAL(forcedSessionClose(QNetworkConfiguration)),
+ this, SLOT(forcedSessionClose(QNetworkConfiguration)));
+
+ opened = false;
+ isOpen = false;
+ state = QNetworkSession::Invalid;
+ lastError = QNetworkSession::UnknownSessionError;
+
+ qRegisterMetaType<QBearerEngineImpl::ConnectionError>
+ ("QBearerEngineImpl::ConnectionError");
+
+ switch (publicConfig.type()) {
+ case QNetworkConfiguration::InternetAccessPoint:
+ activeConfig = publicConfig;
+ engine = getEngineFromId(activeConfig.identifier());
+ if (engine) {
+ connect(engine, SIGNAL(connectionError(QString,QBearerEngineImpl::ConnectionError)),
+ this, SLOT(connectionError(QString,QBearerEngineImpl::ConnectionError)),
+ Qt::QueuedConnection);
+ }
+ break;
+ case QNetworkConfiguration::ServiceNetwork:
+ serviceConfig = publicConfig;
+ // Defer setting engine and signals until open().
+ // fall through
+ case QNetworkConfiguration::UserChoice:
+ // Defer setting serviceConfig and activeConfig until open().
+ // fall through
+ default:
+ engine = 0;
+ }
+
+ networkConfigurationsChanged();
+}
+
+void QNetworkSessionPrivateImpl::open()
+{
+ if (serviceConfig.isValid()) {
+ lastError = QNetworkSession::OperationNotSupportedError;
+ emit QNetworkSessionPrivate::error(lastError);
+ } else if (!isOpen) {
+ if ((activeConfig.state() & QNetworkConfiguration::Discovered) !=
+ QNetworkConfiguration::Discovered) {
+ lastError =QNetworkSession::InvalidConfigurationError;
+ emit QNetworkSessionPrivate::error(lastError);
+ return;
+ }
+ opened = true;
+
+ if ((activeConfig.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active &&
+ (activeConfig.state() & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) {
+ state = QNetworkSession::Connecting;
+ emit stateChanged(state);
+
+ engine->connectToId(activeConfig.identifier());
+ }
+
+ isOpen = (activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active;
+ if (isOpen)
+ emit quitPendingWaitsForOpened();
+ }
+}
+
+void QNetworkSessionPrivateImpl::close()
+{
+ if (serviceConfig.isValid()) {
+ lastError = QNetworkSession::OperationNotSupportedError;
+ emit QNetworkSessionPrivate::error(lastError);
+ } else if (isOpen) {
+ opened = false;
+ isOpen = false;
+ emit closed();
+ }
+}
+
+void QNetworkSessionPrivateImpl::stop()
+{
+ if (serviceConfig.isValid()) {
+ lastError = QNetworkSession::OperationNotSupportedError;
+ emit QNetworkSessionPrivate::error(lastError);
+ } else {
+ if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ state = QNetworkSession::Closing;
+ emit stateChanged(state);
+
+ engine->disconnectFromId(activeConfig.identifier());
+
+ sessionManager()->forceSessionClose(activeConfig);
+ }
+
+ opened = false;
+ isOpen = false;
+ emit closed();
+ }
+}
+
+void QNetworkSessionPrivateImpl::migrate()
+{
+ qWarning("This platform does not support roaming (%s).", __FUNCTION__);
+}
+
+void QNetworkSessionPrivateImpl::accept()
+{
+ qWarning("This platform does not support roaming (%s).", __FUNCTION__);
+}
+
+void QNetworkSessionPrivateImpl::ignore()
+{
+ qWarning("This platform does not support roaming (%s).", __FUNCTION__);
+}
+
+void QNetworkSessionPrivateImpl::reject()
+{
+ qWarning("This platform does not support roaming (%s).", __FUNCTION__);
+}
+
+QNetworkInterface QNetworkSessionPrivateImpl::currentInterface() const
+{
+ if (!publicConfig.isValid() || !engine || state != QNetworkSession::Connected)
+ return QNetworkInterface();
+
+ QString interface = engine->getInterfaceFromId(activeConfig.identifier());
+
+ if (interface.isEmpty())
+ return QNetworkInterface();
+ return QNetworkInterface::interfaceFromName(interface);
+}
+
+QVariant QNetworkSessionPrivateImpl::sessionProperty(const QString& /*key*/) const
+{
+ return QVariant();
+}
+
+void QNetworkSessionPrivateImpl::setSessionProperty(const QString& /*key*/, const QVariant& /*value*/)
+{
+}
+
+QString QNetworkSessionPrivateImpl::errorString() const
+{
+ switch (lastError) {
+ case QNetworkSession::UnknownSessionError:
+ return tr("Unknown session error.");
+ case QNetworkSession::SessionAbortedError:
+ return tr("The session was aborted by the user or system.");
+ case QNetworkSession::OperationNotSupportedError:
+ return tr("The requested operation is not supported by the system.");
+ case QNetworkSession::InvalidConfigurationError:
+ return tr("The specified configuration cannot be used.");
+ case QNetworkSession::RoamingError:
+ return tr("Roaming was aborted or is not possible.");
+
+ }
+
+ return QString();
+}
+
+QNetworkSession::SessionError QNetworkSessionPrivateImpl::error() const
+{
+ return lastError;
+}
+
+quint64 QNetworkSessionPrivateImpl::bytesWritten() const
+{
+ if (engine && state == QNetworkSession::Connected)
+ return engine->bytesWritten(activeConfig.identifier());
+ else
+ return Q_UINT64_C(0);
+}
+
+quint64 QNetworkSessionPrivateImpl::bytesReceived() const
+{
+ if (engine && state == QNetworkSession::Connected)
+ return engine->bytesReceived(activeConfig.identifier());
+ else
+ return Q_UINT64_C(0);
+}
+
+quint64 QNetworkSessionPrivateImpl::activeTime() const
+{
+ if (state == QNetworkSession::Connected && startTime != Q_UINT64_C(0))
+ return QDateTime::currentDateTime().toTime_t() - startTime;
+ else
+ return Q_UINT64_C(0);
+}
+
+void QNetworkSessionPrivateImpl::updateStateFromServiceNetwork()
+{
+ QNetworkSession::State oldState = state;
+
+ foreach (const QNetworkConfiguration &config, serviceConfig.children()) {
+ if ((config.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active)
+ continue;
+
+ if (activeConfig != config) {
+ if (engine) {
+ disconnect(engine,
+ SIGNAL(connectionError(QString,QBearerEngineImpl::ConnectionError)),
+ this,
+ SLOT(connectionError(QString,QBearerEngineImpl::ConnectionError)));
+ }
+
+ activeConfig = config;
+ engine = getEngineFromId(activeConfig.identifier());
+ if (engine) {
+ connect(engine,
+ SIGNAL(connectionError(QString,QBearerEngineImpl::ConnectionError)),
+ this, SLOT(connectionError(QString,QBearerEngineImpl::ConnectionError)),
+ Qt::QueuedConnection);
+ }
+ emit newConfigurationActivated();
+ }
+
+ state = QNetworkSession::Connected;
+ if (state != oldState)
+ emit stateChanged(state);
+
+ return;
+ }
+
+ if (serviceConfig.children().isEmpty())
+ state = QNetworkSession::NotAvailable;
+ else
+ state = QNetworkSession::Disconnected;
+
+ if (state != oldState)
+ emit stateChanged(state);
+}
+
+void QNetworkSessionPrivateImpl::updateStateFromActiveConfig()
+{
+ if (!engine)
+ return;
+
+ QNetworkSession::State oldState = state;
+
+ state = engine->sessionStateForId(activeConfig.identifier());
+
+ bool oldActive = isOpen;
+ isOpen = (state == QNetworkSession::Connected) ? opened : false;
+
+ if (!oldActive && isOpen)
+ emit quitPendingWaitsForOpened();
+ if (oldActive && !isOpen)
+ emit closed();
+
+ if (oldState != state)
+ emit stateChanged(state);
+}
+
+void QNetworkSessionPrivateImpl::networkConfigurationsChanged()
+{
+ if (serviceConfig.isValid())
+ updateStateFromServiceNetwork();
+ else
+ updateStateFromActiveConfig();
+
+ startTime = engine->startTime(activeConfig.identifier());
+}
+
+void QNetworkSessionPrivateImpl::configurationChanged(const QNetworkConfiguration &config)
+{
+ if (serviceConfig.isValid() && (config == serviceConfig || config == activeConfig))
+ updateStateFromServiceNetwork();
+ else if (config == activeConfig)
+ updateStateFromActiveConfig();
+}
+
+void QNetworkSessionPrivateImpl::forcedSessionClose(const QNetworkConfiguration &config)
+{
+ if (activeConfig == config) {
+ opened = false;
+ isOpen = false;
+
+ emit closed();
+
+ lastError = QNetworkSession::SessionAbortedError;
+ emit QNetworkSessionPrivate::error(lastError);
+ }
+}
+
+void QNetworkSessionPrivateImpl::connectionError(const QString &id,
+ QBearerEngineImpl::ConnectionError error)
+{
+ if (activeConfig.identifier() == id) {
+ networkConfigurationsChanged();
+ switch (error) {
+ case QBearerEngineImpl::OperationNotSupported:
+ lastError = QNetworkSession::OperationNotSupportedError;
+ opened = false;
+ break;
+ case QBearerEngineImpl::InterfaceLookupError:
+ case QBearerEngineImpl::ConnectError:
+ case QBearerEngineImpl::DisconnectionError:
+ default:
+ lastError = QNetworkSession::UnknownSessionError;
+ }
+
+ emit quitPendingWaitsForOpened();
+ emit QNetworkSessionPrivate::error(lastError);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/qnetworksession_impl.h b/src/plugins/bearer/qnetworksession_impl.h
new file mode 100644
index 0000000..7349e77
--- /dev/null
+++ b/src/plugins/bearer/qnetworksession_impl.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 QNETWORKSESSION_IMPL_H
+#define QNETWORKSESSION_IMPL_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 "qbearerengine_impl.h"
+
+#include <QtNetwork/private/qnetworkconfigmanager_p.h>
+#include <QtNetwork/private/qnetworksession_p.h>
+
+#include <QtCore/qdatetime.h>
+
+QT_BEGIN_NAMESPACE
+
+class QBearerEngineImpl;
+
+class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate
+{
+ Q_OBJECT
+public:
+ QNetworkSessionPrivateImpl()
+ : startTime(0)
+ {
+ }
+
+ ~QNetworkSessionPrivateImpl()
+ {
+ }
+
+ //called by QNetworkSession constructor and ensures
+ //that the state is immediately updated (w/o actually opening
+ //a session). Also this function should take care of
+ //notification hooks to discover future state changes.
+ void syncStateWithInterface();
+
+ QNetworkInterface currentInterface() const;
+ QVariant sessionProperty(const QString& key) const;
+ void setSessionProperty(const QString& key, const QVariant& value);
+
+ void open();
+ void close();
+ void stop();
+ void migrate();
+ void accept();
+ void ignore();
+ void reject();
+
+ QString errorString() const; //must return translated string
+ QNetworkSession::SessionError error() const;
+
+ quint64 bytesWritten() const;
+ quint64 bytesReceived() const;
+ quint64 activeTime() const;
+
+private:
+ void updateStateFromServiceNetwork();
+ void updateStateFromActiveConfig();
+
+private Q_SLOTS:
+ void networkConfigurationsChanged();
+ void configurationChanged(const QNetworkConfiguration &config);
+ void forcedSessionClose(const QNetworkConfiguration &config);
+ void connectionError(const QString &id, QBearerEngineImpl::ConnectionError error);
+
+private:
+ QNetworkConfigurationManager manager;
+
+ bool opened;
+
+ QBearerEngineImpl *engine;
+
+ QNetworkSession::SessionError lastError;
+
+ quint64 startTime;
+};
+
+QT_END_NAMESPACE
+
+#endif //QNETWORKSESSION_IMPL_H
+
diff --git a/src/plugins/bearer/symbian/main.cpp b/src/plugins/bearer/symbian/main.cpp
new file mode 100644
index 0000000..0321451
--- /dev/null
+++ b/src/plugins/bearer/symbian/main.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "symbianengine.h"
+
+#include <QtNetwork/private/qbearerplugin_p.h>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSymbianEnginePlugin : public QBearerEnginePlugin
+{
+public:
+ QSymbianEnginePlugin();
+ ~QSymbianEnginePlugin();
+
+ QStringList keys() const;
+ QBearerEngine *create(const QString &key) const;
+};
+
+QSymbianEnginePlugin::QSymbianEnginePlugin()
+{
+}
+
+QSymbianEnginePlugin::~QSymbianEnginePlugin()
+{
+}
+
+QStringList QSymbianEnginePlugin::keys() const
+{
+ return QStringList() << QLatin1String("symbian");
+}
+
+QBearerEngine *QSymbianEnginePlugin::create(const QString &key) const
+{
+ if (key == QLatin1String("symbian"))
+ return new SymbianEngine;
+ else
+ return 0;
+}
+
+Q_EXPORT_STATIC_PLUGIN(QSymbianEnginePlugin)
+Q_EXPORT_PLUGIN2(qsymbianbearer, QSymbianEnginePlugin)
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp
new file mode 100644
index 0000000..7762fb5
--- /dev/null
+++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp
@@ -0,0 +1,1135 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "qnetworksession_impl.h"
+#include "symbianengine.h"
+
+#include <es_enum.h>
+#include <es_sock.h>
+#include <in_sock.h>
+#include <stdapis/sys/socket.h>
+#include <stdapis/net/if.h>
+
+QT_BEGIN_NAMESPACE
+
+QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine)
+ : CActive(CActive::EPriorityStandard), engine(engine), ipConnectionNotifier(0),
+ iError(QNetworkSession::UnknownSessionError),
+ iALREnabled(0)
+{
+ CActiveScheduler::Add(this);
+
+ // Try to load "Open C" dll dynamically and
+ // try to attach to setdefaultif function dynamically.
+ if (iOpenCLibrary.Load(_L("libc")) == KErrNone) {
+ iDynamicSetdefaultif = (TOpenCSetdefaultifFunction)iOpenCLibrary.Lookup(564);
+ }
+
+ TRAP_IGNORE(iConnectionMonitor.ConnectL());
+}
+
+QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl()
+{
+ isOpen = false;
+
+ // Cancel Connection Progress Notifications first.
+ // Note: ConnectionNotifier must be destroyed before Canceling RConnection::Start()
+ // => deleting ipConnectionNotifier results RConnection::CancelProgressNotification()
+ delete ipConnectionNotifier;
+ ipConnectionNotifier = NULL;
+
+ // Cancel possible RConnection::Start()
+ Cancel();
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (iMobility) {
+ delete iMobility;
+ iMobility = NULL;
+ }
+#endif
+
+ iConnection.Close();
+ iSocketServ.Close();
+ if (iDynamicSetdefaultif) {
+ iDynamicSetdefaultif(0);
+ }
+
+ iConnectionMonitor.CancelNotifications();
+ iConnectionMonitor.Close();
+
+ iOpenCLibrary.Close();
+}
+
+void QNetworkSessionPrivateImpl::syncStateWithInterface()
+{
+ if (!privateConfiguration(publicConfig))
+ return;
+
+ // Start monitoring changes in IAP states
+ TRAP_IGNORE(iConnectionMonitor.NotifyEventL(*this));
+
+ // Check open connections to see if there is already
+ // an open connection to selected IAP or SNAP
+ TUint count;
+ TRequestStatus status;
+ iConnectionMonitor.GetConnectionCount(count, status);
+ User::WaitForRequest(status);
+ if (status.Int() != KErrNone) {
+ return;
+ }
+
+ TUint numSubConnections;
+ TUint connectionId;
+ for (TUint i = 1; i <= count; i++) {
+ TInt ret = iConnectionMonitor.GetConnectionInfo(i, connectionId, numSubConnections);
+ if (ret == KErrNone) {
+ TUint apId;
+ iConnectionMonitor.GetUintAttribute(connectionId, 0, KIAPId, apId, status);
+ User::WaitForRequest(status);
+ if (status.Int() == KErrNone) {
+ TInt connectionStatus;
+ iConnectionMonitor.GetIntAttribute(connectionId, 0, KConnectionStatus, connectionStatus, status);
+ User::WaitForRequest(status);
+ if (connectionStatus == KLinkLayerOpen) {
+ if (state != QNetworkSession::Closing) {
+ if (newState(QNetworkSession::Connected, apId)) {
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (state != QNetworkSession::Connected) {
+ // There were no open connections to used IAP or SNAP
+ if ((privateConfiguration(publicConfig)->state & QNetworkConfiguration::Discovered) ==
+ QNetworkConfiguration::Discovered) {
+ newState(QNetworkSession::Disconnected);
+ } else {
+ newState(QNetworkSession::NotAvailable);
+ }
+ }
+}
+
+QNetworkInterface QNetworkSessionPrivateImpl::interface(TUint iapId) const
+{
+ QString interfaceName;
+
+ TSoInetInterfaceInfo ifinfo;
+ TPckg<TSoInetInterfaceInfo> ifinfopkg(ifinfo);
+ TSoInetIfQuery ifquery;
+ TPckg<TSoInetIfQuery> ifquerypkg(ifquery);
+
+ // Open dummy socket for interface queries
+ RSocket socket;
+ TInt retVal = socket.Open(iSocketServ, _L("udp"));
+ if (retVal != KErrNone) {
+ return QNetworkInterface();
+ }
+
+ // Start enumerating interfaces
+ socket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl);
+ while(socket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, ifinfopkg) == KErrNone) {
+ ifquery.iName = ifinfo.iName;
+ TInt err = socket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, ifquerypkg);
+ if(err == KErrNone && ifquery.iZone[1] == iapId) { // IAP ID is index 1 of iZone
+ if(ifinfo.iAddress.Address() > 0) {
+ interfaceName = QString::fromUtf16(ifinfo.iName.Ptr(),ifinfo.iName.Length());
+ break;
+ }
+ }
+ }
+
+ socket.Close();
+
+ if (interfaceName.isEmpty()) {
+ return QNetworkInterface();
+ }
+
+ return QNetworkInterface::interfaceFromName(interfaceName);
+}
+
+QNetworkInterface QNetworkSessionPrivateImpl::currentInterface() const
+{
+ if (!publicConfig.isValid() || state != QNetworkSession::Connected) {
+ return QNetworkInterface();
+ }
+
+ return activeInterface;
+}
+
+QVariant QNetworkSessionPrivateImpl::sessionProperty(const QString& /*key*/) const
+{
+ return QVariant();
+}
+
+void QNetworkSessionPrivateImpl::setSessionProperty(const QString& /*key*/, const QVariant& /*value*/)
+{
+}
+
+QString QNetworkSessionPrivateImpl::errorString() const
+{
+ switch (iError) {
+ case QNetworkSession::UnknownSessionError:
+ return tr("Unknown session error.");
+ case QNetworkSession::SessionAbortedError:
+ return tr("The session was aborted by the user or system.");
+ case QNetworkSession::OperationNotSupportedError:
+ return tr("The requested operation is not supported by the system.");
+ case QNetworkSession::InvalidConfigurationError:
+ return tr("The specified configuration cannot be used.");
+ case QNetworkSession::RoamingError:
+ return tr("Roaming was aborted or is not possible.");
+ }
+
+ return QString();
+}
+
+QNetworkSession::SessionError QNetworkSessionPrivateImpl::error() const
+{
+ return iError;
+}
+
+void QNetworkSessionPrivateImpl::open()
+{
+ if (isOpen || !privateConfiguration(publicConfig) || (state == QNetworkSession::Connecting)) {
+ return;
+ }
+
+ // Cancel notifications from RConnectionMonitor
+ // => RConnection::ProgressNotification will be used for IAP/SNAP monitoring
+ iConnectionMonitor.CancelNotifications();
+
+ TInt error = iSocketServ.Connect();
+ if (error != KErrNone) {
+ // Could not open RSocketServ
+ newState(QNetworkSession::Invalid);
+ iError = QNetworkSession::UnknownSessionError;
+ emit QNetworkSessionPrivate::error(iError);
+ syncStateWithInterface();
+ return;
+ }
+
+ error = iConnection.Open(iSocketServ);
+ if (error != KErrNone) {
+ // Could not open RConnection
+ iSocketServ.Close();
+ newState(QNetworkSession::Invalid);
+ iError = QNetworkSession::UnknownSessionError;
+ emit QNetworkSessionPrivate::error(iError);
+ syncStateWithInterface();
+ return;
+ }
+
+ // Use RConnection::ProgressNotification for IAP/SNAP monitoring
+ // (<=> ConnectionProgressNotifier uses RConnection::ProgressNotification)
+ if (!ipConnectionNotifier) {
+ ipConnectionNotifier = new ConnectionProgressNotifier(*this,iConnection);
+ }
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StartNotifications();
+ }
+
+ if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
+ // Search through existing connections.
+ // If there is already connection which matches to given IAP
+ // try to attach to existing connection.
+ TBool connected(EFalse);
+ TConnectionInfoBuf connInfo;
+ TUint count;
+ if (iConnection.EnumerateConnections(count) == KErrNone) {
+ for (TUint i=1; i<=count; i++) {
+ // Note: GetConnectionInfo expects 1-based index.
+ if (iConnection.GetConnectionInfo(i, connInfo) == KErrNone) {
+ if (connInfo().iIapId == toSymbianConfig(privateConfiguration(publicConfig))->numericId) {
+ if (iConnection.Attach(connInfo, RConnection::EAttachTypeNormal) == KErrNone) {
+ activeConfig = publicConfig;
+ activeInterface = interface(toSymbianConfig(privateConfiguration(activeConfig))->numericId);
+ connected = ETrue;
+ startTime = QDateTime::currentDateTime();
+ if (iDynamicSetdefaultif) {
+ // Use name of the IAP to set default IAP
+ QByteArray nameAsByteArray = publicConfig.name().toUtf8();
+ ifreq ifr;
+ strcpy(ifr.ifr_name, nameAsByteArray.constData());
+
+ error = iDynamicSetdefaultif(&ifr);
+ }
+ isOpen = true;
+ // Make sure that state will be Connected
+ newState(QNetworkSession::Connected);
+ emit quitPendingWaitsForOpened();
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (!connected) {
+ TCommDbConnPref pref;
+ pref.SetDialogPreference(ECommDbDialogPrefDoNotPrompt);
+ pref.SetIapId(toSymbianConfig(privateConfiguration(publicConfig))->numericId);
+ iConnection.Start(pref, iStatus);
+ if (!IsActive()) {
+ SetActive();
+ }
+ newState(QNetworkSession::Connecting);
+ }
+ } else if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
+ TConnSnapPref snapPref(toSymbianConfig(privateConfiguration(publicConfig))->numericId);
+ iConnection.Start(snapPref, iStatus);
+ if (!IsActive()) {
+ SetActive();
+ }
+ newState(QNetworkSession::Connecting);
+ } else if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ iKnownConfigsBeforeConnectionStart = engine->accessPointConfigurations.keys();
+ iConnection.Start(iStatus);
+ if (!IsActive()) {
+ SetActive();
+ }
+ newState(QNetworkSession::Connecting);
+ }
+
+ if (error != KErrNone) {
+ isOpen = false;
+ iError = QNetworkSession::UnknownSessionError;
+ emit QNetworkSessionPrivate::error(iError);
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StopNotifications();
+ }
+ syncStateWithInterface();
+ }
+}
+
+TUint QNetworkSessionPrivateImpl::iapClientCount(TUint aIAPId) const
+{
+ TRequestStatus status;
+ TUint connectionCount;
+ iConnectionMonitor.GetConnectionCount(connectionCount, status);
+ User::WaitForRequest(status);
+ if (status.Int() == KErrNone) {
+ for (TUint i = 1; i <= connectionCount; i++) {
+ TUint connectionId;
+ TUint subConnectionCount;
+ iConnectionMonitor.GetConnectionInfo(i, connectionId, subConnectionCount);
+ TUint apId;
+ iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
+ User::WaitForRequest(status);
+ if (apId == aIAPId) {
+ TConnMonClientEnumBuf buf;
+ iConnectionMonitor.GetPckgAttribute(connectionId, 0, KClientInfo, buf, status);
+ User::WaitForRequest(status);
+ if (status.Int() == KErrNone) {
+ return buf().iCount;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+void QNetworkSessionPrivateImpl::close(bool allowSignals)
+{
+ if (!isOpen) {
+ return;
+ }
+
+ TUint activeIap = toSymbianConfig(privateConfiguration(activeConfig))->numericId;
+ isOpen = false;
+ activeConfig = QNetworkConfiguration();
+ serviceConfig = QNetworkConfiguration();
+
+ Cancel();
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (iMobility) {
+ delete iMobility;
+ iMobility = NULL;
+ }
+#endif
+
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StopNotifications();
+ }
+
+ iConnection.Close();
+ iSocketServ.Close();
+ if (iDynamicSetdefaultif) {
+ iDynamicSetdefaultif(0);
+ }
+
+#ifdef Q_CC_NOKIAX86
+ if ((allowSignals && iapClientCount(activeIap) <= 0) ||
+#else
+ if ((allowSignals && iapClientCount(activeIap) <= 1) ||
+#endif
+ (publicConfig.type() == QNetworkConfiguration::UserChoice)) {
+ newState(QNetworkSession::Closing);
+ }
+
+ syncStateWithInterface();
+ if (allowSignals) {
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ newState(QNetworkSession::Disconnected);
+ }
+ emit closed();
+ }
+}
+
+void QNetworkSessionPrivateImpl::stop()
+{
+ if (!isOpen) {
+ return;
+ }
+ isOpen = false;
+ newState(QNetworkSession::Closing);
+ iConnection.Stop(RConnection::EStopAuthoritative);
+ isOpen = true;
+ close(false);
+ emit closed();
+}
+
+void QNetworkSessionPrivateImpl::migrate()
+{
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ iMobility->MigrateToPreferredCarrier();
+#endif
+}
+
+void QNetworkSessionPrivateImpl::ignore()
+{
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ iMobility->IgnorePreferredCarrier();
+ if (!iALRUpgradingConnection) {
+ newState(QNetworkSession::Disconnected);
+ } else {
+ newState(QNetworkSession::Connected,iOldRoamingIap);
+ }
+#endif
+}
+
+void QNetworkSessionPrivateImpl::accept()
+{
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ iMobility->NewCarrierAccepted();
+ if (iDynamicSetdefaultif) {
+ // Use name of the IAP to set default IAP
+ QByteArray nameAsByteArray = activeConfig.name().toUtf8();
+ ifreq ifr;
+ strcpy(ifr.ifr_name, nameAsByteArray.constData());
+
+ iDynamicSetdefaultif(&ifr);
+ }
+ newState(QNetworkSession::Connected, iNewRoamingIap);
+#endif
+}
+
+void QNetworkSessionPrivateImpl::reject()
+{
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ iMobility->NewCarrierRejected();
+ if (!iALRUpgradingConnection) {
+ newState(QNetworkSession::Disconnected);
+ } else {
+ newState(QNetworkSession::Connected, iOldRoamingIap);
+ }
+#endif
+}
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+void QNetworkSessionPrivateImpl::PreferredCarrierAvailable(TAccessPointInfo aOldAPInfo,
+ TAccessPointInfo aNewAPInfo,
+ TBool aIsUpgrade,
+ TBool aIsSeamless)
+{
+ iOldRoamingIap = aOldAPInfo.AccessPoint();
+ iNewRoamingIap = aNewAPInfo.AccessPoint();
+ newState(QNetworkSession::Roaming);
+ if (iALREnabled > 0) {
+ iALRUpgradingConnection = aIsUpgrade;
+ QList<QNetworkConfiguration> configs = publicConfig.children();
+ for (int i=0; i < configs.count(); i++) {
+ if (toSymbianConfig(privateConfiguration(configs[i]))->numericId == aNewAPInfo.AccessPoint()) {
+ emit preferredConfigurationChanged(configs[i], aIsSeamless);
+ }
+ }
+ } else {
+ migrate();
+ }
+}
+
+void QNetworkSessionPrivateImpl::NewCarrierActive(TAccessPointInfo /*aNewAPInfo*/, TBool /*aIsSeamless*/)
+{
+ if (iALREnabled > 0) {
+ emit newConfigurationActivated();
+ } else {
+ accept();
+ }
+}
+
+void QNetworkSessionPrivateImpl::Error(TInt /*aError*/)
+{
+ if (isOpen) {
+ isOpen = false;
+ activeConfig = QNetworkConfiguration();
+ serviceConfig = QNetworkConfiguration();
+ iError = QNetworkSession::RoamingError;
+ emit QNetworkSessionPrivate::error(iError);
+ Cancel();
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StopNotifications();
+ }
+ syncStateWithInterface();
+ // In some cases IAP is still in Connected state when
+ // syncStateWithInterface(); is called
+ // => Following call makes sure that Session state
+ // changes immediately to Disconnected.
+ newState(QNetworkSession::Disconnected);
+ emit closed();
+ }
+}
+#endif
+
+void QNetworkSessionPrivateImpl::setALREnabled(bool enabled)
+{
+ if (enabled) {
+ iALREnabled++;
+ } else {
+ iALREnabled--;
+ }
+}
+
+QNetworkConfiguration QNetworkSessionPrivateImpl::bestConfigFromSNAP(const QNetworkConfiguration& snapConfig) const
+{
+ QNetworkConfiguration config;
+ QList<QNetworkConfiguration> subConfigurations = snapConfig.children();
+ for (int i = 0; i < subConfigurations.count(); i++ ) {
+ if (subConfigurations[i].state() == QNetworkConfiguration::Active) {
+ config = subConfigurations[i];
+ break;
+ } else if (!config.isValid() && subConfigurations[i].state() == QNetworkConfiguration::Discovered) {
+ config = subConfigurations[i];
+ }
+ }
+ if (!config.isValid() && subConfigurations.count() > 0) {
+ config = subConfigurations[0];
+ }
+ return config;
+}
+
+quint64 QNetworkSessionPrivateImpl::bytesWritten() const
+{
+ return transferredData(KUplinkData);
+}
+
+quint64 QNetworkSessionPrivateImpl::bytesReceived() const
+{
+ return transferredData(KDownlinkData);
+}
+
+quint64 QNetworkSessionPrivateImpl::transferredData(TUint dataType) const
+{
+ if (!publicConfig.isValid()) {
+ return 0;
+ }
+
+ QNetworkConfiguration config;
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ if (serviceConfig.isValid()) {
+ config = serviceConfig;
+ } else {
+ if (activeConfig.isValid()) {
+ config = activeConfig;
+ }
+ }
+ } else {
+ config = publicConfig;
+ }
+
+ if (!config.isValid()) {
+ return 0;
+ }
+
+ TUint count;
+ TRequestStatus status;
+ iConnectionMonitor.GetConnectionCount(count, status);
+ User::WaitForRequest(status);
+ if (status.Int() != KErrNone) {
+ return 0;
+ }
+
+ TUint transferredData = 0;
+ TUint numSubConnections;
+ TUint connectionId;
+ bool configFound;
+ for (TUint i = 1; i <= count; i++) {
+ TInt ret = iConnectionMonitor.GetConnectionInfo(i, connectionId, numSubConnections);
+ if (ret == KErrNone) {
+ TUint apId;
+ iConnectionMonitor.GetUintAttribute(connectionId, 0, KIAPId, apId, status);
+ User::WaitForRequest(status);
+ if (status.Int() == KErrNone) {
+ configFound = false;
+ if (config.type() == QNetworkConfiguration::ServiceNetwork) {
+ QList<QNetworkConfiguration> configs = config.children();
+ for (int i=0; i < configs.count(); i++) {
+ if (toSymbianConfig(privateConfiguration(configs[i]))->numericId == apId) {
+ configFound = true;
+ break;
+ }
+ }
+ } else if (toSymbianConfig(privateConfiguration(config))->numericId == apId) {
+ configFound = true;
+ }
+ if (configFound) {
+ TUint tData;
+ iConnectionMonitor.GetUintAttribute(connectionId, 0, dataType, tData, status );
+ User::WaitForRequest(status);
+ if (status.Int() == KErrNone) {
+ transferredData += tData;
+ }
+ }
+ }
+ }
+ }
+
+ return transferredData;
+}
+
+quint64 QNetworkSessionPrivateImpl::activeTime() const
+{
+ if (!isOpen || startTime.isNull()) {
+ return 0;
+ }
+ return startTime.secsTo(QDateTime::currentDateTime());
+}
+
+QNetworkConfiguration QNetworkSessionPrivateImpl::activeConfiguration(TUint32 iapId) const
+{
+ if (iapId == 0) {
+ _LIT(KSetting, "IAP\\Id");
+ iConnection.GetIntSetting(KSetting, iapId);
+ }
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
+ // Try to search IAP from the used SNAP using IAP Id
+ QList<QNetworkConfiguration> children = publicConfig.children();
+ for (int i=0; i < children.count(); i++) {
+ if (toSymbianConfig(privateConfiguration(children[i]))->numericId == iapId) {
+ return children[i];
+ }
+ }
+
+ // Given IAP Id was not found from the used SNAP
+ // => Try to search matching IAP using mappingName
+ // mappingName contains:
+ // 1. "Access point name" for "Packet data" Bearer
+ // 2. "WLAN network name" (= SSID) for "Wireless LAN" Bearer
+ // 3. "Dial-up number" for "Data call Bearer" or "High Speed (GSM)" Bearer
+ // <=> Note: It's possible that in this case reported IAP is
+ // clone of the one of the IAPs of the used SNAP
+ // => If mappingName matches, clone has been found
+ QNetworkConfiguration pt = QNetworkConfigurationManager().configurationFromIdentifier(QString::number(qHash(iapId)));
+ if (privateConfiguration(pt)) {
+ for (int i=0; i < children.count(); i++) {
+ if (toSymbianConfig(privateConfiguration(children[i]))->mappingName == toSymbianConfig(privateConfiguration(pt))->mappingName) {
+ return children[i];
+ }
+ }
+ } else {
+ // Given IAP Id was not found from known IAPs array
+ return QNetworkConfiguration();
+ }
+
+ // Matching IAP was not found from used SNAP
+ // => IAP from another SNAP is returned
+ // (Note: Returned IAP matches to given IAP Id)
+ return pt;
+ }
+#endif
+
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ if (engine) {
+ QNetworkConfiguration pt = QNetworkConfigurationManager().configurationFromIdentifier(QString::number(qHash(iapId)));
+ // Try to found User Selected IAP from known IAPs (accessPointConfigurations)
+ if (pt.isValid()) {
+ return pt;
+ } else {
+ // Check if new (WLAN) IAP was created in IAP/SNAP dialog
+ // 1. Sync internal configurations array to commsdb first
+ engine->updateConfigurations();
+ // 2. Check if new configuration was created during connection creation
+ QList<QString> knownConfigs = engine->accessPointConfigurations.keys();
+ if (knownConfigs.count() > iKnownConfigsBeforeConnectionStart.count()) {
+ // Configuration count increased => new configuration was created
+ // => Search new, created configuration
+ QString newIapId;
+ for (int i=0; i < iKnownConfigsBeforeConnectionStart.count(); i++) {
+ if (knownConfigs[i] != iKnownConfigsBeforeConnectionStart[i]) {
+ newIapId = knownConfigs[i];
+ break;
+ }
+ }
+ if (newIapId.isEmpty()) {
+ newIapId = knownConfigs[knownConfigs.count()-1];
+ }
+ pt = QNetworkConfigurationManager().configurationFromIdentifier(newIapId);
+ if (pt.isValid())
+ return pt;
+ }
+ }
+ }
+ return QNetworkConfiguration();
+ }
+
+ return publicConfig;
+}
+
+void QNetworkSessionPrivateImpl::RunL()
+{
+ TInt statusCode = iStatus.Int();
+
+ switch (statusCode) {
+ case KErrNone: // Connection created succesfully
+ {
+ TInt error = KErrNone;
+ QNetworkConfiguration newActiveConfig = activeConfiguration();
+ if (!newActiveConfig.isValid()) {
+ error = KErrGeneral;
+ } else if (iDynamicSetdefaultif) {
+ // Use name of the IAP to set default IAP
+ QByteArray nameAsByteArray = newActiveConfig.name().toUtf8();
+ ifreq ifr;
+ strcpy(ifr.ifr_name, nameAsByteArray.constData());
+
+ error = iDynamicSetdefaultif(&ifr);
+ }
+
+ if (error != KErrNone) {
+ isOpen = false;
+ iError = QNetworkSession::UnknownSessionError;
+ emit QNetworkSessionPrivate::error(iError);
+ Cancel();
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StopNotifications();
+ }
+ syncStateWithInterface();
+ return;
+ }
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
+ // Activate ALR monitoring
+ iMobility = CActiveCommsMobilityApiExt::NewL(iConnection, *this);
+ }
+#endif
+ isOpen = true;
+ activeConfig = newActiveConfig;
+ activeInterface = interface(toSymbianConfig(privateConfiguration(activeConfig))->numericId);
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ serviceConfig = QNetworkConfigurationManager().configurationFromIdentifier(toSymbianConfig(privateConfiguration(activeConfig))->serviceNetworkPtr->id);
+ }
+
+ startTime = QDateTime::currentDateTime();
+
+ newState(QNetworkSession::Connected);
+ emit quitPendingWaitsForOpened();
+ }
+ break;
+ case KErrNotFound: // Connection failed
+ isOpen = false;
+ activeConfig = QNetworkConfiguration();
+ serviceConfig = QNetworkConfiguration();
+ iError = QNetworkSession::InvalidConfigurationError;
+ emit QNetworkSessionPrivate::error(iError);
+ Cancel();
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StopNotifications();
+ }
+ syncStateWithInterface();
+ break;
+ case KErrCancel: // Connection attempt cancelled
+ case KErrAlreadyExists: // Connection already exists
+ default:
+ isOpen = false;
+ activeConfig = QNetworkConfiguration();
+ serviceConfig = QNetworkConfiguration();
+ iError = QNetworkSession::UnknownSessionError;
+ emit QNetworkSessionPrivate::error(iError);
+ Cancel();
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StopNotifications();
+ }
+ syncStateWithInterface();
+ break;
+ }
+}
+
+void QNetworkSessionPrivateImpl::DoCancel()
+{
+ iConnection.Close();
+}
+
+bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint accessPointId)
+{
+ // Make sure that activeConfig is always updated when SNAP is signaled to be
+ // connected.
+ if (isOpen && publicConfig.type() == QNetworkConfiguration::ServiceNetwork &&
+ newState == QNetworkSession::Connected) {
+ activeConfig = activeConfiguration(accessPointId);
+ activeInterface = interface(toSymbianConfig(privateConfiguration(activeConfig))->numericId);
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (iDynamicSetdefaultif) {
+ // Use name of the IAP to set default IAP
+ QByteArray nameAsByteArray = activeConfig.name().toUtf8();
+ ifreq ifr;
+ strcpy(ifr.ifr_name, nameAsByteArray.constData());
+
+ iDynamicSetdefaultif(&ifr);
+ }
+#endif
+ }
+
+ // Make sure that same state is not signaled twice in a row.
+ if (state == newState) {
+ return true;
+ }
+
+ // Make sure that Connecting state does not overwrite Roaming state
+ if (state == QNetworkSession::Roaming && newState == QNetworkSession::Connecting) {
+ return false;
+ }
+
+ bool emitSessionClosed = false;
+ if (isOpen && state == QNetworkSession::Connected && newState == QNetworkSession::Disconnected) {
+ // Active & Connected state should change directly to Disconnected state
+ // only when something forces connection to close (eg. when another
+ // application or session stops connection or when network drops
+ // unexpectedly).
+ isOpen = false;
+ activeConfig = QNetworkConfiguration();
+ serviceConfig = QNetworkConfiguration();
+ iError = QNetworkSession::SessionAbortedError;
+ emit QNetworkSessionPrivate::error(iError);
+ Cancel();
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StopNotifications();
+ }
+ // Start monitoring changes in IAP states
+ TRAP_IGNORE(iConnectionMonitor.NotifyEventL(*this));
+ emitSessionClosed = true; // Emit SessionClosed after state change has been reported
+ }
+
+ bool retVal = false;
+ if (accessPointId == 0) {
+ state = newState;
+ emit stateChanged(state);
+ retVal = true;
+ } else {
+ if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
+ if (toSymbianConfig(privateConfiguration(publicConfig))->numericId == accessPointId) {
+ state = newState;
+ emit stateChanged(state);
+ retVal = true;
+ }
+ } else if (publicConfig.type() == QNetworkConfiguration::UserChoice && isOpen) {
+ if (toSymbianConfig(privateConfiguration(activeConfig))->numericId == accessPointId) {
+ state = newState;
+ emit stateChanged(state);
+ retVal = true;
+ }
+ } else if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
+ QList<QNetworkConfiguration> subConfigurations = publicConfig.children();
+ for (int i = 0; i < subConfigurations.count(); i++) {
+ if (toSymbianConfig(privateConfiguration(subConfigurations[i]))->numericId == accessPointId) {
+ if (newState == QNetworkSession::Connected) {
+ // Make sure that when AccessPoint is reported to be Connected
+ // also state of the related configuration changes to Active.
+ privateConfiguration(subConfigurations[i])->state = QNetworkConfiguration::Active;
+
+ state = newState;
+ emit stateChanged(state);
+ retVal = true;
+ } else {
+ if (newState == QNetworkSession::Disconnected) {
+ // Make sure that when AccessPoint is reported to be disconnected
+ // also state of the related configuration changes from Active to Defined.
+ privateConfiguration(subConfigurations[i])->state = QNetworkConfiguration::Defined;
+ }
+ QNetworkConfiguration config = bestConfigFromSNAP(publicConfig);
+ if ((config.state() == QNetworkConfiguration::Defined) ||
+ (config.state() == QNetworkConfiguration::Discovered)) {
+ state = newState;
+ emit stateChanged(state);
+ retVal = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (emitSessionClosed) {
+ emit closed();
+ }
+
+ return retVal;
+}
+
+void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConnectionStatus,
+ TInt aError,
+ TUint accessPointId)
+{
+ switch (aConnectionStatus)
+ {
+ // Connection unitialised
+ case KConnectionUninitialised:
+ break;
+
+ // Starting connetion selection
+ case KStartingSelection:
+ break;
+
+ // Selection finished
+ case KFinishedSelection:
+ if (aError == KErrNone)
+ {
+ // The user successfully selected an IAP to be used
+ break;
+ }
+ else
+ {
+ // The user pressed e.g. "Cancel" and did not select an IAP
+ newState(QNetworkSession::Disconnected,accessPointId);
+ }
+ break;
+
+ // Connection failure
+ case KConnectionFailure:
+ newState(QNetworkSession::NotAvailable);
+ break;
+
+ // Prepearing connection (e.g. dialing)
+ case KPsdStartingConfiguration:
+ case KPsdFinishedConfiguration:
+ case KCsdFinishedDialling:
+ case KCsdScanningScript:
+ case KCsdGettingLoginInfo:
+ case KCsdGotLoginInfo:
+ break;
+
+ // Creating connection (e.g. GPRS activation)
+ case KCsdStartingConnect:
+ case KCsdFinishedConnect:
+ newState(QNetworkSession::Connecting,accessPointId);
+ break;
+
+ // Starting log in
+ case KCsdStartingLogIn:
+ break;
+
+ // Finished login
+ case KCsdFinishedLogIn:
+ break;
+
+ // Connection open
+ case KConnectionOpen:
+ break;
+
+ case KLinkLayerOpen:
+ newState(QNetworkSession::Connected,accessPointId);
+ break;
+
+ // Connection blocked or suspended
+ case KDataTransferTemporarilyBlocked:
+ break;
+
+ // Hangup or GRPS deactivation
+ case KConnectionStartingClose:
+ newState(QNetworkSession::Closing,accessPointId);
+ break;
+
+ // Connection closed
+ case KConnectionClosed:
+ break;
+
+ case KLinkLayerClosed:
+ newState(QNetworkSession::Disconnected,accessPointId);
+ break;
+
+ // Unhandled state
+ default:
+ break;
+ }
+}
+
+void QNetworkSessionPrivateImpl::EventL(const CConnMonEventBase& aEvent)
+{
+ switch (aEvent.EventType())
+ {
+ case EConnMonConnectionStatusChange:
+ {
+ CConnMonConnectionStatusChange* realEvent;
+ realEvent = (CConnMonConnectionStatusChange*) &aEvent;
+
+ TUint connectionId = realEvent->ConnectionId();
+ TInt connectionStatus = realEvent->ConnectionStatus();
+
+ // Try to Find IAP Id using connection Id
+ TUint apId = 0;
+ if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
+ QList<QNetworkConfiguration> subConfigurations = publicConfig.children();
+ for (int i = 0; i < subConfigurations.count(); i++ ) {
+ if (toSymbianConfig(privateConfiguration(subConfigurations[i]))->connectionId == connectionId) {
+ apId = toSymbianConfig(privateConfiguration(subConfigurations[i]))->numericId;
+ break;
+ }
+ }
+ } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
+ if (toSymbianConfig(privateConfiguration(publicConfig))->connectionId == connectionId) {
+ apId = toSymbianConfig(privateConfiguration(publicConfig))->numericId;
+ }
+ }
+
+ if (apId > 0) {
+ handleSymbianConnectionStatusChange(connectionStatus, KErrNone, apId);
+ }
+ }
+ break;
+
+ case EConnMonCreateConnection:
+ {
+ CConnMonCreateConnection* realEvent;
+ realEvent = (CConnMonCreateConnection*) &aEvent;
+ TUint apId;
+ TUint connectionId = realEvent->ConnectionId();
+ TRequestStatus status;
+ iConnectionMonitor.GetUintAttribute(connectionId, 0, KIAPId, apId, status);
+ User::WaitForRequest(status);
+ if (status.Int() == KErrNone) {
+ // Store connection id to related AccessPoint Configuration
+ if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
+ QList<QNetworkConfiguration> subConfigurations = publicConfig.children();
+ for (int i = 0; i < subConfigurations.count(); i++ ) {
+ if (toSymbianConfig(privateConfiguration(subConfigurations[i]))->numericId == apId) {
+ toSymbianConfig(privateConfiguration(subConfigurations[i]))->connectionId = connectionId;
+ break;
+ }
+ }
+ } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
+ if (toSymbianConfig(privateConfiguration(publicConfig))->numericId == apId) {
+ toSymbianConfig(privateConfiguration(publicConfig))->connectionId = connectionId;
+ }
+ }
+ }
+ }
+ break;
+
+ case EConnMonDeleteConnection:
+ {
+ CConnMonDeleteConnection* realEvent;
+ realEvent = (CConnMonDeleteConnection*) &aEvent;
+ TUint connectionId = realEvent->ConnectionId();
+ // Remove connection id from related AccessPoint Configuration
+ if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
+ QList<QNetworkConfiguration> subConfigurations = publicConfig.children();
+ for (int i = 0; i < subConfigurations.count(); i++ ) {
+ if (toSymbianConfig(privateConfiguration(subConfigurations[i]))->connectionId == connectionId) {
+ toSymbianConfig(privateConfiguration(subConfigurations[i]))->connectionId = 0;
+ break;
+ }
+ }
+ } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
+ if (toSymbianConfig(privateConfiguration(publicConfig))->connectionId == connectionId) {
+ toSymbianConfig(privateConfiguration(publicConfig))->connectionId = 0;
+ }
+ }
+ }
+ break;
+
+ default:
+ // For unrecognized events
+ break;
+ }
+}
+
+ConnectionProgressNotifier::ConnectionProgressNotifier(QNetworkSessionPrivateImpl &owner, RConnection &connection)
+ : CActive(CActive::EPriorityStandard), iOwner(owner), iConnection(connection)
+{
+ CActiveScheduler::Add(this);
+}
+
+ConnectionProgressNotifier::~ConnectionProgressNotifier()
+{
+ Cancel();
+}
+
+void ConnectionProgressNotifier::StartNotifications()
+{
+ if (!IsActive()) {
+ SetActive();
+ }
+ iConnection.ProgressNotification(iProgress, iStatus);
+}
+
+void ConnectionProgressNotifier::StopNotifications()
+{
+ Cancel();
+}
+
+void ConnectionProgressNotifier::DoCancel()
+{
+ iConnection.CancelProgressNotification();
+}
+
+void ConnectionProgressNotifier::RunL()
+{
+ if (iStatus == KErrNone) {
+ iOwner.handleSymbianConnectionStatusChange(iProgress().iStage, iProgress().iError);
+
+ SetActive();
+ iConnection.ProgressNotification(iProgress, iStatus);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h
new file mode 100644
index 0000000..30f51e1
--- /dev/null
+++ b/src/plugins/bearer/symbian/qnetworksession_impl.h
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 QNETWORKSESSION_IMPL_H
+#define QNETWORKSESSION_IMPL_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/qnetworksession_p.h>
+
+#include <QDateTime>
+
+#include <e32base.h>
+#include <CommDbConnPref.h>
+#include <es_sock.h>
+#include <rconnmon.h>
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ #include <comms-infras/cs_mobility_apiext.h>
+#endif
+
+typedef int(*TOpenCSetdefaultifFunction)(const struct ifreq*);
+
+QT_BEGIN_NAMESPACE
+
+class ConnectionProgressNotifier;
+class SymbianEngine;
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate, public CActive, public MMobilityProtocolResp,
+ public MConnectionMonitorObserver
+#else
+class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate, public CActive, public MConnectionMonitorObserver
+#endif
+{
+ Q_OBJECT
+public:
+ QNetworkSessionPrivateImpl(SymbianEngine *engine);
+ ~QNetworkSessionPrivateImpl();
+
+ //called by QNetworkSession constructor and ensures
+ //that the state is immediately updated (w/o actually opening
+ //a session). Also this function should take care of
+ //notification hooks to discover future state changes.
+ void syncStateWithInterface();
+
+ QNetworkInterface currentInterface() const;
+ QVariant sessionProperty(const QString& key) const;
+ void setSessionProperty(const QString& key, const QVariant& value);
+
+ void setALREnabled(bool enabled);
+
+ void open();
+ inline void close() { close(true); }
+ void close(bool allowSignals);
+ void stop();
+ void migrate();
+ void accept();
+ void ignore();
+ void reject();
+
+ QString errorString() const; //must return translated string
+ QNetworkSession::SessionError error() const;
+
+ quint64 bytesWritten() const;
+ quint64 bytesReceived() const;
+ quint64 activeTime() const;
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+public: // From MMobilityProtocolResp
+ void PreferredCarrierAvailable(TAccessPointInfo aOldAPInfo,
+ TAccessPointInfo aNewAPInfo,
+ TBool aIsUpgrade,
+ TBool aIsSeamless);
+
+ void NewCarrierActive(TAccessPointInfo aNewAPInfo, TBool aIsSeamless);
+
+ void Error(TInt aError);
+#endif
+
+protected: // From CActive
+ void RunL();
+ void DoCancel();
+
+private: // MConnectionMonitorObserver
+ void EventL(const CConnMonEventBase& aEvent);
+
+private:
+ TUint iapClientCount(TUint aIAPId) const;
+ quint64 transferredData(TUint dataType) const;
+ bool newState(QNetworkSession::State newState, TUint accessPointId = 0);
+ void handleSymbianConnectionStatusChange(TInt aConnectionStatus, TInt aError, TUint accessPointId = 0);
+ QNetworkConfiguration bestConfigFromSNAP(const QNetworkConfiguration& snapConfig) const;
+ QNetworkConfiguration activeConfiguration(TUint32 iapId = 0) const;
+ QNetworkInterface interface(TUint iapId) const;
+
+private: // data
+ SymbianEngine *engine;
+
+ mutable QNetworkInterface activeInterface;
+
+ QDateTime startTime;
+
+ RLibrary iOpenCLibrary;
+ TOpenCSetdefaultifFunction iDynamicSetdefaultif;
+
+ mutable RSocketServ iSocketServ;
+ mutable RConnection iConnection;
+ mutable RConnectionMonitor iConnectionMonitor;
+ ConnectionProgressNotifier* ipConnectionNotifier;
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ CActiveCommsMobilityApiExt* iMobility;
+#endif
+
+ QNetworkSession::SessionError iError;
+ TInt iALREnabled;
+ TBool iALRUpgradingConnection;
+
+ QList<QString> iKnownConfigsBeforeConnectionStart;
+
+ TUint32 iOldRoamingIap;
+ TUint32 iNewRoamingIap;
+
+ friend class ConnectionProgressNotifier;
+};
+
+class ConnectionProgressNotifier : public CActive
+{
+public:
+ ConnectionProgressNotifier(QNetworkSessionPrivateImpl &owner, RConnection &connection);
+ ~ConnectionProgressNotifier();
+
+ void StartNotifications();
+ void StopNotifications();
+
+protected: // From CActive
+ void RunL();
+ void DoCancel();
+
+private: // Data
+ QNetworkSessionPrivateImpl &iOwner;
+ RConnection& iConnection;
+ TNifProgressBuf iProgress;
+
+};
+
+QT_END_NAMESPACE
+
+#endif //QNETWORKSESSION_IMPL_H
+
diff --git a/src/plugins/bearer/symbian/symbian.pro b/src/plugins/bearer/symbian/symbian.pro
new file mode 100644
index 0000000..9fd1a74
--- /dev/null
+++ b/src/plugins/bearer/symbian/symbian.pro
@@ -0,0 +1,37 @@
+TARGET = qsymbianbearer
+include(../../qpluginbase.pri)
+
+QT += network
+
+HEADERS += symbianengine.h \
+ qnetworksession_impl.h
+
+SOURCES += symbianengine.cpp \
+ qnetworksession_impl.cpp \
+ main.cpp
+
+exists($${EPOCROOT}epoc32/release/winscw/udeb/cmmanager.lib)| \
+exists($${EPOCROOT}epoc32/release/armv5/lib/cmmanager.lib) {
+ message("Building with SNAP support")
+ DEFINES += SNAP_FUNCTIONALITY_AVAILABLE
+ LIBS += -lcmmanager
+} else {
+ message("Building without SNAP support")
+ LIBS += -lapengine
+}
+
+INCLUDEPATH += $$APP_LAYER_SYSTEMINCLUDE
+
+LIBS += -lcommdb \
+ -lapsettingshandlerui \
+ -lconnmon \
+ -lcentralrepository \
+ -lesock \
+ -linsock \
+ -lecom \
+ -lefsrv \
+ -lnetmeta
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/bearer
+target.path += $$[QT_INSTALL_PLUGINS]/bearer
+INSTALLS += target
diff --git a/src/plugins/bearer/symbian/symbianengine.cpp b/src/plugins/bearer/symbian/symbianengine.cpp
new file mode 100644
index 0000000..e25eda4
--- /dev/null
+++ b/src/plugins/bearer/symbian/symbianengine.cpp
@@ -0,0 +1,955 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 "symbianengine.h"
+#include "qnetworksession_impl.h"
+
+#include <commdb.h>
+#include <cdbcols.h>
+#include <d32dbms.h>
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ #include <cmdestination.h>
+ #include <cmconnectionmethod.h>
+ #include <cmconnectionmethoddef.h>
+ #include <cmpluginwlandef.h>
+ #include <cmpluginpacketdatadef.h>
+ #include <cmplugindialcommondefs.h>
+#else
+ #include <apaccesspointitem.h>
+ #include <apdatahandler.h>
+ #include <aputils.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+static const int KValueThatWillBeAddedToSNAPId = 1000;
+static const int KUserChoiceIAPId = 0;
+
+SymbianNetworkConfigurationPrivate::SymbianNetworkConfigurationPrivate()
+: bearer(BearerUnknown), numericId(0), connectionId(0)
+{
+}
+
+SymbianNetworkConfigurationPrivate::~SymbianNetworkConfigurationPrivate()
+{
+}
+
+QString SymbianNetworkConfigurationPrivate::bearerName() const
+{
+ switch (bearer) {
+ case BearerEthernet:
+ return QLatin1String("Ethernet");
+ case BearerWLAN:
+ return QLatin1String("WLAN");
+ case Bearer2G:
+ return QLatin1String("2G");
+ case BearerCDMA2000:
+ return QLatin1String("CDMA2000");
+ case BearerWCDMA:
+ return QLatin1String("WCDMA");
+ case BearerHSPA:
+ return QLatin1String("HSPA");
+ case BearerBluetooth:
+ return QLatin1String("Bluetooth");
+ case BearerWiMAX:
+ return QLatin1String("WiMAX");
+ default:
+ return QString();
+ }
+}
+
+SymbianEngine::SymbianEngine(QObject *parent)
+: QBearerEngine(parent), CActive(CActive::EPriorityIdle), iInitOk(true)
+{
+ CActiveScheduler::Add(this);
+
+ TRAPD(error, ipCommsDB = CCommsDatabase::NewL(EDatabaseTypeIAP));
+ if (error != KErrNone) {
+ iInitOk = false;
+ return;
+ }
+
+ TRAP_IGNORE(iConnectionMonitor.ConnectL());
+ TRAP_IGNORE(iConnectionMonitor.NotifyEventL(*this));
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ TRAP(error, iCmManager.OpenL());
+ if (error != KErrNone) {
+ iInitOk = false;
+ return;
+ }
+#endif
+
+ SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
+ cpPriv->name = "UserChoice";
+ cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerUnknown;
+ cpPriv->state = QNetworkConfiguration::Discovered;
+ cpPriv->isValid = true;
+ cpPriv->id = QString::number(qHash(KUserChoiceIAPId));
+ cpPriv->numericId = KUserChoiceIAPId;
+ cpPriv->connectionId = 0;
+ cpPriv->type = QNetworkConfiguration::UserChoice;
+ cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
+ cpPriv->roamingSupported = false;
+
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ userChoiceConfigurations.insert(ptr->id, ptr);
+
+ updateConfigurations();
+ updateStatesToSnaps();
+
+ // Start monitoring IAP and/or SNAP changes in Symbian CommsDB
+ startCommsDatabaseNotifications();
+}
+
+SymbianEngine::~SymbianEngine()
+{
+ Cancel();
+
+ iConnectionMonitor.CancelNotifications();
+ iConnectionMonitor.Close();
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ iCmManager.Close();
+#endif
+
+ delete ipAccessPointsAvailabilityScanner;
+ delete ipCommsDB;
+}
+
+bool SymbianEngine::hasIdentifier(const QString &id)
+{
+ return accessPointConfigurations.contains(id) ||
+ snapConfigurations.contains(id) ||
+ userChoiceConfigurations.contains(id);
+}
+
+QNetworkConfigurationManager::Capabilities SymbianEngine::capabilities() const
+{
+ QNetworkConfigurationManager::Capabilities capFlags;
+
+ capFlags = QNetworkConfigurationManager::CanStartAndStopInterfaces |
+ QNetworkConfigurationManager::DirectConnectionRouting |
+ QNetworkConfigurationManager::SystemSessionSupport |
+ QNetworkConfigurationManager::DataStatistics;
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ capFlags |= QNetworkConfigurationManager::ApplicationLevelRoaming |
+ QNetworkConfigurationManager::ForcedRoaming;
+#endif
+
+ return capFlags;
+}
+
+QNetworkSessionPrivate *SymbianEngine::createSessionBackend()
+{
+ return new QNetworkSessionPrivateImpl(this);
+}
+
+void SymbianEngine::requestUpdate()
+{
+ if (!iInitOk || iUpdateGoingOn) {
+ return;
+ }
+ iUpdateGoingOn = true;
+
+ stopCommsDatabaseNotifications();
+ updateConfigurations(); // Synchronous call
+ updateAvailableAccessPoints(); // Asynchronous call
+}
+
+void SymbianEngine::updateConfigurations()
+{
+ if (!iInitOk) {
+ return;
+ }
+
+ TRAP_IGNORE(updateConfigurationsL());
+}
+
+void SymbianEngine::updateConfigurationsL()
+{
+ QList<QString> knownConfigs = accessPointConfigurations.keys();
+ QList<QString> knownSnapConfigs = snapConfigurations.keys();
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ // S60 version is >= Series60 3rd Edition Feature Pack 2
+ TInt error = KErrNone;
+
+ // Loop through all IAPs
+ RArray<TUint32> connectionMethods; // IAPs
+ CleanupClosePushL(connectionMethods);
+ iCmManager.ConnectionMethodL(connectionMethods);
+ for(int i = 0; i < connectionMethods.Count(); i++) {
+ RCmConnectionMethod connectionMethod = iCmManager.ConnectionMethodL(connectionMethods[i]);
+ CleanupClosePushL(connectionMethod);
+ TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
+ QString ident = QString::number(qHash(iapId));
+ if (accessPointConfigurations.contains(ident)) {
+ knownConfigs.removeOne(ident);
+ } else {
+ SymbianNetworkConfigurationPrivate* cpPriv = NULL;
+ TRAP(error, cpPriv = configFromConnectionMethodL(connectionMethod));
+ if (error == KErrNone) {
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ accessPointConfigurations.insert(ptr->id, ptr);
+ emit configurationAdded(ptr);
+ }
+ }
+ CleanupStack::PopAndDestroy(&connectionMethod);
+ }
+ CleanupStack::PopAndDestroy(&connectionMethods);
+
+ // Loop through all SNAPs
+ RArray<TUint32> destinations;
+ CleanupClosePushL(destinations);
+ iCmManager.AllDestinationsL(destinations);
+ for(int i = 0; i < destinations.Count(); i++) {
+ RCmDestination destination;
+ destination = iCmManager.DestinationL(destinations[i]);
+ CleanupClosePushL(destination);
+ QString ident = QString::number(qHash(destination.Id()+KValueThatWillBeAddedToSNAPId)); //TODO: Check if it's ok to add 1000 SNAP Id to prevent SNAP ids overlapping IAP ids
+ if (snapConfigurations.contains(ident)) {
+ knownSnapConfigs.removeOne(ident);
+ } else {
+ SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
+ CleanupStack::PushL(cpPriv);
+
+ HBufC *pName = destination.NameLC();
+ cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length());
+ CleanupStack::PopAndDestroy(pName);
+ pName = NULL;
+
+ cpPriv->isValid = true;
+ cpPriv->id = ident;
+ cpPriv->numericId = destination.Id();
+ cpPriv->connectionId = 0;
+ cpPriv->state = QNetworkConfiguration::Defined;
+ cpPriv->type = QNetworkConfiguration::ServiceNetwork;
+ cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
+ cpPriv->roamingSupported = false;
+
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ snapConfigurations.insert(ident, ptr);
+ emit configurationAdded(ptr);
+
+ CleanupStack::Pop(cpPriv);
+ }
+ QNetworkConfigurationPrivatePointer privSNAP = snapConfigurations.value(ident);
+
+ for (int j=0; j < destination.ConnectionMethodCount(); j++) {
+ RCmConnectionMethod connectionMethod = destination.ConnectionMethodL(j);
+ CleanupClosePushL(connectionMethod);
+
+ TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
+ QString iface = QString::number(qHash(iapId));
+ // Check that IAP can be found from accessPointConfigurations list
+ QNetworkConfigurationPrivatePointer priv = accessPointConfigurations.value(iface);
+ if (!priv) {
+ SymbianNetworkConfigurationPrivate *cpPriv = NULL;
+ TRAP(error, cpPriv = configFromConnectionMethodL(connectionMethod));
+ if (error == KErrNone) {
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ toSymbianConfig(ptr)->serviceNetworkPtr = privSNAP;
+ accessPointConfigurations.insert(ptr->id, ptr);
+ emit configurationAdded(ptr);
+ privSNAP->serviceNetworkMembers.append(ptr);
+ }
+ } else {
+ knownConfigs.removeOne(iface);
+ // Check that IAP can be found from related SNAP's configuration list
+ bool iapFound = false;
+ for (int i = 0; i < privSNAP->serviceNetworkMembers.count(); i++) {
+ if (toSymbianConfig(privSNAP->serviceNetworkMembers[i])->numericId == iapId) {
+ iapFound = true;
+ break;
+ }
+ }
+ if (!iapFound) {
+ toSymbianConfig(priv)->serviceNetworkPtr = privSNAP;
+ privSNAP->serviceNetworkMembers.append(priv);
+ }
+ }
+
+ CleanupStack::PopAndDestroy(&connectionMethod);
+ }
+
+ if (privSNAP->serviceNetworkMembers.count() > 1) {
+ // Roaming is supported only if SNAP contains more than one IAP
+ privSNAP->roamingSupported = true;
+ }
+
+ CleanupStack::PopAndDestroy(&destination);
+ }
+ CleanupStack::PopAndDestroy(&destinations);
+
+#else
+ // S60 version is < Series60 3rd Edition Feature Pack 2
+ CCommsDbTableView* pDbTView = ipCommsDB->OpenTableLC(TPtrC(IAP));
+
+ // Loop through all IAPs
+ TUint32 apId = 0;
+ TInt retVal = pDbTView->GotoFirstRecord();
+ while (retVal == KErrNone) {
+ pDbTView->ReadUintL(TPtrC(COMMDB_ID), apId);
+ QString ident = QString::number(qHash(apId));
+ if (accessPointConfigurations.contains(ident)) {
+ knownConfigs.removeOne(ident);
+ } else {
+ SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
+ if (readNetworkConfigurationValuesFromCommsDb(apId, cpPriv)) {
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ accessPointConfigurations.insert(ident, ptr);
+
+ emit configurationAdded(ptr);
+ } else {
+ delete cpPriv;
+ }
+ }
+ retVal = pDbTView->GotoNextRecord();
+ }
+ CleanupStack::PopAndDestroy(pDbTView);
+#endif
+ updateActiveAccessPoints();
+
+ foreach (const QString &oldIface, knownConfigs) {
+ //remove non existing IAP
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(oldIface);
+ emit configurationRemoved(ptr);
+
+ // Remove non existing IAP from SNAPs
+ foreach (const QString &iface, snapConfigurations.keys()) {
+ QNetworkConfigurationPrivatePointer ptr2 = snapConfigurations.value(iface);
+ // => Check if one of the IAPs of the SNAP is active
+ for (int i = 0; i < ptr2->serviceNetworkMembers.count(); ++i) {
+ if (toSymbianConfig(ptr2->serviceNetworkMembers[i])->numericId ==
+ toSymbianConfig(ptr)->numericId) {
+ ptr2->serviceNetworkMembers.removeAt(i);
+ break;
+ }
+ }
+ }
+ }
+
+ foreach (const QString &oldIface, knownSnapConfigs) {
+ //remove non existing SNAPs
+ QNetworkConfigurationPrivatePointer ptr = snapConfigurations.take(oldIface);
+ emit configurationRemoved(ptr);
+ }
+}
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+SymbianNetworkConfigurationPrivate *SymbianEngine::configFromConnectionMethodL(
+ RCmConnectionMethod& connectionMethod)
+{
+ SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
+ CleanupStack::PushL(cpPriv);
+
+ TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
+ QString ident = QString::number(qHash(iapId));
+
+ HBufC *pName = connectionMethod.GetStringAttributeL(CMManager::ECmName);
+ CleanupStack::PushL(pName);
+ cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length());
+ CleanupStack::PopAndDestroy(pName);
+ pName = NULL;
+
+ TUint32 bearerId = connectionMethod.GetIntAttributeL(CMManager::ECmCommsDBBearerType);
+ switch (bearerId) {
+ case KCommDbBearerCSD:
+ cpPriv->bearer = SymbianNetworkConfigurationPrivate::Bearer2G;
+ break;
+ case KCommDbBearerWcdma:
+ cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerWCDMA;
+ break;
+ case KCommDbBearerLAN:
+ cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerEthernet;
+ break;
+ case KCommDbBearerVirtual:
+ cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerUnknown;
+ break;
+ case KCommDbBearerPAN:
+ cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerUnknown;
+ break;
+ case KCommDbBearerWLAN:
+ cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerWLAN;
+ break;
+ default:
+ cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerUnknown;
+ break;
+ }
+
+ TInt error = KErrNone;
+ TUint32 bearerType = connectionMethod.GetIntAttributeL(CMManager::ECmBearerType);
+ switch (bearerType) {
+ case KUidPacketDataBearerType:
+ // "Packet data" Bearer => Mapping is done using "Access point name"
+ TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EPacketDataAPName));
+ break;
+ case KUidWlanBearerType:
+ // "Wireless LAN" Bearer => Mapping is done using "WLAN network name" = SSID
+ TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EWlanSSID));
+ break;
+ }
+ if (!pName) {
+ // "Data call" Bearer or "High Speed (GSM)" Bearer => Mapping is done using "Dial-up number"
+ TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EDialDefaultTelNum));
+ }
+
+ if (error == KErrNone && pName) {
+ CleanupStack::PushL(pName);
+ cpPriv->mappingName = QString::fromUtf16(pName->Ptr(),pName->Length());
+ CleanupStack::PopAndDestroy(pName);
+ pName = NULL;
+ }
+
+ cpPriv->state = QNetworkConfiguration::Defined;
+ TBool isConnected = connectionMethod.GetBoolAttributeL(CMManager::ECmConnected);
+ if (isConnected) {
+ cpPriv->state = QNetworkConfiguration::Active;
+ }
+
+ cpPriv->isValid = true;
+ cpPriv->id = ident;
+ cpPriv->numericId = iapId;
+ cpPriv->connectionId = 0;
+ cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
+ cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
+ cpPriv->roamingSupported = false;
+
+ CleanupStack::Pop(cpPriv);
+ return cpPriv;
+}
+#else
+bool SymbianEngine::readNetworkConfigurationValuesFromCommsDb(
+ TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration)
+{
+ TRAPD(error, readNetworkConfigurationValuesFromCommsDbL(aApId,apNetworkConfiguration));
+ if (error != KErrNone) {
+ return false;
+ }
+ return true;
+}
+
+void SymbianEngine::readNetworkConfigurationValuesFromCommsDbL(
+ TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration)
+{
+ CApDataHandler* pDataHandler = CApDataHandler::NewLC(*ipCommsDB);
+ CApAccessPointItem* pAPItem = CApAccessPointItem::NewLC();
+ TBuf<KCommsDbSvrMaxColumnNameLength> name;
+
+ CApUtils* pApUtils = CApUtils::NewLC(*ipCommsDB);
+ TUint32 apId = pApUtils->WapIdFromIapIdL(aApId);
+
+ pDataHandler->AccessPointDataL(apId,*pAPItem);
+ pAPItem->ReadTextL(EApIapName, name);
+ if (name.Compare(_L("Easy WLAN")) == 0) {
+ // "Easy WLAN" won't be accepted to the Configurations list
+ User::Leave(KErrNotFound);
+ }
+
+ QString ident = QString::number(qHash(aApId));
+
+ apNetworkConfiguration->name = QString::fromUtf16(name.Ptr(),name.Length());
+ apNetworkConfiguration->isValid = true;
+ apNetworkConfiguration->id = ident;
+ apNetworkConfiguration->numericId = aApId;
+ apNetworkConfiguration->connectionId = 0;
+ apNetworkConfiguration->state = (QNetworkConfiguration::Defined);
+ apNetworkConfiguration->type = QNetworkConfiguration::InternetAccessPoint;
+ apNetworkConfiguration->purpose = QNetworkConfiguration::UnknownPurpose;
+ apNetworkConfiguration->roamingSupported = false;
+ switch (pAPItem->BearerTypeL()) {
+ case EApBearerTypeCSD:
+ apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::Bearer2G;
+ break;
+ case EApBearerTypeGPRS:
+ apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::Bearer2G;
+ break;
+ case EApBearerTypeHSCSD:
+ apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::BearerHSPA;
+ break;
+ case EApBearerTypeCDMA:
+ apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::BearerCDMA2000;
+ break;
+ case EApBearerTypeWLAN:
+ apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::BearerWLAN;
+ break;
+ case EApBearerTypeLAN:
+ apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::BearerEthernet;
+ break;
+ case EApBearerTypeLANModem:
+ apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::BearerEthernet;
+ break;
+ default:
+ apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::BearerUnknown;
+ break;
+ }
+
+ CleanupStack::PopAndDestroy(pApUtils);
+ CleanupStack::PopAndDestroy(pAPItem);
+ CleanupStack::PopAndDestroy(pDataHandler);
+}
+#endif
+
+QNetworkConfigurationPrivatePointer SymbianEngine::defaultConfiguration()
+{
+ QNetworkConfigurationPrivatePointer ptr;
+
+ if (iInitOk) {
+ stopCommsDatabaseNotifications();
+ TRAP_IGNORE(ptr = defaultConfigurationL());
+ startCommsDatabaseNotifications();
+ }
+
+ return ptr;
+}
+
+QNetworkConfigurationPrivatePointer SymbianEngine::defaultConfigurationL()
+{
+ QNetworkConfigurationPrivatePointer ptr;
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ // Check Default Connection (SNAP or IAP)
+ TCmDefConnValue defaultConnectionValue;
+ iCmManager.ReadDefConnL(defaultConnectionValue);
+ if (defaultConnectionValue.iType == ECmDefConnDestination) {
+ QString iface = QString::number(qHash(defaultConnectionValue.iId+KValueThatWillBeAddedToSNAPId));
+ ptr = snapConfigurations.value(iface);
+ } else if (defaultConnectionValue.iType == ECmDefConnConnectionMethod) {
+ QString iface = QString::number(qHash(defaultConnectionValue.iId));
+ ptr = accessPointConfigurations.value(iface);
+ }
+#endif
+
+ if (!ptr->isValid) {
+ QString iface = QString::number(qHash(KUserChoiceIAPId));
+ ptr = userChoiceConfigurations.value(iface);
+ }
+
+ return ptr;
+}
+
+void SymbianEngine::updateActiveAccessPoints()
+{
+ bool online = false;
+ QList<QString> inactiveConfigs = accessPointConfigurations.keys();
+
+ TRequestStatus status;
+ TUint connectionCount;
+ iConnectionMonitor.GetConnectionCount(connectionCount, status);
+ User::WaitForRequest(status);
+
+ // Go through all connections and set state of related IAPs to Active
+ TUint connectionId;
+ TUint subConnectionCount;
+ TUint apId;
+ if (status.Int() == KErrNone) {
+ for (TUint i = 1; i <= connectionCount; i++) {
+ iConnectionMonitor.GetConnectionInfo(i, connectionId, subConnectionCount);
+ iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
+ User::WaitForRequest(status);
+ QString ident = QString::number(qHash(apId));
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+ if (ptr) {
+ online = true;
+ inactiveConfigs.removeOne(ident);
+
+ toSymbianConfig(ptr)->connectionId = connectionId;
+
+ // Configuration is Active
+ changeConfigurationStateTo(ptr, QNetworkConfiguration::Active);
+ }
+ }
+ }
+
+ // Make sure that state of rest of the IAPs won't be Active
+ foreach (const QString &iface, inactiveConfigs) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
+ if (ptr) {
+ // Configuration is either Defined or Discovered
+ changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered);
+ }
+ }
+
+ if (iOnline != online) {
+ iOnline = online;
+ emit this->onlineStateChanged(iOnline);
+ }
+}
+
+void SymbianEngine::updateAvailableAccessPoints()
+{
+ if (!ipAccessPointsAvailabilityScanner) {
+ ipAccessPointsAvailabilityScanner = new AccessPointsAvailabilityScanner(*this, iConnectionMonitor);
+ }
+ if (ipAccessPointsAvailabilityScanner) {
+ // Scanning may take a while because WLAN scanning will be done (if device supports WLAN).
+ ipAccessPointsAvailabilityScanner->StartScanning();
+ }
+}
+
+void SymbianEngine::accessPointScanningReady(TBool scanSuccessful, TConnMonIapInfo iapInfo)
+{
+ iUpdateGoingOn = false;
+ if (scanSuccessful) {
+ QList<QString> unavailableConfigs = accessPointConfigurations.keys();
+
+ // Set state of returned IAPs to Discovered
+ // if state is not already Active
+ for(TUint i=0; i<iapInfo.iCount; i++) {
+ QString ident = QString::number(qHash(iapInfo.iIap[i].iIapId));
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+ if (ptr) {
+ unavailableConfigs.removeOne(ident);
+ if (ptr->state < QNetworkConfiguration::Active) {
+ // Configuration is either Discovered or Active
+ changeConfigurationStateAtMinTo(ptr, QNetworkConfiguration::Discovered);
+ }
+ }
+ }
+
+ // Make sure that state of rest of the IAPs won't be Discovered or Active
+ foreach (const QString &iface, unavailableConfigs) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
+ if (ptr) {
+ // Configuration is Defined
+ changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Defined);
+ }
+ }
+ }
+
+ updateStatesToSnaps();
+
+ startCommsDatabaseNotifications();
+
+ emit updateCompleted();
+}
+
+void SymbianEngine::updateStatesToSnaps()
+{
+ // Go through SNAPs and set correct state to SNAPs
+ QList<QString> snapConfigIdents = snapConfigurations.keys();
+ foreach (QString iface, snapConfigIdents) {
+ bool discovered = false;
+ bool active = false;
+ QNetworkConfigurationPrivatePointer ptr = snapConfigurations.value(iface);
+ // => Check if one of the IAPs of the SNAP is discovered or active
+ // => If one of IAPs is active, also SNAP is active
+ // => If one of IAPs is discovered but none of the IAPs is active, SNAP is discovered
+ for (int i=0; i<ptr->serviceNetworkMembers.count(); i++) {
+ if ((ptr->serviceNetworkMembers[i]->state & QNetworkConfiguration::Active)
+ == QNetworkConfiguration::Active) {
+ active = true;
+ break;
+ } else if ((ptr->serviceNetworkMembers[i]->state & QNetworkConfiguration::Discovered)
+ == QNetworkConfiguration::Discovered) {
+ discovered = true;
+ }
+ }
+ if (active) {
+ changeConfigurationStateTo(ptr, QNetworkConfiguration::Active);
+ } else if (discovered) {
+ changeConfigurationStateTo(ptr, QNetworkConfiguration::Discovered);
+ } else {
+ changeConfigurationStateTo(ptr, QNetworkConfiguration::Defined);
+ }
+ }
+}
+
+bool SymbianEngine::changeConfigurationStateTo(QNetworkConfigurationPrivatePointer ptr,
+ QNetworkConfiguration::StateFlags newState)
+{
+ if (newState != ptr->state) {
+ ptr->state = newState;
+ emit configurationChanged(ptr);
+ return true;
+ }
+ return false;
+}
+
+/* changeConfigurationStateAtMinTo function does not overwrite possible better
+ * state (e.g. Discovered state does not overwrite Active state) but
+ * makes sure that state is at minimum given state.
+*/
+bool SymbianEngine::changeConfigurationStateAtMinTo(QNetworkConfigurationPrivatePointer ptr,
+ QNetworkConfiguration::StateFlags newState)
+{
+ if ((newState | ptr->state) != ptr->state) {
+ ptr->state = (ptr->state | newState);
+ emit configurationChanged(ptr);
+ return true;
+ }
+ return false;
+}
+
+/* changeConfigurationStateAtMaxTo function overwrites possible better
+ * state (e.g. Discovered state overwrites Active state) and
+ * makes sure that state is at maximum given state (e.g. Discovered state
+ * does not overwrite Defined state).
+*/
+bool SymbianEngine::changeConfigurationStateAtMaxTo(QNetworkConfigurationPrivatePointer ptr,
+ QNetworkConfiguration::StateFlags newState)
+{
+ if ((newState & ptr->state) != ptr->state) {
+ ptr->state = (newState & ptr->state);
+ emit configurationChanged(ptr);
+ return true;
+ }
+ return false;
+}
+
+void SymbianEngine::startCommsDatabaseNotifications()
+{
+ if (!iWaitingCommsDatabaseNotifications) {
+ iWaitingCommsDatabaseNotifications = ETrue;
+ if (!IsActive()) {
+ SetActive();
+ // Start waiting for new notification
+ ipCommsDB->RequestNotification(iStatus);
+ }
+ }
+}
+
+void SymbianEngine::stopCommsDatabaseNotifications()
+{
+ if (iWaitingCommsDatabaseNotifications) {
+ iWaitingCommsDatabaseNotifications = EFalse;
+ if (!IsActive()) {
+ SetActive();
+ // Make sure that notifier recorded events will not be returned
+ // as soon as the client issues the next RequestNotification() request.
+ ipCommsDB->RequestNotification(iStatus);
+ ipCommsDB->CancelRequestNotification();
+ } else {
+ ipCommsDB->CancelRequestNotification();
+ }
+ }
+}
+
+void SymbianEngine::RunL()
+{
+ if (iStatus != KErrCancel) {
+ RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int());
+ switch (event) {
+ case RDbNotifier::EUnlock: /** All read locks have been removed. */
+ case RDbNotifier::ECommit: /** A transaction has been committed. */
+ case RDbNotifier::ERollback: /** A transaction has been rolled back */
+ case RDbNotifier::ERecover: /** The database has been recovered */
+ // Note that if further database events occur while a client is handling
+ // a request completion, the notifier records the most significant database
+ // event and this is signalled as soon as the client issues the next
+ // RequestNotification() request.
+ // => Stop recording notifications
+ stopCommsDatabaseNotifications();
+ TRAPD(error, updateConfigurationsL());
+ if (error == KErrNone) {
+ updateStatesToSnaps();
+ }
+ iWaitingCommsDatabaseNotifications = true;
+ break;
+ default:
+ // Do nothing
+ break;
+ }
+ }
+
+ if (iWaitingCommsDatabaseNotifications) {
+ if (!IsActive()) {
+ SetActive();
+ // Start waiting for new notification
+ ipCommsDB->RequestNotification(iStatus);
+ }
+ }
+}
+
+void SymbianEngine::DoCancel()
+{
+ ipCommsDB->CancelRequestNotification();
+}
+
+
+void SymbianEngine::EventL(const CConnMonEventBase& aEvent)
+{
+ switch (aEvent.EventType()) {
+ case EConnMonCreateConnection:
+ {
+ CConnMonCreateConnection* realEvent;
+ realEvent = (CConnMonCreateConnection*) &aEvent;
+ TUint subConnectionCount = 0;
+ TUint apId;
+ TUint connectionId = realEvent->ConnectionId();
+ TRequestStatus status;
+ iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
+ User::WaitForRequest(status);
+ QString ident = QString::number(qHash(apId));
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+ if (ptr) {
+ toSymbianConfig(ptr)->connectionId = connectionId;
+ // Configuration is Active
+ if (changeConfigurationStateTo(ptr, QNetworkConfiguration::Active))
+ updateStatesToSnaps();
+
+ if (!iOnline) {
+ iOnline = true;
+ emit this->onlineStateChanged(iOnline);
+ }
+ }
+ }
+ break;
+
+ case EConnMonDeleteConnection:
+ {
+ CConnMonDeleteConnection* realEvent;
+ realEvent = (CConnMonDeleteConnection*) &aEvent;
+ TUint connectionId = realEvent->ConnectionId();
+
+ QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId);
+ if (ptr) {
+ toSymbianConfig(ptr)->connectionId = 0;
+ // Configuration is either Defined or Discovered
+ if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered))
+ updateStatesToSnaps();
+ }
+
+ bool online = false;
+ foreach (const QString &iface, accessPointConfigurations.keys()) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
+ if (ptr->state == QNetworkConfiguration::Active) {
+ online = true;
+ break;
+ }
+ }
+ if (iOnline != online) {
+ iOnline = online;
+ emit this->onlineStateChanged(iOnline);
+ }
+ }
+ break;
+
+ case EConnMonIapAvailabilityChange:
+ {
+ CConnMonIapAvailabilityChange* realEvent;
+ realEvent = (CConnMonIapAvailabilityChange*) &aEvent;
+ TConnMonIapInfo iaps = realEvent->IapAvailability();
+ QList<QString> unDiscoveredConfigs = accessPointConfigurations.keys();
+ for ( TUint i = 0; i < iaps.Count(); i++ ) {
+ QString ident = QString::number(qHash(iaps.iIap[i].iIapId));
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+ if (ptr) {
+ // Configuration is either Discovered or Active
+ changeConfigurationStateAtMinTo(ptr, QNetworkConfiguration::Discovered);
+ unDiscoveredConfigs.removeOne(ident);
+ }
+ }
+ foreach (const QString &iface, unDiscoveredConfigs) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
+ if (ptr) {
+ // Configuration is Defined
+ changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Defined);
+ }
+ }
+ }
+ break;
+
+ default:
+ // For unrecognized events
+ break;
+ }
+}
+
+QNetworkConfigurationPrivatePointer SymbianEngine::dataByConnectionId(TUint aConnectionId)
+{
+ QNetworkConfiguration item;
+
+ QHash<QString, QNetworkConfigurationPrivatePointer>::const_iterator i =
+ accessPointConfigurations.constBegin();
+ while (i != accessPointConfigurations.constEnd()) {
+ QNetworkConfigurationPrivatePointer ptr = i.value();
+ if (toSymbianConfig(ptr)->connectionId == aConnectionId)
+ return ptr;
+
+ ++i;
+ }
+
+ return QNetworkConfigurationPrivatePointer();
+}
+
+AccessPointsAvailabilityScanner::AccessPointsAvailabilityScanner(SymbianEngine& owner,
+ RConnectionMonitor& connectionMonitor)
+ : CActive(CActive::EPriorityStandard), iOwner(owner), iConnectionMonitor(connectionMonitor)
+{
+ CActiveScheduler::Add(this);
+}
+
+AccessPointsAvailabilityScanner::~AccessPointsAvailabilityScanner()
+{
+ Cancel();
+}
+
+void AccessPointsAvailabilityScanner::DoCancel()
+{
+ iConnectionMonitor.CancelAsyncRequest(EConnMonGetPckgAttribute);
+}
+
+void AccessPointsAvailabilityScanner::StartScanning()
+{
+ iConnectionMonitor.GetPckgAttribute(EBearerIdAll, 0, KIapAvailability, iIapBuf, iStatus);
+ if (!IsActive()) {
+ SetActive();
+ }
+}
+
+void AccessPointsAvailabilityScanner::RunL()
+{
+ if (iStatus.Int() != KErrNone) {
+ iIapBuf().iCount = 0;
+ iOwner.accessPointScanningReady(false,iIapBuf());
+ } else {
+ iOwner.accessPointScanningReady(true,iIapBuf());
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/symbian/symbianengine.h b/src/plugins/bearer/symbian/symbianengine.h
new file mode 100644
index 0000000..587585b
--- /dev/null
+++ b/src/plugins/bearer/symbian/symbianengine.h
@@ -0,0 +1,202 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 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 SYMBIANENGINE_H
+#define SYMBIANENGINE_H
+
+#include <QtNetwork/private/qbearerengine_p.h>
+#include <QtNetwork/qnetworkconfigmanager.h>
+
+#include <QHash>
+#include <rconnmon.h>
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ #include <cmmanager.h>
+#endif
+
+class CCommsDatabase;
+
+QT_BEGIN_NAMESPACE
+class QTimer;
+QT_END_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkSessionPrivate;
+class AccessPointsAvailabilityScanner;
+
+class SymbianNetworkConfigurationPrivate : public QNetworkConfigurationPrivate
+{
+public:
+ enum Bearer {
+ BearerEthernet,
+ BearerWLAN,
+ Bearer2G,
+ BearerCDMA2000,
+ BearerWCDMA,
+ BearerHSPA,
+ BearerBluetooth,
+ BearerWiMAX,
+ BearerUnknown = -1
+ };
+
+ SymbianNetworkConfigurationPrivate();
+ ~SymbianNetworkConfigurationPrivate();
+
+ QString bearerName() const;
+
+ Bearer bearer;
+
+ TUint32 numericId;
+ TUint connectionId;
+
+ QNetworkConfigurationPrivatePointer serviceNetworkPtr;
+
+ QString mappingName;
+};
+
+inline SymbianNetworkConfigurationPrivate *toSymbianConfig(QNetworkConfigurationPrivatePointer ptr)
+{
+ return static_cast<SymbianNetworkConfigurationPrivate *>(ptr.data());
+}
+
+class SymbianEngine : public QBearerEngine, public CActive,
+ public MConnectionMonitorObserver
+{
+ Q_OBJECT
+
+public:
+ SymbianEngine(QObject *parent = 0);
+ virtual ~SymbianEngine();
+
+ bool hasIdentifier(const QString &id);
+
+ void requestUpdate();
+
+ QNetworkConfigurationManager::Capabilities capabilities() const;
+
+ QNetworkSessionPrivate *createSessionBackend();
+
+ QNetworkConfigurationPrivatePointer defaultConfiguration();
+
+Q_SIGNALS:
+ void onlineStateChanged(bool isOnline);
+
+public Q_SLOTS:
+ void updateConfigurations();
+
+private:
+ void updateStatesToSnaps();
+ bool changeConfigurationStateTo(QNetworkConfigurationPrivatePointer ptr,
+ QNetworkConfiguration::StateFlags newState);
+ bool changeConfigurationStateAtMinTo(QNetworkConfigurationPrivatePointer ptr,
+ QNetworkConfiguration::StateFlags newState);
+ bool changeConfigurationStateAtMaxTo(QNetworkConfigurationPrivatePointer ptr,
+ QNetworkConfiguration::StateFlags newState);
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ SymbianNetworkConfigurationPrivate *configFromConnectionMethodL(RCmConnectionMethod& connectionMethod);
+#else
+ bool readNetworkConfigurationValuesFromCommsDb(
+ TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration);
+ void readNetworkConfigurationValuesFromCommsDbL(
+ TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration);
+#endif
+
+ void updateConfigurationsL();
+ void updateActiveAccessPoints();
+ void updateAvailableAccessPoints();
+ void accessPointScanningReady(TBool scanSuccessful, TConnMonIapInfo iapInfo);
+ void startCommsDatabaseNotifications();
+ void stopCommsDatabaseNotifications();
+
+ QNetworkConfigurationPrivatePointer defaultConfigurationL();
+ TBool GetS60PlatformVersion(TUint& aMajor, TUint& aMinor) const;
+ void startMonitoringIAPData(TUint32 aIapId);
+ QNetworkConfigurationPrivatePointer dataByConnectionId(TUint aConnectionId);
+
+protected: // From CActive
+ void RunL();
+ void DoCancel();
+
+private: // MConnectionMonitorObserver
+ void EventL(const CConnMonEventBase& aEvent);
+
+private: // Data
+ CCommsDatabase* ipCommsDB;
+ RConnectionMonitor iConnectionMonitor;
+
+ TBool iWaitingCommsDatabaseNotifications;
+ TBool iOnline;
+ TBool iInitOk;
+ TBool iUpdateGoingOn;
+
+
+ AccessPointsAvailabilityScanner* ipAccessPointsAvailabilityScanner;
+
+ friend class QNetworkSessionPrivate;
+ friend class AccessPointsAvailabilityScanner;
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ RCmManager iCmManager;
+#endif
+};
+
+class AccessPointsAvailabilityScanner : public CActive
+{
+public:
+ AccessPointsAvailabilityScanner(SymbianEngine& owner,
+ RConnectionMonitor& connectionMonitor);
+ ~AccessPointsAvailabilityScanner();
+
+ void StartScanning();
+
+protected: // From CActive
+ void RunL();
+ void DoCancel();
+
+private: // Data
+ SymbianEngine& iOwner;
+ RConnectionMonitor& iConnectionMonitor;
+ TConnMonIapInfoBuf iIapBuf;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index dc2266b..73686bc 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 {