summaryrefslogtreecommitdiffstats
path: root/src/plugins/bearer/symbian
diff options
context:
space:
mode:
authorQt by Nokia <qt-info@nokia.com>2011-04-27 12:05:43 +0200
committeraxis <qt-info@nokia.com>2011-04-27 12:05:43 +0200
commit38be0d13830efd2d98281c645c3a60afe05ffece (patch)
tree6ea73f3ec77f7d153333779883e8120f82820abe /src/plugins/bearer/symbian
Initial import from the monolithic Qt.
This is the beginning of revision history for this module. If you want to look at revision history older than this, please refer to the Qt Git wiki for how to use Git history grafting. At the time of writing, this wiki is located here: http://qt.gitorious.org/qt/pages/GitIntroductionWithQt If you have already performed the grafting and you don't see any history beyond this commit, try running "git log" with the "--follow" argument. Branched from the monolithic repo, Qt master branch, at commit 896db169ea224deb96c59ce8af800d019de63f12
Diffstat (limited to 'src/plugins/bearer/symbian')
-rw-r--r--src/plugins/bearer/symbian/3_1/3_1.pro9
-rw-r--r--src/plugins/bearer/symbian/3_2/3_2.pro17
-rw-r--r--src/plugins/bearer/symbian/main.cpp88
-rw-r--r--src/plugins/bearer/symbian/qnetworksession_impl.cpp1549
-rw-r--r--src/plugins/bearer/symbian/qnetworksession_impl.h237
-rw-r--r--src/plugins/bearer/symbian/symbian.pri32
-rw-r--r--src/plugins/bearer/symbian/symbian.pro8
-rw-r--r--src/plugins/bearer/symbian/symbian_3/symbian_3.pro21
-rw-r--r--src/plugins/bearer/symbian/symbianengine.cpp1409
-rw-r--r--src/plugins/bearer/symbian/symbianengine.h246
10 files changed, 3616 insertions, 0 deletions
diff --git a/src/plugins/bearer/symbian/3_1/3_1.pro b/src/plugins/bearer/symbian/3_1/3_1.pro
new file mode 100644
index 0000000000..b7c6aef913
--- /dev/null
+++ b/src/plugins/bearer/symbian/3_1/3_1.pro
@@ -0,0 +1,9 @@
+include(../symbian.pri)
+
+is_using_gnupoc {
+ LIBS += -lapengine
+} else {
+ LIBS += -lAPEngine
+}
+TARGET = $${TARGET}_3_1
+TARGET.UID3 = 0x2002131C
diff --git a/src/plugins/bearer/symbian/3_2/3_2.pro b/src/plugins/bearer/symbian/3_2/3_2.pro
new file mode 100644
index 0000000000..ac3b3f898f
--- /dev/null
+++ b/src/plugins/bearer/symbian/3_2/3_2.pro
@@ -0,0 +1,17 @@
+include(../symbian.pri)
+
+symbian {
+ contains(S60_VERSION, 3.1) {
+ is_using_gnupoc {
+ LIBS += -lapengine
+ } else {
+ LIBS += -lAPEngine
+ }
+ } else {
+ DEFINES += SNAP_FUNCTIONALITY_AVAILABLE
+ LIBS += -lcmmanager
+ }
+}
+
+TARGET = $${TARGET}_3_2
+TARGET.UID3 = 0x2002131D
diff --git a/src/plugins/bearer/symbian/main.cpp b/src/plugins/bearer/symbian/main.cpp
new file mode 100644
index 0000000000..4506a0bcf2
--- /dev/null
+++ b/src/plugins/bearer/symbian/main.cpp
@@ -0,0 +1,88 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "symbianengine.h"
+
+#include <QtNetwork/private/qbearerplugin_p.h>
+
+#include <QtCore/qdebug.h>
+
+#ifndef QT_NO_BEARERMANAGEMENT
+
+QT_BEGIN_NAMESPACE
+
+class QSymbianEnginePlugin : public QBearerEnginePlugin
+{
+public:
+ QSymbianEnginePlugin();
+ ~QSymbianEnginePlugin();
+
+ QStringList keys() const;
+ QBearerEngine *create(const QString &key) const;
+};
+
+QSymbianEnginePlugin::QSymbianEnginePlugin()
+{
+}
+
+QSymbianEnginePlugin::~QSymbianEnginePlugin()
+{
+}
+
+QStringList QSymbianEnginePlugin::keys() const
+{
+ return QStringList() << QLatin1String("symbian");
+}
+
+QBearerEngine *QSymbianEnginePlugin::create(const QString &key) const
+{
+ if (key == QLatin1String("symbian"))
+ return new SymbianEngine;
+ else
+ return 0;
+}
+
+Q_EXPORT_STATIC_PLUGIN(QSymbianEnginePlugin)
+Q_EXPORT_PLUGIN2(qsymbianbearer, QSymbianEnginePlugin)
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_BEARERMANAGEMENT
diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp
new file mode 100644
index 0000000000..a9bd4146dc
--- /dev/null
+++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp
@@ -0,0 +1,1549 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnetworksession_impl.h"
+#include "symbianengine.h"
+
+#include <es_enum.h>
+#include <es_sock.h>
+#include <in_sock.h>
+#include <private/qcore_symbian_p.h>
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+#include <cmmanager.h>
+#endif
+
+#if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE)
+#include <extendedconnpref.h>
+#endif
+
+#ifndef QT_NO_BEARERMANAGEMENT
+
+QT_BEGIN_NAMESPACE
+
+QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine)
+: engine(engine), iSocketServ(qt_symbianGetSocketServer()),
+ ipConnectionNotifier(0), ipConnectionStarter(0),
+ iHandleStateNotificationsFromManager(false), iFirstSync(true), iStoppedByUser(false),
+ iClosedByUser(false), iError(QNetworkSession::UnknownSessionError), iALREnabled(0),
+ iConnectInBackground(false), isOpening(false)
+{
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ iMobility = NULL;
+#endif
+
+ TRAP_IGNORE(iConnectionMonitor.ConnectL());
+}
+
+void QNetworkSessionPrivateImpl::closeHandles()
+{
+ QMutexLocker lock(&mutex);
+ // Cancel Connection Progress Notifications first.
+ // Note: ConnectionNotifier must be destroyed before RConnection::Close()
+ // => deleting ipConnectionNotifier results RConnection::CancelProgressNotification()
+ delete ipConnectionNotifier;
+ ipConnectionNotifier = NULL;
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ // mobility monitor must be deleted before RConnection is closed
+ delete iMobility;
+ iMobility = NULL;
+#endif
+
+ // Cancel possible RConnection::Start() - may call RConnection::Close if Start was in progress
+ delete ipConnectionStarter;
+ ipConnectionStarter = 0;
+ //close any open connection (note Close twice is safe in case Cancel did it above)
+ iConnection.Close();
+
+ QSymbianSocketManager::instance().setDefaultConnection(0);
+
+ iConnectionMonitor.Close();
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this)
+ << " - handles closed";
+#endif
+
+}
+
+QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl()
+{
+ isOpen = false;
+ isOpening = false;
+
+ closeHandles();
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this)
+ << " - destroyed";
+#endif
+}
+
+void QNetworkSessionPrivateImpl::configurationStateChanged(quint32 accessPointId, quint32 connMonId, QNetworkSession::State newState)
+{
+ if (iHandleStateNotificationsFromManager) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "configurationStateChanged from manager for IAP : " << QString::number(accessPointId)
+ << "connMon ID : " << QString::number(connMonId) << " : to a state: " << newState
+ << "whereas my current state is: " << state;
+#else
+ Q_UNUSED(connMonId);
+#endif
+ this->newState(newState, accessPointId);
+ }
+}
+
+void QNetworkSessionPrivateImpl::configurationRemoved(QNetworkConfigurationPrivatePointer config)
+{
+ if (!publicConfig.isValid())
+ return;
+
+ TUint32 publicNumericId =
+ toSymbianConfig(privateConfiguration(publicConfig))->numericIdentifier();
+
+ if (toSymbianConfig(config)->numericIdentifier() == publicNumericId) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "configurationRemoved IAP: " << QString::number(publicNumericId) << " : going to State: Invalid";
+#endif
+ this->newState(QNetworkSession::Invalid, publicNumericId);
+ }
+}
+
+void QNetworkSessionPrivateImpl::configurationAdded(QNetworkConfigurationPrivatePointer config)
+{
+ Q_UNUSED(config);
+ // If session is based on service network, some other app may create new access points
+ // to the SNAP --> synchronize session's state with that of interface's.
+ if (!publicConfig.isValid() || publicConfig.type() != QNetworkConfiguration::ServiceNetwork)
+ return;
+
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "configurationAdded IAP: "
+ << toSymbianConfig(config)->numericIdentifier();
+#endif
+
+ syncStateWithInterface();
+}
+
+// Function sets the state of the session to match the state
+// of the underlying interface (the configuration this session is based on)
+void QNetworkSessionPrivateImpl::syncStateWithInterface()
+{
+ if (!publicConfig.isValid())
+ return;
+
+ if (iFirstSync) {
+ QObject::connect(engine,
+ SIGNAL(configurationStateChanged(quint32,quint32,QNetworkSession::State)),
+ this,
+ SLOT(configurationStateChanged(quint32,quint32,QNetworkSession::State)));
+ // Listen to configuration removals, so that in case the configuration
+ // this session is based on is removed, session knows to enter Invalid -state.
+ QObject::connect(engine, SIGNAL(configurationRemoved(QNetworkConfigurationPrivatePointer)),
+ this, SLOT(configurationRemoved(QNetworkConfigurationPrivatePointer)));
+ // Connect to configuration additions, so that in case a configuration is added
+ // in a SNAP this session is based on, the session knows to synch its state with its
+ // interface.
+ QObject::connect(engine, SIGNAL(configurationAdded(QNetworkConfigurationPrivatePointer)),
+ this, SLOT(configurationAdded(QNetworkConfigurationPrivatePointer)));
+ }
+ // Start listening IAP state changes from QNetworkConfigurationManagerPrivate
+ iHandleStateNotificationsFromManager = true;
+
+ // Check what is the state of the configuration this session is based on
+ // and set the session in appropriate state.
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "syncStateWithInterface() state of publicConfig is: " << publicConfig.state();
+#endif
+ switch (publicConfig.state()) {
+ case QNetworkConfiguration::Active:
+ newState(QNetworkSession::Connected);
+ break;
+ case QNetworkConfiguration::Discovered:
+ newState(QNetworkSession::Disconnected);
+ break;
+ case QNetworkConfiguration::Defined:
+ newState(QNetworkSession::NotAvailable);
+ break;
+ case QNetworkConfiguration::Undefined:
+ default:
+ newState(QNetworkSession::Invalid);
+ }
+}
+
+#ifndef QT_NO_NETWORKINTERFACE
+QNetworkInterface QNetworkSessionPrivateImpl::interface(TUint iapId) const
+{
+ QString interfaceName;
+
+ TSoInetInterfaceInfo ifinfo;
+ TPckg<TSoInetInterfaceInfo> ifinfopkg(ifinfo);
+ TSoInetIfQuery ifquery;
+ TPckg<TSoInetIfQuery> ifquerypkg(ifquery);
+
+ // Open dummy socket for interface queries
+ RSocket socket;
+ TInt retVal = socket.Open(iSocketServ, _L("udp"));
+ if (retVal != KErrNone) {
+ return QNetworkInterface();
+ }
+
+ // Start enumerating interfaces
+ socket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl);
+ while(socket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, ifinfopkg) == KErrNone) {
+ ifquery.iName = ifinfo.iName;
+ TInt err = socket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, ifquerypkg);
+ if(err == KErrNone && ifquery.iZone[1] == iapId) { // IAP ID is index 1 of iZone
+ if(ifinfo.iAddress.Address() > 0) {
+ interfaceName = QString::fromUtf16(ifinfo.iName.Ptr(),ifinfo.iName.Length());
+ break;
+ }
+ }
+ }
+
+ socket.Close();
+
+ if (interfaceName.isEmpty()) {
+ return QNetworkInterface();
+ }
+
+ return QNetworkInterface::interfaceFromName(interfaceName);
+}
+#endif
+
+#ifndef QT_NO_NETWORKINTERFACE
+QNetworkInterface QNetworkSessionPrivateImpl::currentInterface() const
+{
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "currentInterface() requested, state: " << state
+ << "publicConfig validity: " << publicConfig.isValid();
+ if (activeInterface.isValid())
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "interface is: " << activeInterface.humanReadableName();
+#endif
+
+ if (!publicConfig.isValid() || state != QNetworkSession::Connected) {
+ return QNetworkInterface();
+ }
+
+ return activeInterface;
+}
+#endif
+
+QVariant QNetworkSessionPrivateImpl::sessionProperty(const QString& key) const
+{
+ if (key == "ConnectInBackground") {
+ return QVariant(iConnectInBackground);
+ }
+ return QVariant();
+}
+
+void QNetworkSessionPrivateImpl::setSessionProperty(const QString& key, const QVariant& value)
+{
+ // Valid value means adding property, invalid means removing it.
+ if (key == "ConnectInBackground") {
+ if (value.isValid()) {
+ iConnectInBackground = value.toBool();
+ } else {
+ iConnectInBackground = EFalse;
+ }
+ }
+}
+
+QString QNetworkSessionPrivateImpl::errorString() const
+{
+ switch (iError) {
+ case QNetworkSession::UnknownSessionError:
+ return tr("Unknown session error.");
+ case QNetworkSession::SessionAbortedError:
+ return tr("The session was aborted by the user or system.");
+ case QNetworkSession::OperationNotSupportedError:
+ return tr("The requested operation is not supported by the system.");
+ case QNetworkSession::InvalidConfigurationError:
+ return tr("The specified configuration cannot be used.");
+ case QNetworkSession::RoamingError:
+ return tr("Roaming was aborted or is not possible.");
+ }
+
+ return QString();
+}
+
+QNetworkSession::SessionError QNetworkSessionPrivateImpl::error() const
+{
+ return iError;
+}
+
+void QNetworkSessionPrivateImpl::open()
+{
+ QMutexLocker lock(&mutex);
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "open() called, session state is: " << state << " and isOpen is: "
+ << isOpen << isOpening;
+#endif
+
+ if (isOpen || isOpening)
+ return;
+
+ isOpening = true;
+
+ // Stop handling IAP state change signals from QNetworkConfigurationManagerPrivate
+ // => RConnection::ProgressNotification will be used for IAP/SNAP monitoring
+ iHandleStateNotificationsFromManager = false;
+
+ // Configuration may have been invalidated after session creation by platform
+ // (e.g. configuration has been deleted).
+ if (!publicConfig.isValid()) {
+ newState(QNetworkSession::Invalid);
+ iError = QNetworkSession::InvalidConfigurationError;
+ emit QNetworkSessionPrivate::error(iError);
+ return;
+ }
+ // If opening a undefined configuration, session emits error and enters
+ // NotAvailable -state. Note that we will try ones in 'defined' state to avoid excessive
+ // need for WLAN scans (via updateConfigurations()), because user may have walked
+ // into a WLAN range, but periodic background scan has not occurred yet -->
+ // we don't want to force application to make frequent updateConfigurations() calls
+ // to be able to try if e.g. home WLAN is available.
+ if (publicConfig.state() == QNetworkConfiguration::Undefined) {
+ newState(QNetworkSession::NotAvailable);
+ iError = QNetworkSession::InvalidConfigurationError;
+ emit QNetworkSessionPrivate::error(iError);
+ return;
+ }
+ // Clear possible previous states
+ iStoppedByUser = false;
+ iClosedByUser = false;
+
+ Q_ASSERT(!iConnection.SubSessionHandle());
+ TInt error = iConnection.Open(iSocketServ);
+ if (error != KErrNone) {
+ // Could not open RConnection
+ newState(QNetworkSession::Invalid);
+ iError = QNetworkSession::UnknownSessionError;
+ emit QNetworkSessionPrivate::error(iError);
+ syncStateWithInterface();
+ return;
+ }
+
+ // Use RConnection::ProgressNotification for IAP/SNAP monitoring
+ // (<=> ConnectionProgressNotifier uses RConnection::ProgressNotification)
+ if (!ipConnectionNotifier) {
+ ipConnectionNotifier = new ConnectionProgressNotifier(*this,iConnection);
+ }
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StartNotifications();
+ }
+
+ if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
+ SymbianNetworkConfigurationPrivate *symbianConfig =
+ toSymbianConfig(privateConfiguration(publicConfig));
+
+#if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE)
+ // With One Click Connectivity (Symbian^3 onwards) it is possible
+ // to connect silently, without any popups.
+ TConnPrefList pref;
+ TExtendedConnPref prefs;
+
+ prefs.SetIapId(symbianConfig->numericIdentifier());
+ if (iConnectInBackground) {
+ prefs.SetNoteBehaviour( TExtendedConnPref::ENoteBehaviourConnSilent );
+ }
+ pref.AppendL(&prefs);
+#else
+ TCommDbConnPref pref;
+ pref.SetDialogPreference(ECommDbDialogPrefDoNotPrompt);
+
+ pref.SetIapId(symbianConfig->numericIdentifier());
+#endif
+ if (!ipConnectionStarter) {
+ ipConnectionStarter = new ConnectionStarter(*this, iConnection);
+ ipConnectionStarter->Start(pref);
+ }
+ // Avoid flip flop of states if the configuration is already
+ // active. IsOpen/opened() will indicate when ready.
+ if (state != QNetworkSession::Connected) {
+ newState(QNetworkSession::Connecting);
+ }
+ } else if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
+ SymbianNetworkConfigurationPrivate *symbianConfig =
+ toSymbianConfig(privateConfiguration(publicConfig));
+
+#if defined(OCC_FUNCTIONALITY_AVAILABLE) && defined(SNAP_FUNCTIONALITY_AVAILABLE)
+ // On Symbian^3 if service network is not reachable, it triggers a UI (aka EasyWLAN) where
+ // user can create new IAPs. To detect this, we need to store the number of IAPs
+ // there was before connection was started.
+ iKnownConfigsBeforeConnectionStart = engine->accessPointConfigurationIdentifiers();
+ TConnPrefList snapPref;
+ TExtendedConnPref prefs;
+ prefs.SetSnapId(symbianConfig->numericIdentifier());
+ if (iConnectInBackground) {
+ prefs.SetNoteBehaviour( TExtendedConnPref::ENoteBehaviourConnSilent );
+ }
+ snapPref.AppendL(&prefs);
+#else
+ TConnSnapPref snapPref(symbianConfig->numericIdentifier());
+#endif
+ if (!ipConnectionStarter) {
+ ipConnectionStarter = new ConnectionStarter(*this, iConnection);
+ ipConnectionStarter->Start(snapPref);
+ }
+ // Avoid flip flop of states if the configuration is already
+ // active. IsOpen/opened() will indicate when ready.
+ if (state != QNetworkSession::Connected) {
+ newState(QNetworkSession::Connecting);
+ }
+ } else if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ iKnownConfigsBeforeConnectionStart = engine->accessPointConfigurationIdentifiers();
+ if (!ipConnectionStarter) {
+ ipConnectionStarter = new ConnectionStarter(*this, iConnection);
+ ipConnectionStarter->Start();
+ }
+ newState(QNetworkSession::Connecting);
+ }
+
+ if (error != KErrNone) {
+ isOpen = false;
+ isOpening = false;
+ iError = QNetworkSession::UnknownSessionError;
+ emit QNetworkSessionPrivate::error(iError);
+ closeHandles();
+ syncStateWithInterface();
+ }
+}
+
+TUint QNetworkSessionPrivateImpl::iapClientCount(TUint aIAPId) const
+{
+ TRequestStatus status;
+ TUint connectionCount;
+ iConnectionMonitor.GetConnectionCount(connectionCount, status);
+ User::WaitForRequest(status);
+ if (status.Int() == KErrNone) {
+ for (TUint i = 1; i <= connectionCount; i++) {
+ TUint connectionId;
+ TUint subConnectionCount;
+ iConnectionMonitor.GetConnectionInfo(i, connectionId, subConnectionCount);
+ TUint apId;
+ iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
+ User::WaitForRequest(status);
+ if (apId == aIAPId) {
+ TConnMonClientEnumBuf buf;
+ iConnectionMonitor.GetPckgAttribute(connectionId, 0, KClientInfo, buf, status);
+ User::WaitForRequest(status);
+ if (status.Int() == KErrNone) {
+ return buf().iCount;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+void QNetworkSessionPrivateImpl::close(bool allowSignals)
+{
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "close() called, session state is: " << state << " and isOpen is : "
+ << isOpen;
+#endif
+
+ if (!isOpen && state != QNetworkSession::Connecting) {
+ return;
+ }
+ // Mark this session as closed-by-user so that we are able to report
+ // distinguish between stop() and close() state transitions
+ // when reporting.
+ iClosedByUser = true;
+ isOpen = false;
+ isOpening = false;
+
+ serviceConfig = QNetworkConfiguration();
+
+ closeHandles();
+
+ // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate
+ iHandleStateNotificationsFromManager = true;
+
+ // If UserChoice, go down immediately. If some other configuration,
+ // go down immediately if there is no reports expected from the platform;
+ // in practice Connection Monitor is aware of connections only after
+ // KFinishedSelection event, and hence reports only after that event, but
+ // that does not seem to be trusted on all Symbian versions --> safest
+ // to go down.
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice || state == QNetworkSession::Connecting) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "going disconnected right away, since either UserChoice or Connecting";
+#endif
+ newState(QNetworkSession::Closing);
+ newState(QNetworkSession::Disconnected);
+ }
+ if (allowSignals) {
+ emit closed();
+ }
+}
+
+void QNetworkSessionPrivateImpl::stop()
+{
+ QMutexLocker lock(&mutex);
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "stop() called, session state is: " << state << " and isOpen is : "
+ << isOpen;
+#endif
+ if (!isOpen &&
+ publicConfig.isValid() &&
+ publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "since session is not open, using RConnectionMonitor to stop() the interface";
+#endif
+ iStoppedByUser = true;
+ // If the publicConfig is type of IAP, enumerate through connections at
+ // connection monitor. If publicConfig is active in that list, stop it.
+ // Otherwise there is nothing to stop. Note: because this QNetworkSession is not open,
+ // activeConfig is not usable.
+ TUint count;
+ TRequestStatus status;
+ iConnectionMonitor.GetConnectionCount(count, status);
+ User::WaitForRequest(status);
+ if (status.Int() != KErrNone) {
+ return;
+ }
+ TUint numSubConnections; // Not used but needed by GetConnectionInfo i/f
+ TUint connectionId;
+ for (TUint i = 1; i <= count; ++i) {
+ // Get (connection monitor's assigned) connection ID
+ TInt ret = iConnectionMonitor.GetConnectionInfo(i, connectionId, numSubConnections);
+ if (ret == KErrNone) {
+ SymbianNetworkConfigurationPrivate *symbianConfig =
+ toSymbianConfig(privateConfiguration(publicConfig));
+
+ // See if connection Id matches with our Id. If so, stop() it.
+ if (symbianConfig->connectionIdentifier() == connectionId) {
+ ret = iConnectionMonitor.SetBoolAttribute(connectionId,
+ 0, // subConnectionId don't care
+ KConnectionStop,
+ ETrue);
+ }
+ }
+ // Enter disconnected state right away since the session is not even open.
+ // Symbian^3 connection monitor does not emit KLinkLayerClosed when
+ // connection is stopped via connection monitor.
+ newState(QNetworkSession::Disconnected);
+ }
+ } else if (isOpen) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "since session is open, using RConnection to stop() the interface";
+#endif
+ // Since we are open, use RConnection to stop the interface
+ isOpen = false;
+ isOpening = false;
+ iStoppedByUser = true;
+ newState(QNetworkSession::Closing);
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StopNotifications();
+ // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate
+ iHandleStateNotificationsFromManager = true;
+ }
+ iConnection.Stop(RConnection::EStopAuthoritative);
+ isOpen = true;
+ isOpening = false;
+ close(false);
+ emit closed();
+ }
+}
+
+void QNetworkSessionPrivateImpl::migrate()
+{
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (iMobility) {
+ QSymbianSocketManager::instance().setDefaultConnection(0);
+ // Start migrating to new IAP
+ iMobility->MigrateToPreferredCarrier();
+ }
+#endif
+}
+
+void QNetworkSessionPrivateImpl::ignore()
+{
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (iMobility) {
+ iMobility->IgnorePreferredCarrier();
+
+ if (!iALRUpgradingConnection) {
+ newState(QNetworkSession::Disconnected);
+ } else {
+ newState(QNetworkSession::Connected,iOldRoamingIap);
+ }
+ }
+#endif
+}
+
+void QNetworkSessionPrivateImpl::accept()
+{
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (iMobility) {
+ iMobility->NewCarrierAccepted();
+
+ QNetworkConfiguration newActiveConfig = activeConfiguration(iNewRoamingIap);
+
+ QSymbianSocketManager::instance().setDefaultConnection(&iConnection);
+
+ newState(QNetworkSession::Connected, iNewRoamingIap);
+ }
+#endif
+}
+
+void QNetworkSessionPrivateImpl::reject()
+{
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (iMobility) {
+ iMobility->NewCarrierRejected();
+
+ if (!iALRUpgradingConnection) {
+ newState(QNetworkSession::Disconnected);
+ } else {
+ QNetworkConfiguration newActiveConfig = activeConfiguration(iOldRoamingIap);
+
+ QSymbianSocketManager::instance().setDefaultConnection(&iConnection);
+
+ newState(QNetworkSession::Connected, iOldRoamingIap);
+ }
+ }
+#endif
+}
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+void QNetworkSessionPrivateImpl::PreferredCarrierAvailable(TAccessPointInfo aOldAPInfo,
+ TAccessPointInfo aNewAPInfo,
+ TBool aIsUpgrade,
+ TBool aIsSeamless)
+{
+ iOldRoamingIap = aOldAPInfo.AccessPoint();
+ iNewRoamingIap = aNewAPInfo.AccessPoint();
+ newState(QNetworkSession::Roaming);
+ if (iALREnabled > 0) {
+ iALRUpgradingConnection = aIsUpgrade;
+ QList<QNetworkConfiguration> configs = publicConfig.children();
+ for (int i=0; i < configs.count(); i++) {
+ SymbianNetworkConfigurationPrivate *symbianConfig =
+ toSymbianConfig(privateConfiguration(configs[i]));
+
+ if (symbianConfig->numericIdentifier() == aNewAPInfo.AccessPoint()) {
+ // Any slot connected to the signal might throw an std::exception,
+ // which must not propagate into Symbian code (this function is a callback
+ // from platform). We could convert exception to a symbian Leave, but since the
+ // prototype of this function bans this (no trailing 'L'), we just catch
+ // and drop.
+ QT_TRY {
+ emit preferredConfigurationChanged(configs[i], aIsSeamless);
+ }
+ QT_CATCH (std::exception&) {}
+ }
+ }
+ } else {
+ migrate();
+ }
+}
+
+void QNetworkSessionPrivateImpl::NewCarrierActive(TAccessPointInfo /*aNewAPInfo*/, TBool /*aIsSeamless*/)
+{
+ if (iALREnabled > 0) {
+ QT_TRY {
+ emit newConfigurationActivated();
+ }
+ QT_CATCH (std::exception&) {}
+ } else {
+ accept();
+ }
+}
+
+void QNetworkSessionPrivateImpl::Error(TInt aError)
+{
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "roaming Error() occurred" << aError << ", isOpen is: " << isOpen;
+#endif
+ if (aError == KErrCancel)
+ return; //avoid recursive deletion
+ if (isOpen) {
+ isOpen = false;
+ isOpening = false;
+ activeConfig = QNetworkConfiguration();
+ serviceConfig = QNetworkConfiguration();
+ iError = QNetworkSession::RoamingError;
+ emit QNetworkSessionPrivate::error(iError);
+ closeHandles();
+ QT_TRY {
+ syncStateWithInterface();
+ // In some cases IAP is still in Connected state when
+ // syncStateWithInterface(); is called
+ // => Following call makes sure that Session state
+ // changes immediately to Disconnected.
+ newState(QNetworkSession::Disconnected);
+ emit closed();
+ }
+ QT_CATCH (std::exception&) {}
+ } else if (iStoppedByUser) {
+ // If the user of this session has called the stop() and
+ // configuration is based on internet SNAP, this needs to be
+ // done here because platform might roam.
+ QT_TRY {
+ newState(QNetworkSession::Disconnected);
+ }
+ QT_CATCH (std::exception&) {}
+ }
+}
+#endif
+
+void QNetworkSessionPrivateImpl::setALREnabled(bool enabled)
+{
+ if (enabled) {
+ iALREnabled++;
+ } else {
+ iALREnabled--;
+ }
+}
+
+QNetworkConfiguration QNetworkSessionPrivateImpl::bestConfigFromSNAP(const QNetworkConfiguration& snapConfig) const
+{
+ QNetworkConfiguration config;
+ QList<QNetworkConfiguration> subConfigurations = snapConfig.children();
+ for (int i = 0; i < subConfigurations.count(); i++ ) {
+ if (subConfigurations[i].state() == QNetworkConfiguration::Active) {
+ config = subConfigurations[i];
+ break;
+ } else if (!config.isValid() && subConfigurations[i].state() == QNetworkConfiguration::Discovered) {
+ config = subConfigurations[i];
+ }
+ }
+ if (!config.isValid() && subConfigurations.count() > 0) {
+ config = subConfigurations[0];
+ }
+ return config;
+}
+
+quint64 QNetworkSessionPrivateImpl::bytesWritten() const
+{
+ return transferredData(KUplinkData);
+}
+
+quint64 QNetworkSessionPrivateImpl::bytesReceived() const
+{
+ return transferredData(KDownlinkData);
+}
+
+quint64 QNetworkSessionPrivateImpl::transferredData(TUint dataType) const
+{
+ if (!publicConfig.isValid()) {
+ return 0;
+ }
+
+ QNetworkConfiguration config;
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ if (serviceConfig.isValid()) {
+ config = serviceConfig;
+ } else {
+ if (activeConfig.isValid()) {
+ config = activeConfig;
+ }
+ }
+ } else {
+ config = publicConfig;
+ }
+
+ if (!config.isValid()) {
+ return 0;
+ }
+
+ TUint count;
+ TRequestStatus status;
+ iConnectionMonitor.GetConnectionCount(count, status);
+ User::WaitForRequest(status);
+ if (status.Int() != KErrNone) {
+ return 0;
+ }
+
+ TUint transferredData = 0;
+ TUint numSubConnections;
+ TUint connectionId;
+ bool configFound;
+ for (TUint i = 1; i <= count; i++) {
+ TInt ret = iConnectionMonitor.GetConnectionInfo(i, connectionId, numSubConnections);
+ if (ret == KErrNone) {
+ TUint apId;
+ iConnectionMonitor.GetUintAttribute(connectionId, 0, KIAPId, apId, status);
+ User::WaitForRequest(status);
+ if (status.Int() == KErrNone) {
+ configFound = false;
+ if (config.type() == QNetworkConfiguration::ServiceNetwork) {
+ QList<QNetworkConfiguration> configs = config.children();
+ for (int i=0; i < configs.count(); i++) {
+ SymbianNetworkConfigurationPrivate *symbianConfig =
+ toSymbianConfig(privateConfiguration(configs[i]));
+
+ if (symbianConfig->numericIdentifier() == apId) {
+ configFound = true;
+ break;
+ }
+ }
+ } else {
+ SymbianNetworkConfigurationPrivate *symbianConfig =
+ toSymbianConfig(privateConfiguration(config));
+
+ if (symbianConfig->numericIdentifier() == apId)
+ configFound = true;
+ }
+ if (configFound) {
+ TUint tData;
+ iConnectionMonitor.GetUintAttribute(connectionId, 0, dataType, tData, status );
+ User::WaitForRequest(status);
+ if (status.Int() == KErrNone) {
+ transferredData += tData;
+ }
+ }
+ }
+ }
+ }
+
+ return transferredData;
+}
+
+quint64 QNetworkSessionPrivateImpl::activeTime() const
+{
+ if (!isOpen || startTime.isNull()) {
+ return 0;
+ }
+ return startTime.secsTo(QDateTime::currentDateTime());
+}
+
+QNetworkConfiguration QNetworkSessionPrivateImpl::activeConfiguration(TUint32 iapId) const
+{
+ if (iapId == 0) {
+ _LIT(KSetting, "IAP\\Id");
+ iConnection.GetIntSetting(KSetting, iapId);
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ // Check if this is an Easy WLAN configuration. On Symbian^3 RConnection may report
+ // the used configuration as 'EasyWLAN' IAP ID if someone has just opened the configuration
+ // from WLAN Scan dialog, _and_ that connection is still up. We need to find the
+ // real matching configuration. Function alters the Easy WLAN ID to real IAP ID (only if
+ // easy WLAN):
+ easyWlanTrueIapId(iapId);
+#endif
+ }
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
+ // Try to search IAP from the used SNAP using IAP Id
+ QList<QNetworkConfiguration> children = publicConfig.children();
+ for (int i=0; i < children.count(); i++) {
+ SymbianNetworkConfigurationPrivate *childConfig =
+ toSymbianConfig(privateConfiguration(children[i]));
+
+ if (childConfig->numericIdentifier() == iapId)
+ return children[i];
+ }
+
+ // Given IAP Id was not found from the used SNAP
+ // => Try to search matching IAP using mappingName
+ // mappingName contains:
+ // 1. "Access point name" for "Packet data" Bearer
+ // 2. "WLAN network name" (= SSID) for "Wireless LAN" Bearer
+ // 3. "Dial-up number" for "Data call Bearer" or "High Speed (GSM)" Bearer
+ // <=> Note: It's possible that in this case reported IAP is
+ // clone of the one of the IAPs of the used SNAP
+ // => If mappingName matches, clone has been found
+ QNetworkConfiguration pt = QNetworkConfigurationManager().configurationFromIdentifier(
+ QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(iapId)));
+
+ SymbianNetworkConfigurationPrivate *symbianConfig =
+ toSymbianConfig(privateConfiguration(pt));
+ if (symbianConfig) {
+ for (int i=0; i < children.count(); i++) {
+ SymbianNetworkConfigurationPrivate *childConfig =
+ toSymbianConfig(privateConfiguration(children[i]));
+
+ if (childConfig->configMappingName() == symbianConfig->configMappingName()) {
+ return children[i];
+ }
+ }
+ } else {
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ // On Symbian^3 (only, not earlier or Symbian^4) if the SNAP was not reachable, it
+ // triggers user choice type of activity (EasyWLAN). As a result, a new IAP may be
+ // created, and hence if was not found yet. Therefore update configurations and see if
+ // there is something new.
+
+ // 1. Update knowledge from the databases.
+ if (thread() != engine->thread())
+ QMetaObject::invokeMethod(engine, "requestUpdate", Qt::BlockingQueuedConnection);
+ else
+ engine->requestUpdate();
+
+ // 2. Check if new configuration was created during connection creation
+ QList<QString> knownConfigs = engine->accessPointConfigurationIdentifiers();
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "opened configuration was not known beforehand, looking for new.";
+#endif
+ if (knownConfigs.count() > iKnownConfigsBeforeConnectionStart.count()) {
+ // Configuration count increased => new configuration was created
+ // => Search new, created configuration
+ QString newIapId;
+ for (int i=0; i < iKnownConfigsBeforeConnectionStart.count(); i++) {
+ if (knownConfigs[i] != iKnownConfigsBeforeConnectionStart[i]) {
+ newIapId = knownConfigs[i];
+ break;
+ }
+ }
+ if (newIapId.isEmpty()) {
+ newIapId = knownConfigs[knownConfigs.count()-1];
+ }
+ pt = QNetworkConfigurationManager().configurationFromIdentifier(newIapId);
+ if (pt.isValid()) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "new configuration was found, name, IAP id: " << pt.name() << pt.identifier();
+#endif
+ return pt;
+ }
+ }
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "configuration was not found, returning invalid.";
+#endif
+#endif
+ // Given IAP Id was not found from known IAPs array
+ return QNetworkConfiguration();
+ }
+ // Matching IAP was not found from used SNAP
+ // => IAP from another SNAP is returned
+ // (Note: Returned IAP matches to given IAP Id)
+ return pt;
+ }
+#endif
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ if (engine) {
+ QNetworkConfiguration pt = QNetworkConfigurationManager().configurationFromIdentifier(
+ QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(iapId)));
+ // Try to found User Selected IAP from known IAPs (accessPointConfigurations)
+ if (pt.isValid()) {
+ return pt;
+ } else {
+ // Check if new (WLAN) IAP was created in IAP/SNAP dialog
+ // 1. Sync internal configurations array to commsdb first
+ if (thread() != engine->thread()) {
+ QMetaObject::invokeMethod(engine, "requestUpdate",
+ Qt::BlockingQueuedConnection);
+ } else {
+ engine->requestUpdate();
+ }
+ // 2. Check if new configuration was created during connection creation
+ QStringList knownConfigs = engine->accessPointConfigurationIdentifiers();
+ if (knownConfigs.count() > iKnownConfigsBeforeConnectionStart.count()) {
+ // Configuration count increased => new configuration was created
+ // => Search new, created configuration
+ QString newIapId;
+ for (int i=0; i < iKnownConfigsBeforeConnectionStart.count(); i++) {
+ if (knownConfigs[i] != iKnownConfigsBeforeConnectionStart[i]) {
+ newIapId = knownConfigs[i];
+ break;
+ }
+ }
+ if (newIapId.isEmpty()) {
+ newIapId = knownConfigs[knownConfigs.count()-1];
+ }
+ pt = QNetworkConfigurationManager().configurationFromIdentifier(newIapId);
+ if (pt.isValid())
+ return pt;
+ }
+ }
+ }
+ return QNetworkConfiguration();
+ }
+
+ return publicConfig;
+}
+
+void QNetworkSessionPrivateImpl::ConnectionStartComplete(TInt statusCode)
+{
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "RConnection::Start completed with status code: " << statusCode;
+#endif
+ delete ipConnectionStarter;
+ ipConnectionStarter = 0;
+
+ switch (statusCode) {
+ case KErrNone: // Connection created successfully
+ {
+ TInt error = KErrNone;
+ QNetworkConfiguration newActiveConfig = activeConfiguration();
+ if (!newActiveConfig.isValid()) {
+ // RConnection startup was successful but no configuration
+ // was found. That indicates that user has chosen to create a
+ // new WLAN configuration (from scan results), but that new
+ // configuration does not have access to Internet (Internet
+ // Connectivity Test, ICT, failed).
+ error = KErrGeneral;
+ } else {
+ QSymbianSocketManager::instance().setDefaultConnection(&iConnection);
+ }
+ if (error != KErrNone) {
+ isOpen = false;
+ isOpening = false;
+ iError = QNetworkSession::UnknownSessionError;
+ QT_TRYCATCH_LEAVING(emit QNetworkSessionPrivate::error(iError));
+ closeHandles();
+ if (!newActiveConfig.isValid()) {
+ // No valid configuration, bail out.
+ // Status updates from QNCM won't be received correctly
+ // because there is no configuration to associate them with so transit here.
+ newState(QNetworkSession::Closing);
+ newState(QNetworkSession::Disconnected);
+ }
+ QT_TRYCATCH_LEAVING(syncStateWithInterface());
+ return;
+ }
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
+ // Activate ALR monitoring
+ iMobility = CActiveCommsMobilityApiExt::NewL(iConnection, *this);
+ }
+#endif
+
+ isOpen = true;
+ isOpening = false;
+ activeConfig = newActiveConfig;
+
+ SymbianNetworkConfigurationPrivate *symbianConfig =
+ toSymbianConfig(privateConfiguration(activeConfig));
+
+#ifndef QT_NO_NETWORKINTERFACE
+ activeInterface = interface(symbianConfig->numericIdentifier());
+#endif
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ serviceConfig = QNetworkConfigurationManager()
+ .configurationFromIdentifier(activeConfig.identifier());
+ }
+
+ startTime = QDateTime::currentDateTime();
+
+ QT_TRYCATCH_LEAVING({
+ newState(QNetworkSession::Connected);
+ emit quitPendingWaitsForOpened();
+ });
+ }
+ break;
+ case KErrNotFound: // Connection failed
+ isOpen = false;
+ isOpening = false;
+ activeConfig = QNetworkConfiguration();
+ serviceConfig = QNetworkConfiguration();
+ iError = QNetworkSession::InvalidConfigurationError;
+ QT_TRYCATCH_LEAVING(emit QNetworkSessionPrivate::error(iError));
+ closeHandles();
+ QT_TRYCATCH_LEAVING(syncStateWithInterface());
+ break;
+ case KErrCancel: // Connection attempt cancelled
+ case KErrAlreadyExists: // Connection already exists
+ default:
+ isOpen = false;
+ isOpening = false;
+ activeConfig = QNetworkConfiguration();
+ serviceConfig = QNetworkConfiguration();
+ if (statusCode == KErrCancel) {
+ iError = QNetworkSession::SessionAbortedError;
+ } else if (publicConfig.state() == QNetworkConfiguration::Undefined ||
+ publicConfig.state() == QNetworkConfiguration::Defined) {
+ iError = QNetworkSession::InvalidConfigurationError;
+ } else {
+ iError = QNetworkSession::UnknownSessionError;
+ }
+ QT_TRYCATCH_LEAVING(emit QNetworkSessionPrivate::error(iError));
+ closeHandles();
+ QT_TRYCATCH_LEAVING(syncStateWithInterface());
+ break;
+ }
+}
+
+// Enters newState if feasible according to current state.
+// AccessPointId may be given as parameter. If it is zero, state-change is assumed to
+// concern this session's configuration. If non-zero, the configuration is looked up
+// and checked if it matches the configuration this session is based on.
+bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint accessPointId)
+{
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - "
+ << "NEW STATE, IAP ID : " << QString::number(accessPointId) << " , newState : " << QString::number(newState);
+#endif
+ // Make sure that activeConfig is always updated when SNAP is signaled to be
+ // connected.
+ if (isOpen && publicConfig.type() == QNetworkConfiguration::ServiceNetwork &&
+ newState == QNetworkSession::Connected) {
+ activeConfig = activeConfiguration(accessPointId);
+
+#ifndef QT_NO_NETWORKINTERFACE
+ SymbianNetworkConfigurationPrivate *symbianConfig =
+ toSymbianConfig(privateConfiguration(activeConfig));
+
+ activeInterface = interface(symbianConfig->numericIdentifier());
+#endif
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ QSymbianSocketManager::instance().setDefaultConnection(&iConnection);
+#endif
+ }
+
+ // Make sure that same state is not signaled twice in a row.
+ if (state == newState) {
+ return true;
+ }
+
+ // Make sure that Connecting state does not overwrite Roaming state
+ if (state == QNetworkSession::Roaming && newState == QNetworkSession::Connecting) {
+ return false;
+ }
+
+ // Make sure that Connected state is not reported when Connection is
+ // already Closing.
+ // Note: Stopping connection results sometimes KLinkLayerOpen
+ // to be reported first (just before KLinkLayerClosed).
+ if (state == QNetworkSession::Closing && newState == QNetworkSession::Connected) {
+ return false;
+ }
+
+ // Make sure that some lagging 'closing' state-changes do not overwrite
+ // if we are already disconnected or closed.
+ if (state == QNetworkSession::Disconnected && newState == QNetworkSession::Closing) {
+ return false;
+ }
+
+ // Make sure that some lagging 'connecting' state-changes do not overwrite
+ // if we are already connected (may righfully still happen with roaming though).
+ if (state == QNetworkSession::Connected && newState == QNetworkSession::Connecting) {
+ return false;
+ }
+
+ bool emitSessionClosed = false;
+
+ // If we abruptly go down and user hasn't closed the session, we've been aborted.
+ // Note that session may be in 'closing' state and not in 'connected' state, because
+ // depending on platform the platform may report KConfigDaemonStartingDeregistration
+ // event before KLinkLayerClosed
+ if ((isOpen && state == QNetworkSession::Connected && newState == QNetworkSession::Disconnected) ||
+ (isOpen && !iClosedByUser && newState == QNetworkSession::Disconnected)) {
+ // Active & Connected state should change directly to Disconnected state
+ // only when something forces connection to close (eg. when another
+ // application or session stops connection or when network drops
+ // unexpectedly).
+ isOpen = false;
+ isOpening = false;
+ activeConfig = QNetworkConfiguration();
+ serviceConfig = QNetworkConfiguration();
+ iError = QNetworkSession::SessionAbortedError;
+ emit QNetworkSessionPrivate::error(iError);
+ closeHandles();
+ // Start handling IAP state change signals from QNetworkConfigurationManagerPrivate
+ iHandleStateNotificationsFromManager = true;
+ emitSessionClosed = true; // Emit SessionClosed after state change has been reported
+ }
+
+ bool retVal = false;
+ if (accessPointId == 0) {
+ state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed A to: " << state;
+#endif
+ emit stateChanged(state);
+ retVal = true;
+ } else {
+ if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
+ SymbianNetworkConfigurationPrivate *symbianConfig =
+ toSymbianConfig(privateConfiguration(publicConfig));
+
+ if (symbianConfig->numericIdentifier() == accessPointId) {
+ state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed B to: " << state;
+#endif
+ emit stateChanged(state);
+ retVal = true;
+ }
+ } else if (publicConfig.type() == QNetworkConfiguration::UserChoice && isOpen) {
+ SymbianNetworkConfigurationPrivate *symbianConfig =
+ toSymbianConfig(privateConfiguration(activeConfig));
+
+ if (symbianConfig->numericIdentifier() == accessPointId) {
+ state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed C to: " << state;
+#endif
+ emit stateChanged(state);
+ retVal = true;
+ }
+ } else if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
+ QList<QNetworkConfiguration> subConfigurations = publicConfig.children();
+ for (int i = 0; i < subConfigurations.count(); i++) {
+ SymbianNetworkConfigurationPrivate *symbianConfig =
+ toSymbianConfig(privateConfiguration(subConfigurations[i]));
+
+ if (symbianConfig->numericIdentifier() == accessPointId) {
+ if (newState != QNetworkSession::Disconnected) {
+ state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed D to: " << state;
+#endif
+ emit stateChanged(state);
+ retVal = true;
+ } else {
+ QNetworkConfiguration config = bestConfigFromSNAP(publicConfig);
+ if ((config.state() == QNetworkConfiguration::Defined) ||
+ (config.state() == QNetworkConfiguration::Discovered)) {
+ activeConfig = QNetworkConfiguration();
+ state = newState;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed E to: " << state;
+#endif
+ emit stateChanged(state);
+ retVal = true;
+ } else if (config.state() == QNetworkConfiguration::Active) {
+ // Connection to used IAP was closed, but there is another
+ // IAP that's active in used SNAP
+ // => Change state back to Connected
+ state = QNetworkSession::Connected;
+ emit stateChanged(state);
+ retVal = true;
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed F to: " << state;
+#endif
+ }
+ }
+ }
+ }
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ // If the retVal is not true here, it means that the status update may apply to an IAP outside of
+ // SNAP (session is based on SNAP but follows IAP outside of it), which may occur on Symbian^3 EasyWlan.
+ if (retVal == false && activeConfig.isValid() &&
+ toSymbianConfig(privateConfiguration(activeConfig))->numericIdentifier() == accessPointId) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "===> EMIT State changed G to: " << state;
+#endif
+ if (newState == QNetworkSession::Disconnected) {
+ activeConfig = QNetworkConfiguration();
+ }
+ state = newState;
+ emit stateChanged(state);
+ retVal = true;
+ }
+#endif
+ }
+ }
+ if (emitSessionClosed) {
+ emit closed();
+ }
+ if (state == QNetworkSession::Disconnected) {
+ // Just in case clear activeConfiguration.
+ activeConfig = QNetworkConfiguration();
+ }
+ return retVal;
+}
+
+void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConnectionStatus,
+ TInt aError,
+ TUint accessPointId)
+{
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - " << QString::number(accessPointId) << " , status : " << QString::number(aConnectionStatus);
+#endif
+ switch (aConnectionStatus)
+ {
+ // Connection unitialised
+ case KConnectionUninitialised:
+ break;
+
+ // Starting connetion selection
+ case KStartingSelection:
+ break;
+
+ // Selection finished
+ case KFinishedSelection:
+ if (aError == KErrNone)
+ {
+ 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;
+
+ case KConfigDaemonStartingRegistration:
+ // 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;
+
+ case KConfigDaemonStartingDeregistration:
+ // Hangup or GRPS deactivation
+ case KConnectionStartingClose:
+ newState(QNetworkSession::Closing,accessPointId);
+ break;
+
+ // Connection closed
+ case KConnectionClosed:
+ case KLinkLayerClosed:
+ newState(QNetworkSession::Disconnected,accessPointId);
+ // Report manager about this to make sure this event
+ // is received by all interseted parties (mediated by
+ // manager because it does always receive all events from
+ // connection monitor).
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNS this : " << QString::number((uint)this) << " - " << "reporting disconnection to manager.";
+#endif
+ if (publicConfig.isValid()) {
+ SymbianNetworkConfigurationPrivate *symbianConfig =
+ toSymbianConfig(privateConfiguration(publicConfig));
+
+ engine->configurationStateChangeReport(symbianConfig->numericIdentifier(),
+ QNetworkSession::Disconnected);
+ }
+ break;
+ // Unhandled state
+ default:
+ break;
+ }
+}
+
+#if defined(SNAP_FUNCTIONALITY_AVAILABLE)
+bool QNetworkSessionPrivateImpl::easyWlanTrueIapId(TUint32 &trueIapId) const
+{
+ RCmManager iCmManager;
+ TRAPD(err, iCmManager.OpenL());
+ if (err != KErrNone)
+ return false;
+
+ // Check if this is easy wlan id in the first place
+ if (trueIapId != iCmManager.EasyWlanIdL()) {
+ iCmManager.Close();
+ return false;
+ }
+
+ iCmManager.Close();
+
+ // Loop through all connections that connection monitor is aware
+ // and check for IAPs based on easy WLAN
+ TRequestStatus status;
+ TUint connectionCount;
+ iConnectionMonitor.GetConnectionCount(connectionCount, status);
+ User::WaitForRequest(status);
+ 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);
+ if (apId == trueIapId) {
+ TBuf<50>easyWlanNetworkName;
+ iConnectionMonitor.GetStringAttribute(connectionId, 0, KNetworkName,
+ easyWlanNetworkName, status);
+ User::WaitForRequest(status);
+ if (status.Int() != KErrNone)
+ continue;
+
+ const QString ssid = QString::fromUtf16(easyWlanNetworkName.Ptr(),
+ easyWlanNetworkName.Length());
+
+ QNetworkConfigurationPrivatePointer ptr = engine->configurationFromSsid(ssid);
+ if (ptr) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNCM easyWlanTrueIapId(), found true IAP ID: "
+ << toSymbianConfig(ptr)->numericIdentifier();
+#endif
+ trueIapId = toSymbianConfig(ptr)->numericIdentifier();
+ return true;
+ }
+ }
+ }
+ }
+ return false;
+}
+#endif
+
+RConnection* QNetworkSessionPrivateImpl::nativeSession()
+{
+ return &iConnection;
+}
+
+ConnectionProgressNotifier::ConnectionProgressNotifier(QNetworkSessionPrivateImpl& owner, RConnection& connection)
+ : CActive(CActive::EPriorityUserInput), 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) {
+ SetActive();
+ iConnection.ProgressNotification(iProgress, iStatus);
+ // warning, this object may be deleted in the callback - do nothing after handleSymbianConnectionStatusChange
+ QT_TRYCATCH_LEAVING(iOwner.handleSymbianConnectionStatusChange(iProgress().iStage, iProgress().iError));
+ }
+}
+
+ConnectionStarter::ConnectionStarter(QNetworkSessionPrivateImpl &owner, RConnection &connection)
+ : CActive(CActive::EPriorityUserInput), iOwner(owner), iConnection(connection)
+{
+ CActiveScheduler::Add(this);
+}
+
+ConnectionStarter::~ConnectionStarter()
+{
+ Cancel();
+}
+
+void ConnectionStarter::Start()
+{
+ if (!IsActive()) {
+ iConnection.Start(iStatus);
+ SetActive();
+ }
+}
+
+void ConnectionStarter::Start(TConnPref &pref)
+{
+ if (!IsActive()) {
+ iConnection.Start(pref, iStatus);
+ SetActive();
+ }
+}
+
+void ConnectionStarter::RunL()
+{
+ iOwner.ConnectionStartComplete(iStatus.Int());
+ //note owner deletes on callback
+}
+
+TInt ConnectionStarter::RunError(TInt err)
+{
+ qWarning() << "ConnectionStarter::RunError" << err;
+ return KErrNone;
+}
+
+void ConnectionStarter::DoCancel()
+{
+ iConnection.Close();
+}
+
+QT_END_NAMESPACE
+
+#endif //QT_NO_BEARERMANAGEMENT
+
diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h
new file mode 100644
index 0000000000..2dda456acc
--- /dev/null
+++ b/src/plugins/bearer/symbian/qnetworksession_impl.h
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNETWORKSESSION_IMPL_H
+#define QNETWORKSESSION_IMPL_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtNetwork/private/qnetworksession_p.h>
+
+#include <QDateTime>
+
+#include <e32base.h>
+#include <commdbconnpref.h>
+#include <es_sock.h>
+#include <rconnmon.h>
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ #include <comms-infras/cs_mobility_apiext.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+class ConnectionProgressNotifier;
+class ConnectionStarter;
+class SymbianEngine;
+
+typedef void (*TOpenCUnSetdefaultifFunction)();
+
+class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ , public MMobilityProtocolResp
+#endif
+{
+ Q_OBJECT
+public:
+ QNetworkSessionPrivateImpl(SymbianEngine *engine);
+ ~QNetworkSessionPrivateImpl();
+
+ //called by QNetworkSession constructor and ensures
+ //that the state is immediately updated (w/o actually opening
+ //a session). Also this function should take care of
+ //notification hooks to discover future state changes.
+ void syncStateWithInterface();
+
+#ifndef QT_NO_NETWORKINTERFACE
+ QNetworkInterface currentInterface() const;
+#endif
+ QVariant sessionProperty(const QString& key) const;
+ void setSessionProperty(const QString& key, const QVariant& value);
+
+ void setALREnabled(bool enabled);
+
+ void open();
+ inline void close() { close(true); }
+ void close(bool allowSignals);
+ void stop();
+ void migrate();
+ void accept();
+ void ignore();
+ void reject();
+
+ QString errorString() const; //must return translated string
+ QNetworkSession::SessionError error() const;
+
+ quint64 bytesWritten() const;
+ quint64 bytesReceived() const;
+ quint64 activeTime() const;
+
+ RConnection* nativeSession();
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+public: // From MMobilityProtocolResp
+ void PreferredCarrierAvailable(TAccessPointInfo aOldAPInfo,
+ TAccessPointInfo aNewAPInfo,
+ TBool aIsUpgrade,
+ TBool aIsSeamless);
+
+ void NewCarrierActive(TAccessPointInfo aNewAPInfo, TBool aIsSeamless);
+
+ void Error(TInt aError);
+#endif
+
+protected: // From CActive
+ void ConnectionStartComplete(TInt statusCode);
+ void DoCancel();
+
+private Q_SLOTS:
+ void configurationStateChanged(quint32 accessPointId, quint32 connMonId,
+ QNetworkSession::State newState);
+ void configurationRemoved(QNetworkConfigurationPrivatePointer config);
+ void configurationAdded(QNetworkConfigurationPrivatePointer config);
+
+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;
+#ifndef QT_NO_NETWORKINTERFACE
+ QNetworkInterface interface(TUint iapId) const;
+#endif
+
+#if defined(SNAP_FUNCTIONALITY_AVAILABLE)
+ bool easyWlanTrueIapId(TUint32 &trueIapId) const;
+#endif
+
+ void closeHandles();
+
+private: // data
+ SymbianEngine *engine;
+
+#ifndef QT_NO_NETWORKINTERFACE
+ mutable QNetworkInterface activeInterface;
+#endif
+
+ QDateTime startTime;
+
+ mutable RSocketServ &iSocketServ; //not owned, shared from QtCore
+ mutable RConnection iConnection;
+ mutable RConnectionMonitor iConnectionMonitor;
+ ConnectionProgressNotifier* ipConnectionNotifier;
+ ConnectionStarter* ipConnectionStarter;
+
+ bool iHandleStateNotificationsFromManager;
+ bool iFirstSync;
+ bool iStoppedByUser;
+ bool iClosedByUser;
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ CActiveCommsMobilityApiExt* iMobility;
+#endif
+
+ QNetworkSession::SessionError iError;
+ TInt iALREnabled;
+ TBool iALRUpgradingConnection;
+ TBool iConnectInBackground;
+
+ QList<QString> iKnownConfigsBeforeConnectionStart;
+
+ TUint32 iOldRoamingIap;
+ TUint32 iNewRoamingIap;
+
+ bool isOpening;
+
+ friend class ConnectionProgressNotifier;
+ friend class ConnectionStarter;
+};
+
+class ConnectionProgressNotifier : public CActive
+{
+public:
+ ConnectionProgressNotifier(QNetworkSessionPrivateImpl &owner, RConnection &connection);
+ ~ConnectionProgressNotifier();
+
+ void StartNotifications();
+ void StopNotifications();
+
+protected: // From CActive
+ void RunL();
+ void DoCancel();
+
+private: // Data
+ QNetworkSessionPrivateImpl &iOwner;
+ RConnection& iConnection;
+ TNifProgressBuf iProgress;
+
+};
+
+class ConnectionStarter : public CActive
+{
+public:
+ ConnectionStarter(QNetworkSessionPrivateImpl &owner, RConnection &connection);
+ ~ConnectionStarter();
+
+ void Start();
+ void Start(TConnPref &pref);
+protected:
+ void RunL();
+ TInt RunError(TInt err);
+ void DoCancel();
+
+private: // Data
+ QNetworkSessionPrivateImpl &iOwner;
+ RConnection& iConnection;
+};
+
+QT_END_NAMESPACE
+
+#endif //QNETWORKSESSION_IMPL_H
+
diff --git a/src/plugins/bearer/symbian/symbian.pri b/src/plugins/bearer/symbian/symbian.pri
new file mode 100644
index 0000000000..8d92f57b68
--- /dev/null
+++ b/src/plugins/bearer/symbian/symbian.pri
@@ -0,0 +1,32 @@
+TARGET = qsymbianbearer
+include(../../qpluginbase.pri)
+
+QT = core network
+
+HEADERS += ../symbianengine.h \
+ ../qnetworksession_impl.h
+
+SOURCES += ../symbianengine.cpp \
+ ../qnetworksession_impl.cpp \
+ ../main.cpp
+
+INCLUDEPATH += $$APP_LAYER_SYSTEMINCLUDE
+symbian-abld:INCLUDEPATH += $$QT_BUILD_TREE/include/QtNetwork/private
+
+LIBS += -lcommdb \
+ -lcentralrepository \
+ -lesock \
+ -linsock \
+ -lecom \
+ -lefsrv \
+ -lnetmeta
+
+is_using_gnupoc {
+ LIBS += -lconnmon
+} else {
+ LIBS += -lConnMon
+}
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/bearer
+target.path += $$[QT_INSTALL_PLUGINS]/bearer
+INSTALLS += target
diff --git a/src/plugins/bearer/symbian/symbian.pro b/src/plugins/bearer/symbian/symbian.pro
new file mode 100644
index 0000000000..91f8217b2e
--- /dev/null
+++ b/src/plugins/bearer/symbian/symbian.pro
@@ -0,0 +1,8 @@
+TEMPLATE = subdirs
+
+contains(S60_VERSION, 3.1)|contains(S60_VERSION, 3.2)|contains(S60_VERSION, 5.0) {
+ SUBDIRS += 3_1 3_2
+}
+
+# Symbian3 builds the default plugin for winscw so it is always needed
+SUBDIRS += symbian_3 \ No newline at end of file
diff --git a/src/plugins/bearer/symbian/symbian_3/symbian_3.pro b/src/plugins/bearer/symbian/symbian_3/symbian_3.pro
new file mode 100644
index 0000000000..ef90ad2b73
--- /dev/null
+++ b/src/plugins/bearer/symbian/symbian_3/symbian_3.pro
@@ -0,0 +1,21 @@
+include(../symbian.pri)
+
+symbian {
+ contains(S60_VERSION, 3.1) {
+ is_using_gnupoc {
+ LIBS += -lapengine
+ } else {
+ LIBS += -lAPEngine
+ }
+ } else {
+ DEFINES += SNAP_FUNCTIONALITY_AVAILABLE
+ LIBS += -lcmmanager
+
+ !contains(S60_VERSION, 3.2):!contains(S60_VERSION, 5.0) {
+ DEFINES += OCC_FUNCTIONALITY_AVAILABLE
+ LIBS += -lextendedconnpref
+ }
+ }
+}
+
+TARGET.UID3 = 0x20021319
diff --git a/src/plugins/bearer/symbian/symbianengine.cpp b/src/plugins/bearer/symbian/symbianengine.cpp
new file mode 100644
index 0000000000..f367c26050
--- /dev/null
+++ b/src/plugins/bearer/symbian/symbianengine.cpp
@@ -0,0 +1,1409 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "symbianengine.h"
+#include "qnetworksession_impl.h"
+
+#include <commdb.h>
+#include <cdbcols.h>
+#include <d32dbms.h>
+#include <nifvar.h>
+#include <QTimer>
+#include <QTime> // For randgen seeding
+#include <QtCore> // For randgen seeding
+
+
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+#include <QDebug>
+#endif
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ #include <cmdestination.h>
+ #include <cmconnectionmethod.h>
+ #include <cmconnectionmethoddef.h>
+ #include <cmpluginwlandef.h>
+ #include <cmpluginpacketdatadef.h>
+ #include <cmplugindialcommondefs.h>
+#else
+ #include <ApAccessPointItem.h>
+ #include <ApDataHandler.h>
+ #include <ApUtils.h>
+#endif
+
+#ifndef QT_NO_BEARERMANAGEMENT
+
+QT_BEGIN_NAMESPACE
+
+static const int KUserChoiceIAPId = 0;
+
+SymbianNetworkConfigurationPrivate::SymbianNetworkConfigurationPrivate()
+: numericId(0), connectionId(0)
+{
+}
+
+SymbianNetworkConfigurationPrivate::~SymbianNetworkConfigurationPrivate()
+{
+}
+
+SymbianEngine::SymbianEngine(QObject *parent)
+: QBearerEngine(parent), CActive(CActive::EPriorityHigh), iFirstUpdate(true), ipCommsDB(0),
+ iInitOk(true), iUpdatePending(false), ipAccessPointsAvailabilityScanner(0)
+{
+}
+
+void SymbianEngine::initialize()
+{
+ QMutexLocker locker(&mutex);
+
+ CActiveScheduler::Add(this);
+
+ // Seed the randomgenerator
+ qsrand(QTime(0,0,0).secsTo(QTime::currentTime()) + QCoreApplication::applicationPid());
+
+ TRAPD(error, ipCommsDB = CCommsDatabase::NewL(EDatabaseTypeIAP));
+ if (error != KErrNone) {
+ iInitOk = false;
+ return;
+ }
+
+ TRAP_IGNORE(iConnectionMonitor.ConnectL());
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ TRAP_IGNORE(iConnectionMonitor.SetUintAttribute(EBearerIdAll, 0, KBearerGroupThreshold, 1));
+#endif
+ TRAP_IGNORE(iConnectionMonitor.NotifyEventL(*this));
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ TRAP(error, iCmManager.OpenL());
+ if (error != KErrNone) {
+ iInitOk = false;
+ return;
+ }
+#endif
+
+ SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
+ cpPriv->name = "UserChoice";
+ cpPriv->bearerType = QNetworkConfiguration::BearerUnknown;
+ cpPriv->state = QNetworkConfiguration::Discovered;
+ cpPriv->isValid = true;
+ cpPriv->id = QString::number(qHash(KUserChoiceIAPId));
+ cpPriv->numericId = KUserChoiceIAPId;
+ cpPriv->connectionId = 0;
+ cpPriv->type = QNetworkConfiguration::UserChoice;
+ cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
+ cpPriv->roamingSupported = false;
+
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ userChoiceConfigurations.insert(ptr->id, ptr);
+
+ updateConfigurations();
+ updateStatesToSnaps();
+ updateAvailableAccessPoints(); // On first time updates (without WLAN scans)
+ // Start monitoring IAP and/or SNAP changes in Symbian CommsDB
+ startCommsDatabaseNotifications();
+}
+
+SymbianEngine::~SymbianEngine()
+{
+ Cancel();
+
+ //The scanner may be using the connection monitor so it needs to be
+ //deleted first while the handle is still valid.
+ delete ipAccessPointsAvailabilityScanner;
+
+ iConnectionMonitor.CancelNotifications();
+ iConnectionMonitor.Close();
+
+ // CCommsDatabase destructor and RCmManager.Close() use cleanup stack. Since QNetworkConfigurationManager
+ // is a global static, but the time we are here, E32Main() has been exited already and
+ // the thread's default cleanup stack has been deleted. Without this line, a
+ // 'E32USER-CBase 69' -panic will occur.
+ CTrapCleanup* cleanup = CTrapCleanup::New();
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ iCmManager.Close();
+#endif
+ delete ipCommsDB;
+ delete cleanup;
+}
+
+void SymbianEngine::delayedConfigurationUpdate()
+{
+ QMutexLocker locker(&mutex);
+
+ if (iUpdatePending) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug("QNCM delayed configuration update (ECommit or ERecover occurred).");
+#endif
+ TRAPD(error, updateConfigurationsL());
+ if (error == KErrNone) {
+ updateStatesToSnaps();
+ }
+ iUpdatePending = false;
+ // Start monitoring again.
+ if (!IsActive()) {
+ SetActive();
+ // Start waiting for new notification
+ ipCommsDB->RequestNotification(iStatus);
+ }
+ }
+}
+
+bool SymbianEngine::hasIdentifier(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ return accessPointConfigurations.contains(id) ||
+ snapConfigurations.contains(id) ||
+ userChoiceConfigurations.contains(id);
+}
+
+QNetworkConfigurationManager::Capabilities SymbianEngine::capabilities() const
+{
+ QNetworkConfigurationManager::Capabilities capFlags;
+
+ capFlags = QNetworkConfigurationManager::CanStartAndStopInterfaces |
+ QNetworkConfigurationManager::DirectConnectionRouting |
+ QNetworkConfigurationManager::SystemSessionSupport |
+ QNetworkConfigurationManager::DataStatistics |
+ QNetworkConfigurationManager::NetworkSessionRequired;
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ capFlags |= QNetworkConfigurationManager::ApplicationLevelRoaming |
+ QNetworkConfigurationManager::ForcedRoaming;
+#endif
+
+ return capFlags;
+}
+
+QNetworkSessionPrivate *SymbianEngine::createSessionBackend()
+{
+ return new QNetworkSessionPrivateImpl(this);
+}
+
+void SymbianEngine::requestUpdate()
+{
+ QMutexLocker locker(&mutex);
+
+ if (!iInitOk || iUpdateGoingOn) {
+ return;
+ }
+ iUpdateGoingOn = true;
+
+ stopCommsDatabaseNotifications();
+ updateConfigurations(); // Synchronous call
+ updateAvailableAccessPoints(); // Asynchronous call
+}
+
+void SymbianEngine::updateConfigurations()
+{
+ if (!iInitOk)
+ return;
+
+ TRAP_IGNORE(updateConfigurationsL());
+}
+
+void SymbianEngine::updateConfigurationsL()
+{
+ QList<QString> knownConfigs = accessPointConfigurations.keys();
+ QList<QString> knownSnapConfigs = snapConfigurations.keys();
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ // S60 version is >= Series60 3rd Edition Feature Pack 2
+ TInt error = KErrNone;
+
+ // Loop through all IAPs
+ RArray<TUint32> connectionMethods; // IAPs
+ CleanupClosePushL(connectionMethods);
+ iCmManager.ConnectionMethodL(connectionMethods);
+ for(int i = 0; i < connectionMethods.Count(); i++) {
+ RCmConnectionMethod connectionMethod = iCmManager.ConnectionMethodL(connectionMethods[i]);
+ CleanupClosePushL(connectionMethod);
+ TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
+ QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(iapId));
+ if (accessPointConfigurations.contains(ident)) {
+ knownConfigs.removeOne(ident);
+ } else {
+ SymbianNetworkConfigurationPrivate* cpPriv = NULL;
+ TRAP(error, cpPriv = configFromConnectionMethodL(connectionMethod));
+ if (error == KErrNone) {
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ accessPointConfigurations.insert(ptr->id, ptr);
+ if (!iFirstUpdate) {
+ // Emit configuration added. Connected slots may throw execptions
+ // which propagate here --> must be converted to leaves (standard
+ // std::exception would cause any TRAP trapping this function to terminate
+ // program).
+ QT_TRYCATCH_LEAVING(updateActiveAccessPoints());
+ updateStatesToSnaps();
+ mutex.unlock();
+ QT_TRYCATCH_LEAVING(emit configurationAdded(ptr));
+ mutex.lock();
+ }
+ }
+ }
+ CleanupStack::PopAndDestroy(&connectionMethod);
+ }
+ CleanupStack::PopAndDestroy(&connectionMethods);
+
+ // Loop through all SNAPs
+ RArray<TUint32> destinations;
+ CleanupClosePushL(destinations);
+ iCmManager.AllDestinationsL(destinations);
+ for(int i = 0; i < destinations.Count(); i++) {
+ RCmDestination destination;
+
+ // Some destinatsions require ReadDeviceData -capability (MMS/WAP)
+ // The below function will leave in these cases. Don't. Proceed to
+ // next destination (if any).
+ TRAPD(error, destination = iCmManager.DestinationL(destinations[i]));
+ if (error == KErrPermissionDenied) {
+ continue;
+ } else {
+ User::LeaveIfError(error);
+ }
+
+ CleanupClosePushL(destination);
+ QString ident = QT_BEARERMGMT_CONFIGURATION_SNAP_PREFIX +
+ QString::number(qHash(destination.Id()));
+ if (snapConfigurations.contains(ident)) {
+ knownSnapConfigs.removeOne(ident);
+ } else {
+ SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
+
+ HBufC *pName = destination.NameLC();
+ QT_TRYCATCH_LEAVING(cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length()));
+ CleanupStack::PopAndDestroy(pName);
+ pName = NULL;
+
+ cpPriv->isValid = true;
+ cpPriv->id = ident;
+ cpPriv->numericId = destination.Id();
+ cpPriv->connectionId = 0;
+ cpPriv->state = QNetworkConfiguration::Defined;
+ cpPriv->type = QNetworkConfiguration::ServiceNetwork;
+ cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
+ cpPriv->roamingSupported = false;
+
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ snapConfigurations.insert(ident, ptr);
+ if (!iFirstUpdate) {
+ QT_TRYCATCH_LEAVING(updateActiveAccessPoints());
+ updateStatesToSnaps();
+ mutex.unlock();
+ QT_TRYCATCH_LEAVING(emit configurationAdded(ptr));
+ mutex.lock();
+ }
+ }
+
+ // Loop through all connection methods in this SNAP
+ QMap<unsigned int, QNetworkConfigurationPrivatePointer> connections;
+ for (int j=0; j < destination.ConnectionMethodCount(); j++) {
+ RCmConnectionMethod connectionMethod = destination.ConnectionMethodL(j);
+ CleanupClosePushL(connectionMethod);
+
+ TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
+ QString iface = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(iapId));
+ // Check that IAP can be found from accessPointConfigurations list
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
+ if (!ptr) {
+ SymbianNetworkConfigurationPrivate *cpPriv = NULL;
+ TRAP(error, cpPriv = configFromConnectionMethodL(connectionMethod));
+ if (error == KErrNone) {
+ ptr = QNetworkConfigurationPrivatePointer(cpPriv);
+ accessPointConfigurations.insert(ptr->id, ptr);
+
+ if (!iFirstUpdate) {
+ QT_TRYCATCH_LEAVING(updateActiveAccessPoints());
+ updateStatesToSnaps();
+ mutex.unlock();
+ QT_TRYCATCH_LEAVING(emit configurationAdded(ptr));
+ mutex.lock();
+ }
+ }
+ } else {
+ knownConfigs.removeOne(iface);
+ }
+
+ if (ptr) {
+ unsigned int priority;
+ TRAPD(error, priority = destination.PriorityL(connectionMethod));
+ if (!error)
+ connections.insert(priority, ptr);
+ }
+
+ CleanupStack::PopAndDestroy(&connectionMethod);
+ }
+
+ QNetworkConfigurationPrivatePointer privSNAP = snapConfigurations.value(ident);
+ QMutexLocker snapConfigLocker(&privSNAP->mutex);
+
+ if (privSNAP->serviceNetworkMembers != connections) {
+ privSNAP->serviceNetworkMembers = connections;
+
+ // Roaming is supported only if SNAP contains more than one IAP
+ privSNAP->roamingSupported = privSNAP->serviceNetworkMembers.count() > 1;
+
+ snapConfigLocker.unlock();
+
+ updateStatesToSnaps();
+
+ mutex.unlock();
+ QT_TRYCATCH_LEAVING(emit configurationChanged(privSNAP));
+ mutex.lock();
+ }
+
+ 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 = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId));
+ if (accessPointConfigurations.contains(ident)) {
+ knownConfigs.removeOne(ident);
+ } else {
+ SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
+ if (readNetworkConfigurationValuesFromCommsDb(apId, cpPriv)) {
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ accessPointConfigurations.insert(ident, ptr);
+ if (!iFirstUpdate) {
+ QT_TRYCATCH_LEAVING(updateActiveAccessPoints());
+ updateStatesToSnaps();
+ mutex.unlock();
+ QT_TRYCATCH_LEAVING(emit configurationAdded(ptr));
+ mutex.lock();
+ }
+ } else {
+ delete cpPriv;
+ }
+ }
+ retVal = pDbTView->GotoNextRecord();
+ }
+ CleanupStack::PopAndDestroy(pDbTView);
+#endif
+
+ QT_TRYCATCH_LEAVING(updateActiveAccessPoints());
+
+ foreach (const QString &oldIface, knownConfigs) {
+ //remove non existing IAP
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(oldIface);
+
+ mutex.unlock();
+ emit configurationRemoved(ptr);
+ QT_TRYCATCH_LEAVING(emit configurationRemoved(ptr));
+ mutex.lock();
+
+ // Remove non existing IAP from SNAPs
+ foreach (const QString &iface, snapConfigurations.keys()) {
+ QNetworkConfigurationPrivatePointer ptr2 = snapConfigurations.value(iface);
+ // => Check if one of the IAPs of the SNAP is active
+ QMutexLocker snapConfigLocker(&ptr2->mutex);
+ QMutableMapIterator<unsigned int, QNetworkConfigurationPrivatePointer> i(ptr2->serviceNetworkMembers);
+ while (i.hasNext()) {
+ i.next();
+
+ if (toSymbianConfig(i.value())->numericIdentifier() ==
+ toSymbianConfig(ptr)->numericIdentifier()) {
+ i.remove();
+ break;
+ }
+ }
+ }
+ }
+
+ foreach (const QString &oldIface, knownSnapConfigs) {
+ //remove non existing SNAPs
+ QNetworkConfigurationPrivatePointer ptr = snapConfigurations.take(oldIface);
+
+ mutex.unlock();
+ emit configurationRemoved(ptr);
+ QT_TRYCATCH_LEAVING(emit configurationRemoved(ptr));
+ mutex.lock();
+ }
+
+ // find default configuration.
+ stopCommsDatabaseNotifications();
+ TRAP_IGNORE(defaultConfig = defaultConfigurationL());
+ startCommsDatabaseNotifications();
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ updateStatesToSnaps();
+#endif
+}
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+SymbianNetworkConfigurationPrivate *SymbianEngine::configFromConnectionMethodL(
+ RCmConnectionMethod& connectionMethod)
+{
+ SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
+ TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
+ QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(iapId));
+
+ HBufC *pName = connectionMethod.GetStringAttributeL(CMManager::ECmName);
+ CleanupStack::PushL(pName);
+ QT_TRYCATCH_LEAVING(cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length()));
+ CleanupStack::PopAndDestroy(pName);
+ pName = NULL;
+
+ TUint32 bearerId = connectionMethod.GetIntAttributeL(CMManager::ECmCommsDBBearerType);
+ switch (bearerId) {
+ case KCommDbBearerCSD:
+ cpPriv->bearerType = QNetworkConfiguration::Bearer2G;
+ break;
+ case KCommDbBearerWcdma:
+ cpPriv->bearerType = QNetworkConfiguration::BearerWCDMA;
+ break;
+ case KCommDbBearerLAN:
+ cpPriv->bearerType = QNetworkConfiguration::BearerEthernet;
+ break;
+ case KCommDbBearerVirtual:
+ cpPriv->bearerType = QNetworkConfiguration::BearerUnknown;
+ break;
+ case KCommDbBearerPAN:
+ cpPriv->bearerType = QNetworkConfiguration::BearerUnknown;
+ break;
+ case KCommDbBearerWLAN:
+ cpPriv->bearerType = QNetworkConfiguration::BearerWLAN;
+ break;
+ default:
+ cpPriv->bearerType = QNetworkConfiguration::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);
+ QT_TRYCATCH_LEAVING(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;
+ return cpPriv;
+}
+#else
+bool SymbianEngine::readNetworkConfigurationValuesFromCommsDb(
+ TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration)
+{
+ TRAPD(error, readNetworkConfigurationValuesFromCommsDbL(aApId,apNetworkConfiguration));
+ if (error != KErrNone) {
+ return false;
+ }
+ return true;
+}
+
+void SymbianEngine::readNetworkConfigurationValuesFromCommsDbL(
+ TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration)
+{
+ CApDataHandler* pDataHandler = CApDataHandler::NewLC(*ipCommsDB);
+ CApAccessPointItem* pAPItem = CApAccessPointItem::NewLC();
+ TBuf<KCommsDbSvrMaxColumnNameLength> name;
+
+ CApUtils* pApUtils = CApUtils::NewLC(*ipCommsDB);
+ TUint32 apId = pApUtils->WapIdFromIapIdL(aApId);
+
+ pDataHandler->AccessPointDataL(apId,*pAPItem);
+ pAPItem->ReadTextL(EApIapName, name);
+ if (name.Compare(_L("Easy WLAN")) == 0) {
+ // "Easy WLAN" won't be accepted to the Configurations list
+ User::Leave(KErrNotFound);
+ }
+
+ QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(aApId));
+
+ QT_TRYCATCH_LEAVING(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->bearerType = QNetworkConfiguration::Bearer2G;
+ break;
+ case EApBearerTypeGPRS:
+ apNetworkConfiguration->bearerType = QNetworkConfiguration::Bearer2G;
+ break;
+ case EApBearerTypeHSCSD:
+ apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerHSPA;
+ break;
+ case EApBearerTypeCDMA:
+ apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerCDMA2000;
+ break;
+ case EApBearerTypeWLAN:
+ apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerWLAN;
+ break;
+ case EApBearerTypeLAN:
+ apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerEthernet;
+ break;
+ case EApBearerTypeLANModem:
+ apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerEthernet;
+ break;
+ default:
+ apNetworkConfiguration->bearerType = QNetworkConfiguration::BearerUnknown;
+ break;
+ }
+
+ CleanupStack::PopAndDestroy(pApUtils);
+ CleanupStack::PopAndDestroy(pAPItem);
+ CleanupStack::PopAndDestroy(pDataHandler);
+}
+#endif
+
+QNetworkConfigurationPrivatePointer SymbianEngine::defaultConfiguration()
+{
+ QMutexLocker locker(&mutex);
+
+ return defaultConfig;
+}
+
+QStringList SymbianEngine::accessPointConfigurationIdentifiers()
+{
+ QMutexLocker locker(&mutex);
+
+ return accessPointConfigurations.keys();
+}
+
+QNetworkConfigurationPrivatePointer SymbianEngine::defaultConfigurationL()
+{
+ QNetworkConfigurationPrivatePointer ptr;
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ // Check Default Connection (SNAP or IAP)
+ TCmDefConnValue defaultConnectionValue;
+ iCmManager.ReadDefConnL(defaultConnectionValue);
+ if (defaultConnectionValue.iType == ECmDefConnDestination) {
+ QString iface = QT_BEARERMGMT_CONFIGURATION_SNAP_PREFIX +
+ QString::number(qHash(defaultConnectionValue.iId));
+ ptr = snapConfigurations.value(iface);
+ } else if (defaultConnectionValue.iType == ECmDefConnConnectionMethod) {
+ QString iface = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX +
+ QString::number(qHash(defaultConnectionValue.iId));
+ ptr = accessPointConfigurations.value(iface);
+ }
+#endif
+
+ if (ptr) {
+ QMutexLocker configLocker(&ptr->mutex);
+ if (ptr->isValid)
+ return ptr;
+ }
+
+ QString iface = QString::number(qHash(KUserChoiceIAPId));
+ return userChoiceConfigurations.value(iface);
+}
+
+void SymbianEngine::updateActiveAccessPoints()
+{
+ bool online = false;
+ QList<QString> inactiveConfigs = accessPointConfigurations.keys();
+
+ TRequestStatus status;
+ TUint connectionCount;
+ iConnectionMonitor.GetConnectionCount(connectionCount, status);
+ User::WaitForRequest(status);
+
+ // Go through all connections and set state of related IAPs to Active.
+ // Status needs to be checked carefully, because ConnMon lists also e.g.
+ // WLAN connections that are being currently tried --> we don't want to
+ // state these as active.
+ TUint connectionId;
+ TUint subConnectionCount;
+ TUint apId;
+ TInt connectionStatus;
+ 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 = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId));
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (!ptr) {
+ // If IAP was not found, check if the update was about EasyWLAN
+ ptr = configurationFromEasyWlan(apId, connectionId);
+ // Change the ident correspondingly
+ if (ptr) {
+ ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX +
+ QString::number(qHash(toSymbianConfig(ptr)->numericIdentifier()));
+ }
+ }
+#endif
+ if (ptr) {
+ iConnectionMonitor.GetIntAttribute(connectionId, subConnectionCount, KConnectionStatus, connectionStatus, status);
+ User::WaitForRequest(status);
+
+ if (connectionStatus == KLinkLayerOpen) {
+ online = true;
+ inactiveConfigs.removeOne(ident);
+
+ ptr->mutex.lock();
+ toSymbianConfig(ptr)->connectionId = connectionId;
+ ptr->mutex.unlock();
+
+ // Configuration is Active
+ changeConfigurationStateTo(ptr, QNetworkConfiguration::Active);
+ }
+ }
+ }
+ }
+
+ // Make sure that state of rest of the IAPs won't be Active
+ foreach (const QString &iface, inactiveConfigs) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
+ if (ptr) {
+ // Configuration is either Defined or Discovered
+ changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered);
+ }
+ }
+
+ if (iOnline != online) {
+ iOnline = online;
+ mutex.unlock();
+ emit this->onlineStateChanged(online);
+ mutex.lock();
+ }
+}
+
+void SymbianEngine::updateAvailableAccessPoints()
+{
+ if (!ipAccessPointsAvailabilityScanner) {
+ ipAccessPointsAvailabilityScanner = new AccessPointsAvailabilityScanner(*this, iConnectionMonitor);
+ }
+ if (ipAccessPointsAvailabilityScanner) {
+ // Scanning may take a while because WLAN scanning will be done (if device supports WLAN).
+ ipAccessPointsAvailabilityScanner->StartScanning();
+ }
+}
+
+void SymbianEngine::accessPointScanningReady(TBool scanSuccessful, TConnMonIapInfo iapInfo)
+{
+ iUpdateGoingOn = false;
+ if (scanSuccessful) {
+ QList<QString> unavailableConfigs = accessPointConfigurations.keys();
+
+ // Set state of returned IAPs to Discovered
+ // if state is not already Active
+ for(TUint i=0; i<iapInfo.iCount; i++) {
+ QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX +
+ QString::number(qHash(iapInfo.iIap[i].iIapId));
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+ if (ptr) {
+ unavailableConfigs.removeOne(ident);
+
+ QMutexLocker configLocker(&ptr->mutex);
+ if (ptr->state < QNetworkConfiguration::Active) {
+ // Configuration is either Discovered or Active
+ changeConfigurationStateAtMinTo(ptr, QNetworkConfiguration::Discovered);
+ }
+ }
+ }
+
+ // Make sure that state of rest of the IAPs won't be Active
+ foreach (const QString &iface, unavailableConfigs) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
+ if (ptr) {
+ // Configuration is Defined
+ changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered);
+ }
+ }
+ }
+
+ updateStatesToSnaps();
+
+ if (!iFirstUpdate) {
+ startCommsDatabaseNotifications();
+ mutex.unlock();
+ emit updateCompleted();
+ mutex.lock();
+ } else {
+ iFirstUpdate = false;
+ if (iScanInQueue) {
+ iScanInQueue = EFalse;
+ updateAvailableAccessPoints();
+ }
+ }
+}
+
+void SymbianEngine::updateStatesToSnaps()
+{
+ // Go through SNAPs and set correct state to SNAPs
+ foreach (const QString &iface, snapConfigurations.keys()) {
+ bool discovered = false;
+ bool active = false;
+ QNetworkConfigurationPrivatePointer ptr = snapConfigurations.value(iface);
+
+ QMutexLocker snapConfigLocker(&ptr->mutex);
+
+ // => 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
+ QMapIterator<unsigned int, QNetworkConfigurationPrivatePointer> i(ptr->serviceNetworkMembers);
+ while (i.hasNext()) {
+ i.next();
+
+ const QNetworkConfigurationPrivatePointer child = i.value();
+
+ QMutexLocker configLocker(&child->mutex);
+
+ if ((child->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ active = true;
+ break;
+ } else if ((child->state & QNetworkConfiguration::Discovered) ==
+ QNetworkConfiguration::Discovered) {
+ discovered = true;
+ }
+ }
+ snapConfigLocker.unlock();
+ if (active) {
+ changeConfigurationStateTo(ptr, QNetworkConfiguration::Active);
+ } else if (discovered) {
+ changeConfigurationStateTo(ptr, QNetworkConfiguration::Discovered);
+ } else {
+ changeConfigurationStateTo(ptr, QNetworkConfiguration::Defined);
+ }
+ }
+}
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+void SymbianEngine::updateMobileBearerToConfigs(TConnMonBearerInfo bearerInfo)
+{
+ QHash<QString, QNetworkConfigurationPrivatePointer>::const_iterator i =
+ accessPointConfigurations.constBegin();
+ while (i != accessPointConfigurations.constEnd()) {
+ QNetworkConfigurationPrivatePointer ptr = i.value();
+
+ QMutexLocker locker(&ptr->mutex);
+
+ SymbianNetworkConfigurationPrivate *p = toSymbianConfig(ptr);
+
+ if (p->bearerType >= QNetworkConfiguration::Bearer2G &&
+ p->bearerType <= QNetworkConfiguration::BearerHSPA) {
+ switch (bearerInfo) {
+ case EBearerInfoCSD:
+ p->bearerType = QNetworkConfiguration::Bearer2G;
+ break;
+ case EBearerInfoWCDMA:
+ p->bearerType = QNetworkConfiguration::BearerWCDMA;
+ break;
+ case EBearerInfoCDMA2000:
+ p->bearerType = QNetworkConfiguration::BearerCDMA2000;
+ break;
+ case EBearerInfoGPRS:
+ p->bearerType = QNetworkConfiguration::Bearer2G;
+ break;
+ case EBearerInfoHSCSD:
+ p->bearerType = QNetworkConfiguration::Bearer2G;
+ break;
+ case EBearerInfoEdgeGPRS:
+ p->bearerType = QNetworkConfiguration::Bearer2G;
+ break;
+ case EBearerInfoWcdmaCSD:
+ p->bearerType = QNetworkConfiguration::BearerWCDMA;
+ break;
+ case EBearerInfoHSDPA:
+ p->bearerType = QNetworkConfiguration::BearerHSPA;
+ break;
+ case EBearerInfoHSUPA:
+ p->bearerType = QNetworkConfiguration::BearerHSPA;
+ break;
+ case EBearerInfoHSxPA:
+ p->bearerType = QNetworkConfiguration::BearerHSPA;
+ break;
+ }
+ }
+
+ ++i;
+ }
+}
+#endif
+
+bool SymbianEngine::changeConfigurationStateTo(QNetworkConfigurationPrivatePointer ptr,
+ QNetworkConfiguration::StateFlags newState)
+{
+ ptr->mutex.lock();
+ if (newState != ptr->state) {
+ ptr->state = newState;
+ ptr->mutex.unlock();
+
+ mutex.unlock();
+ emit configurationChanged(ptr);
+ mutex.lock();
+
+ return true;
+ } else {
+ ptr->mutex.unlock();
+ }
+ return false;
+}
+
+/* changeConfigurationStateAtMinTo function does not overwrite possible better
+ * state (e.g. Discovered state does not overwrite Active state) but
+ * makes sure that state is at minimum given state.
+*/
+bool SymbianEngine::changeConfigurationStateAtMinTo(QNetworkConfigurationPrivatePointer ptr,
+ QNetworkConfiguration::StateFlags newState)
+{
+ ptr->mutex.lock();
+ if ((newState | ptr->state) != ptr->state) {
+ ptr->state = (ptr->state | newState);
+ ptr->mutex.unlock();
+
+ mutex.unlock();
+ emit configurationChanged(ptr);
+ mutex.lock();
+
+ return true;
+ } else {
+ ptr->mutex.unlock();
+ }
+ return false;
+}
+
+/* changeConfigurationStateAtMaxTo function overwrites possible better
+ * state (e.g. Discovered state overwrites Active state) and
+ * makes sure that state is at maximum given state (e.g. Discovered state
+ * does not overwrite Defined state).
+*/
+bool SymbianEngine::changeConfigurationStateAtMaxTo(QNetworkConfigurationPrivatePointer ptr,
+ QNetworkConfiguration::StateFlags newState)
+{
+ ptr->mutex.lock();
+ if ((newState & ptr->state) != ptr->state) {
+ ptr->state = (newState & ptr->state);
+ ptr->mutex.unlock();
+
+ mutex.unlock();
+ emit configurationChanged(ptr);
+ mutex.lock();
+
+ return true;
+ } else {
+ ptr->mutex.unlock();
+ }
+ return false;
+}
+
+void SymbianEngine::startCommsDatabaseNotifications()
+{
+ if (!iWaitingCommsDatabaseNotifications) {
+ iWaitingCommsDatabaseNotifications = ETrue;
+ if (!IsActive()) {
+ SetActive();
+ // Start waiting for new notification
+ ipCommsDB->RequestNotification(iStatus);
+ }
+ }
+}
+
+void SymbianEngine::stopCommsDatabaseNotifications()
+{
+ if (iWaitingCommsDatabaseNotifications) {
+ iWaitingCommsDatabaseNotifications = EFalse;
+ Cancel();
+ }
+}
+
+void SymbianEngine::RunL()
+{
+ QMutexLocker locker(&mutex);
+
+ if (iStatus != KErrCancel) {
+ // By default, start relistening notifications. Stop only if interesting event occurred.
+ iWaitingCommsDatabaseNotifications = true;
+ RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int());
+ switch (event) {
+ case RDbNotifier::ECommit: /** A transaction has been committed. */
+ case RDbNotifier::ERecover: /** The database has been recovered */
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug("QNCM CommsDB event (of type RDbNotifier::TEvent) received: %d", iStatus.Int());
+#endif
+ // Mark that there is update pending. No need to ask more events,
+ // as we know we will be updating anyway when the timer expires.
+ if (!iUpdatePending) {
+ iUpdatePending = true;
+ iWaitingCommsDatabaseNotifications = false;
+ // Update after random time, so that many processes won't
+ // start updating simultaneously
+ updateConfigurationsAfterRandomTime();
+ }
+ break;
+ default:
+ // Do nothing
+ break;
+ }
+ }
+
+ if (iWaitingCommsDatabaseNotifications) {
+ if (!IsActive()) {
+ SetActive();
+ // Start waiting for new notification
+ ipCommsDB->RequestNotification(iStatus);
+ }
+ }
+}
+
+void SymbianEngine::DoCancel()
+{
+ QMutexLocker locker(&mutex);
+
+ ipCommsDB->CancelRequestNotification();
+}
+
+void SymbianEngine::EventL(const CConnMonEventBase& aEvent)
+{
+ QMutexLocker locker(&mutex);
+
+ switch (aEvent.EventType()) {
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ case EConnMonBearerInfoChange:
+ {
+ CConnMonBearerInfoChange* realEvent;
+ realEvent = (CConnMonBearerInfoChange*) &aEvent;
+ TUint connectionId = realEvent->ConnectionId();
+ if (connectionId == EBearerIdAll) {
+ //Network level event
+ TConnMonBearerInfo bearerInfo = (TConnMonBearerInfo)realEvent->BearerInfo();
+ updateMobileBearerToConfigs(bearerInfo);
+ }
+ break;
+ }
+#endif
+ case EConnMonConnectionStatusChange:
+ {
+ CConnMonConnectionStatusChange* realEvent;
+ realEvent = (CConnMonConnectionStatusChange*) &aEvent;
+ TInt connectionStatus = realEvent->ConnectionStatus();
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNCM Connection status : " << QString::number(connectionStatus) << " , connection monitor Id : " << realEvent->ConnectionId();
+#endif
+ if (connectionStatus == KConfigDaemonStartingRegistration) {
+ TUint connectionId = realEvent->ConnectionId();
+ TUint subConnectionCount = 0;
+ TUint apId;
+ TRequestStatus status;
+ iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
+ User::WaitForRequest(status);
+
+ QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId));
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (!ptr) {
+ // Check if status was regarding EasyWLAN
+ ptr = configurationFromEasyWlan(apId, connectionId);
+ }
+#endif
+ if (ptr) {
+ ptr->mutex.lock();
+ toSymbianConfig(ptr)->connectionId = connectionId;
+ ptr->mutex.unlock();
+ QT_TRYCATCH_LEAVING(
+ emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(),
+ connectionId, QNetworkSession::Connecting)
+ );
+ }
+ } else if (connectionStatus == KLinkLayerOpen) {
+ // Connection has been successfully opened
+ TUint connectionId = realEvent->ConnectionId();
+ TUint subConnectionCount = 0;
+ TUint apId;
+ TRequestStatus status;
+ iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
+ User::WaitForRequest(status);
+ QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId));
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (!ptr) {
+ // Check for EasyWLAN
+ ptr = configurationFromEasyWlan(apId, connectionId);
+ }
+#endif
+ if (ptr) {
+ ptr->mutex.lock();
+ toSymbianConfig(ptr)->connectionId = connectionId;
+ ptr->mutex.unlock();
+
+ // Configuration is Active
+ QT_TRYCATCH_LEAVING(
+ if (changeConfigurationStateTo(ptr, QNetworkConfiguration::Active)) {
+ updateStatesToSnaps();
+ }
+ emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(),
+ connectionId, QNetworkSession::Connected);
+
+ if (!iOnline) {
+ iOnline = true;
+ emit this->onlineStateChanged(iOnline);
+ }
+ );
+ }
+ } else if (connectionStatus == KConfigDaemonStartingDeregistration) {
+ TUint connectionId = realEvent->ConnectionId();
+ QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId);
+ if (ptr) {
+ QT_TRYCATCH_LEAVING(
+ emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(),
+ connectionId, QNetworkSession::Closing)
+ );
+ }
+ } else if (connectionStatus == KLinkLayerClosed ||
+ connectionStatus == KConnectionClosed) {
+ // Connection has been closed. Which of the above events is reported, depends on the Symbian
+ // platform.
+ TUint connectionId = realEvent->ConnectionId();
+ QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId);
+ if (ptr) {
+ // Configuration is either Defined or Discovered
+ QT_TRYCATCH_LEAVING(
+ if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered)) {
+ updateStatesToSnaps();
+ }
+ emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(),
+ connectionId, QNetworkSession::Disconnected);
+ );
+ }
+
+ bool online = false;
+ foreach (const QString &iface, accessPointConfigurations.keys()) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
+ QMutexLocker configLocker(&ptr->mutex);
+ if (ptr->state == QNetworkConfiguration::Active) {
+ online = true;
+ break;
+ }
+ }
+ if (iOnline != online) {
+ iOnline = online;
+ QT_TRYCATCH_LEAVING(emit this->onlineStateChanged(iOnline));
+ }
+ }
+ }
+ break;
+
+ case EConnMonIapAvailabilityChange:
+ {
+ CConnMonIapAvailabilityChange* realEvent;
+ realEvent = (CConnMonIapAvailabilityChange*) &aEvent;
+ TConnMonIapInfo iaps = realEvent->IapAvailability();
+ QList<QString> unDiscoveredConfigs = accessPointConfigurations.keys();
+ for ( TUint i = 0; i < iaps.Count(); i++ ) {
+ QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX +
+ QString::number(qHash(iaps.iIap[i].iIapId));
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+ if (ptr) {
+ // Configuration is either Discovered or Active
+ QT_TRYCATCH_LEAVING(changeConfigurationStateAtMinTo(ptr, QNetworkConfiguration::Discovered));
+ unDiscoveredConfigs.removeOne(ident);
+ }
+ }
+ foreach (const QString &iface, unDiscoveredConfigs) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
+ if (ptr) {
+ // Configuration is Defined
+ QT_TRYCATCH_LEAVING(changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Defined));
+ }
+ }
+ // Something has in IAPs, update states to SNAPs
+ updateStatesToSnaps();
+ }
+ break;
+
+ case EConnMonCreateConnection:
+ {
+ // This event is caught to keep connection monitor IDs up-to-date.
+ 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 = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX+QString::number(qHash(apId));
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (!ptr) {
+ // If IAP was not found, check if the update was about EasyWLAN
+ ptr = configurationFromEasyWlan(apId, connectionId);
+ }
+#endif
+ if (ptr) {
+ QMutexLocker configLocker(&ptr->mutex);
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNCM updating connection monitor ID : from, to, whose: " << toSymbianConfig(ptr)->connectionId << connectionId << ptr->name;
+#endif
+ toSymbianConfig(ptr)->connectionId = connectionId;
+ }
+ }
+ break;
+ default:
+ // For unrecognized events
+ break;
+ }
+}
+
+/*
+ Returns the network configuration that matches the given SSID.
+*/
+QNetworkConfigurationPrivatePointer SymbianEngine::configurationFromSsid(const QString &ssid)
+{
+ QMutexLocker locker(&mutex);
+
+ // Browser through all items and check their name for match
+ QHash<QString, QNetworkConfigurationPrivatePointer>::ConstIterator i =
+ accessPointConfigurations.constBegin();
+ while (i != accessPointConfigurations.constEnd()) {
+ QNetworkConfigurationPrivatePointer ptr = i.value();
+
+ QMutexLocker configLocker(&ptr->mutex);
+
+ if (ptr->name == ssid) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNCM EasyWlan uses real SSID: " << ssid;
+#endif
+ return ptr;
+ }
+ ++i;
+ }
+
+ return QNetworkConfigurationPrivatePointer();
+}
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+// Tries to derive configuration from EasyWLAN.
+// First checks if the interface brought up was EasyWLAN, then derives the real SSID,
+// and looks up configuration based on that one.
+QNetworkConfigurationPrivatePointer SymbianEngine::configurationFromEasyWlan(TUint32 apId,
+ TUint connectionId)
+{
+ if (apId == iCmManager.EasyWlanIdL()) {
+ TRequestStatus status;
+ TBuf<50> easyWlanNetworkName;
+ iConnectionMonitor.GetStringAttribute( connectionId, 0, KNetworkName,
+ easyWlanNetworkName, status );
+ User::WaitForRequest(status);
+ if (status.Int() == KErrNone) {
+ const QString realSSID = QString::fromUtf16(easyWlanNetworkName.Ptr(),
+ easyWlanNetworkName.Length());
+
+ // Browser through all items and check their name for match
+ QHash<QString, QNetworkConfigurationPrivatePointer>::ConstIterator i =
+ accessPointConfigurations.constBegin();
+ while (i != accessPointConfigurations.constEnd()) {
+ QNetworkConfigurationPrivatePointer ptr = i.value();
+
+ QMutexLocker configLocker(&ptr->mutex);
+
+ if (ptr->name == realSSID) {
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNCM EasyWlan uses real SSID: " << realSSID;
+#endif
+ return ptr;
+ }
+ ++i;
+ }
+ }
+ }
+ return QNetworkConfigurationPrivatePointer();
+}
+#endif
+
+// Sessions may use this function to report configuration state changes,
+// because on some Symbian platforms (especially Symbian^3) all state changes are not
+// reported by the RConnectionMonitor, in particular in relation to stop() call,
+// whereas they _are_ reported on RConnection progress notifier used by sessions --> centralize
+// this data here so that other sessions may benefit from it too (not all sessions necessarily have
+// RConnection progress notifiers available but they relay on having e.g. disconnected information from
+// manager). Currently only 'Disconnected' state is of interest because it has proven to be troublesome.
+void SymbianEngine::configurationStateChangeReport(TUint32 accessPointId, QNetworkSession::State newState)
+{
+ QMutexLocker locker(&mutex);
+
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug() << "QNCM A session reported state change for IAP ID: " << accessPointId << " whose new state is: " << newState;
+#endif
+ switch (newState) {
+ case QNetworkSession::Disconnected:
+ {
+ QString ident = QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX +
+ QString::number(qHash(accessPointId));
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+ if (ptr) {
+ // Configuration is either Defined or Discovered
+ if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered)) {
+ updateStatesToSnaps();
+ }
+
+ locker.unlock();
+ emit configurationStateChanged(toSymbianConfig(ptr)->numericIdentifier(),
+ toSymbianConfig(ptr)->connectionIdentifier(),
+ QNetworkSession::Disconnected);
+ locker.relock();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+}
+
+// Waits for 2..6 seconds.
+void SymbianEngine::updateConfigurationsAfterRandomTime()
+{
+ int iTimeToWait = qMax(1000, (qAbs(qrand()) % 68) * 100);
+#ifdef QT_BEARERMGMT_SYMBIAN_DEBUG
+ qDebug("QNCM waiting random time: %d ms", iTimeToWait);
+#endif
+ QTimer::singleShot(iTimeToWait, this, SLOT(delayedConfigurationUpdate()));
+}
+
+QNetworkConfigurationPrivatePointer SymbianEngine::dataByConnectionId(TUint aConnectionId)
+{
+ QNetworkConfiguration item;
+ QHash<QString, QNetworkConfigurationPrivatePointer>::const_iterator i =
+ accessPointConfigurations.constBegin();
+ while (i != accessPointConfigurations.constEnd()) {
+ QNetworkConfigurationPrivatePointer ptr = i.value();
+ if (toSymbianConfig(ptr)->connectionIdentifier() == aConnectionId)
+ return ptr;
+
+ ++i;
+ }
+
+ return QNetworkConfigurationPrivatePointer();
+}
+
+AccessPointsAvailabilityScanner::AccessPointsAvailabilityScanner(SymbianEngine& owner,
+ RConnectionMonitor& connectionMonitor)
+ : CActive(CActive::EPriorityHigh), iOwner(owner), iConnectionMonitor(connectionMonitor)
+{
+ CActiveScheduler::Add(this);
+}
+
+AccessPointsAvailabilityScanner::~AccessPointsAvailabilityScanner()
+{
+ Cancel();
+}
+
+void AccessPointsAvailabilityScanner::DoCancel()
+{
+ iConnectionMonitor.CancelAsyncRequest(EConnMonGetPckgAttribute);
+ iScanActive = EFalse;
+ iOwner.iScanInQueue = EFalse;
+}
+
+void AccessPointsAvailabilityScanner::StartScanning()
+{
+ if (!iScanActive) {
+ iScanActive = ETrue;
+ if (iOwner.iFirstUpdate) {
+ // On first update (the mgr is being instantiated) update only those bearers who
+ // don't need time-consuming scans (WLAN).
+ // Note: EBearerIdWCDMA covers also GPRS bearer
+ iConnectionMonitor.GetPckgAttribute(EBearerIdWCDMA, 0, KIapAvailability, iIapBuf, iStatus);
+ } else {
+ iConnectionMonitor.GetPckgAttribute(EBearerIdAll, 0, KIapAvailability, iIapBuf, iStatus);
+ }
+
+ if (!IsActive()) {
+ SetActive();
+ }
+ } else {
+ // Queue scan for getting WLAN info after first request returns
+ if (iOwner.iFirstUpdate) {
+ iOwner.iScanInQueue = ETrue;
+ }
+ }
+}
+
+void AccessPointsAvailabilityScanner::RunL()
+{
+ QMutexLocker locker(&iOwner.mutex);
+
+ iScanActive = EFalse;
+ if (iStatus.Int() != KErrNone) {
+ iIapBuf().iCount = 0;
+ QT_TRYCATCH_LEAVING(iOwner.accessPointScanningReady(false,iIapBuf()));
+ } else {
+ QT_TRYCATCH_LEAVING(iOwner.accessPointScanningReady(true,iIapBuf()));
+ }
+}
+
+QT_END_NAMESPACE
+
+#endif // QT_NO_BEARERMANAGEMENT
diff --git a/src/plugins/bearer/symbian/symbianengine.h b/src/plugins/bearer/symbian/symbianengine.h
new file mode 100644
index 0000000000..1ab41ba45f
--- /dev/null
+++ b/src/plugins/bearer/symbian/symbianengine.h
@@ -0,0 +1,246 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SYMBIANENGINE_H
+#define SYMBIANENGINE_H
+
+#include <QtCore/qstringlist.h>
+#include <QtNetwork/private/qbearerengine_p.h>
+#include <QtNetwork/qnetworkconfigmanager.h>
+
+#include <QHash>
+#include <rconnmon.h>
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ #include <cmmanager.h>
+#endif
+
+// Uncomment and compile QtBearer to gain detailed state tracing
+// #define QT_BEARERMGMT_SYMBIAN_DEBUG
+
+#define QT_BEARERMGMT_CONFIGURATION_SNAP_PREFIX QLatin1String("S_")
+#define QT_BEARERMGMT_CONFIGURATION_IAP_PREFIX QLatin1String("I_")
+
+class CCommsDatabase;
+class QEventLoop;
+
+QT_BEGIN_NAMESPACE
+class QTimer;
+QT_END_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkSessionPrivate;
+class AccessPointsAvailabilityScanner;
+
+class SymbianNetworkConfigurationPrivate : public QNetworkConfigurationPrivate
+{
+public:
+ SymbianNetworkConfigurationPrivate();
+ ~SymbianNetworkConfigurationPrivate();
+
+ inline TUint32 numericIdentifier() const
+ {
+ QMutexLocker locker(&mutex);
+ return numericId;
+ }
+
+ inline TUint connectionIdentifier() const
+ {
+ QMutexLocker locker(&mutex);
+ return connectionId;
+ }
+
+ inline QString configMappingName() const
+ {
+ QMutexLocker locker(&mutex);
+ return mappingName;
+ }
+
+ QString mappingName;
+
+ // So called IAP id from the platform. Remains constant as long as the
+ // platform is aware of the configuration ie. it is stored in the databases
+ // --> does not depend on whether connections are currently open or not.
+ // In practice is the same for the lifetime of the QNetworkConfiguration.
+ TUint32 numericId;
+ // So called connection id, or connection monitor ID. A dynamic ID assigned
+ // by RConnectionMonitor whenever a new connection is opened. ConnectionID and
+ // numericId/IAP id have 1-to-1 mapping during the lifetime of the connection at
+ // connection monitor. Notably however it changes whenever a new connection to
+ // a given IAP is created. In a sense it is constant during the time the
+ // configuration remains between states Discovered..Active..Discovered, do not
+ // however relay on this.
+ TUint connectionId;
+};
+
+inline SymbianNetworkConfigurationPrivate *toSymbianConfig(QNetworkConfigurationPrivatePointer ptr)
+{
+ return static_cast<SymbianNetworkConfigurationPrivate *>(ptr.data());
+}
+
+class SymbianEngine : public QBearerEngine, public CActive,
+ public MConnectionMonitorObserver
+{
+ Q_OBJECT
+
+public:
+ SymbianEngine(QObject *parent = 0);
+ virtual ~SymbianEngine();
+
+ bool hasIdentifier(const QString &id);
+
+ Q_INVOKABLE void initialize();
+ Q_INVOKABLE void requestUpdate();
+
+ QNetworkConfigurationManager::Capabilities capabilities() const;
+
+ QNetworkSessionPrivate *createSessionBackend();
+
+ QNetworkConfigurationPrivatePointer defaultConfiguration();
+
+ QStringList accessPointConfigurationIdentifiers();
+
+ QNetworkConfigurationPrivatePointer configurationFromSsid(const QString &ssid);
+
+ // For QNetworkSessionPrivateImpl to indicate about state changes
+ void configurationStateChangeReport(TUint32 accessPointId, QNetworkSession::State newState);
+
+Q_SIGNALS:
+ void onlineStateChanged(bool isOnline);
+
+ void configurationStateChanged(quint32 accessPointId, quint32 connMonId,
+ QNetworkSession::State newState);
+
+public Q_SLOTS:
+ void updateConfigurations();
+ void delayedConfigurationUpdate();
+
+private:
+ void updateStatesToSnaps();
+ bool changeConfigurationStateTo(QNetworkConfigurationPrivatePointer ptr,
+ QNetworkConfiguration::StateFlags newState);
+ bool changeConfigurationStateAtMinTo(QNetworkConfigurationPrivatePointer ptr,
+ QNetworkConfiguration::StateFlags newState);
+ bool changeConfigurationStateAtMaxTo(QNetworkConfigurationPrivatePointer ptr,
+ QNetworkConfiguration::StateFlags newState);
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ void updateMobileBearerToConfigs(TConnMonBearerInfo bearerInfo);
+ SymbianNetworkConfigurationPrivate *configFromConnectionMethodL(RCmConnectionMethod& connectionMethod);
+#else
+ bool readNetworkConfigurationValuesFromCommsDb(
+ TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration);
+ void readNetworkConfigurationValuesFromCommsDbL(
+ TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration);
+#endif
+
+ void updateConfigurationsL();
+ void updateActiveAccessPoints();
+ void updateAvailableAccessPoints();
+ void accessPointScanningReady(TBool scanSuccessful, TConnMonIapInfo iapInfo);
+ void startCommsDatabaseNotifications();
+ void stopCommsDatabaseNotifications();
+ void updateConfigurationsAfterRandomTime();
+
+ QNetworkConfigurationPrivatePointer defaultConfigurationL();
+ TBool GetS60PlatformVersion(TUint& aMajor, TUint& aMinor) const;
+ void startMonitoringIAPData(TUint32 aIapId);
+ QNetworkConfigurationPrivatePointer dataByConnectionId(TUint aConnectionId);
+
+protected:
+ // From CActive
+ void RunL();
+ void DoCancel();
+
+private:
+ // MConnectionMonitorObserver
+ void EventL(const CConnMonEventBase& aEvent);
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ QNetworkConfigurationPrivatePointer configurationFromEasyWlan(TUint32 apId,
+ TUint connectionId);
+#endif
+
+private: // Data
+ bool iFirstUpdate;
+ CCommsDatabase* ipCommsDB;
+ RConnectionMonitor iConnectionMonitor;
+
+ TBool iWaitingCommsDatabaseNotifications;
+ TBool iOnline;
+ TBool iInitOk;
+ TBool iUpdateGoingOn;
+ TBool iUpdatePending;
+ TBool iScanInQueue;
+
+ AccessPointsAvailabilityScanner* ipAccessPointsAvailabilityScanner;
+
+ QNetworkConfigurationPrivatePointer defaultConfig;
+
+ friend class QNetworkSessionPrivate;
+ friend class AccessPointsAvailabilityScanner;
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ RCmManager iCmManager;
+#endif
+};
+
+class AccessPointsAvailabilityScanner : public CActive
+{
+public:
+ AccessPointsAvailabilityScanner(SymbianEngine& owner,
+ RConnectionMonitor& connectionMonitor);
+ ~AccessPointsAvailabilityScanner();
+
+ void StartScanning();
+
+protected: // From CActive
+ void RunL();
+ void DoCancel();
+
+private: // Data
+ SymbianEngine& iOwner;
+ RConnectionMonitor& iConnectionMonitor;
+ TConnMonIapInfoBuf iIapBuf;
+ TBool iScanActive;
+};
+
+QT_END_NAMESPACE
+
+#endif