From 0f31f63e11d4fcb2b399979de28368a89275b911 Mon Sep 17 00:00:00 2001 From: Aaron McCarthy Date: Tue, 22 Dec 2009 12:17:58 +1000 Subject: Bearer Management Integration 1. --- config.tests/mac/corelwan/corewlan.pro | 4 + config.tests/mac/corelwan/corewlantest.mm | 49 + config.tests/unix/networkmanager/main.cpp | 47 + .../unix/networkmanager/networkmanager.pro | 11 + examples/network/bearercloud/bearercloud.cpp | 197 ++++ examples/network/bearercloud/bearercloud.h | 81 ++ examples/network/bearercloud/bearercloud.pro | 30 + examples/network/bearercloud/cloud.cpp | 361 ++++++ examples/network/bearercloud/cloud.h | 97 ++ examples/network/bearercloud/icons.qrc | 7 + examples/network/bearercloud/lan.svg | 76 ++ examples/network/bearercloud/main.cpp | 89 ++ examples/network/bearercloud/unknown.svg | 76 ++ examples/network/bearercloud/wlan.svg | 151 +++ examples/network/bearermonitor/bearermonitor.cpp | 395 +++++++ examples/network/bearermonitor/bearermonitor.h | 92 ++ examples/network/bearermonitor/bearermonitor.pro | 32 + .../network/bearermonitor/bearermonitor_240_320.ui | 420 +++++++ .../network/bearermonitor/bearermonitor_640_480.ui | 386 +++++++ examples/network/bearermonitor/main.cpp | 55 + examples/network/bearermonitor/sessionwidget.cpp | 156 +++ examples/network/bearermonitor/sessionwidget.h | 75 ++ examples/network/bearermonitor/sessionwidget.ui | 251 +++++ src/network/bearer/bearer.pro | 163 +++ src/network/bearer/qcorewlanengine_mac.mm | 461 ++++++++ src/network/bearer/qcorewlanengine_mac_p.h | 100 ++ src/network/bearer/qgenericengine.cpp | 234 ++++ src/network/bearer/qgenericengine_p.h | 94 ++ src/network/bearer/qnativewifiengine_win.cpp | 726 ++++++++++++ src/network/bearer/qnativewifiengine_win_p.h | 95 ++ src/network/bearer/qnetworkconfigmanager.cpp | 333 ++++++ src/network/bearer/qnetworkconfigmanager.h | 101 ++ src/network/bearer/qnetworkconfigmanager_maemo.cpp | 760 +++++++++++++ src/network/bearer/qnetworkconfigmanager_maemo_p.h | 141 +++ src/network/bearer/qnetworkconfigmanager_p.cpp | 450 ++++++++ src/network/bearer/qnetworkconfigmanager_p.h | 178 +++ src/network/bearer/qnetworkconfigmanager_s60_p.cpp | 974 ++++++++++++++++ src/network/bearer/qnetworkconfigmanager_s60_p.h | 182 +++ src/network/bearer/qnetworkconfiguration.cpp | 349 ++++++ src/network/bearer/qnetworkconfiguration.h | 113 ++ src/network/bearer/qnetworkconfiguration_maemo_p.h | 109 ++ src/network/bearer/qnetworkconfiguration_p.h | 104 ++ src/network/bearer/qnetworkconfiguration_s60_p.cpp | 60 + src/network/bearer/qnetworkconfiguration_s60_p.h | 108 ++ src/network/bearer/qnetworkmanagerservice_p.cpp | 1011 +++++++++++++++++ src/network/bearer/qnetworkmanagerservice_p.h | 400 +++++++ src/network/bearer/qnetworksession.cpp | 689 ++++++++++++ src/network/bearer/qnetworksession.h | 135 +++ src/network/bearer/qnetworksession_maemo.cpp | 1181 ++++++++++++++++++++ src/network/bearer/qnetworksession_maemo_p.h | 167 +++ src/network/bearer/qnetworksession_p.cpp | 542 +++++++++ src/network/bearer/qnetworksession_p.h | 167 +++ src/network/bearer/qnetworksession_s60_p.cpp | 1168 +++++++++++++++++++ src/network/bearer/qnetworksession_s60_p.h | 213 ++++ src/network/bearer/qnetworksessionengine.cpp | 57 + src/network/bearer/qnetworksessionengine_p.h | 98 ++ src/network/bearer/qnetworksessionengine_win_p.h | 145 +++ src/network/bearer/qnlaengine_win.cpp | 592 ++++++++++ src/network/bearer/qnlaengine_win_p.h | 104 ++ src/network/bearer/qnmdbushelper.cpp | 117 ++ src/network/bearer/qnmdbushelper_p.h | 90 ++ src/network/bearer/qnmwifiengine_unix.cpp | 1133 +++++++++++++++++++ src/network/bearer/qnmwifiengine_unix_p.h | 164 +++ tests/auto/qbearertestcommon.h | 74 ++ .../qnetworkconfigmanager.pro | 15 + .../tst_qnetworkconfigmanager.cpp | 335 ++++++ .../qnetworkconfiguration.pro | 15 + .../tst_qnetworkconfiguration.cpp | 303 +++++ tests/auto/qnetworksession/lackey/lackey.pro | 12 + tests/auto/qnetworksession/lackey/main.cpp | 138 +++ tests/auto/qnetworksession/qnetworksession.pro | 2 + .../tst_qnetworksession/tst_qnetworksession.cpp | 873 +++++++++++++++ .../tst_qnetworksession/tst_qnetworksession.pro | 21 + tests/manual/bearerex/bearerex.cpp | 565 ++++++++++ tests/manual/bearerex/bearerex.h | 138 +++ tests/manual/bearerex/bearerex.pro | 34 + tests/manual/bearerex/bearerex.ui | 95 ++ tests/manual/bearerex/detailedinfodialog.ui | 54 + tests/manual/bearerex/main.cpp | 58 + tests/manual/bearerex/sessiondialog.ui | 139 +++ tests/manual/bearerex/xqlistwidget.cpp | 66 ++ tests/manual/bearerex/xqlistwidget.h | 58 + tests/manual/networkmanager/README | 2 + tests/manual/networkmanager/dialog.ui | 213 ++++ tests/manual/networkmanager/networkmanager.pro | 19 + tests/manual/networkmanager/networkmanagertest.cpp | 287 +++++ tests/manual/networkmanager/nmview.cpp | 1030 +++++++++++++++++ tests/manual/networkmanager/nmview.h | 107 ++ tests/manual/networkmanager/startdlg.cpp | 95 ++ tests/manual/networkmanager/startdlg.h | 58 + 90 files changed, 21952 insertions(+) create mode 100644 config.tests/mac/corelwan/corewlan.pro create mode 100644 config.tests/mac/corelwan/corewlantest.mm create mode 100644 config.tests/unix/networkmanager/main.cpp create mode 100644 config.tests/unix/networkmanager/networkmanager.pro create mode 100644 examples/network/bearercloud/bearercloud.cpp create mode 100644 examples/network/bearercloud/bearercloud.h create mode 100644 examples/network/bearercloud/bearercloud.pro create mode 100644 examples/network/bearercloud/cloud.cpp create mode 100644 examples/network/bearercloud/cloud.h create mode 100644 examples/network/bearercloud/icons.qrc create mode 100644 examples/network/bearercloud/lan.svg create mode 100644 examples/network/bearercloud/main.cpp create mode 100644 examples/network/bearercloud/unknown.svg create mode 100644 examples/network/bearercloud/wlan.svg create mode 100644 examples/network/bearermonitor/bearermonitor.cpp create mode 100644 examples/network/bearermonitor/bearermonitor.h create mode 100644 examples/network/bearermonitor/bearermonitor.pro create mode 100644 examples/network/bearermonitor/bearermonitor_240_320.ui create mode 100644 examples/network/bearermonitor/bearermonitor_640_480.ui create mode 100644 examples/network/bearermonitor/main.cpp create mode 100644 examples/network/bearermonitor/sessionwidget.cpp create mode 100644 examples/network/bearermonitor/sessionwidget.h create mode 100644 examples/network/bearermonitor/sessionwidget.ui create mode 100644 src/network/bearer/bearer.pro create mode 100644 src/network/bearer/qcorewlanengine_mac.mm create mode 100644 src/network/bearer/qcorewlanengine_mac_p.h create mode 100644 src/network/bearer/qgenericengine.cpp create mode 100644 src/network/bearer/qgenericengine_p.h create mode 100644 src/network/bearer/qnativewifiengine_win.cpp create mode 100644 src/network/bearer/qnativewifiengine_win_p.h create mode 100644 src/network/bearer/qnetworkconfigmanager.cpp create mode 100644 src/network/bearer/qnetworkconfigmanager.h create mode 100644 src/network/bearer/qnetworkconfigmanager_maemo.cpp create mode 100644 src/network/bearer/qnetworkconfigmanager_maemo_p.h create mode 100644 src/network/bearer/qnetworkconfigmanager_p.cpp create mode 100644 src/network/bearer/qnetworkconfigmanager_p.h create mode 100644 src/network/bearer/qnetworkconfigmanager_s60_p.cpp create mode 100644 src/network/bearer/qnetworkconfigmanager_s60_p.h create mode 100644 src/network/bearer/qnetworkconfiguration.cpp create mode 100644 src/network/bearer/qnetworkconfiguration.h create mode 100644 src/network/bearer/qnetworkconfiguration_maemo_p.h create mode 100644 src/network/bearer/qnetworkconfiguration_p.h create mode 100644 src/network/bearer/qnetworkconfiguration_s60_p.cpp create mode 100644 src/network/bearer/qnetworkconfiguration_s60_p.h create mode 100644 src/network/bearer/qnetworkmanagerservice_p.cpp create mode 100644 src/network/bearer/qnetworkmanagerservice_p.h create mode 100644 src/network/bearer/qnetworksession.cpp create mode 100644 src/network/bearer/qnetworksession.h create mode 100644 src/network/bearer/qnetworksession_maemo.cpp create mode 100644 src/network/bearer/qnetworksession_maemo_p.h create mode 100644 src/network/bearer/qnetworksession_p.cpp create mode 100644 src/network/bearer/qnetworksession_p.h create mode 100644 src/network/bearer/qnetworksession_s60_p.cpp create mode 100644 src/network/bearer/qnetworksession_s60_p.h create mode 100644 src/network/bearer/qnetworksessionengine.cpp create mode 100644 src/network/bearer/qnetworksessionengine_p.h create mode 100644 src/network/bearer/qnetworksessionengine_win_p.h create mode 100644 src/network/bearer/qnlaengine_win.cpp create mode 100644 src/network/bearer/qnlaengine_win_p.h create mode 100644 src/network/bearer/qnmdbushelper.cpp create mode 100644 src/network/bearer/qnmdbushelper_p.h create mode 100644 src/network/bearer/qnmwifiengine_unix.cpp create mode 100644 src/network/bearer/qnmwifiengine_unix_p.h create mode 100644 tests/auto/qbearertestcommon.h create mode 100644 tests/auto/qnetworkconfigmanager/qnetworkconfigmanager.pro create mode 100644 tests/auto/qnetworkconfigmanager/tst_qnetworkconfigmanager.cpp create mode 100644 tests/auto/qnetworkconfiguration/qnetworkconfiguration.pro create mode 100644 tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp create mode 100644 tests/auto/qnetworksession/lackey/lackey.pro create mode 100644 tests/auto/qnetworksession/lackey/main.cpp create mode 100644 tests/auto/qnetworksession/qnetworksession.pro create mode 100644 tests/auto/qnetworksession/tst_qnetworksession/tst_qnetworksession.cpp create mode 100644 tests/auto/qnetworksession/tst_qnetworksession/tst_qnetworksession.pro create mode 100644 tests/manual/bearerex/bearerex.cpp create mode 100644 tests/manual/bearerex/bearerex.h create mode 100644 tests/manual/bearerex/bearerex.pro create mode 100644 tests/manual/bearerex/bearerex.ui create mode 100644 tests/manual/bearerex/detailedinfodialog.ui create mode 100644 tests/manual/bearerex/main.cpp create mode 100644 tests/manual/bearerex/sessiondialog.ui create mode 100644 tests/manual/bearerex/xqlistwidget.cpp create mode 100644 tests/manual/bearerex/xqlistwidget.h create mode 100644 tests/manual/networkmanager/README create mode 100644 tests/manual/networkmanager/dialog.ui create mode 100644 tests/manual/networkmanager/networkmanager.pro create mode 100644 tests/manual/networkmanager/networkmanagertest.cpp create mode 100644 tests/manual/networkmanager/nmview.cpp create mode 100644 tests/manual/networkmanager/nmview.h create mode 100644 tests/manual/networkmanager/startdlg.cpp create mode 100644 tests/manual/networkmanager/startdlg.h diff --git a/config.tests/mac/corelwan/corewlan.pro b/config.tests/mac/corelwan/corewlan.pro new file mode 100644 index 0000000..54a6c36 --- /dev/null +++ b/config.tests/mac/corelwan/corewlan.pro @@ -0,0 +1,4 @@ +SOURCES=corewlantest.mm +TARGET=corewlan +LIBS += -framework CoreWLAN -framework Foundation +CONFIG-=app_bundle diff --git a/config.tests/mac/corelwan/corewlantest.mm b/config.tests/mac/corelwan/corewlantest.mm new file mode 100644 index 0000000..bcddf44 --- /dev/null +++ b/config.tests/mac/corelwan/corewlantest.mm @@ -0,0 +1,49 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 +#include + +int main() +{ + [CWInterface interfaceWithName:@"en2"]; + return 0; +} diff --git a/config.tests/unix/networkmanager/main.cpp b/config.tests/unix/networkmanager/main.cpp new file mode 100644 index 0000000..6f2bae6 --- /dev/null +++ b/config.tests/unix/networkmanager/main.cpp @@ -0,0 +1,47 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 + +int main(int argc, char** argv) +{ + return 0; +} diff --git a/config.tests/unix/networkmanager/networkmanager.pro b/config.tests/unix/networkmanager/networkmanager.pro new file mode 100644 index 0000000..554f513 --- /dev/null +++ b/config.tests/unix/networkmanager/networkmanager.pro @@ -0,0 +1,11 @@ +###################################################################### +# Automatically generated by qmake (2.01a) Mon Oct 19 12:58:26 2009 +###################################################################### + +TEMPLATE = app +TARGET = +DEPENDPATH += . +INCLUDEPATH += . + +# Input +SOURCES += main.cpp diff --git a/examples/network/bearercloud/bearercloud.cpp b/examples/network/bearercloud/bearercloud.cpp new file mode 100644 index 0000000..182d4ec --- /dev/null +++ b/examples/network/bearercloud/bearercloud.cpp @@ -0,0 +1,197 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 "bearercloud.h" +#include "cloud.h" + +#include +#include +#include +#include + +#include + +#include + +#ifndef M_PI +#define M_PI 3.14159265358979323846 +#endif + +//! [0] +BearerCloud::BearerCloud(QObject *parent) +: QGraphicsScene(parent), timerId(0) +{ + setSceneRect(-300, -300, 600, 600); + + qsrand(QDateTime::currentDateTime().toTime_t()); + + offset[QNetworkConfiguration::Active] = 2 * M_PI * qrand() / RAND_MAX; + offset[QNetworkConfiguration::Discovered] = offset[QNetworkConfiguration::Active] + M_PI / 6; + offset[QNetworkConfiguration::Defined] = offset[QNetworkConfiguration::Discovered] - M_PI / 6; + offset[QNetworkConfiguration::Undefined] = offset[QNetworkConfiguration::Undefined] + M_PI / 6; + + thisDevice = new QGraphicsTextItem(QHostInfo::localHostName()); + thisDevice->setData(0, QLatin1String("This Device")); + thisDevice->setPos(thisDevice->boundingRect().width() / -2, + thisDevice->boundingRect().height() / -2); + addItem(thisDevice); + + qreal radius = Cloud::getRadiusForState(QNetworkConfiguration::Active); + QGraphicsEllipseItem *orbit = new QGraphicsEllipseItem(-radius, -radius, 2*radius, 2*radius); + orbit->setPen(QColor(Qt::green)); + addItem(orbit); + radius = Cloud::getRadiusForState(QNetworkConfiguration::Discovered); + orbit = new QGraphicsEllipseItem(-radius, -radius, 2*radius, 2*radius); + orbit->setPen(QColor(Qt::blue)); + addItem(orbit); + radius = Cloud::getRadiusForState(QNetworkConfiguration::Defined); + orbit = new QGraphicsEllipseItem(-radius, -radius, 2*radius, 2*radius); + orbit->setPen(QColor(Qt::darkGray)); + addItem(orbit); + radius = Cloud::getRadiusForState(QNetworkConfiguration::Undefined); + orbit = new QGraphicsEllipseItem(-radius, -radius, 2*radius, 2*radius); + orbit->setPen(QColor(Qt::lightGray)); + addItem(orbit); + + connect(&manager, SIGNAL(configurationAdded(QNetworkConfiguration)), + this, SLOT(configurationAdded(QNetworkConfiguration))); + connect(&manager, SIGNAL(configurationRemoved(QNetworkConfiguration)), + this, SLOT(configurationRemoved(QNetworkConfiguration))); + connect(&manager, SIGNAL(configurationChanged(QNetworkConfiguration)), + this, SLOT(configurationChanged(QNetworkConfiguration))); + + QTimer::singleShot(0, this, SLOT(updateConfigurations())); +} +//! [0] + +BearerCloud::~BearerCloud() +{ +} + +void BearerCloud::cloudMoved() +{ + if (!timerId) + timerId = startTimer(1000 / 25); +} + +void BearerCloud::timerEvent(QTimerEvent *) +{ + QList clouds; + foreach (QGraphicsItem *item, items()) { + if (Cloud *cloud = qgraphicsitem_cast(item)) + clouds << cloud; + } + + foreach (Cloud *cloud, clouds) + cloud->calculateForces(); + + bool cloudsMoved = false; + foreach (Cloud *cloud, clouds) + cloudsMoved |= cloud->advance(); + + if (!cloudsMoved) { + killTimer(timerId); + timerId = 0; + } +} + +//! [2] +void BearerCloud::configurationAdded(const QNetworkConfiguration &config) +{ + const QNetworkConfiguration::StateFlags state = config.state(); + + configStates.insert(state, config.identifier()); + + const qreal radius = Cloud::getRadiusForState(state); + const int count = configStates.count(state); + const qreal angle = 2 * M_PI / count; + + Cloud *item = new Cloud(config); + configurations.insert(config.identifier(), item); + + item->setPos(radius * cos((count-1) * angle + offset[state]), + radius * sin((count-1) * angle + offset[state])); + + addItem(item); + + cloudMoved(); +} +//! [2] + +//! [3] +void BearerCloud::configurationRemoved(const QNetworkConfiguration &config) +{ + foreach (const QNetworkConfiguration::StateFlags &state, configStates.uniqueKeys()) + configStates.remove(state, config.identifier()); + + Cloud *item = configurations.take(config.identifier()); + + item->setFinalScale(0.0); + item->setDeleteAfterAnimation(true); + + cloudMoved(); +} +//! [3] + +//! [4] +void BearerCloud::configurationChanged(const QNetworkConfiguration &config) +{ + foreach (const QNetworkConfiguration::StateFlags &state, configStates.uniqueKeys()) + configStates.remove(state, config.identifier()); + + configStates.insert(config.state(), config.identifier()); + + cloudMoved(); +} +//! [4] + +//! [1] +void BearerCloud::updateConfigurations() +{ + QList allConfigurations = manager.allConfigurations(); + + while (!allConfigurations.isEmpty()) + configurationAdded(allConfigurations.takeFirst()); + + cloudMoved(); +} +//! [1] + diff --git a/examples/network/bearercloud/bearercloud.h b/examples/network/bearercloud/bearercloud.h new file mode 100644 index 0000000..c18ffd3 --- /dev/null +++ b/examples/network/bearercloud/bearercloud.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 + +#include +#include +#include + +QTM_USE_NAMESPACE + +class Cloud; + +class BearerCloud : public QGraphicsScene +{ + Q_OBJECT + +public: + BearerCloud(QObject *parent = 0); + ~BearerCloud(); + + void cloudMoved(); + + void timerEvent(QTimerEvent *event); + +private Q_SLOTS: + void configurationAdded(const QNetworkConfiguration &config); + void configurationRemoved(const QNetworkConfiguration &config); + void configurationChanged(const QNetworkConfiguration &config); + void updateConfigurations(); + +private: + QNetworkConfigurationManager manager; + + QGraphicsTextItem *thisDevice; + QHash configurations; + + QMap offset; + QMultiMap configStates; + + int timerId; +}; + diff --git a/examples/network/bearercloud/bearercloud.pro b/examples/network/bearercloud/bearercloud.pro new file mode 100644 index 0000000..308ddda --- /dev/null +++ b/examples/network/bearercloud/bearercloud.pro @@ -0,0 +1,30 @@ +HEADERS = bearercloud.h \ + cloud.h + +SOURCES = main.cpp \ + bearercloud.cpp \ + cloud.cpp + +RESOURCES = icons.qrc + +TARGET = bearercloud + +QT = core gui network svg + +INCLUDEPATH += ../../src/bearer + +include(../examples.pri) + +qtAddLibrary(QtBearer) + +CONFIG += console + +include(../examples.pri) + + +macx: { + contains(QT_CONFIG,qt_framework):LIBS += -framework QtBearer + INCLUDEPATH += ../../ + contains(CONFIG, debug) { + } +} diff --git a/examples/network/bearercloud/cloud.cpp b/examples/network/bearercloud/cloud.cpp new file mode 100644 index 0000000..4a1bde7 --- /dev/null +++ b/examples/network/bearercloud/cloud.cpp @@ -0,0 +1,361 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 "cloud.h" +#include "bearercloud.h" + +#include + +#include +#include +#include +#include +#include + +#include + +#include + +static QMap svgCache; + +//! [0] +Cloud::Cloud(const QNetworkConfiguration &config, QGraphicsItem *parent) +: QGraphicsItem(parent), configuration(config), deleteAfterAnimation(false) +{ + session = new QNetworkSession(configuration, this); + connect(session, SIGNAL(newConfigurationActivated()), + this, SLOT(newConfigurationActivated())); + connect(session, SIGNAL(stateChanged(QNetworkSession::State)), + this, SLOT(stateChanged(QNetworkSession::State))); + + setFlag(ItemIsMovable); +#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 0)) + setFlag(ItemSendsGeometryChanges); +#endif + setZValue(1); + + icon = new QGraphicsSvgItem(this); + text = new QGraphicsTextItem(this); + + currentScale = 0; + finalScale = 1; + setTransform(QTransform::fromScale(currentScale, currentScale), false); + setOpacity(0); + + newConfigurationActivated(); +} +//! [0] + +Cloud::~Cloud() +{ +} + +void Cloud::setFinalScale(qreal factor) +{ + finalScale = factor; +} + +void Cloud::setDeleteAfterAnimation(bool deleteAfter) +{ + deleteAfterAnimation = deleteAfter; +} + +void Cloud::calculateForces() +{ + if (!scene() || scene()->mouseGrabberItem() == this) { + newPos = pos(); + return; + } + + // sum up all the forces push this item away + qreal xvel = 0; + qreal yvel = 0; + QLineF orbitForce; + foreach (QGraphicsItem *item, scene()->items()) { + // other clouds + Cloud *cloud = qgraphicsitem_cast(item); + if (!cloud && item->data(0) != QLatin1String("This Device")) + continue; + + qreal factor = 1.0; + + QLineF line(cloud ? item->mapToScene(0, 0) : QPointF(0, 0), mapToScene(0, 0)); + if (item->data(0) == QLatin1String("This Device")) + orbitForce = line; + + if (cloud) + factor = cloud->currentScale; + + qreal dx = line.dx(); + qreal dy = line.dy(); + double l = 2.0 * (dx * dx + dy * dy); + if (l > 0) { + xvel += factor * dx * 200.0 / l; + yvel += factor * dy * 200.0 / l; + } + } + + // tendency to stay at a fixed orbit + qreal orbit = getRadiusForState(configuration.state()); + qreal distance = orbitForce.length(); + + QLineF unit = orbitForce.unitVector(); + + orbitForce.setLength(xvel * unit.dx() + yvel * unit.dy()); + + qreal w = 2 - exp(-pow(distance-orbit, 2)/(2 * 50)); + + if (distance < orbit) { + xvel += orbitForce.dx() * w; + yvel += orbitForce.dy() * w; + } else { + xvel -= orbitForce.dx() * w; + yvel -= orbitForce.dy() * w; + } + + if (qAbs(xvel) < 0.1 && qAbs(yvel) < 0.1) + xvel = yvel = 0; + + QRectF sceneRect = scene()->sceneRect(); + newPos = pos() + QPointF(xvel, yvel); + newPos.setX(qMin(qMax(newPos.x(), sceneRect.left() + 10), sceneRect.right() - 10)); + newPos.setY(qMin(qMax(newPos.y(), sceneRect.top() + 10), sceneRect.bottom() - 10)); +} + +bool Cloud::advance() +{ + static const qreal scaleDelta = 0.01; + + bool animated = false; + + if (currentScale < finalScale) { + animated = true; + currentScale = qMin(currentScale + scaleDelta, finalScale); + setTransform(QTransform::fromScale(currentScale, currentScale), false); + } else if (currentScale > finalScale) { + animated = true; + currentScale = qMax(currentScale - scaleDelta, finalScale); + setTransform(QTransform::fromScale(currentScale, currentScale), false); + } + + if (newPos != pos()) { + setPos(newPos); + animated = true; + } + + if (opacity() != finalOpacity) { + animated = true; + if (qAbs(finalScale - currentScale) > 0.0) { + // use scale as reference + setOpacity(opacity() + scaleDelta * (finalOpacity - opacity()) / + qAbs(finalScale - currentScale)); + } else { + setOpacity(finalOpacity); + } + } + + if (!animated && deleteAfterAnimation) + deleteLater(); + + return animated; +} + +QRectF Cloud::boundingRect() const +{ + return childrenBoundingRect(); +} + +void Cloud::paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *) +{ +} + +//! [4] +QVariant Cloud::itemChange(GraphicsItemChange change, const QVariant &value) +{ + switch (change) { + case ItemPositionHasChanged: + if (BearerCloud *bearercloud = qobject_cast(scene())) + bearercloud->cloudMoved(); + default: + ; + }; + + return QGraphicsItem::itemChange(change, value); +} +//! [4] + +//! [3] +void Cloud::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event) +{ + if (event->button() == Qt::LeftButton) { + if (session->isActive()) + session->close(); + else + session->open(); + + event->accept(); + } +} +//! [3] + +//! [2] +void Cloud::stateChanged(QNetworkSession::State state) +{ + if (configuration.name().isEmpty()) + finalOpacity = qreal(0.1); + else if (session->state() == QNetworkSession::NotAvailable) + finalOpacity = 0.5; + else + finalOpacity = 1.0; + + QString tooltip; + + if (configuration.name().isEmpty()) + tooltip += tr("HIDDEN NETWORK
"); + else + tooltip += tr("%1
").arg(configuration.name()); + + const QNetworkInterface interface = session->interface(); + if (interface.isValid()) + tooltip += tr("
Interface: %1").arg(interface.humanReadableName()); + tooltip += tr("
Id: %1").arg(configuration.identifier()); + + const QString bearerName = session->bearerName(); + if (!bearerName.isEmpty()) + tooltip += tr("
Bearer: %1").arg(bearerName); + + QString s = tr("
State: %1 (%2)"); + switch (state) { + case QNetworkSession::Invalid: + s = s.arg(tr("Invalid")); + break; + case QNetworkSession::NotAvailable: + s = s.arg(tr("Not Available")); + break; + case QNetworkSession::Connecting: + s = s.arg(tr("Connecting")); + break; + case QNetworkSession::Connected: + s = s.arg(tr("Connected")); + break; + case QNetworkSession::Closing: + s = s.arg(tr("Closing")); + break; + case QNetworkSession::Disconnected: + s = s.arg(tr("Disconnected")); + break; + case QNetworkSession::Roaming: + s = s.arg(tr("Roaming")); + break; + default: + s = s.arg(tr("Unknown")); + } + + if (session->isActive()) + s = s.arg(tr("Active")); + else + s = s.arg(tr("Inactive")); + + tooltip += s; + + tooltip += tr("

Active time: %1 seconds").arg(session->activeTime()); + tooltip += tr("
Received data: %1 bytes").arg(session->bytesReceived()); + tooltip += tr("
Sent data: %1 bytes").arg(session->bytesWritten()); + + setToolTip(tooltip); +} +//! [2] + +//! [1] +void Cloud::newConfigurationActivated() +{ + const QString bearerName = session->bearerName(); + if (!svgCache.contains(bearerName)) { + if (bearerName == QLatin1String("WLAN")) + svgCache.insert(bearerName, new QSvgRenderer(QLatin1String(":wlan.svg"))); + else if (bearerName == QLatin1String("Ethernet")) + svgCache.insert(bearerName, new QSvgRenderer(QLatin1String(":lan.svg"))); + else + svgCache.insert(bearerName, new QSvgRenderer(QLatin1String(":unknown.svg"))); + } + + icon->setSharedRenderer(svgCache[bearerName]); + + if (configuration.name().isEmpty()) { + text->setPlainText(tr("HIDDEN NETWORK")); + } else { + if (configuration.type() == QNetworkConfiguration::ServiceNetwork) + text->setHtml("" + configuration.name() + ""); + else + text->setPlainText(configuration.name()); + } + + const qreal height = icon->boundingRect().height() + text->boundingRect().height(); + + icon->setPos(icon->boundingRect().width() / -2, height / -2); + + text->setPos(text->boundingRect().width() / -2, + height / 2 - text->boundingRect().height()); + + stateChanged(session->state()); +} +//! [1] + +qreal Cloud::getRadiusForState(QNetworkConfiguration::StateFlags state) +{ + switch (state) { + case QNetworkConfiguration::Active: + return 100; + break; + case QNetworkConfiguration::Discovered: + return 150; + break; + case QNetworkConfiguration::Defined: + return 200; + break; + case QNetworkConfiguration::Undefined: + return 250; + break; + default: + return 300; + } +} + diff --git a/examples/network/bearercloud/cloud.h b/examples/network/bearercloud/cloud.h new file mode 100644 index 0000000..4ce43df --- /dev/null +++ b/examples/network/bearercloud/cloud.h @@ -0,0 +1,97 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 +#include + +#include +QTM_USE_NAMESPACE + +class QGraphicsTextItem; +class QGraphicsSvgItem; + +class Cloud : public QObject, public QGraphicsItem +{ + Q_OBJECT + Q_INTERFACES(QGraphicsItem) + +public: + Cloud(const QNetworkConfiguration &config, QGraphicsItem *parent = 0); + ~Cloud(); + + enum { Type = UserType + 1 }; + int type() const { return Type; } + + void setFinalScale(qreal factor); + void setDeleteAfterAnimation(bool deleteAfter); + + void calculateForces(); + + bool advance(); + QRectF boundingRect() const; + void paint(QPainter *, const QStyleOptionGraphicsItem *, QWidget *); + + static qreal getRadiusForState(QNetworkConfiguration::StateFlags state); + +protected: + QVariant itemChange(GraphicsItemChange change, const QVariant &value); + void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); + +private Q_SLOTS: + void stateChanged(QNetworkSession::State state); + void newConfigurationActivated(); + +private: + QNetworkConfiguration configuration; + QNetworkSession *session; + + QGraphicsTextItem *text; + QGraphicsSvgItem *icon; + + qreal finalOpacity; + qreal finalScale; + qreal currentScale; + + QPointF newPos; + + bool deleteAfterAnimation; +}; + diff --git a/examples/network/bearercloud/icons.qrc b/examples/network/bearercloud/icons.qrc new file mode 100644 index 0000000..84a8939 --- /dev/null +++ b/examples/network/bearercloud/icons.qrc @@ -0,0 +1,7 @@ + + + wlan.svg + lan.svg + unknown.svg + + diff --git a/examples/network/bearercloud/lan.svg b/examples/network/bearercloud/lan.svg new file mode 100644 index 0000000..3cce805 --- /dev/null +++ b/examples/network/bearercloud/lan.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + image/svg+xml + + + + + + LAN + + diff --git a/examples/network/bearercloud/main.cpp b/examples/network/bearercloud/main.cpp new file mode 100644 index 0000000..33c55e9 --- /dev/null +++ b/examples/network/bearercloud/main.cpp @@ -0,0 +1,89 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 "bearercloud.h" + +#include +#include + +class CloudView : public QGraphicsView +{ + Q_OBJECT + +public: + CloudView(QGraphicsScene *scene); + ~CloudView() { } + +protected: + void resizeEvent(QResizeEvent *) { + fitInView(sceneRect(), Qt::KeepAspectRatio); + } +#ifdef Q_OS_WINCE + void hideEvent(QHideEvent *) { + qApp->quit(); + } +#endif +}; + +CloudView::CloudView(QGraphicsScene *scene) +: QGraphicsView(scene) +{ + setRenderHints(QPainter::TextAntialiasing | QPainter::Antialiasing | + QPainter::SmoothPixmapTransform); +#if defined (Q_OS_SYMBIAN) || defined (Q_OS_WINCE) + setWindowState(Qt::WindowMaximized); +#endif +} + +#include "main.moc" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + BearerCloud bearerCloud; + + CloudView view(&bearerCloud); + view.show(); + + return app.exec(); +} + diff --git a/examples/network/bearercloud/unknown.svg b/examples/network/bearercloud/unknown.svg new file mode 100644 index 0000000..fd10298 --- /dev/null +++ b/examples/network/bearercloud/unknown.svg @@ -0,0 +1,76 @@ + + + + + + + + + + + image/svg+xml + + + + + + NET + + diff --git a/examples/network/bearercloud/wlan.svg b/examples/network/bearercloud/wlan.svg new file mode 100644 index 0000000..8b86089 --- /dev/null +++ b/examples/network/bearercloud/wlan.svg @@ -0,0 +1,151 @@ + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + diff --git a/examples/network/bearermonitor/bearermonitor.cpp b/examples/network/bearermonitor/bearermonitor.cpp new file mode 100644 index 0000000..70c8269 --- /dev/null +++ b/examples/network/bearermonitor/bearermonitor.cpp @@ -0,0 +1,395 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 "bearermonitor.h" +#include "sessionwidget.h" + +#include + +#ifdef Q_OS_WIN +#include +#undef interface + +#ifndef NS_NLA +#define NS_NLA 15 +#endif +#endif + +BearerMonitor::BearerMonitor(QWidget *parent) +: QWidget(parent) +{ + setupUi(this); + delete tabWidget->currentWidget(); + sessionGroup->hide(); +#if defined (Q_OS_SYMBIAN) || defined(Q_OS_WINCE) + setWindowState(Qt::WindowMaximized); +#endif + updateConfigurations(); + + onlineStateChanged(!manager.allConfigurations(QNetworkConfiguration::Active).isEmpty()); + + QNetworkConfiguration defaultConfiguration = manager.defaultConfiguration(); + for (int i = 0; i < treeWidget->topLevelItemCount(); ++i) { + QTreeWidgetItem *item = treeWidget->topLevelItem(i); + + if (item->data(0, Qt::UserRole).toString() == defaultConfiguration.identifier()) { + treeWidget->setCurrentItem(item); + showConfigurationFor(item); + break; + } + } + + connect(&manager, SIGNAL(configurationAdded(const QNetworkConfiguration&)), + this, SLOT(configurationAdded(const QNetworkConfiguration&))); + connect(&manager, SIGNAL(configurationRemoved(const QNetworkConfiguration&)), + this, SLOT(configurationRemoved(const QNetworkConfiguration&))); + connect(&manager, SIGNAL(configurationChanged(const QNetworkConfiguration&)), + this, SLOT(configurationChanged(const QNetworkConfiguration))); + connect(&manager, SIGNAL(updateCompleted()), this, SLOT(updateConfigurations())); + connect(&manager, SIGNAL(onlineStateChanged(bool)), this ,SLOT(onlineStateChanged(bool))); + +#ifdef Q_OS_WIN + connect(registerButton, SIGNAL(clicked()), this, SLOT(registerNetwork())); + connect(unregisterButton, SIGNAL(clicked()), this, SLOT(unregisterNetwork())); +#else + nlaGroup->hide(); +#endif + + connect(treeWidget, SIGNAL(itemActivated(QTreeWidgetItem*,int)), + this, SLOT(createSessionFor(QTreeWidgetItem*))); + + connect(treeWidget, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)), + this, SLOT(showConfigurationFor(QTreeWidgetItem*))); + + connect(newSessionButton, SIGNAL(clicked()), + this, SLOT(createNewSession())); + connect(deleteSessionButton, SIGNAL(clicked()), + this, SLOT(deleteSession())); + + connect(scanButton, SIGNAL(clicked()), + this, SLOT(performScan())); +} + +BearerMonitor::~BearerMonitor() +{ +} + +static void updateItem(QTreeWidgetItem *item, const QNetworkConfiguration &config) +{ + item->setText(0, config.name()); + item->setData(0, Qt::UserRole, config.identifier()); + + QFont font = item->font(1); + font.setBold((config.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active); + item->setFont(0, font); +} + +void BearerMonitor::configurationAdded(const QNetworkConfiguration &config, QTreeWidgetItem *parent) +{ + QTreeWidgetItem *item = new QTreeWidgetItem; + updateItem(item, config); + + if (parent) + parent->addChild(item); + else + treeWidget->addTopLevelItem(item); + + if (config.type() == QNetworkConfiguration::ServiceNetwork) { + foreach (const QNetworkConfiguration &child, config.children()) + configurationAdded(child, item); + } +} + +void BearerMonitor::configurationRemoved(const QNetworkConfiguration &config) +{ + for (int i = 0; i < treeWidget->topLevelItemCount(); ++i) { + QTreeWidgetItem *item = treeWidget->topLevelItem(i); + + if (item->data(0, Qt::UserRole).toString() == config.identifier()) { + delete item; + break; + } + } +} + +void BearerMonitor::configurationChanged(const QNetworkConfiguration &config) +{ + for (int i = 0; i < treeWidget->topLevelItemCount(); ++i) { + QTreeWidgetItem *item = treeWidget->topLevelItem(i); + + if (item->data(0, Qt::UserRole).toString() == config.identifier()) { + updateItem(item, config); + + if (config.type() == QNetworkConfiguration::ServiceNetwork) + updateSnapConfiguration(item, config); + + if (item == treeWidget->currentItem()) + showConfigurationFor(item); + + break; + } + } +} + +void BearerMonitor::updateSnapConfiguration(QTreeWidgetItem *parent, const QNetworkConfiguration &snap) +{ + QMap itemMap; + for (int i = 0; i < parent->childCount(); ++i) { + QTreeWidgetItem *item = parent->child(i); + itemMap.insert(item->data(0, Qt::UserRole).toString(), item); + } + + QList allConfigurations = snap.children(); + + while (!allConfigurations.isEmpty()) { + QNetworkConfiguration config = allConfigurations.takeFirst(); + + QTreeWidgetItem *item = itemMap.take(config.identifier()); + if (item) { + updateItem(item, config); + + if (config.type() == QNetworkConfiguration::ServiceNetwork) + updateSnapConfiguration(item, config); + } else { + configurationAdded(config, parent); + } + } + + foreach (const QString &id, itemMap.keys()) + delete itemMap.value(id); + + itemMap.clear(); +} + +void BearerMonitor::updateConfigurations() +{ + progressBar->hide(); + scanButton->show(); + + QList items = treeWidget->findItems(QLatin1String("*"), Qt::MatchWildcard); + QMap itemMap; + while (!items.isEmpty()) { + QTreeWidgetItem *item = items.takeFirst(); + itemMap.insert(item->data(0, Qt::UserRole).toString(), item); + } + + QList allConfigurations = manager.allConfigurations(); + + while (!allConfigurations.isEmpty()) { + QNetworkConfiguration config = allConfigurations.takeFirst(); + + QTreeWidgetItem *item = itemMap.take(config.identifier()); + if (item) { + updateItem(item, config); + + if (config.type() == QNetworkConfiguration::ServiceNetwork) + updateSnapConfiguration(item, config); + } else { + configurationAdded(config); + } + } + + foreach (const QString &id, itemMap.keys()) + delete itemMap.value(id); +} + +void BearerMonitor::onlineStateChanged(bool isOnline) +{ + if (isOnline) + onlineState->setText(tr("Online")); + else + onlineState->setText(tr("Offline")); +} + +#ifdef Q_OS_WIN +void BearerMonitor::registerNetwork() +{ + QTreeWidgetItem *item = treeWidget->currentItem(); + + QNetworkConfiguration configuration = + manager.configurationFromIdentifier(item->data(0, Qt::UserRole).toString()); + + const QString name = configuration.name(); + + qDebug() << "Registering" << name << "with system"; + + WSAQUERYSET networkInfo; + memset(&networkInfo, 0, sizeof(networkInfo)); + networkInfo.dwSize = sizeof(networkInfo); + networkInfo.lpszServiceInstanceName = (LPWSTR)name.utf16(); + networkInfo.dwNameSpace = NS_NLA; + + if (WSASetService(&networkInfo, RNRSERVICE_REGISTER, 0) == SOCKET_ERROR) + qDebug() << "WSASetService(RNRSERVICE_REGISTER) returned" << WSAGetLastError(); +} + +void BearerMonitor::unregisterNetwork() +{ + QTreeWidgetItem *item = treeWidget->currentItem(); + + QNetworkConfiguration configuration = + manager.configurationFromIdentifier(item->data(0, Qt::UserRole).toString()); + + const QString name = configuration.name(); + + qDebug() << "Unregistering" << name << "with system"; + + WSAQUERYSET networkInfo; + memset(&networkInfo, 0, sizeof(networkInfo)); + networkInfo.dwSize = sizeof(networkInfo); + networkInfo.lpszServiceInstanceName = (LPWSTR)name.utf16(); + networkInfo.dwNameSpace = NS_NLA; + + if (WSASetService(&networkInfo, RNRSERVICE_DELETE, 0) == SOCKET_ERROR) + qDebug() << "WSASetService(RNRSERVICE_DELETE) returned" << WSAGetLastError(); +} +#endif + +void BearerMonitor::showConfigurationFor(QTreeWidgetItem *item) +{ + QString identifier; + + if (item) + identifier = item->data(0, Qt::UserRole).toString(); + + QNetworkConfiguration conf = manager.configurationFromIdentifier(identifier); + + switch (conf.state()) { + case QNetworkConfiguration::Active: + configurationState->setText(tr("Active")); + break; + case QNetworkConfiguration::Discovered: + configurationState->setText(tr("Discovered")); + break; + case QNetworkConfiguration::Defined: + configurationState->setText(tr("Defined")); + break; + case QNetworkConfiguration::Undefined: + configurationState->setText(tr("Undefined")); + break; + default: + configurationState->setText(QString()); + } + + switch (conf.type()) { + case QNetworkConfiguration::InternetAccessPoint: + configurationType->setText(tr("Internet Access Point")); + break; + case QNetworkConfiguration::ServiceNetwork: + configurationType->setText(tr("Service Network")); + break; + case QNetworkConfiguration::UserChoice: + configurationType->setText(tr("User Choice")); + break; + case QNetworkConfiguration::Invalid: + configurationType->setText(tr("Invalid")); + break; + default: + configurationType->setText(QString()); + } + + switch (conf.purpose()) { + case QNetworkConfiguration::UnknownPurpose: + configurationPurpose->setText(tr("Unknown")); + break; + case QNetworkConfiguration::PublicPurpose: + configurationPurpose->setText(tr("Public")); + break; + case QNetworkConfiguration::PrivatePurpose: + configurationPurpose->setText(tr("Private")); + break; + case QNetworkConfiguration::ServiceSpecificPurpose: + configurationPurpose->setText(tr("Service Specific")); + break; + default: + configurationPurpose->setText(QString()); + } + + configurationIdentifier->setText(conf.identifier()); + + configurationRoaming->setText(conf.isRoamingAvailable() ? tr("Available") : tr("Not available")); + + configurationChildren->setText(QString::number(conf.children().count())); + + configurationName->setText(conf.name()); +} + +void BearerMonitor::createSessionFor(QTreeWidgetItem *item) +{ + const QString identifier = item->data(0, Qt::UserRole).toString(); + + QNetworkConfiguration conf = manager.configurationFromIdentifier(identifier); + + SessionWidget *session = new SessionWidget(conf); + + tabWidget->addTab(session, conf.name()); + + sessionGroup->show(); + + sessionWidgets.append(session); +} + +void BearerMonitor::createNewSession() +{ + QTreeWidgetItem *item = treeWidget->currentItem(); + + createSessionFor(item); +} + +void BearerMonitor::deleteSession() +{ + SessionWidget *session = qobject_cast(tabWidget->currentWidget()); + if (session) { + sessionWidgets.removeAll(session); + + delete session; + + if (tabWidget->count() == 0) + sessionGroup->hide(); + } +} + +void BearerMonitor::performScan() +{ + scanButton->hide(); + progressBar->show(); + manager.updateConfigurations(); +} diff --git a/examples/network/bearermonitor/bearermonitor.h b/examples/network/bearermonitor/bearermonitor.h new file mode 100644 index 0000000..d1f4601 --- /dev/null +++ b/examples/network/bearermonitor/bearermonitor.h @@ -0,0 +1,92 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 BEARERMONITOR_H +#define BEARERMONITOR_H + +#include +#include +#if defined (Q_OS_SYMBIAN) || defined(Q_OS_WINCE) +#include "ui_bearermonitor_240_320.h" +#else +#include "ui_bearermonitor_640_480.h" +#endif + +QTM_USE_NAMESPACE + +class SessionWidget; + +class BearerMonitor : public QWidget, public Ui_BearerMonitor +{ + Q_OBJECT + +public: + BearerMonitor(QWidget *parent = 0); + ~BearerMonitor(); + +private slots: + void configurationAdded(const QNetworkConfiguration &config, QTreeWidgetItem *parent = 0); + void configurationRemoved(const QNetworkConfiguration &config); + void configurationChanged(const QNetworkConfiguration &config); + void updateSnapConfiguration(QTreeWidgetItem *parent, const QNetworkConfiguration &snap); + void updateConfigurations(); + + void onlineStateChanged(bool isOnline); + +#ifdef Q_OS_WIN + void registerNetwork(); + void unregisterNetwork(); +#endif + + void showConfigurationFor(QTreeWidgetItem *item); + + void createSessionFor(QTreeWidgetItem *item); + void createNewSession(); + void deleteSession(); + + void performScan(); + +private: + QNetworkConfigurationManager manager; + QList sessionWidgets; +}; + +#endif //BEARERMONITOR_H diff --git a/examples/network/bearermonitor/bearermonitor.pro b/examples/network/bearermonitor/bearermonitor.pro new file mode 100644 index 0000000..c8fb3c2 --- /dev/null +++ b/examples/network/bearermonitor/bearermonitor.pro @@ -0,0 +1,32 @@ +HEADERS = sessionwidget.h \ + bearermonitor.h + +SOURCES = main.cpp \ + bearermonitor.cpp \ + sessionwidget.cpp + +FORMS = bearermonitor_240_320.ui \ + bearermonitor_640_480.ui \ + sessionwidget.ui + +TARGET = bearermonitor + +QT = core gui network + +INCLUDEPATH += ../../src/bearer + +include(../examples.pri) + +qtAddLibrary(QtBearer) +win32:!wince*:LIBS += -lWs2_32 +wince*:LIBS += -lWs2 + +CONFIG += console + +include(../examples.pri) + +macx: { + contains(QT_CONFIG,qt_framework):LIBS += -framework QtBearer + contains(CONFIG, debug) { + } +} diff --git a/examples/network/bearermonitor/bearermonitor_240_320.ui b/examples/network/bearermonitor/bearermonitor_240_320.ui new file mode 100644 index 0000000..ce9c2d1 --- /dev/null +++ b/examples/network/bearermonitor/bearermonitor_240_320.ui @@ -0,0 +1,420 @@ + + + BearerMonitor + + + + 0 + 0 + 240 + 320 + + + + Form + + + + + + QFrame::NoFrame + + + QFrame::Plain + + + true + + + + + 0 + -274 + 206 + 576 + + + + + + + System State + + + true + + + + 0 + + + 0 + + + 0 + + + + + + + Online State: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + + Configurations + + + true + + + + 0 + + + 0 + + + 0 + + + + + + + + + Name: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + State: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Type: + + + + + + + + 0 + 0 + + + + Invalid + + + + + + + + + + + Purpose: + + + + + + + + 0 + 0 + + + + Unknown + + + + + + + + + + + Identifier: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Roaming: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Children: + + + + + + + + 0 + 0 + + + + + + + + + + + + + Network Location Awareness + + + + + + Register + + + + + + + Unregister + + + + + + + + + + New Session + + + + + + + Delete Session + + + + + + + Scan + + + + + + + 0 + + + -1 + + + false + + + false + + + %p% + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 0 + + + + Qt::ScrollBarAlwaysOff + + + false + + + + 1 + + + + + + + + + + + + + Sessions + + + true + + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + 0 + + + + Session 1 + + + + + + + + + + + + + + + + diff --git a/examples/network/bearermonitor/bearermonitor_640_480.ui b/examples/network/bearermonitor/bearermonitor_640_480.ui new file mode 100644 index 0000000..941eaa0 --- /dev/null +++ b/examples/network/bearermonitor/bearermonitor_640_480.ui @@ -0,0 +1,386 @@ + + + BearerMonitor + + + + 0 + 0 + 640 + 515 + + + + Form + + + + + + System State + + + true + + + + 0 + + + 0 + + + 0 + + + + + + + Online State: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + + Configurations + + + true + + + + 0 + + + 0 + + + 0 + + + + + false + + + + 1 + + + + + + + + + + + + Name: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + State: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Type: + + + + + + + + 0 + 0 + + + + Invalid + + + + + + + + + + + Purpose: + + + + + + + + 0 + 0 + + + + Unknown + + + + + + + + + + + Identifier: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Roaming: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Children: + + + + + + + + 0 + 0 + + + + + + + + + + + + + Network Location Awareness + + + + + + Register + + + + + + + Unregister + + + + + + + + + + New Session + + + + + + + Delete Session + + + + + + + Scan + + + + + + + 0 + + + -1 + + + false + + + false + + + %p% + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + + + + + Sessions + + + true + + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + 0 + + + + Session 1 + + + + + + + + + + + + diff --git a/examples/network/bearermonitor/main.cpp b/examples/network/bearermonitor/main.cpp new file mode 100644 index 0000000..9685181 --- /dev/null +++ b/examples/network/bearermonitor/main.cpp @@ -0,0 +1,55 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 + +#include "bearermonitor.h" + +int main(int argc, char *argv[]) +{ + QApplication app(argc, argv); + + BearerMonitor monitor; + monitor.show(); + + return app.exec(); +} + diff --git a/examples/network/bearermonitor/sessionwidget.cpp b/examples/network/bearermonitor/sessionwidget.cpp new file mode 100644 index 0000000..7633dd7 --- /dev/null +++ b/examples/network/bearermonitor/sessionwidget.cpp @@ -0,0 +1,156 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 "sessionwidget.h" + +SessionWidget::SessionWidget(const QNetworkConfiguration &config, QWidget *parent) +: QWidget(parent) +{ + setupUi(this); + + session = new QNetworkSession(config, this); + + connect(session, SIGNAL(stateChanged(QNetworkSession::State)), + this, SLOT(updateSession())); + connect(session, SIGNAL(error(QNetworkSession::SessionError)), + this, SLOT(updateSession())); + + updateSession(); + + sessionId->setText(QString("0x%1").arg(qulonglong(session), 8, 16, QChar('0'))); + + configuration->setText(session->configuration().name()); + + connect(openSessionButton, SIGNAL(clicked()), + this, SLOT(openSession())); + connect(openSyncSessionButton, SIGNAL(clicked()), + this, SLOT(openSyncSession())); + connect(closeSessionButton, SIGNAL(clicked()), + this, SLOT(closeSession())); + connect(stopSessionButton, SIGNAL(clicked()), + this, SLOT(stopSession())); +} + +SessionWidget::~SessionWidget() +{ + delete session; +} + +void SessionWidget::updateSession() +{ + updateSessionState(session->state()); + updateSessionError(session->error()); + + bearer->setText(session->bearerName()); + + interfaceName->setText(session->interface().humanReadableName()); + interfaceGuid->setText(session->interface().name()); +} + +void SessionWidget::openSession() +{ + session->open(); + updateSession(); +} + +void SessionWidget::openSyncSession() +{ + session->open(); + session->waitForOpened(); + updateSession(); +} + +void SessionWidget::closeSession() +{ + session->close(); + updateSession(); +} + +void SessionWidget::stopSession() +{ + session->stop(); + updateSession(); +} + +void SessionWidget::updateSessionState(QNetworkSession::State state) +{ + QString s = tr("%1 (%2)"); + + switch (state) { + case QNetworkSession::Invalid: + s = s.arg(tr("Invalid")); + break; + case QNetworkSession::NotAvailable: + s = s.arg(tr("Not Available")); + break; + case QNetworkSession::Connecting: + s = s.arg(tr("Connecting")); + break; + case QNetworkSession::Connected: + s = s.arg(tr("Connected")); + break; + case QNetworkSession::Closing: + s = s.arg(tr("Closing")); + break; + case QNetworkSession::Disconnected: + s = s.arg(tr("Disconnected")); + break; + case QNetworkSession::Roaming: + s = s.arg(tr("Roaming")); + break; + default: + s = s.arg(tr("Unknown")); + } + + if (session->isActive()) + s = s.arg(tr("Active")); + else + s = s.arg(tr("Inactive")); + + sessionState->setText(s); +} + +void SessionWidget::updateSessionError(QNetworkSession::SessionError error) +{ + lastError->setText(QString::number(error)); + errorString->setText(session->errorString()); +} + diff --git a/examples/network/bearermonitor/sessionwidget.h b/examples/network/bearermonitor/sessionwidget.h new file mode 100644 index 0000000..cb6591e --- /dev/null +++ b/examples/network/bearermonitor/sessionwidget.h @@ -0,0 +1,75 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 SESSIONWIDGET_H +#define SESSIONWIDGET_H + +#include "ui_sessionwidget.h" + +#include + +QTM_USE_NAMESPACE + +class SessionWidget : public QWidget, public Ui_SessionWidget +{ + Q_OBJECT + +public: + SessionWidget(const QNetworkConfiguration &config, QWidget *parent = 0); + ~SessionWidget(); + +private: + void updateSessionState(QNetworkSession::State state); + void updateSessionError(QNetworkSession::SessionError error); + +private Q_SLOTS: + void openSession(); + void openSyncSession(); + void closeSession(); + void stopSession(); + void updateSession(); + +private: + QNetworkSession *session; +}; + +#endif + diff --git a/examples/network/bearermonitor/sessionwidget.ui b/examples/network/bearermonitor/sessionwidget.ui new file mode 100644 index 0000000..f02f306 --- /dev/null +++ b/examples/network/bearermonitor/sessionwidget.ui @@ -0,0 +1,251 @@ + + + SessionWidget + + + + 0 + 0 + 340 + 220 + + + + Form + + + + + + + + Session ID: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + + 0 + 0 + + + + Session State: + + + + + + + + 0 + 0 + + + + Invalid + + + + + + + + + + + Configuration: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Bearer: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Interface Name: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Interface GUID: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Last Error: + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Error String + + + + + + + + 0 + 0 + + + + + + + + + + + + + + + Open + + + + + + + Blocking Open + + + + + + + Close + + + + + + + Stop + + + + + + + + + + diff --git a/src/network/bearer/bearer.pro b/src/network/bearer/bearer.pro new file mode 100644 index 0000000..2255b7c --- /dev/null +++ b/src/network/bearer/bearer.pro @@ -0,0 +1,163 @@ +# Qt bearer management library +TEMPLATE = lib +TARGET = QtBearer + +QT += network +include (../../common.pri) + +DEFINES += QT_BUILD_BEARER_LIB QT_MAKEDLL + +#DEFINES += BEARER_MANAGEMENT_DEBUG + +PUBLIC_HEADERS += qnetworkconfiguration.h \ + qnetworksession.h \ + qnetworkconfigmanager.h + +HEADERS += $$PUBLIC_HEADERS +SOURCES += qnetworksession.cpp \ + qnetworkconfigmanager.cpp \ + qnetworkconfiguration.cpp + +symbian: { + exists($${EPOCROOT}epoc32/release/winscw/udeb/cmmanager.lib)| \ + exists($${EPOCROOT}epoc32/release/armv5/lib/cmmanager.lib) { + message("Building with SNAP support") + DEFINES += SNAP_FUNCTIONALITY_AVAILABLE=1 + LIBS += -lcmmanager + } else { + message("Building without SNAP support") + LIBS += -lapengine + } + + INCLUDEPATH += $$APP_LAYER_SYSTEMINCLUDE + + HEADERS += qnetworkconfigmanager_s60_p.h \ + qnetworkconfiguration_s60_p.h \ + qnetworksession_s60_p.h + SOURCES += qnetworkconfigmanager_s60_p.cpp \ + qnetworkconfiguration_s60_p.cpp \ + qnetworksession_s60_p.cpp + + LIBS += -lcommdb \ + -lapsettingshandlerui \ + -lconnmon \ + -lcentralrepository \ + -lesock \ + -linsock \ + -lecom \ + -lefsrv \ + -lnetmeta + + deploy.path = $${EPOCROOT} + exportheaders.sources = $$PUBLIC_HEADERS + exportheaders.path = epoc32/include + + for(header, exportheaders.sources) { + BLD_INF_RULES.prj_exports += "$$header $$deploy.path$$exportheaders.path/$$basename(header)" + } + + bearer_deployment.sources = QtBearer.dll + bearer_deployment.path = /sys/bin + DEPLOYMENT += bearer_deployment + + TARGET.CAPABILITY = All -TCB +} else { + maemo { + QT += dbus + CONFIG += link_pkgconfig + + exists(../debug) { + message("Enabling debug messages.") + DEFINES += BEARER_MANAGEMENT_DEBUG + } + + HEADERS += qnetworksession_maemo_p.h \ + qnetworkconfigmanager_maemo_p.h \ + qnetworkconfiguration_maemo_p.h + + SOURCES += qnetworkconfigmanager_maemo.cpp \ + qnetworksession_maemo.cpp + + documentation.path = $$QT_MOBILITY_PREFIX/doc + documentation.files = doc/html + + PKGCONFIG += glib-2.0 dbus-glib-1 gconf-2.0 osso-ic conninet + + CONFIG += create_pc create_prl + QMAKE_PKGCONFIG_REQUIRES = glib-2.0 dbus-glib-1 gconf-2.0 osso-ic conninet + pkgconfig.path = $$QT_MOBILITY_LIB/pkgconfig + pkgconfig.files = QtBearer.pc + + INSTALLS += pkgconfig documentation + + } else { + + DEFINES += BEARER_ENGINE + + HEADERS += qnetworkconfigmanager_p.h \ + qnetworkconfiguration_p.h \ + qnetworksession_p.h \ + qnetworksessionengine_p.h \ + qgenericengine_p.h + + SOURCES += qnetworkconfigmanager_p.cpp \ + qnetworksession_p.cpp \ + qnetworksessionengine.cpp \ + qgenericengine.cpp + + unix:!mac:contains(networkmanager_enabled, yes) { + contains(QT_CONFIG,dbus) { + DEFINES += BACKEND_NM + QT += dbus + + HEADERS += qnmdbushelper_p.h \ + qnetworkmanagerservice_p.h \ + qnmwifiengine_unix_p.h + + SOURCES += qnmdbushelper.cpp \ + qnetworkmanagerservice_p.cpp \ + qnmwifiengine_unix.cpp + } else { + message("NetworkManager backend requires Qt DBus support") + } + } + + win32: { + HEADERS += qnlaengine_win_p.h \ + qnetworksessionengine_win_p.h + + !wince*:HEADERS += qnativewifiengine_win_p.h + + SOURCES += qnlaengine_win.cpp + + !wince*:SOURCES += qnativewifiengine_win.cpp + + !wince*:LIBS += -lWs2_32 + wince*:LIBS += -lWs2 + } + } + macx: { + HEADERS += qcorewlanengine_mac_p.h + SOURCES+= qcorewlanengine_mac.mm + LIBS += -framework Foundation -framework SystemConfiguration + + contains(corewlan_enabled, yes) { + isEmpty(QMAKE_MAC_SDK) { + SDK6="yes" + } else { + contains(QMAKE_MAC_SDK, "/Developer/SDKs/MacOSX10.6.sdk") { + SDK6="yes" + } + } + + !isEmpty(SDK6) { + LIBS += -framework CoreWLAN + DEFINES += MAC_SDK_10_6 + } + } + + + } +} + +include(../../features/deploy.pri) diff --git a/src/network/bearer/qcorewlanengine_mac.mm b/src/network/bearer/qcorewlanengine_mac.mm new file mode 100644 index 0000000..5451615 --- /dev/null +++ b/src/network/bearer/qcorewlanengine_mac.mm @@ -0,0 +1,461 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qcorewlanengine_mac_p.h" +#include "qnetworkconfiguration_p.h" + +#include +#include +#include +#include + +#include + +#if defined(MAC_SDK_10_6) //not much functionality without this +#include +#include +#include +#include +#endif + +#include +#include +#include + +#include +QMap networkInterfaces; + +QTM_BEGIN_NAMESPACE + +Q_GLOBAL_STATIC(QCoreWlanEngine, coreWlanEngine) + +inline QString cfstringRefToQstring(CFStringRef cfStringRef) { +// return QString([cfStringRef UTF8String]); + QString retVal; + CFIndex maxLength = 2 * CFStringGetLength(cfStringRef) + 1/*zero term*/; // max UTF8 + char *cstring = new char[maxLength]; + if (CFStringGetCString(CFStringRef(cfStringRef), cstring, maxLength, kCFStringEncodingUTF8)) { + retVal = QString::fromUtf8(cstring); + } + delete cstring; + return retVal; +} + +inline CFStringRef qstringToCFStringRef(const QString &string) +{ + return CFStringCreateWithCharacters(0, reinterpret_cast(string.unicode()), + string.length()); +} + +inline NSString *qstringToNSString(const QString &qstr) +{ return [reinterpret_cast(qstringToCFStringRef(qstr)) autorelease]; } + +inline QString nsstringToQString(const NSString *nsstr) +{ return cfstringRefToQstring(reinterpret_cast(nsstr)); } + +inline QStringList nsarrayToQStringList(void *nsarray) +{ + QStringList result; + NSArray *array = static_cast(nsarray); + for (NSUInteger i=0; i<[array count]; ++i) + result << nsstringToQString([array objectAtIndex:i]); + return result; +} + +static QString qGetInterfaceType(const QString &interfaceString) +{ + return networkInterfaces.value(interfaceString); +} + +QCoreWlanEngine::QCoreWlanEngine(QObject *parent) +: QNetworkSessionEngine(parent) +{ + getAllScInterfaces(); + connect(&pollTimer, SIGNAL(timeout()), this, SIGNAL(configurationsChanged())); + pollTimer.setInterval(10000); +} + +QCoreWlanEngine::~QCoreWlanEngine() +{ +} + +QList QCoreWlanEngine::getWifiConfigurations() +{ + QMapIterator i(networkInterfaces); + while (i.hasNext()) { + i.next(); + QString interfaceName = i.key(); + if (i.value() == "WLAN") { + if(!isWifiReady(interfaceName)) { + qWarning() << "wifi not powered on"; + return QList(); + } else { + // QList profs = getWlanProfiles(interfaceName); + scanForSsids(interfaceName); + } + } else { + + } + } + return QList (); +} + +QList QCoreWlanEngine::getConfigurations(bool *ok) +{ + if (ok) + *ok = true; + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + + QList foundConfigurations; + QList wificonfigs = getWifiConfigurations(); + + uint identifier; + QMapIterator i(networkInterfaces); + while (i.hasNext()) { + i.next(); + if (i.value() == "WLAN") { + QList fetchedConfigurations = scanForSsids(i.key()); + for (int i = 0; i < fetchedConfigurations.count(); ++i) { + + QNetworkConfigurationPrivate *config = new QNetworkConfigurationPrivate; + config->name = fetchedConfigurations.at(i)->name; + config->isValid = fetchedConfigurations.at(i)->isValid; + config->id = fetchedConfigurations.at(i)->id; + + config->state = fetchedConfigurations.at(i)->state; + config->type = fetchedConfigurations.at(i)->type; + config->roamingSupported = fetchedConfigurations.at(i)->roamingSupported; + config->purpose = fetchedConfigurations.at(i)->purpose; + config->internet = fetchedConfigurations.at(i)->internet; + config->serviceInterface = fetchedConfigurations.at(i)->serviceInterface; + + identifier = config->name.toUInt(); + configurationInterface[identifier] = config->serviceInterface.name(); + foundConfigurations.append(config); + } + } + + QNetworkInterface interface = QNetworkInterface::interfaceFromName(i.key()); + QNetworkConfigurationPrivate *cpPriv = new QNetworkConfigurationPrivate; + const QString humanReadableName = interface.humanReadableName(); + cpPriv->name = humanReadableName.isEmpty() ? interface.name() : humanReadableName; + cpPriv->isValid = true; + + if (interface.index()) + identifier = interface.index(); + else + identifier = qHash(interface.hardwareAddress()); + + cpPriv->id = QString::number(identifier); + cpPriv->type = QNetworkConfiguration::InternetAccessPoint; + cpPriv->state = QNetworkConfiguration::Undefined; + + if (interface.flags() & QNetworkInterface::IsRunning) { + cpPriv->state = QNetworkConfiguration::Defined; + cpPriv->internet = true; + } + if ( !interface.addressEntries().isEmpty()) { + cpPriv->state |= QNetworkConfiguration::Active; + cpPriv->internet = true; + } + configurationInterface[identifier] = interface.name(); + foundConfigurations.append(cpPriv); + } + [autoreleasepool release]; + pollTimer.start(); + return foundConfigurations; +} + +QString QCoreWlanEngine::getInterfaceFromId(const QString &id) +{ + return configurationInterface.value(id.toUInt()); +} + +bool QCoreWlanEngine::hasIdentifier(const QString &id) +{ + return configurationInterface.contains(id.toUInt()); +} + +QString QCoreWlanEngine::bearerName(const QString &id) +{ + QString interface = getInterfaceFromId(id); + + if (interface.isEmpty()) + return QString(); + + return qGetInterfaceType(interface); +} + +void QCoreWlanEngine::connectToId(const QString &id) +{ + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + QString interfaceString = getInterfaceFromId(id); + + if(networkInterfaces.value(interfaceString) == "WLAN") { +#if defined(MAC_SDK_10_6) + CWInterface *wifiInterface = [CWInterface interfaceWithName: qstringToNSString(interfaceString)]; + CWConfiguration *userConfig = [ wifiInterface configuration]; + + NSSet *remNets = [userConfig rememberedNetworks]; //CWWirelessProfile + + NSEnumerator *enumerator = [remNets objectEnumerator]; + CWWirelessProfile *wProfile; + NSUInteger index=0; + while ((wProfile = [enumerator nextObject])) { //CWWirelessProfile + + if(id == nsstringToQString([wProfile ssid])) { + CW8021XProfile *user8021XProfile = nil; + user8021XProfile = [ wProfile user8021XProfile]; + + NSError *err = nil; + NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0]; + + if(user8021XProfile) { + [params setValue: user8021XProfile forKey:kCWAssocKey8021XProfile]; + } else { + [params setValue: [wProfile passphrase] forKey: kCWAssocKeyPassphrase]; + } + + NSDictionary *parametersDict = nil; + NSArray* apArray = [NSMutableArray arrayWithArray:[wifiInterface scanForNetworksWithParameters:parametersDict error:&err]]; + if(!err) { + for(uint row=0; row < [apArray count]; row++ ) { + CWNetwork *apNetwork = [apArray objectAtIndex:row]; + if([[apNetwork ssid] compare:[wProfile ssid]] == NSOrderedSame) { + bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err]; + if(!result) { + qWarning() <<"ERROR"<< nsstringToQString([err localizedDescription ]); + emit connectionError(id, ConnectError); + } else { + [autoreleasepool release]; + return; + } + } + } + } + } + index++; + } + emit connectionError(id, InterfaceLookupError); +#endif + } else { + // not wifi + } + emit connectionError(id, OperationNotSupported); + [autoreleasepool release]; +} + +void QCoreWlanEngine::disconnectFromId(const QString &id) +{ + QString interfaceString = getInterfaceFromId(id); + if(networkInterfaces.value(getInterfaceFromId(id)) == "WLAN") { //wifi only for now +#if defined(MAC_SDK_10_6) + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + CWInterface *wifiInterface = [CWInterface interfaceWithName: qstringToNSString(interfaceString)]; + [wifiInterface disassociate]; + if([[wifiInterface interfaceState]intValue] != kCWInterfaceStateInactive) { + emit connectionError(id, DisconnectionError); + } + [autoreleasepool release]; + return; +#endif + } else { + + } + emit connectionError(id, OperationNotSupported); +} + +void QCoreWlanEngine::requestUpdate() +{ + getAllScInterfaces(); + emit configurationsChanged(); +} + +QCoreWlanEngine *QCoreWlanEngine::instance() +{ + return coreWlanEngine(); +} + +QList QCoreWlanEngine::scanForSsids(const QString &interfaceName) +{ + QList foundConfigs; +#if defined(MAC_SDK_10_6) + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + + CWInterface *currentInterface = [CWInterface interfaceWithName:qstringToNSString(interfaceName)]; + NSError *err = nil; + NSDictionary *parametersDict = nil; + NSArray* apArray = [NSMutableArray arrayWithArray:[currentInterface scanForNetworksWithParameters:parametersDict error:&err]]; + + if(!err) { + for(uint row=0; row < [apArray count]; row++ ) { + CWNetwork *apNetwork = [apArray objectAtIndex:row]; + QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); + QString networkSsid = nsstringToQString([apNetwork ssid]); + cpPriv->name = networkSsid; + cpPriv->isValid = true; + cpPriv->id = networkSsid; + cpPriv->internet = true; + cpPriv->type = QNetworkConfiguration::InternetAccessPoint; + cpPriv->serviceInterface = QNetworkInterface::interfaceFromName(nsstringToQString([[CWInterface interface] name])); + + CWWirelessProfile *networkProfile = apNetwork.wirelessProfile; + CW8021XProfile *userNetworkProfile = networkProfile.user8021XProfile; + if(!userNetworkProfile) { + } else { + qWarning() <<"Has profile!" ; + } + + if( [currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) { + QString interfaceSsidString = nsstringToQString( [currentInterface ssid]); + if( cpPriv->name == interfaceSsidString) { + cpPriv->state |= QNetworkConfiguration::Active; + } + } else { + if(isKnownSsid(cpPriv->serviceInterface.name(), networkSsid)) { + cpPriv->state = QNetworkConfiguration::Discovered; + } else { + cpPriv->state = QNetworkConfiguration::Defined; + } + } + if(!cpPriv->state) { + cpPriv->state = QNetworkConfiguration::Undefined; + } + if([[apNetwork securityMode ] intValue]== kCWSecurityModeOpen) + cpPriv->purpose = QNetworkConfiguration::PublicPurpose; + else + cpPriv->purpose = QNetworkConfiguration::PrivatePurpose; + foundConfigs.append(cpPriv); + } + } else { + qWarning() << "ERROR scanning for ssids" << nsstringToQString([err localizedDescription]) + < QCoreWlanEngine::getWlanProfiles(const QString &interfaceName) +{ + Q_UNUSED(interfaceName) +#if defined(MAC_SDK_10_6) +// for( CW8021XProfile *each8021XProfile in [CW8021XProfile allUser8021XProfiles] ) { +// qWarning() << "Profile name" << nsstringToQString([each8021XProfile ssid]); +// } + +#endif + return QList (); +} + +bool QCoreWlanEngine::getAllScInterfaces() +{ + networkInterfaces.clear(); + NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init]; + + CFArrayRef interfaces = SCNetworkInterfaceCopyAll(); + if (interfaces != NULL) { + CFIndex interfaceCount; + CFIndex interfaceIndex; + interfaceCount = CFArrayGetCount(interfaces); + for (interfaceIndex = 0; interfaceIndex < interfaceCount; interfaceIndex++) { + + CFStringRef bsdName; + CFTypeRef thisInterface = CFArrayGetValueAtIndex(interfaces, interfaceIndex); + bsdName = SCNetworkInterfaceGetBSDName((SCNetworkInterfaceRef)thisInterface); + QString interfaceName = cfstringRefToQstring(bsdName); + QString typeStr; + CFStringRef type = SCNetworkInterfaceGetInterfaceType((SCNetworkInterfaceRef)thisInterface); + if ( CFEqual(type, kSCNetworkInterfaceTypeIEEE80211)) { + typeStr = "WLAN"; +// } else if (CFEqual(type, kSCNetworkInterfaceTypeBluetooth)) { +// typeStr = "Bluetooth"; + } else if(CFEqual(type, kSCNetworkInterfaceTypeEthernet)) { + typeStr = "Ethernet"; + } else if(CFEqual(type, kSCNetworkInterfaceTypeFireWire)) { + typeStr = "Ethernet"; //ok a bit fudged + } + if(!networkInterfaces.contains(interfaceName) && !typeStr.isEmpty()) { + networkInterfaces.insert(interfaceName,typeStr); + } + } + } + CFRelease(interfaces); + + [autoreleasepool release]; + return true; +} + +#include "moc_qcorewlanengine_mac_p.cpp" + +QTM_END_NAMESPACE + diff --git a/src/network/bearer/qcorewlanengine_mac_p.h b/src/network/bearer/qcorewlanengine_mac_p.h new file mode 100644 index 0000000..fc8e4b5 --- /dev/null +++ b/src/network/bearer/qcorewlanengine_mac_p.h @@ -0,0 +1,100 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QCOREWLANENGINE_P_H +#define QCOREWLANENGINE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qnetworksessionengine_p.h" +#include +#include +QTM_BEGIN_NAMESPACE + +class QNetworkConfigurationPrivate; + +class QCoreWlanEngine : public QNetworkSessionEngine +{ + Q_OBJECT + +public: + QCoreWlanEngine(QObject *parent = 0); + ~QCoreWlanEngine(); + + QList getConfigurations(bool *ok = 0); + QString getInterfaceFromId(const QString &id); + bool hasIdentifier(const QString &id); + + QString bearerName(const QString &id); + + void connectToId(const QString &id); + void disconnectFromId(const QString &id); + + void requestUpdate(); + + static QCoreWlanEngine *instance(); + static bool getAllScInterfaces(); + +private: + bool isWifiReady(const QString &dev); + QMap configurationInterface; + QTimer pollTimer; + QList scanForSsids(const QString &interfaceName); + + QList getWlanProfiles(const QString &interfaceName); + + QList getWifiConfigurations(); + bool isKnownSsid(const QString &interfaceName, const QString &ssid); +}; + +QTM_END_NAMESPACE + +#endif + diff --git a/src/network/bearer/qgenericengine.cpp b/src/network/bearer/qgenericengine.cpp new file mode 100644 index 0000000..184a69c --- /dev/null +++ b/src/network/bearer/qgenericengine.cpp @@ -0,0 +1,234 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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_p.h" +#include "qnetworkconfiguration_p.h" + +#include +#include +#include +#include + +#include + +#ifdef Q_OS_WIN +#include "qnetworksessionengine_win_p.h" +#endif + +QTM_BEGIN_NAMESPACE + +Q_GLOBAL_STATIC(QGenericEngine, genericEngine) + +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 QString(); + + 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 QString(); + } + + 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 QString(); + } + + 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 +#else + Q_UNUSED(interface); +#endif + + return QString(); +} + +QGenericEngine::QGenericEngine(QObject *parent) +: QNetworkSessionEngine(parent) +{ + connect(&pollTimer, SIGNAL(timeout()), this, SIGNAL(configurationsChanged())); + pollTimer.setInterval(10000); +} + +QGenericEngine::~QGenericEngine() +{ +} + +QList QGenericEngine::getConfigurations(bool *ok) +{ + if (ok) + *ok = true; + + QList foundConfigurations; + + // 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 interfaces = QNetworkInterface::allInterfaces(); + if (interfaces.isEmpty()) + interfaces = QNetworkInterface::allInterfaces(); + + // 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()) == "WLAN") + continue; + + QNetworkConfigurationPrivate *cpPriv = new QNetworkConfigurationPrivate; + const QString humanReadableName = interface.humanReadableName(); + cpPriv->name = humanReadableName.isEmpty() ? interface.name() : humanReadableName; + cpPriv->isValid = true; + + uint identifier; + if (interface.index()) + identifier = qHash(QLatin1String("NLA:") + QString::number(interface.index())); + else + identifier = qHash(QLatin1String("NLA:") + interface.hardwareAddress()); + + cpPriv->id = QString::number(identifier); + cpPriv->state = QNetworkConfiguration::Discovered; + cpPriv->type = QNetworkConfiguration::InternetAccessPoint; + if (interface.flags() & QNetworkInterface::IsUp) + cpPriv->state |= QNetworkConfiguration::Active; + + configurationInterface[identifier] = interface.name(); + + foundConfigurations.append(cpPriv); + } + + pollTimer.start(); + + return foundConfigurations; +} + +QString QGenericEngine::getInterfaceFromId(const QString &id) +{ + return configurationInterface.value(id.toUInt()); +} + +bool QGenericEngine::hasIdentifier(const QString &id) +{ + return configurationInterface.contains(id.toUInt()); +} + +QString QGenericEngine::bearerName(const QString &id) +{ + QString interface = getInterfaceFromId(id); + + if (interface.isEmpty()) + return QString(); + + return qGetInterfaceType(interface); +} + +void QGenericEngine::connectToId(const QString &id) +{ + emit connectionError(id, OperationNotSupported); +} + +void QGenericEngine::disconnectFromId(const QString &id) +{ + emit connectionError(id, OperationNotSupported); +} + +void QGenericEngine::requestUpdate() +{ + emit configurationsChanged(); +} + +QGenericEngine *QGenericEngine::instance() +{ + return genericEngine(); +} + +#include "moc_qgenericengine_p.cpp" +QTM_END_NAMESPACE + diff --git a/src/network/bearer/qgenericengine_p.h b/src/network/bearer/qgenericengine_p.h new file mode 100644 index 0000000..976776e --- /dev/null +++ b/src/network/bearer/qgenericengine_p.h @@ -0,0 +1,94 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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_P_H +#define QGENERICENGINE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qnetworksessionengine_p.h" + +#include +#include + +QTM_BEGIN_NAMESPACE + +class QNetworkConfigurationPrivate; + +class QGenericEngine : public QNetworkSessionEngine +{ + Q_OBJECT + +public: + QGenericEngine(QObject *parent = 0); + ~QGenericEngine(); + + QList getConfigurations(bool *ok = 0); + QString getInterfaceFromId(const QString &id); + bool hasIdentifier(const QString &id); + + QString bearerName(const QString &id); + + void connectToId(const QString &id); + void disconnectFromId(const QString &id); + + void requestUpdate(); + + static QGenericEngine *instance(); + +private: + QMap configurationInterface; + QTimer pollTimer; +}; + +QTM_END_NAMESPACE + +#endif + diff --git a/src/network/bearer/qnativewifiengine_win.cpp b/src/network/bearer/qnativewifiengine_win.cpp new file mode 100644 index 0000000..d8fe5fb --- /dev/null +++ b/src/network/bearer/qnativewifiengine_win.cpp @@ -0,0 +1,726 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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_win_p.h" +#include "qnetworkconfiguration_p.h" + +#include +#include +#include +#include + +#include + +#include +#undef interface + +QTM_BEGIN_NAMESPACE + +Q_GLOBAL_STATIC(QNativeWifiEngine, nativeWifiEngine) + +#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); + +static WlanOpenHandleProto local_WlanOpenHandle = 0; +static WlanRegisterNotificationProto local_WlanRegisterNotification = 0; +static WlanEnumInterfacesProto local_WlanEnumInterfaces = 0; +static WlanGetAvailableNetworkListProto local_WlanGetAvailableNetworkList = 0; +static WlanQueryInterfaceProto local_WlanQueryInterface = 0; +static WlanConnectProto local_WlanConnect = 0; +static WlanDisconnectProto local_WlanDisconnect = 0; +static WlanScanProto local_WlanScan = 0; +static WlanFreeMemoryProto local_WlanFreeMemory = 0; +static WlanCloseHandleProto local_WlanCloseHandle = 0; + +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; + } + } +} + +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: + d->emitConfigurationsChanged(); + break; + default: + qDebug() << "wlan unknown notification"; + } +} + +QNativeWifiEngine::QNativeWifiEngine(QObject *parent) +: QNetworkSessionEngine(parent), handle(0) +{ + DWORD clientVersion; + + DWORD result = local_WlanOpenHandle(1, 0, &clientVersion, &handle); + if (result != ERROR_SUCCESS) { + if (result != ERROR_SERVICE_NOT_ACTIVE) + qWarning("%s: WlanOpenHandle failed with error %ld\n", __FUNCTION__, result); + + return; + } + + result = local_WlanRegisterNotification(handle, WLAN_NOTIFICATION_SOURCE_ALL, true, + WLAN_NOTIFICATION_CALLBACK(qNotificationCallback), + this, 0, 0); + if (result != ERROR_SUCCESS) + qWarning("%s: WlanRegisterNotification failed with error %ld\n", __FUNCTION__, result); + + // On Windows XP SP2 and SP3 only connection and disconnection notifications are available. + // We need to poll for changes in available wireless networks. + connect(&pollTimer, SIGNAL(timeout()), this, SIGNAL(configurationsChanged())); + pollTimer.setInterval(10000); +} + +QNativeWifiEngine::~QNativeWifiEngine() +{ + local_WlanCloseHandle(handle, 0); +} + +QList QNativeWifiEngine::getConfigurations(bool *ok) +{ + if (ok) + *ok = false; + + QList foundConfigurations; + + // 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 foundConfigurations; + } + + 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(network.dot11Ssid.ucSSID), + network.dot11Ssid.uSSIDLength); + } + + // don't add duplicate networks + if (seenNetworks.contains(networkName)) + continue; + else + seenNetworks.append(networkName); + + QNetworkConfigurationPrivate *cpPriv = new QNetworkConfigurationPrivate; + + cpPriv->isValid = true; + + cpPriv->name = networkName; + cpPriv->id = QString::number(qHash(QLatin1String("WLAN:") + cpPriv->name)); + + if (!(network.dwFlags & WLAN_AVAILABLE_NETWORK_HAS_PROFILE)) + cpPriv->state = QNetworkConfiguration::Undefined; + + if (network.strProfileName[0] != 0) { + if (network.bNetworkConnectable) { + if (network.dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED) + cpPriv->state = QNetworkConfiguration::Active; + else + cpPriv->state = QNetworkConfiguration::Discovered; + } else { + cpPriv->state = QNetworkConfiguration::Defined; + } + } + + cpPriv->type = QNetworkConfiguration::InternetAccessPoint; + + foundConfigurations.append(cpPriv); + } + + local_WlanFreeMemory(networkList); + } + + local_WlanFreeMemory(interfaceList); + + if (ok) + *ok = true; + + pollTimer.start(); + + return foundConfigurations; +} + +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(&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); + + return guid.toUpper(); + } + + local_WlanFreeMemory(connectionAttributes); + } + + 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(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(profile.utf16()); + parameters.pDot11Ssid = 0; + parameters.pDesiredBssidList = 0; + parameters.dot11BssType = dot11_BSS_type_any; + parameters.dwFlags = 0; + + DWORD result = local_WlanConnect(handle, &interface.InterfaceGuid, ¶meters, 0); + if (result != ERROR_SUCCESS) { + qWarning("%s: WlanConnect failed with error %ld\n", __FUNCTION__, result); + emit connectionError(id, ConnectError); + break; + } + + break; + } + } + + local_WlanFreeMemory(interfaceList); + + if (profile.isEmpty()) + emit connectionError(id, InterfaceLookupError); +} + +void QNativeWifiEngine::disconnectFromId(const QString &id) +{ + QString interface = getInterfaceFromId(id); + + if (interface.isEmpty()) { + emit connectionError(id, InterfaceLookupError); + return; + } + + QStringList split = interface.mid(1, interface.length() - 2).split('-'); + + GUID guid; + guid.Data1 = split.at(0).toUInt(0, 16); + guid.Data2 = split.at(1).toUShort(0, 16); + guid.Data3 = split.at(2).toUShort(0, 16); + guid.Data4[0] = split.at(3).left(2).toUShort(0, 16); + guid.Data4[1] = split.at(3).right(2).toUShort(0, 16); + for (int i = 0; i < 6; ++i) + guid.Data4[i + 2] = split.at(4).mid(i*2, 2).toUShort(0, 16); + + DWORD result = local_WlanDisconnect(handle, &guid, 0); + if (result != ERROR_SUCCESS) { + qWarning("%s: WlanDisconnect failed with error %ld\n", __FUNCTION__, result); + emit connectionError(id, DisconnectionError); + return; + } +} + +void QNativeWifiEngine::requestUpdate() +{ + // enumerate interfaces + WLAN_INTERFACE_INFO_LIST *interfaceList; + DWORD result = local_WlanEnumInterfaces(handle, 0, &interfaceList); + if (result != ERROR_SUCCESS) { + qWarning("%s: WlanEnumInterfaces failed with error %ld\n", __FUNCTION__, result); + return; + } + + for (unsigned int i = 0; i < interfaceList->dwNumberOfItems; ++i) { + result = local_WlanScan(handle, &interfaceList->InterfaceInfo[i].InterfaceGuid, 0, 0, 0); + if (result != ERROR_SUCCESS) + qWarning("%s: WlanScan failed with error %ld\n", __FUNCTION__, result); + } +} + +QNativeWifiEngine *QNativeWifiEngine::instance() +{ + resolveLibrary(); + + // native wifi dll not available + if (!local_WlanOpenHandle) + return 0; + + QNativeWifiEngine *engine = nativeWifiEngine(); + + // could not initialise subsystem + if (engine && engine->handle == 0) + return 0; + + return engine; +} + +#include "moc_qnativewifiengine_win_p.cpp" + +QTM_END_NAMESPACE diff --git a/src/network/bearer/qnativewifiengine_win_p.h b/src/network/bearer/qnativewifiengine_win_p.h new file mode 100644 index 0000000..0d5bcb0 --- /dev/null +++ b/src/network/bearer/qnativewifiengine_win_p.h @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 "qnetworksessionengine_p.h" + +#include + +QTM_BEGIN_NAMESPACE + +class QNetworkConfigurationPrivate; + +class QNativeWifiEngine : public QNetworkSessionEngine +{ + Q_OBJECT + +public: + QNativeWifiEngine(QObject *parent = 0); + ~QNativeWifiEngine(); + + QList getConfigurations(bool *ok = 0); + QString getInterfaceFromId(const QString &id); + bool hasIdentifier(const QString &id); + + QString bearerName(const QString &id); + + void connectToId(const QString &id); + void disconnectFromId(const QString &id); + + void requestUpdate(); + + inline void emitConfigurationsChanged() { emit configurationsChanged(); } + + static QNativeWifiEngine *instance(); + +private: + QTimer pollTimer; + + Qt::HANDLE handle; +}; + +QTM_END_NAMESPACE + +#endif diff --git a/src/network/bearer/qnetworkconfigmanager.cpp b/src/network/bearer/qnetworkconfigmanager.cpp new file mode 100644 index 0000000..264f0df --- /dev/null +++ b/src/network/bearer/qnetworkconfigmanager.cpp @@ -0,0 +1,333 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 "qnetworkconfigmanager.h" + +#ifdef Q_OS_SYMBIAN +#include "qnetworkconfigmanager_s60_p.h" +#else +#include "qnetworkconfigmanager_p.h" +#endif + +QTM_BEGIN_NAMESPACE + +Q_GLOBAL_STATIC(QNetworkConfigurationManagerPrivate, connManager); + +/*! + \class QNetworkConfigurationManager + + \brief The QNetworkConfigurationManager class manages the network configurations provided + by the system. + + \inmodule QtNetwork + \ingroup bearer + + QNetworkConfigurationManager provides access to the network configurations known to the system and + enables applications to detect the system capabilities (with regards to network sessions) at runtime. + + A QNetworkConfiguration abstracts a set of configuration options describing how a + network interface has to be configured to connect to a particular target network. + QNetworkConfigurationManager maintains and updates the global list of + QNetworkConfigurations. Applications can access and filter this list via + allConfigurations(). If a new configuration is added or an existing one is removed or changed + the configurationAdded(), configurationRemoved() and configurationChanged() signals are emitted + respectively. + + The defaultConfiguration() can be used when intending to immediately create a new + network session without caring about the particular configuration. It returns + a \l QNetworkConfiguration::Discovered configuration. If there are not any + discovered ones an invalid configuration is returned. + + Some configuration updates may require some time to perform updates. A WLAN scan is + such an example. Unless the platform performs internal updates it may be required to + manually trigger configuration updates via QNetworkConfigurationManager::updateConfigurations(). + The completion of the update process is indicted by emitting the updateCompleted() + signal. The update process ensures that every existing QNetworkConfiguration instance + is updated. There is no need to ask for a renewed configuration list via allConfigurations(). + + \sa QNetworkConfiguration +*/ + +/*! + \fn void QNetworkConfigurationManager::configurationAdded(const QNetworkConfiguration& config) + + This signal is emitted whenever a new network configuration is added to the system. The new + configuration is specified by \a config. +*/ + +/*! + \fn void QNetworkConfigurationManager::configurationRemoved(const QNetworkConfiguration& configuration) + + This signal is emitted when a configuration is about to be removed from the system. The removed + \a configuration is invalid but retains name and identifier. +*/ + +/*! + \fn void QNetworkConfigurationManager::updateCompleted() + + This signal is emitted when the configuration update has been completed. Such an update can + be initiated via \l updateConfigurations(). +*/ + +/*! \fn void QNetworkConfigurationManager::configurationChanged(const QNetworkConfiguration& config) + + This signal is emitted when the \l {QNetworkConfiguration::state()}{state} of \a config changes. +*/ + +/*! + \fn void QNetworkConfigurationManager::onlineStateChanged(bool isOnline) + + This signal is emitted when the device changes from online to offline mode or vice versa. + \a isOnline represents the new state of the device. + + The state is considered to be online for as long as + \l{allConfigurations()}{allConfigurations}(QNetworkConfiguration::Active) returns a list with + at least one entry. +*/ + +/*! + \enum QNetworkConfigurationManager::Capability + + Specifies the system capabilities of the bearer API. The possible values are: + + \value CanStartAndStopInterfaces Network sessions and their underlying access points can be + started and stopped. If this flag is not set QNetworkSession + can only monitor but not influence the state of access points. + On some platforms this feature may require elevated user + permissions. This option is platform specific and may not + always be available. + \value DirectConnectionRouting Network sessions and their sockets can be bound to a + particular network interface. Any packet that passes through + the socket goes to the specified network interface and thus + disregards standard routing table entries. This may be useful + when two interfaces can reach overlapping IP ranges or an + application has specific needs in regards to target networks. + This option is platform specific and may not always be + available. + \value SystemSessionSupport If this flag is set the underlying platform ensures that a + network interface is not shut down until the last network + session has been \l{QNetworkSession::close()}{closed()}. This + works across multiple processes. If the platform session + support is missing this API can only ensure the above behavior + for network sessions within the same process. + In general mobile platforms (such as Symbian/S60) have such + support whereas most desktop platform lack this capability. + \value ApplicationLevelRoaming The system gives applications control over the systems roaming + behavior. Applications can initiate roaming (in case the + current link is not suitable) and are consulted if the system + has identified a more suitable access point. + \value ForcedRoaming The system disconnects an existing access point and reconnects + via a more suitable one. The application does not have any + control over this process and has to reconnect its active + sockets. + \value DataStatistics If this flag is set QNetworkSession can provide statistics + about transmitted and received data. +*/ + +/*! + Constructs a QNetworkConfigurationManager with the given \a parent. +*/ +QNetworkConfigurationManager::QNetworkConfigurationManager( QObject* parent ) + : QObject(parent) +{ + QNetworkConfigurationManagerPrivate* priv = connManager(); + connect(priv, SIGNAL(configurationAdded(QNetworkConfiguration)), + this, SIGNAL(configurationAdded(QNetworkConfiguration))); + connect(priv, SIGNAL(configurationRemoved(QNetworkConfiguration)), + this, SIGNAL(configurationRemoved(QNetworkConfiguration))); + connect(priv, SIGNAL(configurationUpdateComplete()), + this, SIGNAL(updateCompleted())); + connect(priv, SIGNAL(onlineStateChanged(bool)), + this, SIGNAL(onlineStateChanged(bool))); + connect(priv, SIGNAL(configurationChanged(QNetworkConfiguration)), + this, SIGNAL(configurationChanged(QNetworkConfiguration))); +} + +/*! + Frees the resources associated with the QNetworkConfigurationManager object. +*/ +QNetworkConfigurationManager::~QNetworkConfigurationManager() +{ +} + + +/*! + Returns the default configuration to be used. This function always returns a discovered + configuration; otherwise an invalid configuration. + + In some cases it may be required to call updateConfigurations() and wait for the + updateCompleted() signal before calling this function. + + \sa allConfigurations() +*/ +QNetworkConfiguration QNetworkConfigurationManager::defaultConfiguration() const +{ + return connManager()->defaultConfiguration(); +} + +/*! + Returns the list of configurations which comply with the given \a filter. + + By default this function returns all (defined and undefined) configurations. + + A wireless network with a particular SSID may only be accessible in a + certain area despite the fact that the system has a valid configuration + for it. Therefore the filter flag may be used to limit the list to + discovered and possibly connected configurations only. + + If \a filter is set to zero this function returns all possible configurations. + + Note that this function returns the states for all configurations as they are known at + the time of this function call. If for instance a configuration of type WLAN is defined + the system may have to perform a WLAN scan in order to determine whether it is + actually available. To obtain the most accurate state updateConfigurations() should + be used to update each configuration's state. Note that such an update may require + some time. It's completion is signalled by updateCompleted(). In the absence of a + configuration update this function returns the best estimate at the time of the call. +*/ +QList QNetworkConfigurationManager::allConfigurations(QNetworkConfiguration::StateFlags filter) const +{ + QList result; + QNetworkConfigurationManagerPrivate* conPriv = connManager(); + QList cpsIdents = conPriv->accessPointConfigurations.keys(); + + //find all InternetAccessPoints + foreach( QString ii, cpsIdents) { + QExplicitlySharedDataPointer p = + conPriv->accessPointConfigurations.value(ii); + if ( (p->state & filter) == filter ) { + QNetworkConfiguration pt; + pt.d = conPriv->accessPointConfigurations.value(ii); + result << pt; + } + } + + //find all service networks + cpsIdents = conPriv->snapConfigurations.keys(); + foreach( QString ii, cpsIdents) { + QExplicitlySharedDataPointer p = + conPriv->snapConfigurations.value(ii); + if ( (p->state & filter) == filter ) { + QNetworkConfiguration pt; + pt.d = conPriv->snapConfigurations.value(ii); + result << pt; + } + } + + return result; +} + +/*! + Returns the QNetworkConfiguration for \a identifier; otherwise returns an + invalid QNetworkConfiguration. + + \sa QNetworkConfiguration::identifier() +*/ +QNetworkConfiguration QNetworkConfigurationManager::configurationFromIdentifier(const QString& identifier) const +{ + QNetworkConfigurationManagerPrivate* conPriv = connManager(); + QNetworkConfiguration item; + if (conPriv->accessPointConfigurations.contains(identifier)) + item.d = conPriv->accessPointConfigurations.value(identifier); + else if (conPriv->snapConfigurations.contains(identifier)) + item.d = conPriv->snapConfigurations.value(identifier); + else if (conPriv->userChoiceConfigurations.contains(identifier)) + item.d = conPriv->userChoiceConfigurations.value(identifier); + return item; + +} + +/*! + Returns true if the system is considered to be connected to another device via an active + network interface; otherwise returns false. + + This is equivalent to the following code snippet: + + \code + QNetworkConfigurationManager mgr; + QList activeConfigs = mgr.allConfigurations(QNetworkConfiguration::Active) + if (activeConfigs.count() > 0) + Q_ASSERT(mgr.isOnline()) + else + Q_ASSERT(!mgr.isOnline()) + \endcode + + \sa onlineStateChanged() +*/ +bool QNetworkConfigurationManager::isOnline() const +{ + QNetworkConfigurationManagerPrivate* conPriv = connManager(); + Q_UNUSED(conPriv); + QList activeConfigs = allConfigurations(QNetworkConfiguration::Active); + return activeConfigs.count() > 0; +} + +/*! + Returns the capabilities supported by the current platform. +*/ +QNetworkConfigurationManager::Capabilities QNetworkConfigurationManager::capabilities() const +{ + return connManager()->capFlags; +} + +/*! + Initiates an update of all configurations. This may be used to initiate WLAN scans or other + time consuming updates which may be required to obtain the correct state for configurations. + + This call is asynchronous. On completion of this update the updateCompleted() signal is + emitted. If new configurations are discovered or old ones were removed or changed the update + process may trigger the emission of one or multiple configurationAdded(), + configurationRemoved() and configurationChanged() signals. + + If a configuration state changes as a result of this update all existing QNetworkConfiguration + instances are updated automatically. + + \sa allConfigurations() +*/ +void QNetworkConfigurationManager::updateConfigurations() +{ + connManager()->performAsyncConfigurationUpdate(); +} + +#include "moc_qnetworkconfigmanager.cpp" + +QTM_END_NAMESPACE + diff --git a/src/network/bearer/qnetworkconfigmanager.h b/src/network/bearer/qnetworkconfigmanager.h new file mode 100644 index 0000000..98641f6 --- /dev/null +++ b/src/network/bearer/qnetworkconfigmanager.h @@ -0,0 +1,101 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 QNETWORKCONFIGURATIONMANAGER_H +#define QNETWORKCONFIGURATIONMANAGER_H + +#include "qmobilityglobal.h" + +#include +#include "qnetworkconfiguration.h" + +QT_BEGIN_HEADER + +QTM_BEGIN_NAMESPACE + +class QNetworkConfigurationManagerPrivate; +class Q_BEARER_EXPORT QNetworkConfigurationManager : public QObject +{ + Q_OBJECT + +public: + + enum Capability { + CanStartAndStopInterfaces = 0x00000001, + DirectConnectionRouting = 0x00000002, + SystemSessionSupport = 0x00000004, + ApplicationLevelRoaming = 0x00000008, + ForcedRoaming = 0x00000010, + DataStatistics = 0x00000020 + }; + + Q_DECLARE_FLAGS(Capabilities, Capability) + + QNetworkConfigurationManager( QObject* parent = 0 ); + virtual ~QNetworkConfigurationManager(); + + + QNetworkConfigurationManager::Capabilities capabilities() const; + + QNetworkConfiguration defaultConfiguration() const; + QList allConfigurations(QNetworkConfiguration::StateFlags flags = 0) const; + QNetworkConfiguration configurationFromIdentifier(const QString& identifier) const; + void updateConfigurations(); + + bool isOnline() const; + +Q_SIGNALS: + void configurationAdded(const QNetworkConfiguration& config); + void configurationRemoved(const QNetworkConfiguration& config); + void configurationChanged(const QNetworkConfiguration& config); + void onlineStateChanged(bool isOnline); + void updateCompleted(); + +}; + +Q_DECLARE_OPERATORS_FOR_FLAGS(QNetworkConfigurationManager::Capabilities) + +QTM_END_NAMESPACE + +QT_END_HEADER + +#endif //QNETWORKCONFIGURATIONMANAGER_H + diff --git a/src/network/bearer/qnetworkconfigmanager_maemo.cpp b/src/network/bearer/qnetworkconfigmanager_maemo.cpp new file mode 100644 index 0000000..795b054 --- /dev/null +++ b/src/network/bearer/qnetworkconfigmanager_maemo.cpp @@ -0,0 +1,760 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 + +#include "qnetworkconfigmanager_maemo_p.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +QTM_BEGIN_NAMESPACE + +#define IAP "/system/osso/connectivity/IAP" +static int iap_prefix_len; +static void notify_iap(GConfClient *client, guint id, + GConfEntry *entry, gpointer user_data); + + +/* 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, QNetworkConfigurationManagerPrivate *d); + + QString iap_id; + QTimer timer; + QNetworkConfigurationManagerPrivate *d; + +public Q_SLOTS: + void timeout(); +}; + + +void _IapAddTimer::add(QString& id, QNetworkConfigurationManagerPrivate *d_ptr) +{ + iap_id = id; + d = d_ptr; + + if (timer.isActive()) { + QObject::disconnect(&timer, SIGNAL(timeout()), this, SLOT(timeout())); + timer.stop(); + } + timer.setSingleShot(true); + QObject::connect(&timer, SIGNAL(timeout()), this, SLOT(timeout())); + timer.start(1500); +} + + +void _IapAddTimer::timeout() +{ + d->addConfiguration(iap_id); +} + + +class IapAddTimer { + QHash timers; + +public: + IapAddTimer() {} + ~IapAddTimer() {} + + void add(QString& iap_id, QNetworkConfigurationManagerPrivate *d); + void del(QString& iap_id); + void removeAll(); +}; + + +void IapAddTimer::removeAll() +{ + QHashIterator i(timers); + while (i.hasNext()) { + i.next(); + _IapAddTimer *t = i.value(); + delete t; + } + timers.clear(); +} + + +void IapAddTimer::add(QString& iap_id, QNetworkConfigurationManagerPrivate *d) +{ + if (timers.contains(iap_id)) { + _IapAddTimer *iap = timers.value(iap_id); + iap->add(iap_id, d); + } else { + _IapAddTimer *iap = new _IapAddTimer; + iap->add(iap_id, d); + timers.insert(iap_id, iap); + } +} + +void IapAddTimer::del(QString& iap_id) +{ + if (timers.contains(iap_id)) { + _IapAddTimer *iap = timers.take(iap_id); + delete iap; + } +} + + +class IapMonitor +{ +public: + IapMonitor() : first_call(true) { } + friend void notify_iap(GConfClient *, guint, + GConfEntry *entry, gpointer user_data); + + void setup(QNetworkConfigurationManagerPrivate *d); + void cleanup(); + +private: + bool first_call; + + void iapAdded(const char *key, GConfEntry *entry); + void iapDeleted(const char *key, GConfEntry *entry); + + Maemo::IAPMonitor *iap; + QNetworkConfigurationManagerPrivate *d; + IapAddTimer timers; +}; + +Q_GLOBAL_STATIC(IapMonitor, iapMonitor); + + +/* Notify func that is called when IAP is added or deleted */ +static 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(QNetworkConfigurationManagerPrivate *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); +} + + + +void QNetworkConfigurationManagerPrivate::registerPlatformCapabilities() +{ + capFlags |= QNetworkConfigurationManager::CanStartAndStopInterfaces; + capFlags |= QNetworkConfigurationManager::DataStatistics; + capFlags |= QNetworkConfigurationManager::ForcedRoaming; +} + + +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 ""; +} + + +struct SSIDInfo { + QString iap_id; + QString wlan_security; +}; + + +void QNetworkConfigurationManagerPrivate::configurationChanged(QNetworkConfigurationPrivate *ptr) +{ + QNetworkConfiguration item; + item.d = ptr; + emit configurationChanged(item); +} + +void QNetworkConfigurationManagerPrivate::deleteConfiguration(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)) { + QExplicitlySharedDataPointer priv = accessPointConfigurations.take(iap_id); + if (priv.data()) { + priv->isValid = false; +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug() << "IAP" << iap_id << "was removed from storage."; +#endif + + QNetworkConfiguration item; + item.d = priv; + emit configurationRemoved(item); + configChanged(priv.data(), false); + } 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 + } +} + + +uint32_t QNetworkConfigurationManagerPrivate::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 QNetworkConfigurationManagerPrivate::addConfiguration(QString& iap_id) +{ + if (!accessPointConfigurations.contains(iap_id)) { + Maemo::IAPConf saved_iap(iap_id); + QString iap_type = saved_iap.value("type").toString(); + if (!iap_type.isEmpty()) { + QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); + cpPriv->name = saved_iap.value("name").toString(); + if (cpPriv->name.isEmpty()) + cpPriv->name = iap_id; + cpPriv->isValid = true; + cpPriv->id = iap_id; + cpPriv->iap_type = iap_type; + cpPriv->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString()); + cpPriv->service_id = saved_iap.value("service_id").toString(); + cpPriv->service_type = saved_iap.value("service_type").toString(); + if (iap_type.startsWith("WLAN")) { + QByteArray ssid = saved_iap.value("wlan_ssid").toByteArray(); + if (ssid.isEmpty()) { + qWarning() << "Cannot get ssid for" << iap_id; + } + } + cpPriv->type = QNetworkConfiguration::InternetAccessPoint; + cpPriv->state = QNetworkConfiguration::Defined; + + QExplicitlySharedDataPointer ptr(cpPriv); + accessPointConfigurations.insert(iap_id, ptr); + +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug("IAP: %s, name: %s, added to known list", iap_id.toAscii().data(), cpPriv->name.toAscii().data()); +#endif + + QNetworkConfiguration item; + item.d = ptr; + emit configurationAdded(item); + configChanged(ptr.data(), true); + } else { + qWarning("IAP %s does not have \"type\" field defined, skipping this IAP.", iap_id.toAscii().data()); + } + } else { +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug() << "IAP" << iap_id << "already in gconf."; +#endif + + /* Check if the data in gconf changed and update configuration + * accordingly + */ + QExplicitlySharedDataPointer ptr = accessPointConfigurations.take(iap_id); + if (ptr.data()) { + Maemo::IAPConf changed_iap(iap_id); + QString iap_type = changed_iap.value("type").toString(); + bool update_needed = false; /* if IAP type or ssid changed, we need to change the state */ + + ptr->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString()); + ptr->service_id = changed_iap.value("service_id").toString(); + ptr->service_type = changed_iap.value("service_type").toString(); + + if (!iap_type.isEmpty()) { + ptr->name = changed_iap.value("name").toString(); + if (ptr->name.isEmpty()) + ptr->name = iap_id; + ptr->isValid = true; + if (ptr->iap_type != iap_type) { + ptr->iap_type = iap_type; + update_needed = true; + } + if (iap_type.startsWith("WLAN")) { + QByteArray ssid = changed_iap.value("wlan_ssid").toByteArray(); + if (ssid.isEmpty()) { + qWarning() << "Cannot get ssid for" << iap_id; + } + if (ptr->network_id != ssid) { + ptr->network_id = ssid; + update_needed = true; + } + } + } + accessPointConfigurations.insert(iap_id, ptr); + if (update_needed) { + ptr->type = QNetworkConfiguration::InternetAccessPoint; + if (ptr->state != QNetworkConfiguration::Defined) { + ptr->state = QNetworkConfiguration::Defined; + configurationChanged(ptr.data()); + } + } + } else { + qWarning("Cannot find IAP %s from current configuration although it should be there.", iap_id.toAscii().data()); + } + } +} + + +void QNetworkConfigurationManagerPrivate::updateConfigurations() +{ + /* Contains known network id (like ssid) from storage */ + QMultiHash knownConfigs; + + /* All the scanned access points */ + QList scanned; + + /* Turn on IAP monitoring */ + iapMonitor()->setup(this); + + if (firstUpdate) { + /* We create a default configuration which is a pseudo config */ + QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); + cpPriv->name = "UserChoice"; + cpPriv->state = QNetworkConfiguration::Discovered; + cpPriv->isValid = true; + cpPriv->id = OSSO_IAP_ANY; + cpPriv->type = QNetworkConfiguration::UserChoice; + cpPriv->purpose = QNetworkConfiguration::UnknownPurpose; + cpPriv->roamingSupported = false; + cpPriv->manager = this; + QExplicitlySharedDataPointer ptr(cpPriv); + userChoiceConfigurations.insert(cpPriv->id, ptr); + } + + /* We return currently configured IAPs in the first run and do the WLAN + * scan in subsequent runs. + */ + QList 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); + + 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(); + SSIDInfo *info = new SSIDInfo; + info->iap_id = iap_id; + info->wlan_security = security_method; + knownConfigs.insert(ssid, info); + } 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)) { + QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); + //cpPriv->name = iap_info.value().toString(); + 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; + cpPriv->manager = this; + + QExplicitlySharedDataPointer ptr(cpPriv); + accessPointConfigurations.insert(iap_id, ptr); + +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug("IAP: %s, name: %s, ssid: %s, added to known list", iap_id.toAscii().data(), cpPriv->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 (!firstUpdate) { + 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 priv = accessPointConfigurations.take(iapid); + if (priv.data()) { + priv->state = QNetworkConfiguration::Discovered; /* Defined is set automagically */ + priv->network_attrs = ap.scan.network_attrs; + priv->service_id = ap.scan.service_id; + priv->service_type = ap.scan.service_type; + priv->service_attrs = ap.scan.service_attrs; + + configurationChanged(priv.data()); + accessPointConfigurations.insert(iapid, priv); +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug("IAP: %s, ssid: %s, discovered", iapid.toAscii().data(), priv->network_id.data()); +#endif + + if (!ap.scan.network_type.startsWith("WLAN")) + continue; // not a wlan AP + + /* Remove scanned AP from known configurations so that we can + * emit configurationRemoved signal later + */ + QList known_iaps = knownConfigs.values(priv->network_id); + rescan_list: + if (!known_iaps.isEmpty()) { + for (int k=0; kiap_id << "security" << iap->wlan_security << "scan" << network_attrs_to_security(ap.scan.network_attrs); +#endif + + if (iap->wlan_security == + network_attrs_to_security(ap.scan.network_attrs)) { + /* Remove IAP from the list */ + knownConfigs.remove(priv->network_id, iap); +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug() << "Removed IAP" << iap->iap_id << "from unknown config"; +#endif + known_iaps.removeAt(k); + delete iap; + goto rescan_list; + } + } + } + } else { + qWarning() << "IAP" << iapid << "is missing in configuration."; + } + + } else { + /* Non saved access point data */ + QByteArray scanned_ssid = ap.scan.network_id; + QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); + QString hrs = scanned_ssid.data(); + + cpPriv->name = ap.network_name.isEmpty() ? hrs : ap.network_name; + cpPriv->isValid = true; + cpPriv->id = scanned_ssid.data(); // Note: id is now ssid, it should be set to IAP id if the IAP is saved + cpPriv->network_id = scanned_ssid; + cpPriv->iap_type = ap.scan.network_type; + 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->manager = this; + + cpPriv->type = QNetworkConfiguration::InternetAccessPoint; + cpPriv->state = QNetworkConfiguration::Undefined; + + QExplicitlySharedDataPointer ptr(cpPriv); + accessPointConfigurations.insert(cpPriv->id, ptr); + +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug() << "IAP with network id" << cpPriv->id << "was found in the scan."; +#endif + + QNetworkConfiguration item; + item.d = ptr; + emit configurationAdded(item); + } + } + + + /* Remove non existing iaps since last update */ + if (!firstUpdate) { + QHashIterator i(knownConfigs); + while (i.hasNext()) { + i.next(); + SSIDInfo *iap = i.value(); + QString iap_id = iap->iap_id; + //qDebug() << i.key() << ": " << iap_id; + + QExplicitlySharedDataPointer priv = accessPointConfigurations.take(iap_id); + if (priv.data()) { + priv->isValid = false; +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug() << "IAP" << iap_id << "was removed as it was not found in scan."; +#endif + + QNetworkConfiguration item; + item.d = priv; + emit configurationRemoved(item); + configChanged(priv.data(), false); + + //if we would have SNAP support we would have to remove the references + //from existing ServiceNetworks to the removed access point configuration + } + } + } + + + QMutableHashIterator i(knownConfigs); + while (i.hasNext()) { + i.next(); + SSIDInfo *iap = i.value(); + delete iap; + i.remove(); + } + + if (!firstUpdate) + emit configurationUpdateComplete(); + + if (firstUpdate) + firstUpdate = false; +} + + +QNetworkConfiguration QNetworkConfigurationManagerPrivate::defaultConfiguration() +{ + /* Here we just return [ANY] request to icd and let the icd decide which + * IAP to connect. + */ + QNetworkConfiguration item; + if (userChoiceConfigurations.contains(OSSO_IAP_ANY)) + item.d = userChoiceConfigurations.value(OSSO_IAP_ANY); + return item; +} + + +void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate() +{ + QTimer::singleShot(0, this, SLOT(updateConfigurations())); +} + + +void QNetworkConfigurationManagerPrivate::cleanup() +{ + iapMonitor()->cleanup(); +} + + +void QNetworkConfigurationManagerPrivate::configChanged(QNetworkConfigurationPrivate *ptr, bool added) +{ + if (added) { + if (ptr && ptr->state == QNetworkConfiguration::Active) { + onlineConfigurations++; + if (!firstUpdate && onlineConfigurations == 1) + emit onlineStateChanged(true); + } + } else { + if (ptr && ptr->state == QNetworkConfiguration::Active) { + onlineConfigurations--; + if (!firstUpdate && onlineConfigurations == 0) + emit onlineStateChanged(false); + if (onlineConfigurations < 0) + onlineConfigurations = 0; + } + } +} + + +#include "qnetworkconfigmanager_maemo.moc" +#include "moc_qnetworkconfigmanager_maemo_p.cpp" + +QTM_END_NAMESPACE diff --git a/src/network/bearer/qnetworkconfigmanager_maemo_p.h b/src/network/bearer/qnetworkconfigmanager_maemo_p.h new file mode 100644 index 0000000..e182495 --- /dev/null +++ b/src/network/bearer/qnetworkconfigmanager_maemo_p.h @@ -0,0 +1,141 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 QNETWORKCONFIGURATIONMANAGERPRIVATE_H +#define QNETWORKCONFIGURATIONMANAGERPRIVATE_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 +#include +#include + +#include +#include + +QTM_BEGIN_NAMESPACE + + +class QNetworkConfigurationManagerPrivate : public QObject +{ + Q_OBJECT +public: + QNetworkConfigurationManagerPrivate() + : QObject(0), capFlags(0), firstUpdate(true), onlineConfigurations(0) + { + registerPlatformCapabilities(); + updateConfigurations(); + } + + virtual ~QNetworkConfigurationManagerPrivate() + { + QList configIdents = snapConfigurations.keys(); + foreach(const QString oldIface, configIdents) { + QExplicitlySharedDataPointer priv = snapConfigurations.take(oldIface); + priv->isValid = false; + priv->id.clear(); + } + + configIdents = accessPointConfigurations.keys(); + foreach(const QString oldIface, configIdents) { + QExplicitlySharedDataPointer priv = accessPointConfigurations.take(oldIface); + priv->isValid = false; + priv->id.clear(); + } + + configIdents = userChoiceConfigurations.keys(); + foreach(const QString oldIface, configIdents) { + QExplicitlySharedDataPointer priv = userChoiceConfigurations.take(oldIface); + priv->isValid = false; + priv->id.clear(); + } + + cleanup(); + } + + QNetworkConfiguration defaultConfiguration(); + + QNetworkConfigurationManager::Capabilities capFlags; + void registerPlatformCapabilities(); + + void performAsyncConfigurationUpdate(); + + //this table contains an up to date list of all configs at any time. + //it must be updated if configurations change, are added/removed or + //the members of ServiceNetworks change + QHash > accessPointConfigurations; + QHash > snapConfigurations; + QHash > userChoiceConfigurations; + bool firstUpdate; + int onlineConfigurations; + friend class IapMonitor; + void cleanup(); + void deleteConfiguration(QString &iap_id); + void addConfiguration(QString &iap_id); + void configurationChanged(QNetworkConfigurationPrivate *ptr); + uint32_t getNetworkAttrs(bool is_iap_id, QString& iap_id, + QString& iap_type, QString security_method); + void configChanged(QNetworkConfigurationPrivate *ptr, bool added); + friend class QNetworkSessionPrivate; + +public slots: + void updateConfigurations(); + +Q_SIGNALS: + void configurationAdded(const QNetworkConfiguration& config); + void configurationRemoved(const QNetworkConfiguration& config); + void configurationUpdateComplete(); + void configurationChanged(const QNetworkConfiguration& config); + void onlineStateChanged(bool isOnline); +}; + +QTM_END_NAMESPACE + +#endif //QNETWORKCONFIGURATIONMANAGERPRIVATE_H diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp new file mode 100644 index 0000000..8b15f41 --- /dev/null +++ b/src/network/bearer/qnetworkconfigmanager_p.cpp @@ -0,0 +1,450 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 "qnetworkconfigmanager_p.h" +#include "qgenericengine_p.h" + +#ifdef Q_OS_WIN +#include "qnlaengine_win_p.h" +#endif +#ifdef Q_OS_WIN32 +#include "qnativewifiengine_win_p.h" +#endif +#if defined(BACKEND_NM) +#include "qnmwifiengine_unix_p.h" +#endif +#ifdef Q_OS_DARWIN +#include "qcorewlanengine_mac_p.h" +#endif + +#include +#include +#include + +QTM_BEGIN_NAMESPACE + +void QNetworkConfigurationManagerPrivate::registerPlatformCapabilities() +{ + capFlags = QNetworkConfigurationManager::ForcedRoaming; +} + +void QNetworkConfigurationManagerPrivate::configurationAdded(QNetworkConfigurationPrivate *cpPriv, QNetworkSessionEngine *engine) +{ + QExplicitlySharedDataPointer ptr(new QNetworkConfigurationPrivate); + + ptr.data()->isValid = cpPriv->isValid; + ptr.data()->name = cpPriv->name; + ptr.data()->id = cpPriv->id; + ptr.data()->state = cpPriv->state; + ptr.data()->type = cpPriv->type; + ptr.data()->roamingSupported = cpPriv->roamingSupported; + ptr.data()->purpose = cpPriv->purpose; + ptr.data()->internet = cpPriv->internet; + + accessPointConfigurations.insert(cpPriv->id, ptr); + configurationEngine.insert(cpPriv->id, engine); + + if (!firstUpdate) { + QNetworkConfiguration item; + item.d = ptr; + emit configurationAdded(item); + } + + if (ptr.data()->state == QNetworkConfiguration::Active) { + ++onlineConfigurations; + if (!firstUpdate && onlineConfigurations == 1) + emit onlineStateChanged(true); + } +} + +void QNetworkConfigurationManagerPrivate::configurationRemoved(const QString &id) +{ + if (!accessPointConfigurations.contains(id)) + return; + + QExplicitlySharedDataPointer ptr = + accessPointConfigurations.take(id); + + configurationEngine.remove(id); + + ptr.data()->isValid = false; + + if (!firstUpdate) { + QNetworkConfiguration item; + item.d = ptr; + emit configurationRemoved(item); + } + + if (ptr.data()->state == QNetworkConfiguration::Active) { + --onlineConfigurations; + if (!firstUpdate && onlineConfigurations == 0) + emit onlineStateChanged(false); + } +} + +void QNetworkConfigurationManagerPrivate::configurationChanged(QNetworkConfigurationPrivate *cpPriv) +{ + if (!accessPointConfigurations.contains(cpPriv->id)) + return; + + QExplicitlySharedDataPointer ptr = + accessPointConfigurations.value(cpPriv->id); + + if (ptr.data()->isValid != cpPriv->isValid || + ptr.data()->name != cpPriv->name || + ptr.data()->id != cpPriv->id || + ptr.data()->state != cpPriv->state || + ptr.data()->type != cpPriv->type || + ptr.data()->roamingSupported != cpPriv->roamingSupported || + ptr.data()->purpose != cpPriv->purpose || + ptr.data()->internet != cpPriv->internet) { + + const QNetworkConfiguration::StateFlags oldState = ptr.data()->state; + + ptr.data()->isValid = cpPriv->isValid; + ptr.data()->name = cpPriv->name; + ptr.data()->id = cpPriv->id; + ptr.data()->state = cpPriv->state; + ptr.data()->type = cpPriv->type; + ptr.data()->roamingSupported = cpPriv->roamingSupported; + ptr.data()->purpose = cpPriv->purpose; + ptr.data()->internet = cpPriv->internet; + + if (!firstUpdate) { + QNetworkConfiguration item; + item.d = ptr; + emit configurationChanged(item); + } + + if (ptr.data()->state == QNetworkConfiguration::Active && oldState != ptr.data()->state) { + // configuration went online + ++onlineConfigurations; + if (!firstUpdate && onlineConfigurations == 1) + emit onlineStateChanged(true); + } else if (ptr.data()->state != QNetworkConfiguration::Active && oldState == QNetworkConfiguration::Active) { + // configuration went offline + --onlineConfigurations; + if (!firstUpdate && onlineConfigurations == 0) + emit onlineStateChanged(false); + } + } +} + +void QNetworkConfigurationManagerPrivate::updateInternetServiceConfiguration() +{ + if (!snapConfigurations.contains(QLatin1String("Internet Service Network"))) { + QNetworkConfigurationPrivate *serviceNetwork = new QNetworkConfigurationPrivate; + serviceNetwork->name = tr("Internet"); + serviceNetwork->isValid = true; + serviceNetwork->id = QLatin1String("Internet Service Network"); + serviceNetwork->state = QNetworkConfiguration::Defined; + serviceNetwork->type = QNetworkConfiguration::ServiceNetwork; + + QExplicitlySharedDataPointer ptr(serviceNetwork); + + snapConfigurations.insert(serviceNetwork->id, ptr); + + if (!firstUpdate) { + QNetworkConfiguration item; + item.d = ptr; + emit configurationAdded(item); + } + } + + QExplicitlySharedDataPointer ptr = + snapConfigurations.value(QLatin1String("Internet Service Network")); + + QList > serviceNetworkMembers; + + QHash >::const_iterator i = + accessPointConfigurations.constBegin(); + + QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Defined; + while (i != accessPointConfigurations.constEnd()) { + QExplicitlySharedDataPointer child = i.value(); + + if (child.data()->internet && ((child.data()->state & QNetworkConfiguration::Defined) + == QNetworkConfiguration::Defined)) { + serviceNetworkMembers.append(child); + + state |= child.data()->state; + } + + ++i; + } + + + if (ptr.data()->state != state || ptr.data()->serviceNetworkMembers != serviceNetworkMembers) { + ptr.data()->state = state; + ptr.data()->serviceNetworkMembers = serviceNetworkMembers; + + QNetworkConfiguration item; + item.d = ptr; + emit configurationChanged(item); + } +} + +void QNetworkConfigurationManagerPrivate::updateConfigurations() +{ + if (firstUpdate) { + updateState = NotUpdating; + onlineConfigurations = 0; + +#if defined (Q_OS_DARWIN) + coreWifi = QCoreWlanEngine::instance(); + if (coreWifi) { + connect(coreWifi, SIGNAL(configurationsChanged()), + this, SLOT(updateConfigurations())); + } +#else +#if defined(BACKEND_NM) + nmWifi = QNmWifiEngine::instance(); + if (nmWifi) { + connect(nmWifi, SIGNAL(configurationsChanged()), + this, SLOT(updateConfigurations())); + } else { +#endif + generic = QGenericEngine::instance(); + if (generic) { + connect(generic, SIGNAL(configurationsChanged()), + this, SLOT(updateConfigurations())); + } +#if defined(BACKEND_NM) + } +#endif +#endif + +#ifdef Q_OS_WIN + nla = QNlaEngine::instance(); + if (nla) { + connect(nla, SIGNAL(configurationsChanged()), + this, SLOT(updateConfigurations())); + } +#endif + +#ifdef Q_OS_WIN32 + nativeWifi = QNativeWifiEngine::instance(); + if (nativeWifi) { + connect(nativeWifi, SIGNAL(configurationsChanged()), + this, SLOT(updateConfigurations())); + + capFlags |= QNetworkConfigurationManager::CanStartAndStopInterfaces; + } +#endif + } + + QNetworkSessionEngine *engine = qobject_cast(sender()); + if (updateState & Updating && engine) { +#if defined (Q_OS_DARWIN) + if (engine == coreWifi) + updateState &= ~CoreWifiUpdating; +#else +#if defined(BACKEND_NM) + if (engine == nmWifi) + updateState &= ~NmUpdating; + else if (engine == generic) + updateState &= ~GenericUpdating; +#else + if (engine == generic) + updateState &= ~GenericUpdating; +#endif +#endif + +#ifdef Q_OS_WIN + else if (engine == nla) + updateState &= ~NlaUpdating; +#ifdef Q_OS_WIN32 + else if (engine == nativeWifi) + updateState &= ~NativeWifiUpdating; +#endif +#endif + } + QList engines; + if (firstUpdate) { +#if defined (Q_OS_DARWIN) + if (coreWifi) + engines << coreWifi; +#else +#if defined(BACKEND_NM) + if (nmWifi) + engines << nmWifi; + else if (generic) + engines << generic; +#else + if (generic) + engines << generic; +#endif +#endif + +#ifdef Q_OS_WIN + if (nla) + engines << nla; +#ifdef Q_OS_WIN32 + if (nativeWifi) + engines << nativeWifi; +#endif +#endif + } else if (engine) { + engines << engine; + } + + while (!engines.isEmpty()) { + engine = engines.takeFirst(); + + bool ok; + QList foundConfigurations = engine->getConfigurations(&ok); + + // Find removed configurations. + QList removedIdentifiers = configurationEngine.keys(); + for (int i = 0; i < foundConfigurations.count(); ++i) + removedIdentifiers.removeOne(foundConfigurations.at(i)->id); + + // Update or add configurations. + while (!foundConfigurations.isEmpty()) { + QNetworkConfigurationPrivate *cpPriv = foundConfigurations.takeFirst(); + + if (accessPointConfigurations.contains(cpPriv->id)) + configurationChanged(cpPriv); + else + configurationAdded(cpPriv, engine); + + delete cpPriv; + } + + // Remove configurations. + while (!removedIdentifiers.isEmpty()) { + const QString id = removedIdentifiers.takeFirst(); + + if (configurationEngine.value(id) == engine) + configurationRemoved(id); + } + } + + updateInternetServiceConfiguration(); + + if (updateState == Updating) { + updateState = NotUpdating; + emit configurationUpdateComplete(); + } + + if (firstUpdate) + firstUpdate = false; +} + +/*! + Returns the first active configuration found, if one exists; otherwise returns the first + discovered configuration found, if one exists; otherwise returns an empty configuration. + + \internal +*/ +QNetworkConfiguration QNetworkConfigurationManagerPrivate::defaultConfiguration() +{ + QExplicitlySharedDataPointer firstActive; + QExplicitlySharedDataPointer firstDiscovered; + + QHash >::const_iterator i = + accessPointConfigurations.constBegin(); + while (i != accessPointConfigurations.constEnd()) { + QNetworkConfigurationPrivate *priv = i.value().data(); + + if (!firstActive && priv->isValid && + (priv->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) + firstActive = i.value(); + if (!firstDiscovered && priv->isValid && + (priv->state & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) + firstDiscovered = i.value(); + + ++i; + } + + QNetworkConfiguration item; + + if (firstActive) + item.d = firstActive; + else if (firstDiscovered) + item.d = firstDiscovered; + + return item; +} + +void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate() +{ + updateState = Updating; +#if defined (Q_OS_DARWIN) + if (coreWifi) { + updateState |= CoreWifiUpdating; + coreWifi->requestUpdate(); + } +#else +#if defined(BACKEND_NM) + if (nmWifi) { + updateState |= NmUpdating; + nmWifi->requestUpdate(); + } else if (generic) { + updateState |= GenericUpdating; + generic->requestUpdate(); + } +#else + if (generic) { + updateState |= GenericUpdating; + generic->requestUpdate(); + } +#endif +#endif +#ifdef Q_OS_WIN + if (nla) { + updateState |= NlaUpdating; + nla->requestUpdate(); + } +#endif + +#ifdef Q_OS_WIN32 + if (nativeWifi) { + updateState |= NativeWifiUpdating; + nativeWifi->requestUpdate(); + } +#endif +} + +#include "moc_qnetworkconfigmanager_p.cpp" + +QTM_END_NAMESPACE + diff --git a/src/network/bearer/qnetworkconfigmanager_p.h b/src/network/bearer/qnetworkconfigmanager_p.h new file mode 100644 index 0000000..0c42f9b --- /dev/null +++ b/src/network/bearer/qnetworkconfigmanager_p.h @@ -0,0 +1,178 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 QNETWORKCONFIGURATIONMANAGERPRIVATE_H +#define QNETWORKCONFIGURATIONMANAGERPRIVATE_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 "qnetworkconfigmanager.h" +#include "qnetworkconfiguration_p.h" + +#include +#include + +QTM_BEGIN_NAMESPACE + +#ifdef BEARER_ENGINE +class QNetworkSessionEngine; +class QGenericEngine; +class QNlaEngine; +class QNativeWifiEngine; +class QNmWifiEngine; +class QCoreWlanEngine; +#endif + + +class QNetworkConfigurationManagerPrivate : public QObject +{ + Q_OBJECT +public: + QNetworkConfigurationManagerPrivate() + : QObject(0), capFlags(0), firstUpdate(true) + { + registerPlatformCapabilities(); + updateConfigurations(); + } + + virtual ~QNetworkConfigurationManagerPrivate() + { + QList configIdents = snapConfigurations.keys(); + foreach(const QString oldIface, configIdents) { + QExplicitlySharedDataPointer priv = snapConfigurations.take(oldIface); + priv->isValid = false; + priv->id.clear(); + } + + configIdents = accessPointConfigurations.keys(); + foreach(const QString oldIface, configIdents) { + QExplicitlySharedDataPointer priv = accessPointConfigurations.take(oldIface); + priv->isValid = false; + priv->id.clear(); + } + } + + QNetworkConfiguration defaultConfiguration(); + + QNetworkConfigurationManager::Capabilities capFlags; + void registerPlatformCapabilities(); + + void performAsyncConfigurationUpdate(); + + //this table contains an up to date list of all configs at any time. + //it must be updated if configurations change, are added/removed or + //the members of ServiceNetworks change + QHash > accessPointConfigurations; + QHash > snapConfigurations; + QHash > userChoiceConfigurations; +#ifdef BEARER_ENGINE + QHash configurationEngine; +#endif + bool firstUpdate; + +public slots: + void updateConfigurations(); + +Q_SIGNALS: + void configurationAdded(const QNetworkConfiguration& config); + void configurationRemoved(const QNetworkConfiguration& config); + void configurationUpdateComplete(); + void configurationChanged(const QNetworkConfiguration& config); + void onlineStateChanged(bool isOnline); + +private: +#ifdef BEARER_ENGINE + void updateInternetServiceConfiguration(); + + void abort(); +#endif + +#ifdef BEARER_ENGINE + QGenericEngine *generic; +#ifdef Q_OS_WIN + QNlaEngine *nla; +#ifndef Q_OS_WINCE + QNativeWifiEngine *nativeWifi; +#endif +#endif +#ifdef BACKEND_NM + QNmWifiEngine *nmWifi; +#endif +#ifdef Q_OS_DARWIN + QCoreWlanEngine *coreWifi; +#endif + + uint onlineConfigurations; + + enum EngineUpdate { + NotUpdating = 0x00, + Updating = 0x01, + GenericUpdating = 0x02, + NlaUpdating = 0x04, + NativeWifiUpdating = 0x08, + NmUpdating = 0x20, + CoreWifiUpdating = 0x40, + }; + Q_DECLARE_FLAGS(EngineUpdateState, EngineUpdate) + + EngineUpdateState updateState; +#endif + +private Q_SLOTS: +#ifdef BEARER_ENGINE + void configurationAdded(QNetworkConfigurationPrivate *cpPriv, QNetworkSessionEngine *engine); + void configurationRemoved(const QString &id); + void configurationChanged(QNetworkConfigurationPrivate *cpPriv); +#endif +}; + +QTM_END_NAMESPACE + +#endif //QNETWORKCONFIGURATIONMANAGERPRIVATE_H diff --git a/src/network/bearer/qnetworkconfigmanager_s60_p.cpp b/src/network/bearer/qnetworkconfigmanager_s60_p.cpp new file mode 100644 index 0000000..760a194 --- /dev/null +++ b/src/network/bearer/qnetworkconfigmanager_s60_p.cpp @@ -0,0 +1,974 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 "qnetworkconfigmanager_s60_p.h" + +#include +#include +#include + +#ifdef SNAP_FUNCTIONALITY_AVAILABLE + #include + #include + #include + #include + #include + #include +#else + #include + #include + #include +#endif + +QTM_BEGIN_NAMESPACE + +static const int KValueThatWillBeAddedToSNAPId = 1000; +static const int KUserChoiceIAPId = 0; + +QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate() + : QObject(0), CActive(CActive::EPriorityIdle), capFlags(0), iFirstUpdate(true), iInitOk(true) +{ + CActiveScheduler::Add(this); + + registerPlatformCapabilities(); + 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 + + QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); + cpPriv->name = "UserChoice"; + cpPriv->bearer = QNetworkConfigurationPrivate::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; + cpPriv->manager = this; + QExplicitlySharedDataPointer ptr(cpPriv); + userChoiceConfigurations.insert(cpPriv->id, ptr); + + updateConfigurations(); + updateStatesToSnaps(); + + // Start monitoring IAP and/or SNAP changes in Symbian CommsDB + startCommsDatabaseNotifications(); +} + +QNetworkConfigurationManagerPrivate::~QNetworkConfigurationManagerPrivate() +{ + Cancel(); + + QList configIdents = snapConfigurations.keys(); + foreach(QString oldIface, configIdents) { + QExplicitlySharedDataPointer priv = snapConfigurations.take(oldIface); + priv->isValid = false; + priv->id.clear(); + } + + configIdents = accessPointConfigurations.keys(); + foreach(QString oldIface, configIdents) { + QExplicitlySharedDataPointer priv = accessPointConfigurations.take(oldIface); + priv->isValid = false; + priv->id.clear(); + } + + configIdents = userChoiceConfigurations.keys(); + foreach(QString oldIface, configIdents) { + QExplicitlySharedDataPointer priv = userChoiceConfigurations.take(oldIface); + priv->isValid = false; + priv->id.clear(); + priv->manager = 0; + } + + iConnectionMonitor.CancelNotifications(); + iConnectionMonitor.Close(); + +#ifdef SNAP_FUNCTIONALITY_AVAILABLE + iCmManager.Close(); +#endif + + delete ipAccessPointsAvailabilityScanner; + delete ipCommsDB; +} + + +void QNetworkConfigurationManagerPrivate::registerPlatformCapabilities() +{ + capFlags |= QNetworkConfigurationManager::CanStartAndStopInterfaces; + capFlags |= QNetworkConfigurationManager::DirectConnectionRouting; + capFlags |= QNetworkConfigurationManager::SystemSessionSupport; +#ifdef SNAP_FUNCTIONALITY_AVAILABLE + capFlags |= QNetworkConfigurationManager::ApplicationLevelRoaming; + capFlags |= QNetworkConfigurationManager::ForcedRoaming; +#endif + capFlags |= QNetworkConfigurationManager::DataStatistics; +} + +void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate() +{ + if (!iInitOk || iUpdateGoingOn) { + return; + } + iUpdateGoingOn = true; + + stopCommsDatabaseNotifications(); + updateConfigurations(); // Synchronous call + updateAvailableAccessPoints(); // Asynchronous call +} + +void QNetworkConfigurationManagerPrivate::updateConfigurations() +{ + if (!iInitOk) { + return; + } + + TRAP_IGNORE(updateConfigurationsL()); +} + +void QNetworkConfigurationManagerPrivate::updateConfigurationsL() +{ + QList knownConfigs = accessPointConfigurations.keys(); + QList knownSnapConfigs = snapConfigurations.keys(); + +#ifdef SNAP_FUNCTIONALITY_AVAILABLE + // S60 version is >= Series60 3rd Edition Feature Pack 2 + TInt error = KErrNone; + + // Loop through all IAPs + RArray 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 { + QNetworkConfigurationPrivate* cpPriv = NULL; + TRAP(error, cpPriv = configFromConnectionMethodL(connectionMethod)); + if (error == KErrNone) { + QExplicitlySharedDataPointer ptr(cpPriv); + accessPointConfigurations.insert(cpPriv->id, ptr); + if (!iFirstUpdate) { + QNetworkConfiguration item; + item.d = ptr; + emit configurationAdded(item); + } + } + } + CleanupStack::PopAndDestroy(&connectionMethod); + } + CleanupStack::PopAndDestroy(&connectionMethods); + + // Loop through all SNAPs + RArray 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 { + QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); + 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; + cpPriv->manager = this; + + QExplicitlySharedDataPointer ptr(cpPriv); + snapConfigurations.insert(ident, ptr); + if (!iFirstUpdate) { + QNetworkConfiguration item; + item.d = ptr; + emit configurationAdded(item); + } + + CleanupStack::Pop(cpPriv); + } + QExplicitlySharedDataPointer 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 + QExplicitlySharedDataPointer priv = accessPointConfigurations.value(iface); + if (priv.data() == 0) { + QNetworkConfigurationPrivate* cpPriv = NULL; + TRAP(error, cpPriv = configFromConnectionMethodL(connectionMethod)); + if (error == KErrNone) { + QExplicitlySharedDataPointer ptr(cpPriv); + ptr.data()->serviceNetworkPtr = privSNAP; + accessPointConfigurations.insert(cpPriv->id, ptr); + if (!iFirstUpdate) { + QNetworkConfiguration item; + item.d = ptr; + emit configurationAdded(item); + } + 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; iserviceNetworkMembers.count(); i++) { + if (privSNAP->serviceNetworkMembers[i]->numericId == iapId) { + iapFound = true; + break; + } + } + if (!iapFound) { + priv.data()->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 { + QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); + if (readNetworkConfigurationValuesFromCommsDb(apId, cpPriv)) { + QExplicitlySharedDataPointer ptr(cpPriv); + accessPointConfigurations.insert(ident, ptr); + if (!iFirstUpdate) { + QNetworkConfiguration item; + item.d = ptr; + emit configurationAdded(item); + } + } else { + delete cpPriv; + } + } + retVal = pDbTView->GotoNextRecord(); + } + CleanupStack::PopAndDestroy(pDbTView); +#endif + updateActiveAccessPoints(); + + foreach (QString oldIface, knownConfigs) { + //remove non existing IAP + QExplicitlySharedDataPointer priv = accessPointConfigurations.take(oldIface); + priv->isValid = false; + if (!iFirstUpdate) { + QNetworkConfiguration item; + item.d = priv; + emit configurationRemoved(item); + } + // Remove non existing IAP from SNAPs + QList snapConfigIdents = snapConfigurations.keys(); + foreach (QString iface, snapConfigIdents) { + QExplicitlySharedDataPointer priv2 = snapConfigurations.value(iface); + // => Check if one of the IAPs of the SNAP is active + for (int i=0; iserviceNetworkMembers.count(); i++) { + if (priv2->serviceNetworkMembers[i]->numericId == priv->numericId) { + priv2->serviceNetworkMembers.removeAt(i); + break; + } + } + } + } + foreach (QString oldIface, knownSnapConfigs) { + //remove non existing SNAPs + QExplicitlySharedDataPointer priv = snapConfigurations.take(oldIface); + priv->isValid = false; + if (!iFirstUpdate) { + QNetworkConfiguration item; + item.d = priv; + emit configurationRemoved(item); + } + } + + iFirstUpdate = false; +} + +#ifdef SNAP_FUNCTIONALITY_AVAILABLE +QNetworkConfigurationPrivate* QNetworkConfigurationManagerPrivate::configFromConnectionMethodL( + RCmConnectionMethod& connectionMethod) +{ + QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); + 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 = QNetworkConfigurationPrivate::Bearer2G; + break; + case KCommDbBearerWcdma: + cpPriv->bearer = QNetworkConfigurationPrivate::BearerWCDMA; + break; + case KCommDbBearerLAN: + cpPriv->bearer = QNetworkConfigurationPrivate::BearerEthernet; + break; + case KCommDbBearerVirtual: + cpPriv->bearer = QNetworkConfigurationPrivate::BearerUnknown; + break; + case KCommDbBearerPAN: + cpPriv->bearer = QNetworkConfigurationPrivate::BearerUnknown; + break; + case KCommDbBearerWLAN: + cpPriv->bearer = QNetworkConfigurationPrivate::BearerWLAN; + break; + default: + cpPriv->bearer = QNetworkConfigurationPrivate::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; + cpPriv->manager = this; + + CleanupStack::Pop(cpPriv); + return cpPriv; +} +#else +bool QNetworkConfigurationManagerPrivate::readNetworkConfigurationValuesFromCommsDb( + TUint32 aApId, QNetworkConfigurationPrivate* apNetworkConfiguration) +{ + TRAPD(error, readNetworkConfigurationValuesFromCommsDbL(aApId,apNetworkConfiguration)); + if (error != KErrNone) { + return false; + } + return true; +} + +void QNetworkConfigurationManagerPrivate::readNetworkConfigurationValuesFromCommsDbL( + TUint32 aApId, QNetworkConfigurationPrivate* apNetworkConfiguration) +{ + CApDataHandler* pDataHandler = CApDataHandler::NewLC(*ipCommsDB); + CApAccessPointItem* pAPItem = CApAccessPointItem::NewLC(); + TBuf 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 = QNetworkConfigurationPrivate::Bearer2G; + break; + case EApBearerTypeGPRS: + apNetworkConfiguration->bearer = QNetworkConfigurationPrivate::Bearer2G; + break; + case EApBearerTypeHSCSD: + apNetworkConfiguration->bearer = QNetworkConfigurationPrivate::BearerHSPA; + break; + case EApBearerTypeCDMA: + apNetworkConfiguration->bearer = QNetworkConfigurationPrivate::BearerCDMA2000; + break; + case EApBearerTypeWLAN: + apNetworkConfiguration->bearer = QNetworkConfigurationPrivate::BearerWLAN; + break; + case EApBearerTypeLAN: + apNetworkConfiguration->bearer = QNetworkConfigurationPrivate::BearerEthernet; + break; + case EApBearerTypeLANModem: + apNetworkConfiguration->bearer = QNetworkConfigurationPrivate::BearerEthernet; + break; + default: + apNetworkConfiguration->bearer = QNetworkConfigurationPrivate::BearerUnknown; + break; + } + apNetworkConfiguration->manager = this; + + CleanupStack::PopAndDestroy(pApUtils); + CleanupStack::PopAndDestroy(pAPItem); + CleanupStack::PopAndDestroy(pDataHandler); +} +#endif + +QNetworkConfiguration QNetworkConfigurationManagerPrivate::defaultConfiguration() +{ + QNetworkConfiguration config; + + if (iInitOk) { + stopCommsDatabaseNotifications(); + TRAP_IGNORE(config = defaultConfigurationL()); + startCommsDatabaseNotifications(); + } + + return config; +} + +QNetworkConfiguration QNetworkConfigurationManagerPrivate::defaultConfigurationL() +{ + QNetworkConfiguration item; + +#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)); + QExplicitlySharedDataPointer priv = snapConfigurations.value(iface); + if (priv.data() != 0) { + item.d = priv; + } + } else if (defaultConnectionValue.iType == ECmDefConnConnectionMethod) { + QString iface = QString::number(qHash(defaultConnectionValue.iId)); + QExplicitlySharedDataPointer priv = accessPointConfigurations.value(iface); + if (priv.data() != 0) { + item.d = priv; + } + } +#endif + + if (!item.isValid()) { + QString iface = QString::number(qHash(KUserChoiceIAPId)); + QExplicitlySharedDataPointer priv = userChoiceConfigurations.value(iface); + if (priv.data() != 0) { + item.d = priv; + } + } + + return item; +} + +void QNetworkConfigurationManagerPrivate::updateActiveAccessPoints() +{ + bool online = false; + QList 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)); + QExplicitlySharedDataPointer priv = accessPointConfigurations.value(ident); + if (priv.data()) { + online = true; + inactiveConfigs.removeOne(ident); + priv.data()->connectionId = connectionId; + // Configuration is Active + changeConfigurationStateTo(priv, QNetworkConfiguration::Active); + } + } + } + + // Make sure that state of rest of the IAPs won't be Active + foreach (QString iface, inactiveConfigs) { + QExplicitlySharedDataPointer priv = accessPointConfigurations.value(iface); + if (priv.data()) { + // Configuration is either Defined or Discovered + changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Discovered); + } + } + + if (iOnline != online) { + iOnline = online; + emit this->onlineStateChanged(iOnline); + } +} + +void QNetworkConfigurationManagerPrivate::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 QNetworkConfigurationManagerPrivate::accessPointScanningReady(TBool scanSuccessful, TConnMonIapInfo iapInfo) +{ + iUpdateGoingOn = false; + if (scanSuccessful) { + QList unavailableConfigs = accessPointConfigurations.keys(); + + // Set state of returned IAPs to Discovered + // if state is not already Active + for(TUint i=0; i priv = accessPointConfigurations.value(ident); + if (priv.data()) { + unavailableConfigs.removeOne(ident); + if (priv.data()->state < QNetworkConfiguration::Active) { + // Configuration is either Discovered or Active + changeConfigurationStateAtMinTo(priv, QNetworkConfiguration::Discovered); + } + } + } + + // Make sure that state of rest of the IAPs won't be Discovered or Active + foreach (QString iface, unavailableConfigs) { + QExplicitlySharedDataPointer priv = accessPointConfigurations.value(iface); + if (priv.data()) { + // Configuration is Defined + changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Defined); + } + } + } + + updateStatesToSnaps(); + + startCommsDatabaseNotifications(); + + emit this->configurationUpdateComplete(); +} + +void QNetworkConfigurationManagerPrivate::updateStatesToSnaps() +{ + // Go through SNAPs and set correct state to SNAPs + QList snapConfigIdents = snapConfigurations.keys(); + foreach (QString iface, snapConfigIdents) { + bool discovered = false; + bool active = false; + QExplicitlySharedDataPointer priv = 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; iserviceNetworkMembers.count(); i++) { + QExplicitlySharedDataPointer priv2 = priv->serviceNetworkMembers[i]; + if ((priv->serviceNetworkMembers[i]->state & QNetworkConfiguration::Active) + == QNetworkConfiguration::Active) { + active = true; + break; + } else if ((priv->serviceNetworkMembers[i]->state & QNetworkConfiguration::Discovered) + == QNetworkConfiguration::Discovered) { + discovered = true; + } + } + if (active) { + changeConfigurationStateTo(priv, QNetworkConfiguration::Active); + } else if (discovered) { + changeConfigurationStateTo(priv, QNetworkConfiguration::Discovered); + } else { + changeConfigurationStateTo(priv, QNetworkConfiguration::Defined); + } + } +} + +bool QNetworkConfigurationManagerPrivate::changeConfigurationStateTo(QExplicitlySharedDataPointer& sharedData, + QNetworkConfiguration::StateFlags newState) +{ + if (newState != sharedData.data()->state) { + sharedData.data()->state = newState; + QNetworkConfiguration item; + item.d = sharedData; + if (!iFirstUpdate) { + emit configurationChanged(item); + } + 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 QNetworkConfigurationManagerPrivate::changeConfigurationStateAtMinTo(QExplicitlySharedDataPointer& sharedData, + QNetworkConfiguration::StateFlags newState) +{ + if ((newState | sharedData.data()->state) != sharedData.data()->state) { + sharedData.data()->state = (sharedData.data()->state | newState); + QNetworkConfiguration item; + item.d = sharedData; + if (!iFirstUpdate) { + emit configurationChanged(item); + } + 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 QNetworkConfigurationManagerPrivate::changeConfigurationStateAtMaxTo(QExplicitlySharedDataPointer& sharedData, + QNetworkConfiguration::StateFlags newState) +{ + if ((newState & sharedData.data()->state) != sharedData.data()->state) { + sharedData.data()->state = (newState & sharedData.data()->state); + QNetworkConfiguration item; + item.d = sharedData; + if (!iFirstUpdate) { + emit configurationChanged(item); + } + return true; + } + return false; +} + +void QNetworkConfigurationManagerPrivate::startCommsDatabaseNotifications() +{ + if (!iWaitingCommsDatabaseNotifications) { + iWaitingCommsDatabaseNotifications = ETrue; + if (!IsActive()) { + SetActive(); + // Start waiting for new notification + ipCommsDB->RequestNotification(iStatus); + } + } +} + +void QNetworkConfigurationManagerPrivate::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 QNetworkConfigurationManagerPrivate::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 QNetworkConfigurationManagerPrivate::DoCancel() +{ + ipCommsDB->CancelRequestNotification(); +} + + +void QNetworkConfigurationManagerPrivate::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)); + QExplicitlySharedDataPointer priv = accessPointConfigurations.value(ident); + if (priv.data()) { + priv.data()->connectionId = connectionId; + // Configuration is Active + if (changeConfigurationStateTo(priv, QNetworkConfiguration::Active)) { + updateStatesToSnaps(); + } + if (!iOnline) { + iOnline = true; + emit this->onlineStateChanged(iOnline); + } + } + } + break; + + case EConnMonDeleteConnection: + { + CConnMonDeleteConnection* realEvent; + realEvent = (CConnMonDeleteConnection*) &aEvent; + TUint connectionId = realEvent->ConnectionId(); + QExplicitlySharedDataPointer priv = dataByConnectionId(connectionId); + if (priv.data()) { + priv.data()->connectionId = 0; + // Configuration is either Defined or Discovered + if (changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Discovered)) { + updateStatesToSnaps(); + } + } + + bool online = false; + QList iapConfigs = accessPointConfigurations.keys(); + foreach (QString iface, iapConfigs) { + QExplicitlySharedDataPointer priv = accessPointConfigurations.value(iface); + if (priv.data()->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 unDiscoveredConfigs = accessPointConfigurations.keys(); + for ( TUint i = 0; i < iaps.Count(); i++ ) { + QString ident = QString::number(qHash(iaps.iIap[i].iIapId)); + QExplicitlySharedDataPointer priv = accessPointConfigurations.value(ident); + if (priv.data()) { + // Configuration is either Discovered or Active + changeConfigurationStateAtMinTo(priv, QNetworkConfiguration::Discovered); + unDiscoveredConfigs.removeOne(ident); + } + } + foreach (QString iface, unDiscoveredConfigs) { + QExplicitlySharedDataPointer priv = accessPointConfigurations.value(iface); + if (priv.data()) { + // Configuration is Defined + changeConfigurationStateAtMaxTo(priv, QNetworkConfiguration::Defined); + } + } + } + break; + + default: + // For unrecognized events + break; + } +} + +QExplicitlySharedDataPointer QNetworkConfigurationManagerPrivate::dataByConnectionId(TUint aConnectionId) +{ + QNetworkConfiguration item; + + QHash >::const_iterator i = + accessPointConfigurations.constBegin(); + while (i != accessPointConfigurations.constEnd()) { + QExplicitlySharedDataPointer priv = i.value(); + if (priv.data()->connectionId == aConnectionId) { + return priv; + } + ++i; + } + + return QExplicitlySharedDataPointer(); +} + +AccessPointsAvailabilityScanner::AccessPointsAvailabilityScanner(QNetworkConfigurationManagerPrivate& 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()); + } +} +#include "moc_qnetworkconfigmanager_s60_p.cpp" +QTM_END_NAMESPACE diff --git a/src/network/bearer/qnetworkconfigmanager_s60_p.h b/src/network/bearer/qnetworkconfigmanager_s60_p.h new file mode 100644 index 0000000..296d67f --- /dev/null +++ b/src/network/bearer/qnetworkconfigmanager_s60_p.h @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 QNETWORKCONFIGURATIONMANAGERPRIVATE_H +#define QNETWORKCONFIGURATIONMANAGERPRIVATE_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 +#include + +#include +#include +#ifdef SNAP_FUNCTIONALITY_AVAILABLE + #include +#endif + +class CCommsDatabase; +class QTimer; + +QTM_BEGIN_NAMESPACE + +class QNetworkSessionPrivate; +class AccessPointsAvailabilityScanner; + +class QNetworkConfigurationManagerPrivate : public QObject, public CActive, public MConnectionMonitorObserver +{ + Q_OBJECT + +public: + QNetworkConfigurationManagerPrivate(); + virtual ~QNetworkConfigurationManagerPrivate(); + + QNetworkConfiguration defaultConfiguration(); + void performAsyncConfigurationUpdate(); + +Q_SIGNALS: + void configurationAdded(const QNetworkConfiguration& config); + void configurationRemoved(const QNetworkConfiguration& config); + void configurationUpdateComplete(); + void configurationChanged(const QNetworkConfiguration& config); + void onlineStateChanged(bool isOnline); + +public Q_SLOTS: + void updateConfigurations(); + +private: + void registerPlatformCapabilities(); + void updateStatesToSnaps(); + bool changeConfigurationStateTo(QExplicitlySharedDataPointer& sharedData, + QNetworkConfiguration::StateFlags newState); + bool changeConfigurationStateAtMinTo(QExplicitlySharedDataPointer& sharedData, + QNetworkConfiguration::StateFlags newState); + bool changeConfigurationStateAtMaxTo(QExplicitlySharedDataPointer& sharedData, + QNetworkConfiguration::StateFlags newState); +#ifdef SNAP_FUNCTIONALITY_AVAILABLE + QNetworkConfigurationPrivate* configFromConnectionMethodL(RCmConnectionMethod& connectionMethod); +#else + bool readNetworkConfigurationValuesFromCommsDb( + TUint32 aApId, QNetworkConfigurationPrivate* apNetworkConfiguration); + void readNetworkConfigurationValuesFromCommsDbL( + TUint32 aApId, QNetworkConfigurationPrivate* apNetworkConfiguration); +#endif + + void updateConfigurationsL(); + void updateActiveAccessPoints(); + void updateAvailableAccessPoints(); + void accessPointScanningReady(TBool scanSuccessful, TConnMonIapInfo iapInfo); + void startCommsDatabaseNotifications(); + void stopCommsDatabaseNotifications(); + + QNetworkConfiguration defaultConfigurationL(); + TBool GetS60PlatformVersion(TUint& aMajor, TUint& aMinor) const; + void startMonitoringIAPData(TUint32 aIapId); + QExplicitlySharedDataPointer dataByConnectionId(TUint aConnectionId); + +protected: // From CActive + void RunL(); + void DoCancel(); + +private: // MConnectionMonitorObserver + void EventL(const CConnMonEventBase& aEvent); + +public: // Data + //this table contains an up to date list of all configs at any time. + //it must be updated if configurations change, are added/removed or + //the members of ServiceNetworks change + QHash > accessPointConfigurations; + QHash > snapConfigurations; + QHash > userChoiceConfigurations; + QNetworkConfigurationManager::Capabilities capFlags; + +private: // Data + bool iFirstUpdate; + 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(QNetworkConfigurationManagerPrivate& owner, + RConnectionMonitor& connectionMonitor); + ~AccessPointsAvailabilityScanner(); + + void StartScanning(); + +protected: // From CActive + void RunL(); + void DoCancel(); + +private: // Data + QNetworkConfigurationManagerPrivate& iOwner; + RConnectionMonitor& iConnectionMonitor; + TConnMonIapInfoBuf iIapBuf; +}; + +QTM_END_NAMESPACE + +#endif //QNETWORKCONFIGURATIONMANAGERPRIVATE_H diff --git a/src/network/bearer/qnetworkconfiguration.cpp b/src/network/bearer/qnetworkconfiguration.cpp new file mode 100644 index 0000000..c92b356 --- /dev/null +++ b/src/network/bearer/qnetworkconfiguration.cpp @@ -0,0 +1,349 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 "qnetworkconfiguration.h" + +#ifdef Q_OS_SYMBIAN +#include "qnetworkconfiguration_s60_p.h" +#else +#include "qnetworkconfiguration_p.h" +#endif + +QTM_BEGIN_NAMESPACE + +/*! + \class QNetworkConfiguration + + \brief The QNetworkConfiguration class provides an abstraction of one or more access point configurations. + + \inmodule QtNetwork + \ingroup bearer + + QNetworkConfiguration encapsulates a single access point or service network. + In most cases a single access point configuration can be mapped to one network + interface. However a single network interface may not always map to only one + access point configuration. Multiple configurations for the same + network device may enable multiple access points. An example + device that could exhibit such a configuration might be a + Smartphone which allows the user to manage multiple WLAN + configurations while the device itself has only one WLAN network device. + + The QNetworkConfiguration also supports the concept of service networks. + This concept allows the grouping of multiple access point configurations + into one entity. Such a group is called service network and can be + beneficial in cases whereby a network session to a + particular destination network is required (e.g. a company network). + When using a service network the user doesn't usually care which one of the + connectivity options is chosen (e.g. corporate WLAN or VPN via GPRS) + as long as he can reach the company's target server. Depending + on the current position and time some of the access points that make + up the service network may not even be available. Furthermore + automated access point roaming can be enabled which enables the device + to change the network interface configuration dynamically while maintaining + the applications connection to the target network. It allows adaption + to the changing environment and may enable optimization with regards to + cost, speed or other network parameters. + + Special configurations of type UserChoice provide a placeholder configuration which is + resolved to an actual network configuration by the platform when a + \l {QNetworkSession}{session} is \l {QNetworkSession::open()}{opened}. Not all platforms + support the concept of a user choice configuration. + + \section1 Configuration states + + The list of available configurations can be obtained via + QNetworkConfigurationManager::allConfigurations(). A configuration can have + multiple states. The \l Defined configuration state indicates that the configuration + is stored on the device. However the configuration is not yet ready to be activated + as e.g. a WLAN may not be available at the current time. + + The \l Discovered state implies that the configuration is \l Defined and + the outside conditions are such that the configuration can be used immediately + to open a new network session. An example of such an outside condition may be + that the Ethernet cable is actually connected to the device or that the WLAN + with the specified SSID is in range. + + The \l Active state implies that the configuration is \l Discovered. A configuration + in this state is currently being used by an application. The underlying network + interface has a valid IP configuration and can transfer IP packets between the + device and the target network. + + The \l Undefined state indicates that the system has knowledge of possible target + networks but cannot actually use that knowledge to connect to it. An example + for such a state could be an encrypted WLAN that has been discovered + but the user hasn't actually saved a configuration including the required password + which would allow the device to connect to it. + + Depending on the type of configuration some states are transient in nature. A GPRS/UMTS + connection may almost always be \l Discovered if the GSM/UMTS network is available. + However if the GSM/UMTS network looses the connection the associated configuration may change its state + from \l Discovered to \l Defined as well. A similar use case might be triggered by + WLAN availability. QNetworkConfigurationManager::updateConfigurations() can be used to + manually trigger updates of states. Note that some platforms do not require such updates + as they implicitly change the state once it has been discovered. If the state of a + configuration changes all related QNetworkConfiguration instances change their state automatically. + + \sa QNetworkSession, QNetworkConfigurationManager +*/ + +/*! + \enum QNetworkConfiguration::Type + + This enum describes the type of configuration. + + \value InternetAccessPoint The configuration specifies the details for a single access point. + Note that configurations of type InternetAccessPoint may be part + of other QNetworkConfigurations of type ServiceNetwork. + \value ServiceNetwork The configuration is based on a group of QNetworkConfigurations of + type InternetAccessPoint. All group members can reach the same + target network. This type of configuration is a mandatory + requirement for roaming enabled network sessions. On some + platforms this form of configuration may also be called Service + Network Access Point (SNAP). + \value UserChoice The configuration is a placeholder which will be resolved to an + actual configuration by the platform when a session is opened. Depending + on the platform the selection may generate a popup dialog asking the user + for his preferred choice. + \value Invalid The configuration is invalid. +*/ + +/*! + \enum QNetworkConfiguration::StateFlag + + Specifies the configuration states. + + \value Undefined This state is used for transient configurations such as newly discovered + WLANs for which the user has not actually created a configuration yet. + \value Defined Defined configurations are known to the system but are not immediately + usable (e.g. a configured WLAN is not within range or the Ethernet cable + is currently not plugged into the machine). + \value Discovered A discovered configuration can be immediately used to create a new + QNetworkSession. An example of a discovered configuration could be a WLAN + which is within in range. If the device moves out of range the discovered + flag is dropped. A second example is a GPRS configuration which generally + remains discovered for as long as the phone has network coverage. A + configuration that has this state is also in state + QNetworkConfiguration::Defined. If the configuration is a service network + this flag is set if at least one of the underlying access points + configurations has the Discovered state. + \value Active The configuration is currently used by an open/active network session + (see \l QNetworkSession::isActive()). However this does not mean that the + current process is the entity that created the active session. It merely + indicates that if a new QNetworkSession were to be constructed based on + this configuration \l QNetworkSession::state() would return + \l QNetworkSession::Connected. This state implies the + QNetworkConfiguration::Discovered state. +*/ + +/*! + \enum QNetworkConfiguration::Purpose + + Specifies the purpose of the configuration. + + \value UnknownPurpose The configuration doesn't specify any purpose. This is the default value. + \value PublicPurpose The configuration can be used for general purpose internet access. + \value PrivatePurpose The configuration is suitable to access a private network such as an office Intranet. + \value ServiceSpecificPurpose The configuration can be used for operator specific services (e.g. + receiving MMS messages or content streaming). +*/ + +/*! + Constructs an invalid configuration object. + + \sa isValid() +*/ +QNetworkConfiguration::QNetworkConfiguration() + : d(0) +{ +} + +/*! + Creates a copy of the QNetworkConfiguration object contained in \a other. +*/ +QNetworkConfiguration::QNetworkConfiguration(const QNetworkConfiguration& other) + : d(other.d) +{ +} + +/*! + Copies the content of the QNetworkConfiguration object contained in \a other into this one. +*/ +QNetworkConfiguration& QNetworkConfiguration::operator=(const QNetworkConfiguration& other) +{ + d = other.d; + return *this; +} + +/*! + Frees the resources associated with the QNetworkConfiguration object. +*/ +QNetworkConfiguration::~QNetworkConfiguration() +{ +} + +/*! + Returns true, if this configuration is the same as the \a other + configuration given; otherwise returns false. +*/ +bool QNetworkConfiguration::operator==(const QNetworkConfiguration& other) const +{ + if (!d) + return !other.d; + + if (!other.d) + return false; + + return (d == other.d); +} + +/*! + \fn bool QNetworkConfiguration::operator!=(const QNetworkConfiguration& other) const + + Returns true if this configuration is not the same as the \a other + configuration given; otherwise returns false. +*/ + +/*! + Returns the user visible name of this configuration. + + The name may either be the name of the underlying access point or the + name for service network that this configuration represents. +*/ +QString QNetworkConfiguration::name() const +{ + return d ? d->name : QString(); +} + +/*! + Returns the unique and platform specific identifier for this network configuration; + otherwise an empty string. +*/ +QString QNetworkConfiguration::identifier() const +{ + return d ? d->id : QString(); +} + +/*! + Returns the type of the configuration. + + A configuration can represent a single access point configuration or + a set of access point configurations. Such a set is called service network. + A configuration that is based on a service network can potentially support + roaming of network sessions. +*/ +QNetworkConfiguration::Type QNetworkConfiguration::type() const +{ + return d ? d->type : QNetworkConfiguration::Invalid; +} + +/*! + Returns true if this QNetworkConfiguration object is valid. + A configuration may become invalid if the user deletes the configuration or + the configuration was default-constructed. + + The addition and removal of configurations can be monitored via the + QNetworkConfigurationManager. + + \sa QNetworkConfigurationManager +*/ +bool QNetworkConfiguration::isValid() const +{ + return d ? d->isValid : false; +} + +/*! + Returns the current state of the configuration. +*/ +QNetworkConfiguration::StateFlags QNetworkConfiguration::state() const +{ + return d ? d->state : QNetworkConfiguration::Undefined; +} + +/*! + Returns the purpose of this configuration. + + The purpose field may be used to programmatically determine the + purpose of a configuration. Such information is usually part of the + access point or service network meta data. +*/ +QNetworkConfiguration::Purpose QNetworkConfiguration::purpose() const +{ + return d ? d->purpose : QNetworkConfiguration::UnknownPurpose; +} + +/*! + Returns true if this configuration supports roaming; otherwise false. +*/ +bool QNetworkConfiguration::isRoamingAvailable() const +{ + return d ? d->roamingSupported : false; +} + +/*! + Returns all sub configurations of this network configuration. + Only network configurations of type \l ServiceNetwork can have children. Otherwise + this function returns an empty list. +*/ +QList QNetworkConfiguration::children() const +{ + QList results; + if (type() != QNetworkConfiguration::ServiceNetwork || !isValid() ) + return results; + + QMutableListIterator > iter(d->serviceNetworkMembers); + QExplicitlySharedDataPointer p(0); + while(iter.hasNext()) { + p = iter.next(); + //if we have an invalid member get rid of it -> was deleted earlier on + if (!p->isValid) + iter.remove(); + + QNetworkConfiguration item; + item.d = p; + results << item; + } + + return results; +} + + +QTM_END_NAMESPACE + diff --git a/src/network/bearer/qnetworkconfiguration.h b/src/network/bearer/qnetworkconfiguration.h new file mode 100644 index 0000000..f8c17d5 --- /dev/null +++ b/src/network/bearer/qnetworkconfiguration.h @@ -0,0 +1,113 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 QNETWORKCONFIGURATION_H +#define QNETWORKCONFIGURATION_H + +#include "qmobilityglobal.h" + +#include +#include +#include + +QT_BEGIN_HEADER + +QTM_BEGIN_NAMESPACE + +class QNetworkConfigurationPrivate; +class Q_BEARER_EXPORT QNetworkConfiguration +{ +public: + QNetworkConfiguration(); + QNetworkConfiguration(const QNetworkConfiguration& other); + QNetworkConfiguration &operator=(const QNetworkConfiguration& other); + ~QNetworkConfiguration(); + + bool operator==(const QNetworkConfiguration& cp) const; + inline bool operator!=(const QNetworkConfiguration& cp) const + { return !operator==(cp); } + + enum Type { + InternetAccessPoint = 0, + ServiceNetwork, + UserChoice, + Invalid + }; + + enum Purpose { + UnknownPurpose = 0, + PublicPurpose, + PrivatePurpose, + ServiceSpecificPurpose + }; + + enum StateFlag { + Undefined = 0x0000001, + Defined = 0x0000002, + Discovered = 0x0000006, + Active = 0x000000e + }; + + Q_DECLARE_FLAGS(StateFlags, StateFlag) + + StateFlags state() const; + Type type() const; + Purpose purpose() const; + QString identifier() const; + bool isRoamingAvailable() const; + QList children() const; + + QString name() const; + bool isValid() const; + +private: + friend class QNetworkConfigurationPrivate; + friend class QNetworkConfigurationManager; + friend class QNetworkConfigurationManagerPrivate; + friend class QNetworkSessionPrivate; + QExplicitlySharedDataPointer d; +}; + +QTM_END_NAMESPACE + +QT_END_HEADER + +#endif //QNETWORKCONFIGURATION_H diff --git a/src/network/bearer/qnetworkconfiguration_maemo_p.h b/src/network/bearer/qnetworkconfiguration_maemo_p.h new file mode 100644 index 0000000..8d786aa --- /dev/null +++ b/src/network/bearer/qnetworkconfiguration_maemo_p.h @@ -0,0 +1,109 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 QNETWORKCONFIGURATIONPRIVATE_H +#define QNETWORKCONFIGURATIONPRIVATE_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 +#include +#include + +QTM_BEGIN_NAMESPACE + +class QNetworkConfigurationPrivate : public QSharedData +{ +public: + QNetworkConfigurationPrivate () + : isValid(false), type(QNetworkConfiguration::Invalid), + roamingSupported(false), purpose(QNetworkConfiguration::UnknownPurpose), + network_attrs(0), service_attrs(0), manager(0) + { + } + + ~QNetworkConfigurationPrivate() + { + //release pointers to member configurations + serviceNetworkMembers.clear(); + } + + QString name; + bool isValid; + QString id; + QNetworkConfiguration::StateFlags state; + QNetworkConfiguration::Type type; + bool roamingSupported; + QNetworkConfiguration::Purpose purpose; + + QList > serviceNetworkMembers; + QNetworkInterface serviceInterface; + + /* In Maemo the id field (defined above) 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 */ + uint32_t network_attrs; /* network attributes for this IAP, this is the value returned by icd and passed to it when connecting */ + + QString service_type; + QString service_id; + uint32_t service_attrs; + + QNetworkConfigurationManagerPrivate *manager; + +private: + + // disallow detaching + QNetworkConfigurationPrivate &operator=(const QNetworkConfigurationPrivate &other); + QNetworkConfigurationPrivate(const QNetworkConfigurationPrivate &other); +}; + +QTM_END_NAMESPACE + +#endif //QNETWORKCONFIGURATIONPRIVATE_H diff --git a/src/network/bearer/qnetworkconfiguration_p.h b/src/network/bearer/qnetworkconfiguration_p.h new file mode 100644 index 0000000..a3bcd9a --- /dev/null +++ b/src/network/bearer/qnetworkconfiguration_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 QNETWORKCONFIGURATIONPRIVATE_H +#define QNETWORKCONFIGURATIONPRIVATE_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 "qnetworkconfiguration.h" +#include +#include + +QTM_BEGIN_NAMESPACE + +class QNetworkConfigurationPrivate : public QSharedData +{ +public: + QNetworkConfigurationPrivate () + : isValid(false), type(QNetworkConfiguration::Invalid), + roamingSupported(false), purpose(QNetworkConfiguration::UnknownPurpose) + { +#ifdef BEARER_ENGINE + internet = false; +#endif + } + + ~QNetworkConfigurationPrivate() + { + //release pointers to member configurations + serviceNetworkMembers.clear(); + } + + QString name; + bool isValid; + QString id; + QNetworkConfiguration::StateFlags state; + QNetworkConfiguration::Type type; + bool roamingSupported; + QNetworkConfiguration::Purpose purpose; + +#ifdef BEARER_ENGINE + bool internet; +#endif + + QList > serviceNetworkMembers; + QNetworkInterface serviceInterface; + +private: + + // disallow detaching + QNetworkConfigurationPrivate &operator=(const QNetworkConfigurationPrivate &other); + QNetworkConfigurationPrivate(const QNetworkConfigurationPrivate &other); +}; + +QTM_END_NAMESPACE + +#endif //QNETWORKCONFIGURATIONPRIVATE_H diff --git a/src/network/bearer/qnetworkconfiguration_s60_p.cpp b/src/network/bearer/qnetworkconfiguration_s60_p.cpp new file mode 100644 index 0000000..61548ba --- /dev/null +++ b/src/network/bearer/qnetworkconfiguration_s60_p.cpp @@ -0,0 +1,60 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 "qnetworkconfiguration_s60_p.h" + +QTM_BEGIN_NAMESPACE + +QNetworkConfigurationPrivate::QNetworkConfigurationPrivate() + : isValid(false), type(QNetworkConfiguration::Invalid), + roamingSupported(false), purpose(QNetworkConfiguration::UnknownPurpose), + bearer(QNetworkConfigurationPrivate::BearerUnknown), numericId(0), + connectionId(0), manager(0) +{ +} + +QNetworkConfigurationPrivate::~QNetworkConfigurationPrivate() +{ + //release pointers to member configurations + serviceNetworkMembers.clear(); +} + +QTM_END_NAMESPACE diff --git a/src/network/bearer/qnetworkconfiguration_s60_p.h b/src/network/bearer/qnetworkconfiguration_s60_p.h new file mode 100644 index 0000000..44f8f56 --- /dev/null +++ b/src/network/bearer/qnetworkconfiguration_s60_p.h @@ -0,0 +1,108 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 QNETWORKCONFIGURATIONPRIVATE_H +#define QNETWORKCONFIGURATIONPRIVATE_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 +#include + +QTM_BEGIN_NAMESPACE + +class QNetworkConfigurationPrivate : public QSharedData +{ +public: + enum Bearer { + BearerEthernet, + BearerWLAN, + Bearer2G, + BearerCDMA2000, + BearerWCDMA, + BearerHSPA, + BearerBluetooth, + BearerWiMAX, + BearerUnknown = -1 + }; + + QNetworkConfigurationPrivate(); + ~QNetworkConfigurationPrivate(); + + QString name; + bool isValid; + QString id; + QNetworkConfiguration::StateFlags state; + QNetworkConfiguration::Type type; + bool roamingSupported; + QNetworkConfiguration::Purpose purpose; + + QList > serviceNetworkMembers; + + QNetworkConfigurationPrivate::Bearer bearer; + TUint32 numericId; + TUint connectionId; + + TAny* manager; + + QString mappingName; + + QExplicitlySharedDataPointer serviceNetworkPtr; + +private: + // disallow detaching + QNetworkConfigurationPrivate &operator=(const QNetworkConfigurationPrivate &other); + QNetworkConfigurationPrivate(const QNetworkConfigurationPrivate &other); +}; + +QTM_END_NAMESPACE + +#endif //QNETWORKCONFIGURATIONPRIVATE_H + diff --git a/src/network/bearer/qnetworkmanagerservice_p.cpp b/src/network/bearer/qnetworkmanagerservice_p.cpp new file mode 100644 index 0000000..2f91af0 --- /dev/null +++ b/src/network/bearer/qnetworkmanagerservice_p.cpp @@ -0,0 +1,1011 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include "qnetworkmanagerservice_p.h" + +//Q_DECLARE_METATYPE(QList) +QTM_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) +{ + d = new QNetworkManagerInterfacePrivate(); + d->connectionInterface = new QDBusInterface(NM_DBUS_SERVICE, + NM_DBUS_PATH, + NM_DBUS_INTERFACE, + dbusConnection); + if (!d->connectionInterface->isValid()) { + qWarning() << "Could not find NetworkManager"; + d->valid = false; + return; + } + d->valid = true; + nmDBusHelper = new QNmDBusHelper; + connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(const QString &,QMap)), + this,SIGNAL(propertiesChanged( const QString &, QMap))); + connect(nmDBusHelper,SIGNAL(pathForStateChanged(const QString &, quint32)), + this, SIGNAL(stateChanged(const QString&, quint32))); + +} + +QNetworkManagerInterface::~QNetworkManagerInterface() +{ + 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)))) { + 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 QNetworkManagerInterface::getDevices() const +{ + QDBusReply > 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 QNetworkManagerInterface::activeConnections() const +{ + QVariant prop = d->connectionInterface->property("ActiveConnections"); + return prop.value >(); +} + +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) +{ + 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() +{ + delete d->connectionInterface; + delete d; +} + +bool QNetworkManagerInterfaceAccessPoint::isValid() +{ + return d->valid; +} + +bool QNetworkManagerInterfaceAccessPoint::setConnections() +{ + if(!isValid() ) + return false; + + bool allOk = false; + nmDBusHelper = new QNmDBusHelper; + connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(const QString &,QMap)), + this,SIGNAL(propertiesChanged( const QString &, QMap))); + + if(dbusConnection.connect(NM_DBUS_SERVICE, + d->path, + NM_DBUS_INTERFACE_ACCESS_POINT, + "PropertiesChanged", + nmDBusHelper,SLOT(slotPropertiesChanged( QMap))) ) { + 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) +{ + d = new QNetworkManagerInterfaceDevicePrivate(); + d->path = deviceObjectPath; + d->connectionInterface = new QDBusInterface(NM_DBUS_SERVICE, + d->path, + NM_DBUS_INTERFACE_DEVICE, + dbusConnection); + if (!d->connectionInterface->isValid()) { + d->valid = false; + qWarning() << "Could not find NetworkManager"; + return; + } + d->valid = true; +} + +QNetworkManagerInterfaceDevice::~QNetworkManagerInterfaceDevice() +{ + delete d->connectionInterface; + delete d; +} + +bool QNetworkManagerInterfaceDevice::isValid() +{ + return d->valid; +} + +bool QNetworkManagerInterfaceDevice::setConnections() +{ + if(!isValid() ) + return false; + + bool allOk = false; + 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(); +} + +///////////// +class QNetworkManagerInterfaceDeviceWiredPrivate +{ +public: + QDBusInterface *connectionInterface; + QString path; + bool valid; +}; + +QNetworkManagerInterfaceDeviceWired::QNetworkManagerInterfaceDeviceWired(const QString &ifaceDevicePath, QObject *parent) +{ + 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() +{ + delete d->connectionInterface; + delete d; +} + +bool QNetworkManagerInterfaceDeviceWired::isValid() +{ + + return d->valid; +} + +bool QNetworkManagerInterfaceDeviceWired::setConnections() +{ + if(!isValid() ) + return false; + + bool allOk = false; + + nmDBusHelper = new QNmDBusHelper; + connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(const QString &,QMap)), + this,SIGNAL(propertiesChanged( const QString &, QMap))); + if(dbusConnection.connect(NM_DBUS_SERVICE, + d->path, + NM_DBUS_INTERFACE_DEVICE_WIRED, + "PropertiesChanged", + nmDBusHelper,SLOT(slotPropertiesChanged( QMap))) ) { + 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) +{ + 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() +{ + delete d->connectionInterface; + delete d; +} + +bool QNetworkManagerInterfaceDeviceWireless::isValid() +{ + return d->valid; +} + +bool QNetworkManagerInterfaceDeviceWireless::setConnections() +{ + if(!isValid() ) + return false; + + bool allOk = false; + nmDBusHelper = new QNmDBusHelper; + connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(const QString &,QMap)), + this,SIGNAL(propertiesChanged( const QString &, QMap))); + + 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)))) { + allOk = true; + } + + return allOk; +} + +QDBusInterface *QNetworkManagerInterfaceDeviceWireless::connectionInterface() const +{ + return d->connectionInterface; +} + +QList QNetworkManagerInterfaceDeviceWireless::getAccessPoints() +{ + QDBusReply > 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(); +} + +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) +{ +// qWarning() << __PRETTY_FUNCTION__; + 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 QNetworkManagerSettings::listConnections() +{ + QDBusReply > 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) +{ + qDBusRegisterMetaType(); + 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() +{ + 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, "NewConnection", + this, SIGNAL(updated(QNmSettingsMap)))) { + allOk = true; + } + + 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 innerMap = i.value(); + QMap::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 innerMap = i.value(); + QMap::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 innerMap = i.value(); + QMap::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 innerMap = i.value(); + QMap::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 innerMap = i.value(); + QMap::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 innerMap = i.value(); + QMap::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 innerMap = i.value(); + QMap::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 innerMap = i.value(); + QMap::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 innerMap = i.value(); + QMap::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) +{ + 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() +{ + delete d->connectionInterface; + delete d; +} + +bool QNetworkManagerConnectionActive::isValid() +{ + return d->valid; +} + +bool QNetworkManagerConnectionActive::setConnections() +{ + if(!isValid() ) + return false; + + bool allOk = false; + nmDBusHelper = new QNmDBusHelper; + connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(const QString &,QMap)), + this,SIGNAL(propertiesChanged( const QString &, QMap))); + if(dbusConnection.connect(NM_DBUS_SERVICE, + d->path, + NM_DBUS_INTERFACE_ACTIVE_CONNECTION, + "PropertiesChanged", + nmDBusHelper,SLOT(slotPropertiesChanged( QMap))) ) { + 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 QNetworkManagerConnectionActive::specificObject() const +{ + QVariant prop = d->connectionInterface->property("SpecificObject"); + return prop.value(); +} + +QList QNetworkManagerConnectionActive::devices() const +{ + QVariant prop = d->connectionInterface->property("Devices"); + return prop.value >(); +} + +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) +{ + 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(); +} + +#include "moc_qnetworkmanagerservice_p.cpp" + +QTM_END_NAMESPACE diff --git a/src/network/bearer/qnetworkmanagerservice_p.h b/src/network/bearer/qnetworkmanagerservice_p.h new file mode 100644 index 0000000..8569e71 --- /dev/null +++ b/src/network/bearer/qnetworkmanagerservice_p.h @@ -0,0 +1,400 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 +#include +#include +#include +#include +#include +#include +#include + + +#include +#include + + +QTM_BEGIN_NAMESPACE +typedef QMap< QString, QMap > QNmSettingsMap; +typedef QList ServerThing; +QTM_END_NAMESPACE + +Q_DECLARE_METATYPE(QTM_PREPEND_NAMESPACE(QNmSettingsMap)) +Q_DECLARE_METATYPE(QTM_PREPEND_NAMESPACE(ServerThing)) + + +QTM_BEGIN_NAMESPACE +class QNetworkManagerInterfacePrivate; +class QNetworkManagerInterface : public QObject +{ + Q_OBJECT + +public: + + QNetworkManagerInterface(QObject *parent = 0); + ~QNetworkManagerInterface(); + + QList 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 activeConnections() const; + quint32 state(); + bool setConnections(); + bool isValid(); + +Q_SIGNALS: + void deviceAdded(QDBusObjectPath); + void deviceRemoved(QDBusObjectPath); + void propertiesChanged( const QString &, QMap); + 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 ); + void propertiesChanged( const QString &, QMap); +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); +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 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); + 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 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(QMap< QString, QMap > s); + void removed(const QString &); + +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 devices() const; + quint32 state() const; + bool defaultRoute() const; + bool setConnections(); + bool isValid(); + + +Q_SIGNALS: + void propertiesChanged(QList); + void propertiesChanged( const QString &, QMap); +private: + QNetworkManagerConnectionActivePrivate *d; + QNmDBusHelper *nmDBusHelper; +}; //QNetworkManagerConnectionActive + +//// +class QNetworkManagerIp4ConfigPrivate; +class QNetworkManagerIp4Config : public QObject +{ + Q_OBJECT + +public: + QNetworkManagerIp4Config(const QString &dbusPathName, QObject *parent = 0); + ~QNetworkManagerIp4Config(); + + // QList nameservers(); + QStringList domains() const; + bool isValid(); + + private: + QNetworkManagerIp4ConfigPrivate *d; +}; +//// + +QTM_END_NAMESPACE + +#endif //QNETWORKMANAGERSERVICE_H diff --git a/src/network/bearer/qnetworksession.cpp b/src/network/bearer/qnetworksession.cpp new file mode 100644 index 0000000..d3a323a --- /dev/null +++ b/src/network/bearer/qnetworksession.cpp @@ -0,0 +1,689 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 +#include + +#include "qnetworksession.h" + +#ifdef Q_OS_SYMBIAN +#include "qnetworksession_s60_p.h" +#elif MAEMO +#include "qnetworksession_maemo_p.h" +#else +#include "qnetworksession_p.h" +#endif + +QTM_BEGIN_NAMESPACE + +/*! + \class QNetworkSession + + \brief The QNetworkSession class provides control over the system's access points + and enables session management for cases when multiple clients access the same access point. + + \inmodule QtNetwork + \ingroup bearer + + A QNetworkSession enables control over the system's network interfaces. The session's configuration + parameter are determined via the QNetworkConfiguration object to which it is bound. Depending on the + type of the session (single access point or service network) a session may be linked to one or more + network interfaces. By means of \l{open()}{opening} and \l{close()}{closing} of network sessions + a developer can start and stop the systems network interfaces. If the configuration represents + multiple access points (see \l QNetworkConfiguration::ServiceNetwork) more advanced features such as roaming may be supported. + + QNetworkSession supports session management within the same process and depending on the platform's + capabilities may support out-of-process sessions. If the same + network configuration is used by multiple active sessions the underlying network interface is only terminated once + the last session has been closed. + + \section1 Roaming + + Applications may connect to the preferredConfigurationChanged() signal in order to + receive notifications when a more suitable access point becomes available. + In response to this signal the application may initiate the roaming via migrate() + or may ignore() the new access point. Once the session has roamed the + newConfigurationActivated() signal is emitted. The application may now test the + carrier and can accept() or reject() it. The session will return to the previous + access point if the roaming was rejected. + + Some platforms may support the notion of forced roaming and application level roaming (ALR). + ALR implies that the application controls (via migrate(), ignore(), accept() and reject()) + whether a network session can roam from one network configuration to the next. Such control is useful + if the application maintains stateful socket connections and wants to control the transition from + one interface to the next. + + Forced roaming implies that the system automatically roams to the next network without + consulting the application. This has the advantage that the application can make use of roaming features + without actually being aware of it. It is expected that the application detects that the underlying + socket is broken and automatically reconnects via the new network link. + + If the platform supports both modes of roaming an application indicates its preference + by connecting to the preferredConfigurationChanged() signal. Connecting to this signal means that + the application wants to take control over the roaming behavior and therefore implies application + level roaming. + + \sa QNetworkConfiguration, QNetworkConfigurationManager +*/ + +/*! + \enum QNetworkSession::State + + This enum describes the connectivity state of the session. If the session is based on a + single access point configuration the state of the session is the same as the state of the + associated network interface. + + \value Invalid The session is invalid due to an invalid configuration. This may + happen due to a removed access point or a configuration that was + invalid to begin with. + \value NotAvailable The session is based on a defined but not yet discovered QNetworkConfiguration + (see \l QNetworkConfiguration::StateFlag). + \value Connecting The network session is being established. + \value Connected The network session is connected. If the current process wishes to use this session + it has to register its interest by calling open(). A network session + is considered to be ready for socket operations if it isActive() and connected. + \value Closing The network session is in the process of being shut down. + \value Disconnected The network session is not connected. The associated QNetworkConfiguration + has the state QNetworkConfiguration::Discovered. + \value Roaming The network session is roaming from one access point to another + access point. +*/ + +/*! + \enum QNetworkSession::SessionError + + This enum describes the session errors that can occur. + + \value UnknownSessionError An unidentified error occurred. + \value SessionAbortedError The session was aborted by the user or system. + \value RoamingError The session cannot roam to the new configuration. + \value OperationNotSupportedError The operation is not supported for current configuration. + \value InvalidConfigurationError The operation cannot currently be performed for the + current configuration. +*/ + +/*! + \fn void QNetworkSession::stateChanged(QNetworkSession::State state) + + This signal is emitted whenever the state of the network session changes. + The \a state parameter is the new state. + + \sa state() +*/ + +/*! + \fn void QNetworkSession::error(QNetworkSession::SessionError error) + + This signal is emitted after an error occurred. The \a error parameter + describes the error that occurred. + + \sa error(), errorString() +*/ + +/*! + \fn void QNetworkSession::preferredConfigurationChanged(const QNetworkConfiguration& config, bool isSeamless) + + This signal is emitted when the preferred configuration/access point for the + session changes. Only sessions which are based on service network configurations + may emit this signal. \a config can be used to determine access point specific + details such as proxy settings and \a isSeamless indicates whether roaming will + break the sessions IP address. + + As a consequence to this signal the application may start the roaming process + by calling migrate() or may chose to ignore() the new access point. If the application + doesn't call either of the two functions the session ignores the migration opportunity. + + If the roaming process is non-seamless the IP address will change which means that + a socket becomes invalid. However seamless mobility can ensure that the local IP address + does not change. This is achieved by using a virtual IP address which is bound to the actual + link address. During the roaming process the virtual address is attached to the new link + address. + + Some platforms may support the concept of Forced Roaming and Application Level Roaming (ALR). + Forced roaming implies that the platform may simply roam to a new configuration without + consulting applications. It is up to the application to detect the link layer loss and reestablish + its sockets. In contrast ALR provides the opportunity to prevent the system from roaming. + If this session is based on a configuration that supports roaming the application can choose + whether it wants to be consulted (ALR use case) by connecting to this signal. For as long as this signal + connection remains the session remains registered as a roaming stakeholder; otherwise roaming will + be enforced by the platform. + + \sa migrate(), ignore(), QNetworkConfiguration::isRoamingAvailable() +*/ + +/*! + \fn void QNetworkSession::newConfigurationActivated() + + This signal is emitted once the session has roamed to the new access point. + The application may reopen its socket and test the suitability of the new network link. + Subsequently it may accept() or reject() the new access point. + + \sa accept(), reject() +*/ + +/*! + \fn void QNetworkSession::opened() + + This signal is emitted when the network session has been opened. + + The underlying network interface will not be shut down as long as the session remains open. + Note that this feature is dependent on \l{QNetworkConfigurationManager::SystemSessionSupport}{system wide session support}. +*/ + +/*! + \fn void QNetworkSession::closed() + + This signal is emitted when the network session has been closed. +*/ + +/*! + Constructs a session based on \a connectionConfig with the given \a parent. + + \sa QNetworkConfiguration +*/ +QNetworkSession::QNetworkSession(const QNetworkConfiguration& connectionConfig, QObject* parent) + : QObject(parent) +{ + d = new QNetworkSessionPrivate; + d->q = this; + d->publicConfig = connectionConfig; + d->syncStateWithInterface(); + QObject::connect(d, SIGNAL(quitPendingWaitsForOpened()), + this, SIGNAL(opened())); +} + +/*! + Frees the resources associated with the QNetworkSession object. +*/ +QNetworkSession::~QNetworkSession() +{ + delete d; +} + +/*! + Creates an active/open session which increases the session counter on the underlying network interface. + The system will not terminate a network interface until the session reference counter reaches zero. + Therefore an active session allows an application to register its use of the interface. + + The interface is started if it is not active yet. Some platforms may not provide support + for out-of-process sessions. On such platforms the session counter ignores any sessions + held by another process. The platform capabilities can be + detected via QNetworkConfigurationManager::capabilities(). + + Note that this call is asynchronous. Depending on the outcome of this call the results can be enquired + by connecting to the stateChanged(), opened() or error() signals. + + It is not a requirement to open a session in order to monitor the underlying network interface. + + \sa close(), stop(), isActive() +*/ +void QNetworkSession::open() +{ + d->open(); +} + +/*! + Waits until the session has been opened, up to \a msecs milliseconds. If the session has been opened, this + function returns true; otherwise it returns false. In the case where it returns false, you can call error() + to determine the cause of the error. + + The following example waits up to one second for the session to be opened: + + \code + session->open(); + if (session->waitForOpened(1000)) + qDebug("Open!"); + \endcode + + If \a msecs is -1, this function will not time out. + + \sa open(), error() +*/ +bool QNetworkSession::waitForOpened(int msecs) +{ + if (d->isActive) + return true; + + if (d->state != Connecting) + return false; + + QEventLoop* loop = new QEventLoop(this); + QObject::connect(d, SIGNAL(quitPendingWaitsForOpened()), + loop, SLOT(quit())); + + //final call + if (msecs>=0) + QTimer::singleShot(msecs, loop, SLOT(quit())); + + loop->exec(); + loop->disconnect(); + loop->deleteLater(); + + return d->isActive; +} + +/*! + Decreases the session counter on the associated network configuration. If the session counter reaches zero + the active network interface is shut down. This also means that state() will only change from \l Connected to + \l Disconnected if this was the last active session. + + If the platform does not support out-of-process sessions calling this function does not stop the + interface. In this case \l{stop()} has to be used to force a shut down. + The platform capabilities can be detected via QNetworkConfigurationManager::capabilities(). + + Note that this call is asynchronous. Depending on the outcome of this call the results can be enquired + by connecting to the stateChanged(), opened() or error() signals. + + \sa open(), stop(), isActive() +*/ +void QNetworkSession::close() +{ + d->close(); +} + +/*! + Invalidates all active sessions against the network interface and therefore stops the + underlying network interface. This function always changes the session's state() flag to + \l Disconnected. + + \sa open(), close() +*/ +void QNetworkSession::stop() +{ + d->stop(); +} + +/*! + Returns the QNetworkConfiguration that this network session object is based on. + + \sa QNetworkConfiguration +*/ +QNetworkConfiguration QNetworkSession::configuration() const +{ + return d->publicConfig; +} + +/*! + Returns the type of bearer currently used by this session. The string is not translated and therefore can + not be shown to the user. The subsequent table presents the currently known bearer types: + + \table + \header + \o Value + \o Description + \row + \o Ethernet + \o The session is based on Ethernet. + \row + \o WLAN + \o The session is based on Wireless LAN. + \row + \o 2G + \o The session uses CSD, GPRS, HSCSD, EDGE or cdmaOne. + \row + \o CDMA2000 + \o The session uses CDMA. + \row + \o WCDMA + \o The session uses W-CDMA/UMTS. + \row + \o HSPA + \o The session uses High Speed Packet Access. + \row + \o Bluetooth + \o The session uses Bluetooth. + \row + \o WiMAX + \o The session uses WiMAX. + \endtable + + If the session is based on a network configuration of type + \l QNetworkConfiguration::ServiceNetwork the type of the preferred or currently + active configuration is returned. Therefore the bearer type may change + over time. + + This function returns an empty string if this session is based on an invalid configuration. +*/ +QString QNetworkSession::bearerName() const +{ + return d->bearerName(); +} + +/*! + Returns the network interface that is used by this session. + + This function only returns a valid QNetworkInterface when this session is \l Connected. + + The returned interface may change as a result of a roaming process. + + \sa state() +*/ +QNetworkInterface QNetworkSession::interface() const +{ + return d->currentInterface(); +} + +/*! + Returns true if this object holds an active session on the underlying network interface. + The session can be controlled via open() and close(). +*/ +bool QNetworkSession::isActive() const +{ + return d->isActive; +} + +/*! + Returns the state of the session. If the session is based on a + single access point configuration the state of the session is the same as the state of the + associated network interface. Therefore a network session object can be used to monitor + network interfaces. + + A \l QNetworkConfiguration::ServiceNetwork based session summarizes the state of all its children + and therefore returns the \l Connected state if at least one of its sub configurations is connected. + + Note that it is not required to hold an active session in order to obtain the network interface state. + A connected but inactive session may be used to monitor network interfaces whereas an active and connected + session object may prevent the network interface from being shut down. + + \sa error(), stateChanged() +*/ +QNetworkSession::State QNetworkSession::state() const +{ + return d->state; +} + +/*! + Returns the type of error that last occurred. + + \sa state(), errorString() +*/ +QNetworkSession::SessionError QNetworkSession::error() const +{ + return d->error(); +} + +/*! + Returns a human-readable description of the last device error that + occurred. + + \sa error() +*/ +QString QNetworkSession::errorString() const +{ + return d->errorString(); +} + +/*! + Returns the value for property \a key. + + A network session can have properties attached which may describe the session in more details. + This function can be used to gain access to those properties. + + The following property keys are guaranteed to be specified on all platforms: + + \table + \header + \o Key \o Description + \row + \o ActiveConfigurationIdentifier + \o If the session \l isActive() this property returns the identifier of the + QNetworkConfiguration that is used by this session; otherwise an empty string. + + The main purpose of this key is to determine which Internet access point is used + if the session is based on a \l{QNetworkConfiguration::ServiceNetwork}{ServiceNetwork}. + The following code snippet highlights the difference: + \code + QNetworkConfigurationManager mgr; + QNetworkConfiguration ap = mgr.defaultConfiguration(); + QNetworkSession* session = new QNetworkSession(ap); + ... //code activates session + + QString ident = session->sessionProperty("ActiveConfigurationIdentifier").toString(); + if ( ap.type() == QNetworkConfiguration::ServiceNetwork ) { + Q_ASSERT( ap.identifier() != ident ); + Q_ASSERT( ap.children().contains( mgr.configurationFromIdentifier(ident) ) ); + } else if ( ap.type() == QNetworkConfiguration::InternetAccessPoint ) { + Q_ASSERT( ap.identifier() == ident ); + } + \endcode + \row + \o UserChoiceConfigurationIdentifier + \o If the session \l isActive() and is bound to a QNetworkConfiguration of type + UserChoice, this property returns the identifier of the QNetworkConfiguration that the + configuration resolved to when \l open() was called; otherwise an empty string. + + The purpose of this key is to determine the real QNetworkConfiguration that the + session is using. This key is different to \i ActiveConfigurationIdentifier in that + this key may return an identifier for either a + \l {QNetworkConfiguration::ServiceNetwork}{service network} or a + \l {QNetworkConfiguration::InternetAccessPoint}{Internet access points} configurations + whereas \i ActiveConfigurationIdentifier always returns identifiers for + \l {QNetworkConfiguration::InternetAccessPoint}{Internet access points} configurations. + \row + \o ConnectInBackground + \o Setting this property to \i true before calling \l open() implies that the connection attempt + is made but if no connection can be established, the user is not connsulted and asked to select + a suitable connection. This property is not set by default and support for it depends on the platform. + \endtable +*/ +QVariant QNetworkSession::sessionProperty(const QString& key) const +{ + if (!d->publicConfig.isValid()) + return QVariant(); + + if (key == "ActiveConfigurationIdentifier") { + if (!d->isActive) + return QString(); + else + return d->activeConfig.identifier(); + } + + if (key == "UserChoiceConfigurationIdentifier") { + if (!d->isActive || d->publicConfig.type() != QNetworkConfiguration::UserChoice) + return QString(); + + if (d->serviceConfig.isValid()) + return d->serviceConfig.identifier(); + else + return d->activeConfig.identifier(); + } + + return d->sessionProperty(key); +} + +/*! + Sets the property \a value on the session. The property is identified using + \a key. Removing an already set property can be achieved by passing an + invalid QVariant. + + Note that the \i UserChoiceConfigurationIdentifier and \i ActiveConfigurationIdentifier + properties are read only and cannot be changed using this method. +*/ +void QNetworkSession::setSessionProperty(const QString& key, const QVariant& value) +{ + if (key == "ActiveConfigurationIdentifier" + || key == "UserChoiceConfigurationIdentifier") + return; + + d->setSessionProperty(key, value); +} + +/*! + Instructs the session to roam to the new access point. The old access point remains active + until the application calls accept(). + + The newConfigurationActivated() signal is emitted once roaming has been completed. + + \sa accept() +*/ +void QNetworkSession::migrate() +{ + d->migrate(); +} + +/*! + This function indicates that the application does not wish to roam the session. This + is the default behavior if an application doesn't call migrate() in response to a + preferredConfigurationChanged() signal. + + \sa migrate() +*/ +void QNetworkSession::ignore() +{ + //TODO Do we really need this function if we consider that this is + // the default behavior if nobody calls migrate()? + d->ignore(); +} + +/*! + Instructs the session to permanently accept the new access point. Once this function + has been called the session may not return to the old access point. + + The old access point may be closed in the process if there are no other network sessions for it. + Therefore any open socket that still uses the old access point + may become unusable and should be closed before completing the migration. +*/ +void QNetworkSession::accept() +{ + d->accept(); +} + +/*! + The new access point is not suitable for the application. By calling this function the + session returns to the previous access point/configuration. This action may invalidate + any socket that has been created via the not desired access point. + + \sa accept() +*/ +void QNetworkSession::reject() +{ + d->reject(); +} + + +/*! + Returns the amount of data sent in bytes; otherwise 0. + + This field value includes the usage across all active network + sessions which use the same network interface. + + If the session is based on a service network configuration the number of + sent bytes across all active member configurations are returned. + + This function may not always be supported on all platforms and returns + 0. The platform capability can be detected via QNetworkConfigurationManager::DataStatistics. +*/ +quint64 QNetworkSession::bytesWritten() const +{ + return d->bytesWritten(); +} + +/*! + Returns the amount of data received in bytes; otherwise 0. + + This field value includes the usage across all active network + sessions which use the same network interface. + + If the session is based on a service network configuration the number of + sent bytes across all active member configurations are returned. + + This function may not always be supported on all platforms and returns + 0. The platform capability can be detected via QNetworkConfigurationManager::DataStatistics. +*/ +quint64 QNetworkSession::bytesReceived() const +{ + return d->bytesReceived(); +} + +/*! + Returns the number of seconds that the session has been active. +*/ +quint64 QNetworkSession::activeTime() const +{ + return d->activeTime(); +} + +/*! + \internal + + This function is required to detect whether the client wants to control + the roaming process. If he connects to preferredConfigurationChanged() signal + he intends to influence it. Otherwise QNetworkSession always roams + without registering this session as a stakeholder in the roaming process. + + For more details check the Forced vs ALR roaming section in the QNetworkSession + class description. +*/ +void QNetworkSession::connectNotify(const char *signal) +{ + QObject::connectNotify(signal); + //check for preferredConfigurationChanged() signal connect notification + //This is not required on all platforms +#ifdef Q_OS_SYMBIAN + if (qstrcmp(signal, SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool))) == 0) { + d->setALREnabled(true); + } +#endif +} + +/*! + \internal + + This function is called when the client disconnects from the preferredConfigurationChanged() + signal. + + \sa connectNotify() +*/ +void QNetworkSession::disconnectNotify(const char *signal) +{ + QObject::disconnectNotify(signal); + //check for preferredConfigurationChanged() signal disconnect notification + //This is not required on all platforms +#ifdef Q_OS_SYMBIAN + if (qstrcmp(signal, SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool))) == 0) { + d->setALREnabled(false); + } +#endif +} + +#include "moc_qnetworksession.cpp" + +QTM_END_NAMESPACE diff --git a/src/network/bearer/qnetworksession.h b/src/network/bearer/qnetworksession.h new file mode 100644 index 0000000..47377c4 --- /dev/null +++ b/src/network/bearer/qnetworksession.h @@ -0,0 +1,135 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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_H +#define QNETWORKSESSION_H + +#include "qmobilityglobal.h" + +#include +#include +#include +#include +#include +#include "qnetworkconfiguration.h" + + +QT_BEGIN_HEADER + +QTM_BEGIN_NAMESPACE + +class QNetworkSessionPrivate; +class Q_BEARER_EXPORT QNetworkSession : public QObject +{ + Q_OBJECT +public: + enum State { + Invalid = 0, + NotAvailable, + Connecting, + Connected, + Closing, + Disconnected, + Roaming + }; + + enum SessionError { + UnknownSessionError = 0, + SessionAbortedError, + RoamingError, + OperationNotSupportedError, + InvalidConfigurationError + }; + + QNetworkSession(const QNetworkConfiguration& connConfig, QObject* parent =0); + virtual ~QNetworkSession(); + + bool isActive() const; + QNetworkConfiguration configuration() const; + QString bearerName() const; + QNetworkInterface interface() const; + + State state() const; + SessionError error() const; + QString errorString() const; + QVariant sessionProperty(const QString& key) const; + void setSessionProperty(const QString& key, const QVariant& value); + + quint64 bytesWritten() const; + quint64 bytesReceived() const; + quint64 activeTime() const; + + bool waitForOpened(int msecs = 30000); + +public Q_SLOTS: + void open(); + void close(); + void stop(); + + //roaming related slots + void migrate(); + void ignore(); + void accept(); + void reject(); + + +Q_SIGNALS: + void stateChanged(QNetworkSession::State); + void opened(); + void closed(); + void error(QNetworkSession::SessionError); + void preferredConfigurationChanged(const QNetworkConfiguration& config, bool isSeamless); + void newConfigurationActivated(); + +protected: + virtual void connectNotify(const char *signal); + virtual void disconnectNotify(const char *signal); + +private: + QNetworkSessionPrivate* d; + friend class QNetworkSessionPrivate; + }; + +QTM_END_NAMESPACE + +QT_END_HEADER + +#endif //QNETWORKSESSION_H diff --git a/src/network/bearer/qnetworksession_maemo.cpp b/src/network/bearer/qnetworksession_maemo.cpp new file mode 100644 index 0000000..c7c7a31 --- /dev/null +++ b/src/network/bearer/qnetworksession_maemo.cpp @@ -0,0 +1,1181 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 + +#include "qnetworksession_maemo_p.h" +#include +#include + +#include +#include + +#include +#include +#include +#include +#include + +QTM_BEGIN_NAMESPACE + +static QHash 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(QNetworkSessionPrivate *d); + void cleanup(); + void cleanupSession(QNetworkSessionPrivate *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 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(QNetworkSessionPrivate *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)) { + QNetworkSessionPrivate *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; + } + + QNetworkSessionPrivate *session = sessions.value(iap_id); + QNetworkConfiguration ap_conf = session->manager.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(QNetworkSessionPrivate *ptr) +{ + if (ptr->publicConfig.type() == QNetworkConfiguration::UserChoice) + (void)sessions.take(ptr->activeConfig.identifier()); + else + (void)sessions.take(ptr->publicConfig.identifier()); +} + + +void QNetworkSessionPrivate::cleanupSession(void) +{ + icdListener()->cleanupSession(this); +} + + +void QNetworkSessionPrivate::updateState(QNetworkSession::State newState) +{ + if( newState != state) { + state = newState; + + if (state == QNetworkSession::Disconnected) { + isActive = false; + currentNetworkInterface.clear(); + if (publicConfig.type() == QNetworkConfiguration::UserChoice) + activeConfig.d->state = QNetworkConfiguration::Defined; + publicConfig.d->state = QNetworkConfiguration::Defined; + + } else if (state == QNetworkSession::Connected) { + isActive = true; + if (publicConfig.type() == QNetworkConfiguration::UserChoice) { + activeConfig.d->state = QNetworkConfiguration::Active; + activeConfig.d->type = QNetworkConfiguration::InternetAccessPoint; + } + publicConfig.d->state = QNetworkConfiguration::Active; + } + + emit q->stateChanged(newState); + } +} + + +void QNetworkSessionPrivate::updateIdentifier(QString &newId) +{ + if (publicConfig.type() == QNetworkConfiguration::UserChoice) { + activeConfig.d->network_attrs |= ICD_NW_ATTR_IAPNAME; + activeConfig.d->id = newId; + } else { + publicConfig.d->network_attrs |= ICD_NW_ATTR_IAPNAME; + if (publicConfig.d->id != newId) { + qWarning() << "Your config id changed from" << publicConfig.d->id << "to" << newId; + publicConfig.d->id = newId; + } + } +} + + +quint64 QNetworkSessionPrivate::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 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 */ + QNetworkConfigurationPrivate *d = activeConfig.d.data(); + if (res.params.network_id == d->network_id) { + counter_tx = res.bytes_sent; + counter_rx = res.bytes_received; + } + } + } + + if (sent) + return counter_tx; + else + return counter_rx; +} + + +quint64 QNetworkSessionPrivate::bytesWritten() const +{ + return getStatistics(true); +} + +quint64 QNetworkSessionPrivate::bytesReceived() const +{ + return getStatistics(false); +} + +quint64 QNetworkSessionPrivate::activeTime() const +{ + if (startTime.isNull()) { + return 0; + } + return startTime.secsTo(QDateTime::currentDateTime()); +} + + +QNetworkConfiguration& QNetworkSessionPrivate::copyConfig(QNetworkConfiguration &fromConfig, QNetworkConfiguration &toConfig, bool deepCopy) +{ + if (deepCopy) { + QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); + QExplicitlySharedDataPointer ptr(cpPriv); + toConfig.d = ptr; + } + + toConfig.d->name = fromConfig.d->name; + toConfig.d->isValid = fromConfig.d->isValid; + // Note that we do not copy id field here as the publicConfig does + // not contain a valid IAP id. + toConfig.d->state = fromConfig.d->state; + toConfig.d->type = fromConfig.d->type; + toConfig.d->roamingSupported = fromConfig.d->roamingSupported; + toConfig.d->purpose = fromConfig.d->purpose; + toConfig.d->network_id = fromConfig.d->network_id; + toConfig.d->iap_type = fromConfig.d->iap_type; + toConfig.d->network_attrs = fromConfig.d->network_attrs; + toConfig.d->service_type = fromConfig.d->service_type; + toConfig.d->service_id = fromConfig.d->service_id; + toConfig.d->service_attrs = fromConfig.d->service_attrs; + toConfig.d->manager = fromConfig.d->manager; + + return toConfig; +} + + +/* This is called by QNetworkSession constructor and it updates the current + * state of the configuration. + */ +void QNetworkSessionPrivate::syncStateWithInterface() +{ + /* Start to listen Icd status messages. */ + icdListener()->setup(this); + + /* Initially we are not active although the configuration might be in + * connected state. + */ + isActive = false; + opened = false; + + QObject::connect(&manager, SIGNAL(updateCompleted()), this, SLOT(networkConfigurationsChanged())); + + if (publicConfig.d.data()) { + QNetworkConfigurationManagerPrivate* mgr = (QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager; + if (mgr) { + QObject::connect(mgr, SIGNAL(configurationChanged(QNetworkConfiguration)), + this, SLOT(configurationChanged(QNetworkConfiguration))); + } else { + qWarning()<<"Manager object not set when trying to connect configurationChanged signal. Your configuration object is not correctly setup, did you remember to call manager.updateConfigurations() before creating session object?"; + state = QNetworkSession::Invalid; + lastError = QNetworkSession::UnknownSessionError; + return; + } + } + + 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 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 || + publicConfig.d->id == state_results.first().params.network_id) { + + switch (state_results.first().state) { + case ICD_STATE_DISCONNECTED: + state = QNetworkSession::Disconnected; + if (activeConfig.d.data()) + activeConfig.d->isValid = true; + break; + case ICD_STATE_CONNECTING: + state = QNetworkSession::Connecting; + if (activeConfig.d.data()) + activeConfig.d->isValid = true; + break; + case ICD_STATE_CONNECTED: + { + if (!state_results.first().error.isEmpty()) + break; + + const QString id = state_results.first().params.network_id; + + QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)activeConfig.d.data()->manager; + if (mgr->accessPointConfigurations.contains(id)) { + //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 + QExplicitlySharedDataPointer priv = mgr->accessPointConfigurations.value(activeConfig.d->id); + activeConfig.d = priv; + } + + + state = QNetworkSession::Connected; + activeConfig.d->network_id = state_results.first().params.network_id; + activeConfig.d->id = activeConfig.d->network_id; + activeConfig.d->network_attrs = state_results.first().params.network_attrs; + activeConfig.d->iap_type = state_results.first().params.network_type; + activeConfig.d->service_type = state_results.first().params.service_type; + activeConfig.d->service_id = state_results.first().params.service_id; + activeConfig.d->service_attrs = state_results.first().params.service_attrs; + activeConfig.d->type = QNetworkConfiguration::InternetAccessPoint; + activeConfig.d->state = QNetworkConfiguration::Active; + activeConfig.d->isValid = true; + currentNetworkInterface = get_network_interface(); + + Maemo::IAPConf iap_name(activeConfig.d->id); + QString name_value = iap_name.value("name").toString(); + if (!name_value.isEmpty()) + activeConfig.d->name = name_value; + else + activeConfig.d->name = activeConfig.d->id; + + + // Add the new active configuration to manager or update the old config + mgr = (QNetworkConfigurationManagerPrivate*)activeConfig.d.data()->manager; + if (!(mgr->accessPointConfigurations.contains(activeConfig.d->id))) { + QExplicitlySharedDataPointer ptr = activeConfig.d; + mgr->accessPointConfigurations.insert(activeConfig.d->id, ptr); + + QNetworkConfiguration item; + item.d = ptr; + emit mgr->configurationAdded(item); + +#ifdef BEARER_MANAGEMENT_DEBUG + //qDebug()<<"New configuration"<id<<"added to manager in sync"; +#endif + + } else { + mgr->configurationChanged((QNetworkConfigurationPrivate*)(activeConfig.d.data())); +#ifdef BEARER_MANAGEMENT_DEBUG + //qDebug()<<"Existing configuration"<id<<"updated in manager in sync"; +#endif + } + + } + break; + + case ICD_STATE_DISCONNECTING: + state = QNetworkSession::Closing; + if (activeConfig.d.data()) + activeConfig.d->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 QNetworkSessionPrivate::networkConfigurationsChanged() +{ + if (serviceConfig.isValid()) + updateStateFromServiceNetwork(); + else + updateStateFromActiveConfig(); +} + + +void QNetworkSessionPrivate::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 q->newConfigurationActivated(); + } + + state = QNetworkSession::Connected; + if (state != oldState) + emit q->stateChanged(state); + + return; + } + + if (serviceConfig.children().isEmpty()) + state = QNetworkSession::NotAvailable; + else + state = QNetworkSession::Disconnected; + + if (state != oldState) + emit q->stateChanged(state); +} + + +void QNetworkSessionPrivate::clearConfiguration(QNetworkConfiguration &config) +{ + config.d->network_id.clear(); + config.d->iap_type.clear(); + config.d->network_attrs = 0; + config.d->service_type.clear(); + config.d->service_id.clear(); + config.d->service_attrs = 0; +} + + +void QNetworkSessionPrivate::updateStateFromActiveConfig() +{ + QNetworkSession::State oldState = state; + + bool newActive = false; + + if (!activeConfig.d.data()) + 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 = isActive; + isActive = newActive; + + if (!oldActive && isActive) + emit quitPendingWaitsForOpened(); + + if (oldActive && !isActive) + emit q->closed(); + + if (oldState != state) { + emit q->stateChanged(state); + + if (state == QNetworkSession::Disconnected) { +#ifdef BEARER_MANAGEMENT_DEBUG + //qDebug()<<"session aborted error emitted for"<error(lastError); + } + } + +#ifdef BEARER_MANAGEMENT_DEBUG + //qDebug()<<"oldState ="<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 QNetworkSessionPrivate::open() +{ + if (serviceConfig.isValid()) { + lastError = QNetworkSession::OperationNotSupportedError; + emit q->error(lastError); + } else if (!isActive) { + + 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 q->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 q->error(lastError); + return; + } + opened = true; + + if ((activeConfig.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active) { + state = QNetworkSession::Connecting; + emit q->stateChanged(state); + + QTimer::singleShot(0, this, SLOT(do_open())); + return; + } + + isActive = (activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active; + if (isActive) + emit quitPendingWaitsForOpened(); + } else { + /* We seem to be active so inform caller */ + emit quitPendingWaitsForOpened(); + } +} + + +void QNetworkSessionPrivate::do_open() +{ + icd_connection_flags flags = connectFlags; + bool st; + QString result; + QString iap = publicConfig.identifier(); + QString bearer_name; + + if (state == QNetworkSession::Connected) { +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug() << "Already connected to" << activeConfig.identifier(); +#endif + emit q->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 params; + Maemo::ConnectParams param; + param.connect.service_type = config.d->service_type; + param.connect.service_attrs = config.d->service_attrs; + param.connect.service_id = config.d->service_id; + param.connect.network_type = config.d->iap_type; + param.connect.network_attrs = config.d->network_attrs; + if (config.d->network_attrs & ICD_NW_ATTR_IAPNAME) + param.connect.network_id = QByteArray(iap.toLatin1()); + else + param.connect.network_id = config.d->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 q->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 q->error(QNetworkSession::InvalidConfigurationError); + return; + } + + + /* Did we connect to non saved IAP? */ + if (!(config.d->network_attrs & ICD_NW_ATTR_IAPNAME)) { + /* Because the connection succeeded, the IAP is now known. + */ + config.d->network_attrs |= ICD_NW_ATTR_IAPNAME; + config.d->id = connected_iap; + } + + /* User might have changed the IAP name when a new IAP was saved */ + Maemo::IAPConf iap_name(config.d->id); + QString name = iap_name.value("name").toString(); + if (!name.isEmpty()) + config.d->name = name; + + bearer_name = connect_result.connect.network_type; + if (bearer_name == "WLAN_INFRA" || + bearer_name == "WLAN_ADHOC") + currentBearerName = "WLAN"; + else if (bearer_name == "GPRS") + currentBearerName = "HSPA"; + else + currentBearerName = bearer_name; + + config.d->isValid = true; + config.d->state = QNetworkConfiguration::Active; + config.d->type = QNetworkConfiguration::InternetAccessPoint; + + startTime = QDateTime::currentDateTime(); + updateState(QNetworkSession::Connected); + + currentNetworkInterface = get_network_interface(); + +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug() << "connected to" << result << config.d->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.d->type == QNetworkConfiguration::UserChoice) { + +#ifdef BEARER_MANAGEMENT_DEBUG +#if 0 + QList configs; + QNetworkConfigurationManagerPrivate *conPriv = (QNetworkConfigurationManagerPrivate*)config.d.data()->manager; + QList cpsIdents = conPriv->accessPointConfigurations.keys(); + foreach( QString ii, cpsIdents) { + QExplicitlySharedDataPointer p = + conPriv->accessPointConfigurations.value(ii); + QNetworkConfiguration pt; + pt.d = conPriv->accessPointConfigurations.value(ii); + configs << pt; + } + + int all = configs.count(); + qDebug() << "All configurations:" << all; + foreach(QNetworkConfiguration p, configs) { + qDebug() << p.name() <<": isvalid->" <"<< p.type() << + " roaming->" << p.isRoamingAvailable() << "identifier->" << p.identifier() << + " purpose->" << p.purpose() << " state->" << p.state(); + } +#endif +#endif + + QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)config.d.data()->manager; + if (!mgr->accessPointConfigurations.contains(result)) { + QExplicitlySharedDataPointer ptr = config.d; + mgr->accessPointConfigurations.insert(result, ptr); + + QNetworkConfiguration item; + item.d = ptr; + emit mgr->configurationAdded(item); + +#ifdef BEARER_MANAGEMENT_DEBUG + //qDebug()<<"New configuration"< priv = mgr->accessPointConfigurations.value(result); + QNetworkConfiguration reference; + reference.d = priv; + copyConfig(config, reference, false); + config = reference; + activeConfig = reference; + mgr->configurationChanged((QNetworkConfigurationPrivate*)(config.d.data())); + +#ifdef BEARER_MANAGEMENT_DEBUG + //qDebug()<<"Existing configuration"<error(QNetworkSession::UnknownSessionError); + } +} + + +void QNetworkSessionPrivate::cleanupAnyConfiguration() +{ +#ifdef BEARER_MANAGEMENT_DEBUG + qDebug()<<"Removing configuration created for" << activeConfig.d->id; +#endif + activeConfig = publicConfig; +} + + +void QNetworkSessionPrivate::close() +{ + if (serviceConfig.isValid()) { + lastError = QNetworkSession::OperationNotSupportedError; + emit q->error(lastError); + } else if (isActive) { + opened = false; + isActive = false; + emit q->closed(); + } +} + + +void QNetworkSessionPrivate::stop() +{ + if (serviceConfig.isValid()) { + lastError = QNetworkSession::OperationNotSupportedError; + emit q->error(lastError); + } else { + if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { + state = QNetworkSession::Closing; + emit q->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). + */ + + activeConfig.d->state = QNetworkConfiguration::Discovered; + QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)activeConfig.d.data()->manager; + mgr->configurationChanged((QNetworkConfigurationPrivate*)activeConfig.d.data()); + + opened = false; + isActive = false; + + } else { + opened = false; + isActive = false; + emit q->closed(); + } + } +} + + +void QNetworkSessionPrivate::migrate() +{ + qWarning("This platform does not support roaming (%s).", __FUNCTION__); +} + + +void QNetworkSessionPrivate::accept() +{ + qWarning("This platform does not support roaming (%s).", __FUNCTION__); +} + + +void QNetworkSessionPrivate::ignore() +{ + qWarning("This platform does not support roaming (%s).", __FUNCTION__); +} + + +void QNetworkSessionPrivate::reject() +{ + qWarning("This platform does not support roaming (%s).", __FUNCTION__); +} + + +QNetworkInterface QNetworkSessionPrivate::currentInterface() const +{ + if (!publicConfig.isValid() || state != QNetworkSession::Connected) + return QNetworkInterface(); + + if (currentNetworkInterface.isEmpty()) + return QNetworkInterface(); + + return QNetworkInterface::interfaceFromName(currentNetworkInterface); +} + + +void QNetworkSessionPrivate::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 QNetworkSessionPrivate::sessionProperty(const QString& key) const +{ + return properties.value(key); +} + + +QString QNetworkSessionPrivate::bearerName() const +{ + if (!publicConfig.isValid()) + return QString(); + + return currentBearerName; +} + + +QString QNetworkSessionPrivate::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 QNetworkSessionPrivate::error() const +{ + return QNetworkSession::UnknownSessionError; +} + +#include "qnetworksession_maemo.moc" +#include "moc_qnetworksession_maemo_p.cpp" + +QTM_END_NAMESPACE diff --git a/src/network/bearer/qnetworksession_maemo_p.h b/src/network/bearer/qnetworksession_maemo_p.h new file mode 100644 index 0000000..e233087 --- /dev/null +++ b/src/network/bearer/qnetworksession_maemo_p.h @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 QNETWORKSESSIONPRIVATE_H +#define QNETWORKSESSIONPRIVATE_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 "qnetworkconfigmanager_maemo_p.h" +#include "qnetworksession.h" + +#include +#include +#include + +#include + +QTM_BEGIN_NAMESPACE + +class QNetworkSessionPrivate : public QObject +{ + Q_OBJECT +public: + QNetworkSessionPrivate() : + tx_data(0), rx_data(0), m_activeTime(0), isActive(false), + connectFlags(ICD_CONNECTION_FLAG_USER_EVENT) + { + } + + ~QNetworkSessionPrivate() + { + 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); + QString bearerName() const; + + 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(); + +Q_SIGNALS: + //releases any pending waitForOpened() calls + void quitPendingWaitsForOpened(); + +private Q_SLOTS: + void do_open(); + void networkConfigurationsChanged(); + void configurationChanged(const QNetworkConfiguration &config); + +private: + QNetworkConfigurationManager manager; + + quint64 tx_data; + quint64 rx_data; + quint64 m_activeTime; + + // The config set on QNetworkSession. + QNetworkConfiguration publicConfig; + + // If publicConfig is a ServiceNetwork this is a copy of publicConfig. + // If publicConfig is an UserChoice that is resolved to a ServiceNetwork this is the actual + // ServiceNetwork configuration. + QNetworkConfiguration serviceConfig; + + // This is the actual active configuration currently in use by the session. + // Either a copy of publicConfig or one of serviceConfig.children(). + QNetworkConfiguration activeConfig; + + QNetworkConfiguration& copyConfig(QNetworkConfiguration &fromConfig, QNetworkConfiguration &toConfig, bool deepCopy = true); + void clearConfiguration(QNetworkConfiguration &config); + void cleanupAnyConfiguration(); + + QNetworkSession::State state; + bool isActive; + bool opened; + icd_connection_flags connectFlags; + + QNetworkSession::SessionError lastError; + + QNetworkSession* q; + friend class QNetworkSession; + + QDateTime startTime; + QString currentBearerName; + QString currentNetworkInterface; + friend class IcdListener; + void updateState(QNetworkSession::State); + void updateIdentifier(QString &newId); + quint64 getStatistics(bool sent) const; + void cleanupSession(void); +}; + +QTM_END_NAMESPACE + +#endif //QNETWORKSESSIONPRIVATE_H + diff --git a/src/network/bearer/qnetworksession_p.cpp b/src/network/bearer/qnetworksession_p.cpp new file mode 100644 index 0000000..c6f9833 --- /dev/null +++ b/src/network/bearer/qnetworksession_p.cpp @@ -0,0 +1,542 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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_p.h" +#include "qnetworksession.h" +#include "qnetworksessionengine_p.h" +#include "qgenericengine_p.h" + +#ifdef Q_OS_WIN +#include "qnlaengine_win_p.h" +#endif +#ifdef Q_OS_WIN32 +#include "qnativewifiengine_win_p.h" +#endif +#ifdef Q_OS_DARWIN +#include "qcorewlanengine_mac_p.h" +#endif +#include +#include +#include + +#include + +#if defined(BACKEND_NM) +#include "qnmwifiengine_unix_p.h" +#endif + +QTM_BEGIN_NAMESPACE + +#if defined(BACKEND_NM) +static bool NetworkManagerAvailable() +{ + QDBusConnection dbusConnection = QDBusConnection::systemBus(); + if (dbusConnection.isConnected()) { + QDBusConnectionInterface *dbiface = dbusConnection.interface(); + QDBusReply reply = dbiface->isServiceRegistered("org.freedesktop.NetworkManager"); + if (reply.isValid()) + return reply.value(); + } + return false; +} +#endif + +static QNetworkSessionEngine *getEngineFromId(const QString &id) +{ +#ifdef Q_OS_WIN + QNlaEngine *nla = QNlaEngine::instance(); + if (nla && nla->hasIdentifier(id)) + return nla; +#endif + +#ifdef Q_OS_WIN32 + QNativeWifiEngine *nativeWifi = QNativeWifiEngine::instance(); + if (nativeWifi && nativeWifi->hasIdentifier(id)) + return nativeWifi; +#endif + +#if defined(BACKEND_NM) + if(NetworkManagerAvailable()) { + QNmWifiEngine *nmwiifi = QNmWifiEngine::instance(); + if (nmwiifi && nmwiifi->hasIdentifier(id)) + return nmwiifi; + } +#endif +#ifdef Q_OS_DARWIN + QCoreWlanEngine *coreWifi = QCoreWlanEngine::instance(); + if (coreWifi && coreWifi->hasIdentifier(id)) + return coreWifi; + +#endif + QGenericEngine *generic = QGenericEngine::instance(); + if (generic && generic->hasIdentifier(id)) + return generic; + + 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_p.moc" + +Q_GLOBAL_STATIC(QNetworkSessionManagerPrivate, sessionManager); + +QNetworkSessionManagerPrivate::QNetworkSessionManagerPrivate(QObject *parent) +: QObject(parent) +{ +} + +QNetworkSessionManagerPrivate::~QNetworkSessionManagerPrivate() +{ +} + +void QNetworkSessionManagerPrivate::forceSessionClose(const QNetworkConfiguration &config) +{ + emit forcedSessionClose(config); +} + +void QNetworkSessionPrivate::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; + state = QNetworkSession::Invalid; + lastError = QNetworkSession::UnknownSessionError; + + qRegisterMetaType + ("QNetworkSessionEngine::ConnectionError"); + + switch (publicConfig.type()) { + case QNetworkConfiguration::InternetAccessPoint: + activeConfig = publicConfig; + engine = getEngineFromId(activeConfig.identifier()); + if (engine) { + connect(engine, SIGNAL(connectionError(QString,QNetworkSessionEngine::ConnectionError)), + this, SLOT(connectionError(QString,QNetworkSessionEngine::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 QNetworkSessionPrivate::open() +{ + if (serviceConfig.isValid()) { + lastError = QNetworkSession::OperationNotSupportedError; + emit q->error(lastError); + } else if (!isActive) { + if ((activeConfig.state() & QNetworkConfiguration::Discovered) != + QNetworkConfiguration::Discovered) { + lastError =QNetworkSession::InvalidConfigurationError; + emit q->error(lastError); + return; + } + opened = true; + + if ((activeConfig.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active && + (activeConfig.state() & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) { + state = QNetworkSession::Connecting; + emit q->stateChanged(state); + + engine->connectToId(activeConfig.identifier()); + } + + isActive = (activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active; + if (isActive) + emit quitPendingWaitsForOpened(); + } +} + +void QNetworkSessionPrivate::close() +{ + if (serviceConfig.isValid()) { + lastError = QNetworkSession::OperationNotSupportedError; + emit q->error(lastError); + } else if (isActive) { + opened = false; + isActive = false; + emit q->closed(); + } +} + +void QNetworkSessionPrivate::stop() +{ + if (serviceConfig.isValid()) { + lastError = QNetworkSession::OperationNotSupportedError; + emit q->error(lastError); + } else { + if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { + state = QNetworkSession::Closing; + emit q->stateChanged(state); + + engine->disconnectFromId(activeConfig.identifier()); + + sessionManager()->forceSessionClose(activeConfig); + } + + opened = false; + isActive = false; + emit q->closed(); + } +} + +void QNetworkSessionPrivate::migrate() +{ + qWarning("This platform does not support roaming (%s).", __FUNCTION__); +} + +void QNetworkSessionPrivate::accept() +{ + qWarning("This platform does not support roaming (%s).", __FUNCTION__); +} + +void QNetworkSessionPrivate::ignore() +{ + qWarning("This platform does not support roaming (%s).", __FUNCTION__); +} + +void QNetworkSessionPrivate::reject() +{ + qWarning("This platform does not support roaming (%s).", __FUNCTION__); +} + +QNetworkInterface QNetworkSessionPrivate::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 QNetworkSessionPrivate::sessionProperty(const QString& /*key*/) const +{ + return QVariant(); +} + +void QNetworkSessionPrivate::setSessionProperty(const QString& /*key*/, const QVariant& /*value*/) +{ +} + +QString QNetworkSessionPrivate::bearerName() const +{ + if (!publicConfig.isValid() || !engine) + return QString(); + + return engine->bearerName(activeConfig.identifier()); +} + +QString QNetworkSessionPrivate::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 QNetworkSessionPrivate::error() const +{ + return lastError; +} + +quint64 QNetworkSessionPrivate::bytesWritten() const +{ +#if defined(BACKEND_NM) + if( state == QNetworkSession::Connected ) { + if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) { + foreach (const QNetworkConfiguration &config, publicConfig.children()) { + if ((config.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { + return static_cast(getEngineFromId(config.d->id))->sentDataForId(config.d->id); + } + } + } else { + return static_cast(getEngineFromId(activeConfig.d->id))->sentDataForId(activeConfig.d->id); + } + } +#endif + return tx_data; +} + +quint64 QNetworkSessionPrivate::bytesReceived() const +{ +#if defined(BACKEND_NM) + if( state == QNetworkSession::Connected ) { + if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) { + foreach (const QNetworkConfiguration &config, publicConfig.children()) { + if ((config.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { + return static_cast(getEngineFromId(activeConfig.d->id))->receivedDataForId(config.d->id); + } + } + } else { + return static_cast(getEngineFromId(activeConfig.d->id))->receivedDataForId(activeConfig.d->id); + } + } +#endif + return rx_data; +} + +quint64 QNetworkSessionPrivate::activeTime() const +{ +#if defined(BACKEND_NM) + if (startTime.isNull()) { + return 0; + } + if(state == QNetworkSession::Connected ) + return startTime.secsTo(QDateTime::currentDateTime()); +#endif + return m_activeTime; +} + +void QNetworkSessionPrivate::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,QNetworkSessionEngine::ConnectionError)), + this, SLOT(connectionError(QString,QNetworkSessionEngine::ConnectionError))); + } + + activeConfig = config; + engine = getEngineFromId(activeConfig.identifier()); + if (engine) { + connect(engine, SIGNAL(connectionError(QString,QNetworkSessionEngine::ConnectionError)), + this, SLOT(connectionError(QString,QNetworkSessionEngine::ConnectionError)), + Qt::QueuedConnection); + } + emit q->newConfigurationActivated(); + } + + state = QNetworkSession::Connected; + if (state != oldState) + emit q->stateChanged(state); + + return; + } + + if (serviceConfig.children().isEmpty()) + state = QNetworkSession::NotAvailable; + else + state = QNetworkSession::Disconnected; + + if (state != oldState) + emit q->stateChanged(state); +} + +void QNetworkSessionPrivate::updateStateFromActiveConfig() +{ + QNetworkSession::State oldState = state; + + bool newActive = false; + + if (!activeConfig.isValid()) { + state = QNetworkSession::Invalid; + } 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; + } + + bool oldActive = isActive; + isActive = newActive; + + if (!oldActive && isActive) + emit quitPendingWaitsForOpened(); + if (oldActive && !isActive) + emit q->closed(); + + if (oldState != state) + emit q->stateChanged(state); +} + +void QNetworkSessionPrivate::networkConfigurationsChanged() +{ + if (serviceConfig.isValid()) + updateStateFromServiceNetwork(); + else + updateStateFromActiveConfig(); +#if defined(BACKEND_NM) + setActiveTimeStamp(); +#endif +} + +void QNetworkSessionPrivate::configurationChanged(const QNetworkConfiguration &config) +{ + if (serviceConfig.isValid() && (config == serviceConfig || config == activeConfig)) + updateStateFromServiceNetwork(); + else if (config == activeConfig) + updateStateFromActiveConfig(); +} + +void QNetworkSessionPrivate::forcedSessionClose(const QNetworkConfiguration &config) +{ + if (activeConfig == config) { + opened = false; + isActive = false; + + emit q->closed(); + + lastError = QNetworkSession::SessionAbortedError; + emit q->error(lastError); + } +} + +void QNetworkSessionPrivate::connectionError(const QString &id, QNetworkSessionEngine::ConnectionError error) +{ + if (activeConfig.identifier() == id) { + networkConfigurationsChanged(); + switch (error) { + case QNetworkSessionEngine::OperationNotSupported: + lastError = QNetworkSession::OperationNotSupportedError; + opened = false; + break; + case QNetworkSessionEngine::InterfaceLookupError: + case QNetworkSessionEngine::ConnectError: + case QNetworkSessionEngine::DisconnectionError: + default: + lastError = QNetworkSession::UnknownSessionError; + } + + emit quitPendingWaitsForOpened(); + emit q->error(lastError); + } +} + +#if defined(BACKEND_NM) +void QNetworkSessionPrivate::setActiveTimeStamp() +{ + if(NetworkManagerAvailable()) { + startTime = QDateTime(); + return; + } + QString connectionIdent = q->configuration().identifier(); + QString interface = currentInterface().hardwareAddress().toLower(); + QString devicePath = "/org/freedesktop/Hal/devices/net_" + interface.replace(":","_"); + + QString path; + QString serviceName; + QNetworkManagerInterface * ifaceD; + ifaceD = new QNetworkManagerInterface(); + + QList connections = ifaceD->activeConnections(); + foreach(QDBusObjectPath conpath, connections) { + QNetworkManagerConnectionActive *conDetails; + conDetails = new QNetworkManagerConnectionActive(conpath.path()); + QDBusObjectPath connection = conDetails->connection(); + serviceName = conDetails->serviceName(); + QList so = conDetails->devices(); + foreach(QDBusObjectPath device, so) { + + if(device.path() == devicePath) { + path = connection.path(); + } + break; + } + } +if(serviceName.isEmpty()) + return; + QNetworkManagerSettings *settingsiface; + settingsiface = new QNetworkManagerSettings(serviceName); + QList list = settingsiface->listConnections(); + foreach(QDBusObjectPath path, list) { + QNetworkManagerSettingsConnection *sysIface; + sysIface = new QNetworkManagerSettingsConnection(serviceName, path.path()); + startTime = QDateTime::fromTime_t(sysIface->getTimestamp()); + // isActive = (publicConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active; + } + if(startTime.isNull()) + startTime = QDateTime::currentDateTime(); +} +#endif + +#include "moc_qnetworksession_p.cpp" +QTM_END_NAMESPACE + diff --git a/src/network/bearer/qnetworksession_p.h b/src/network/bearer/qnetworksession_p.h new file mode 100644 index 0000000..a2aaa6a --- /dev/null +++ b/src/network/bearer/qnetworksession_p.h @@ -0,0 +1,167 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 QNETWORKSESSIONPRIVATE_H +#define QNETWORKSESSIONPRIVATE_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 "qnetworkconfigmanager_p.h" +#include "qnetworksession.h" +#ifdef BEARER_ENGINE +#include "qnetworksessionengine_p.h" +#endif + +#include "qnetworksession.h" +#include +#include + +QTM_BEGIN_NAMESPACE +#ifdef BEARER_ENGINE +class QNetworkSessionEngine; +#endif + +class QNetworkSessionPrivate : public QObject +{ + Q_OBJECT +public: + QNetworkSessionPrivate() : + tx_data(0), rx_data(0), m_activeTime(0), isActive(false) + { + } + + ~QNetworkSessionPrivate() + { + } + + //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); + QString bearerName() const; + + 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(); + +Q_SIGNALS: + //releases any pending waitForOpened() calls + void quitPendingWaitsForOpened(); + +private Q_SLOTS: +#ifdef BEARER_ENGINE + void networkConfigurationsChanged(); + void configurationChanged(const QNetworkConfiguration &config); + void forcedSessionClose(const QNetworkConfiguration &config); + void connectionError(const QString &id, QNetworkSessionEngine::ConnectionError error); +#endif + +private: + QNetworkConfigurationManager manager; + + quint64 tx_data; + quint64 rx_data; + quint64 m_activeTime; + + // The config set on QNetworkSession. + QNetworkConfiguration publicConfig; + + // If publicConfig is a ServiceNetwork this is a copy of publicConfig. + // If publicConfig is an UserChoice that is resolved to a ServiceNetwork this is the actual + // ServiceNetwork configuration. + QNetworkConfiguration serviceConfig; + + // This is the actual active configuration currently in use by the session. + // Either a copy of publicConfig or one of serviceConfig.children(). + QNetworkConfiguration activeConfig; + + QNetworkSession::State state; + bool isActive; + +#ifdef BEARER_ENGINE + bool opened; + + QNetworkSessionEngine *engine; +#endif + QNetworkSession::SessionError lastError; + + QNetworkSession* q; + friend class QNetworkSession; + +#if defined(BEARER_ENGINE) && defined(BACKEND_NM) + QDateTime startTime; + void setActiveTimeStamp(); +#endif +}; + +QTM_END_NAMESPACE + +#endif //QNETWORKSESSIONPRIVATE_H + diff --git a/src/network/bearer/qnetworksession_s60_p.cpp b/src/network/bearer/qnetworksession_s60_p.cpp new file mode 100644 index 0000000..764c1c4 --- /dev/null +++ b/src/network/bearer/qnetworksession_s60_p.cpp @@ -0,0 +1,1168 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 +#include "qnetworksession_s60_p.h" +#include "qnetworkconfiguration_s60_p.h" +#include "qnetworkconfigmanager_s60_p.h" +#include +#include +#include +#include +#include + +QTM_BEGIN_NAMESPACE + +QNetworkSessionPrivate::QNetworkSessionPrivate() + : CActive(CActive::EPriorityStandard), state(QNetworkSession::Invalid), + isActive(false), 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()); +} + +QNetworkSessionPrivate::~QNetworkSessionPrivate() +{ + isActive = 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 QNetworkSessionPrivate::syncStateWithInterface() +{ + if (!publicConfig.d) { + 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 ((publicConfig.d.data()->state & QNetworkConfiguration::Discovered) == + QNetworkConfiguration::Discovered) { + newState(QNetworkSession::Disconnected); + } else { + newState(QNetworkSession::NotAvailable); + } + } +} + +QNetworkInterface QNetworkSessionPrivate::interface(TUint iapId) const +{ + QString interfaceName; + + TSoInetInterfaceInfo ifinfo; + TPckg ifinfopkg(ifinfo); + TSoInetIfQuery ifquery; + TPckg 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 QNetworkSessionPrivate::currentInterface() const +{ + if (!publicConfig.isValid() || state != QNetworkSession::Connected) { + return QNetworkInterface(); + } + + return activeInterface; +} + +QVariant QNetworkSessionPrivate::sessionProperty(const QString& /*key*/) const +{ + return QVariant(); +} + +void QNetworkSessionPrivate::setSessionProperty(const QString& /*key*/, const QVariant& /*value*/) +{ +} + +QString QNetworkSessionPrivate::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 QNetworkSessionPrivate::error() const +{ + return iError; +} + +void QNetworkSessionPrivate::open() +{ + if (isActive || !publicConfig.d || (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 q->error(iError); + syncStateWithInterface(); + return; + } + + error = iConnection.Open(iSocketServ); + if (error != KErrNone) { + // Could not open RConnection + iSocketServ.Close(); + newState(QNetworkSession::Invalid); + iError = QNetworkSession::UnknownSessionError; + emit q->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 == publicConfig.d.data()->numericId) { + if (iConnection.Attach(connInfo, RConnection::EAttachTypeNormal) == KErrNone) { + activeConfig = publicConfig; + activeInterface = interface(activeConfig.d.data()->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); + } + isActive = true; + // Make sure that state will be Connected + newState(QNetworkSession::Connected); + emit quitPendingWaitsForOpened(); + break; + } + } + } + } + } + if (!connected) { + TCommDbConnPref pref; + pref.SetDialogPreference(ECommDbDialogPrefDoNotPrompt); + pref.SetIapId(publicConfig.d.data()->numericId); + iConnection.Start(pref, iStatus); + if (!IsActive()) { + SetActive(); + } + newState(QNetworkSession::Connecting); + } + } else if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) { + TConnSnapPref snapPref(publicConfig.d.data()->numericId); + iConnection.Start(snapPref, iStatus); + if (!IsActive()) { + SetActive(); + } + newState(QNetworkSession::Connecting); + } else if (publicConfig.type() == QNetworkConfiguration::UserChoice) { + iKnownConfigsBeforeConnectionStart = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.keys(); + iConnection.Start(iStatus); + if (!IsActive()) { + SetActive(); + } + newState(QNetworkSession::Connecting); + } + + if (error != KErrNone) { + isActive = false; + iError = QNetworkSession::UnknownSessionError; + emit q->error(iError); + if (ipConnectionNotifier) { + ipConnectionNotifier->StopNotifications(); + } + syncStateWithInterface(); + } +} + +TUint QNetworkSessionPrivate::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 QNetworkSessionPrivate::close(bool allowSignals) +{ + if (!isActive) { + return; + } + + TUint activeIap = activeConfig.d.data()->numericId; + isActive = 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 q->closed(); + } +} + +void QNetworkSessionPrivate::stop() +{ + if (!isActive) { + return; + } + isActive = false; + newState(QNetworkSession::Closing); + iConnection.Stop(RConnection::EStopAuthoritative); + isActive = true; + close(false); + emit q->closed(); +} + +void QNetworkSessionPrivate::migrate() +{ +#ifdef SNAP_FUNCTIONALITY_AVAILABLE + iMobility->MigrateToPreferredCarrier(); +#endif +} + +void QNetworkSessionPrivate::ignore() +{ +#ifdef SNAP_FUNCTIONALITY_AVAILABLE + iMobility->IgnorePreferredCarrier(); + if (!iALRUpgradingConnection) { + newState(QNetworkSession::Disconnected); + } else { + newState(QNetworkSession::Connected,iOldRoamingIap); + } +#endif +} + +void QNetworkSessionPrivate::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 QNetworkSessionPrivate::reject() +{ +#ifdef SNAP_FUNCTIONALITY_AVAILABLE + iMobility->NewCarrierRejected(); + if (!iALRUpgradingConnection) { + newState(QNetworkSession::Disconnected); + } else { + newState(QNetworkSession::Connected, iOldRoamingIap); + } +#endif +} + +#ifdef SNAP_FUNCTIONALITY_AVAILABLE +void QNetworkSessionPrivate::PreferredCarrierAvailable(TAccessPointInfo aOldAPInfo, + TAccessPointInfo aNewAPInfo, + TBool aIsUpgrade, + TBool aIsSeamless) +{ + iOldRoamingIap = aOldAPInfo.AccessPoint(); + iNewRoamingIap = aNewAPInfo.AccessPoint(); + newState(QNetworkSession::Roaming); + if (iALREnabled > 0) { + iALRUpgradingConnection = aIsUpgrade; + QList configs = publicConfig.children(); + for (int i=0; i < configs.count(); i++) { + if (configs[i].d.data()->numericId == aNewAPInfo.AccessPoint()) { + emit q->preferredConfigurationChanged(configs[i],aIsSeamless); + } + } + } else { + migrate(); + } +} + +void QNetworkSessionPrivate::NewCarrierActive(TAccessPointInfo /*aNewAPInfo*/, TBool /*aIsSeamless*/) +{ + if (iALREnabled > 0) { + emit q->newConfigurationActivated(); + } else { + accept(); + } +} + +void QNetworkSessionPrivate::Error(TInt /*aError*/) +{ + if (isActive) { + isActive = false; + activeConfig = QNetworkConfiguration(); + serviceConfig = QNetworkConfiguration(); + iError = QNetworkSession::RoamingError; + emit q->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 q->closed(); + } +} +#endif + +void QNetworkSessionPrivate::setALREnabled(bool enabled) +{ + if (enabled) { + iALREnabled++; + } else { + iALREnabled--; + } +} + +QNetworkConfiguration QNetworkSessionPrivate::bestConfigFromSNAP(const QNetworkConfiguration& snapConfig) const +{ + QNetworkConfiguration config; + QList 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; +} + +QString QNetworkSessionPrivate::bearerName() const +{ + QNetworkConfiguration config; + if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) { + config = publicConfig; + } else if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) { + if (activeConfig.isValid()) { + config = activeConfig; + } else { + config = bestConfigFromSNAP(publicConfig); + } + } else if (publicConfig.type() == QNetworkConfiguration::UserChoice) { + if (activeConfig.isValid()) { + config = activeConfig; + } + } + + if (!config.isValid()) { + return QString(); + } + + switch (config.d.data()->bearer) { + case QNetworkConfigurationPrivate::BearerEthernet: return QString("Ethernet"); + case QNetworkConfigurationPrivate::BearerWLAN: return QString("WLAN"); + case QNetworkConfigurationPrivate::Bearer2G: return QString("2G"); + case QNetworkConfigurationPrivate::BearerCDMA2000: return QString("CDMA2000"); + case QNetworkConfigurationPrivate::BearerWCDMA: return QString("WCDMA"); + case QNetworkConfigurationPrivate::BearerHSPA: return QString("HSPA"); + case QNetworkConfigurationPrivate::BearerBluetooth: return QString("Bluetooth"); + case QNetworkConfigurationPrivate::BearerWiMAX: return QString("WiMAX"); + default: return QString(); + } +} + +quint64 QNetworkSessionPrivate::bytesWritten() const +{ + return transferredData(KUplinkData); +} + +quint64 QNetworkSessionPrivate::bytesReceived() const +{ + return transferredData(KDownlinkData); +} + +quint64 QNetworkSessionPrivate::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 configs = config.children(); + for (int i=0; i < configs.count(); i++) { + if (configs[i].d.data()->numericId == apId) { + configFound = true; + break; + } + } + } else if (config.d.data()->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 QNetworkSessionPrivate::activeTime() const +{ + if (!isActive || startTime.isNull()) { + return 0; + } + return startTime.secsTo(QDateTime::currentDateTime()); +} + +QNetworkConfiguration QNetworkSessionPrivate::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 children = publicConfig.children(); + for (int i=0; i < children.count(); i++) { + if (children[i].d.data()->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; + pt.d = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.value(QString::number(qHash(iapId))); + if (pt.d) { + for (int i=0; i < children.count(); i++) { + if (children[i].d.data()->mappingName == pt.d.data()->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 (publicConfig.d.data()->manager) { + QNetworkConfiguration pt; + // Try to found User Selected IAP from known IAPs (accessPointConfigurations) + pt.d = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.value(QString::number(qHash(iapId))); + if (pt.d) { + return pt; + } else { + // Check if new (WLAN) IAP was created in IAP/SNAP dialog + // 1. Sync internal configurations array to commsdb first + ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->updateConfigurations(); + // 2. Check if new configuration was created during connection creation + QList knownConfigs = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->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.d = ((QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager)->accessPointConfigurations.value(newIapId); + if (pt.d) { + return pt; + } + } + } + } + return QNetworkConfiguration(); + } + + return publicConfig; +} + +void QNetworkSessionPrivate::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) { + isActive = false; + iError = QNetworkSession::UnknownSessionError; + emit q->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 + isActive = true; + activeConfig = newActiveConfig; + activeInterface = interface(activeConfig.d.data()->numericId); + if (publicConfig.type() == QNetworkConfiguration::UserChoice) { + QNetworkConfiguration pt; + pt.d = activeConfig.d.data()->serviceNetworkPtr; + serviceConfig = pt; + } + + startTime = QDateTime::currentDateTime(); + + newState(QNetworkSession::Connected); + emit quitPendingWaitsForOpened(); + } + break; + case KErrNotFound: // Connection failed + isActive = false; + activeConfig = QNetworkConfiguration(); + serviceConfig = QNetworkConfiguration(); + iError = QNetworkSession::InvalidConfigurationError; + emit q->error(iError); + Cancel(); + if (ipConnectionNotifier) { + ipConnectionNotifier->StopNotifications(); + } + syncStateWithInterface(); + break; + case KErrCancel: // Connection attempt cancelled + case KErrAlreadyExists: // Connection already exists + default: + isActive = false; + activeConfig = QNetworkConfiguration(); + serviceConfig = QNetworkConfiguration(); + iError = QNetworkSession::UnknownSessionError; + emit q->error(iError); + Cancel(); + if (ipConnectionNotifier) { + ipConnectionNotifier->StopNotifications(); + } + syncStateWithInterface(); + break; + } +} + +void QNetworkSessionPrivate::DoCancel() +{ + iConnection.Close(); +} + +bool QNetworkSessionPrivate::newState(QNetworkSession::State newState, TUint accessPointId) +{ + // Make sure that activeConfig is always updated when SNAP is signaled to be + // connected. + if (isActive && publicConfig.type() == QNetworkConfiguration::ServiceNetwork && + newState == QNetworkSession::Connected) { + activeConfig = activeConfiguration(accessPointId); + activeInterface = interface(activeConfig.d.data()->numericId); + } + + // 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 (isActive && 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). + isActive = false; + activeConfig = QNetworkConfiguration(); + serviceConfig = QNetworkConfiguration(); + iError = QNetworkSession::SessionAbortedError; + emit q->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 q->stateChanged(state); + retVal = true; + } else { + if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) { + if (publicConfig.d.data()->numericId == accessPointId) { + state = newState; + emit q->stateChanged(state); + retVal = true; + } + } else if (publicConfig.type() == QNetworkConfiguration::UserChoice && isActive) { + if (activeConfig.d.data()->numericId == accessPointId) { + state = newState; + emit q->stateChanged(state); + retVal = true; + } + } else if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) { + QList subConfigurations = publicConfig.children(); + for (int i = 0; i < subConfigurations.count(); i++) { + if (subConfigurations[i].d.data()->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. + subConfigurations[i].d.data()->state = QNetworkConfiguration::Active; + + state = newState; + emit q->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. + subConfigurations[i].d.data()->state = QNetworkConfiguration::Defined; + } + QNetworkConfiguration config = bestConfigFromSNAP(publicConfig); + if ((config.state() == QNetworkConfiguration::Defined) || + (config.state() == QNetworkConfiguration::Discovered)) { + state = newState; + emit q->stateChanged(state); + retVal = true; + } + } + } + } + } + } + + if (emitSessionClosed) { + emit q->closed(); + } + + return retVal; +} + +void QNetworkSessionPrivate::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 QNetworkSessionPrivate::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 subConfigurations = publicConfig.children(); + for (int i = 0; i < subConfigurations.count(); i++ ) { + if (subConfigurations[i].d.data()->connectionId == connectionId) { + apId = subConfigurations[i].d.data()->numericId; + break; + } + } + } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) { + if (publicConfig.d.data()->connectionId == connectionId) { + apId = publicConfig.d.data()->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 subConfigurations = publicConfig.children(); + for (int i = 0; i < subConfigurations.count(); i++ ) { + if (subConfigurations[i].d.data()->numericId == apId) { + subConfigurations[i].d.data()->connectionId = connectionId; + break; + } + } + } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) { + if (publicConfig.d.data()->numericId == apId) { + publicConfig.d.data()->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 subConfigurations = publicConfig.children(); + for (int i = 0; i < subConfigurations.count(); i++ ) { + if (subConfigurations[i].d.data()->connectionId == connectionId) { + subConfigurations[i].d.data()->connectionId = 0; + break; + } + } + } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) { + if (publicConfig.d.data()->connectionId == connectionId) { + publicConfig.d.data()->connectionId = 0; + } + } + } + break; + + default: + // For unrecognized events + break; + } +} + +ConnectionProgressNotifier::ConnectionProgressNotifier(QNetworkSessionPrivate& 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); + } +} + +#include "moc_qnetworksession_s60_p.cpp" + +QTM_END_NAMESPACE diff --git a/src/network/bearer/qnetworksession_s60_p.h b/src/network/bearer/qnetworksession_s60_p.h new file mode 100644 index 0000000..cfb99c9 --- /dev/null +++ b/src/network/bearer/qnetworksession_s60_p.h @@ -0,0 +1,213 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 QNETWORKSESSIONPRIVATE_H +#define QNETWORKSESSIONPRIVATE_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 "qnetworksession.h" + +#include + +#include +#include +#include +#include +#ifdef SNAP_FUNCTIONALITY_AVAILABLE + #include +#endif + +typedef int(*TOpenCSetdefaultifFunction)(const struct ifreq*); + +QTM_BEGIN_NAMESPACE + +class ConnectionProgressNotifier; + +#ifdef SNAP_FUNCTIONALITY_AVAILABLE +class QNetworkSessionPrivate : public QObject, public CActive, public MMobilityProtocolResp, + public MConnectionMonitorObserver +#else +class QNetworkSessionPrivate : public QObject, public CActive, public MConnectionMonitorObserver +#endif +{ + Q_OBJECT +public: + QNetworkSessionPrivate(); + ~QNetworkSessionPrivate(); + + //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); + QString bearerName() const; + + void setALREnabled(bool enabled); + + void open(); + void close(bool allowSignals = true); + 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 + +Q_SIGNALS: + //releases any pending waitForOpened() calls + void quitPendingWaitsForOpened(); + +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 + // The config set on QNetworkSession + mutable QNetworkConfiguration publicConfig; + + // If publicConfig is a ServiceNetwork this is a copy of publicConfig. + // If publicConfig is an UserChoice that is resolved to a ServiceNetwork this is the actual + // ServiceNetwork configuration. + mutable QNetworkConfiguration serviceConfig; + + // This is the actual active configuration currently in use by the session. + // Either a copy of publicConfig or one of serviceConfig.children(). + mutable QNetworkConfiguration activeConfig; + + mutable QNetworkInterface activeInterface; + + QNetworkSession::State state; + bool isActive; + + QNetworkSession* q; + 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 iKnownConfigsBeforeConnectionStart; + + TUint32 iOldRoamingIap; + TUint32 iNewRoamingIap; + + friend class QNetworkSession; + friend class ConnectionProgressNotifier; +}; + +class ConnectionProgressNotifier : public CActive +{ +public: + ConnectionProgressNotifier(QNetworkSessionPrivate& owner, RConnection& connection); + ~ConnectionProgressNotifier(); + + void StartNotifications(); + void StopNotifications(); + +protected: // From CActive + void RunL(); + void DoCancel(); + +private: // Data + QNetworkSessionPrivate& iOwner; + RConnection& iConnection; + TNifProgressBuf iProgress; + +}; + +QTM_END_NAMESPACE + +#endif //QNETWORKSESSIONPRIVATE_H + diff --git a/src/network/bearer/qnetworksessionengine.cpp b/src/network/bearer/qnetworksessionengine.cpp new file mode 100644 index 0000000..55fc4f3 --- /dev/null +++ b/src/network/bearer/qnetworksessionengine.cpp @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 "qnetworksessionengine_p.h" + +QTM_BEGIN_NAMESPACE + +QNetworkSessionEngine::QNetworkSessionEngine(QObject *parent) +: QObject(parent) +{ +} + +QNetworkSessionEngine::~QNetworkSessionEngine() +{ +} + +#include "moc_qnetworksessionengine_p.cpp" +QTM_END_NAMESPACE + diff --git a/src/network/bearer/qnetworksessionengine_p.h b/src/network/bearer/qnetworksessionengine_p.h new file mode 100644 index 0000000..795a209 --- /dev/null +++ b/src/network/bearer/qnetworksessionengine_p.h @@ -0,0 +1,98 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 QNETWORKSESSIONENGINE_P_H +#define QNETWORKSESSIONENGINE_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 +#include +#include +#include +#include + +QTM_BEGIN_NAMESPACE + +class QNetworkConfigurationPrivate; +class QNetworkSessionEngine : public QObject +{ + Q_OBJECT + +public: + enum ConnectionError { + InterfaceLookupError = 0, + ConnectError, + OperationNotSupported, + DisconnectionError, + }; + + QNetworkSessionEngine(QObject *parent = 0); + virtual ~QNetworkSessionEngine(); + + virtual QList getConfigurations(bool *ok = 0) = 0; + virtual QString getInterfaceFromId(const QString &id) = 0; + virtual bool hasIdentifier(const QString &id) = 0; + + virtual QString bearerName(const QString &id) = 0; + + virtual void connectToId(const QString &id) = 0; + virtual void disconnectFromId(const QString &id) = 0; + + virtual void requestUpdate() = 0; + +Q_SIGNALS: + void configurationsChanged(); + void connectionError(const QString &id, QNetworkSessionEngine::ConnectionError error); +}; + +QTM_END_NAMESPACE + +#endif diff --git a/src/network/bearer/qnetworksessionengine_win_p.h b/src/network/bearer/qnetworksessionengine_win_p.h new file mode 100644 index 0000000..cf01719 --- /dev/null +++ b/src/network/bearer/qnetworksessionengine_win_p.h @@ -0,0 +1,145 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 QNETWORKSESSIONENGINE_WIN_P_H +#define QNETWORKSESSIONENGINE_WIN_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 +#include +#undef interface +#include + +#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 // QNETWORKSESSIONENGINE_WIN_P_H diff --git a/src/network/bearer/qnlaengine_win.cpp b/src/network/bearer/qnlaengine_win.cpp new file mode 100644 index 0000000..b606ef4 --- /dev/null +++ b/src/network/bearer/qnlaengine_win.cpp @@ -0,0 +1,592 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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_win_p.h" +#include "qnetworkconfiguration_p.h" + +#include +#include +#include +#include + +#include + +#include "qnetworksessionengine_win_p.h" + +QTM_BEGIN_NAMESPACE + +Q_GLOBAL_STATIC(QNlaEngine, nlaEngine) + +QWindowsSockInit::QWindowsSockInit() +: 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; + } +} + +QWindowsSockInit::~QWindowsSockInit() +{ + 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("\\\\.\\%1").arg(interface).utf16(), 0, + FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); + if (handle == INVALID_HANDLE_VALUE) + return QString(); + + 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 QString(); + } + + 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 QString(); + } + + 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 QString(); +} + +class QNlaThread : public QThread +{ + Q_OBJECT + +public: + QNlaThread(QNlaEngine *parent = 0); + ~QNlaThread(); + + QList getConfigurations(); + + void forceUpdate(); + +protected: + virtual void run(); + +private: + void updateConfigurations(QList &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 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 QNlaThread::getConfigurations() +{ + QMutexLocker locker(&mutex); + + QList foundConfigurations; + + for (int i = 0; i < fetchedConfigurations.count(); ++i) { + QNetworkConfigurationPrivate *config = new QNetworkConfigurationPrivate; + config->name = fetchedConfigurations.at(i)->name; + config->isValid = fetchedConfigurations.at(i)->isValid; + config->id = fetchedConfigurations.at(i)->id; + config->state = fetchedConfigurations.at(i)->state; + config->type = fetchedConfigurations.at(i)->type; + config->roamingSupported = fetchedConfigurations.at(i)->roamingSupported; + config->purpose = fetchedConfigurations.at(i)->purpose; + config->internet = fetchedConfigurations.at(i)->internet; + + foundConfigurations.append(config); + } + + 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) {} +#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 &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(parent())) { + engine->configurationInterface[cpPriv->id.toUInt()] = + QString(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(querySet->lpBlob->pBlobData + offset); + DWORD nextOffset = parseBlob(blob, cpPriv); + if (nextOffset == offset) + break; + else + offset = nextOffset; + } while (offset != 0 && offset < querySet->lpBlob->cbSize); + } + + return cpPriv; +} + +void QNlaThread::fetchConfigurations() +{ + QList 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(buffer)); + + if (result == SOCKET_ERROR) { + int error = WSAGetLastError(); + + if (error == WSA_E_NO_MORE) + break; + + if (error == WSAEFAULT) { + qDebug() << "buffer not big enough" << bufferLength; + break; + } + + qWarning("WSALookupServiceNext error %d", WSAGetLastError()); + break; + } + + QNetworkConfigurationPrivate *cpPriv = + parseQuerySet(reinterpret_cast(buffer)); + + foundConfigurations.append(cpPriv); + } + + if (hLookup) { + result = WSALookupServiceEnd(hLookup); + if (result == SOCKET_ERROR) { + qWarning("WSALookupServiceEnd error %d", WSAGetLastError()); + } + } + + updateConfigurations(foundConfigurations); +} + +QNlaEngine::QNlaEngine(QObject *parent) +: QNetworkSessionEngine(parent), nlaThread(0) +{ + nlaThread = new QNlaThread(this); + connect(nlaThread, SIGNAL(networksChanged()), + this, SIGNAL(configurationsChanged())); + nlaThread->start(); + + qApp->processEvents(QEventLoop::ExcludeUserInputEvents); +} + +QNlaEngine::~QNlaEngine() +{ + delete nlaThread; +} + +QList QNlaEngine::getConfigurations(bool *ok) +{ + if (ok) + *ok = true; + + return nlaThread->getConfigurations(); +} + +QString QNlaEngine::getInterfaceFromId(const QString &id) +{ + return configurationInterface.value(id.toUInt()); +} + +bool QNlaEngine::hasIdentifier(const QString &id) +{ + if (configurationInterface.contains(id.toUInt())) + return true; + + foreach (QNetworkConfigurationPrivate *cpPriv, nlaThread->getConfigurations()) { + if (cpPriv->id == id) + return true; + } + + return false; +} + +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(); +} + +QNlaEngine *QNlaEngine::instance() +{ + return nlaEngine(); +} + +#include "qnlaengine_win.moc" +#include "moc_qnlaengine_win_p.cpp" +QTM_END_NAMESPACE + + + diff --git a/src/network/bearer/qnlaengine_win_p.h b/src/network/bearer/qnlaengine_win_p.h new file mode 100644 index 0000000..394b8cf --- /dev/null +++ b/src/network/bearer/qnlaengine_win_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 "qnetworksessionengine_p.h" + +#include + +QTM_BEGIN_NAMESPACE + +class QNetworkConfigurationPrivate; +class QNlaThread; + +class QWindowsSockInit +{ +public: + QWindowsSockInit(); + ~QWindowsSockInit(); + int version; +}; + +class QNlaEngine : public QNetworkSessionEngine +{ + Q_OBJECT + + friend class QNlaThread; + +public: + QNlaEngine(QObject *parent = 0); + ~QNlaEngine(); + + QList getConfigurations(bool *ok = 0); + QString getInterfaceFromId(const QString &id); + bool hasIdentifier(const QString &id); + + QString bearerName(const QString &id); + + void connectToId(const QString &id); + void disconnectFromId(const QString &id); + + void requestUpdate(); + + static QNlaEngine *instance(); + +private: + QWindowsSockInit winSock; + QNlaThread *nlaThread; + QMap configurationInterface; +}; + +QTM_END_NAMESPACE + +#endif diff --git a/src/network/bearer/qnmdbushelper.cpp b/src/network/bearer/qnmdbushelper.cpp new file mode 100644 index 0000000..3b780f6 --- /dev/null +++ b/src/network/bearer/qnmdbushelper.cpp @@ -0,0 +1,117 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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_p.h" + +#if !defined(QT_NO_DBUS) && !defined(Q_OS_MAC) +#include + +#include +#include +#include +#include +#endif + +#include + +QTM_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 map) +{ + QDBusMessage msg = this->message(); + QMapIterator 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") { + // qWarning() << __PRETTY_FUNCTION__ << i.key() << ": " << i.value().value().path(); + // } else if( i.key() == "Strength") + // qWarning() << __PRETTY_FUNCTION__ << i.key() << ": " << i.value().toUInt(); + // else + // qWarning() << __PRETTY_FUNCTION__ << i.key() << ": " << i.value(); + } + } +} + +void QNmDBusHelper::slotSettingsRemoved() +{ + QDBusMessage msg = this->message(); + emit pathForSettingsRemoved(msg.path()); +} + +#include "moc_qnmdbushelper_p.cpp" +QTM_END_NAMESPACE diff --git a/src/network/bearer/qnmdbushelper_p.h b/src/network/bearer/qnmdbushelper_p.h new file mode 100644 index 0000000..f0248dc --- /dev/null +++ b/src/network/bearer/qnmdbushelper_p.h @@ -0,0 +1,90 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 + +// +// 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 +#if !defined(QT_NO_DBUS) && !defined(Q_OS_MAC) +#include +#include +#include +#endif + +QTM_BEGIN_NAMESPACE + +#if !defined(QT_NO_DBUS) && !defined(Q_OS_MAC) + +class QNmDBusHelper: public QObject, protected QDBusContext + { + Q_OBJECT + public: + + public slots: + void deviceStateChanged(quint32); + void slotAccessPointAdded( QDBusObjectPath ); + void slotAccessPointRemoved( QDBusObjectPath ); + void slotPropertiesChanged( QMap); + void slotSettingsRemoved(); + +Q_SIGNALS: + void pathForStateChanged(const QString &, quint32); + void pathForAccessPointAdded(const QString &, QDBusObjectPath ); + void pathForAccessPointRemoved(const QString &, QDBusObjectPath ); + void pathForPropertiesChanged(const QString &, QMap); + void pathForSettingsRemoved(const QString &); +}; +#endif + +QTM_END_NAMESPACE + +#endif// QNMDBUSHELPERPRIVATE_H diff --git a/src/network/bearer/qnmwifiengine_unix.cpp b/src/network/bearer/qnmwifiengine_unix.cpp new file mode 100644 index 0000000..f558fa8 --- /dev/null +++ b/src/network/bearer/qnmwifiengine_unix.cpp @@ -0,0 +1,1133 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 "qnmwifiengine_unix_p.h" +#include "qnetworkconfiguration_p.h" +#include + +#include + +#include +#include +#include + +#include + + + +QTM_BEGIN_NAMESPACE +Q_GLOBAL_STATIC(QNmWifiEngine, nmWifiEngine) +typedef QList > QNmSettingsAddressMap; +QTM_END_NAMESPACE + +Q_DECLARE_METATYPE(QTM_PREPEND_NAMESPACE(QNmSettingsAddressMap)) + +QTM_BEGIN_NAMESPACE + +QNmWifiEngine::QNmWifiEngine(QObject *parent) +: QNetworkSessionEngine(parent) +{ + iface = new QNetworkManagerInterface(); + if(!iface->isValid()) { + return; + } + iface->setConnections(); + connect(iface,SIGNAL(deviceAdded(QDBusObjectPath)), + this,SLOT(addDevice(QDBusObjectPath))); + connect(iface,SIGNAL(deviceRemoved(QDBusObjectPath)), + this,SLOT(removeDevice(QDBusObjectPath))); + + QList list = iface->getDevices(); + + foreach(QDBusObjectPath path, list) { + addDevice(path); + } + + QStringList connectionServices; + connectionServices << NM_DBUS_SERVICE_SYSTEM_SETTINGS; + connectionServices << NM_DBUS_SERVICE_USER_SETTINGS; + foreach (QString service, connectionServices) { + QNetworkManagerSettings *settingsiface; + settingsiface = new QNetworkManagerSettings(service); + settingsiface->setConnections(); + connect(settingsiface,SIGNAL(newConnection(QDBusObjectPath)), + this,(SLOT(newConnection(QDBusObjectPath)))); + } + + updated = false; +} + +QNmWifiEngine::~QNmWifiEngine() +{ +} + +QString QNmWifiEngine::getNameForConfiguration(QNetworkManagerInterfaceDevice *devIface) +{ + QString newname; + if (devIface->state() == NM_DEVICE_STATE_ACTIVATED) { + QString path = devIface->ip4config().path(); + QNetworkManagerIp4Config * ipIface; + ipIface = new QNetworkManagerIp4Config(path); + newname = ipIface->domains().join(" "); + } + //fallback to interface name + if(newname.isEmpty()) + newname = devIface->interface().name(); + return newname; +} + + +QList QNmWifiEngine::getConfigurations(bool *ok) +{ +// qWarning() << Q_FUNC_INFO << updated; + if (ok) + *ok = false; + + if(!updated) { + foundConfigurations.clear(); + if(knownSsids.isEmpty()) + getKnownSsids(); // list of ssids that have user configurations. + + scanForAccessPoints(); + getActiveConnectionsPaths(); + knownConnections(); + + accessPointConnections(); + +// findConnections(); + //add access points + updated = true; + } + return foundConfigurations; +} + +void QNmWifiEngine::findConnections() +{ + QList list = iface->getDevices(); + + foreach(QDBusObjectPath path, list) { + QNetworkManagerInterfaceDevice *devIface = new QNetworkManagerInterfaceDevice(path.path()); + + //// eth + switch (devIface->deviceType()) { +// qWarning() << devIface->connectionInterface()->path(); + + case DEVICE_TYPE_802_3_ETHERNET: + { + QString ident; + QNetworkManagerInterfaceDeviceWired *devWiredIface; + devWiredIface = new QNetworkManagerInterfaceDeviceWired(devIface->connectionInterface()->path()); + + ident = devWiredIface->hwAddress(); + + QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); + cpPriv->name = getNameForConfiguration(devIface); + cpPriv->isValid = true; + cpPriv->id = ident; + cpPriv->internet = devWiredIface->carrier(); + + cpPriv->serviceInterface = devIface->interface(); + cpPriv->type = QNetworkConfiguration::InternetAccessPoint; + switch (devIface->state()) { + case NM_DEVICE_STATE_UNKNOWN: + case NM_DEVICE_STATE_UNMANAGED: + case NM_DEVICE_STATE_FAILED: + cpPriv->state = (cpPriv->state | QNetworkConfiguration::Undefined); + break; + case NM_DEVICE_STATE_UNAVAILABLE: + cpPriv->state = (cpPriv->state | QNetworkConfiguration::Defined); + break; + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + case NM_DEVICE_STATE_NEED_AUTH: + case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_DISCONNECTED: + { + cpPriv->state = ( cpPriv->state | QNetworkConfiguration::Discovered + | QNetworkConfiguration::Defined); + } + break; + case NM_DEVICE_STATE_ACTIVATED: + cpPriv->state = (cpPriv->state | QNetworkConfiguration::Active ); + break; + default: + cpPriv->state = (cpPriv->state | QNetworkConfiguration::Undefined); + break; + }; + cpPriv->purpose = QNetworkConfiguration::PublicPurpose; + foundConfigurations.append(cpPriv); + configurationInterface[cpPriv->id] = cpPriv->serviceInterface.name(); + } + break; + case DEVICE_TYPE_802_11_WIRELESS: + { +// QNetworkManagerInterfaceDeviceWireless *devWirelessIface; +// devWirelessIface = new QNetworkManagerInterfaceDeviceWireless(devIface->connectionInterface()->path()); +// +// //// connections +// QStringList connectionServices; +// connectionServices << NM_DBUS_SERVICE_SYSTEM_SETTINGS; +// connectionServices << NM_DBUS_SERVICE_USER_SETTINGS; +// +// QString connPath; +// +// foreach (QString service, connectionServices) { +// QString ident; +// QNetworkManagerSettings *settingsiface; +// settingsiface = new QNetworkManagerSettings(service); +// QList list = settingsiface->listConnections(); +// +// foreach(QDBusObjectPath path, list) { //for each connection path +//qWarning() << path.path(); +// ident = path.path(); +// bool addIt = false; +// QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); +// cpPriv->isValid = true; +// cpPriv->id = ident; +// cpPriv->internet = true; +// +// cpPriv->type = QNetworkConfiguration::InternetAccessPoint; +// cpPriv->state = ( cpPriv->state | QNetworkConfiguration::Discovered +// | QNetworkConfiguration::Defined); +// cpPriv->purpose = QNetworkConfiguration::PrivatePurpose; +// +// QNetworkManagerSettingsConnection *sysIface; +// sysIface = new QNetworkManagerSettingsConnection(service, path.path()); +// cpPriv->name = sysIface->getId();//ii.value().toString(); +//qWarning() << cpPriv->name; +// if(sysIface->getType() == DEVICE_TYPE_802_3_ETHERNET/*type == "802-3-ethernet"*/ +// && devIface->deviceType() == DEVICE_TYPE_802_3_ETHERNET) { +// cpPriv->serviceInterface = devIface->interface(); +// addIt = true; +// } else if(sysIface->getType() == DEVICE_TYPE_802_11_WIRELESS/*type == "802-11-wireless"*/ +// && devIface->deviceType() == DEVICE_TYPE_802_11_WIRELESS) { +// cpPriv->serviceInterface = devIface->interface(); +// addIt = true; +// // get the wifi interface state first.. do we need this? +// // QString activeAPPath = devWirelessIface->activeAccessPoint().path(); +// } +// +// //#if 0 +// foreach(QString conpath, activeConnectionPaths) { +// QNetworkManagerConnectionActive *aConn; +// aConn = new QNetworkManagerConnectionActive(conpath); +// // in case of accesspoint, specificObject will hold the accessPOintObjectPath +// // qWarning() << aConn->connection().path() << aConn->specificObject().path() << aConn->devices().count(); +// if( aConn->connection().path() == ident) { +// +// QList devs = aConn->devices(); +// foreach(QDBusObjectPath device, devs) { +// QNetworkManagerInterfaceDevice *ifaceDevice; +// ifaceDevice = new QNetworkManagerInterfaceDevice(device.path()); +// cpPriv->serviceInterface = ifaceDevice->interface(); +// cpPriv->state = getStateFlag(ifaceDevice->state()); +// //cpPriv->accessPoint = aConn->specificObject().path(); +// +// break; +// } +// } +// } +// //#endif +// // } //end while connection +// if(addIt) { +// foundConfigurations.append(cpPriv); +// configurationInterface[cpPriv->id] = cpPriv->serviceInterface.name(); +// } +// } +// } //end each connection service +// +// // ////////////// AccessPoints +//// QList apList = devWirelessIface->getAccessPoints(); +////// qWarning() << apList.count(); +//// foreach(QDBusObjectPath path, apList) { +//// QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); +//// cpPriv = addAccessPoint( devIface->connectionInterface()->path(), path); +//// if(cpPriv->isValid) { +//// foundConfigurations.append(cpPriv); +//// } +//// } + } // end DEVICE_TYPE_802_11_WIRELESS + break; + }; + } //end foreach device +} + +void QNmWifiEngine::knownConnections() +{ +// qWarning() << Q_FUNC_INFO; + //// connections + QStringList connectionServices; + connectionServices << NM_DBUS_SERVICE_SYSTEM_SETTINGS; + connectionServices << NM_DBUS_SERVICE_USER_SETTINGS; + + QString connPath; + + foreach (QString service, connectionServices) { + QString ident; + QNetworkManagerSettings *settingsiface; + settingsiface = new QNetworkManagerSettings(service); + QList list = settingsiface->listConnections(); + +// qWarning() <setConnections(); + connect(sysIface, SIGNAL(removed(QString)), + this,SLOT(settingsConnectionRemoved(QString))); + + cpPriv->name = sysIface->getId(); + cpPriv->isValid = true; + cpPriv->id = sysIface->getUuid(); +// cpPriv->id = ident; + cpPriv->internet = true; + cpPriv->type = QNetworkConfiguration::InternetAccessPoint; +//qWarning() << cpPriv->name; + cpPriv->state = getStateForId(cpPriv->id); + + cpPriv->purpose = QNetworkConfiguration::PrivatePurpose; + + if(sysIface->getType() == DEVICE_TYPE_802_3_ETHERNET) { + QString mac = sysIface->getMacAddress(); + if(!mac.length() > 2) { + qWarning() <<"XXXXXXXXXXXXXXXXXXXXXXXXX" << mac << "type ethernet"; + QString devPath; + devPath = deviceConnectionPath(mac); + + // qWarning() << Q_FUNC_INFO << devPath; + QNetworkManagerInterfaceDevice *devIface; + devIface = new QNetworkManagerInterfaceDevice(devPath); + cpPriv->serviceInterface = devIface->interface(); + QNetworkManagerInterfaceDeviceWired *devWiredIface; + devWiredIface = new QNetworkManagerInterfaceDeviceWired(devIface->connectionInterface()->path()); + cpPriv->internet = devWiredIface->carrier(); + + // use this mac addy + } else { + cpPriv->serviceInterface = getBestInterface( DEVICE_TYPE_802_3_ETHERNET, cpPriv->id); + } + + cpPriv->internet = true;//sysIface->isAutoConnect(); + + addIt = true; + } else if(sysIface->getType() == DEVICE_TYPE_802_11_WIRELESS) { + QString mac = sysIface->getMacAddress();; + if(!mac.length() > 2) { + qWarning() <<"XXXXXXXXXXXXXXXXXXXXXXXXX" << mac << "type wireless"; + QString devPath; + devPath = deviceConnectionPath(mac); +// qWarning() << Q_FUNC_INFO << devPath; + + QNetworkManagerInterfaceDevice *devIface; + devIface = new QNetworkManagerInterfaceDevice(devPath); + cpPriv->serviceInterface = devIface->interface(); + // use this mac addy + } else { + cpPriv->serviceInterface = getBestInterface( DEVICE_TYPE_802_11_WIRELESS, cpPriv->id); + } + // cpPriv->serviceInterface = devIface->interface(); + addIt = true; + // get the wifi interface state first.. do we need this? + // QString activeAPPath = devWirelessIface->activeAccessPoint().path(); + } + if(addIt) { + foundConfigurations.append(cpPriv); + configurationInterface[cpPriv->id] = cpPriv->serviceInterface.name(); + } + } //end each connection service + } +} + +void QNmWifiEngine::accessPointConnections() +{ + //qWarning() << Q_FUNC_INFO; + QList list = iface->getDevices(); + foreach(QDBusObjectPath path, list) { + QNetworkManagerInterfaceDevice *devIface; + devIface = new QNetworkManagerInterfaceDevice(path.path()); + if(devIface->deviceType() == DEVICE_TYPE_802_11_WIRELESS) { + QList apList = availableAccessPoints.uniqueKeys(); + + QList::const_iterator i; + for (i = apList.constBegin(); i != apList.constEnd(); ++i) { + QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); + cpPriv = addAccessPoint( devIface->connectionInterface()->path(), availableAccessPoints[*i]); + if(cpPriv->isValid) { + foundConfigurations.append(cpPriv); + // qWarning() << "adding" << cpPriv->name << "to things"; + configurationInterface[cpPriv->id] = cpPriv->serviceInterface.name(); + } + } + } + } +} + +QString QNmWifiEngine::getInterfaceFromId(const QString &id) +{ + return configurationInterface.value(id); +} + +bool QNmWifiEngine::hasIdentifier(const QString &id) +{ + if (configurationInterface.contains(id)) + return true; + foreach (QNetworkConfigurationPrivate *cpPriv, getConfigurations()) { + if (cpPriv->id == id) + return true; + } + return false; +} + +QString QNmWifiEngine::bearerName(const QString &id) +{ + QString interface = getInterfaceFromId(id); + + QList list = iface->getDevices(); + foreach(QDBusObjectPath path, list) { + QNetworkManagerInterfaceDevice *devIface; + devIface = new QNetworkManagerInterfaceDevice(path.path()); + if(interface == devIface->interface().name()) { + switch(devIface->deviceType()) { + case DEVICE_TYPE_802_3_ETHERNET/*NM_DEVICE_TYPE_ETHERNET*/: + return QLatin1String("Ethernet"); + break; + case DEVICE_TYPE_802_11_WIRELESS/*NM_DEVICE_TYPE_WIFI*/: + return QLatin1String("WLAN"); + break; + case DEVICE_TYPE_GSM/*NM_DEVICE_TYPE_GSM*/: + return QLatin1String("2G"); + break; + case DEVICE_TYPE_CDMA/*NM_DEVICE_TYPE_CDMA*/: + return QLatin1String("CDMA2000"); + break; + default: + break; + }; + } + } + return QString(); +} + +void QNmWifiEngine::connectToId(const QString &id) +{ +// qWarning() <<"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" << __FUNCTION__ << id; + activatingConnectionPath = id; + QStringList connectionSettings = getConnectionPathForId(id); + if(connectionSettings.isEmpty()) { + emit connectionError(id, OperationNotSupported); + return; + } + + QDBusObjectPath connectionPath(connectionSettings.at(1)); + QString interface = getInterfaceFromId(id); + + interface = QNetworkInterface::interfaceFromName(interface).hardwareAddress().toLower(); + QString devPath; + devPath = deviceConnectionPath(interface); + QDBusObjectPath devicePath(devPath); + + iface = new QNetworkManagerInterface(); + iface->activateConnection( + connectionSettings.at(0), + connectionPath, + devicePath, + connectionPath); + + connect(iface, SIGNAL(activationFinished(QDBusPendingCallWatcher*)), + this, SLOT(slotActivationFinished(QDBusPendingCallWatcher*))); +} + +void QNmWifiEngine::disconnectFromId(const QString &id) +{ + QString activeConnectionPath = getActiveConnectionPath(id); + //qWarning() <<"XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" << __FUNCTION__ << id << activeConnectionPath ; + + if (!activeConnectionPath.isEmpty()) { + QNetworkManagerConnectionActive *activeCon; + activeCon = new QNetworkManagerConnectionActive(activeConnectionPath); + QNetworkManagerSettingsConnection *settingsCon; + settingsCon = new QNetworkManagerSettingsConnection(activeCon->serviceName(), activeCon->connection().path()); + + if(settingsCon->isAutoConnect()) { +// qWarning() << id << "is autoconnect"; + emit connectionError(id, OperationNotSupported); + //unsupported + } else { +// qWarning() <deactivateConnection(dbpath); + activatingConnectionPath = ""; + } + } +} + +void QNmWifiEngine::requestUpdate() +{ + updated = false; + knownSsids.clear(); + availableAccessPoints.clear(); + emitConfigurationsChanged(); +} + +QNmWifiEngine *QNmWifiEngine::instance() +{ + QDBusConnection dbusConnection = QDBusConnection::systemBus(); + if (dbusConnection.isConnected()) { + QDBusConnectionInterface *dbiface = dbusConnection.interface(); + QDBusReply reply = dbiface->isServiceRegistered("org.freedesktop.NetworkManager"); + if (reply.isValid() && reply.value()) + return nmWifiEngine(); + } + + return 0; +} + +void QNmWifiEngine::getKnownSsids() +{ + QStringList connectionServices; + connectionServices << NM_DBUS_SERVICE_SYSTEM_SETTINGS; + connectionServices << NM_DBUS_SERVICE_USER_SETTINGS; +//qWarning() << Q_FUNC_INFO; + foreach (QString service, connectionServices) { + QNetworkManagerSettings *settingsiface; + settingsiface = new QNetworkManagerSettings(service); + QList list = settingsiface->listConnections(); + foreach(QDBusObjectPath path, list) { + QNetworkManagerSettingsConnection *sysIface; + sysIface = new QNetworkManagerSettingsConnection(service, path.path()); +// qWarning() << sysIface->getSsid(); + knownSsids << sysIface->getSsid(); + } + } +} + +void QNmWifiEngine::getActiveConnectionsPaths() +{ +// qWarning() << Q_FUNC_INFO; + QNetworkManagerInterface *dbIface; + activeConnectionPaths.clear(); + dbIface = new QNetworkManagerInterface; + QList connections = dbIface->activeConnections(); + + foreach(QDBusObjectPath conpath, connections) { + activeConnectionPaths << conpath.path(); +// qWarning() << __FUNCTION__ << conpath.path() << activeConnectionPaths.count(); + + QNetworkManagerConnectionActive *activeConn; + activeConn = new QNetworkManagerConnectionActive(conpath.path()); + +// qWarning() << activeConn->connection().path() /*<< activeConn->specificObject().path() */<< activeConn->devices()[0].path(); + + } +} + +QNetworkConfigurationPrivate * QNmWifiEngine::addAccessPoint( const QString &iPath, QDBusObjectPath path) +{ //foreach accessPoint + //qWarning() << Q_FUNC_INFO << iPath << path.path(); + + QNetworkManagerInterfaceDevice *devIface; + devIface = new QNetworkManagerInterfaceDevice(iPath); + QNetworkManagerInterfaceDeviceWireless *devWirelessIface; + devWirelessIface = new QNetworkManagerInterfaceDeviceWireless(iPath); + + QString activeAPPath = devWirelessIface->activeAccessPoint().path(); + + QNetworkManagerInterfaceAccessPoint *accessPointIface; + accessPointIface = new QNetworkManagerInterfaceAccessPoint(path.path()); + + QString ident = accessPointIface->connectionInterface()->path(); + quint32 nmState = devIface->state(); + + QString ssid = accessPointIface->ssid(); + QString hwAddy = accessPointIface->hwAddress(); + QString sInterface = devIface->interface().name(); + + QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); + bool addIt = true; + //qWarning() << availableAccessPoints.count() << ssid; + +// if(availableAccessPoints.contains(ssid)) { +// addIt = false; +// +// } +// foreach (QNetworkConfigurationPrivate *cpPriv, foundConfigurations) { +// if (cpPriv->name == ssid) { //weed out duplicate ssid's ?? +// addIt = false; +// break; +// } +// } + + if(addIt) { + + cpPriv->name = ssid; + cpPriv->isValid = true; + cpPriv->id = ident; + cpPriv->internet = true; + cpPriv->type = QNetworkConfiguration::InternetAccessPoint; + cpPriv->serviceInterface = devIface->interface(); + + //qWarning() <<__FUNCTION__ << ssid; + + cpPriv->state = getAPState(nmState, knownSsids.contains(cpPriv->name)); + + if(activeAPPath == accessPointIface->connectionInterface()->path()) { + cpPriv->state = ( cpPriv->state | QNetworkConfiguration::Active); + } + if(accessPointIface->flags() == NM_802_11_AP_FLAGS_PRIVACY) + cpPriv->purpose = QNetworkConfiguration::PrivatePurpose; + else + cpPriv->purpose = QNetworkConfiguration::PublicPurpose; + return cpPriv; + } else { + cpPriv->isValid = false; + } + return cpPriv; +} + + + QNetworkConfiguration::StateFlags QNmWifiEngine::getAPState(qint32 nmState, bool isKnown) +{ + QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined; +//qWarning() << nmState << knownSsids; + // this is the state of the wifi device interface + if(isKnown) + state = ( QNetworkConfiguration::Defined); + + switch(nmState) { //device interface state, not AP state + case NM_DEVICE_STATE_UNKNOWN: + case NM_DEVICE_STATE_UNMANAGED: + case NM_DEVICE_STATE_UNAVAILABLE: + state = (QNetworkConfiguration::Undefined); + break; + case NM_DEVICE_STATE_DISCONNECTED: + { + if(isKnown) + state = ( state | QNetworkConfiguration::Discovered); + } + break; + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + case NM_DEVICE_STATE_NEED_AUTH: + case NM_DEVICE_STATE_IP_CONFIG: + if(isKnown) + state = ( state | QNetworkConfiguration::Discovered); + break; + case NM_DEVICE_STATE_ACTIVATED: + { + if(isKnown) + state = ( state | QNetworkConfiguration::Discovered); + } + break; + }; + return state; +} + +QString QNmWifiEngine::getActiveConnectionPath(const QString &id) +{ + //qWarning() << Q_FUNC_INFO << id; + QStringList connectionSettings = getConnectionPathForId(id); + //qWarning() << Q_FUNC_INFO << id << connectionSettings.count(); + QNetworkManagerInterface * ifaceD; + ifaceD = new QNetworkManagerInterface(); + QList connections = ifaceD->activeConnections(); + foreach(QDBusObjectPath path, connections) { + QNetworkManagerConnectionActive *conDetailsD; + conDetailsD = new QNetworkManagerConnectionActive( path.path()); + if(conDetailsD->connection().path() == connectionSettings.at(1) + && conDetailsD->serviceName() == connectionSettings.at(0)) + return path.path(); + } + return QString(); +} + + QNetworkConfiguration::StateFlags QNmWifiEngine::getStateFlag(quint32 nmstate) + { +// qWarning() << Q_FUNC_INFO << nmstate; + QNetworkConfiguration::StateFlags flag; + switch (nmstate) { + case NM_DEVICE_STATE_UNKNOWN: + case NM_DEVICE_STATE_FAILED: + case NM_DEVICE_STATE_UNMANAGED: + flag = (QNetworkConfiguration::Undefined); + break; + case NM_DEVICE_STATE_PREPARE: + case NM_DEVICE_STATE_CONFIG: + case NM_DEVICE_STATE_NEED_AUTH: + case NM_DEVICE_STATE_IP_CONFIG: + case NM_DEVICE_STATE_UNAVAILABLE: + flag = (QNetworkConfiguration::Defined); + break; + case NM_DEVICE_STATE_DISCONNECTED: + flag = ( flag | QNetworkConfiguration::Discovered ); + break; + case NM_DEVICE_STATE_ACTIVATED: + { + flag = ( flag | QNetworkConfiguration::Discovered + | QNetworkConfiguration::Active ); + } + break; + default: + flag = ( QNetworkConfiguration::Defined); + break; + }; + return flag; + } + +void QNmWifiEngine::updateDeviceInterfaceState(const QString &/*path*/, quint32 nmState) +{ +// qWarning() << Q_FUNC_INFO << path << nmState; + + if(nmState == NM_DEVICE_STATE_ACTIVATED + || nmState == NM_DEVICE_STATE_DISCONNECTED + || nmState == NM_DEVICE_STATE_UNAVAILABLE + || nmState == NM_DEVICE_STATE_FAILED) { + +/* InterfaceLookupError = 0, + ConnectError, + OperationNotSupported, + DisconnectionError, +*/ +// qWarning() << Q_FUNC_INFO << ident; + QNetworkConfiguration::StateFlags state = (QNetworkConfiguration::Defined); + switch (nmState) { + case NM_DEVICE_STATE_UNKNOWN: + case NM_DEVICE_STATE_FAILED: + state = (QNetworkConfiguration::Undefined); + emit connectionError(activatingConnectionPath, ConnectError); + requestUpdate(); +// qWarning() << Q_FUNC_INFO; + break; + case NM_DEVICE_STATE_UNAVAILABLE: + state = (QNetworkConfiguration::Defined); +// emit connectionError(activatingConnectionPath, ConnectError); + requestUpdate(); + break; + case NM_DEVICE_STATE_DISCONNECTED: + state = ( state | QNetworkConfiguration::Discovered ); + requestUpdate(); + break; + case NM_DEVICE_STATE_ACTIVATED: + { + state = ( state | QNetworkConfiguration::Discovered + | QNetworkConfiguration::Active ); + requestUpdate(); + } + break; + default: + state = ( QNetworkConfiguration::Defined); + break; + }; + } +} + +void QNmWifiEngine::addDevice(QDBusObjectPath path) +{ + //qWarning() << Q_FUNC_INFO << path.path(); + QNetworkManagerInterfaceDevice *devIface = new QNetworkManagerInterfaceDevice(path.path()); + devIface->setConnections(); + connect(devIface,SIGNAL(stateChanged(const QString &, quint32)), + this, SLOT(updateDeviceInterfaceState(const QString&, quint32))); + + if(!devicePaths.contains(path.path())) + devicePaths << path.path(); + + switch(devIface->deviceType()) { + case DEVICE_TYPE_802_3_ETHERNET: + { + QNetworkManagerInterfaceDeviceWired * devWiredIface; + devWiredIface = new QNetworkManagerInterfaceDeviceWired(devIface->connectionInterface()->path()); + devWiredIface->setConnections(); + connect(devWiredIface, SIGNAL(propertiesChanged(const QString &,QMap)), + this,SLOT(cmpPropertiesChanged( const QString &, QMap))); + requestUpdate(); + } + break; + case DEVICE_TYPE_802_11_WIRELESS: + { + QNetworkManagerInterfaceDeviceWireless *devWirelessIface; + devWirelessIface = new QNetworkManagerInterfaceDeviceWireless(devIface->connectionInterface()->path()); + devWirelessIface->setConnections(); + + connect(devWirelessIface, SIGNAL(propertiesChanged(const QString &,QMap)), + this,SLOT(cmpPropertiesChanged( const QString &, QMap))); + + connect(devWirelessIface, SIGNAL(accessPointAdded(const QString &,QDBusObjectPath)), + this,SLOT(accessPointAdded(const QString &,QDBusObjectPath))); + + connect(devWirelessIface, SIGNAL(accessPointRemoved(const QString &,QDBusObjectPath)), + this,SLOT(accessPointRemoved(const QString &,QDBusObjectPath))); + requestUpdate(); + + } + break; + default: + break; + }; +} + +void QNmWifiEngine::removeDevice(QDBusObjectPath /*path*/) +{ +// qWarning() << Q_FUNC_INFO << path.path(); +// disconnect(devIface,SIGNAL(stateChanged(const QString &, quint32)), +// this, SLOT(updateDeviceInterfaceState(const QString&, quint32))); +// +// if(devIface->deviceType() == DEVICE_TYPE_802_11_WIRELESS) { +// // devWirelessIface = new QNetworkManagerInterfaceDeviceWireless(devIface->connectionInterface()->path()); +// // devWirelessIface->setConnections(); +// +// disconnect(devWirelessIface, SIGNAL(propertiesChanged(const QString &,QMap)), +// this,SIGNAL(cmpPropertiesChanged( const QString &, QMap))); +// +// disconnect(devWirelessIface, SIGNAL(accessPointAdded(const QString &,QDBusObjectPath)), +// this,SIGNAL(accessPointAdded(const QString &,QDBusObjectPath))); +// +// disconnect(devWirelessIface, SIGNAL(accessPointRemoved(const QString &,QDBusObjectPath)), +// this,SIGNAL(accessPointRemoved(const QString &,QDBusObjectPath))); +// +// } +} +void QNmWifiEngine::cmpPropertiesChanged(const QString &path, QMap map) +{ + QMapIterator i(map); + while (i.hasNext()) { + i.next(); +// qWarning() << Q_FUNC_INFO << path << i.key() << i.value().toUInt(); + if( i.key() == "State") { //only applies to device interfaces + updateDeviceInterfaceState(path, i.value().toUInt()); + } + if( i.key() == "ActiveAccessPoint") { + } + if( i.key() == "Carrier") { //someone got plugged in + // requestUpdate(); + } + } +} + +void QNmWifiEngine::accessPointRemoved( const QString &aPath, QDBusObjectPath /*oPath*/) +{ + //qWarning() << Q_FUNC_INFO << aPath << oPath.path(); + + if(aPath.contains("devices")) { + requestUpdate(); + } +} + +void QNmWifiEngine::accessPointAdded( const QString &aPath, QDBusObjectPath oPath) +{ + //qWarning() << Q_FUNC_INFO << aPath << oPath.path(); + + QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate(); + cpPriv = addAccessPoint( aPath, oPath); + requestUpdate(); +} + +QNetworkConfiguration::StateFlags QNmWifiEngine::getStateForId(const QString &id) +{ + //qWarning() << Q_FUNC_INFO << id; + bool isAvailable = false; + QStringList conPath = getConnectionPathForId(id); + QString aconpath = getActiveConnectionPath(id); + + //qWarning() << Q_FUNC_INFO << id << aconpath; + + if(!aconpath.isEmpty()) { + //active connection + QNetworkManagerConnectionActive *aConn; + aConn = new QNetworkManagerConnectionActive(aconpath); + + QList devs = aConn->devices(); + + foreach(QDBusObjectPath dev, devs) { + //qWarning() << "foreach" << dev.path(); + QNetworkManagerInterfaceDevice *ifaceDevice; + ifaceDevice = new QNetworkManagerInterfaceDevice(dev.path()); + + if(ifaceDevice->deviceType() == DEVICE_TYPE_802_3_ETHERNET) { + + if(isAddressOfConnection(id, ifaceDevice->ip4Address())) { + // this is it! + return getStateFlag(ifaceDevice->state()); + } else { + continue; + } + + if(ifaceDevice->state() == NM_DEVICE_STATE_UNAVAILABLE || + ifaceDevice->state() == NM_DEVICE_STATE_DISCONNECTED) { + isAvailable = true; + + QNetworkManagerInterfaceDeviceWired *devWiredIface; + devWiredIface = new QNetworkManagerInterfaceDeviceWired(ifaceDevice->connectionInterface()->path()); + if(!devWiredIface->carrier()) + return QNetworkConfiguration::Defined; + } //end eth + } else if(ifaceDevice->deviceType() == DEVICE_TYPE_802_11_WIRELESS) { + qWarning() << "FIXME!!!!!!!!!!!!!!!!!"; + } + + return getStateFlag(ifaceDevice->state()); + } + } else { + // not active + //qWarning() << Q_FUNC_INFO << "Not active"; + QNetworkManagerSettingsConnection *sysIface; + sysIface = new QNetworkManagerSettingsConnection(conPath.at(0),conPath.at(1)); + if(sysIface->isValid()) { + if(sysIface->getType() == DEVICE_TYPE_802_11_WIRELESS) { + QString ssid = sysIface->getSsid(); + bool ok = false; + + if(knownSsids.contains(ssid, Qt::CaseSensitive)) { + foreach(QString onessid, knownSsids) { + // qWarning() << ssid << onessid; + if(onessid == ssid && availableAccessPoints.contains(ssid)) { + // qWarning() < devices = aConn->devices(); + foreach(QDBusObjectPath device, devices) { + QNetworkManagerInterfaceDevice *ifaceDevice; + ifaceDevice = new QNetworkManagerInterfaceDevice(device.path()); + if(ifaceDevice->ip4Address() == ipaddress) { + return true; + } + } + return false; +} + +QNetworkInterface QNmWifiEngine::getBestInterface( quint32 type, const QString &id) +{ + // check active connections first. + QStringList conIdPath = getConnectionPathForId(id); +// qWarning() << Q_FUNC_INFO << id << conIdPath; + + QNetworkInterface interface; + foreach(QString conpath, activeConnectionPaths) { + QNetworkManagerConnectionActive *aConn; + aConn = new QNetworkManagerConnectionActive(conpath); + + if(aConn->connection().path() == conIdPath.at(1) + && aConn->serviceName() == conIdPath.at(0)) { + + QList devs = aConn->devices(); + QNetworkManagerInterfaceDevice *ifaceDevice; + ifaceDevice = new QNetworkManagerInterfaceDevice(devs[0].path()); //just take the first one + interface = ifaceDevice->interface(); + return interface; + } + } + +//try guessing + QList list = iface->getDevices(); + foreach(QDBusObjectPath path, list) { + QNetworkManagerInterfaceDevice *devIface = new QNetworkManagerInterfaceDevice(path.path()); + if(devIface->deviceType() == type /*&& devIface->managed()*/) { + interface = devIface->interface(); + if(devIface->state() == NM_STATE_DISCONNECTED) { + return interface; + } + } + } + return interface; +} + +quint64 QNmWifiEngine::receivedDataForId(const QString &id) const +{ + if(configurationInterface.count() > 1) + return 0; + quint64 result = 0; + + QString devFile; + devFile = configurationInterface.value(id); + QFile rx("/sys/class/net/"+devFile+"/statistics/rx_bytes"); + if(rx.exists() && rx.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&rx); + in >> result; + rx.close(); + } + return result; +} + +quint64 QNmWifiEngine::sentDataForId(const QString &id) const +{ + if(configurationInterface.count() > 1) + return 0; + quint64 result = 0; + QString devFile; + devFile = configurationInterface.value(id); + + QFile tx("/sys/class/net/"+devFile+"/statistics/tx_bytes"); + if(tx.exists() && tx.open(QIODevice::ReadOnly | QIODevice::Text)) { + QTextStream in(&tx); + in >> result; + tx.close(); + } + return result; +} + +void QNmWifiEngine::newConnection(QDBusObjectPath /*path*/) +{ + //qWarning() << Q_FUNC_INFO; + requestUpdate(); +} + +void QNmWifiEngine::settingsConnectionRemoved(const QString &/*path*/) +{ + //qWarning() << Q_FUNC_INFO; + requestUpdate(); +} + +void QNmWifiEngine::slotActivationFinished(QDBusPendingCallWatcher *openCall) +{ + QDBusPendingReply reply = *openCall; + if (reply.isError()) { + qWarning() <<"Error" << reply.error().name() << reply.error().message() + < list = iface->getDevices(); + + foreach(QDBusObjectPath path, list) { + QNetworkManagerInterfaceDevice *devIface; + devIface = new QNetworkManagerInterfaceDevice(path.path()); + + if(devIface->deviceType() == DEVICE_TYPE_802_11_WIRELESS) { + +// qWarning() << devIface->connectionInterface()->path(); + + QNetworkManagerInterfaceDeviceWireless *devWirelessIface; + devWirelessIface = new QNetworkManagerInterfaceDeviceWireless(devIface->connectionInterface()->path()); + ////////////// AccessPoints + QList apList = devWirelessIface->getAccessPoints(); + + foreach(QDBusObjectPath path, apList) { + QNetworkManagerInterfaceAccessPoint *accessPointIface; + accessPointIface = new QNetworkManagerInterfaceAccessPoint(path.path()); + QString ssid = accessPointIface->ssid(); + availableAccessPoints.insert(ssid, path); + } + } + } +} + +QString QNmWifiEngine::deviceConnectionPath(const QString &mac) +{ +// qWarning() << __FUNCTION__ << mac; + QString newMac = mac; + newMac = newMac.replace(":","_").toLower(); + //device object path might not contain just mac address + //might contain extra numbers on the end. thanks HAL + foreach(QString device, devicePaths) { + if(device.contains(newMac)) { + newMac = device; + break; + } + } + return newMac; +} + +QStringList QNmWifiEngine::getConnectionPathForId(const QString &uuid) +{ + QStringList connectionServices; + connectionServices << NM_DBUS_SERVICE_SYSTEM_SETTINGS; + connectionServices << NM_DBUS_SERVICE_USER_SETTINGS; +//qWarning() << Q_FUNC_INFO; + foreach (QString service, connectionServices) { + QNetworkManagerSettings *settingsiface; + settingsiface = new QNetworkManagerSettings(service); + QList list = settingsiface->listConnections(); + foreach(QDBusObjectPath path, list) { + QNetworkManagerSettingsConnection *sysIface; + sysIface = new QNetworkManagerSettingsConnection(service, path.path()); +// qWarning() << uuid << sysIface->getUuid(); + if(sysIface->getUuid() == uuid) { +// qWarning() <<__FUNCTION__ << service << sysIface->getId() << sysIface->connectionInterface()->path(); + return QStringList() << service << sysIface->connectionInterface()->path(); + } + } + } + return QStringList(); +} + +#include "moc_qnmwifiengine_unix_p.cpp" + +QTM_END_NAMESPACE + diff --git a/src/network/bearer/qnmwifiengine_unix_p.h b/src/network/bearer/qnmwifiengine_unix_p.h new file mode 100644 index 0000000..1287800 --- /dev/null +++ b/src/network/bearer/qnmwifiengine_unix_p.h @@ -0,0 +1,164 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 QNMWIFIENGINE_P_H +#define QNMWIFIENGINE_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 + +#include +#include +#include +#include + +#include "qnetworksessionengine_p.h" +#include +#include +#include + + + +QTM_BEGIN_NAMESPACE + +class QNetworkConfigurationPrivate; + +class QNmWifiEngine : public QNetworkSessionEngine +{ + Q_OBJECT + +public: + QNmWifiEngine(QObject *parent = 0); + ~QNmWifiEngine(); + + QList getConfigurations(bool *ok = 0); + QString getInterfaceFromId(const QString &id); + bool hasIdentifier(const QString &id); + + QString bearerName(const QString &id); + + void connectToId(const QString &id); + void disconnectFromId(const QString &id); + + void requestUpdate(); + + static QNmWifiEngine *instance(); + + QStringList knownSsids; + inline void emitConfigurationsChanged() { emit configurationsChanged(); } + QNetworkConfigurationPrivate * addAccessPoint(const QString &, QDBusObjectPath ); + + QStringList getConnectionPathForId(const QString &uuid); + //QString getConnectionPathForId(const QString &name = QString()); + quint64 sentDataForId(const QString &id) const; + quint64 receivedDataForId(const QString &id) const; + +private: + bool updated; + QString activatingConnectionPath; + QStringList activeConnectionPaths; + + + QMap availableAccessPoints; + void scanForAccessPoints(); + + QStringList devicePaths; + + void getActiveConnectionsPaths(); + void getKnownSsids(); + void accessPointConnections(); + void knownConnections(); + void findConnections(); + QString deviceConnectionPath(const QString &mac); + + QList foundConfigurations; + // QHash > allConfigurations; + + QNetworkManagerInterface *iface; + + QNetworkConfiguration::StateFlags getAPState(qint32 vState, bool isKnown); + QNetworkConfiguration::StateFlags getStateFlag(quint32 nmstate); + + QString getActiveConnectionPath(const QString &identifier); + QString getNameForConfiguration(QNetworkManagerInterfaceDevice *devIface); + + QNetworkConfiguration::StateFlags getStateForId(const QString &id); + + QNetworkInterface getBestInterface(quint32 type, const QString &conPath); + + QMap configurationInterface; + + bool isAddressOfConnection(const QString &conPath, quint32 ipaddress); + +private slots: + void updateDeviceInterfaceState(const QString &, quint32); + void addDevice(QDBusObjectPath path); + void removeDevice(QDBusObjectPath path); + +Q_SIGNALS: + void configurationChanged(const QNetworkConfiguration& config); + void updateAccessPointState(const QString &, quint32); +// void slotActivationFinished(QDBusPendingCallWatcher*); + +private slots: + void accessPointAdded( const QString &aPath, QDBusObjectPath oPath); + void accessPointRemoved( const QString &aPath, QDBusObjectPath oPath); + void cmpPropertiesChanged(const QString &, QMap map); + void newConnection(QDBusObjectPath); + void settingsConnectionRemoved(const QString &); + void slotActivationFinished(QDBusPendingCallWatcher*); +}; + +QTM_END_NAMESPACE + +#endif + + diff --git a/tests/auto/qbearertestcommon.h b/tests/auto/qbearertestcommon.h new file mode 100644 index 0000000..3356bd6 --- /dev/null +++ b/tests/auto/qbearertestcommon.h @@ -0,0 +1,74 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 QBEARERTESTCOMMON_H +#define QBEARERTESTCOMMON_H + +// Will try to wait for the condition while allowing event processing +#define QTRY_VERIFY(__expr) \ + do { \ + const int __step = 50; \ + const int __timeout = 90000; \ + if (!(__expr)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeout && !(__expr); __i+=__step) { \ + QTest::qWait(__step); \ + } \ + QVERIFY(__expr); \ + } while(0) + +// Will try to wait for the condition while allowing event processing +#define QTRY_COMPARE(__expr, __expected) \ + do { \ + const int __step = 50; \ + const int __timeout = 90000; \ + if ((__expr) != (__expected)) { \ + QTest::qWait(0); \ + } \ + for (int __i = 0; __i < __timeout && ((__expr) != (__expected)); __i+=__step) { \ + QTest::qWait(__step); \ + } \ + QCOMPARE(__expr, __expected); \ + } while(0) + +#endif + diff --git a/tests/auto/qnetworkconfigmanager/qnetworkconfigmanager.pro b/tests/auto/qnetworkconfigmanager/qnetworkconfigmanager.pro new file mode 100644 index 0000000..0b2ed1a --- /dev/null +++ b/tests/auto/qnetworkconfigmanager/qnetworkconfigmanager.pro @@ -0,0 +1,15 @@ +SOURCES += tst_qnetworkconfigmanager.cpp +HEADERS += ../qbearertestcommon.h +TARGET = tst_qnetworkconfigurationmanager +CONFIG += testcase + +QT = core network + +INCLUDEPATH += ../../../src/bearer + +include(../../../common.pri) +qtAddLibrary(QtBearer) + +symbian { + TARGET.CAPABILITY = NetworkServices NetworkControl ReadUserData +} diff --git a/tests/auto/qnetworkconfigmanager/tst_qnetworkconfigmanager.cpp b/tests/auto/qnetworkconfigmanager/tst_qnetworkconfigmanager.cpp new file mode 100644 index 0000000..796677d --- /dev/null +++ b/tests/auto/qnetworkconfigmanager/tst_qnetworkconfigmanager.cpp @@ -0,0 +1,335 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 +#include "../qbearertestcommon.h" +#include "qnetworkconfiguration.h" +#include "qnetworkconfigmanager.h" + +#ifdef MAEMO +#include +#include +#endif + +QTM_USE_NAMESPACE +class tst_QNetworkConfigurationManager : public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + void init(); + void cleanup(); + +private slots: + void allConfigurations(); + void defaultConfiguration(); + void configurationFromIdentifier(); + +private: +#ifdef MAEMO + Maemo::IAPConf *iapconf; + Maemo::IAPConf *iapconf2; + Maemo::IAPConf *gprsiap; +#define MAX_IAPS 50 + Maemo::IAPConf *iaps[MAX_IAPS]; + QProcess *icd_stub; +#endif +}; + +void tst_QNetworkConfigurationManager::initTestCase() +{ +#ifdef MAEMO + iapconf = new Maemo::IAPConf("007"); + iapconf->setValue("ipv4_type", "AUTO"); + iapconf->setValue("wlan_wepkey1", "connt"); + iapconf->setValue("wlan_wepdefkey", 1); + iapconf->setValue("wlan_ssid", QByteArray("JamesBond")); + iapconf->setValue("name", "James Bond"); + iapconf->setValue("type", "WLAN_INFRA"); + + gprsiap = new Maemo::IAPConf("This-is-GPRS-IAP"); + gprsiap->setValue("ask_password", false); + gprsiap->setValue("gprs_accesspointname", "internet"); + gprsiap->setValue("gprs_password", ""); + gprsiap->setValue("gprs_username", ""); + gprsiap->setValue("ipv4_autodns", true); + gprsiap->setValue("ipv4_type", "AUTO"); + gprsiap->setValue("sim_imsi", "244070123456789"); + gprsiap->setValue("name", "MI6"); + gprsiap->setValue("type", "GPRS"); + + iapconf2 = new Maemo::IAPConf("osso.net"); + iapconf2->setValue("ipv4_type", "AUTO"); + iapconf2->setValue("wlan_wepkey1", "osso.net"); + iapconf2->setValue("wlan_wepdefkey", 1); + iapconf2->setValue("wlan_ssid", QByteArray("osso.net")); + iapconf2->setValue("name", "osso.net"); + iapconf2->setValue("type", "WLAN_INFRA"); + iapconf2->setValue("wlan_security", "WEP"); + + /* Create large number of IAPs in the gconf and see what happens */ + fflush(stdout); + printf("Creating %d IAPS: ", MAX_IAPS); + for (int i=0; isetValue("name", QString("test-iap-")+num); + iaps[i]->setValue("type", "WLAN_INFRA"); + iaps[i]->setValue("wlan_ssid", QString(QString("test-ssid-")+num).toAscii()); + iaps[i]->setValue("wlan_security", "WPA_PSK"); + iaps[i]->setValue("EAP_wpa_preshared_passphrase", QString("test-passphrase-")+num); + printf("."); + fflush(stdout); + } + printf("\n"); + fflush(stdout); + + icd_stub = new QProcess(this); + icd_stub->start("/usr/bin/icd2_stub.py"); + QTest::qWait(1000); + + // Add a known network to scan list that icd2 stub returns + QProcess dbus_send; + // 007 network + dbus_send.start("dbus-send --type=method_call --system " + "--dest=com.nokia.icd2 /com/nokia/icd2 " + "com.nokia.icd2.testing.add_available_network " + "string:'' uint32:0 string:'' " + "string:WLAN_INFRA uint32:5000011 array:byte:48,48,55"); + dbus_send.waitForFinished(); + + // osso.net network + dbus_send.start("dbus-send --type=method_call --system " + "--dest=com.nokia.icd2 /com/nokia/icd2 " + "com.nokia.icd2.testing.add_available_network " + "string:'' uint32:0 string:'' " + "string:WLAN_INFRA uint32:83886097 array:byte:111,115,115,111,46,110,101,116"); + dbus_send.waitForFinished(); +#endif +} + + +void tst_QNetworkConfigurationManager::cleanupTestCase() +{ +#ifdef MAEMO + iapconf->clear(); + delete iapconf; + iapconf2->clear(); + delete iapconf2; + gprsiap->clear(); + delete gprsiap; + + printf("Deleting %d IAPS : ", MAX_IAPS); + for (int i=0; iclear(); + delete iaps[i]; + printf("."); + fflush(stdout); + } + printf("\n"); + qDebug() << "Deleted" << MAX_IAPS << "IAPs"; + + icd_stub->terminate(); + icd_stub->waitForFinished(); +#endif +} + +void tst_QNetworkConfigurationManager::init() +{ +} + +void tst_QNetworkConfigurationManager::cleanup() +{ +} + +void printConfigurationDetails(const QNetworkConfiguration& p) +{ + qDebug() << p.name() <<": isvalid->" <"<< p.type() << + " roaming->" << p.isRoamingAvailable() << "identifier->" << p.identifier() << + " purpose->" << p.purpose() << " state->" << p.state(); +} + +void tst_QNetworkConfigurationManager::allConfigurations() +{ + QNetworkConfigurationManager manager; + QList preScanConfigs = manager.allConfigurations(); + + foreach(QNetworkConfiguration c, preScanConfigs) + { + QVERIFY2(c.type()!=QNetworkConfiguration::UserChoice, "allConfiguration must not return UserChoice configs"); + } + + QSignalSpy spy(&manager, SIGNAL(updateCompleted())); + manager.updateConfigurations(); //initiate scans + QTRY_VERIFY(spy.count() == 1); //wait for scan to complete + + QList configs = manager.allConfigurations(); + + int all = configs.count(); + qDebug() << "All configurations:" << all; + QVERIFY(all); + foreach(QNetworkConfiguration p, configs) { + QVERIFY(p.isValid()); + printConfigurationDetails(p); + QVERIFY(p.type() != QNetworkConfiguration::Invalid); + QVERIFY(p.type() != QNetworkConfiguration::UserChoice); + } + + configs = manager.allConfigurations(QNetworkConfiguration::Undefined); + int undefined = configs.count(); + QVERIFY(undefined <= all); + qDebug() << "Undefined configurations:" << undefined; + foreach( const QNetworkConfiguration p, configs) { + printConfigurationDetails(p); + QVERIFY(p.state() & QNetworkConfiguration::Undefined); + QVERIFY(!(p.state() & QNetworkConfiguration::Defined)); + } + + //get defined configs only (same as all) + configs = manager.allConfigurations(QNetworkConfiguration::Defined); + int defined = configs.count(); + qDebug() << "Defined configurations:" << defined; + QVERIFY(defined <= all); + foreach( const QNetworkConfiguration p, configs) { + printConfigurationDetails(p); + QVERIFY(p.state() & QNetworkConfiguration::Defined); + QVERIFY(!(p.state() & QNetworkConfiguration::Undefined)); + } + + //get discovered configurations only + configs = manager.allConfigurations(QNetworkConfiguration::Discovered); + int discovered = configs.count(); + //QVERIFY(discovered); + qDebug() << "Discovered configurations:" << discovered; + foreach(const QNetworkConfiguration p, configs) { + printConfigurationDetails(p); + QVERIFY(p.isValid()); + QVERIFY(!(p.state() & QNetworkConfiguration::Undefined)); + QVERIFY(p.state() & QNetworkConfiguration::Defined); + QVERIFY(p.state() & QNetworkConfiguration::Discovered); + } + + //getactive configurations only + configs = manager.allConfigurations(QNetworkConfiguration::Active); + int active = configs.count(); + if (active) + QVERIFY(manager.isOnline()); + else + QVERIFY(!manager.isOnline()); + + //QVERIFY(active); + qDebug() << "Active configurations:" << active; + foreach(const QNetworkConfiguration p, configs) { + printConfigurationDetails(p); + QVERIFY(p.isValid()); + QVERIFY(!(p.state() & QNetworkConfiguration::Undefined)); + QVERIFY(p.state() & QNetworkConfiguration::Active); + QVERIFY(p.state() & QNetworkConfiguration::Discovered); + QVERIFY(p.state() & QNetworkConfiguration::Defined); + } + + QVERIFY(all >= discovered); + QVERIFY(discovered >= active); +} + + +void tst_QNetworkConfigurationManager::defaultConfiguration() +{ + QNetworkConfigurationManager manager; + QSignalSpy spy(&manager, SIGNAL(updateCompleted())); + manager.updateConfigurations(); //initiate scans + QTRY_VERIFY(spy.count() == 1); //wait for scan to complete + + QList configs = manager.allConfigurations(); + QNetworkConfiguration defaultConfig = manager.defaultConfiguration(); + + bool confirm = configs.contains(defaultConfig); + bool isUserChoice = (defaultConfig.type() == QNetworkConfiguration::UserChoice); + + //user choice config is not part of allConfigurations() + QVERIFY(isUserChoice != confirm); + if (!isUserChoice) { + QVERIFY(confirm || !defaultConfig.isValid()); + QVERIFY(!(confirm && !defaultConfig.isValid())); + } else { + QVERIFY(defaultConfig.isValid()); + QCOMPARE(defaultConfig.name(), QString("UserChoice")); + QCOMPARE(defaultConfig.children().count(), 0); + QVERIFY(!defaultConfig.isRoamingAvailable()); + QCOMPARE(defaultConfig.state(), QNetworkConfiguration::Discovered); + QNetworkConfiguration copy = manager.configurationFromIdentifier(defaultConfig.identifier()); + QVERIFY(copy == defaultConfig); + } +} + +void tst_QNetworkConfigurationManager::configurationFromIdentifier() +{ + QNetworkConfigurationManager manager; + QSet allIdentifier; + + //force an update to get maximum number of configs + QSignalSpy spy(&manager, SIGNAL(updateCompleted())); + manager.updateConfigurations(); //initiate scans + QTRY_VERIFY(spy.count() == 1); //wait for scan to complete + + QList configs = manager.allConfigurations(); + + foreach(QNetworkConfiguration c, configs) { + QVERIFY(!allIdentifier.contains(c.identifier())); + allIdentifier.insert(c.identifier()); + + QNetworkConfiguration direct = manager.configurationFromIdentifier(c.identifier()); + QVERIFY(direct.isValid()); + QVERIFY(direct == c); + } + + //assume that there is no item with identifier 'FooBar' + QVERIFY(!allIdentifier.contains("FooBar")); + QNetworkConfiguration invalid = manager.configurationFromIdentifier("FooBar"); + QVERIFY(!invalid.isValid()); +} + + +QTEST_MAIN(tst_QNetworkConfigurationManager) +#include "tst_qnetworkconfigmanager.moc" diff --git a/tests/auto/qnetworkconfiguration/qnetworkconfiguration.pro b/tests/auto/qnetworkconfiguration/qnetworkconfiguration.pro new file mode 100644 index 0000000..61e4097 --- /dev/null +++ b/tests/auto/qnetworkconfiguration/qnetworkconfiguration.pro @@ -0,0 +1,15 @@ +SOURCES += tst_qnetworkconfiguration.cpp +HEADERS += ../qbearertestcommon.h +TARGET = tst_qnetworkconfiguration +CONFIG += testcase + +QT = core network + +INCLUDEPATH += ../../../src/bearer + +include(../../../common.pri) +qtAddLibrary(QtBearer) + +symbian { + TARGET.CAPABILITY = NetworkServices NetworkControl ReadUserData +} diff --git a/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp b/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp new file mode 100644 index 0000000..cbb13f3 --- /dev/null +++ b/tests/auto/qnetworkconfiguration/tst_qnetworkconfiguration.cpp @@ -0,0 +1,303 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 +#include "../qbearertestcommon.h" +#include "qnetworkconfiguration.h" +#include "qnetworkconfigmanager.h" + +#ifdef MAEMO +#include +#include +#endif + +QTM_USE_NAMESPACE +class tst_QNetworkConfiguration : public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + +private slots: + void invalidPoint(); + void comparison(); + void children(); + void isRoamingAvailable(); + +private: +#ifdef MAEMO + Maemo::IAPConf *iapconf; + Maemo::IAPConf *iapconf2; + Maemo::IAPConf *gprsiap; +#define MAX_IAPS 50 + Maemo::IAPConf *iaps[MAX_IAPS]; + QProcess *icd_stub; +#endif +}; + +void tst_QNetworkConfiguration::initTestCase() +{ +#ifdef MAEMO + iapconf = new Maemo::IAPConf("007"); + iapconf->setValue("ipv4_type", "AUTO"); + iapconf->setValue("wlan_wepkey1", "connt"); + iapconf->setValue("wlan_wepdefkey", 1); + iapconf->setValue("wlan_ssid", QByteArray("JamesBond")); + iapconf->setValue("name", "James Bond"); + iapconf->setValue("type", "WLAN_INFRA"); + + iapconf2 = new Maemo::IAPConf("osso.net"); + iapconf2->setValue("ipv4_type", "AUTO"); + iapconf2->setValue("wlan_wepkey1", "osso.net"); + iapconf2->setValue("wlan_wepdefkey", 1); + iapconf2->setValue("wlan_ssid", QByteArray("osso.net")); + iapconf2->setValue("name", "osso.net"); + iapconf2->setValue("type", "WLAN_INFRA"); + iapconf2->setValue("wlan_security", "WEP"); + + gprsiap = new Maemo::IAPConf("This-is-GPRS-IAP"); + gprsiap->setValue("ask_password", false); + gprsiap->setValue("gprs_accesspointname", "internet"); + gprsiap->setValue("gprs_password", ""); + gprsiap->setValue("gprs_username", ""); + gprsiap->setValue("ipv4_autodns", true); + gprsiap->setValue("ipv4_type", "AUTO"); + gprsiap->setValue("sim_imsi", "244070123456789"); + gprsiap->setValue("name", "MI6"); + gprsiap->setValue("type", "GPRS"); + + /* Create large number of IAPs in the gconf and see what happens */ + fflush(stdout); + printf("Creating %d IAPS: ", MAX_IAPS); + for (int i=0; isetValue("name", QString("test-iap-")+num); + iaps[i]->setValue("type", "WLAN_INFRA"); + iaps[i]->setValue("wlan_ssid", QString(QString("test-ssid-")+num).toAscii()); + iaps[i]->setValue("wlan_security", "WPA_PSK"); + iaps[i]->setValue("EAP_wpa_preshared_passphrase", QString("test-passphrase-")+num); + printf("."); + fflush(stdout); + } + printf("\n"); + fflush(stdout); + + icd_stub = new QProcess(this); + icd_stub->start("/usr/bin/icd2_stub.py"); + QTest::qWait(1000); + + // Add a known network to scan list that icd2 stub returns + QProcess dbus_send; + // 007 network + dbus_send.start("dbus-send --type=method_call --system " + "--dest=com.nokia.icd2 /com/nokia/icd2 " + "com.nokia.icd2.testing.add_available_network " + "string:'' uint32:0 string:'' " + "string:WLAN_INFRA uint32:5000011 array:byte:48,48,55"); + dbus_send.waitForFinished(); + + // osso.net network + dbus_send.start("dbus-send --type=method_call --system " + "--dest=com.nokia.icd2 /com/nokia/icd2 " + "com.nokia.icd2.testing.add_available_network " + "string:'' uint32:0 string:'' " + "string:WLAN_INFRA uint32:83886097 array:byte:111,115,115,111,46,110,101,116"); + dbus_send.waitForFinished(); +#endif +} + +void tst_QNetworkConfiguration::cleanupTestCase() +{ +#ifdef MAEMO + iapconf->clear(); + delete iapconf; + iapconf2->clear(); + delete iapconf2; + gprsiap->clear(); + delete gprsiap; + + printf("Deleting %d IAPS : ", MAX_IAPS); + for (int i=0; iclear(); + delete iaps[i]; + printf("."); + fflush(stdout); + } + printf("\n"); + qDebug() << "Deleted" << MAX_IAPS << "IAPs"; + + // Terminate icd2 stub + icd_stub->terminate(); + icd_stub->waitForFinished(); +#endif +} + +void tst_QNetworkConfiguration::invalidPoint() +{ + QNetworkConfiguration pt; + + QVERIFY(pt.name().isEmpty()); + QVERIFY(!pt.isValid()); + QVERIFY(pt.type() == QNetworkConfiguration::Invalid); + QVERIFY(!(pt.state() & QNetworkConfiguration::Defined)); + QVERIFY(!(pt.state() & QNetworkConfiguration::Discovered)); + QVERIFY(!(pt.state() & QNetworkConfiguration::Active)); + QVERIFY(!pt.isRoamingAvailable()); + + QNetworkConfiguration pt2(pt); + QVERIFY(pt2.name().isEmpty()); + QVERIFY(!pt2.isValid()); + QVERIFY(pt2.type() == QNetworkConfiguration::Invalid); + QVERIFY(!(pt2.state() & QNetworkConfiguration::Defined)); + QVERIFY(!(pt2.state() & QNetworkConfiguration::Discovered)); + QVERIFY(!(pt2.state() & QNetworkConfiguration::Active)); + QVERIFY(!pt2.isRoamingAvailable()); + +} + +void tst_QNetworkConfiguration::comparison() +{ + //test copy constructor and assignment operator + //compare invalid connection points + QNetworkConfiguration pt1; + QVERIFY(!pt1.isValid()); + QVERIFY(pt1.type() == QNetworkConfiguration::Invalid); + + QNetworkConfiguration pt2(pt1); + QVERIFY(pt1==pt2); + QVERIFY(!(pt1!=pt2)); + QVERIFY(pt1.name() == pt2.name()); + QVERIFY(pt1.isValid() == pt2.isValid()); + QVERIFY(pt1.type() == pt2.type()); + QVERIFY(pt1.state() == pt2.state()); + QVERIFY(pt1.purpose() == pt2.purpose()); + + + QNetworkConfiguration pt3; + pt3 = pt1; + QVERIFY(pt1==pt3); + QVERIFY(!(pt1!=pt3)); + QVERIFY(pt1.name() == pt3.name()); + QVERIFY(pt1.isValid() == pt3.isValid()); + QVERIFY(pt1.type() == pt3.type()); + QVERIFY(pt1.state() == pt3.state()); + QVERIFY(pt1.purpose() == pt3.purpose()); + + //test case must run on machine that has valid connection points + QNetworkConfigurationManager manager; + QList preScanConfigs = manager.allConfigurations(); + + QSignalSpy spy(&manager, SIGNAL(updateCompleted())); + manager.updateConfigurations(); //initiate scans + QTRY_VERIFY(spy.count() == 1); //wait for scan to complete + + QList configs = manager.allConfigurations(QNetworkConfiguration::Discovered); + QVERIFY(configs.count()); + QNetworkConfiguration defaultConfig = manager.defaultConfiguration(); + QVERIFY(defaultConfig.isValid()); + QVERIFY(defaultConfig.type() != QNetworkConfiguration::Invalid); + QVERIFY(!defaultConfig.name().isEmpty()); + + pt3 = defaultConfig; + QVERIFY(defaultConfig==pt3); + QVERIFY(!(defaultConfig!=pt3)); + QVERIFY(defaultConfig.name() == pt3.name()); + QVERIFY(defaultConfig.isValid() == pt3.isValid()); + QVERIFY(defaultConfig.type() == pt3.type()); + QVERIFY(defaultConfig.state() == pt3.state()); + QVERIFY(defaultConfig.purpose() == pt3.purpose()); +} + +void tst_QNetworkConfiguration::children() +{ + QNetworkConfigurationManager manager; + QList configs = manager.allConfigurations(); + + foreach(QNetworkConfiguration c, configs) + { + if ( c.type() == QNetworkConfiguration::ServiceNetwork ) { + qDebug() << "found service network" << c.name() << c.children().count(); + QVERIFY(c.isValid()); + QList members = c.children(); + foreach(QNetworkConfiguration child, members) { + QVERIFY(child.isValid()); + QVERIFY(configs.contains(child)); + qDebug() << "\t" << child.name(); + } + } + } +} + +void tst_QNetworkConfiguration::isRoamingAvailable() +{ + QNetworkConfigurationManager manager; + QList configs = manager.allConfigurations(); + + //force update to get maximum list + QSignalSpy spy(&manager, SIGNAL(updateCompleted())); + manager.updateConfigurations(); //initiate scans + QTRY_VERIFY(spy.count() == 1); //wait for scan to complete + + foreach(QNetworkConfiguration c, configs) + { + QVERIFY(QNetworkConfiguration::UserChoice != c.type()); + QVERIFY(QNetworkConfiguration::Invalid != c.type()); + if ( c.type() == QNetworkConfiguration::ServiceNetwork ) { + //cannot test flag as some SNAPs may not support roaming anyway + //QVERIFY(c.roamingavailable()) + if ( c.children().count() <= 1 ) + QVERIFY(!c.isRoamingAvailable()); + foreach(QNetworkConfiguration child, c.children()) { + QVERIFY(QNetworkConfiguration::InternetAccessPoint == child.type()); + QCOMPARE(child.children().count(), 0); + } + } else { + QVERIFY(!c.isRoamingAvailable()); + } + } +} + +QTEST_MAIN(tst_QNetworkConfiguration) +#include "tst_qnetworkconfiguration.moc" diff --git a/tests/auto/qnetworksession/lackey/lackey.pro b/tests/auto/qnetworksession/lackey/lackey.pro new file mode 100644 index 0000000..4cb8555 --- /dev/null +++ b/tests/auto/qnetworksession/lackey/lackey.pro @@ -0,0 +1,12 @@ +SOURCES += main.cpp +TARGET = qnetworksessionlackey +INCLUDEPATH += ../../../../src/bearer +DEPENDPATH += ../../../../src/bearer + +QT = core network + +CONFIG+= testcase + +include(../../../../common.pri) + +qtAddLibrary(QtBearer) diff --git a/tests/auto/qnetworksession/lackey/main.cpp b/tests/auto/qnetworksession/lackey/main.cpp new file mode 100644 index 0000000..53f6f4f --- /dev/null +++ b/tests/auto/qnetworksession/lackey/main.cpp @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 +#include +#include +#include +#include +#include + +#include + +QTM_USE_NAMESPACE + + +#define NO_DISCOVERED_CONFIGURATIONS_ERROR 1 +#define SESSION_OPEN_ERROR 2 + +int main(int argc, char** argv) +{ + QCoreApplication app(argc, argv); + + QNetworkConfigurationManager manager; + QList discovered = + manager.allConfigurations(QNetworkConfiguration::Discovered); + + if (discovered.isEmpty()) + return NO_DISCOVERED_CONFIGURATIONS_ERROR; + + // Cannot read/write to processes on WinCE or Symbian. + // Easiest alternative is to use sockets for IPC. + + QLocalSocket oopSocket; + + oopSocket.connectToServer("tst_qnetworksession"); + oopSocket.waitForConnected(-1); + + qDebug() << "Lackey started"; + + QNetworkSession *session = 0; + do { + if (session) { + delete session; + session = 0; + } + + qDebug() << "Discovered configurations:" << discovered.count(); + + if (discovered.isEmpty()) { + qDebug() << "No more configurations"; + break; + } + + qDebug() << "Taking first configuration"; + + QNetworkConfiguration config = discovered.takeFirst(); + if ((config.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { + qDebug() << config.name() << "is active"; + continue; + } + + qDebug() << "Creating session for" << config.name() << config.identifier(); + + session = new QNetworkSession(config); + + QString output = QString("Starting session for %1\n").arg(config.identifier()); + oopSocket.write(output.toAscii()); + oopSocket.waitForBytesWritten(); + + session->open(); + session->waitForOpened(); + } while (!(session && session->isActive())); + + qDebug() << "loop done"; + + if (!session) { + qDebug() << "Could not start session"; + + oopSocket.disconnectFromServer(); + oopSocket.waitForDisconnected(-1); + + return SESSION_OPEN_ERROR; + } + + QString output = QString("Started session for %1\n").arg(session->configuration().identifier()); + oopSocket.write(output.toAscii()); + oopSocket.waitForBytesWritten(); + + oopSocket.waitForReadyRead(); + oopSocket.readLine(); + + session->stop(); + + delete session; + + oopSocket.disconnectFromServer(); + oopSocket.waitForDisconnected(-1); + + return 0; +} diff --git a/tests/auto/qnetworksession/qnetworksession.pro b/tests/auto/qnetworksession/qnetworksession.pro new file mode 100644 index 0000000..14dbb3e --- /dev/null +++ b/tests/auto/qnetworksession/qnetworksession.pro @@ -0,0 +1,2 @@ +TEMPLATE = subdirs +SUBDIRS = lackey tst_qnetworksession diff --git a/tests/auto/qnetworksession/tst_qnetworksession/tst_qnetworksession.cpp b/tests/auto/qnetworksession/tst_qnetworksession/tst_qnetworksession.cpp new file mode 100644 index 0000000..cbd4c8f --- /dev/null +++ b/tests/auto/qnetworksession/tst_qnetworksession/tst_qnetworksession.cpp @@ -0,0 +1,873 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 +#include +#include +#include "../../qbearertestcommon.h" +#include +#include + +#ifdef MAEMO +#include +#include +#endif + +QTM_USE_NAMESPACE + +Q_DECLARE_METATYPE(QNetworkConfiguration) +Q_DECLARE_METATYPE(QNetworkSession::State); +Q_DECLARE_METATYPE(QNetworkSession::SessionError); + +class tst_QNetworkSession : public QObject +{ + Q_OBJECT + +public slots: + void initTestCase(); + void cleanupTestCase(); + +private slots: + void invalidSession(); + + void sessionProperties_data(); + void sessionProperties(); + + void userChoiceSession_data(); + void userChoiceSession(); + + void sessionOpenCloseStop_data(); + void sessionOpenCloseStop(); + + void outOfProcessSession(); + +private: + QNetworkConfigurationManager manager; + + uint inProcessSessionManagementCount; + +#ifdef MAEMO + Maemo::IAPConf *iapconf; + Maemo::IAPConf *iapconf2; + Maemo::IAPConf *gprsiap; +#define MAX_IAPS 10 + Maemo::IAPConf *iaps[MAX_IAPS]; + QProcess *icd_stub; +#endif +}; + +void tst_QNetworkSession::initTestCase() +{ + qRegisterMetaType("QNetworkSession::State"); + qRegisterMetaType("QNetworkSession::SessionError"); + qRegisterMetaType("QNetworkConfiguration"); + +#ifdef MAEMO + iapconf = new Maemo::IAPConf("007"); + iapconf->setValue("ipv4_type", "AUTO"); + iapconf->setValue("wlan_wepkey1", "connt"); + iapconf->setValue("wlan_wepdefkey", 1); + iapconf->setValue("wlan_ssid", QByteArray("JamesBond")); + iapconf->setValue("name", "James Bond"); + iapconf->setValue("type", "WLAN_INFRA"); + + gprsiap = new Maemo::IAPConf("This-is-GPRS-IAP"); + gprsiap->setValue("ask_password", false); + gprsiap->setValue("gprs_accesspointname", "internet"); + gprsiap->setValue("gprs_password", ""); + gprsiap->setValue("gprs_username", ""); + gprsiap->setValue("ipv4_autodns", true); + gprsiap->setValue("ipv4_type", "AUTO"); + gprsiap->setValue("sim_imsi", "244070123456789"); + gprsiap->setValue("name", "MI6"); + gprsiap->setValue("type", "GPRS"); + + iapconf2 = new Maemo::IAPConf("osso.net"); + iapconf2->setValue("ipv4_type", "AUTO"); + iapconf2->setValue("wlan_wepkey1", "osso.net"); + iapconf2->setValue("wlan_wepdefkey", 1); + iapconf2->setValue("wlan_ssid", QByteArray("osso.net")); + iapconf2->setValue("name", "osso.net"); + iapconf2->setValue("type", "WLAN_INFRA"); + iapconf2->setValue("wlan_security", "WEP"); + + /* Create large number of IAPs in the gconf and see what happens */ + fflush(stdout); + printf("Creating %d IAPS: ", MAX_IAPS); + for (int i=0; isetValue("name", QString("test-iap-")+num); + iaps[i]->setValue("type", "WLAN_INFRA"); + iaps[i]->setValue("wlan_ssid", QString(QString("test-ssid-")+num).toAscii()); + iaps[i]->setValue("wlan_security", "WPA_PSK"); + iaps[i]->setValue("EAP_wpa_preshared_passphrase", QString("test-passphrase-")+num); + printf("."); + fflush(stdout); + } + printf("\n"); + fflush(stdout); + + icd_stub = new QProcess(this); + icd_stub->start("/usr/bin/icd2_stub.py"); + QTest::qWait(1000); + + // Add a known network to scan list that icd2 stub returns + QProcess dbus_send; + // 007 network + dbus_send.start("dbus-send --type=method_call --system " + "--dest=com.nokia.icd2 /com/nokia/icd2 " + "com.nokia.icd2.testing.add_available_network " + "string:'' uint32:0 string:'' " + "string:WLAN_INFRA uint32:5000011 array:byte:48,48,55"); + dbus_send.waitForFinished(); + + // osso.net network + dbus_send.start("dbus-send --type=method_call --system " + "--dest=com.nokia.icd2 /com/nokia/icd2 " + "com.nokia.icd2.testing.add_available_network " + "string:'' uint32:0 string:'' " + "string:WLAN_INFRA uint32:83886097 array:byte:111,115,115,111,46,110,101,116"); + dbus_send.waitForFinished(); +#endif + + inProcessSessionManagementCount = 0; + + QSignalSpy spy(&manager, SIGNAL(updateCompleted())); + manager.updateConfigurations(); + QTRY_VERIFY(spy.count() == 1); +} + +void tst_QNetworkSession::cleanupTestCase() +{ + if (!(manager.capabilities() & QNetworkConfigurationManager::SystemSessionSupport) && + (manager.capabilities() & QNetworkConfigurationManager::CanStartAndStopInterfaces) && + inProcessSessionManagementCount == 0) { + QFAIL("No usable configurations found to complete all possible " + "tests in inProcessSessionManagement()"); + } + +#ifdef MAEMO + iapconf->clear(); + delete iapconf; + iapconf2->clear(); + delete iapconf2; + gprsiap->clear(); + delete gprsiap; + + printf("Deleting %d IAPS : ", MAX_IAPS); + for (int i=0; iclear(); + delete iaps[i]; + printf("."); + fflush(stdout); + } + printf("\n"); + qDebug() << "Deleted" << MAX_IAPS << "IAPs"; + + icd_stub->terminate(); + icd_stub->waitForFinished(); +#endif +} + +void tst_QNetworkSession::invalidSession() +{ + QNetworkSession session(QNetworkConfiguration(), 0); + QVERIFY(!session.isActive()); + QVERIFY(session.state() == QNetworkSession::Invalid); +} + +void tst_QNetworkSession::sessionProperties_data() +{ + QTest::addColumn("configuration"); + + QTest::newRow("invalid configuration") << QNetworkConfiguration(); + + foreach (const QNetworkConfiguration &config, manager.allConfigurations()) { + const QString name = config.name().isEmpty() ? QString("") : config.name(); + QTest::newRow(name.toLocal8Bit().constData()) << config; + } +} + +void tst_QNetworkSession::sessionProperties() +{ + QFETCH(QNetworkConfiguration, configuration); + + QNetworkSession session(configuration); + + QVERIFY(session.configuration() == configuration); + + QStringList validBearerNames = QStringList() << QString() + << QLatin1String("Ethernet") + << QLatin1String("WLAN") + << QLatin1String("2G") + << QLatin1String("CDMA2000") + << QLatin1String("WCDMA") + << QLatin1String("HSPA") + << QLatin1String("Bluetooth") + << QLatin1String("WiMAX"); + + if (!configuration.isValid()) + QVERIFY(session.bearerName().isEmpty()); + else + QVERIFY(validBearerNames.contains(session.bearerName())); + + // QNetworkSession::interface() should return an invalid interface unless + // session is in the connected state. + QCOMPARE(session.state() == QNetworkSession::Connected, session.interface().isValid()); + + if (!configuration.isValid()) { + QVERIFY(configuration.state() == QNetworkConfiguration::Undefined && + session.state() == QNetworkSession::Invalid); + } else { + switch (configuration.state()) { + case QNetworkConfiguration::Undefined: + QVERIFY(session.state() == QNetworkSession::NotAvailable); + break; + case QNetworkConfiguration::Defined: + QVERIFY(session.state() == QNetworkSession::NotAvailable); + break; + case QNetworkConfiguration::Discovered: + QVERIFY(session.state() == QNetworkSession::Connecting || + session.state() == QNetworkSession::Disconnected); + break; + case QNetworkConfiguration::Active: + QVERIFY(session.state() == QNetworkSession::Connected || + session.state() == QNetworkSession::Closing || + session.state() == QNetworkSession::Roaming); + break; + default: + QFAIL("Invalid configuration state"); + }; + } +} + +void tst_QNetworkSession::userChoiceSession_data() +{ + QTest::addColumn("configuration"); + + QNetworkConfiguration config = manager.defaultConfiguration(); + if (config.type() == QNetworkConfiguration::UserChoice) + QTest::newRow("UserChoice") << config; + else + QSKIP("Default configuration is not a UserChoice configuration.", SkipAll); +} + +void tst_QNetworkSession::userChoiceSession() +{ + QFETCH(QNetworkConfiguration, configuration); + + QVERIFY(configuration.type() == QNetworkConfiguration::UserChoice); + + QNetworkSession session(configuration); + + QVERIFY(session.configuration() == configuration); + + QVERIFY(!session.isActive()); + + QVERIFY(session.sessionProperty("ActiveConfigurationIdentifier").toString().isEmpty()); + + + // The remaining tests require the session to be not NotAvailable. + if (session.state() == QNetworkSession::NotAvailable) + QSKIP("Network is not available.", SkipSingle); + + QSignalSpy sessionOpenedSpy(&session, SIGNAL(opened())); + QSignalSpy sessionClosedSpy(&session, SIGNAL(closed())); + QSignalSpy stateChangedSpy(&session, SIGNAL(stateChanged(QNetworkSession::State))); + QSignalSpy errorSpy(&session, SIGNAL(error(QNetworkSession::SessionError))); + + // Test opening the session. + { + bool expectStateChange = session.state() != QNetworkSession::Connected; + + session.open(); + + session.waitForOpened(); + + if (session.isActive()) + QVERIFY(!sessionOpenedSpy.isEmpty() || !errorSpy.isEmpty()); + if (!errorSpy.isEmpty()) { + QNetworkSession::SessionError error = + qvariant_cast(errorSpy.first().at(0)); + if (error == QNetworkSession::OperationNotSupportedError) { + // The session needed to bring up the interface, + // but the operation is not supported. + QSKIP("Configuration does not support open().", SkipSingle); + } else if (error == QNetworkSession::InvalidConfigurationError) { + // The session needed to bring up the interface, but it is not possible for the + // specified configuration. + if ((session.configuration().state() & QNetworkConfiguration::Discovered) == + QNetworkConfiguration::Discovered) { + QFAIL("Failed to open session for Discovered configuration."); + } else { + QSKIP("Cannot test session for non-Discovered configuration.", SkipSingle); + } + } else if (error == QNetworkSession::UnknownSessionError) { + QSKIP("Unknown session error.", SkipSingle); + } else { + QFAIL("Error opening session."); + } + } else if (!sessionOpenedSpy.isEmpty()) { + QCOMPARE(sessionOpenedSpy.count(), 1); + QVERIFY(sessionClosedSpy.isEmpty()); + QVERIFY(errorSpy.isEmpty()); + + if (expectStateChange) + QTRY_VERIFY(!stateChangedSpy.isEmpty()); + + QVERIFY(session.state() == QNetworkSession::Connected); + QVERIFY(session.interface().isValid()); + + const QString userChoiceIdentifier = + session.sessionProperty("UserChoiceConfigurationIdentifier").toString(); + + QVERIFY(!userChoiceIdentifier.isEmpty()); + QVERIFY(userChoiceIdentifier != configuration.identifier()); + + QNetworkConfiguration userChoiceConfiguration = + manager.configurationFromIdentifier(userChoiceIdentifier); + + QVERIFY(userChoiceConfiguration.isValid()); + QVERIFY(userChoiceConfiguration.type() != QNetworkConfiguration::UserChoice); + + const QString testIdentifier("abc"); + //resetting UserChoiceConfigurationIdentifier is ignored (read only property) + session.setSessionProperty("UserChoiceConfigurationIdentifier", testIdentifier); + QVERIFY(session.sessionProperty("UserChoiceConfigurationIdentifier").toString() != testIdentifier); + + const QString activeIdentifier = + session.sessionProperty("ActiveConfigurationIdentifier").toString(); + + QVERIFY(!activeIdentifier.isEmpty()); + QVERIFY(activeIdentifier != configuration.identifier()); + + QNetworkConfiguration activeConfiguration = + manager.configurationFromIdentifier(activeIdentifier); + + QVERIFY(activeConfiguration.isValid()); + QVERIFY(activeConfiguration.type() == QNetworkConfiguration::InternetAccessPoint); + + //resetting ActiveConfigurationIdentifier is ignored (read only property) + session.setSessionProperty("ActiveConfigurationIdentifier", testIdentifier); + QVERIFY(session.sessionProperty("ActiveConfigurationIdentifier").toString() != testIdentifier); + + if (userChoiceConfiguration.type() == QNetworkConfiguration::InternetAccessPoint) { + QVERIFY(userChoiceConfiguration == activeConfiguration); + } else { + QVERIFY(userChoiceConfiguration.type() == QNetworkConfiguration::ServiceNetwork); + QVERIFY(userChoiceConfiguration.children().contains(activeConfiguration)); + } + } else { + QFAIL("Timeout waiting for session to open."); + } + } +} + +void tst_QNetworkSession::sessionOpenCloseStop_data() +{ + QTest::addColumn("configuration"); + QTest::addColumn("forceSessionStop"); + + foreach (const QNetworkConfiguration &config, manager.allConfigurations()) { + const QString name = config.name().isEmpty() ? QString("") : config.name(); + QTest::newRow((name + QLatin1String(" close")).toLocal8Bit().constData()) + << config << false; + QTest::newRow((name + QLatin1String(" stop")).toLocal8Bit().constData()) + << config << true; + } +} + +void tst_QNetworkSession::sessionOpenCloseStop() +{ + QFETCH(QNetworkConfiguration, configuration); + QFETCH(bool, forceSessionStop); + + QNetworkSession session(configuration); + + // Test initial state of the session. + { + QVERIFY(session.configuration() == configuration); + QVERIFY(!session.isActive()); + // session may be invalid if configuration is removed between when + // sessionOpenCloseStop_data() is called and here. + QVERIFY((configuration.isValid() && (session.state() != QNetworkSession::Invalid)) || + (!configuration.isValid() && (session.state() == QNetworkSession::Invalid))); + QVERIFY(session.error() == QNetworkSession::UnknownSessionError); + } + + // The remaining tests require the session to be not NotAvailable. + if (session.state() == QNetworkSession::NotAvailable) + QSKIP("Network is not available.", SkipSingle); + + QSignalSpy sessionOpenedSpy(&session, SIGNAL(opened())); + QSignalSpy sessionClosedSpy(&session, SIGNAL(closed())); + QSignalSpy stateChangedSpy(&session, SIGNAL(stateChanged(QNetworkSession::State))); + QSignalSpy errorSpy(&session, SIGNAL(error(QNetworkSession::SessionError))); + + // Test opening the session. + { + QNetworkSession::State previousState = session.state(); + bool expectStateChange = previousState != QNetworkSession::Connected; + + session.open(); + + session.waitForOpened(); + + if (session.isActive()) + QVERIFY(!sessionOpenedSpy.isEmpty() || !errorSpy.isEmpty()); + if (!errorSpy.isEmpty()) { + QNetworkSession::SessionError error = + qvariant_cast(errorSpy.first().at(0)); + + QVERIFY(session.state() == previousState); + + if (error == QNetworkSession::OperationNotSupportedError) { + // The session needed to bring up the interface, + // but the operation is not supported. + QSKIP("Configuration does not support open().", SkipSingle); + } else if (error == QNetworkSession::InvalidConfigurationError) { + // The session needed to bring up the interface, but it is not possible for the + // specified configuration. + if ((session.configuration().state() & QNetworkConfiguration::Discovered) == + QNetworkConfiguration::Discovered) { + QFAIL("Failed to open session for Discovered configuration."); + } else { + QSKIP("Cannot test session for non-Discovered configuration.", SkipSingle); + } + } else if (error == QNetworkSession::UnknownSessionError) { + QSKIP("Unknown Session error.", SkipSingle); + } else { + QFAIL("Error opening session."); + } + } else if (!sessionOpenedSpy.isEmpty()) { + QCOMPARE(sessionOpenedSpy.count(), 1); + QVERIFY(sessionClosedSpy.isEmpty()); + QVERIFY(errorSpy.isEmpty()); + + if (expectStateChange) { + QTRY_VERIFY(stateChangedSpy.count() >= 2); + + QNetworkSession::State state = + qvariant_cast(stateChangedSpy.at(0).at(0)); + QVERIFY(state == QNetworkSession::Connecting); + + state = qvariant_cast(stateChangedSpy.at(1).at(0)); + QVERIFY(state == QNetworkSession::Connected); + } + + QVERIFY(session.state() == QNetworkSession::Connected); + QVERIFY(session.interface().isValid()); + } else { + QFAIL("Timeout waiting for session to open."); + } + } + + sessionOpenedSpy.clear(); + sessionClosedSpy.clear(); + stateChangedSpy.clear(); + errorSpy.clear(); + + QNetworkSession session2(configuration); + + QSignalSpy sessionOpenedSpy2(&session2, SIGNAL(opened())); + QSignalSpy sessionClosedSpy2(&session2, SIGNAL(closed())); + QSignalSpy stateChangedSpy2(&session2, SIGNAL(stateChanged(QNetworkSession::State))); + QSignalSpy errorSpy2(&session2, SIGNAL(error(QNetworkSession::SessionError))); + + // Test opening a second session. + { + QVERIFY(session2.configuration() == configuration); + QVERIFY(!session2.isActive()); + QVERIFY(session2.state() == QNetworkSession::Connected); + QVERIFY(session.error() == QNetworkSession::UnknownSessionError); + + session2.open(); + + QTRY_VERIFY(!sessionOpenedSpy2.isEmpty() || !errorSpy2.isEmpty()); + + QVERIFY(session.isActive()); + QVERIFY(session2.isActive()); + QVERIFY(session.state() == QNetworkSession::Connected); + QVERIFY(session2.state() == QNetworkSession::Connected); + QVERIFY(session.interface().isValid()); + QCOMPARE(session.interface().hardwareAddress(), session2.interface().hardwareAddress()); + QCOMPARE(session.interface().index(), session2.interface().index()); + } + + sessionOpenedSpy2.clear(); + + if (forceSessionStop) { + // Test forcing the second session to stop the interface. + QNetworkSession::State previousState = session.state(); +#ifdef Q_CC_NOKIAX86 + // For S60 emulator builds: RConnection::Stop does not work on all Emulators + bool expectStateChange = false; +#else + bool expectStateChange = previousState != QNetworkSession::Disconnected; +#endif + + session2.stop(); + + QTRY_VERIFY(!sessionClosedSpy2.isEmpty() || !errorSpy2.isEmpty()); + + QVERIFY(!session2.isActive()); + + if (!errorSpy2.isEmpty()) { + QVERIFY(!errorSpy.isEmpty()); + + // check for SessionAbortedError + QNetworkSession::SessionError error = + qvariant_cast(errorSpy.first().at(0)); + QNetworkSession::SessionError error2 = + qvariant_cast(errorSpy2.first().at(0)); + + QVERIFY(error == QNetworkSession::SessionAbortedError); + QVERIFY(error2 == QNetworkSession::SessionAbortedError); + + QCOMPARE(errorSpy.count(), 1); + QCOMPARE(errorSpy2.count(), 1); + + errorSpy.clear(); + errorSpy2.clear(); + } + + QVERIFY(errorSpy.isEmpty()); + QVERIFY(errorSpy2.isEmpty()); + + if (expectStateChange) + QTRY_VERIFY(stateChangedSpy2.count() >= 2 || !errorSpy2.isEmpty()); + + if (!errorSpy2.isEmpty()) { + QVERIFY(session2.state() == previousState); + QVERIFY(session.state() == previousState); + + QNetworkSession::SessionError error = + qvariant_cast(errorSpy2.first().at(0)); + if (error == QNetworkSession::OperationNotSupportedError) { + // The session needed to bring down the interface, + // but the operation is not supported. + QSKIP("Configuration does not support stop().", SkipSingle); + } else if (error == QNetworkSession::InvalidConfigurationError) { + // The session needed to bring down the interface, but it is not possible for the + // specified configuration. + if ((session.configuration().state() & QNetworkConfiguration::Discovered) == + QNetworkConfiguration::Discovered) { + QFAIL("Failed to stop session for Discovered configuration."); + } else { + QSKIP("Cannot test session for non-Discovered configuration.", SkipSingle); + } + } else { + QFAIL("Error stopping session."); + } + } else if (!sessionClosedSpy2.isEmpty()) { + if (expectStateChange) { + if (configuration.type() == QNetworkConfiguration::ServiceNetwork) { + bool roamedSuccessfully = false; + + QCOMPARE(stateChangedSpy2.count(), 4); + + QNetworkSession::State state = + qvariant_cast(stateChangedSpy2.at(0).at(0)); + QVERIFY(state == QNetworkSession::Connecting); + + state = qvariant_cast(stateChangedSpy2.at(1).at(0)); + QVERIFY(state == QNetworkSession::Connected); + + state = qvariant_cast(stateChangedSpy2.at(2).at(0)); + QVERIFY(state == QNetworkSession::Closing); + + state = qvariant_cast(stateChangedSpy2.at(3).at(0)); + QVERIFY(state == QNetworkSession::Disconnected); + + QTRY_VERIFY(stateChangedSpy.count() > 0); + state = qvariant_cast(stateChangedSpy.at(0).at(0)); + if (state == QNetworkSession::Roaming) { + QTRY_VERIFY(!errorSpy.isEmpty() || stateChangedSpy.count() > 1); + if (stateChangedSpy.count() > 1) { + state = qvariant_cast(stateChangedSpy.at(1).at(0)); + if (state == QNetworkSession::Connected) { + roamedSuccessfully = true; + QTRY_VERIFY(session2.state() == QNetworkSession::Disconnected); + } + } + } + if (roamedSuccessfully) { + QString configId = session.sessionProperty("ActiveConfigurationIdentifier").toString(); + QNetworkConfiguration config = manager.configurationFromIdentifier(configId); + QNetworkSession session3(config); + QSignalSpy errorSpy3(&session3, SIGNAL(error(QNetworkSession::SessionError))); + QSignalSpy sessionOpenedSpy3(&session3, SIGNAL(opened())); + + session3.open(); + session3.waitForOpened(); + + if (session.isActive()) + QVERIFY(!sessionOpenedSpy3.isEmpty() || !errorSpy3.isEmpty()); + + session.stop(); + + QTRY_VERIFY(session.state() == QNetworkSession::Disconnected); + QTRY_VERIFY(session3.state() == QNetworkSession::Disconnected); + } +#ifndef Q_CC_NOKIAX86 + if (!roamedSuccessfully) + QVERIFY(!errorSpy.isEmpty()); +#endif + } else { + QCOMPARE(stateChangedSpy2.count(), 2); + + QNetworkSession::State state = + qvariant_cast(stateChangedSpy2.at(0).at(0)); + QVERIFY(state == QNetworkSession::Closing); + + state = qvariant_cast(stateChangedSpy2.at(1).at(0)); + QVERIFY(state == QNetworkSession::Disconnected); + } + + QTRY_VERIFY(!sessionClosedSpy.isEmpty()); + QVERIFY(session.state() == QNetworkSession::Disconnected); + QVERIFY(session2.state() == QNetworkSession::Disconnected); + } + + QVERIFY(errorSpy2.isEmpty()); + + ++inProcessSessionManagementCount; + } else { + QFAIL("Timeout waiting for session to stop."); + } + +#ifndef Q_CC_NOKIAX86 + QVERIFY(!sessionClosedSpy.isEmpty()); +#endif + QVERIFY(!sessionClosedSpy2.isEmpty()); + +#ifndef Q_CC_NOKIAX86 + QVERIFY(!session.isActive()); +#endif + QVERIFY(!session2.isActive()); + } else { + // Test closing the second session. + { + int stateChangedCountBeforeClose = stateChangedSpy2.count(); + session2.close(); + + QTRY_VERIFY(!sessionClosedSpy2.isEmpty()); +#ifndef Q_CC_NOKIAX86 + QVERIFY(stateChangedSpy2.count() == stateChangedCountBeforeClose); +#endif + + QVERIFY(sessionClosedSpy.isEmpty()); + + QVERIFY(session.isActive()); + QVERIFY(!session2.isActive()); + QVERIFY(session.state() == QNetworkSession::Connected); + QVERIFY(session2.state() == QNetworkSession::Connected); + QVERIFY(session.interface().isValid()); + QCOMPARE(session.interface().hardwareAddress(), session2.interface().hardwareAddress()); + QCOMPARE(session.interface().index(), session2.interface().index()); + } + + sessionClosedSpy2.clear(); + + // Test closing the first session. + { +#ifdef Q_CC_NOKIAX86 + // For S60 emulator builds: RConnection::Close does not actually + // close network connection on all Emulators + bool expectStateChange = false; +#else + bool expectStateChange = session.state() != QNetworkSession::Disconnected && + manager.capabilities() & QNetworkConfigurationManager::SystemSessionSupport; +#endif + + session.close(); + + QTRY_VERIFY(!sessionClosedSpy.isEmpty() || !errorSpy.isEmpty()); + + QVERIFY(!session.isActive()); + + if (expectStateChange) + QTRY_VERIFY(!stateChangedSpy.isEmpty() || !errorSpy.isEmpty()); + + if (!errorSpy.isEmpty()) { + QNetworkSession::SessionError error = + qvariant_cast(errorSpy.first().at(0)); + if (error == QNetworkSession::OperationNotSupportedError) { + // The session needed to bring down the interface, + // but the operation is not supported. + QSKIP("Configuration does not support close().", SkipSingle); + } else if (error == QNetworkSession::InvalidConfigurationError) { + // The session needed to bring down the interface, but it is not possible for the + // specified configuration. + if ((session.configuration().state() & QNetworkConfiguration::Discovered) == + QNetworkConfiguration::Discovered) { + QFAIL("Failed to close session for Discovered configuration."); + } else { + QSKIP("Cannot test session for non-Discovered configuration.", SkipSingle); + } + } else { + QFAIL("Error closing session."); + } + } else if (!sessionClosedSpy.isEmpty()) { + QVERIFY(sessionOpenedSpy.isEmpty()); + QCOMPARE(sessionClosedSpy.count(), 1); + if (expectStateChange) + QVERIFY(!stateChangedSpy.isEmpty()); + QVERIFY(errorSpy.isEmpty()); + + if (expectStateChange) + QTRY_VERIFY(session.state() == QNetworkSession::Disconnected); + + ++inProcessSessionManagementCount; + } else { + QFAIL("Timeout waiting for session to close."); + } + } + } +} + +QDebug operator<<(QDebug debug, const QList &list) +{ + debug.nospace() << "( "; + foreach (const QNetworkConfiguration &config, list) + debug.nospace() << config.identifier() << ", "; + debug.nospace() << ")\n"; + return debug; +} + +void tst_QNetworkSession::outOfProcessSession() +{ + QNetworkConfigurationManager manager; + + QList before = manager.allConfigurations(QNetworkConfiguration::Active); + + QSignalSpy spy(&manager, SIGNAL(configurationChanged(QNetworkConfiguration))); + + // Cannot read/write to processes on WinCE or Symbian. + // Easiest alternative is to use sockets for IPC. + + QLocalServer oopServer; + oopServer.listen("tst_qnetworksession"); + + QProcess lackey; + lackey.start("qnetworksessionlackey"); + QVERIFY(lackey.waitForStarted()); + + QVERIFY(oopServer.waitForNewConnection(-1)); + QLocalSocket *oopSocket = oopServer.nextPendingConnection(); + + do { + QByteArray output; + + if(oopSocket->waitForReadyRead()) + output = oopSocket->readLine().trimmed(); + + if (output.startsWith("Started session ")) { + QString identifier = QString::fromLocal8Bit(output.mid(16).constData()); + + QNetworkConfiguration changed; + + do { + QTRY_VERIFY(!spy.isEmpty()); + + changed = qvariant_cast(spy.takeFirst().at(0)); + + } while (changed.identifier() != identifier); + + QVERIFY((changed.state() & QNetworkConfiguration::Active) == + QNetworkConfiguration::Active); + + QVERIFY(!before.contains(changed)); + + QList after = + manager.allConfigurations(QNetworkConfiguration::Active); + + QVERIFY(after.contains(changed)); + + spy.clear(); + + oopSocket->write("stop\n"); + oopSocket->waitForBytesWritten(); + + do { + QTRY_VERIFY(!spy.isEmpty()); + + changed = qvariant_cast(spy.takeFirst().at(0)); + } while (changed.identifier() != identifier); + + QVERIFY((changed.state() & QNetworkConfiguration::Active) != + QNetworkConfiguration::Active); + + QList afterStop = + manager.allConfigurations(QNetworkConfiguration::Active); + + QVERIFY(!afterStop.contains(changed)); + + oopSocket->disconnectFromServer(); + oopSocket->waitForDisconnected(-1); + + lackey.waitForFinished(); + } + // This is effected by QTBUG-4903, process will always report as running + //} while (lackey.state() == QProcess::Running); + + // Workaround: the socket in the lackey will disconnect on exit + } while (oopSocket->state() == QLocalSocket::ConnectedState); + + switch (lackey.exitCode()) { + case 0: + break; + case 1: + QSKIP("No discovered configurations found.", SkipAll); + break; + case 2: + QSKIP("Lackey could not start session.", SkipAll); + default: + QSKIP("Lackey failed", SkipAll); + } +} + +QTEST_MAIN(tst_QNetworkSession) + +#include "tst_qnetworksession.moc" + diff --git a/tests/auto/qnetworksession/tst_qnetworksession/tst_qnetworksession.pro b/tests/auto/qnetworksession/tst_qnetworksession/tst_qnetworksession.pro new file mode 100644 index 0000000..1410601 --- /dev/null +++ b/tests/auto/qnetworksession/tst_qnetworksession/tst_qnetworksession.pro @@ -0,0 +1,21 @@ +SOURCES += tst_qnetworksession.cpp +HEADERS += ../../qbearertestcommon.h +TARGET = tst_qnetworksession +CONFIG += testcase + +QT = core network + +INCLUDEPATH += ../../../../src/bearer + +include(../../../../common.pri) +qtAddLibrary(QtBearer) + +wince* { + LACKEY.sources = $$OUTPUT_DIR/build/tests/bin/qnetworksessionlackey.exe + LACKEY.path = . + DEPLOYMENT += LACKEY +} + +symbian { + TARGET.CAPABILITY = NetworkServices NetworkControl ReadUserData +} diff --git a/tests/manual/bearerex/bearerex.cpp b/tests/manual/bearerex/bearerex.cpp new file mode 100644 index 0000000..68590cc --- /dev/null +++ b/tests/manual/bearerex/bearerex.cpp @@ -0,0 +1,565 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 "bearerex.h" + +#include + +Q_DECLARE_METATYPE(QNetworkConfiguration) + +BearerEx::BearerEx(QWidget* parent) + : QMainWindow(parent) +{ + setupUi(this); + + createMenus(); + + connect(&m_NetworkConfigurationManager, SIGNAL(updateCompleted()), this, SLOT(configurationsUpdateCompleted())); + connect(&m_NetworkConfigurationManager, SIGNAL(configurationAdded(const QNetworkConfiguration&)), + this, SLOT(configurationAdded(const QNetworkConfiguration&))); + connect(&m_NetworkConfigurationManager, SIGNAL(configurationRemoved(const QNetworkConfiguration&)), + this, SLOT(configurationRemoved(const QNetworkConfiguration&))); + connect(&m_NetworkConfigurationManager, SIGNAL(onlineStateChanged(bool)), + this, SLOT(onlineStateChanged(bool))); + connect(&m_NetworkConfigurationManager, SIGNAL(configurationChanged(const QNetworkConfiguration&)), + this, SLOT(configurationChanged(const QNetworkConfiguration&))); + showConfigurations(); +} + +void BearerEx::createMenus() +{ + QAction* act1 = new QAction(tr("Show Details"), this); + menuBar()->addAction(act1); + connect(act1, SIGNAL(triggered()), this, SLOT(on_showDetailsButton_clicked())); + + m_openAction = new QAction(tr("Open Session"), this); + menuBar()->addAction(m_openAction); + connect(m_openAction, SIGNAL(triggered()), this, SLOT(on_openSessionButton_clicked())); + + QAction* exitAct = new QAction(tr("Exit"), this); + menuBar()->addAction(exitAct); + connect(exitAct, SIGNAL(triggered()), this, SLOT(close())); +} + +void BearerEx::showConfigurations() +{ + listWidget->clear(); + QListWidgetItem* listItem; + + QNetworkConfiguration defaultConfig = m_NetworkConfigurationManager.defaultConfiguration(); + if (defaultConfig.type() == QNetworkConfiguration::UserChoice) { + listItem = new QListWidgetItem(); + QFont font = listItem->font(); + font.setBold(true); + font.setUnderline(true); + listItem->setFont(font); + listItem->setText(" UserChoice"); + listItem->setData(Qt::UserRole, qVariantFromValue(defaultConfig)); + listWidget->addItem(listItem); + } + + QList configurations = m_NetworkConfigurationManager.allConfigurations(); + for (int i=0; ifont(); + font.setBold(true); + font.setUnderline(true); + listItem->setFont(font); + } + listItem->setText(text); + listItem->setData(Qt::UserRole, qVariantFromValue(configurations[i])); + listWidget->addItem(listItem); + } +} + +void BearerEx::on_updateConfigurationsButton_clicked() +{ + m_NetworkConfigurationManager.updateConfigurations(); +} + +void BearerEx::on_updateListButton_clicked() +{ + showConfigurations(); +} + +void BearerEx::on_showDetailsButton_clicked() +{ + QListWidgetItem* item = listWidget->currentItem(); + if (!item) { + return; + } + + QNetworkConfiguration networkConfiguration = qVariantValue(item->data(Qt::UserRole)); + DetailedInfoDialog infoDialog(&networkConfiguration,this); + infoDialog.exec(); +} + +void BearerEx::on_createSessionButton_clicked() +{ + QListWidgetItem* item = listWidget->currentItem(); + if (!item) { + return; + } + QNetworkConfiguration networkConfiguration = qVariantValue(item->data(Qt::UserRole)); + int newTabIndex = mainTabWidget->count(); + SessionTab* newTab = new SessionTab(&networkConfiguration,&m_NetworkConfigurationManager,eventListWidget,newTabIndex-1); + QString label = QString("S")+QString::number(newTabIndex-1); + mainTabWidget->insertTab(newTabIndex,newTab,label); + mainTabWidget->setCurrentIndex(newTabIndex); +} + +void BearerEx::on_clearEventListButton_clicked() +{ + eventListWidget->clear(); +} + +void BearerEx::configurationAdded(const QNetworkConfiguration& config) +{ + QListWidgetItem* listItem = new QListWidgetItem(); + listItem->setText(QString("Added: ")+config.name()); + eventListWidget->addItem(listItem); +} + +void BearerEx::configurationRemoved(const QNetworkConfiguration& config) +{ + QListWidgetItem* listItem = new QListWidgetItem(); + listItem->setText(QString("Removed: ")+config.name()); + eventListWidget->addItem(listItem); +} + +void BearerEx::onlineStateChanged(bool isOnline) +{ + QListWidgetItem* listItem = new QListWidgetItem(); + QFont font = listItem->font(); + font.setBold(true); + listItem->setFont(font); + if (isOnline) { + listItem->setText(QString("> Online")); + } else { + listItem->setText(QString("< Offline")); + } + eventListWidget->addItem(listItem); +} + +void BearerEx::configurationChanged(const QNetworkConfiguration & config) +{ + QListWidgetItem* listItem = new QListWidgetItem(); + QString state; + switch (config.state()) + { + case QNetworkConfiguration::Undefined: + state = "Undef : "; + break; + case QNetworkConfiguration::Defined: + state = "Def : "; + break; + case QNetworkConfiguration::Discovered: + state = "Disc : "; + break; + case QNetworkConfiguration::Active: + state = "Act : "; + break; + } + listItem->setText(state+config.name()); + eventListWidget->addItem(listItem); +} + +void BearerEx::configurationsUpdateCompleted() +{ + QMessageBox msgBox; + msgBox.setStandardButtons(QMessageBox::Close); + msgBox.setText("Configurations update completed."); + msgBox.exec(); +} + +DetailedInfoDialog::DetailedInfoDialog(QNetworkConfiguration* apNetworkConfiguration, QWidget * parent) + : QDialog(parent) +{ + setupUi(this); + + tableWidget->setColumnCount(2); + int rowCount = 2; + + if (apNetworkConfiguration->type() == QNetworkConfiguration::ServiceNetwork) { + rowCount = rowCount + apNetworkConfiguration->children().count(); + } + + tableWidget->setRowCount(rowCount); + tableWidget->setColumnWidth(1,250); + tableWidget->setItem(0, 0, new QTableWidgetItem(tr("Name"))); + tableWidget->setItem(0, 1, new QTableWidgetItem(apNetworkConfiguration->name())); + tableWidget->setItem(1, 0, new QTableWidgetItem(tr("Id"))); + tableWidget->setItem(1, 1, new QTableWidgetItem(apNetworkConfiguration->identifier())); + if (apNetworkConfiguration->type() == QNetworkConfiguration::ServiceNetwork) { + for (int i=0; ichildren().count(); i++) { + tableWidget->setItem(i+2, 0, new QTableWidgetItem(QString("IAP")+QString::number(i+1))); + tableWidget->setItem(i+2, 1, new QTableWidgetItem(apNetworkConfiguration->children()[i].name())); + } + } + + tableWidget->setFocusPolicy(Qt::NoFocus); + +#ifdef Q_OS_SYMBIAN + this->showMaximized(); +#endif +} + +SessionTab::SessionTab(QNetworkConfiguration* apNetworkConfiguration, + QNetworkConfigurationManager* configManager, + QListWidget* eventListWidget, + int index, + BearerEx * parent) + : QWidget(parent), m_http(0), m_eventListWidget(eventListWidget), + m_index(index), m_httpRequestOngoing(false), m_alrEnabled (false) +{ + setupUi(this); + + m_ConfigManager = configManager; + m_NetworkSession = new QNetworkSession(*apNetworkConfiguration); + + // Update initial Session state to UI + newState(m_NetworkSession->state()); + + connect(m_NetworkSession, SIGNAL(newConfigurationActivated()), this, SLOT(newConfigurationActivated())); + connect(m_NetworkSession, SIGNAL(stateChanged(QNetworkSession::State)), + this, SLOT(stateChanged(QNetworkSession::State))); + connect(m_NetworkSession, SIGNAL(opened()), this, SLOT(opened())); + connect(m_NetworkSession, SIGNAL(closed()), this, SLOT(closed())); + connect(m_NetworkSession, SIGNAL(error(QNetworkSession::SessionError)), this, SLOT(error(QNetworkSession::SessionError))); + + if (apNetworkConfiguration->type() == QNetworkConfiguration::InternetAccessPoint) { + snapLabel->hide(); + snapLineEdit->hide(); + alrButton->hide(); + iapLineEdit->setText(apNetworkConfiguration->name()+" ("+apNetworkConfiguration->identifier()+")"); + } else if (apNetworkConfiguration->type() == QNetworkConfiguration::ServiceNetwork) { + snapLineEdit->setText(apNetworkConfiguration->name()+" ("+apNetworkConfiguration->identifier()+")"); + } + bearerLineEdit->setText(m_NetworkSession->bearerName()); + sentRecDataLineEdit->setText(QString::number(m_NetworkSession->bytesWritten())+ + QString(" / ")+ + QString::number(m_NetworkSession->bytesReceived())); + snapLineEdit->setFocusPolicy(Qt::NoFocus); + iapLineEdit->setFocusPolicy(Qt::NoFocus); + bearerLineEdit->setFocusPolicy(Qt::NoFocus); + sentRecDataLineEdit->setFocusPolicy(Qt::NoFocus); + stateLineEdit->setFocusPolicy(Qt::NoFocus); +} + +SessionTab::~SessionTab() +{ + delete m_NetworkSession; + delete m_http; +} + +void SessionTab::on_createQHttpButton_clicked() +{ + if (m_httpRequestOngoing) { + return; + } + + if (m_http) { + disconnect(m_http, 0, 0, 0); + delete m_http; + } + m_http = new QHttp(this); + createQHttpButton->setText("Recreate QHttp"); + connect(m_http, SIGNAL(done(bool)), this, SLOT(done(bool))); +} + +void SessionTab::on_sendRequestButton_clicked() +{ + if (m_http) { + QString urlstring("http://www.google.com"); + QUrl url(urlstring); + m_http->setHost(url.host(), QHttp::ConnectionModeHttp, url.port() == -1 ? 0 : url.port()); + m_http->get(urlstring); + m_httpRequestOngoing = true; + } else { + QMessageBox msgBox; + msgBox.setStandardButtons(QMessageBox::Close); + msgBox.setText("QHttp not created.\nCreate QHttp First."); + msgBox.exec(); + } +} + +void SessionTab::on_openSessionButton_clicked() +{ + m_NetworkSession->open(); + if (m_NetworkSession->isActive()) { + newState(m_NetworkSession->state()); + } +} + +void SessionTab::on_closeSessionButton_clicked() +{ + m_NetworkSession->close(); + if (!m_NetworkSession->isActive()) { + newState(m_NetworkSession->state()); + } +} + +void SessionTab::on_stopConnectionButton_clicked() +{ + m_NetworkSession->stop(); +} + +void SessionTab::on_alrButton_clicked() +{ + if (!m_alrEnabled) { + connect(m_NetworkSession, SIGNAL(preferredConfigurationChanged(const QNetworkConfiguration&, bool)), + this, SLOT(preferredConfigurationChanged(const QNetworkConfiguration&, bool))); + alrButton->setText("Disable ALR"); + m_alrEnabled = true; + } else { + disconnect(m_NetworkSession, SIGNAL(preferredConfigurationChanged(const QNetworkConfiguration&, bool)), 0, 0); + alrButton->setText("Enable ALR"); + m_alrEnabled = false; + } +} + +void SessionTab::on_deleteSessionButton_clicked() +{ + setWindowTitle("Bearer Example"); + delete this; +} + +void SessionTab::newConfigurationActivated() +{ + QMessageBox msgBox; + msgBox.setText("New configuration activated."); + msgBox.setInformativeText("Do you want to accept new configuration?"); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::Yes); + if (msgBox.exec() == QMessageBox::Yes) { + m_NetworkSession->accept(); + iapLineEdit->setText(m_config.name()+" ("+m_config.identifier()+")"); + } else { + m_NetworkSession->reject(); + } +} + +void SessionTab::preferredConfigurationChanged(const QNetworkConfiguration& config, bool /*isSeamless*/) +{ + m_config = config; + QMessageBox msgBox; + msgBox.setText("Roaming to new configuration."); + msgBox.setInformativeText("Do you want to migrate to "+config.name()+"?"); + msgBox.setStandardButtons(QMessageBox::Yes | QMessageBox::No); + msgBox.setDefaultButton(QMessageBox::Yes); + if (msgBox.exec() == QMessageBox::Yes) { + m_NetworkSession->migrate(); + } else { + m_NetworkSession->ignore(); + } +} + +void SessionTab::opened() +{ + QListWidgetItem* listItem = new QListWidgetItem(); + QFont font = listItem->font(); + font.setBold(true); + listItem->setFont(font); + listItem->setText(QString("S")+QString::number(m_index)+QString(" - ")+QString("Opened")); + m_eventListWidget->addItem(listItem); + + QVariant identifier = m_NetworkSession->property("ActiveConfigurationIdentifier"); + if (!identifier.isNull()) { + QString configId = identifier.toString(); + QNetworkConfiguration config = m_ConfigManager->configurationFromIdentifier(configId); + if (config.isValid()) { + iapLineEdit->setText(config.name()+" ("+config.identifier()+")"); + } + } + + if (m_NetworkSession->configuration().type() == QNetworkConfiguration::UserChoice) { + QVariant identifier = m_NetworkSession->property("UserChoiceConfigurationIdentifier"); + if (!identifier.isNull()) { + QString configId = identifier.toString(); + QNetworkConfiguration config = m_ConfigManager->configurationFromIdentifier(configId); + if (config.isValid() && (config.type() == QNetworkConfiguration::ServiceNetwork)) { + snapLineEdit->setText(config.name()); + } + } + } +} + +void SessionTab::closed() +{ + QListWidgetItem* listItem = new QListWidgetItem(); + QFont font = listItem->font(); + font.setBold(true); + listItem->setFont(font); + listItem->setText(QString("S")+QString::number(m_index)+QString(" - ")+QString("Closed")); + m_eventListWidget->addItem(listItem); +} + +QString SessionTab::stateString(QNetworkSession::State state) +{ + QString stateString; + switch (state) + { + case QNetworkSession::Invalid: + stateString = "Invalid"; + break; + case QNetworkSession::NotAvailable: + stateString = "NotAvailable"; + break; + case QNetworkSession::Connecting: + stateString = "Connecting"; + break; + case QNetworkSession::Connected: + stateString = "Connected"; + break; + case QNetworkSession::Closing: + stateString = "Closing"; + break; + case QNetworkSession::Disconnected: + stateString = "Disconnected"; + break; + case QNetworkSession::Roaming: + stateString = "Roaming"; + break; + } + return stateString; +} + +void SessionTab::stateChanged(QNetworkSession::State state) +{ + newState(state); + + QListWidgetItem* listItem = new QListWidgetItem(); + listItem->setText(QString("S")+QString::number(m_index)+QString(" - ")+stateString(state)); + m_eventListWidget->addItem(listItem); +} + +void SessionTab::newState(QNetworkSession::State state) +{ + if (state == QNetworkSession::Connected) { + QVariant identifier = m_NetworkSession->property("ActiveConfigurationIdentifier"); + if (!identifier.isNull()) { + QString configId = identifier.toString(); + QNetworkConfiguration config = m_ConfigManager->configurationFromIdentifier(configId); + if (config.isValid()) { + iapLineEdit->setText(config.name()+" ("+config.identifier()+")"); + } + } + } + + bearerLineEdit->setText(m_NetworkSession->bearerName()); + + QString active; + if (m_NetworkSession->isActive()) { + active = " (A)"; + } + stateLineEdit->setText(stateString(state)+active); +} + +void SessionTab::error(QNetworkSession::SessionError error) +{ + QListWidgetItem* listItem = new QListWidgetItem(); + QMessageBox msgBox; + msgBox.setStandardButtons(QMessageBox::Close); + + QString errorString; + switch (error) + { + case QNetworkSession::UnknownSessionError: + errorString = "UnknownSessionError"; + break; + case QNetworkSession::SessionAbortedError: + errorString = "SessionAbortedError"; + break; + case QNetworkSession::RoamingError: + errorString = "RoamingError"; + break; + case QNetworkSession::OperationNotSupportedError: + errorString = "OperationNotSupportedError"; + break; + case QNetworkSession::InvalidConfigurationError: + errorString = "InvalidConfigurationError"; + break; + } + listItem->setText(QString("S")+QString::number(m_index)+QString(" - ")+errorString); + m_eventListWidget->addItem(listItem); + + msgBox.setText(errorString); + msgBox.exec(); +} + +void SessionTab::done(bool error) +{ + m_httpRequestOngoing = false; + + QMessageBox msgBox; + msgBox.setStandardButtons(QMessageBox::Close); + if (error) { + msgBox.setText("HTTP request failed."); + } else { + QString result(m_http->readAll()); + msgBox.setText(QString("HTTP request finished successfully.\nReceived ")+QString::number(result.length())+QString(" bytes.")); + } + msgBox.exec(); + + sentRecDataLineEdit->setText(QString::number(m_NetworkSession->bytesWritten())+ + QString(" / ")+ + QString::number(m_NetworkSession->bytesReceived())); +} + +// End of file + diff --git a/tests/manual/bearerex/bearerex.h b/tests/manual/bearerex/bearerex.h new file mode 100644 index 0000000..f18180e --- /dev/null +++ b/tests/manual/bearerex/bearerex.h @@ -0,0 +1,138 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 ACCESSPOINTMANAGEREX_H +#define ACCESSPOINTMANAGEREX_H + +#include + +#include "ui_bearerex.h" +#include "ui_detailedinfodialog.h" +#include "ui_sessiondialog.h" + +#include "qnetworkconfigmanager.h" +#include "qnetworksession.h" +#include "xqlistwidget.h" + +class QHttp; +class SessionTab; + +QTM_USE_NAMESPACE + +class BearerEx : public QMainWindow, public Ui::BearerExMainWindow +{ + Q_OBJECT + +public: + BearerEx(QWidget* parent = 0); + void createMenus(); + void showConfigurations(); + +private Q_SLOTS: + void on_updateConfigurationsButton_clicked(); + void on_updateListButton_clicked(); + void on_showDetailsButton_clicked(); + void on_createSessionButton_clicked(); + void on_clearEventListButton_clicked(); + + void configurationsUpdateCompleted(); + void configurationAdded(const QNetworkConfiguration& config); + void configurationRemoved(const QNetworkConfiguration& config); + void onlineStateChanged(bool isOnline); + void configurationChanged(const QNetworkConfiguration & config); + +private: + QNetworkConfigurationManager m_NetworkConfigurationManager; + QAction* m_openAction; +}; + +class DetailedInfoDialog : public QDialog, public Ui::DetailedInfoDialog +{ + Q_OBJECT + +public: + DetailedInfoDialog(QNetworkConfiguration* apNetworkConfiguration = 0, QWidget* parent = 0); +}; + + +class SessionTab : public QWidget, public Ui::SessionTab +{ + Q_OBJECT + +public: + SessionTab(QNetworkConfiguration* apNetworkConfiguration = 0, QNetworkConfigurationManager* configManager = 0, + QListWidget* eventListWidget = 0, int index = 0, BearerEx* parent = 0); + ~SessionTab(); + + QString stateString(QNetworkSession::State state); + +private Q_SLOTS: + void on_createQHttpButton_clicked(); + void on_sendRequestButton_clicked(); + void on_openSessionButton_clicked(); + void on_closeSessionButton_clicked(); + void on_stopConnectionButton_clicked(); + void on_deleteSessionButton_clicked(); + void on_alrButton_clicked(); + void done(bool error); + + void newConfigurationActivated(); + void preferredConfigurationChanged(const QNetworkConfiguration& config, bool isSeamless); + void stateChanged(QNetworkSession::State state); + void newState(QNetworkSession::State state); + void opened(); + void closed(); + void error(QNetworkSession::SessionError error); + +private: //data + QHttp* m_http; + QNetworkSession* m_NetworkSession; + QNetworkConfigurationManager* m_ConfigManager; + QListWidget* m_eventListWidget; + QNetworkConfiguration m_config; + int m_index; + bool m_httpRequestOngoing; + bool m_alrEnabled; +}; + +#endif // ACCESSPOINTMANAGEREX_H + +// End of file + diff --git a/tests/manual/bearerex/bearerex.pro b/tests/manual/bearerex/bearerex.pro new file mode 100644 index 0000000..a870eb1 --- /dev/null +++ b/tests/manual/bearerex/bearerex.pro @@ -0,0 +1,34 @@ +TEMPLATE = app +TARGET = BearerEx + +QT += core \ + gui \ + network + +FORMS += sessiondialog.ui \ + bearerex.ui \ + detailedinfodialog.ui +include(../../common.pri) +#not really a test case but deployment happens same way +CONFIG += testcase + +DEPENDPATH += . +INCLUDEPATH += . \ + ../../src/bearer + +# Example headers and sources +HEADERS += bearerex.h \ + xqlistwidget.h + +SOURCES += bearerex.cpp \ + main.cpp \ + xqlistwidget.cpp + +symbian: { + bearerex.sources = Qtbearer.dll + bearerex.path = /sys/bin + DEPLOYMENT += bearerex + + TARGET.CAPABILITY = NetworkServices NetworkControl ReadUserData +} +qtAddLibrary(QtBearer) diff --git a/tests/manual/bearerex/bearerex.ui b/tests/manual/bearerex/bearerex.ui new file mode 100644 index 0000000..e5ab62f --- /dev/null +++ b/tests/manual/bearerex/bearerex.ui @@ -0,0 +1,95 @@ + + BearerExMainWindow + + + + 0 + 0 + 360 + 640 + + + + Bearer Example + + + + + + + + Main + + + + + + Network Configurations + + + Qt::AlignCenter + + + + + + + + + + + + Update Configs + + + + + + + Update List + + + + + + + Create Session + + + + + + + Show Details + + + + + + + + + + Events + + + + + + + + + Clear + + + + + + + + + + + + + diff --git a/tests/manual/bearerex/detailedinfodialog.ui b/tests/manual/bearerex/detailedinfodialog.ui new file mode 100644 index 0000000..c4a21fa --- /dev/null +++ b/tests/manual/bearerex/detailedinfodialog.ui @@ -0,0 +1,54 @@ + + DetailedInfoDialog + + + + 0 + 0 + 308 + 396 + + + + Bearer Example + + + + + + Detailed information + + + + + + + + + + QDialogButtonBox::Ok + + + + + + + + + buttonBox + accepted() + DetailedInfoDialog + accept() + + + 205 + 371 + + + 223 + 8 + + + + + diff --git a/tests/manual/bearerex/main.cpp b/tests/manual/bearerex/main.cpp new file mode 100644 index 0000000..e13a494 --- /dev/null +++ b/tests/manual/bearerex/main.cpp @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 + +#include "bearerex.h" + +int main(int argc, char* argv[]) +{ + QApplication app(argc, argv); + BearerEx bearerEx; +#ifdef Q_OS_SYMBIAN + bearerEx.showMaximized(); +#else + bearerEx.show(); +#endif + return app.exec(); +} + +// End of file + diff --git a/tests/manual/bearerex/sessiondialog.ui b/tests/manual/bearerex/sessiondialog.ui new file mode 100644 index 0000000..fcf2136 --- /dev/null +++ b/tests/manual/bearerex/sessiondialog.ui @@ -0,0 +1,139 @@ + + SessionTab + + + + + + + + SNAP + + + + + + + true + + + + + + + IAP + + + + + + + true + + + true + + + + + + + Bearer + + + + + + + true + + + + + + + Sent/Rec. + + + + + + + true + + + + + + + State + + + + + + + true + + + + + + + + + + + Open Session + + + + + + + Close Session + + + + + + + Stop Conn. + + + + + + + Create QHttp + + + + + + + Send Test Req. + + + + + + + Enable ALR + + + + + + + Delete Session + + + + + + + + + + diff --git a/tests/manual/bearerex/xqlistwidget.cpp b/tests/manual/bearerex/xqlistwidget.cpp new file mode 100644 index 0000000..0618725 --- /dev/null +++ b/tests/manual/bearerex/xqlistwidget.cpp @@ -0,0 +1,66 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 "xqlistwidget.h" + +XQListWidget::XQListWidget(QWidget* parent) : QListWidget(parent) +{ +} + +void XQListWidget::keyPressEvent(QKeyEvent* event) +{ + switch (event->key()) + { + case Qt::Key_Left: + { + focusPreviousChild(); + break; + } + case Qt::Key_Right: + { + focusNextChild(); + break; + } + default: + { + QListWidget::keyPressEvent(event); + } + } +} diff --git a/tests/manual/bearerex/xqlistwidget.h b/tests/manual/bearerex/xqlistwidget.h new file mode 100644 index 0000000..1053328 --- /dev/null +++ b/tests/manual/bearerex/xqlistwidget.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 XQLISTWIDGET_H +#define XQLISTWIDGET_H + +#include +#include + +class XQListWidget: public QListWidget +{ +public: + XQListWidget(QWidget* parent = 0); + +protected: + void keyPressEvent(QKeyEvent* event); +}; + +#endif // XQLISTWIDGET_H + + diff --git a/tests/manual/networkmanager/README b/tests/manual/networkmanager/README new file mode 100644 index 0000000..4bc7171 --- /dev/null +++ b/tests/manual/networkmanager/README @@ -0,0 +1,2 @@ +This application serves as prototype/test-bed for NetworkManager development. The excellent (non-existing) documentation +for the various NetworkManager interfaces makes this harder than it should be. diff --git a/tests/manual/networkmanager/dialog.ui b/tests/manual/networkmanager/dialog.ui new file mode 100644 index 0000000..1301908 --- /dev/null +++ b/tests/manual/networkmanager/dialog.ui @@ -0,0 +1,213 @@ + + + Dialog + + + + 0 + 0 + 919 + 657 + + + + Dialog + + + + + + + + Connections + + + + + + + + Path + + + + + State + + + + + Id + + + + + Settings + + + + + + + + + + + + Devices: + + + + + + + + Path + + + + + Managed + + + + + Interface + + + + + Driver + + + + + Type + + + + + State + + + + + IP4 Address + + + + + IP4 Config + + + + + Hostname + + + + + Domains + + + + + + + + + + Qt::Horizontal + + + + 908 + 20 + + + + + + + + true + + + + SSID + + + + + Strength + + + + + Wpa + + + + + Rsn + + + + + Freq + + + + + Hardware Address + + + + + Mode + + + + + Max Bitrate + + + + + + + + + + Start + + + + + + + Stop + + + + + + + Scan + + + + + + + Update + + + + + + + + + + diff --git a/tests/manual/networkmanager/networkmanager.pro b/tests/manual/networkmanager/networkmanager.pro new file mode 100644 index 0000000..31b2af1 --- /dev/null +++ b/tests/manual/networkmanager/networkmanager.pro @@ -0,0 +1,19 @@ +SOURCES += networkmanagertest.cpp nmview.cpp +HEADERS += nmview.h +TARGET = tst_networkmanagertest + +QT = core network dbus gui + +#not really a test case but deployment happens same way +CONFIG += testcase + +requires(contains(QT_CONFIG,dbus)) + +INCLUDEPATH += ../../src/bearer +include(../../common.pri) + +qtAddLibrary(QtBearer) + +#MOC_DIR = .moc +#OBJECTS_DIR = .obj +FORMS += dialog.ui diff --git a/tests/manual/networkmanager/networkmanagertest.cpp b/tests/manual/networkmanager/networkmanagertest.cpp new file mode 100644 index 0000000..a39b041 --- /dev/null +++ b/tests/manual/networkmanager/networkmanagertest.cpp @@ -0,0 +1,287 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "nmview.h" + +#include + +typedef QMap< QString, QMap > SettingsMap; +Q_DECLARE_METATYPE(SettingsMap) + +void printConnectionDetails(const QString& service) +{ + QDBusConnection dbc = QDBusConnection::systemBus(); + if (!dbc.isConnected()) { + qWarning() << "Unable to connect to D-Bus:" << dbc.lastError(); + return; + } + QDBusInterface allCons(service, NM_DBUS_PATH_SETTINGS, NM_DBUS_IFACE_SETTINGS, dbc); + if (allCons.isValid()) { + QDBusReply > reply = allCons.call("ListConnections"); + if ( reply.isValid() ) { + qWarning() << "Known connections:"; + QList list = reply.value(); + foreach(QDBusObjectPath path, list) { + qWarning() << " " << path.path(); + QDBusInterface sysIface(NM_DBUS_SERVICE_SYSTEM_SETTINGS, path.path(), NM_DBUS_IFACE_SETTINGS_CONNECTION, dbc); + if (sysIface.isValid()) { + QDBusMessage r = sysIface.call("GetSettings"); + QDBusReply< SettingsMap > rep = sysIface.call("GetSettings"); + qWarning() << " GetSettings:" << r.arguments() << r.signature() << rep.isValid() << sysIface.lastError(); + QMap< QString, QMap > map = rep.value(); + QList list = map.keys(); + foreach (QString key, list) { + QMap innerMap = map[key]; + qWarning() << " Key: " << key; + QMap::const_iterator i = innerMap.constBegin(); + while (i != innerMap.constEnd()) { + QString k = i.key(); + qWarning() << " Key: " << k << " Entry: " << i.value(); + if (k == "addresses" && i.value().canConvert()) { + QDBusArgument arg = i.value().value(); + arg.beginArray(); + while (!arg.atEnd()) { + QDBusVariant addr; + arg >> addr; + uint ip = addr.variant().toUInt(); + qWarning() << ip; + qWarning() << " " << QHostAddress(htonl(ip)).toString(); + } + + } + i++; + } + } + } + } + } + } + + +} + +void readConnectionManagerDetails() +{ + qDBusRegisterMetaType(); + QDBusConnection dbc = QDBusConnection::systemBus(); + if (!dbc.isConnected()) { + qWarning() << "Unable to connect to D-Bus:" << dbc.lastError(); + return; + } + + QDBusInterface iface(NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, dbc); + if (!iface.isValid()) { + qWarning() << "Could not find NetworkManager"; + return; + } + + uint state = iface.property("State").toUInt(); + switch(state) { + case NM_STATE_UNKNOWN: + qWarning() << "State: Unknown"; break; + case NM_STATE_ASLEEP: + qWarning() << "State: Asleep"; break; + case NM_STATE_CONNECTING: + qWarning() << "State: Connecting"; break; + case NM_STATE_CONNECTED: + qWarning() << "State: Connected"; break; + case NM_STATE_DISCONNECTED: + qWarning() << "State: Disconnected"; break; + } + //get list of network devices + QDBusReply > reply = iface.call("GetDevices"); + if ( reply.isValid() ) { + qWarning() << "Current devices:"; + QList list = reply.value(); + foreach(QDBusObjectPath path, list) { + qWarning() << " " << path.path(); + QDBusInterface devIface(NM_DBUS_SERVICE, path.path(), NM_DBUS_INTERFACE_DEVICE, dbc); + if (devIface.isValid()) { + qWarning() << " Managed: " << devIface.property("Managed").toBool(); + qWarning() << " Interface: " << devIface.property("Interface").toString(); + qWarning() << " HAL UDI: " << devIface.property("Udi").toString(); + qWarning() << " Driver: " << devIface.property("Driver").toString(); + QVariant v = devIface.property("DeviceType"); + switch(v.toUInt()) { + case DEVICE_TYPE_UNKNOWN: + qWarning() << " DeviceType: Unknown" ; + break; + case DEVICE_TYPE_802_3_ETHERNET: + qWarning() << " DeviceType: Ethernet" ; + break; + case DEVICE_TYPE_802_11_WIRELESS: + qWarning() << " DeviceType: Wireless" ; + break; + case DEVICE_TYPE_GSM: + qWarning() << " DeviceType: GSM" ; + break; + case DEVICE_TYPE_CDMA: + qWarning() << " DeviceType: CDMA" ; + break; + + } + v = devIface.property("State"); + switch(v.toUInt()) { + case NM_DEVICE_STATE_UNKNOWN: + qWarning() << " State: Unknown" ; break; + case NM_DEVICE_STATE_UNMANAGED: + qWarning() << " State: Unmanaged" ; break; + case NM_DEVICE_STATE_UNAVAILABLE: + qWarning() << " State: Unavailable" ; break; + case NM_DEVICE_STATE_DISCONNECTED: + qWarning() << " State: Disconnected" ; break; + case NM_DEVICE_STATE_PREPARE: + qWarning() << " State: Preparing" ; break; + case NM_DEVICE_STATE_CONFIG: + qWarning() << " State: Being configured" ; break; + case NM_DEVICE_STATE_NEED_AUTH: + qWarning() << " State: Awaiting secrets" ; break; + case NM_DEVICE_STATE_IP_CONFIG: + qWarning() << " State: IP requested" ; break; + case NM_DEVICE_STATE_ACTIVATED: + qWarning() << " State: Activated" ; break; + case NM_DEVICE_STATE_FAILED: + qWarning() << " State: FAILED" ; break; + } + quint32 ip = devIface.property("Ip4Address").toUInt(); + qWarning() << " IP4Address: " << QHostAddress(htonl(ip)).toString(); + if (v.toUInt() == NM_DEVICE_STATE_ACTIVATED) { + QString path = devIface.property("Ip4Config").value().path(); + qWarning() << " IP4Config: " << path; + QDBusInterface ipIface(NM_DBUS_SERVICE, path, NM_DBUS_INTERFACE_IP4_CONFIG, dbc); + if (ipIface.isValid()) { + qWarning() << " Hostname: " << ipIface.property("Hostname").toString(); + qWarning() << " Domains: " << ipIface.property("Domains").toStringList(); + qWarning() << " NisDomain: " << ipIface.property("NisDomain").toString(); + QDBusArgument arg= ipIface.property("Addresses").value(); + //qWarning() << " " << arg.currentType(); + qWarning() << " Addresses: " << ipIface.property("Addresses"); + qWarning() << " Nameservers: " << ipIface.property("Nameservers"); + qWarning() << " NisServers: " << ipIface.property("NisServers"); + } + + } + + } + } + } + + //get list of active connections + QVariant prop = iface.property("ActiveConnections"); + QList connections = prop.value >(); + QString activePath; + if ( connections.count() ) + qWarning() << "Active connections:"; + foreach(QDBusObjectPath path, connections) { + qWarning() << " " << path.path(); + activePath = path.path(); + QString serviceName; + QDBusInterface conIface(NM_DBUS_SERVICE, path.path(), NM_DBUS_INTERFACE_ACTIVE_CONNECTION, dbc); + if (conIface.isValid()) { + qWarning() << " default connection: " << conIface.property("Default").toBool(); + serviceName = conIface.property("ServiceName").toString(); + qWarning() << " service name: " << serviceName; + qWarning() << " connection path: " << conIface.property("Connection").value().path(); + qWarning() << " specific object:" << conIface.property("SpecificObject").value().path(); + qWarning() << " sharedServiceName: " << conIface.property("SharedServiceName").toString(); + QList devs = conIface.property("Devices").value >(); + qWarning() << " devices: "; + foreach(QDBusObjectPath p, devs) + qWarning() << " " << path.path(); + QVariant v = conIface.property("State"); + switch (v.toInt()) { + case NM_ACTIVE_CONNECTION_STATE_UNKNOWN: + qWarning()<< " State: unknown"; break; + case NM_ACTIVE_CONNECTION_STATE_ACTIVATING: + qWarning()<< " State: activating"; break; + case NM_ACTIVE_CONNECTION_STATE_ACTIVATED: + qWarning()<< " State: activated"; break; + } + } else { + qWarning() << conIface.lastError(); + } + + } + + printConnectionDetails(NM_DBUS_SERVICE_SYSTEM_SETTINGS); + printConnectionDetails(NM_DBUS_SERVICE_USER_SETTINGS); + + + //turn active connection off + /*QDBusObjectPath dbop("/org/freedesktop/NetworkManager/ActiveConnection/1"); + QVariant asd = QVariant::fromValue(dbop); + iface.call(QLatin1String("DeactivateConnection"), asd); + qWarning() << iface.lastError();*/ + + /*QDBusObjectPath p1device("/org/freedesktop/Hal/devices/net_00_60_6e_82_02_65"); + QVariant p1v = QVariant::fromValue(p1device); + QDBusObjectPath p1con("/org/freedesktop/NetworkManagerSettings/0"); + QVariant p1c = QVariant::fromValue(p1con); + QDBusObjectPath p1sp(""); + QVariant p1sp1 = QVariant::fromValue(p1sp); + iface.call(QLatin1String("ActivateConnection"), + QString("/org/freedesktop/NetworkManagerSystemSettings"), p1c,p1v, p1v ); + qWarning() << iface.lastError(); + */ +} + +int main( int argc, char** argv) +{ + QApplication app(argc, argv); + //readConnectionManagerDetails(); + QMainWindow main; + NMView view; + main.setCentralWidget(&view); + main.show(); + return app.exec(); + +} diff --git a/tests/manual/networkmanager/nmview.cpp b/tests/manual/networkmanager/nmview.cpp new file mode 100644 index 0000000..ca9d907 --- /dev/null +++ b/tests/manual/networkmanager/nmview.cpp @@ -0,0 +1,1030 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 "nmview.h" + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +//#include "ui_dialog.h" + +#include +#include +#include +#include + +//static QDBusConnection dbc = QDBusConnection::systemBus(); +//typedef QMap< QString, QMap > SettingsMap; +//Q_DECLARE_METATYPE(SettingsMap) + + +NMView::NMView(QDialog* parent) + : QDialog(parent, 0), dbc(QDBusConnection::systemBus()) +{ + init(); + + if (!dbc.isConnected()) { + qWarning() << "Unable to connect to D-Bus:" << dbc.lastError(); + return; + } + updateConnections(); + getDevices(); +} + +NMView::~NMView() +{ +} +void NMView::init() +{ + setupUi(this); + sess = 0; +// readSettings(); + connect(startButton, SIGNAL(clicked()), this, SLOT(activate())); + connect(stopButton, SIGNAL(clicked()), this, SLOT(deactivate())); + connect(scanButton, SIGNAL(clicked()), this, SLOT(findAccessPoints())); + connect(updateButton, SIGNAL(clicked()), this, SLOT(update())); + + connect(cons, SIGNAL(itemActivated(QTreeWidgetItem*, int)), + this,SLOT(connectionItemActivated(QTreeWidgetItem*, int))); + + + connect(devicesTreeWidget, SIGNAL(itemActivated(QTreeWidgetItem*, int)), + this, SLOT(deviceItemActivated(QTreeWidgetItem*, int))); + + cons->header()->setResizeMode(QHeaderView::ResizeToContents); + devicesTreeWidget->header()->setResizeMode(QHeaderView::ResizeToContents); + accessPointsTreeWidget->header()->setResizeMode(QHeaderView::ResizeToContents); +// accessPointsTreeWidget->header()->setResizeMode(QHeaderView::ResizeToContents); + + manager = new QNetworkConfigurationManager(this); + + connect(manager, SIGNAL(updateCompleted()), this, SLOT(updateCompleted())); + + connect(manager, SIGNAL(configurationAdded(const QNetworkConfiguration &)), + this, SLOT(configurationAdded(const QNetworkConfiguration&))); + + devicesTreeWidget->header()->hideSection(0); + devicesTreeWidget->header()->hideSection(1); + devicesTreeWidget->header()->hideSection(3); + devicesTreeWidget->header()->hideSection(5); + devicesTreeWidget->header()->hideSection(6); + devicesTreeWidget->header()->hideSection(7); + devicesTreeWidget->header()->hideSection(8); + devicesTreeWidget->header()->hideSection(9); +} + +void NMView::updateConnections() +{ + cons->clear(); + manager->updateConfigurations(); + QList configs = manager->allConfigurations(); + foreach(QNetworkConfiguration p, configs) { + QStringList strlist; + strlist << p.name(); + strlist << stateToString(p.state()); + strlist << p.identifier(); + strlist << typeToString(p.type()); + QTreeWidgetItem *item; + item = new QTreeWidgetItem(strlist); + cons->insertTopLevelItem(0, item); + } + cons->sortItems ( 1, Qt::AscendingOrder); +} + +void NMView::getActiveConnections() +{ + QList configs = manager->allConfigurations(QNetworkConfiguration::Active); + foreach(QNetworkConfiguration p, configs) { + qWarning() << __FUNCTION__ << p.name() << p.identifier(); + } + +// QDBusInterface iface(NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, dbc); +// if (!iface.isValid()) { +// qWarning() << "Could not find NetworkManager"; +// return; +// } + +// QVariant prop = iface.property("ActiveConnections"); +// QList connections = prop.value >(); +// foreach(QDBusObjectPath path, connections) { +// QDBusInterface conDetails(NM_DBUS_SERVICE, path.path(), NM_DBUS_INTERFACE_ACTIVE_CONNECTION, dbc); +// if (conDetails.isValid()) { +// QString desc = path.path(); +// conDetails.property("Connection Path").value().path(); + +// QList devices = conDetails.property("Devices").value >(); +// +// foreach(QDBusObjectPath devpath, devices) { +// QDBusInterface devIface(NM_DBUS_SERVICE, devpath.path(), NM_DBUS_INTERFACE_DEVICE, dbc); +// desc += " "+devIface.property("Interface").toString(); +// desc += " "+QHostAddress(htonl(devIface.property("Ip4Address").toUInt())).toString(); + +// } + +// qWarning() << conDetails.property("Connection").value().path() << path.path(); + +// QListWidgetItem* item = new QListWidgetItem(desc, activeCons); +// item->setData(Qt::UserRole, path.path()); +// } +// } +} + +void NMView::update() +{ +// if(sess) +// qWarning() << __FUNCTION__<< sess->bytesWritten() << sess->bearerName(); +// QNetworkManagerInterface *dbIface; +// dbIface = new QNetworkManagerInterface; +// QList connections = dbIface->activeConnections(); +// +// foreach(QDBusObjectPath conpath, connections) { +// QNetworkManagerConnectionActive *aConn; +// aConn = new QNetworkManagerConnectionActive(conpath.path()); +// // in case of accesspoint, specificObject will hold the accessPOintObjectPath +// qWarning() << aConn->connection().path() << aConn->specificObject().path() << aConn->devices().count(); +// QList devs = aConn->devices(); +// foreach(QDBusObjectPath device, devs) { +// qWarning() << " " << device.path(); +// } +// } + + QStringList connectionServices; + connectionServices << NM_DBUS_SERVICE_SYSTEM_SETTINGS; + connectionServices << NM_DBUS_SERVICE_USER_SETTINGS; + foreach (QString service, connectionServices) { + QDBusInterface allCons(service, + NM_DBUS_PATH_SETTINGS, + NM_DBUS_IFACE_SETTINGS, + dbc); + if (allCons.isValid()) { + QDBusReply > reply = allCons.call("ListConnections"); + if ( reply.isValid() ) { + QList list = reply.value(); + foreach(QDBusObjectPath path, list) { + QDBusInterface sysIface(service, + path.path(), + NM_DBUS_IFACE_SETTINGS_CONNECTION, + dbc); + if (sysIface.isValid()) { + qWarning() << ""; + qWarning() << path.path(); + + // QDBusMessage r = sysIface.call("GetSettings"); + QDBusReply< QNmSettingsMap > rep = sysIface.call("GetSettings"); + + QMap< QString, QMap > map = rep.value(); + QList list = map.keys(); + foreach (QString key, list) { + QMap innerMap = map[key]; + qWarning() << " Key: " << key; + QMap::const_iterator i = innerMap.constBegin(); + + while (i != innerMap.constEnd()) { + QString k = i.key(); + qWarning() << " Key: " << k << " Entry: " << i.value(); + i++; + }//end innerMap + }//end foreach key + }//end settings connection + } // foreach path + } //end ListConnections + } //end settingsInterface + }// end services + QDBusInterface iface(NM_DBUS_SERVICE, + NM_DBUS_PATH, + NM_DBUS_INTERFACE, + dbc); + if (iface.isValid()) { + QVariant prop = iface.property("ActiveConnections"); + QList connections = prop.value >(); + foreach(QDBusObjectPath conpath, connections) { + qWarning() << "Active connection" << conpath.path(); + QDBusInterface conDetails(NM_DBUS_SERVICE, + conpath.path(), + NM_DBUS_INTERFACE_ACTIVE_CONNECTION, + dbc); + if (conDetails.isValid()) { + + QVariant prop = conDetails.property("Connection"); + QDBusObjectPath connection = prop.value(); + qWarning() << conDetails.property("Default").toBool() << connection.path(); + +// QVariant Sprop = conDetails.property("Devices"); +// QList so = Sprop.value >(); +// foreach(QDBusObjectPath device, so) { +// if(device.path() == devicePath) { +// path = connection.path(); +// } +// break; +// } + } + } + } +qWarning() << ""; +} + +void NMView::deactivate() +{ + QList configs = manager->allConfigurations(QNetworkConfiguration::Active); + foreach(QNetworkConfiguration p, configs) { + qWarning() << "Active cons" << p.name(); + if(p.name() == cons->currentItem()->text(0) + && p.identifier() == cons->currentItem()->text(2)) { + qWarning() <<__FUNCTION__<< p.name(); + if(!sess) { + sess = new QNetworkSession(p); + + connect(sess, SIGNAL(stateChanged(QNetworkSession::State)), + this, SLOT(stateChanged(QNetworkSession::State))); + + connect(sess, SIGNAL(error(QNetworkSession::SessionError)), + this, SLOT(networkSessionError(QNetworkSession::SessionError))); + } + sess->close(); + delete sess; + sess = 0; + } + } +} + +void NMView::activate() +{ + qWarning() << __FUNCTION__ << cons->currentItem()->text(0); + + QList configs = manager->allConfigurations(); + foreach(QNetworkConfiguration p, configs) { + if(p.name() == cons->currentItem()->text(0)) { + + sess = new QNetworkSession(p); + + connect(sess, SIGNAL(newConfigurationActivated()), + this, SLOT(getActiveConnections())); + + connect(sess, SIGNAL(stateChanged(QNetworkSession::State)), + this, SLOT(stateChanged(QNetworkSession::State))); + + connect(sess, SIGNAL(error(QNetworkSession::SessionError)), + this, SLOT(networkSessionError(QNetworkSession::SessionError))); + + sess->open(); + } + } +} + +void NMView::getDevices() +{ + qWarning() << ""; + qWarning() << __FUNCTION__; + devicesTreeWidget->clear(); + //qDBusRegisterMetaType(); + + if (!dbc.isConnected()) { + qWarning() << "Unable to connect to D-Bus:" << dbc.lastError(); + return; + } + QDBusInterface iface(NM_DBUS_SERVICE, + NM_DBUS_PATH, + NM_DBUS_INTERFACE, + dbc); +//NetworkManager interface + if (!iface.isValid()) { + qWarning() << "Could not find NetworkManager"; + return; + } + +// uint state = iface.property("State").toUInt(); +// switch(state) { +// case NM_STATE_UNKNOWN: +// qWarning() << "State: Unknown"; break; +// case NM_STATE_ASLEEP: +// qWarning() << "State: Asleep"; break; +// case NM_STATE_CONNECTING: +// qWarning() << "State: Connecting"; break; +// case NM_STATE_CONNECTED: +// qWarning() << "State: Connected"; break; +// case NM_STATE_DISCONNECTED: +// qWarning() << "State: Disconnected"; break; +// } + + //get list of network devices + QTreeWidgetItem *item; + QDBusReply > reply = iface.call("GetDevices"); + if ( reply.isValid() ) { +// qWarning() << "Current devices:"; + QList list = reply.value(); + foreach(QDBusObjectPath path, list) { + QStringList devicesList; + qWarning() << " " << path.path(); + devicesList << path.path(); + + QDBusInterface devIface(NM_DBUS_SERVICE, + path.path(), + NM_DBUS_INTERFACE_DEVICE, + dbc); + if (devIface.isValid()) { + + + + ////// connect the dbus signal +// /*if(*/dbc.connect(NM_DBUS_SERVICE, +// path.path(), +// NM_DBUS_INTERFACE_DEVICE, +// "StateChanged", +// this,SLOT(deviceStateChanged(quint32))); +// { +// qWarning() << "XXXXXXXXXX dbus connect successful" << path.path(); +// } + + + // qWarning() << " Managed: " << devIface.property("Managed").toBool(); + devicesList << devIface.property("Managed").toString(); + // qWarning() << " Interface: " << devIface.property("Interface").toString(); + devicesList << devIface.property("Interface").toString(); + // qWarning() << " HAL UDI: " << devIface.property("Udi").toString(); + // qWarning() << " Driver: " << devIface.property("Driver").toString(); + devicesList << devIface.property("Driver").toString(); + + QString x = deviceTypeToString(devIface.property("DeviceType").toUInt()); + // qWarning() << " Type:" << x; + devicesList << x; + + if( devIface.property("DeviceType").toUInt() == DEVICE_TYPE_802_11_WIRELESS) { + qWarning() << "Device is WIFI"; + // // findAccessPoints(path.path()); + } + + QVariant v = devIface.property("State"); + x = deviceStateToString(v.toUInt()); +// qWarning() << " State:" << x; + devicesList << x; + + quint32 ip = devIface.property("Ip4Address").toUInt(); +// qWarning() << " IP4Address: " << QHostAddress(htonl(ip)).toString(); + devicesList << QHostAddress(htonl(ip)).toString(); + + + if (v.toUInt() == NM_DEVICE_STATE_ACTIVATED) { + QString path = devIface.property("Ip4Config").value().path(); +// qWarning() << " IP4Config: " << path; + devicesList << path; + QDBusInterface ipIface(NM_DBUS_SERVICE, + path, + NM_DBUS_INTERFACE_IP4_CONFIG, + dbc); + if (ipIface.isValid()) { + // qWarning() << " Hostname: " << ipIface.property("Hostname").toString(); + devicesList << ipIface.property("Hostname").toString(); +// qWarning() << " Domains: " << ipIface.property("Domains").toStringList(); + devicesList << ipIface.property("Domains").toStringList().join(", "); +// qWarning() << " NisDomain: " << ipIface.property("NisDomain").toString(); + QDBusArgument arg= ipIface.property("Addresses").value(); +// qWarning() << " Addresses: " << ipIface.property("Addresses"); +// qWarning() << " Nameservers: " << ipIface.property("Nameservers"); +// qWarning() << " NisServers: " << ipIface.property("NisServers"); + } + + } + + } + item = new QTreeWidgetItem(devicesList); + devicesTreeWidget->insertTopLevelItem(0, item); + } + } + + +// netconfig(); + +} + +void NMView::readSettings() +{ + QDBusInterface settingsiface(NM_DBUS_SERVICE_SYSTEM_SETTINGS, + NM_DBUS_PATH_SETTINGS, + NM_DBUS_IFACE_SETTINGS, + dbc); + //NetworkManagerSettings interface + if (settingsiface.isValid()) { + QDBusReply > reply = settingsiface.call("ListConnections"); + if ( reply.isValid() ) { + QList list = reply.value(); + foreach(QDBusObjectPath path, list) { + qWarning() <<__FUNCTION__ << path.path(); + + } + } + } + + QDBusInterface iface(NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, dbc); + if (!iface.isValid()) { + qWarning() << "Could not find NetworkManager"; + return; + } + + // QStringList list = item->text().split(" -> "); + + QVariant prop = iface.property("ActiveConnections"); + QList connections = prop.value >(); + foreach(QDBusObjectPath path, connections) { + QDBusInterface conDetails(NM_DBUS_SERVICE, + path.path(), + NM_DBUS_INTERFACE_ACTIVE_CONNECTION, + dbc); + + if (conDetails.isValid()) { + QString desc = path.path(); + qWarning() << desc; + //if ( item->text(0) == conDetails.property("Connection").value().path() ) { + // QListWidgetItem* item = new QTreeWidgetItem( desc, + // cons); + // item->setData(Qt::UserRole, desc); + // activeItemActivated( item ); + //} + } + } +} + +void NMView::printConnectionDetails(const QString& service) +{ + Q_UNUSED(service); + +// +// qWarning() << __FUNCTION__ << service; +// +// QDBusConnection dbc = QDBusConnection::systemBus(); +// if (!dbc.isConnected()) { +// qWarning() << "Unable to connect to D-Bus:" << dbc.lastError(); +// return; +// } +// QDBusInterface allCons(service, +// NM_DBUS_PATH_SETTINGS, +// NM_DBUS_IFACE_SETTINGS, +// dbc); +// +// if (allCons.isValid()) { +// QDBusReply > reply = allCons.call("ListConnections"); +// +// if ( reply.isValid() ) { +// qWarning() << "Known connections:"; +// QList list = reply.value(); +// +// foreach(QDBusObjectPath path, list) { +// qWarning() << " " << path.path(); +// +// QDBusInterface sysIface(NM_DBUS_SERVICE_SYSTEM_SETTINGS, +// path.path(), +// NM_DBUS_IFACE_SETTINGS_CONNECTION, +// dbc); +// +// if (sysIface.isValid()) { +// QDBusMessage r = sysIface.call("GetSettings"); +// QDBusReply< QSettingsMap > rep = sysIface.call("GetSettings"); +// +// qWarning() << " GetSettings:" << r.arguments() << r.signature() << rep.isValid() << sysIface.lastError(); +// +// QMap< QString, QMap > map = rep.value(); +// QList list = map.keys(); +// +// foreach (QString key, list) { +// QMap innerMap = map[key]; +// qWarning() << " Key: " << key; +// QMap::const_iterator i = innerMap.constBegin(); +// +// while (i != innerMap.constEnd()) { +// QString k = i.key(); +// qWarning() << " Key: " << k << " Entry: " << i.value(); +// +// if (k == "addresses" && i.value().canConvert()) { +// QDBusArgument arg = i.value().value(); +// arg.beginArray(); +// +// while (!arg.atEnd()) { +// QDBusVariant addr; +// arg >> addr; +// uint ip = addr.variant().toUInt(); +// qWarning() << ip; +// qWarning() << " " << QHostAddress(htonl(ip)).toString(); +// } +// +// } +// i++; +// } +// } +// } +// } +// } +// } + qWarning() << ""; +} + +void NMView::getNetworkDevices() +{ + +} + +void NMView::connectionItemActivated( QTreeWidgetItem * item, int col ) +{ + Q_UNUSED(col); + + qWarning() <<__FUNCTION__<< item->text(0); + QDBusInterface iface(NM_DBUS_SERVICE, + NM_DBUS_PATH, + NM_DBUS_INTERFACE, + dbc); + if (!iface.isValid()) { + qWarning() << "Could not find NetworkManager"; + return; + } + QVariant prop = iface.property("ActiveConnections"); + QList connections = prop.value >(); + foreach(QDBusObjectPath path, connections) { + QDBusInterface conDetails(NM_DBUS_SERVICE, + path.path(), + NM_DBUS_INTERFACE_ACTIVE_CONNECTION, + dbc); + + if (conDetails.isValid()) { + QString desc = path.path(); + qWarning() << desc; + if ( item->text(0) == conDetails.property("Connection").value().path() ) { +// QListWidgetItem* item = new QTreeWidgetItem( desc, +// cons); +// item->setData(Qt::UserRole, desc); +// activeItemActivated( item ); + } + } + } +} + + + +void NMView::deviceItemActivated( QTreeWidgetItem * item , int section) +{ + Q_UNUSED(item); + Q_UNUSED(section); + + // qWarning() << item->text(section) << item->text(4); + //if(item->text(4) == "Wireless") findAccessPoints(item->text(0)); +} + + +void NMView::netconfig() +{ +// qWarning() << __FUNCTION__; + +// qDBusRegisterMetaType(); + QDBusConnection dbc = QDBusConnection::systemBus(); + if (!dbc.isConnected()) { + qWarning() << "Unable to connect to D-Bus:" << dbc.lastError(); + return; + } + + QDBusInterface iface(NM_DBUS_SERVICE, + NM_DBUS_PATH, + NM_DBUS_IFACE_SETTINGS_CONNECTION, + dbc); + if (!iface.isValid()) { + qWarning() << "Could not find NetworkManager Settings"; + return; + } else { + QDBusReply > reply = iface.call("ListConnections"); + QList list = reply.value(); +// qWarning() << reply.value(); + foreach(QDBusObjectPath path, list) { + qWarning() << " " << path.path(); + } + } +} + + +void NMView::findAccessPoints() +{ + accessPointsTreeWidget->clear(); + + QDBusInterface iface(NM_DBUS_SERVICE, + NM_DBUS_PATH, + NM_DBUS_INTERFACE, + dbc); + + QDBusReply > reply = iface.call("GetDevices"); + if ( reply.isValid() ) { + QList list = reply.value(); + foreach(QDBusObjectPath path, list) { + QDBusInterface devIface(NM_DBUS_SERVICE, + path.path(), + NM_DBUS_INTERFACE_DEVICE, + dbc); + if (devIface.isValid()) { + + if( devIface.property("DeviceType").toUInt() == DEVICE_TYPE_802_11_WIRELESS) { + +// qWarning() <<"deviface"<< devIface.path(); + QDBusInterface wififace(NM_DBUS_SERVICE, + devIface.path(), + NM_DBUS_INTERFACE_DEVICE_WIRELESS, + dbc); + if (!wififace.isValid()) { + qWarning() << "Could not find NetworkManager wireless interface"; + return; + } + +///////////////////////// +// if(dbc.connect(NM_DBUS_SERVICE, +// path.path(), +// NM_DBUS_INTERFACE_DEVICE_WIRELESS, +// "PropertiesChanged", +// this,SLOT(aPPropertiesChanged( QMap))) ) { +// qWarning() << "PropertiesChanged connect"; +// } else { +// qWarning() << "NOT connect"; + +// } +///////////////////////// + qWarning() <<"wififace"<< wififace.path(); + QDBusReply > reply2 = wififace.call("GetAccessPoints"); + if ( reply2.isValid() ) { + QTreeWidgetItem *item; + QList list2 = reply2.value(); + foreach(QDBusObjectPath path2, list2) { + QDBusInterface accessPointIface(NM_DBUS_SERVICE, + path2.path(), + NM_DBUS_INTERFACE_ACCESS_POINT, + dbc); + if (accessPointIface.isValid()) { +//// qWarning() <<"path2" << path2.path(); + +// if(dbc.connect(NM_DBUS_SERVICE, //signal strength +// path2.path(), +// NM_DBUS_INTERFACE_ACCESS_POINT, +// "PropertiesChanged", +// this,SLOT(aPPropertiesChanged( QMap))) ) { +// qWarning() << "PropertiesChanged connect"; +// } else { +// qWarning() << "NOT connect"; +// +// } + + QStringList accessPoints; + accessPoints << accessPointIface.property("Ssid").toString(); + accessPoints << QString::number(accessPointIface.property("Strength").toInt()); + accessPoints << securityCapabilitiesToString(accessPointIface.property("WpaFlags" ).toInt()); + accessPoints << securityCapabilitiesToString(accessPointIface.property("RsnFlags" ).toInt()); + accessPoints << accessPointIface.property("Frequency" ).toString(); + accessPoints << accessPointIface.property("HwAddress" ).toString(); + accessPoints << deviceModeToString(accessPointIface.property("Mode" ).toInt()); + accessPoints << accessPointIface.property("MaxBitrate" ).toString(); + //HwAddress + // if(accessPointIface.property("Flags" ).toInt() == NM_802_11_AP_FLAGS_PRIVACY ) { + // qWarning() << "Secure"; + // } + item = new QTreeWidgetItem(accessPoints); + accessPointsTreeWidget->insertTopLevelItem(0, item); + } + } + } + } + } + } + } +} + +QString NMView::deviceStateToString(int state) +{ + QString ret; + switch(state) { + case NM_DEVICE_STATE_UNKNOWN: + ret = "Unknown"; + break; + case NM_DEVICE_STATE_UNMANAGED: + ret = "Unmanaged"; + break; + case NM_DEVICE_STATE_UNAVAILABLE: + ret = "Unavailable"; + break; + case NM_DEVICE_STATE_DISCONNECTED: + ret = "Disconnected"; + break; + case NM_DEVICE_STATE_PREPARE: + ret = "Preparing to connect"; + break; + case NM_DEVICE_STATE_CONFIG: + ret = "Being configured"; + break; + case NM_DEVICE_STATE_NEED_AUTH: + ret = "Awaiting secrets"; + break; + case NM_DEVICE_STATE_IP_CONFIG: + ret = "IP requested"; + break; + case NM_DEVICE_STATE_ACTIVATED: + ret = "Activated"; + break; + case NM_DEVICE_STATE_FAILED: + ret = "FAILED"; + break; + }; + return ret; +} + +QString NMView::deviceTypeToString(int device) +{ + QString ret; + switch(device) { + case DEVICE_TYPE_UNKNOWN: + ret = "Unknown"; + break; + case DEVICE_TYPE_802_3_ETHERNET: + ret = "Ethernet"; + break; + case DEVICE_TYPE_802_11_WIRELESS: + ret = "Wireless"; + break; + case DEVICE_TYPE_GSM: + ret = "GSM"; + break; + case DEVICE_TYPE_CDMA: + ret = "CDMA"; + break; + }; + return ret; +} + +QString NMView::securityCapabilitiesToString(int caps) +{ + int check = caps; +// qWarning() << __FUNCTION__<< caps; + QString ret; + if( check == 0 ) + ret += "None."; + if( (check & NM_802_11_AP_SEC_PAIR_WEP40)) + ret += " 40-bit WEP encryption. "; + if( (check & NM_802_11_AP_SEC_PAIR_WEP104) ) + ret += " 104-bit WEP encryption. "; + if( (check & NM_802_11_AP_SEC_PAIR_TKIP) ) + ret += " TKIP encryption. "; + if( (check & NM_802_11_AP_SEC_PAIR_CCMP) ) + ret += " CCMP encryption. "; + if( (check & NM_802_11_AP_SEC_GROUP_WEP40)) + ret += " 40-bit WEP cipher. "; + if( (check & NM_802_11_AP_SEC_GROUP_WEP104)) + ret += " 104-bit WEP cipher. "; + if( (check & NM_802_11_AP_SEC_GROUP_TKIP) ) + ret += " TKIP cipher. "; + if( (check & NM_802_11_AP_SEC_GROUP_CCMP) ) + ret += " CCMP cipher. "; + if( (check & NM_802_11_AP_SEC_KEY_MGMT_PSK)) + ret += " PSK key management. "; + if( (check & NM_802_11_AP_SEC_KEY_MGMT_802_1X) ) + ret += " 802.1x key management. "; + return ret; +} + +QString NMView::deviceModeToString(int mode) +{ + QString ret; + switch (mode) { + case NM_802_11_MODE_UNKNOWN: + ret = "Unknown"; + break; + case NM_802_11_MODE_ADHOC: + ret = " (Adhoc)."; + break; + case NM_802_11_MODE_INFRA: + ret = " (Infrastructure)"; + }; + return ret; +} + +void NMView::netManagerState(quint32 state) +{ + qWarning() << __FUNCTION__ << state;// << old << reason; + switch(state) { + case NM_STATE_UNKNOWN: + qWarning() << "The NetworkManager daemon is in an unknown state. "; + break; + case NM_STATE_ASLEEP: + qWarning() << "The NetworkManager daemon is asleep and all interfaces managed by it are inactive. "; + break; + case NM_STATE_CONNECTING: + qWarning() << "The NetworkManager daemon is connecting a device. FIXME: What does this mean when one device is active and another is connecting? "; + break; + case NM_STATE_CONNECTED: + qWarning() <<"The NetworkManager daemon is connected. "; + break; + case NM_STATE_DISCONNECTED: + qWarning() << "The NetworkManager daemon is disconnected."; + break; + + }; +} + +void NMView::deviceStateChanged(quint32 state) +{ + qWarning() << __FUNCTION__ << state; + switch(state) { + case NM_DEVICE_STATE_UNKNOWN : + qWarning() <<"The device is in an unknown state. "; + break; + case NM_DEVICE_STATE_UNMANAGED: + qWarning() <<"The device is not managed by NetworkManager."; + break; + case NM_DEVICE_STATE_UNAVAILABLE: + qWarning() <<"The device cannot be used (carrier off, rfkill, etc)."; + break; + case NM_DEVICE_STATE_DISCONNECTED: + qWarning() <<"The device is not connected."; + break; + case NM_DEVICE_STATE_PREPARE: + qWarning() <<"The device is preparing to connect."; + break; + case NM_DEVICE_STATE_CONFIG: + qWarning() <<"The device is being configured."; + break; + case NM_DEVICE_STATE_NEED_AUTH: + qWarning() <<"The device is awaiting secrets necessary to continue connection."; + break; + case NM_DEVICE_STATE_IP_CONFIG: + qWarning() <<"The IP settings of the device are being requested and configured."; + break; + case NM_DEVICE_STATE_ACTIVATED: + qWarning() <<"The device is active."; + break; + case NM_DEVICE_STATE_FAILED: + qWarning() <<"The device is in a failure state following an attempt to activate it."; + break; + }; +} + +void NMView::updateCompleted() +{ + qWarning() << __FUNCTION__; +} + +void NMView::newConfigurationActivated() +{ + qWarning() << __FUNCTION__; + getActiveConnections(); +} + +void NMView::stateChanged(QNetworkSession::State state) +{ + // QString stateStringstr; + switch (state) { + case QNetworkSession::Invalid: + stateString = "Invalid session"; + break; + case QNetworkSession::NotAvailable: + stateString = "Session is defined but not yet discovered"; + break; + case QNetworkSession::Connecting: + stateString = "Session is being established"; + break; + case QNetworkSession::Connected: + stateString = "Session is active and can be used for socket operations"; + cons->currentItem()->setText(1, "Active"); + break; + case QNetworkSession::Closing: + stateString = "Session is being shutdown"; + break; + case QNetworkSession::Disconnected: + qWarning() << __FUNCTION__; + manager->updateConfigurations(); + stateString = "Session disconnected"; + cons->currentItem()->setText(1,"Discovered") ; + break; + case QNetworkSession::Roaming: + stateString = "session is roaming from one AP to another"; + break; + }; + qWarning() << __FUNCTION__ << state << stateString; +} + +QString NMView::stateToString(int state) +{ + switch (state) { + case QNetworkConfiguration::Undefined: + return "Undefined"; + break; + case QNetworkConfiguration::Defined: + return "Defined"; + break; + case QNetworkConfiguration::Discovered: + return "Discovered"; + break; + case QNetworkConfiguration::Active: + return "Active"; + break; + }; + return ""; +} + +void NMView::configurationAdded(const QNetworkConfiguration &config) +{ + qWarning() << __FUNCTION__<< config.name() << config.identifier(); +} + +QString NMView::typeToString(int type) +{ + switch(type) { + case QNetworkConfiguration::InternetAccessPoint: + return "Internet AccessPoint"; + break; + case QNetworkConfiguration::ServiceNetwork: + return "Service Network"; + break; + }; + return QString(); +} + +void NMView::aPPropertiesChanged( QMap map) +{ + //QMap::const_iterator iterator = d->values.find(type + QLatin1String("Path")) + QMapIterator i(map); + while (i.hasNext()) { + i.next(); + if( i.key() == "State") { + qWarning() << __FUNCTION__ << i.key() << ": " << i.value().toUInt(); +// deviceStateChanged(i.value().toUInt()); + } else if( i.key() == "ActiveAccessPoint") { + qWarning() << __FUNCTION__ << i.key() << ": " << i.value().value().path(); + } else if( i.key() == "Strength") + qWarning() << __FUNCTION__ << i.key() << ": " << i.value().toUInt(); + else + qWarning() << __FUNCTION__ << i.key() << ": " << i.value(); + } +} + +void NMView::networkSessionError(QNetworkSession::SessionError error) +{ + QString errorStr; + switch(error) { + case QNetworkSession::RoamingError: + errorStr = "Roaming error"; + break; + case QNetworkSession::SessionAbortedError: + errorStr = "Session aborted by user or system"; + break; + default: + case QNetworkSession::UnknownSessionError: + errorStr = "Unidentified Error"; + break; + }; + + QMessageBox::warning(this, tr("NMView"), errorStr, QMessageBox::Ok); +} diff --git a/tests/manual/networkmanager/nmview.h b/tests/manual/networkmanager/nmview.h new file mode 100644 index 0000000..641385e --- /dev/null +++ b/tests/manual/networkmanager/nmview.h @@ -0,0 +1,107 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 +#include +#include +#include +#include + +#include "ui_dialog.h" + +QTM_USE_NAMESPACE + +class QListWidget; +class QTreeWidget; +class QTreeWidgetItem; + +class NMView : public QDialog, private Ui::Dialog +{ + Q_OBJECT +public: + NMView(QDialog* parent = 0); + virtual ~NMView(); + +private: + void init(); + QString stateString; + + QDBusConnection dbc; + void printConnectionDetails(const QString&); + + QString deviceStateToString(int state); + QString deviceTypeToString(int device); + QString securityCapabilitiesToString(int caps); + QString deviceModeToString(int mode); +//QDBusInterface getInterface(); + QNetworkConfigurationManager *manager; + QNetworkSession *sess; + QString stateToString(int state); + QString typeToString(int type); + +private slots: + void update(); + void deactivate(); + void activate(); + void getActiveConnections(); + void updateConnections(); + void getDevices(); + // void readConnectionManagerDetails(); + void getNetworkDevices(); + void connectionItemActivated( QTreeWidgetItem *, int); +// void activeItemActivated( QListWidgetItem *); + void deviceItemActivated( QTreeWidgetItem *, int); + void netconfig(); + void findAccessPoints(); + + void netManagerState(quint32); + void readSettings(); + void updateCompleted(); + void newConfigurationActivated(); + + void stateChanged(QNetworkSession::State); + void deviceStateChanged(quint32 state); + + void configurationAdded(const QNetworkConfiguration &config); + void aPPropertiesChanged( QMap map); + void networkSessionError(QNetworkSession::SessionError); + +}; diff --git a/tests/manual/networkmanager/startdlg.cpp b/tests/manual/networkmanager/startdlg.cpp new file mode 100644 index 0000000..4720932 --- /dev/null +++ b/tests/manual/networkmanager/startdlg.cpp @@ -0,0 +1,95 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 "startdlg.h" +#include + + +StartDialog::StartDialog(QWidget * parent) + :QDialog(parent) +{ + QVBoxLayout *layout = new QVBoxLayout(this); + box = new QComboBox(); + layout->addWidget(box); + + QHBoxLayout* hbox = new QHBoxLayout(); + QPushButton* start = new QPushButton("Start"); + connect(start, SIGNAL(clicked()), this, SLOT(accept())); + QPushButton* cancel = new QPushButton("Cancel"); + connect(cancel, SIGNAL(clicked()), this, SLOT(reject())); + + + hbox->addWidget(start); + hbox->addWidget(cancel); + + layout->addLayout(hbox); + + QDBusConnection dbc = QDBusConnection::systemBus(); + if (!dbc.isConnected()) { + qWarning() << "Unable to connect to D-Bus:" << dbc.lastError(); + return; + } + QDBusInterface iface(NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, dbc); + if (!iface.isValid()) { + qWarning() << "Could not find NetworkManager"; + return; + } + QDBusReply > reply = iface.call("GetDevices"); + if ( reply.isValid() ) { + QList list = reply.value(); + foreach(QDBusObjectPath path, list) { + QDBusInterface devIface(NM_DBUS_SERVICE, path.path(), NM_DBUS_INTERFACE_DEVICE, dbc); + if ( devIface.isValid() ) { + box->addItem(devIface.property("Interface").toString(), QVariant(path.path())); + } + } + } +} + +QString StartDialog::device() const +{ + return dev; +} + +void StartDialog::accept() +{ + dev = box->itemData(box->currentIndex(), Qt::UserRole).toString(); + QDialog::accept(); +} diff --git a/tests/manual/networkmanager/startdlg.h b/tests/manual/networkmanager/startdlg.h new file mode 100644 index 0000000..a9f1e7c --- /dev/null +++ b/tests/manual/networkmanager/startdlg.h @@ -0,0 +1,58 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the Qt Mobility Components. +** +** $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 +#include +#include + +class StartDialog : public QDialog +{ + Q_OBJECT +public: + StartDialog(QWidget* parent = 0); + + QString device() const; + +public slots: + void accept(); +private: + QString dev; + QComboBox* box; +}; -- cgit v0.12