summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorWarwick Allison <warwick.allison@nokia.com>2010-02-24 05:07:11 (GMT)
committerWarwick Allison <warwick.allison@nokia.com>2010-02-24 05:07:11 (GMT)
commit485f0bfd5761eff264712fcc0bd46c66470be505 (patch)
tree24a9762a3d5c87d267fab398d5598dbd46b646fe /src
parent7c76abb0dc4204043bec9b6fa315f9753a7986ae (diff)
parent4d615766184e3eeee25ffc634847bec1edd47ac0 (diff)
downloadQt-485f0bfd5761eff264712fcc0bd46c66470be505.zip
Qt-485f0bfd5761eff264712fcc0bd46c66470be505.tar.gz
Qt-485f0bfd5761eff264712fcc0bd46c66470be505.tar.bz2
Merge branch 'master' of git://scm.dev.nokia.troll.no/qt/qt
Conflicts: tests/auto/declarative/qmlgraphicsborderimage/tst_qmlgraphicsborderimage.cpp tests/auto/declarative/qmlgraphicsimage/tst_qmlgraphicsimage.cpp
Diffstat (limited to 'src')
-rw-r--r--src/gui/painting/qpainter.cpp1
-rw-r--r--src/network/access/qnetworkaccessbackend.cpp33
-rw-r--r--src/network/access/qnetworkaccessbackend_p.h6
-rw-r--r--src/network/access/qnetworkaccesshttpbackend.cpp48
-rw-r--r--src/network/access/qnetworkaccesshttpbackend_p.h5
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp198
-rw-r--r--src/network/access/qnetworkaccessmanager.h17
-rw-r--r--src/network/access/qnetworkaccessmanager_p.h15
-rw-r--r--src/network/access/qnetworkreply.cpp5
-rw-r--r--src/network/access/qnetworkreply.h1
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp160
-rw-r--r--src/network/access/qnetworkreplyimpl_p.h31
-rw-r--r--src/network/bearer/bearer.pri18
-rw-r--r--src/network/bearer/qbearerengine.cpp75
-rw-r--r--src/network/bearer/qbearerengine_p.h112
-rw-r--r--src/network/bearer/qbearerplugin.cpp57
-rw-r--r--src/network/bearer/qbearerplugin_p.h93
-rw-r--r--src/network/bearer/qnetworkconfigmanager.cpp419
-rw-r--r--src/network/bearer/qnetworkconfigmanager.h101
-rw-r--r--src/network/bearer/qnetworkconfigmanager_p.cpp211
-rw-r--r--src/network/bearer/qnetworkconfigmanager_p.h114
-rw-r--r--src/network/bearer/qnetworkconfiguration.cpp396
-rw-r--r--src/network/bearer/qnetworkconfiguration.h115
-rw-r--r--src/network/bearer/qnetworkconfiguration_p.h107
-rw-r--r--src/network/bearer/qnetworksession.cpp684
-rw-r--r--src/network/bearer/qnetworksession.h132
-rw-r--r--src/network/bearer/qnetworksession_p.h150
-rw-r--r--src/network/network.pro1
-rw-r--r--src/plugins/bearer/bearer.pro14
-rw-r--r--src/plugins/bearer/corewlan/corewlan.pro24
-rw-r--r--src/plugins/bearer/corewlan/main.cpp84
-rw-r--r--src/plugins/bearer/corewlan/qcorewlanengine.h99
-rw-r--r--src/plugins/bearer/corewlan/qcorewlanengine.mm553
-rw-r--r--src/plugins/bearer/generic/generic.pro16
-rw-r--r--src/plugins/bearer/generic/main.cpp84
-rw-r--r--src/plugins/bearer/generic/qgenericengine.cpp333
-rw-r--r--src/plugins/bearer/generic/qgenericengine.h92
-rw-r--r--src/plugins/bearer/icd/icd.pro22
-rw-r--r--src/plugins/bearer/icd/main.cpp84
-rw-r--r--src/plugins/bearer/icd/monitor.cpp116
-rw-r--r--src/plugins/bearer/icd/monitor.h116
-rw-r--r--src/plugins/bearer/icd/qicdengine.cpp426
-rw-r--r--src/plugins/bearer/icd/qicdengine.h130
-rw-r--r--src/plugins/bearer/icd/qnetworksession_impl.cpp1104
-rw-r--r--src/plugins/bearer/icd/qnetworksession_impl.h147
-rw-r--r--src/plugins/bearer/nativewifi/main.cpp139
-rw-r--r--src/plugins/bearer/nativewifi/nativewifi.pro17
-rw-r--r--src/plugins/bearer/nativewifi/platformdefs.h322
-rw-r--r--src/plugins/bearer/nativewifi/qnativewifiengine.cpp495
-rw-r--r--src/plugins/bearer/nativewifi/qnativewifiengine.h104
-rw-r--r--src/plugins/bearer/networkmanager/main.cpp89
-rw-r--r--src/plugins/bearer/networkmanager/networkmanager.pro20
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp847
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerengine.h139
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp1046
-rw-r--r--src/plugins/bearer/networkmanager/qnetworkmanagerservice.h397
-rw-r--r--src/plugins/bearer/networkmanager/qnmdbushelper.cpp117
-rw-r--r--src/plugins/bearer/networkmanager/qnmdbushelper.h73
-rw-r--r--src/plugins/bearer/nla/main.cpp84
-rw-r--r--src/plugins/bearer/nla/nla.pro23
-rw-r--r--src/plugins/bearer/nla/qnlaengine.cpp661
-rw-r--r--src/plugins/bearer/nla/qnlaengine.h114
-rw-r--r--src/plugins/bearer/platformdefs_win.h134
-rw-r--r--src/plugins/bearer/qbearerengine_impl.h81
-rw-r--r--src/plugins/bearer/qnetworksession_impl.cpp408
-rw-r--r--src/plugins/bearer/qnetworksession_impl.h130
-rw-r--r--src/plugins/bearer/symbian/main.cpp84
-rw-r--r--src/plugins/bearer/symbian/qnetworksession_impl.cpp1135
-rw-r--r--src/plugins/bearer/symbian/qnetworksession_impl.h196
-rw-r--r--src/plugins/bearer/symbian/symbian.pro37
-rw-r--r--src/plugins/bearer/symbian/symbianengine.cpp1006
-rw-r--r--src/plugins/bearer/symbian/symbianengine.h205
-rw-r--r--src/plugins/plugins.pro2
-rw-r--r--src/s60installs/s60installs.pro11
74 files changed, 14852 insertions, 13 deletions
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index e69512d..4f532c0 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -38,6 +38,7 @@
** $QT_END_LICENSE$
**
****************************************************************************/
+
// QtCore
#include <qdebug.h>
#include <qmath.h>
diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp
index 34d576a..1fcfebb 100644
--- a/src/network/access/qnetworkaccessbackend.cpp
+++ b/src/network/access/qnetworkaccessbackend.cpp
@@ -46,9 +46,11 @@
#include "qnetworkreply_p.h"
#include "QtCore/qhash.h"
#include "QtCore/qmutex.h"
+#include "QtNetwork/qnetworksession.h"
#include "qnetworkaccesscachebackend_p.h"
#include "qabstractnetworkcache.h"
+#include "qhostinfo.h"
#include "private/qnoncontiguousbytedevice_p.h"
@@ -344,4 +346,35 @@ void QNetworkAccessBackend::sslErrors(const QList<QSslError> &errors)
#endif
}
+/*!
+ Starts the backend. Returns true if the backend is started. Returns false if the backend
+ could not be started due to an unopened or roaming session. The caller should recall this
+ function once the session has been opened or the roaming process has finished.
+*/
+bool QNetworkAccessBackend::start()
+{
+ if (!manager->networkSession) {
+ open();
+ return true;
+ }
+
+ // This is not ideal.
+ const QString host = reply->url.host();
+ if (host == QLatin1String("localhost") ||
+ QHostAddress(host) == QHostAddress::LocalHost ||
+ QHostAddress(host) == QHostAddress::LocalHostIPv6) {
+ // Don't need an open session for localhost access.
+ open();
+ return true;
+ }
+
+ if (manager->networkSession->isOpen() &&
+ manager->networkSession->state() == QNetworkSession::Connected) {
+ open();
+ return true;
+ }
+
+ return false;
+}
+
QT_END_NAMESPACE
diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h
index 43d993c..9bc15e5 100644
--- a/src/network/access/qnetworkaccessbackend_p.h
+++ b/src/network/access/qnetworkaccessbackend_p.h
@@ -111,6 +111,7 @@ public:
// socket).
virtual void open() = 0;
+ virtual bool start();
virtual void closeDownstreamChannel() = 0;
virtual bool waitForDownstreamReadyRead(int msecs) = 0;
@@ -160,6 +161,10 @@ public:
// This will possibly enable buffering of the upload data.
virtual bool needsResetableUploadData() { return false; }
+ // Returns true if backend is able to resume downloads.
+ virtual bool canResume() const { return false; }
+ virtual void setResumeOffset(quint64 offset) { Q_UNUSED(offset); }
+
protected:
// Create the device used for reading the upload data
QNonContiguousByteDevice* createUploadByteDevice();
@@ -190,6 +195,7 @@ private:
friend class QNetworkAccessManager;
friend class QNetworkAccessManagerPrivate;
friend class QNetworkAccessBackendUploadIODevice;
+ friend class QNetworkReplyImplPrivate;
QNetworkAccessManagerPrivate *manager;
QNetworkReplyImplPrivate *reply;
};
diff --git a/src/network/access/qnetworkaccesshttpbackend.cpp b/src/network/access/qnetworkaccesshttpbackend.cpp
index dcd4e19..7a48c2b 100644
--- a/src/network/access/qnetworkaccesshttpbackend.cpp
+++ b/src/network/access/qnetworkaccesshttpbackend.cpp
@@ -297,6 +297,7 @@ QNetworkAccessHttpBackend::QNetworkAccessHttpBackend()
#ifndef QT_NO_OPENSSL
, pendingSslConfiguration(0), pendingIgnoreAllSslErrors(false)
#endif
+ , resumeOffset(0)
{
}
@@ -542,6 +543,28 @@ void QNetworkAccessHttpBackend::postRequest()
httpRequest.setUrl(url());
QList<QByteArray> headers = request().rawHeaderList();
+ if (resumeOffset != 0) {
+ if (headers.contains("Range")) {
+ // Need to adjust resume offset for user specified range
+
+ headers.removeOne("Range");
+
+ // We've already verified that requestRange starts with "bytes=", see canResume.
+ QByteArray requestRange = request().rawHeader("Range").mid(6);
+
+ int index = requestRange.indexOf('-');
+
+ quint64 requestStartOffset = requestRange.left(index).toULongLong();
+ quint64 requestEndOffset = requestRange.mid(index + 1).toULongLong();
+
+ requestRange = "bytes=" + QByteArray::number(resumeOffset + requestStartOffset) +
+ '-' + QByteArray::number(requestEndOffset);
+
+ httpRequest.setHeaderField("Range", requestRange);
+ } else {
+ httpRequest.setHeaderField("Range", "bytes=" + QByteArray::number(resumeOffset) + '-');
+ }
+ }
foreach (const QByteArray &header, headers)
httpRequest.setHeaderField(header, request().rawHeader(header));
@@ -1117,6 +1140,31 @@ QNetworkCacheMetaData QNetworkAccessHttpBackend::fetchCacheMetaData(const QNetwo
return metaData;
}
+bool QNetworkAccessHttpBackend::canResume() const
+{
+ // Only GET operation supports resuming.
+ if (operation() != QNetworkAccessManager::GetOperation)
+ return false;
+
+ // Can only resume if server/resource supports Range header.
+ if (httpReply->headerField("Accept-Ranges", "none") == "none")
+ return false;
+
+ // We only support resuming for byte ranges.
+ if (request().hasRawHeader("Range")) {
+ QByteArray range = request().rawHeader("Range");
+ if (!range.startsWith("bytes="))
+ return false;
+ }
+
+ return true;
+}
+
+void QNetworkAccessHttpBackend::setResumeOffset(quint64 offset)
+{
+ resumeOffset = offset;
+}
+
QT_END_NAMESPACE
#endif // QT_NO_HTTP
diff --git a/src/network/access/qnetworkaccesshttpbackend_p.h b/src/network/access/qnetworkaccesshttpbackend_p.h
index 0eaf003..e5cc0ab 100644
--- a/src/network/access/qnetworkaccesshttpbackend_p.h
+++ b/src/network/access/qnetworkaccesshttpbackend_p.h
@@ -99,6 +99,9 @@ public:
// we return true since HTTP needs to send PUT/POST data again after having authenticated
bool needsResetableUploadData() { return true; }
+ bool canResume() const;
+ void setResumeOffset(quint64 offset);
+
private slots:
void replyReadyRead();
void replyFinished();
@@ -120,6 +123,8 @@ private:
QList<QSslError> pendingIgnoreSslErrorsList;
#endif
+ quint64 resumeOffset;
+
void disconnectFromHttp();
void setupConnection();
void validateCache(QHttpNetworkRequest &httpRequest, bool &loadedFromCache);
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index cc4c977..b9bd52a 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -47,6 +47,8 @@
#include "qnetworkcookie.h"
#include "qabstractnetworkcache.h"
+#include "QtNetwork/qnetworksession.h"
+
#include "qnetworkaccesshttpbackend_p.h"
#include "qnetworkaccessftpbackend_p.h"
#include "qnetworkaccessfilebackend_p.h"
@@ -59,6 +61,7 @@
#include "QtCore/qvector.h"
#include "QtNetwork/qauthenticator.h"
#include "QtNetwork/qsslconfiguration.h"
+#include "QtNetwork/qnetworkconfigmanager.h"
QT_BEGIN_NAMESPACE
@@ -163,6 +166,43 @@ static void ensureInitialized()
*/
/*!
+ \property QNetworkAccessManager::networkAccess
+ \brief states whether network access is enabled or disabled through this network access
+ manager.
+
+ \since 4.7
+
+ Network access is enabled by default.
+
+ When network access is disabled the network access manager will not process any new network
+ requests, all such requests will fail with an error. Requests with URLs with the file:// scheme
+ will still be processed.
+
+ This property can be used to enable and disable network access for all clients of a single
+ network access manager instance.
+*/
+
+/*!
+ \fn void QNetworkAccessManager::networkAccessChanged(bool enabled)
+
+ This signal is emitted when the value of the \l networkAccess property changes. If \a enabled
+ is true new requests that access the network will be processed; otherwise new network requests
+ that require network access will fail with an error.
+*/
+
+/*!
+ \fn void QNetworkAccessManager::networkSessionOnline()
+
+ \since 4.7
+
+ \internal
+
+ This signal is emitted when the status of the network session changes into a usable state.
+ It is used to signal QNetworkReply's to start or migrate their network operation once the
+ network session has been opened / roamed.
+*/
+
+/*!
\fn void QNetworkAccessManager::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator)
This signal is emitted whenever a proxy requests authentication
@@ -670,6 +710,110 @@ QNetworkReply *QNetworkAccessManager::deleteResource(const QNetworkRequest &requ
/*!
\since 4.7
+ Sets the network configuration that will be used when creating the
+ \l {QNetworkSession}{network session} to \a config.
+
+ The network configuration is used to create and open a network session before any request that
+ requires network access is process. If no network configuration is explicitly set via this
+ function the network configuration returned by
+ QNetworkConfigurationManager::defaultConfiguration() will be used.
+
+ To restore the default network configuration set the network configuration to the value
+ returned from QNetworkConfigurationManager::defaultConfiguration().
+
+ \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 2
+
+ If an invalid network configuration is set, a network session will not be created. In this
+ case network requests will be processed regardless, but may fail. For example:
+
+ \snippet doc/src/snippets/code/src_network_access_qnetworkaccessmanager.cpp 3
+
+ \sa configuration(), QNetworkSession
+*/
+void QNetworkAccessManager::setConfiguration(const QNetworkConfiguration &config)
+{
+ d_func()->createSession(config);
+}
+
+/*!
+ \since 4.7
+
+ Returns the network configuration that will be used to create the
+ \l {QNetworkSession}{network session} which will be used when processing network requests.
+
+ \sa setConfiguration(), activeConfiguration()
+*/
+QNetworkConfiguration QNetworkAccessManager::configuration() const
+{
+ Q_D(const QNetworkAccessManager);
+
+ if (d->networkSession)
+ return d->networkSession->configuration();
+ else
+ return QNetworkConfiguration();
+}
+
+/*!
+ \since 4.7
+
+ Returns the current active network configuration.
+
+ If the network configuration returned by configuration() is of type
+ QNetworkConfiguration::ServiceNetwork this function will return the current active child
+ network configuration of that configuration. Otherwise returns the same network configuration
+ as configuration().
+
+ Use this function to return the actual network configuration currently in use by the network
+ session.
+
+ \sa configuration()
+*/
+QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const
+{
+ Q_D(const QNetworkAccessManager);
+
+ if (d->networkSession) {
+ QNetworkConfigurationManager manager;
+
+ return manager.configurationFromIdentifier(
+ d->networkSession->sessionProperty(QLatin1String("ActiveConfiguration")).toString());
+ } else {
+ return QNetworkConfiguration();
+ }
+}
+
+/*!
+ \since 4.7
+
+ Enables network access via this QNetworkAccessManager if \a enabled is true; otherwise disables
+ access.
+*/
+void QNetworkAccessManager::setNetworkAccessEnabled(bool enabled)
+{
+ Q_D(QNetworkAccessManager);
+
+ if (d->networkAccessEnabled != enabled) {
+ d->networkAccessEnabled = enabled;
+ emit networkAccessChanged(enabled);
+ }
+}
+
+/*!
+ \since 4.7
+
+ Returns true if network access via this QNetworkAccessManager is enabled; otherwise returns
+ false.
+*/
+bool QNetworkAccessManager::networkAccessEnabled() const
+{
+ Q_D(const QNetworkAccessManager);
+
+ return d->networkAccessEnabled;
+}
+
+/*!
+ \since 4.7
+
Sends a custom request to the server identified by the URL of \a request.
It is the user's responsibility to send a \a verb to the server that is valid
@@ -722,6 +866,20 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
return new QFileNetworkReply(this, req, op);
}
+ // Return a disabled network reply if network access is disabled.
+ // Except if the scheme is empty or file://.
+ if (!d->networkAccessEnabled && !(req.url().scheme() == QLatin1String("file") ||
+ req.url().scheme().isEmpty())) {
+ return new QDisabledNetworkReply(this, req, op);
+ }
+
+ if (d->initializeSession && !d->networkSession) {
+ QNetworkConfigurationManager manager;
+ d->createSession(manager.defaultConfiguration());
+
+ d->initializeSession = false;
+ }
+
QNetworkRequest request = req;
if (!request.header(QNetworkRequest::ContentLengthHeader).isValid() &&
outgoingData && !outgoingData->isSequential()) {
@@ -738,6 +896,8 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
// first step: create the reply
QUrl url = request.url();
QNetworkReplyImpl *reply = new QNetworkReplyImpl(this);
+ if (req.url().scheme() != QLatin1String("file") && !req.url().scheme().isEmpty())
+ connect(this, SIGNAL(networkSessionOnline()), reply, SLOT(_q_networkSessionOnline()));
QNetworkReplyImplPrivate *priv = reply->d_func();
priv->manager = this;
@@ -772,6 +932,7 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
void QNetworkAccessManagerPrivate::_q_replyFinished()
{
Q_Q(QNetworkAccessManager);
+
QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender());
if (reply)
emit q->finished(reply);
@@ -1027,6 +1188,43 @@ QNetworkAccessManagerPrivate::~QNetworkAccessManagerPrivate()
{
}
+void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &config)
+{
+ Q_Q(QNetworkAccessManager);
+
+ if (networkSession)
+ delete networkSession;
+
+ if (!config.isValid()) {
+ networkSession = 0;
+ return;
+ }
+
+ networkSession = new QNetworkSession(config, q);
+
+ QObject::connect(networkSession, SIGNAL(opened()), q, SIGNAL(networkSessionOnline()));
+ QObject::connect(networkSession, SIGNAL(newConfigurationActivated()),
+ q, SLOT(_q_networkSessionNewConfigurationActivated()));
+ QObject::connect(networkSession,
+ SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool)),
+ q,
+ SLOT(_q_networkSessionPreferredConfigurationChanged(QNetworkConfiguration,bool)));
+}
+
+void QNetworkAccessManagerPrivate::_q_networkSessionNewConfigurationActivated()
+{
+ Q_Q(QNetworkAccessManager);
+
+ networkSession->accept();
+
+ emit q->networkSessionOnline();
+}
+
+void QNetworkAccessManagerPrivate::_q_networkSessionPreferredConfigurationChanged(const QNetworkConfiguration &, bool)
+{
+ networkSession->migrate();
+}
+
QT_END_NAMESPACE
#include "moc_qnetworkaccessmanager.cpp"
diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h
index 3a8ba58..252dfd0 100644
--- a/src/network/access/qnetworkaccessmanager.h
+++ b/src/network/access/qnetworkaccessmanager.h
@@ -62,12 +62,16 @@ class QNetworkReply;
class QNetworkProxy;
class QNetworkProxyFactory;
class QSslError;
+class QNetworkConfiguration;
class QNetworkReplyImplPrivate;
class QNetworkAccessManagerPrivate;
class Q_NETWORK_EXPORT QNetworkAccessManager: public QObject
{
Q_OBJECT
+
+ Q_PROPERTY(bool networkAccess READ networkAccessEnabled WRITE setNetworkAccessEnabled NOTIFY networkAccessChanged)
+
public:
enum Operation {
HeadOperation = 1,
@@ -105,6 +109,13 @@ public:
QNetworkReply *deleteResource(const QNetworkRequest &request);
QNetworkReply *sendCustomRequest(const QNetworkRequest &request, const QByteArray &verb, QIODevice *data = 0);
+ void setConfiguration(const QNetworkConfiguration &config);
+ QNetworkConfiguration configuration() const;
+ QNetworkConfiguration activeConfiguration() const;
+
+ void setNetworkAccessEnabled(bool enabled);
+ bool networkAccessEnabled() const;
+
Q_SIGNALS:
#ifndef QT_NO_NETWORKPROXY
void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator);
@@ -115,6 +126,10 @@ Q_SIGNALS:
void sslErrors(QNetworkReply *reply, const QList<QSslError> &errors);
#endif
+ void networkSessionOnline();
+
+ void networkAccessChanged(bool enabled);
+
protected:
virtual QNetworkReply *createRequest(Operation op, const QNetworkRequest &request,
QIODevice *outgoingData = 0);
@@ -124,6 +139,8 @@ private:
Q_DECLARE_PRIVATE(QNetworkAccessManager)
Q_PRIVATE_SLOT(d_func(), void _q_replyFinished())
Q_PRIVATE_SLOT(d_func(), void _q_replySslErrors(QList<QSslError>))
+ Q_PRIVATE_SLOT(d_func(), void _q_networkSessionNewConfigurationActivated())
+ Q_PRIVATE_SLOT(d_func(), void _q_networkSessionPreferredConfigurationChanged(QNetworkConfiguration,bool))
};
QT_END_NAMESPACE
diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h
index 1749373..8d772f0 100644
--- a/src/network/access/qnetworkaccessmanager_p.h
+++ b/src/network/access/qnetworkaccessmanager_p.h
@@ -65,6 +65,7 @@ class QAuthenticator;
class QAbstractNetworkCache;
class QNetworkAuthenticationCredential;
class QNetworkCookieJar;
+class QNetworkSession;
class QNetworkAccessManagerPrivate: public QObjectPrivate
{
@@ -74,6 +75,9 @@ public:
#ifndef QT_NO_NETWORKPROXY
proxyFactory(0),
#endif
+ networkSession(0),
+ networkAccessEnabled(true),
+ initializeSession(true),
cookieJarCreated(false)
{ }
~QNetworkAccessManagerPrivate();
@@ -99,6 +103,12 @@ public:
QNetworkAccessBackend *findBackend(QNetworkAccessManager::Operation op, const QNetworkRequest &request);
+ void createSession(const QNetworkConfiguration &config);
+
+ void _q_networkSessionNewConfigurationActivated();
+ void _q_networkSessionPreferredConfigurationChanged(const QNetworkConfiguration &config,
+ bool isSeamless);
+
// this is the cache for storing downloaded files
QAbstractNetworkCache *networkCache;
@@ -110,8 +120,11 @@ public:
QNetworkProxyFactory *proxyFactory;
#endif
- bool cookieJarCreated;
+ QNetworkSession *networkSession;
+ bool networkAccessEnabled;
+ bool initializeSession;
+ bool cookieJarCreated;
// this cache can be used by individual backends to cache e.g. their TCP connections to a server
// and use the connections for multiple requests.
diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp
index 15748fe..c8b8c1f 100644
--- a/src/network/access/qnetworkreply.cpp
+++ b/src/network/access/qnetworkreply.cpp
@@ -125,6 +125,11 @@ QNetworkReplyPrivate::QNetworkReplyPrivate()
encrypted channel could not be established. The sslErrors() signal
should have been emitted.
+ \value TemporaryNetworkFailureError the connection was broken due
+ to disconnection from the network, however the system has initiated
+ roaming to another access point. The request should be resubmitted
+ and will be processed as soon as the connection is re-established.
+
\value ProxyConnectionRefusedError the connection to the proxy
server was refused (the proxy server is not accepting requests)
diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h
index 5db4985..acb7379 100644
--- a/src/network/access/qnetworkreply.h
+++ b/src/network/access/qnetworkreply.h
@@ -77,6 +77,7 @@ public:
TimeoutError,
OperationCanceledError,
SslHandshakeFailedError,
+ TemporaryNetworkFailureError,
UnknownNetworkError = 99,
// proxy errors (101-199):
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index 59c7d76..2175686 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -46,7 +46,9 @@
#include "QtCore/qcoreapplication.h"
#include "QtCore/qdatetime.h"
#include "QtNetwork/qsslconfiguration.h"
+#include "QtNetwork/qnetworksession.h"
#include "qnetworkaccesshttpbackend_p.h"
+#include "qnetworkaccessmanager_p.h"
#include <QtCore/QCoreApplication>
@@ -57,7 +59,7 @@ inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate()
copyDevice(0),
cacheEnabled(false), cacheSaveDevice(0),
notificationHandlingPaused(false),
- bytesDownloaded(0), lastBytesDownloaded(-1), bytesUploaded(-1),
+ bytesDownloaded(0), lastBytesDownloaded(-1), bytesUploaded(-1), preMigrationDownloaded(-1),
httpStatusCode(0),
state(Idle)
{
@@ -82,7 +84,24 @@ void QNetworkReplyImplPrivate::_q_startOperation()
return;
}
- backend->open();
+ if (!backend->start()) {
+ // backend failed to start because the session state is not Connected.
+ // QNetworkAccessManager will call reply->backend->start() again for us when the session
+ // state changes.
+ state = WaitingForSession;
+
+ QNetworkSession *session = manager->d_func()->networkSession;
+
+ if (session) {
+ if (!session->isOpen())
+ session->open();
+ } else {
+ qWarning("Backend is waiting for QNetworkSession to connect, but there is none!");
+ }
+
+ return;
+ }
+
if (state != Finished) {
if (operation == QNetworkAccessManager::GetOperation)
pendingNotifications.append(NotifyDownstreamReadyWrite);
@@ -134,6 +153,8 @@ void QNetworkReplyImplPrivate::_q_copyReadyRead()
lastBytesDownloaded = bytesDownloaded;
QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
+ if (preMigrationDownloaded != Q_INT64_C(-1))
+ totalSize = totalSize.toLongLong() + preMigrationDownloaded;
pauseNotificationHandling();
emit q->downloadProgress(bytesDownloaded,
totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong());
@@ -206,6 +227,26 @@ void QNetworkReplyImplPrivate::_q_bufferOutgoingData()
}
}
+void QNetworkReplyImplPrivate::_q_networkSessionOnline()
+{
+ Q_Q(QNetworkReplyImpl);
+
+ switch (state) {
+ case QNetworkReplyImplPrivate::Buffering:
+ case QNetworkReplyImplPrivate::Working:
+ case QNetworkReplyImplPrivate::Reconnecting:
+ // Migrate existing downloads to new network connection.
+ migrateBackend();
+ break;
+ case QNetworkReplyImplPrivate::WaitingForSession:
+ // Start waiting requests.
+ QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
+ break;
+ default:
+ ;
+ }
+}
+
void QNetworkReplyImplPrivate::setup(QNetworkAccessManager::Operation op, const QNetworkRequest &req,
QIODevice *data)
{
@@ -457,6 +498,8 @@ void QNetworkReplyImplPrivate::appendDownstreamData(QByteDataBuffer &data)
QPointer<QNetworkReplyImpl> qq = q;
QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
+ if (preMigrationDownloaded != Q_INT64_C(-1))
+ totalSize = totalSize.toLongLong() + preMigrationDownloaded;
pauseNotificationHandling();
emit q->downloadProgress(bytesDownloaded,
totalSize.isNull() ? Q_INT64_C(-1) : totalSize.toLongLong());
@@ -498,14 +541,42 @@ void QNetworkReplyImplPrivate::appendDownstreamData(QIODevice *data)
void QNetworkReplyImplPrivate::finished()
{
Q_Q(QNetworkReplyImpl);
- if (state == Finished || state == Aborted)
+
+ if (state == Finished || state == Aborted || state == WaitingForSession)
return;
+ pauseNotificationHandling();
+ QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
+ if (preMigrationDownloaded != Q_INT64_C(-1))
+ totalSize = totalSize.toLongLong() + preMigrationDownloaded;
+
+ if (!manager.isNull()) {
+ QNetworkSession *session = manager->d_func()->networkSession;
+ if (session && session->state() == QNetworkSession::Roaming &&
+ state == Working && errorCode != QNetworkReply::OperationCanceledError) {
+ // only content with a known size will fail with a temporary network failure error
+ if (!totalSize.isNull()) {
+ if (bytesDownloaded != totalSize) {
+ if (migrateBackend()) {
+ // either we are migrating or the request is finished/aborted
+ if (state == Reconnecting || state == WaitingForSession) {
+ resumeNotificationHandling();
+ return; // exit early if we are migrating.
+ }
+ } else {
+ error(QNetworkReply::TemporaryNetworkFailureError,
+ q->tr("Temporary network failure."));
+ }
+ }
+ }
+ }
+ }
+ resumeNotificationHandling();
+
state = Finished;
pendingNotifications.clear();
pauseNotificationHandling();
- QVariant totalSize = cookedHeaders.value(QNetworkRequest::ContentLengthHeader);
if (totalSize.isNull() || totalSize == -1) {
emit q->downloadProgress(bytesDownloaded, bytesDownloaded);
}
@@ -514,7 +585,9 @@ void QNetworkReplyImplPrivate::finished()
emit q->uploadProgress(0, 0);
resumeNotificationHandling();
- completeCacheSave();
+ // if we don't know the total size of or we received everything save the cache
+ if (totalSize.isNull() || totalSize == -1 || bytesDownloaded == totalSize)
+ completeCacheSave();
// note: might not be a good idea, since users could decide to delete us
// which would delete the backend too...
@@ -722,6 +795,83 @@ bool QNetworkReplyImpl::event(QEvent *e)
return QObject::event(e);
}
+/*
+ Migrates the backend of the QNetworkReply to a new network connection if required. Returns
+ true if the reply is migrated or it is not required; otherwise returns false.
+*/
+bool QNetworkReplyImplPrivate::migrateBackend()
+{
+ Q_Q(QNetworkReplyImpl);
+
+ // Network reply is already finished or aborted, don't need to migrate.
+ if (state == Finished || state == Aborted)
+ return true;
+
+ // Backend does not support resuming download.
+ if (!backend->canResume())
+ return false;
+
+ // Request has outgoing data, not migrating.
+ if (outgoingData)
+ return false;
+
+ // Request is serviced from the cache, don't need to migrate.
+ if (copyDevice)
+ return true;
+
+ state = QNetworkReplyImplPrivate::Reconnecting;
+
+ if (backend) {
+ delete backend;
+ backend = 0;
+ }
+
+ cookedHeaders.clear();
+ rawHeaders.clear();
+
+ preMigrationDownloaded = bytesDownloaded;
+
+ backend = manager->d_func()->findBackend(operation, request);
+
+ if (backend) {
+ backend->setParent(q);
+ backend->reply = this;
+ backend->setResumeOffset(bytesDownloaded);
+ }
+
+ if (qobject_cast<QNetworkAccessHttpBackend *>(backend)) {
+ _q_startOperation();
+ } else {
+ QMetaObject::invokeMethod(q, "_q_startOperation", Qt::QueuedConnection);
+ }
+
+ return true;
+}
+
+QDisabledNetworkReply::QDisabledNetworkReply(QObject *parent,
+ const QNetworkRequest &req,
+ QNetworkAccessManager::Operation op)
+: QNetworkReply(parent)
+{
+ setRequest(req);
+ setUrl(req.url());
+ setOperation(op);
+
+ qRegisterMetaType<QNetworkReply::NetworkError>("QNetworkReply::NetworkError");
+
+ QString msg = QCoreApplication::translate("QNetworkAccessManager",
+ "Network access is disabled.");
+ setError(UnknownNetworkError, msg);
+
+ QMetaObject::invokeMethod(this, "error", Qt::QueuedConnection,
+ Q_ARG(QNetworkReply::NetworkError, UnknownNetworkError));
+ QMetaObject::invokeMethod(this, "finished", Qt::QueuedConnection);
+}
+
+QDisabledNetworkReply::~QDisabledNetworkReply()
+{
+}
+
QT_END_NAMESPACE
#include "moc_qnetworkreplyimpl_p.cpp"
diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h
index 168e5cf..ec413cc 100644
--- a/src/network/access/qnetworkreplyimpl_p.h
+++ b/src/network/access/qnetworkreplyimpl_p.h
@@ -98,6 +98,7 @@ public:
Q_PRIVATE_SLOT(d_func(), void _q_copyReadChannelFinished())
Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingData())
Q_PRIVATE_SLOT(d_func(), void _q_bufferOutgoingDataFinished())
+ Q_PRIVATE_SLOT(d_func(), void _q_networkSessionOnline())
};
class QNetworkReplyImplPrivate: public QNetworkReplyPrivate
@@ -110,11 +111,13 @@ public:
};
enum State {
- Idle,
- Buffering,
- Working,
- Finished,
- Aborted
+ Idle, // The reply is idle.
+ Buffering, // The reply is buffering outgoing data.
+ Working, // The reply is uploading/downloading data.
+ Finished, // The reply has finished.
+ Aborted, // The reply has been aborted.
+ WaitingForSession, // The reply is waiting for the session to open before connecting.
+ Reconnecting // The reply will reconnect to once roaming has completed.
};
typedef QQueue<InternalNotifications> NotificationQueue;
@@ -128,6 +131,7 @@ public:
void _q_copyReadChannelFinished();
void _q_bufferOutgoingData();
void _q_bufferOutgoingDataFinished();
+ void _q_networkSessionOnline();
void setup(QNetworkAccessManager::Operation op, const QNetworkRequest &request,
QIODevice *outgoingData);
@@ -161,6 +165,8 @@ public:
QIODevice *copyDevice;
QAbstractNetworkCache *networkCache() const;
+ bool migrateBackend();
+
bool cacheEnabled;
QIODevice *cacheSaveDevice;
@@ -177,6 +183,7 @@ public:
qint64 bytesDownloaded;
qint64 lastBytesDownloaded;
qint64 bytesUploaded;
+ qint64 preMigrationDownloaded;
QString httpReasonPhrase;
int httpStatusCode;
@@ -186,6 +193,20 @@ public:
Q_DECLARE_PUBLIC(QNetworkReplyImpl)
};
+class QDisabledNetworkReply : public QNetworkReply
+{
+ Q_OBJECT
+
+public:
+ QDisabledNetworkReply(QObject *parent, const QNetworkRequest &req,
+ const QNetworkAccessManager::Operation op);
+ ~QDisabledNetworkReply();
+
+ void abort() { }
+protected:
+ qint64 readData(char *, qint64) { return -1; }
+};
+
QT_END_NAMESPACE
#endif
diff --git a/src/network/bearer/bearer.pri b/src/network/bearer/bearer.pri
new file mode 100644
index 0000000..44e97fd
--- /dev/null
+++ b/src/network/bearer/bearer.pri
@@ -0,0 +1,18 @@
+# Qt network bearer management module
+
+HEADERS += bearer/qnetworkconfiguration.h \
+ bearer/qnetworksession.h \
+ bearer/qnetworkconfigmanager.h \
+ bearer/qnetworkconfigmanager_p.h \
+ bearer/qnetworkconfiguration_p.h \
+ bearer/qnetworksession_p.h \
+ bearer/qbearerengine_p.h \
+ bearer/qbearerplugin_p.h
+
+SOURCES += bearer/qnetworksession.cpp \
+ bearer/qnetworkconfigmanager.cpp \
+ bearer/qnetworkconfiguration.cpp \
+ bearer/qnetworkconfigmanager_p.cpp \
+ bearer/qbearerengine.cpp \
+ bearer/qbearerplugin.cpp
+
diff --git a/src/network/bearer/qbearerengine.cpp b/src/network/bearer/qbearerengine.cpp
new file mode 100644
index 0000000..eb851cc
--- /dev/null
+++ b/src/network/bearer/qbearerengine.cpp
@@ -0,0 +1,75 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbearerengine_p.h"
+
+QT_BEGIN_NAMESPACE
+
+QBearerEngine::QBearerEngine(QObject *parent)
+: QObject(parent), mutex(QMutex::Recursive)
+{
+}
+
+QBearerEngine::~QBearerEngine()
+{
+ QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator it;
+ QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator end;
+ for (it = snapConfigurations.begin(), end = snapConfigurations.end(); it != end; ++it) {
+ it.value()->isValid = false;
+ it.value()->id.clear();
+ }
+
+ for (it = accessPointConfigurations.begin(), end = accessPointConfigurations.end();
+ it != end; ++it) {
+ it.value()->isValid = false;
+ it.value()->id.clear();
+ }
+
+ for (it = userChoiceConfigurations.begin(), end = userChoiceConfigurations.end();
+ it != end; ++it) {
+ it.value()->isValid = false;
+ it.value()->id.clear();
+ }
+}
+
+#include "moc_qbearerengine_p.cpp"
+
+QT_END_NAMESPACE
diff --git a/src/network/bearer/qbearerengine_p.h b/src/network/bearer/qbearerengine_p.h
new file mode 100644
index 0000000..5e12b0f
--- /dev/null
+++ b/src/network/bearer/qbearerengine_p.h
@@ -0,0 +1,112 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBEARERENGINE_P_H
+#define QBEARERENGINE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qnetworkconfiguration_p.h"
+#include "qnetworksession.h"
+#include "qnetworkconfigmanager.h"
+
+#include <QtCore/qobject.h>
+#include <QtCore/qglobal.h>
+#include <QtCore/qlist.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qhash.h>
+#include <QtCore/qsharedpointer.h>
+#include <QtCore/qmutex.h>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkConfiguration;
+
+class Q_NETWORK_EXPORT QBearerEngine : public QObject
+{
+ Q_OBJECT
+
+ friend class QNetworkConfigurationManager;
+
+public:
+ QBearerEngine(QObject *parent = 0);
+ virtual ~QBearerEngine();
+
+ virtual bool hasIdentifier(const QString &id) = 0;
+
+ virtual void requestUpdate() = 0;
+
+ virtual QNetworkConfigurationManager::Capabilities capabilities() const = 0;
+
+ virtual QNetworkSessionPrivate *createSessionBackend() = 0;
+
+ virtual QNetworkConfigurationPrivatePointer defaultConfiguration() = 0;
+
+Q_SIGNALS:
+ void configurationAdded(QNetworkConfigurationPrivatePointer config);
+ void configurationRemoved(QNetworkConfigurationPrivatePointer config);
+ void configurationChanged(QNetworkConfigurationPrivatePointer config);
+
+ void updateCompleted();
+
+protected:
+ //this table contains an up to date list of all configs at any time.
+ //it must be updated if configurations change, are added/removed or
+ //the members of ServiceNetworks change
+ QHash<QString, QNetworkConfigurationPrivatePointer> accessPointConfigurations;
+ QHash<QString, QNetworkConfigurationPrivatePointer> snapConfigurations;
+ QHash<QString, QNetworkConfigurationPrivatePointer> userChoiceConfigurations;
+
+ mutable QMutex mutex;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/network/bearer/qbearerplugin.cpp b/src/network/bearer/qbearerplugin.cpp
new file mode 100644
index 0000000..4509fd0
--- /dev/null
+++ b/src/network/bearer/qbearerplugin.cpp
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qbearerplugin_p.h"
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+QBearerEnginePlugin::QBearerEnginePlugin(QObject *parent)
+: QObject(parent)
+{
+}
+
+QBearerEnginePlugin::~QBearerEnginePlugin()
+{
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/bearer/qbearerplugin_p.h b/src/network/bearer/qbearerplugin_p.h
new file mode 100644
index 0000000..36709c2
--- /dev/null
+++ b/src/network/bearer/qbearerplugin_p.h
@@ -0,0 +1,93 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBEARERPLUGIN_P_H
+#define QBEARERPLUGIN_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qbearerengine_p.h"
+
+#include <QtCore/qplugin.h>
+#include <QtCore/qfactoryinterface.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Network)
+
+struct Q_NETWORK_EXPORT QBearerEngineFactoryInterface : public QFactoryInterface
+{
+ virtual QBearerEngine *create(const QString &key = QString()) const = 0;
+};
+
+#define QBearerEngineFactoryInterface_iid "com.trolltech.Qt.QBearerEngineFactoryInterface"
+Q_DECLARE_INTERFACE(QBearerEngineFactoryInterface, QBearerEngineFactoryInterface_iid)
+
+class Q_NETWORK_EXPORT QBearerEnginePlugin : public QObject, public QBearerEngineFactoryInterface
+{
+ Q_OBJECT
+ Q_INTERFACES(QBearerEngineFactoryInterface:QFactoryInterface)
+
+public:
+ explicit QBearerEnginePlugin(QObject *parent = 0);
+ virtual ~QBearerEnginePlugin();
+
+ virtual QStringList keys() const = 0;
+ virtual QBearerEngine *create(const QString &key = QString()) const = 0;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
+
diff --git a/src/network/bearer/qnetworkconfigmanager.cpp b/src/network/bearer/qnetworkconfigmanager.cpp
new file mode 100644
index 0000000..e960323
--- /dev/null
+++ b/src/network/bearer/qnetworkconfigmanager.cpp
@@ -0,0 +1,419 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnetworkconfigmanager.h"
+
+#include "qnetworkconfigmanager_p.h"
+#include "qbearerengine_p.h"
+
+#include <QtCore/qstringlist.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC(QNetworkConfigurationManagerPrivate, connManager);
+
+QNetworkConfigurationManagerPrivate *qNetworkConfigurationManagerPrivate()
+{
+ return connManager();
+}
+
+/*!
+ \class QNetworkConfigurationManager
+
+ \brief The QNetworkConfigurationManager class manages the network configurations provided
+ by the system.
+
+ \since 4.7
+
+ \inmodule QtNetwork
+ \ingroup bearer
+
+ QNetworkConfigurationManager provides access to the network configurations known to the system and
+ enables applications to detect the system capabilities (with regards to network sessions) at runtime.
+
+ A QNetworkConfiguration abstracts a set of configuration options describing how a
+ network interface has to be configured to connect to a particular target network.
+ QNetworkConfigurationManager maintains and updates the global list of
+ QNetworkConfigurations. Applications can access and filter this list via
+ allConfigurations(). If a new configuration is added or an existing one is removed or changed
+ the configurationAdded(), configurationRemoved() and configurationChanged() signals are emitted
+ respectively.
+
+ The defaultConfiguration() can be used when intending to immediately create a new
+ network session without caring about the particular configuration. It returns
+ a \l QNetworkConfiguration::Discovered configuration. If there are not any
+ discovered ones an invalid configuration is returned.
+
+ Some configuration updates may require some time to perform updates. A WLAN scan is
+ such an example. Unless the platform performs internal updates it may be required to
+ manually trigger configuration updates via QNetworkConfigurationManager::updateConfigurations().
+ The completion of the update process is indicted by emitting the updateCompleted()
+ signal. The update process ensures that every existing QNetworkConfiguration instance
+ is updated. There is no need to ask for a renewed configuration list via allConfigurations().
+
+ \sa QNetworkConfiguration
+*/
+
+/*!
+ \fn void QNetworkConfigurationManager::configurationAdded(const QNetworkConfiguration& config)
+
+ This signal is emitted whenever a new network configuration is added to the system. The new
+ configuration is specified by \a config.
+*/
+
+/*!
+ \fn void QNetworkConfigurationManager::configurationRemoved(const QNetworkConfiguration& configuration)
+
+ This signal is emitted when a configuration is about to be removed from the system. The removed
+ \a configuration is invalid but retains name and identifier.
+*/
+
+/*!
+ \fn void QNetworkConfigurationManager::updateCompleted()
+
+ This signal is emitted when the configuration update has been completed. Such an update can
+ be initiated via \l updateConfigurations().
+*/
+
+/*! \fn void QNetworkConfigurationManager::configurationChanged(const QNetworkConfiguration& config)
+
+ This signal is emitted when the \l {QNetworkConfiguration::state()}{state} of \a config changes.
+*/
+
+/*!
+ \fn void QNetworkConfigurationManager::onlineStateChanged(bool isOnline)
+
+ This signal is emitted when the device changes from online to offline mode or vice versa.
+ \a isOnline represents the new state of the device.
+
+ The state is considered to be online for as long as
+ \l{allConfigurations()}{allConfigurations}(QNetworkConfiguration::Active) returns a list with
+ at least one entry.
+*/
+
+/*!
+ \enum QNetworkConfigurationManager::Capability
+
+ Specifies the system capabilities of the bearer API. The possible values are:
+
+ \value CanStartAndStopInterfaces Network sessions and their underlying access points can be
+ started and stopped. If this flag is not set QNetworkSession
+ can only monitor but not influence the state of access points.
+ On some platforms this feature may require elevated user
+ permissions. This option is platform specific and may not
+ always be available.
+ \value DirectConnectionRouting Network sessions and their sockets can be bound to a
+ particular network interface. Any packet that passes through
+ the socket goes to the specified network interface and thus
+ disregards standard routing table entries. This may be useful
+ when two interfaces can reach overlapping IP ranges or an
+ application has specific needs in regards to target networks.
+ This option is platform specific and may not always be
+ available.
+ \value SystemSessionSupport If this flag is set the underlying platform ensures that a
+ network interface is not shut down until the last network
+ session has been \l{QNetworkSession::close()}{closed()}. This
+ works across multiple processes. If the platform session
+ support is missing this API can only ensure the above behavior
+ for network sessions within the same process.
+ In general mobile platforms (such as Symbian/S60) have such
+ support whereas most desktop platform lack this capability.
+ \value ApplicationLevelRoaming The system gives applications control over the systems roaming
+ behavior. Applications can initiate roaming (in case the
+ current link is not suitable) and are consulted if the system
+ has identified a more suitable access point.
+ \value ForcedRoaming The system disconnects an existing access point and reconnects
+ via a more suitable one. The application does not have any
+ control over this process and has to reconnect its active
+ sockets.
+ \value DataStatistics If this flag is set QNetworkSession can provide statistics
+ about transmitted and received data.
+*/
+
+/*!
+ Constructs a QNetworkConfigurationManager with the given \a parent.
+*/
+QNetworkConfigurationManager::QNetworkConfigurationManager( QObject* parent )
+ : QObject(parent)
+{
+ QNetworkConfigurationManagerPrivate* priv = connManager();
+ connect(priv, SIGNAL(configurationAdded(QNetworkConfiguration)),
+ this, SIGNAL(configurationAdded(QNetworkConfiguration)));
+ connect(priv, SIGNAL(configurationRemoved(QNetworkConfiguration)),
+ this, SIGNAL(configurationRemoved(QNetworkConfiguration)));
+ connect(priv, SIGNAL(configurationUpdateComplete()),
+ this, SIGNAL(updateCompleted()));
+ connect(priv, SIGNAL(onlineStateChanged(bool)),
+ this, SIGNAL(onlineStateChanged(bool)));
+ connect(priv, SIGNAL(configurationChanged(QNetworkConfiguration)),
+ this, SIGNAL(configurationChanged(QNetworkConfiguration)));
+}
+
+/*!
+ Frees the resources associated with the QNetworkConfigurationManager object.
+*/
+QNetworkConfigurationManager::~QNetworkConfigurationManager()
+{
+}
+
+
+/*!
+ Returns the default configuration to be used. This function always returns a discovered
+ configuration; otherwise an invalid configuration.
+
+ In some cases it may be required to call updateConfigurations() and wait for the
+ updateCompleted() signal before calling this function.
+
+ \sa allConfigurations()
+*/
+QNetworkConfiguration QNetworkConfigurationManager::defaultConfiguration() const
+{
+ QNetworkConfigurationManagerPrivate *conPriv = connManager();
+
+ foreach (QBearerEngine *engine, conPriv->engines()) {
+ QNetworkConfigurationPrivatePointer ptr = engine->defaultConfiguration();
+
+ if (ptr) {
+ QNetworkConfiguration config;
+ config.d = ptr;
+ return config;
+ }
+ }
+
+ // Engines don't have a default configuration.
+
+ // Return first active snap
+ QNetworkConfigurationPrivatePointer firstDiscovered;
+
+ foreach (QBearerEngine *engine, conPriv->engines()) {
+ QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator it;
+ QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator end;
+
+ QMutexLocker locker(&engine->mutex);
+
+ for (it = engine->snapConfigurations.begin(), end = engine->snapConfigurations.end();
+ it != end; ++it) {
+ if ((it.value()->state & QNetworkConfiguration::Active) ==
+ QNetworkConfiguration::Active) {
+ QNetworkConfiguration config;
+ config.d = it.value();
+ return config;
+ } else if ((it.value()->state & QNetworkConfiguration::Discovered) ==
+ QNetworkConfiguration::Discovered) {
+ firstDiscovered = it.value();
+ }
+ }
+ }
+
+ // No Active SNAPs return first Discovered SNAP.
+ if (firstDiscovered) {
+ QNetworkConfiguration config;
+ config.d = firstDiscovered;
+ return config;
+ }
+
+ // No Active or Discovered SNAPs, do same for InternetAccessPoints.
+ firstDiscovered.reset();
+
+ foreach (QBearerEngine *engine, conPriv->engines()) {
+ QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator it;
+ QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator end;
+
+ QMutexLocker locker(&engine->mutex);
+
+ for (it = engine->accessPointConfigurations.begin(),
+ end = engine->accessPointConfigurations.end(); it != end; ++it) {
+ if ((it.value()->state & QNetworkConfiguration::Active) ==
+ QNetworkConfiguration::Active) {
+ QNetworkConfiguration config;
+ config.d = it.value();
+ return config;
+ } else if ((it.value()->state & QNetworkConfiguration::Discovered) ==
+ QNetworkConfiguration::Discovered) {
+ firstDiscovered = it.value();
+ }
+ }
+ }
+
+ // No Active InternetAccessPoint return first Discovered InternetAccessPoint.
+ if (firstDiscovered) {
+ QNetworkConfiguration config;
+ config.d = firstDiscovered;
+ return config;
+ }
+
+ return QNetworkConfiguration();
+}
+
+/*!
+ Returns the list of configurations which comply with the given \a filter.
+
+ By default this function returns all (defined and undefined) configurations.
+
+ A wireless network with a particular SSID may only be accessible in a
+ certain area despite the fact that the system has a valid configuration
+ for it. Therefore the filter flag may be used to limit the list to
+ discovered and possibly connected configurations only.
+
+ If \a filter is set to zero this function returns all possible configurations.
+
+ Note that this function returns the states for all configurations as they are known at
+ the time of this function call. If for instance a configuration of type WLAN is defined
+ the system may have to perform a WLAN scan in order to determine whether it is
+ actually available. To obtain the most accurate state updateConfigurations() should
+ be used to update each configuration's state. Note that such an update may require
+ some time. It's completion is signalled by updateCompleted(). In the absence of a
+ configuration update this function returns the best estimate at the time of the call.
+*/
+QList<QNetworkConfiguration> QNetworkConfigurationManager::allConfigurations(QNetworkConfiguration::StateFlags filter) const
+{
+ QList<QNetworkConfiguration> result;
+ QNetworkConfigurationManagerPrivate* conPriv = connManager();
+
+ foreach (QBearerEngine *engine, conPriv->engines()) {
+ QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator it;
+ QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator end;
+
+ QMutexLocker locker(&engine->mutex);
+
+ //find all InternetAccessPoints
+ for (it = engine->accessPointConfigurations.begin(),
+ end = engine->accessPointConfigurations.end(); it != end; ++it) {
+ if ((it.value()->state & filter) == filter) {
+ QNetworkConfiguration pt;
+ pt.d = it.value();
+ result << pt;
+ }
+ }
+
+ //find all service networks
+ for (it = engine->snapConfigurations.begin(),
+ end = engine->snapConfigurations.end(); it != end; ++it) {
+ if ((it.value()->state & filter) == filter) {
+ QNetworkConfiguration pt;
+ pt.d = it.value();
+ result << pt;
+ }
+ }
+ }
+
+ return result;
+}
+
+/*!
+ Returns the QNetworkConfiguration for \a identifier; otherwise returns an
+ invalid QNetworkConfiguration.
+
+ \sa QNetworkConfiguration::identifier()
+*/
+QNetworkConfiguration QNetworkConfigurationManager::configurationFromIdentifier(const QString& identifier) const
+{
+ QNetworkConfigurationManagerPrivate* conPriv = connManager();
+
+ QNetworkConfiguration item;
+
+ foreach (QBearerEngine *engine, conPriv->engines()) {
+ QMutexLocker locker(&engine->mutex);
+
+ if (engine->accessPointConfigurations.contains(identifier))
+ item.d = engine->accessPointConfigurations.value(identifier);
+ else if (engine->snapConfigurations.contains(identifier))
+ item.d = engine->snapConfigurations.value(identifier);
+ else if (engine->userChoiceConfigurations.contains(identifier))
+ item.d = engine->userChoiceConfigurations.value(identifier);
+ else
+ continue;
+
+ return item;
+ }
+
+ return item;
+}
+
+/*!
+ Returns true if the system is considered to be connected to another device via an active
+ network interface; otherwise returns false.
+
+ This is equivalent to the following code snippet:
+
+ \snippet doc/src/snippets/code/src_network_bearer_qnetworkconfigmanager.cpp 0
+
+ \sa onlineStateChanged()
+*/
+bool QNetworkConfigurationManager::isOnline() const
+{
+ QNetworkConfigurationManagerPrivate* conPriv = connManager();
+ Q_UNUSED(conPriv);
+ QList<QNetworkConfiguration> activeConfigs = allConfigurations(QNetworkConfiguration::Active);
+ return activeConfigs.count() > 0;
+}
+
+/*!
+ Returns the capabilities supported by the current platform.
+*/
+QNetworkConfigurationManager::Capabilities QNetworkConfigurationManager::capabilities() const
+{
+ return connManager()->capFlags;
+}
+
+/*!
+ Initiates an update of all configurations. This may be used to initiate WLAN scans or other
+ time consuming updates which may be required to obtain the correct state for configurations.
+
+ This call is asynchronous. On completion of this update the updateCompleted() signal is
+ emitted. If new configurations are discovered or old ones were removed or changed the update
+ process may trigger the emission of one or multiple configurationAdded(),
+ configurationRemoved() and configurationChanged() signals.
+
+ If a configuration state changes as a result of this update all existing QNetworkConfiguration
+ instances are updated automatically.
+
+ \sa allConfigurations()
+*/
+void QNetworkConfigurationManager::updateConfigurations()
+{
+ connManager()->performAsyncConfigurationUpdate();
+}
+
+#include "moc_qnetworkconfigmanager.cpp"
+
+QT_END_NAMESPACE
+
diff --git a/src/network/bearer/qnetworkconfigmanager.h b/src/network/bearer/qnetworkconfigmanager.h
new file mode 100644
index 0000000..73041fe
--- /dev/null
+++ b/src/network/bearer/qnetworkconfigmanager.h
@@ -0,0 +1,101 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNETWORKCONFIGURATIONMANAGER_H
+#define QNETWORKCONFIGURATIONMANAGER_H
+
+#include <QtCore/qobject.h>
+#include <QtNetwork/qnetworkconfiguration.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Network)
+
+class QNetworkConfigurationManagerPrivate;
+class Q_NETWORK_EXPORT QNetworkConfigurationManager : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ enum Capability {
+ CanStartAndStopInterfaces = 0x00000001,
+ DirectConnectionRouting = 0x00000002,
+ SystemSessionSupport = 0x00000004,
+ ApplicationLevelRoaming = 0x00000008,
+ ForcedRoaming = 0x00000010,
+ DataStatistics = 0x00000020
+ };
+
+ Q_DECLARE_FLAGS(Capabilities, Capability)
+
+ QNetworkConfigurationManager( QObject* parent = 0 );
+ virtual ~QNetworkConfigurationManager();
+
+
+ QNetworkConfigurationManager::Capabilities capabilities() const;
+
+ QNetworkConfiguration defaultConfiguration() const;
+ QList<QNetworkConfiguration> allConfigurations(QNetworkConfiguration::StateFlags flags = 0) const;
+ QNetworkConfiguration configurationFromIdentifier(const QString& identifier) const;
+ void updateConfigurations();
+
+ bool isOnline() const;
+
+Q_SIGNALS:
+ void configurationAdded(const QNetworkConfiguration& config);
+ void configurationRemoved(const QNetworkConfiguration& config);
+ void configurationChanged(const QNetworkConfiguration& config);
+ void onlineStateChanged(bool isOnline);
+ void updateCompleted();
+
+};
+
+Q_DECLARE_OPERATORS_FOR_FLAGS(QNetworkConfigurationManager::Capabilities)
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QNETWORKCONFIGURATIONMANAGER_H
+
diff --git a/src/network/bearer/qnetworkconfigmanager_p.cpp b/src/network/bearer/qnetworkconfigmanager_p.cpp
new file mode 100644
index 0000000..1ac10c5
--- /dev/null
+++ b/src/network/bearer/qnetworkconfigmanager_p.cpp
@@ -0,0 +1,211 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnetworkconfigmanager_p.h"
+#include "qbearerplugin_p.h"
+
+#include <QtCore/private/qfactoryloader_p.h>
+
+#include <QtCore/qdebug.h>
+#include <QtCore/qtimer.h>
+#include <QtCore/qstringlist.h>
+#include <QtCore/private/qcoreapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
+ (QBearerEngineFactoryInterface_iid, QLatin1String("/bearer")))
+
+QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate()
+: capFlags(0), mutex(QMutex::Recursive), firstUpdate(true)
+{
+ updateConfigurations();
+
+ moveToThread(QCoreApplicationPrivate::mainThread());
+ foreach (QBearerEngine *engine, sessionEngines)
+ engine->moveToThread(QCoreApplicationPrivate::mainThread());
+}
+
+QNetworkConfigurationManagerPrivate::~QNetworkConfigurationManagerPrivate()
+{
+ QMutexLocker locker(&mutex);
+
+ qDeleteAll(sessionEngines);
+}
+
+void QNetworkConfigurationManagerPrivate::configurationAdded(QNetworkConfigurationPrivatePointer ptr)
+{
+ QMutexLocker locker(&mutex);
+
+ if (!firstUpdate) {
+ QNetworkConfiguration item;
+ item.d = ptr;
+ emit configurationAdded(item);
+ }
+
+ if (ptr->state == QNetworkConfiguration::Active) {
+ onlineConfigurations.insert(ptr);
+ if (!firstUpdate && onlineConfigurations.count() == 1)
+ emit onlineStateChanged(true);
+ }
+}
+
+void QNetworkConfigurationManagerPrivate::configurationRemoved(QNetworkConfigurationPrivatePointer ptr)
+{
+ QMutexLocker locker(&mutex);
+
+ ptr->isValid = false;
+
+ if (!firstUpdate) {
+ QNetworkConfiguration item;
+ item.d = ptr;
+ emit configurationRemoved(item);
+ }
+
+ onlineConfigurations.remove(ptr);
+ if (!firstUpdate && onlineConfigurations.isEmpty())
+ emit onlineStateChanged(false);
+}
+
+void QNetworkConfigurationManagerPrivate::configurationChanged(QNetworkConfigurationPrivatePointer ptr)
+{
+ QMutexLocker locker(&mutex);
+
+ if (!firstUpdate) {
+ QNetworkConfiguration item;
+ item.d = ptr;
+ emit configurationChanged(item);
+ }
+
+ bool previous = !onlineConfigurations.isEmpty();
+
+ if (ptr->state == QNetworkConfiguration::Active)
+ onlineConfigurations.insert(ptr);
+ else
+ onlineConfigurations.remove(ptr);
+
+ bool online = !onlineConfigurations.isEmpty();
+
+ if (!firstUpdate && online != previous)
+ emit onlineStateChanged(online);
+}
+
+void QNetworkConfigurationManagerPrivate::updateConfigurations()
+{
+ QMutexLocker locker(&mutex);
+
+ if (firstUpdate) {
+ updating = false;
+
+ QFactoryLoader *l = loader();
+
+ QBearerEngine *generic = 0;
+
+ foreach (const QString &key, l->keys()) {
+ QBearerEnginePlugin *plugin = qobject_cast<QBearerEnginePlugin *>(l->instance(key));
+ if (plugin) {
+ QBearerEngine *engine = plugin->create(key);
+ if (!engine)
+ continue;
+
+ if (key == QLatin1String("generic"))
+ generic = engine;
+ else
+ sessionEngines.append(engine);
+
+ connect(engine, SIGNAL(updateCompleted()),
+ this, SLOT(updateConfigurations()));
+ connect(engine, SIGNAL(configurationAdded(QNetworkConfigurationPrivatePointer)),
+ this, SLOT(configurationAdded(QNetworkConfigurationPrivatePointer)));
+ connect(engine, SIGNAL(configurationRemoved(QNetworkConfigurationPrivatePointer)),
+ this, SLOT(configurationRemoved(QNetworkConfigurationPrivatePointer)));
+ connect(engine, SIGNAL(configurationChanged(QNetworkConfigurationPrivatePointer)),
+ this, SLOT(configurationChanged(QNetworkConfigurationPrivatePointer)));
+
+ capFlags |= engine->capabilities();
+ }
+ }
+
+ if (generic)
+ sessionEngines.append(generic);
+ }
+
+ QBearerEngine *engine = qobject_cast<QBearerEngine *>(sender());
+ if (!updatingEngines.isEmpty() && engine) {
+ int index = sessionEngines.indexOf(engine);
+ if (index >= 0)
+ updatingEngines.remove(index);
+ }
+
+ if (updating && updatingEngines.isEmpty()) {
+ updating = false;
+ emit configurationUpdateComplete();
+ }
+
+ if (firstUpdate)
+ firstUpdate = false;
+}
+
+void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate()
+{
+ QMutexLocker locker(&mutex);
+
+ if (sessionEngines.isEmpty()) {
+ emit configurationUpdateComplete();
+ return;
+ }
+
+ updating = true;
+
+ for (int i = 0; i < sessionEngines.count(); ++i) {
+ updatingEngines.insert(i);
+ sessionEngines.at(i)->requestUpdate();
+ }
+}
+
+QList<QBearerEngine *> QNetworkConfigurationManagerPrivate::engines()
+{
+ QMutexLocker locker(&mutex);
+
+ return sessionEngines;
+}
+
+QT_END_NAMESPACE
diff --git a/src/network/bearer/qnetworkconfigmanager_p.h b/src/network/bearer/qnetworkconfigmanager_p.h
new file mode 100644
index 0000000..c7e988e
--- /dev/null
+++ b/src/network/bearer/qnetworkconfigmanager_p.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNETWORKCONFIGURATIONMANAGERPRIVATE_H
+#define QNETWORKCONFIGURATIONMANAGERPRIVATE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qnetworkconfigmanager.h"
+#include "qnetworkconfiguration_p.h"
+
+#include <QtCore/qmutex.h>
+
+QT_BEGIN_NAMESPACE
+
+class QBearerEngine;
+
+class Q_NETWORK_EXPORT QNetworkConfigurationManagerPrivate : public QObject
+{
+ Q_OBJECT
+public:
+ QNetworkConfigurationManagerPrivate();
+ virtual ~QNetworkConfigurationManagerPrivate();
+
+ QNetworkConfiguration defaultConfiguration();
+
+ QNetworkConfigurationManager::Capabilities capFlags;
+
+ void performAsyncConfigurationUpdate();
+
+ QList<QBearerEngine *> engines();
+
+public slots:
+ void updateConfigurations();
+
+Q_SIGNALS:
+ void configurationAdded(const QNetworkConfiguration& config);
+ void configurationRemoved(const QNetworkConfiguration& config);
+ void configurationUpdateComplete();
+ void configurationChanged(const QNetworkConfiguration& config);
+ void onlineStateChanged(bool isOnline);
+
+ void abort();
+
+private:
+ QMutex mutex;
+
+ QList<QBearerEngine *> sessionEngines;
+
+ QSet<QNetworkConfigurationPrivatePointer> onlineConfigurations;
+
+ QSet<int> updatingEngines;
+ bool updating;
+
+ bool firstUpdate;
+
+private Q_SLOTS:
+ void configurationAdded(QNetworkConfigurationPrivatePointer ptr);
+ void configurationRemoved(QNetworkConfigurationPrivatePointer ptr);
+ void configurationChanged(QNetworkConfigurationPrivatePointer ptr);
+};
+
+Q_NETWORK_EXPORT QNetworkConfigurationManagerPrivate *qNetworkConfigurationManagerPrivate();
+
+QT_END_NAMESPACE
+
+#endif //QNETWORKCONFIGURATIONMANAGERPRIVATE_H
diff --git a/src/network/bearer/qnetworkconfiguration.cpp b/src/network/bearer/qnetworkconfiguration.cpp
new file mode 100644
index 0000000..c551dc5
--- /dev/null
+++ b/src/network/bearer/qnetworkconfiguration.cpp
@@ -0,0 +1,396 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnetworkconfiguration.h"
+
+#include "qnetworkconfiguration_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QNetworkConfiguration
+
+ \brief The QNetworkConfiguration class provides an abstraction of one or more access point configurations.
+
+ \since 4.7
+
+ \inmodule QtNetwork
+ \ingroup bearer
+
+ QNetworkConfiguration encapsulates a single access point or service network.
+ In most cases a single access point configuration can be mapped to one network
+ interface. However a single network interface may not always map to only one
+ access point configuration. Multiple configurations for the same
+ network device may enable multiple access points. An example
+ device that could exhibit such a configuration might be a
+ Smartphone which allows the user to manage multiple WLAN
+ configurations while the device itself has only one WLAN network device.
+
+ The QNetworkConfiguration also supports the concept of service networks.
+ This concept allows the grouping of multiple access point configurations
+ into one entity. Such a group is called service network and can be
+ beneficial in cases whereby a network session to a
+ particular destination network is required (e.g. a company network).
+ When using a service network the user doesn't usually care which one of the
+ connectivity options is chosen (e.g. corporate WLAN or VPN via GPRS)
+ as long as he can reach the company's target server. Depending
+ on the current position and time some of the access points that make
+ up the service network may not even be available. Furthermore
+ automated access point roaming can be enabled which enables the device
+ to change the network interface configuration dynamically while maintaining
+ the applications connection to the target network. It allows adaption
+ to the changing environment and may enable optimization with regards to
+ cost, speed or other network parameters.
+
+ Special configurations of type UserChoice provide a placeholder configuration which is
+ resolved to an actual network configuration by the platform when a
+ \l {QNetworkSession}{session} is \l {QNetworkSession::open()}{opened}. Not all platforms
+ support the concept of a user choice configuration.
+
+ \section1 Configuration states
+
+ The list of available configurations can be obtained via
+ QNetworkConfigurationManager::allConfigurations(). A configuration can have
+ multiple states. The \l Defined configuration state indicates that the configuration
+ is stored on the device. However the configuration is not yet ready to be activated
+ as e.g. a WLAN may not be available at the current time.
+
+ The \l Discovered state implies that the configuration is \l Defined and
+ the outside conditions are such that the configuration can be used immediately
+ to open a new network session. An example of such an outside condition may be
+ that the Ethernet cable is actually connected to the device or that the WLAN
+ with the specified SSID is in range.
+
+ The \l Active state implies that the configuration is \l Discovered. A configuration
+ in this state is currently being used by an application. The underlying network
+ interface has a valid IP configuration and can transfer IP packets between the
+ device and the target network.
+
+ The \l Undefined state indicates that the system has knowledge of possible target
+ networks but cannot actually use that knowledge to connect to it. An example
+ for such a state could be an encrypted WLAN that has been discovered
+ but the user hasn't actually saved a configuration including the required password
+ which would allow the device to connect to it.
+
+ Depending on the type of configuration some states are transient in nature. A GPRS/UMTS
+ connection may almost always be \l Discovered if the GSM/UMTS network is available.
+ However if the GSM/UMTS network looses the connection the associated configuration may change its state
+ from \l Discovered to \l Defined as well. A similar use case might be triggered by
+ WLAN availability. QNetworkConfigurationManager::updateConfigurations() can be used to
+ manually trigger updates of states. Note that some platforms do not require such updates
+ as they implicitly change the state once it has been discovered. If the state of a
+ configuration changes all related QNetworkConfiguration instances change their state automatically.
+
+ \sa QNetworkSession, QNetworkConfigurationManager
+*/
+
+/*!
+ \enum QNetworkConfiguration::Type
+
+ This enum describes the type of configuration.
+
+ \value InternetAccessPoint The configuration specifies the details for a single access point.
+ Note that configurations of type InternetAccessPoint may be part
+ of other QNetworkConfigurations of type ServiceNetwork.
+ \value ServiceNetwork The configuration is based on a group of QNetworkConfigurations of
+ type InternetAccessPoint. All group members can reach the same
+ target network. This type of configuration is a mandatory
+ requirement for roaming enabled network sessions. On some
+ platforms this form of configuration may also be called Service
+ Network Access Point (SNAP).
+ \value UserChoice The configuration is a placeholder which will be resolved to an
+ actual configuration by the platform when a session is opened. Depending
+ on the platform the selection may generate a popup dialog asking the user
+ for his preferred choice.
+ \value Invalid The configuration is invalid.
+*/
+
+/*!
+ \enum QNetworkConfiguration::StateFlag
+
+ Specifies the configuration states.
+
+ \value Undefined This state is used for transient configurations such as newly discovered
+ WLANs for which the user has not actually created a configuration yet.
+ \value Defined Defined configurations are known to the system but are not immediately
+ usable (e.g. a configured WLAN is not within range or the Ethernet cable
+ is currently not plugged into the machine).
+ \value Discovered A discovered configuration can be immediately used to create a new
+ QNetworkSession. An example of a discovered configuration could be a WLAN
+ which is within in range. If the device moves out of range the discovered
+ flag is dropped. A second example is a GPRS configuration which generally
+ remains discovered for as long as the device has network coverage. A
+ configuration that has this state is also in state
+ QNetworkConfiguration::Defined. If the configuration is a service network
+ this flag is set if at least one of the underlying access points
+ configurations has the Discovered state.
+ \value Active The configuration is currently used by an open network session
+ (see \l QNetworkSession::isOpen()). However this does not mean that the
+ current process is the entity that created the open session. It merely
+ indicates that if a new QNetworkSession were to be constructed based on
+ this configuration \l QNetworkSession::state() would return
+ \l QNetworkSession::Connected. This state implies the
+ QNetworkConfiguration::Discovered state.
+*/
+
+/*!
+ \enum QNetworkConfiguration::Purpose
+
+ Specifies the purpose of the configuration.
+
+ \value UnknownPurpose The configuration doesn't specify any purpose. This is the default value.
+ \value PublicPurpose The configuration can be used for general purpose internet access.
+ \value PrivatePurpose The configuration is suitable to access a private network such as an office Intranet.
+ \value ServiceSpecificPurpose The configuration can be used for operator specific services (e.g.
+ receiving MMS messages or content streaming).
+*/
+
+/*!
+ Constructs an invalid configuration object.
+
+ \sa isValid()
+*/
+QNetworkConfiguration::QNetworkConfiguration()
+ : d(0)
+{
+}
+
+/*!
+ Creates a copy of the QNetworkConfiguration object contained in \a other.
+*/
+QNetworkConfiguration::QNetworkConfiguration(const QNetworkConfiguration& other)
+ : d(other.d)
+{
+}
+
+/*!
+ Copies the content of the QNetworkConfiguration object contained in \a other into this one.
+*/
+QNetworkConfiguration& QNetworkConfiguration::operator=(const QNetworkConfiguration& other)
+{
+ d = other.d;
+ return *this;
+}
+
+/*!
+ Frees the resources associated with the QNetworkConfiguration object.
+*/
+QNetworkConfiguration::~QNetworkConfiguration()
+{
+}
+
+/*!
+ Returns true, if this configuration is the same as the \a other
+ configuration given; otherwise returns false.
+*/
+bool QNetworkConfiguration::operator==(const QNetworkConfiguration& other) const
+{
+ if (!d)
+ return !other.d;
+
+ if (!other.d)
+ return false;
+
+ return (d == other.d);
+}
+
+/*!
+ \fn bool QNetworkConfiguration::operator!=(const QNetworkConfiguration& other) const
+
+ Returns true if this configuration is not the same as the \a other
+ configuration given; otherwise returns false.
+*/
+
+/*!
+ Returns the user visible name of this configuration.
+
+ The name may either be the name of the underlying access point or the
+ name for service network that this configuration represents.
+*/
+QString QNetworkConfiguration::name() const
+{
+ return d ? d->name : QString();
+}
+
+/*!
+ Returns the unique and platform specific identifier for this network configuration;
+ otherwise an empty string.
+*/
+QString QNetworkConfiguration::identifier() const
+{
+ return d ? d->id : QString();
+}
+
+/*!
+ Returns the type of the configuration.
+
+ A configuration can represent a single access point configuration or
+ a set of access point configurations. Such a set is called service network.
+ A configuration that is based on a service network can potentially support
+ roaming of network sessions.
+*/
+QNetworkConfiguration::Type QNetworkConfiguration::type() const
+{
+ return d ? d->type : QNetworkConfiguration::Invalid;
+}
+
+/*!
+ Returns true if this QNetworkConfiguration object is valid.
+ A configuration may become invalid if the user deletes the configuration or
+ the configuration was default-constructed.
+
+ The addition and removal of configurations can be monitored via the
+ QNetworkConfigurationManager.
+
+ \sa QNetworkConfigurationManager
+*/
+bool QNetworkConfiguration::isValid() const
+{
+ return d ? d->isValid : false;
+}
+
+/*!
+ Returns the current state of the configuration.
+*/
+QNetworkConfiguration::StateFlags QNetworkConfiguration::state() const
+{
+ return d ? d->state : QNetworkConfiguration::Undefined;
+}
+
+/*!
+ Returns the purpose of this configuration.
+
+ The purpose field may be used to programmatically determine the
+ purpose of a configuration. Such information is usually part of the
+ access point or service network meta data.
+*/
+QNetworkConfiguration::Purpose QNetworkConfiguration::purpose() const
+{
+ return d ? d->purpose : QNetworkConfiguration::UnknownPurpose;
+}
+
+/*!
+ Returns true if this configuration supports roaming; otherwise false.
+*/
+bool QNetworkConfiguration::isRoamingAvailable() const
+{
+ return d ? d->roamingSupported : false;
+}
+
+/*!
+ Returns all sub configurations of this network configuration.
+ Only network configurations of type \l ServiceNetwork can have children. Otherwise
+ this function returns an empty list.
+*/
+QList<QNetworkConfiguration> QNetworkConfiguration::children() const
+{
+ QList<QNetworkConfiguration> results;
+ if (type() != QNetworkConfiguration::ServiceNetwork || !isValid() )
+ return results;
+
+ QMutableListIterator<QNetworkConfigurationPrivatePointer> iter(d->serviceNetworkMembers);
+ while(iter.hasNext()) {
+ QNetworkConfigurationPrivatePointer p = iter.next();
+ //if we have an invalid member get rid of it -> was deleted earlier on
+ if (!p->isValid)
+ iter.remove();
+
+ QNetworkConfiguration item;
+ item.d = p;
+ results << item;
+ }
+
+ return results;
+}
+
+/*!
+ Returns the type of bearer. The string is not translated and
+ therefore can not be shown to the user. The subsequent table presents the currently known
+ bearer types:
+
+ \table
+ \header
+ \o Value
+ \o Description
+ \row
+ \o Unknown
+ \o The session is based on an unknown or unspecified bearer type.
+ \row
+ \o Ethernet
+ \o The session is based on Ethernet.
+ \row
+ \o WLAN
+ \o The session is based on Wireless LAN.
+ \row
+ \o 2G
+ \o The session uses CSD, GPRS, HSCSD, EDGE or cdmaOne.
+ \row
+ \o CDMA2000
+ \o The session uses CDMA.
+ \row
+ \o WCDMA
+ \o The session uses W-CDMA/UMTS.
+ \row
+ \o HSPA
+ \o The session uses High Speed Packet Access.
+ \row
+ \o Bluetooth
+ \o The session uses Bluetooth.
+ \row
+ \o WiMAX
+ \o The session uses WiMAX.
+ \endtable
+
+ This function returns an empty string if this is an invalid configuration,
+ a network configuration of type \l QNetworkConfiguration::ServiceNetwork or
+ \l QNetworkConfiguration::UserChoice.
+*/
+QString QNetworkConfiguration::bearerName() const
+{
+ if (!isValid())
+ return QString();
+
+ return d->bearerName();
+}
+
+
+QT_END_NAMESPACE
+
diff --git a/src/network/bearer/qnetworkconfiguration.h b/src/network/bearer/qnetworkconfiguration.h
new file mode 100644
index 0000000..dad6198
--- /dev/null
+++ b/src/network/bearer/qnetworkconfiguration.h
@@ -0,0 +1,115 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNETWORKCONFIGURATION_H
+#define QNETWORKCONFIGURATION_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qshareddata.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qlist.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Network)
+
+class QNetworkConfigurationPrivate;
+class Q_NETWORK_EXPORT QNetworkConfiguration
+{
+public:
+ QNetworkConfiguration();
+ QNetworkConfiguration(const QNetworkConfiguration& other);
+ QNetworkConfiguration &operator=(const QNetworkConfiguration& other);
+ ~QNetworkConfiguration();
+
+ bool operator==(const QNetworkConfiguration& cp) const;
+ inline bool operator!=(const QNetworkConfiguration& cp) const
+ { return !operator==(cp); }
+
+ enum Type {
+ InternetAccessPoint = 0,
+ ServiceNetwork,
+ UserChoice,
+ Invalid
+ };
+
+ enum Purpose {
+ UnknownPurpose = 0,
+ PublicPurpose,
+ PrivatePurpose,
+ ServiceSpecificPurpose
+ };
+
+ enum StateFlag {
+ Undefined = 0x0000001,
+ Defined = 0x0000002,
+ Discovered = 0x0000006,
+ Active = 0x000000e
+ };
+
+ Q_DECLARE_FLAGS(StateFlags, StateFlag)
+
+ StateFlags state() const;
+ Type type() const;
+ Purpose purpose() const;
+ QString bearerName() const;
+ QString identifier() const;
+ bool isRoamingAvailable() const;
+ QList<QNetworkConfiguration> children() const;
+
+ QString name() const;
+ bool isValid() const;
+
+private:
+ friend class QNetworkConfigurationPrivate;
+ friend class QNetworkConfigurationManager;
+ friend class QNetworkConfigurationManagerPrivate;
+ friend class QNetworkSessionPrivate;
+ QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> d;
+};
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QNETWORKCONFIGURATION_H
diff --git a/src/network/bearer/qnetworkconfiguration_p.h b/src/network/bearer/qnetworkconfiguration_p.h
new file mode 100644
index 0000000..6b40946
--- /dev/null
+++ b/src/network/bearer/qnetworkconfiguration_p.h
@@ -0,0 +1,107 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNETWORKCONFIGURATIONPRIVATE_H
+#define QNETWORKCONFIGURATIONPRIVATE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qnetworkconfiguration.h"
+#include <QtCore/qshareddata.h>
+#include <QtNetwork/QNetworkInterface>
+
+QT_BEGIN_NAMESPACE
+
+typedef QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> QNetworkConfigurationPrivatePointer;
+class QNetworkConfigurationPrivate : public QSharedData
+{
+public:
+ QNetworkConfigurationPrivate ()
+ : isValid(false), type(QNetworkConfiguration::Invalid),
+ roamingSupported(false), purpose(QNetworkConfiguration::UnknownPurpose), internet(false)
+ {
+ }
+
+ ~QNetworkConfigurationPrivate()
+ {
+ //release pointers to member configurations
+ serviceNetworkMembers.clear();
+ }
+
+ virtual QString bearerName() const
+ {
+ return bearer;
+ }
+
+ QString bearer;
+
+ QString name;
+
+ bool isValid;
+ QString id;
+ QNetworkConfiguration::StateFlags state;
+ QNetworkConfiguration::Type type;
+ bool roamingSupported;
+ QNetworkConfiguration::Purpose purpose;
+
+ bool internet;
+
+ QList<QNetworkConfigurationPrivatePointer> serviceNetworkMembers;
+
+private:
+
+ // disallow detaching
+ QNetworkConfigurationPrivate &operator=(const QNetworkConfigurationPrivate &other);
+ QNetworkConfigurationPrivate(const QNetworkConfigurationPrivate &other);
+};
+
+QT_END_NAMESPACE
+
+#endif //QNETWORKCONFIGURATIONPRIVATE_H
diff --git a/src/network/bearer/qnetworksession.cpp b/src/network/bearer/qnetworksession.cpp
new file mode 100644
index 0000000..6a82791
--- /dev/null
+++ b/src/network/bearer/qnetworksession.cpp
@@ -0,0 +1,684 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QEventLoop>
+#include <QTimer>
+
+#include "qnetworksession.h"
+#include "qbearerengine_p.h"
+#include "qnetworkconfigmanager_p.h"
+#include "qnetworksession_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QNetworkSession
+
+ \brief The QNetworkSession class provides control over the system's access points
+ and enables session management for cases when multiple clients access the same access point.
+
+ \since 4.7
+
+ \inmodule QtNetwork
+ \ingroup bearer
+
+ A QNetworkSession enables control over the system's network interfaces. The session's configuration
+ parameter are determined via the QNetworkConfiguration object to which it is bound. Depending on the
+ type of the session (single access point or service network) a session may be linked to one or more
+ network interfaces. By means of \l{open()}{opening} and \l{close()}{closing} of network sessions
+ a developer can start and stop the systems network interfaces. If the configuration represents
+ multiple access points (see \l QNetworkConfiguration::ServiceNetwork) more advanced features such as roaming may be supported.
+
+ QNetworkSession supports session management within the same process and depending on the platform's
+ capabilities may support out-of-process sessions. If the same
+ network configuration is used by multiple open sessions the underlying network interface is only terminated once
+ the last session has been closed.
+
+ \section1 Roaming
+
+ Applications may connect to the preferredConfigurationChanged() signal in order to
+ receive notifications when a more suitable access point becomes available.
+ In response to this signal the application must either initiate the roaming via migrate()
+ or ignore() the new access point. Once the session has roamed the
+ newConfigurationActivated() signal is emitted. The application may now test the
+ carrier and must either accept() or reject() it. The session will return to the previous
+ access point if the roaming was rejected. The subsequent state diagram depicts the required
+ state transitions.
+
+ \image roaming-states.png
+
+ Some platforms may distinguish forced roaming and application level roaming (ALR).
+ ALR implies that the application controls (via migrate(), ignore(), accept() and reject())
+ whether a network session can roam from one access point to the next. Such control is useful
+ if the application maintains stateful socket connections and wants to control the transition from
+ one interface to the next. Forced roaming implies that the system automatically roams to the next network without
+ consulting the application. This has the advantage that the application can make use of roaming features
+ without actually being aware of it. It is expected that the application detects that the underlying
+ socket is broken and automatically reconnects via the new network link.
+
+ If the platform supports both modes of roaming, an application indicates its preference
+ by connecting to the preferredConfigurationChanged() signal. Connecting to this signal means that
+ the application wants to take control over the roaming behavior and therefore implies application
+ level roaming. If the client does not connect to the preferredConfigurationChanged(), forced roaming
+ is used. If forced roaming is not supported the network session will not roam by default.
+
+ Some applications may want to suppress any form of roaming altogether. Possible use cases may be
+ high priority downloads or remote services which cannot handle a roaming enabled client. Clients
+ can suppress roaming by connecting to the preferredConfigurationChanged() signal and answer each
+ signal emission with ignore().
+
+ \sa QNetworkConfiguration, QNetworkConfigurationManager
+*/
+
+/*!
+ \enum QNetworkSession::State
+
+ This enum describes the connectivity state of the session. If the session is based on a
+ single access point configuration the state of the session is the same as the state of the
+ associated network interface.
+
+ \value Invalid The session is invalid due to an invalid configuration. This may
+ happen due to a removed access point or a configuration that was
+ invalid to begin with.
+ \value NotAvailable The session is based on a defined but not yet discovered QNetworkConfiguration
+ (see \l QNetworkConfiguration::StateFlag).
+ \value Connecting The network session is being established.
+ \value Connected The network session is connected. If the current process wishes to use this session
+ it has to register its interest by calling open(). A network session
+ is considered to be ready for socket operations if it isOpen() and connected.
+ \value Closing The network session is in the process of being shut down.
+ \value Disconnected The network session is not connected. The associated QNetworkConfiguration
+ has the state QNetworkConfiguration::Discovered.
+ \value Roaming The network session is roaming from one access point to another
+ access point.
+*/
+
+/*!
+ \enum QNetworkSession::SessionError
+
+ This enum describes the session errors that can occur.
+
+ \value UnknownSessionError An unidentified error occurred.
+ \value SessionAbortedError The session was aborted by the user or system.
+ \value RoamingError The session cannot roam to a new configuration.
+ \value OperationNotSupportedError The operation is not supported for current configuration.
+ \value InvalidConfigurationError The operation cannot currently be performed for the
+ current configuration.
+*/
+
+/*!
+ \fn void QNetworkSession::stateChanged(QNetworkSession::State state)
+
+ This signal is emitted whenever the state of the network session changes.
+ The \a state parameter is the new state.
+
+ \sa state()
+*/
+
+/*!
+ \fn void QNetworkSession::error(QNetworkSession::SessionError error)
+
+ This signal is emitted after an error occurred. The \a error parameter
+ describes the error that occurred.
+
+ \sa error(), errorString()
+*/
+
+/*!
+ \fn void QNetworkSession::preferredConfigurationChanged(const QNetworkConfiguration& config, bool isSeamless)
+
+ This signal is emitted when the preferred configuration/access point for the
+ session changes. Only sessions which are based on service network configurations
+ may emit this signal. \a config can be used to determine access point specific
+ details such as proxy settings and \a isSeamless indicates whether roaming will
+ break the sessions IP address.
+
+ As a consequence to this signal the application must either start the roaming process
+ by calling migrate() or choose to ignore() the new access point.
+
+ If the roaming process is non-seamless the IP address will change which means that
+ a socket becomes invalid. However seamless mobility can ensure that the local IP address
+ does not change. This is achieved by using a virtual IP address which is bound to the actual
+ link address. During the roaming process the virtual address is attached to the new link
+ address.
+
+ Some platforms may support the concept of Forced Roaming and Application Level Roaming (ALR).
+ Forced roaming implies that the platform may simply roam to a new configuration without
+ consulting applications. It is up to the application to detect the link layer loss and reestablish
+ its sockets. In contrast ALR provides the opportunity to prevent the system from roaming.
+ If this session is based on a configuration that supports roaming the application can choose
+ whether it wants to be consulted (ALR use case) by connecting to this signal. For as long as this signal
+ connection remains the session remains registered as a roaming stakeholder; otherwise roaming will
+ be enforced by the platform.
+
+ \sa migrate(), ignore(), QNetworkConfiguration::isRoamingAvailable()
+*/
+
+/*!
+ \fn void QNetworkSession::newConfigurationActivated()
+
+ This signal is emitted once the session has roamed to the new access point.
+ The application may reopen its socket and test the suitability of the new network link.
+ Subsequently it must either accept() or reject() the new access point.
+
+ \sa accept(), reject()
+*/
+
+/*!
+ \fn void QNetworkSession::opened()
+
+ This signal is emitted when the network session has been opened.
+
+ The underlying network interface will not be shut down as long as the session remains open.
+ Note that this feature is dependent on \l{QNetworkConfigurationManager::SystemSessionSupport}{system wide session support}.
+*/
+
+/*!
+ \fn void QNetworkSession::closed()
+
+ This signal is emitted when the network session has been closed.
+*/
+
+/*!
+ Constructs a session based on \a connectionConfig with the given \a parent.
+
+ \sa QNetworkConfiguration
+*/
+QNetworkSession::QNetworkSession(const QNetworkConfiguration& connectionConfig, QObject* parent)
+: QObject(parent), d(0)
+{
+ foreach (QBearerEngine *engine, qNetworkConfigurationManagerPrivate()->engines()) {
+ if (engine->hasIdentifier(connectionConfig.identifier())) {
+ d = engine->createSessionBackend();
+ d->q = this;
+ d->publicConfig = connectionConfig;
+ d->syncStateWithInterface();
+ connect(d, SIGNAL(quitPendingWaitsForOpened()), this, SIGNAL(opened()));
+ connect(d, SIGNAL(error(QNetworkSession::SessionError)),
+ this, SIGNAL(error(QNetworkSession::SessionError)));
+ connect(d, SIGNAL(stateChanged(QNetworkSession::State)),
+ this, SIGNAL(stateChanged(QNetworkSession::State)));
+ connect(d, SIGNAL(closed()), this, SIGNAL(closed()));
+ connect(d, SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool)),
+ this, SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool)));
+ connect(d, SIGNAL(newConfigurationActivated()),
+ this, SIGNAL(newConfigurationActivated()));
+ break;
+ }
+ }
+}
+
+/*!
+ Frees the resources associated with the QNetworkSession object.
+*/
+QNetworkSession::~QNetworkSession()
+{
+ delete d;
+}
+
+/*!
+ Creates an open session which increases the session counter on the underlying network interface.
+ The system will not terminate a network interface until the session reference counter reaches zero.
+ Therefore an open session allows an application to register its use of the interface.
+
+ As a result of calling open() the interface will be started if it is not connected/up yet.
+ Some platforms may not provide support for out-of-process sessions. On such platforms the session
+ counter ignores any sessions held by another process. The platform capabilities can be
+ detected via QNetworkConfigurationManager::capabilities().
+
+ Note that this call is asynchronous. Depending on the outcome of this call the results can be enquired
+ by connecting to the stateChanged(), opened() or error() signals.
+
+ It is not a requirement to open a session in order to monitor the underlying network interface.
+
+ \sa close(), stop(), isOpen()
+*/
+void QNetworkSession::open()
+{
+ if (d)
+ d->open();
+}
+
+/*!
+ Waits until the session has been opened, up to \a msecs milliseconds. If the session has been opened, this
+ function returns true; otherwise it returns false. In the case where it returns false, you can call error()
+ to determine the cause of the error.
+
+ The following example waits up to one second for the session to be opened:
+
+ \code
+ session->open();
+ if (session->waitForOpened(1000))
+ qDebug("Open!");
+ \endcode
+
+ If \a msecs is -1, this function will not time out.
+
+ \sa open(), error()
+*/
+bool QNetworkSession::waitForOpened(int msecs)
+{
+ if (!d)
+ return false;
+
+ if (d->isOpen)
+ return true;
+
+ if (d->state != Connecting)
+ return false;
+
+ QEventLoop* loop = new QEventLoop(this);
+ QObject::connect(d, SIGNAL(quitPendingWaitsForOpened()),
+ loop, SLOT(quit()));
+
+ //final call
+ if (msecs>=0)
+ QTimer::singleShot(msecs, loop, SLOT(quit()));
+
+ loop->exec();
+ loop->disconnect();
+ loop->deleteLater();
+
+ return d->isOpen;
+}
+
+/*!
+ Decreases the session counter on the associated network configuration. If the session counter reaches zero
+ the active network interface is shut down. This also means that state() will only change from \l Connected to
+ \l Disconnected if the current session was the last open session.
+
+ If the platform does not support out-of-process sessions calling this function does not stop the
+ interface. In this case \l{stop()} has to be used to force a shut down.
+ The platform capabilities can be detected via QNetworkConfigurationManager::capabilities().
+
+ Note that this call is asynchronous. Depending on the outcome of this call the results can be enquired
+ by connecting to the stateChanged(), opened() or error() signals.
+
+ \sa open(), stop(), isOpen()
+*/
+void QNetworkSession::close()
+{
+ if (d)
+ d->close();
+}
+
+/*!
+ Invalidates all open sessions against the network interface and therefore stops the
+ underlying network interface. This function always changes the session's state() flag to
+ \l Disconnected.
+
+ On Symbian platform, a 'NetworkControl' capability is required for
+ full interface-level stop (without the capability, only the current session is stopped).
+
+ \sa open(), close()
+*/
+void QNetworkSession::stop()
+{
+ if (d)
+ d->stop();
+}
+
+/*!
+ Returns the QNetworkConfiguration that this network session object is based on.
+
+ \sa QNetworkConfiguration
+*/
+QNetworkConfiguration QNetworkSession::configuration() const
+{
+ return d ? d->publicConfig : QNetworkConfiguration();
+}
+
+/*!
+ Returns the network interface that is used by this session.
+
+ This function only returns a valid QNetworkInterface when this session is \l Connected.
+
+ The returned interface may change as a result of a roaming process.
+
+ Note: this function does not work in Symbian emulator due to the way the
+ connectivity is emulated on Windows.
+
+ \sa state()
+*/
+QNetworkInterface QNetworkSession::interface() const
+{
+ return d ? d->currentInterface() : QNetworkInterface();
+}
+
+/*!
+ Returns true if this session is open. If the number of all open sessions is greater than
+ zero the underlying network interface will remain connected/up.
+
+ The session can be controlled via open() and close().
+*/
+bool QNetworkSession::isOpen() const
+{
+ return d ? d->isOpen : false;
+}
+
+/*!
+ Returns the state of the session.
+
+ If the session is based on a single access point configuration the state of the
+ session is the same as the state of the associated network interface. Therefore
+ a network session object can be used to monitor network interfaces.
+
+ A \l QNetworkConfiguration::ServiceNetwork based session summarizes the state of all its children
+ and therefore returns the \l Connected state if at least one of the service network's
+ \l {QNetworkConfiguration::children()}{children()} configurations is active.
+
+ Note that it is not required to hold an open session in order to obtain the network interface state.
+ A connected but closed session may be used to monitor network interfaces whereas an open and connected
+ session object may prevent the network interface from being shut down.
+
+ \sa error(), stateChanged()
+*/
+QNetworkSession::State QNetworkSession::state() const
+{
+ return d ? d->state : QNetworkSession::Invalid;
+}
+
+/*!
+ Returns the type of error that last occurred.
+
+ \sa state(), errorString()
+*/
+QNetworkSession::SessionError QNetworkSession::error() const
+{
+ return d ? d->error() : InvalidConfigurationError;
+}
+
+/*!
+ Returns a human-readable description of the last device error that
+ occurred.
+
+ \sa error()
+*/
+QString QNetworkSession::errorString() const
+{
+ return d ? d->errorString() : tr("Invalid configuration.");
+}
+
+/*!
+ Returns the value for property \a key.
+
+ A network session can have properties attached which may describe the session in more details.
+ This function can be used to gain access to those properties.
+
+ The following property keys are guaranteed to be specified on all platforms:
+
+ \table
+ \header
+ \o Key \o Description
+ \row
+ \o ActiveConfiguration
+ \o If the session \l isOpen() this property returns the identifier of the
+ QNetworkConfiguration that is used by this session; otherwise an empty string.
+
+ The main purpose of this key is to determine which Internet access point is used
+ if the session is based on a \l{QNetworkConfiguration::ServiceNetwork}{ServiceNetwork}.
+ The following code snippet highlights the difference:
+ \code
+ QNetworkConfigurationManager mgr;
+ QNetworkConfiguration ap = mgr.defaultConfiguration();
+ QNetworkSession* session = new QNetworkSession(ap);
+ ... //code activates session
+
+ QString ident = session->sessionProperty("ActiveConfiguration").toString();
+ if ( ap.type() == QNetworkConfiguration::ServiceNetwork ) {
+ Q_ASSERT( ap.identifier() != ident );
+ Q_ASSERT( ap.children().contains( mgr.configurationFromIdentifier(ident) ) );
+ } else if ( ap.type() == QNetworkConfiguration::InternetAccessPoint ) {
+ Q_ASSERT( ap.identifier() == ident );
+ }
+ \endcode
+ \row
+ \o UserChoiceConfiguration
+ \o If the session \l isOpen() and is bound to a QNetworkConfiguration of type
+ UserChoice, this property returns the identifier of the QNetworkConfiguration that the
+ configuration resolved to when \l open() was called; otherwise an empty string.
+
+ The purpose of this key is to determine the real QNetworkConfiguration that the
+ session is using. This key is different to \i ActiveConfiguration in that
+ this key may return an identifier for either a
+ \l {QNetworkConfiguration::ServiceNetwork}{service network} or a
+ \l {QNetworkConfiguration::InternetAccessPoint}{Internet access points} configurations
+ whereas \i ActiveConfiguration always returns identifiers to
+ \l {QNetworkConfiguration::InternetAccessPoint}{Internet access points} configurations.
+ \row
+ \o ConnectInBackground
+ \o Setting this property to \i true before calling \l open() implies that the connection attempt
+ is made but if no connection can be established, the user is not connsulted and asked to select
+ a suitable connection. This property is not set by default and support for it depends on the platform.
+ \endtable
+*/
+QVariant QNetworkSession::sessionProperty(const QString& key) const
+{
+ if (!d)
+ return QVariant();
+
+ if (!d->publicConfig.isValid())
+ return QVariant();
+
+ if (key == QLatin1String("ActiveConfiguration")) {
+ if (!d->isOpen)
+ return QString();
+ else
+ return d->activeConfig.identifier();
+ }
+
+ if (key == QLatin1String("UserChoiceConfiguration")) {
+ if (!d->isOpen || d->publicConfig.type() != QNetworkConfiguration::UserChoice)
+ return QString();
+
+ if (d->serviceConfig.isValid())
+ return d->serviceConfig.identifier();
+ else
+ return d->activeConfig.identifier();
+ }
+
+ return d->sessionProperty(key);
+}
+
+/*!
+ Sets the property \a value on the session. The property is identified using
+ \a key. Removing an already set property can be achieved by passing an
+ invalid QVariant.
+
+ Note that the \i UserChoiceConfiguration and \i ActiveConfiguration
+ properties are read only and cannot be changed using this method.
+*/
+void QNetworkSession::setSessionProperty(const QString& key, const QVariant& value)
+{
+ if (!d)
+ return;
+
+ if (key == QLatin1String("ActiveConfiguration") ||
+ key == QLatin1String("UserChoiceConfiguration")) {
+ return;
+ }
+
+ d->setSessionProperty(key, value);
+}
+
+/*!
+ Instructs the session to roam to the new access point. The old access point remains active
+ until the application calls accept().
+
+ The newConfigurationActivated() signal is emitted once roaming has been completed.
+
+ \sa accept()
+*/
+void QNetworkSession::migrate()
+{
+ if (d)
+ d->migrate();
+}
+
+/*!
+ This function indicates that the application does not wish to roam the session.
+
+ \sa migrate()
+*/
+void QNetworkSession::ignore()
+{
+ // Needed on at least Symbian platform: the roaming must be explicitly
+ // ignore()'d or migrate()'d
+ if (d)
+ d->ignore();
+}
+
+/*!
+ Instructs the session to permanently accept the new access point. Once this function
+ has been called the session may not return to the old access point.
+
+ The old access point may be closed in the process if there are no other network sessions for it.
+ Therefore any open socket that still uses the old access point
+ may become unusable and should be closed before completing the migration.
+*/
+void QNetworkSession::accept()
+{
+ if (d)
+ d->accept();
+}
+
+/*!
+ The new access point is not suitable for the application. By calling this function the
+ session returns to the previous access point/configuration. This action may invalidate
+ any socket that has been created via the not desired access point.
+
+ \sa accept()
+*/
+void QNetworkSession::reject()
+{
+ if (d)
+ d->reject();
+}
+
+
+/*!
+ Returns the amount of data sent in bytes; otherwise 0.
+
+ This field value includes the usage across all open network
+ sessions which use the same network interface.
+
+ If the session is based on a service network configuration the number of
+ sent bytes across all active member configurations are returned.
+
+ This function may not always be supported on all platforms and returns
+ 0. The platform capability can be detected via QNetworkConfigurationManager::DataStatistics.
+*/
+quint64 QNetworkSession::bytesWritten() const
+{
+ return d ? d->bytesWritten() : Q_UINT64_C(0);
+}
+
+/*!
+ Returns the amount of data received in bytes; otherwise 0.
+
+ This field value includes the usage across all open network
+ sessions which use the same network interface.
+
+ If the session is based on a service network configuration the number of
+ sent bytes across all active member configurations are returned.
+
+ This function may not always be supported on all platforms and returns
+ 0. The platform capability can be detected via QNetworkConfigurationManager::DataStatistics.
+*/
+quint64 QNetworkSession::bytesReceived() const
+{
+ return d ? d->bytesReceived() : Q_UINT64_C(0);
+}
+
+/*!
+ Returns the number of seconds that the session has been active.
+*/
+quint64 QNetworkSession::activeTime() const
+{
+ return d ? d->activeTime() : Q_UINT64_C(0);
+}
+
+/*!
+ \internal
+
+ This function is required to detect whether the client wants to control
+ the roaming process. If he connects to preferredConfigurationChanged() signal
+ he intends to influence it. Otherwise QNetworkSession always roams
+ without registering this session as a stakeholder in the roaming process.
+
+ For more details check the Forced vs ALR roaming section in the QNetworkSession
+ class description.
+*/
+void QNetworkSession::connectNotify(const char *signal)
+{
+ QObject::connectNotify(signal);
+ //check for preferredConfigurationChanged() signal connect notification
+ //This is not required on all platforms
+ if (!d)
+ return;
+
+ if (qstrcmp(signal, SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool))) == 0)
+ d->setALREnabled(true);
+}
+
+/*!
+ \internal
+
+ This function is called when the client disconnects from the preferredConfigurationChanged()
+ signal.
+
+ \sa connectNotify()
+*/
+void QNetworkSession::disconnectNotify(const char *signal)
+{
+ QObject::disconnectNotify(signal);
+ //check for preferredConfigurationChanged() signal disconnect notification
+ //This is not required on all platforms
+ if (!d)
+ return;
+
+ if (qstrcmp(signal, SIGNAL(preferredConfigurationChanged(QNetworkConfiguration,bool))) == 0)
+ d->setALREnabled(false);
+}
+
+#include "moc_qnetworksession.cpp"
+
+QT_END_NAMESPACE
diff --git a/src/network/bearer/qnetworksession.h b/src/network/bearer/qnetworksession.h
new file mode 100644
index 0000000..18437f6
--- /dev/null
+++ b/src/network/bearer/qnetworksession.h
@@ -0,0 +1,132 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNETWORKSESSION_H
+#define QNETWORKSESSION_H
+
+#include <QtCore/qobject.h>
+#include <QtCore/qstring.h>
+#include <QtNetwork/qnetworkinterface.h>
+#include <QtCore/qvariant.h>
+#include <QtNetwork/qnetworkconfiguration.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Network)
+
+class QNetworkSessionPrivate;
+class Q_NETWORK_EXPORT QNetworkSession : public QObject
+{
+ Q_OBJECT
+public:
+ enum State {
+ Invalid = 0,
+ NotAvailable,
+ Connecting,
+ Connected,
+ Closing,
+ Disconnected,
+ Roaming
+ };
+
+ enum SessionError {
+ UnknownSessionError = 0,
+ SessionAbortedError,
+ RoamingError,
+ OperationNotSupportedError,
+ InvalidConfigurationError
+ };
+
+ QNetworkSession(const QNetworkConfiguration& connConfig, QObject* parent =0);
+ virtual ~QNetworkSession();
+
+ bool isOpen() const;
+ QNetworkConfiguration configuration() const;
+ QNetworkInterface interface() const;
+
+ State state() const;
+ SessionError error() const;
+ QString errorString() const;
+ QVariant sessionProperty(const QString& key) const;
+ void setSessionProperty(const QString& key, const QVariant& value);
+
+ quint64 bytesWritten() const;
+ quint64 bytesReceived() const;
+ quint64 activeTime() const;
+
+ bool waitForOpened(int msecs = 30000);
+
+public Q_SLOTS:
+ void open();
+ void close();
+ void stop();
+
+ //roaming related slots
+ void migrate();
+ void ignore();
+ void accept();
+ void reject();
+
+
+Q_SIGNALS:
+ void stateChanged(QNetworkSession::State);
+ void opened();
+ void closed();
+ void error(QNetworkSession::SessionError);
+ void preferredConfigurationChanged(const QNetworkConfiguration& config, bool isSeamless);
+ void newConfigurationActivated();
+
+protected:
+ virtual void connectNotify(const char *signal);
+ virtual void disconnectNotify(const char *signal);
+
+private:
+ QNetworkSessionPrivate* d;
+ friend class QNetworkSessionPrivate;
+ };
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif //QNETWORKSESSION_H
diff --git a/src/network/bearer/qnetworksession_p.h b/src/network/bearer/qnetworksession_p.h
new file mode 100644
index 0000000..76691b3
--- /dev/null
+++ b/src/network/bearer/qnetworksession_p.h
@@ -0,0 +1,150 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtNetwork module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNETWORKSESSIONPRIVATE_H
+#define QNETWORKSESSIONPRIVATE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qnetworksession.h"
+#include "qnetworkconfiguration_p.h"
+
+#include <QNetworkInterface>
+
+QT_BEGIN_NAMESPACE
+
+class Q_NETWORK_EXPORT QNetworkSessionPrivate : public QObject
+{
+ Q_OBJECT
+
+ friend class QNetworkSession;
+
+public:
+ QNetworkSessionPrivate()
+ : state(QNetworkSession::Invalid), isOpen(false)
+ {
+ }
+
+ virtual ~QNetworkSessionPrivate()
+ {
+ }
+
+ //called by QNetworkSession constructor and ensures
+ //that the state is immediately updated (w/o actually opening
+ //a session). Also this function should take care of
+ //notification hooks to discover future state changes.
+ virtual void syncStateWithInterface() = 0;
+
+ virtual QNetworkInterface currentInterface() const = 0;
+ virtual QVariant sessionProperty(const QString& key) const = 0;
+ virtual void setSessionProperty(const QString& key, const QVariant& value) = 0;
+
+ virtual void open() = 0;
+ virtual void close() = 0;
+ virtual void stop() = 0;
+
+ virtual void setALREnabled(bool /*enabled*/) { }
+ virtual void migrate() = 0;
+ virtual void accept() = 0;
+ virtual void ignore() = 0;
+ virtual void reject() = 0;
+
+ virtual QString errorString() const = 0; //must return translated string
+ virtual QNetworkSession::SessionError error() const = 0;
+
+ virtual quint64 bytesWritten() const = 0;
+ virtual quint64 bytesReceived() const = 0;
+ virtual quint64 activeTime() const = 0;
+
+protected:
+ inline QNetworkConfigurationPrivatePointer privateConfiguration(const QNetworkConfiguration &config) const
+ {
+ return config.d;
+ }
+
+ inline void setPrivateConfiguration(QNetworkConfiguration &config,
+ QNetworkConfigurationPrivatePointer ptr) const
+ {
+ config.d = ptr;
+ }
+
+Q_SIGNALS:
+ //releases any pending waitForOpened() calls
+ void quitPendingWaitsForOpened();
+
+ void error(QNetworkSession::SessionError error);
+ void stateChanged(QNetworkSession::State state);
+ void closed();
+ void newConfigurationActivated();
+ void preferredConfigurationChanged(const QNetworkConfiguration &config, bool isSeamless);
+
+protected:
+ // The config set on QNetworkSession.
+ QNetworkConfiguration publicConfig;
+
+ // If publicConfig is a ServiceNetwork this is a copy of publicConfig.
+ // If publicConfig is an UserChoice that is resolved to a ServiceNetwork this is the actual
+ // ServiceNetwork configuration.
+ QNetworkConfiguration serviceConfig;
+
+ // This is the actual active configuration currently in use by the session.
+ // Either a copy of publicConfig or one of serviceConfig.children().
+ QNetworkConfiguration activeConfig;
+
+ QNetworkSession::State state;
+ bool isOpen;
+
+ QNetworkSession *q;
+};
+
+QT_END_NAMESPACE
+
+#endif //QNETWORKSESSIONPRIVATE_H
+
diff --git a/src/network/network.pro b/src/network/network.pro
index e890b94..8582d8a 100644
--- a/src/network/network.pro
+++ b/src/network/network.pro
@@ -17,6 +17,7 @@ unix:QMAKE_PKGCONFIG_REQUIRES = QtCore
include(../qbase.pri)
include(access/access.pri)
+include(bearer/bearer.pri)
include(kernel/kernel.pri)
include(socket/socket.pri)
include(ssl/ssl.pri)
diff --git a/src/plugins/bearer/bearer.pro b/src/plugins/bearer/bearer.pro
new file mode 100644
index 0000000..7ba62b3
--- /dev/null
+++ b/src/plugins/bearer/bearer.pro
@@ -0,0 +1,14 @@
+TEMPLATE = subdirs
+
+!maemo:contains(QT_CONFIG, dbus):contains(QT_CONFIG, networkmanager) {
+ SUBDIRS += networkmanager generic
+}
+#win32:SUBDIRS += nla
+win32:SUBDIRS += generic
+win32:!wince*:SUBDIRS += nativewifi
+macx:SUBDIRS += corewlan
+macx:SUBDIRS += generic
+symbian:SUBDIRS += symbian
+maemo6:contains(QT_CONFIG, dbus):SUBDIRS += icd
+
+isEmpty(SUBDIRS):SUBDIRS += generic
diff --git a/src/plugins/bearer/corewlan/corewlan.pro b/src/plugins/bearer/corewlan/corewlan.pro
new file mode 100644
index 0000000..50c72b2
--- /dev/null
+++ b/src/plugins/bearer/corewlan/corewlan.pro
@@ -0,0 +1,24 @@
+TARGET = qcorewlanbearer
+include(../../qpluginbase.pri)
+
+QT += network
+LIBS += -framework Foundation -framework SystemConfiguration
+
+contains(QT_CONFIG, corewlan) {
+ isEmpty(QMAKE_MAC_SDK)|contains(QMAKE_MAC_SDK, "/Developer/SDKs/MacOSX10.6.sdk") {
+ LIBS += -framework CoreWLAN
+ DEFINES += MAC_SDK_10_6
+ }
+}
+
+HEADERS += qcorewlanengine.h \
+ ../qnetworksession_impl.h \
+ ../qbearerengine_impl.h
+
+SOURCES += main.cpp \
+ qcorewlanengine.mm \
+ ../qnetworksession_impl.cpp
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/bearer
+target.path += $$[QT_INSTALL_PLUGINS]/bearer
+INSTALLS += target
diff --git a/src/plugins/bearer/corewlan/main.cpp b/src/plugins/bearer/corewlan/main.cpp
new file mode 100644
index 0000000..5be8c0e
--- /dev/null
+++ b/src/plugins/bearer/corewlan/main.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcorewlanengine.h"
+
+#include <QtNetwork/private/qbearerplugin_p.h>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QCoreWlanEnginePlugin : public QBearerEnginePlugin
+{
+public:
+ QCoreWlanEnginePlugin();
+ ~QCoreWlanEnginePlugin();
+
+ QStringList keys() const;
+ QBearerEngine *create(const QString &key) const;
+};
+
+QCoreWlanEnginePlugin::QCoreWlanEnginePlugin()
+{
+}
+
+QCoreWlanEnginePlugin::~QCoreWlanEnginePlugin()
+{
+}
+
+QStringList QCoreWlanEnginePlugin::keys() const
+{
+ return QStringList() << QLatin1String("corewlan");
+}
+
+QBearerEngine *QCoreWlanEnginePlugin::create(const QString &key) const
+{
+ if (key == QLatin1String("corewlan"))
+ return new QCoreWlanEngine;
+ else
+ return 0;
+}
+
+Q_EXPORT_STATIC_PLUGIN(QCoreWlanEnginePlugin)
+Q_EXPORT_PLUGIN2(qcorewlanbearer, QCoreWlanEnginePlugin)
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.h b/src/plugins/bearer/corewlan/qcorewlanengine.h
new file mode 100644
index 0000000..044b433
--- /dev/null
+++ b/src/plugins/bearer/corewlan/qcorewlanengine.h
@@ -0,0 +1,99 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QCOREWLANENGINE_H
+#define QCOREWLANENGINE_H
+
+#include "../qbearerengine_impl.h"
+
+#include <QMap>
+#include <QTimer>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkConfigurationPrivate;
+
+class QCoreWlanEngine : public QBearerEngineImpl
+{
+ Q_OBJECT
+
+public:
+ QCoreWlanEngine(QObject *parent = 0);
+ ~QCoreWlanEngine();
+
+ QString getInterfaceFromId(const QString &id);
+ bool hasIdentifier(const QString &id);
+
+ QString bearerName(const QString &id);
+
+ void connectToId(const QString &id);
+ void disconnectFromId(const QString &id);
+
+ void requestUpdate();
+
+ QNetworkSession::State sessionStateForId(const QString &id);
+
+ QNetworkConfigurationManager::Capabilities capabilities() const;
+
+ QNetworkSessionPrivate *createSessionBackend();
+
+ QNetworkConfigurationPrivatePointer defaultConfiguration();
+
+ bool getAllScInterfaces();
+
+private Q_SLOTS:
+ void doRequestUpdate();
+
+private:
+ bool isWifiReady(const QString &dev);
+ QMap<QString, QString> configurationInterface;
+ QTimer pollTimer;
+ QStringList scanForSsids(const QString &interfaceName);
+
+ bool isKnownSsid(const QString &interfaceName, const QString &ssid);
+ QList<QNetworkConfigurationPrivate *> foundConfigurations;
+
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/plugins/bearer/corewlan/qcorewlanengine.mm b/src/plugins/bearer/corewlan/qcorewlanengine.mm
new file mode 100644
index 0000000..a5384d1
--- /dev/null
+++ b/src/plugins/bearer/corewlan/qcorewlanengine.mm
@@ -0,0 +1,553 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qcorewlanengine.h"
+#include "../qnetworksession_impl.h"
+
+#include <QtNetwork/private/qnetworkconfiguration_p.h>
+
+#include <QtCore/qthread.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qstringlist.h>
+
+#include <QtCore/qdebug.h>
+
+#if defined(MAC_SDK_10_6) //not much functionality without this
+#include <CoreWLAN/CoreWLAN.h>
+#include <CoreWLAN/CWInterface.h>
+#include <CoreWLAN/CWNetwork.h>
+#include <CoreWLAN/CWNetwork.h>
+#endif
+
+#include <Foundation/NSEnumerator.h>
+#include <Foundation/NSKeyValueObserving.h>
+#include <Foundation/NSAutoreleasePool.h>
+
+#include <SystemConfiguration/SCNetworkConfiguration.h>
+QMap <QString, QString> networkInterfaces;
+
+QT_BEGIN_NAMESPACE
+
+inline QString cfstringRefToQstring(CFStringRef cfStringRef) {
+// return QString([cfStringRef UTF8String]);
+ QString retVal;
+ CFIndex maxLength = 2 * CFStringGetLength(cfStringRef) + 1/*zero term*/; // max UTF8
+ char *cstring = new char[maxLength];
+ if (CFStringGetCString(CFStringRef(cfStringRef), cstring, maxLength, kCFStringEncodingUTF8)) {
+ retVal = QString::fromUtf8(cstring);
+ }
+ delete[] cstring;
+ return retVal;
+}
+
+inline CFStringRef qstringToCFStringRef(const QString &string)
+{
+ return CFStringCreateWithCharacters(0, reinterpret_cast<const UniChar *>(string.unicode()),
+ string.length());
+}
+
+inline NSString *qstringToNSString(const QString &qstr)
+{ return [reinterpret_cast<const NSString *>(qstringToCFStringRef(qstr)) autorelease]; }
+
+inline QString nsstringToQString(const NSString *nsstr)
+{ return cfstringRefToQstring(reinterpret_cast<const CFStringRef>(nsstr)); }
+
+inline QStringList nsarrayToQStringList(void *nsarray)
+{
+ QStringList result;
+ NSArray *array = static_cast<NSArray *>(nsarray);
+ for (NSUInteger i=0; i<[array count]; ++i)
+ result << nsstringToQString([array objectAtIndex:i]);
+ return result;
+}
+
+static QString qGetInterfaceType(const QString &interfaceString)
+{
+ return networkInterfaces.value(interfaceString, QLatin1String("Unknown"));
+}
+
+QCoreWlanEngine::QCoreWlanEngine(QObject *parent)
+: QBearerEngineImpl(parent)
+{
+ connect(&pollTimer, SIGNAL(timeout()), this, SLOT(doRequestUpdate()));
+ pollTimer.setInterval(10000);
+ doRequestUpdate();
+}
+
+QCoreWlanEngine::~QCoreWlanEngine()
+{
+ while (!foundConfigurations.isEmpty())
+ delete foundConfigurations.takeFirst();
+}
+
+QString QCoreWlanEngine::getInterfaceFromId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ return configurationInterface.value(id);
+}
+
+bool QCoreWlanEngine::hasIdentifier(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ return configurationInterface.contains(id);
+}
+
+void QCoreWlanEngine::connectToId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+ QString interfaceString = getInterfaceFromId(id);
+
+ if(networkInterfaces.value(interfaceString) == "WLAN") {
+#if defined(MAC_SDK_10_6)
+ CWInterface *wifiInterface = [CWInterface interfaceWithName: qstringToNSString(interfaceString)];
+ CWConfiguration *userConfig = [ wifiInterface configuration];
+
+ NSSet *remNets = [userConfig rememberedNetworks]; //CWWirelessProfile
+
+ NSEnumerator *enumerator = [remNets objectEnumerator];
+ CWWirelessProfile *wProfile;
+ NSUInteger index=0;
+ CWNetwork *apNetwork;
+ NSDictionary *parametersDict;
+ NSArray* apArray;
+
+ CW8021XProfile *user8021XProfile;
+ NSError *err;
+ NSMutableDictionary *params;
+
+ while ((wProfile = [enumerator nextObject])) { //CWWirelessProfile
+
+ if(id == nsstringToQString([wProfile ssid])) {
+ user8021XProfile = nil;
+ user8021XProfile = [ wProfile user8021XProfile];
+
+ err = nil;
+ params = [NSMutableDictionary dictionaryWithCapacity:0];
+
+ if(user8021XProfile) {
+ [params setValue: user8021XProfile forKey:kCWAssocKey8021XProfile];
+ } else {
+ [params setValue: [wProfile passphrase] forKey: kCWAssocKeyPassphrase];
+ }
+
+ parametersDict = nil;
+ apArray = [NSMutableArray arrayWithArray:[wifiInterface scanForNetworksWithParameters:parametersDict error:&err]];
+
+ if(!err) {
+
+ for(uint row=0; row < [apArray count]; row++ ) {
+ apNetwork = [apArray objectAtIndex:row];
+ if([[apNetwork ssid] compare:[wProfile ssid]] == NSOrderedSame) {
+
+ bool result = [wifiInterface associateToNetwork: apNetwork parameters:[NSDictionary dictionaryWithDictionary:params] error:&err];
+
+ if(!result) {
+ qWarning() <<"ERROR"<< nsstringToQString([err localizedDescription ]);
+ emit connectionError(id, ConnectError);
+ } else {
+ [apNetwork release];
+ [autoreleasepool release];
+ return;
+ }
+ }
+ }
+ }
+ }
+ index++;
+ }
+ [apNetwork release];
+
+ emit connectionError(id, InterfaceLookupError);
+#endif
+ } else {
+ // not wifi
+ }
+ emit connectionError(id, OperationNotSupported);
+ [autoreleasepool release];
+}
+
+void QCoreWlanEngine::disconnectFromId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ QString interfaceString = getInterfaceFromId(id);
+ if(networkInterfaces.value(getInterfaceFromId(id)) == "WLAN") { //wifi only for now
+#if defined(MAC_SDK_10_6)
+ NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+ CWInterface *wifiInterface = [CWInterface interfaceWithName: qstringToNSString(interfaceString)];
+ [wifiInterface disassociate];
+ if([[wifiInterface interfaceState]intValue] != kCWInterfaceStateInactive) {
+ emit connectionError(id, DisconnectionError);
+ }
+ [autoreleasepool release];
+ return;
+#endif
+ } else {
+
+ }
+ emit connectionError(id, OperationNotSupported);
+}
+
+void QCoreWlanEngine::requestUpdate()
+{
+ QMutexLocker locker(&mutex);
+
+ pollTimer.stop();
+ QTimer::singleShot(0, this, SLOT(doRequestUpdate()));
+}
+
+void QCoreWlanEngine::doRequestUpdate()
+{
+ QMutexLocker locker(&mutex);
+
+ getAllScInterfaces();
+
+ QStringList previous = accessPointConfigurations.keys();
+
+ QMapIterator<QString, QString> i(networkInterfaces);
+ while (i.hasNext()) {
+ i.next();
+ if (i.value() == QLatin1String("WLAN")) {
+ QStringList added = scanForSsids(i.key());
+ while (!added.isEmpty()) {
+ previous.removeAll(added.takeFirst());
+ }
+ }
+
+ QNetworkInterface interface = QNetworkInterface::interfaceFromName(i.key());
+
+ if (!interface.isValid())
+ continue;
+
+ uint identifier;
+ if (interface.index())
+ identifier = qHash(QLatin1String("corewlan:") + QString::number(interface.index()));
+ else
+ identifier = qHash(QLatin1String("corewlan:") + interface.hardwareAddress());
+
+ const QString id = QString::number(identifier);
+
+ previous.removeAll(id);
+
+ QString name = interface.humanReadableName();
+ if (name.isEmpty())
+ name = interface.name();
+
+ QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined;
+
+ if (interface.flags() && QNetworkInterface::IsRunning)
+ state = QNetworkConfiguration::Defined;
+
+ if (!interface.addressEntries().isEmpty())
+ state = QNetworkConfiguration::Active;
+
+ if (accessPointConfigurations.contains(id)) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+
+ bool changed = false;
+
+ if (!ptr->isValid) {
+ ptr->isValid = true;
+ changed = true;
+ }
+
+ if (ptr->name != name) {
+ ptr->name = name;
+ changed = true;
+ }
+
+ if (ptr->id != id) {
+ ptr->id = id;
+ changed = true;
+ }
+
+ if (ptr->state != state) {
+ ptr->state = state;
+ changed = true;
+ }
+
+ if (changed)
+ emit configurationChanged(ptr);
+ } else {
+ QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate);
+
+ ptr->name = name;
+ ptr->isValid = true;
+ ptr->id = id;
+ ptr->state = state;
+ ptr->type = QNetworkConfiguration::InternetAccessPoint;
+ ptr->bearer = qGetInterfaceType(interface.name());
+
+ accessPointConfigurations.insert(id, ptr);
+ configurationInterface.insert(id, interface.name());
+
+ emit configurationAdded(ptr);
+ }
+ }
+
+ while (!previous.isEmpty()) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(previous.takeFirst());
+
+ configurationInterface.remove(ptr->id);
+ emit configurationRemoved(ptr);
+ }
+
+ pollTimer.start();
+
+ emit updateCompleted();
+}
+
+QStringList QCoreWlanEngine::scanForSsids(const QString &interfaceName)
+{
+ QMutexLocker locker(&mutex);
+
+ QStringList found;
+
+#if defined(MAC_SDK_10_6)
+ NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+
+ CWInterface *currentInterface = [CWInterface interfaceWithName:qstringToNSString(interfaceName)];
+ NSError *err = nil;
+ NSDictionary *parametersDict = nil;
+ NSArray* apArray = [currentInterface scanForNetworksWithParameters:parametersDict error:&err];
+
+ CWNetwork *apNetwork;
+ if (!err) {
+ for(uint row=0; row < [apArray count]; row++ ) {
+ NSAutoreleasePool *looppool = [[NSAutoreleasePool alloc] init];
+
+ apNetwork = [apArray objectAtIndex:row];
+
+ const QString networkSsid = nsstringToQString([apNetwork ssid]);
+
+ const QString id = QString::number(qHash(QLatin1String("corewlan:") + networkSsid));
+ found.append(id);
+
+ QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined;
+
+ if ([currentInterface.interfaceState intValue] == kCWInterfaceStateRunning) {
+ if (networkSsid == nsstringToQString([currentInterface ssid]))
+ state = QNetworkConfiguration::Active;
+ } else {
+ if (isKnownSsid(interfaceName, networkSsid))
+ state = QNetworkConfiguration::Discovered;
+ else
+ state = QNetworkConfiguration::Defined;
+ }
+
+ if (accessPointConfigurations.contains(id)) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+
+ bool changed = false;
+
+ if (!ptr->isValid) {
+ ptr->isValid = true;
+ changed = true;
+ }
+
+ if (ptr->name != networkSsid) {
+ ptr->name = networkSsid;
+ changed = true;
+ }
+
+ if (ptr->id != id) {
+ ptr->id = id;
+ changed = true;
+ }
+
+ if (ptr->state != state) {
+ ptr->state = state;
+ changed = true;
+ }
+
+ if (changed)
+ emit configurationChanged(ptr);
+ } else {
+ QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate);
+
+ ptr->name = networkSsid;
+ ptr->isValid = true;
+ ptr->id = id;
+ ptr->state = state;
+ ptr->type = QNetworkConfiguration::InternetAccessPoint;
+ ptr->bearer = QLatin1String("WLAN");
+
+ accessPointConfigurations.insert(id, ptr);
+ configurationInterface.insert(id, interfaceName);
+
+ emit configurationAdded(ptr);
+ }
+ [looppool release];
+ }
+ } else {
+ qWarning() << "ERROR scanning for ssids" << nsstringToQString([err localizedDescription])
+ <<nsstringToQString([err domain]);
+ }
+
+ [autoreleasepool drain];
+#else
+ Q_UNUSED(interfaceName);
+#endif
+ return found;
+}
+
+bool QCoreWlanEngine::isWifiReady(const QString &wifiDeviceName)
+{
+ QMutexLocker locker(&mutex);
+
+#if defined(MAC_SDK_10_6)
+ CWInterface *defaultInterface = [CWInterface interfaceWithName: qstringToNSString(wifiDeviceName)];
+ if([defaultInterface power])
+ return true;
+#else
+ Q_UNUSED(wifiDeviceName);
+#endif
+ return false;
+}
+
+bool QCoreWlanEngine::isKnownSsid(const QString &interfaceName, const QString &ssid)
+{
+ QMutexLocker locker(&mutex);
+
+#if defined(MAC_SDK_10_6)
+ CWInterface *wifiInterface = [CWInterface interfaceWithName: qstringToNSString(interfaceName)];
+ CWConfiguration *userConfig = [wifiInterface configuration];
+ NSSet *remNets = [userConfig rememberedNetworks];
+ for (CWWirelessProfile *wProfile in remNets) {
+ if(ssid == nsstringToQString([wProfile ssid]))
+ return true;
+ }
+#else
+ Q_UNUSED(interfaceName);
+ Q_UNUSED(ssid);
+#endif
+ return false;
+}
+
+bool QCoreWlanEngine::getAllScInterfaces()
+{
+ QMutexLocker locker(&mutex);
+
+ networkInterfaces.clear();
+ NSAutoreleasePool *autoreleasepool = [[NSAutoreleasePool alloc] init];
+
+ CFArrayRef interfaces = SCNetworkInterfaceCopyAll();
+ if (interfaces != NULL) {
+ CFIndex interfaceCount;
+ CFIndex interfaceIndex;
+ interfaceCount = CFArrayGetCount(interfaces);
+ for (interfaceIndex = 0; interfaceIndex < interfaceCount; interfaceIndex++) {
+ NSAutoreleasePool *looppool = [[NSAutoreleasePool alloc] init];
+
+ CFStringRef bsdName;
+ CFTypeRef thisInterface = CFArrayGetValueAtIndex(interfaces, interfaceIndex);
+ bsdName = SCNetworkInterfaceGetBSDName((SCNetworkInterfaceRef)thisInterface);
+ QString interfaceName = cfstringRefToQstring(bsdName);
+ QString typeStr;
+ CFStringRef type = SCNetworkInterfaceGetInterfaceType((SCNetworkInterfaceRef)thisInterface);
+ if ( CFEqual(type, kSCNetworkInterfaceTypeIEEE80211)) {
+ typeStr = "WLAN";
+// } else if (CFEqual(type, kSCNetworkInterfaceTypeBluetooth)) {
+// typeStr = "Bluetooth";
+ } else if(CFEqual(type, kSCNetworkInterfaceTypeEthernet)) {
+ typeStr = "Ethernet";
+ } else if(CFEqual(type, kSCNetworkInterfaceTypeFireWire)) {
+ typeStr = "Ethernet"; //ok a bit fudged
+ }
+ if(!networkInterfaces.contains(interfaceName) && !typeStr.isEmpty()) {
+ networkInterfaces.insert(interfaceName,typeStr);
+ }
+ [looppool release];
+ }
+ }
+ CFRelease(interfaces);
+
+ [autoreleasepool drain];
+ return true;
+}
+
+QNetworkSession::State QCoreWlanEngine::sessionStateForId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+
+ if (!ptr)
+ return QNetworkSession::Invalid;
+
+ if (!ptr->isValid) {
+ return QNetworkSession::Invalid;
+ } else if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ return QNetworkSession::Connected;
+ } else if ((ptr->state & QNetworkConfiguration::Discovered) ==
+ QNetworkConfiguration::Discovered) {
+ return QNetworkSession::Disconnected;
+ } else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
+ return QNetworkSession::NotAvailable;
+ } else if ((ptr->state & QNetworkConfiguration::Undefined) ==
+ QNetworkConfiguration::Undefined) {
+ return QNetworkSession::NotAvailable;
+ }
+
+ return QNetworkSession::Invalid;
+}
+
+QNetworkConfigurationManager::Capabilities QCoreWlanEngine::capabilities() const
+{
+ return QNetworkConfigurationManager::ForcedRoaming;
+}
+
+QNetworkSessionPrivate *QCoreWlanEngine::createSessionBackend()
+{
+ return new QNetworkSessionPrivateImpl;
+}
+
+QNetworkConfigurationPrivatePointer QCoreWlanEngine::defaultConfiguration()
+{
+ return QNetworkConfigurationPrivatePointer();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/generic/generic.pro b/src/plugins/bearer/generic/generic.pro
new file mode 100644
index 0000000..1d141fd
--- /dev/null
+++ b/src/plugins/bearer/generic/generic.pro
@@ -0,0 +1,16 @@
+TARGET = qgenericbearer
+include(../../qpluginbase.pri)
+
+QT += network
+
+HEADERS += qgenericengine.h \
+ ../qnetworksession_impl.h \
+ ../qbearerengine_impl.h \
+ ../platformdefs_win.h
+SOURCES += qgenericengine.cpp \
+ ../qnetworksession_impl.cpp \
+ main.cpp
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/bearer
+target.path += $$[QT_INSTALL_PLUGINS]/bearer
+INSTALLS += target
diff --git a/src/plugins/bearer/generic/main.cpp b/src/plugins/bearer/generic/main.cpp
new file mode 100644
index 0000000..ba85d93
--- /dev/null
+++ b/src/plugins/bearer/generic/main.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgenericengine.h"
+
+#include <QtNetwork/private/qbearerplugin_p.h>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QGenericEnginePlugin : public QBearerEnginePlugin
+{
+public:
+ QGenericEnginePlugin();
+ ~QGenericEnginePlugin();
+
+ QStringList keys() const;
+ QBearerEngine *create(const QString &key) const;
+};
+
+QGenericEnginePlugin::QGenericEnginePlugin()
+{
+}
+
+QGenericEnginePlugin::~QGenericEnginePlugin()
+{
+}
+
+QStringList QGenericEnginePlugin::keys() const
+{
+ return QStringList() << QLatin1String("generic");
+}
+
+QBearerEngine *QGenericEnginePlugin::create(const QString &key) const
+{
+ if (key == QLatin1String("generic"))
+ return new QGenericEngine;
+ else
+ return 0;
+}
+
+Q_EXPORT_STATIC_PLUGIN(QGenericEnginePlugin)
+Q_EXPORT_PLUGIN2(qgenericbearer, QGenericEnginePlugin)
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/generic/qgenericengine.cpp b/src/plugins/bearer/generic/qgenericengine.cpp
new file mode 100644
index 0000000..a95b14b
--- /dev/null
+++ b/src/plugins/bearer/generic/qgenericengine.cpp
@@ -0,0 +1,333 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qgenericengine.h"
+#include "../qnetworksession_impl.h"
+
+#include <QtNetwork/private/qnetworkconfiguration_p.h>
+
+#include <QtCore/qthread.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qstringlist.h>
+
+#include <QtCore/qdebug.h>
+
+#ifdef Q_OS_WIN
+#include "../platformdefs_win.h"
+#endif
+
+#ifdef Q_OS_LINUX
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+#endif
+
+
+static QString qGetInterfaceType(const QString &interface)
+{
+#ifdef Q_OS_WIN32
+ unsigned long oid;
+ DWORD bytesWritten;
+
+ NDIS_MEDIUM medium;
+ NDIS_PHYSICAL_MEDIUM physicalMedium;
+
+ HANDLE handle = CreateFile((TCHAR *)QString("\\\\.\\%1").arg(interface).utf16(), 0,
+ FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+ if (handle == INVALID_HANDLE_VALUE)
+ return QLatin1String("Unknown");
+
+ oid = OID_GEN_MEDIA_SUPPORTED;
+ bytesWritten = 0;
+ bool result = DeviceIoControl(handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof(oid),
+ &medium, sizeof(medium), &bytesWritten, 0);
+ if (!result) {
+ CloseHandle(handle);
+ return QLatin1String("Unknown");
+ }
+
+ oid = OID_GEN_PHYSICAL_MEDIUM;
+ bytesWritten = 0;
+ result = DeviceIoControl(handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof(oid),
+ &physicalMedium, sizeof(physicalMedium), &bytesWritten, 0);
+ if (!result) {
+ CloseHandle(handle);
+
+ if (medium == NdisMedium802_3)
+ return QLatin1String("Ethernet");
+ else
+ return QLatin1String("Unknown");
+ }
+
+ CloseHandle(handle);
+
+ if (medium == NdisMedium802_3) {
+ switch (physicalMedium) {
+ case NdisPhysicalMediumWirelessLan:
+ return QLatin1String("WLAN");
+ case NdisPhysicalMediumBluetooth:
+ return QLatin1String("Bluetooth");
+ case NdisPhysicalMediumWiMax:
+ return QLatin1String("WiMAX");
+ default:
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "Physical Medium" << physicalMedium;
+#endif
+ return QLatin1String("Ethernet");
+ }
+ }
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << medium << physicalMedium;
+#endif
+#elif defined(Q_OS_LINUX)
+ int sock = socket(AF_INET, SOCK_DGRAM, 0);
+
+ ifreq request;
+ strncpy(request.ifr_name, interface.toLocal8Bit().data(), sizeof(request.ifr_name));
+ if (ioctl(sock, SIOCGIFHWADDR, &request) >= 0) {
+ switch (request.ifr_hwaddr.sa_family) {
+ case ARPHRD_ETHER:
+ return QLatin1String("Ethernet");
+ }
+ }
+
+ close(sock);
+#else
+ Q_UNUSED(interface);
+#endif
+
+ return QLatin1String("Unknown");
+}
+
+QGenericEngine::QGenericEngine(QObject *parent)
+: QBearerEngineImpl(parent)
+{
+ connect(&pollTimer, SIGNAL(timeout()), this, SLOT(doRequestUpdate()));
+ pollTimer.setInterval(10000);
+ doRequestUpdate();
+}
+
+QGenericEngine::~QGenericEngine()
+{
+}
+
+QString QGenericEngine::getInterfaceFromId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ return configurationInterface.value(id);
+}
+
+bool QGenericEngine::hasIdentifier(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ return configurationInterface.contains(id);
+}
+
+void QGenericEngine::connectToId(const QString &id)
+{
+ emit connectionError(id, OperationNotSupported);
+}
+
+void QGenericEngine::disconnectFromId(const QString &id)
+{
+ emit connectionError(id, OperationNotSupported);
+}
+
+void QGenericEngine::requestUpdate()
+{
+ QMutexLocker locker(&mutex);
+
+ pollTimer.stop();
+ QTimer::singleShot(0, this, SLOT(doRequestUpdate()));
+}
+
+void QGenericEngine::doRequestUpdate()
+{
+ QMutexLocker locker(&mutex);
+
+ // Immediately after connecting with a wireless access point
+ // QNetworkInterface::allInterfaces() will sometimes return an empty list. Calling it again a
+ // second time results in a non-empty list. If we loose interfaces we will end up removing
+ // network configurations which will break current sessions.
+ QList<QNetworkInterface> interfaces = QNetworkInterface::allInterfaces();
+ if (interfaces.isEmpty())
+ interfaces = QNetworkInterface::allInterfaces();
+
+ QStringList previous = accessPointConfigurations.keys();
+
+ // create configuration for each interface
+ while (!interfaces.isEmpty()) {
+ QNetworkInterface interface = interfaces.takeFirst();
+
+ if (!interface.isValid())
+ continue;
+
+ // ignore loopback interface
+ if (interface.flags() & QNetworkInterface::IsLoopBack)
+ continue;
+
+ // ignore WLAN interface handled in seperate engine
+ if (qGetInterfaceType(interface.name()) == QLatin1String("WLAN"))
+ continue;
+
+ uint identifier;
+ if (interface.index())
+ identifier = qHash(QLatin1String("generic:") + QString::number(interface.index()));
+ else
+ identifier = qHash(QLatin1String("generic:") + interface.hardwareAddress());
+
+ const QString id = QString::number(identifier);
+
+ previous.removeAll(id);
+
+ QString name = interface.humanReadableName();
+ if (name.isEmpty())
+ name = interface.name();
+
+ QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Discovered;
+ if (interface.flags() & QNetworkInterface::IsUp)
+ state |= QNetworkConfiguration::Active;
+
+ if (accessPointConfigurations.contains(id)) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+
+ bool changed = false;
+
+ if (!ptr->isValid) {
+ ptr->isValid = true;
+ changed = true;
+ }
+
+ if (ptr->name != name) {
+ ptr->name = name;
+ changed = true;
+ }
+
+ if (ptr->id != id) {
+ ptr->id = id;
+ changed = true;
+ }
+
+ if (ptr->state != state) {
+ ptr->state = state;
+ changed = true;
+ }
+
+ if (changed)
+ emit configurationChanged(ptr);
+ } else {
+ QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate);
+
+ ptr->name = name;
+ ptr->isValid = true;
+ ptr->id = id;
+ ptr->state = state;
+ ptr->type = QNetworkConfiguration::InternetAccessPoint;
+ ptr->bearer = qGetInterfaceType(interface.name());
+
+ accessPointConfigurations.insert(id, ptr);
+ configurationInterface.insert(id, interface.name());
+
+ emit configurationAdded(ptr);
+ }
+ }
+
+ while (!previous.isEmpty()) {
+ QNetworkConfigurationPrivatePointer ptr =
+ accessPointConfigurations.take(previous.takeFirst());
+
+ configurationInterface.remove(ptr->id);
+ emit configurationRemoved(ptr);
+ }
+
+ pollTimer.start();
+
+ emit updateCompleted();
+}
+
+QNetworkSession::State QGenericEngine::sessionStateForId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+
+ if (!ptr)
+ return QNetworkSession::Invalid;
+
+ if (!ptr->isValid) {
+ return QNetworkSession::Invalid;
+ } else if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ return QNetworkSession::Connected;
+ } else if ((ptr->state & QNetworkConfiguration::Discovered) ==
+ QNetworkConfiguration::Discovered) {
+ return QNetworkSession::Disconnected;
+ } else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
+ return QNetworkSession::NotAvailable;
+ } else if ((ptr->state & QNetworkConfiguration::Undefined) ==
+ QNetworkConfiguration::Undefined) {
+ return QNetworkSession::NotAvailable;
+ }
+
+ return QNetworkSession::Invalid;
+}
+
+QNetworkConfigurationManager::Capabilities QGenericEngine::capabilities() const
+{
+ return QNetworkConfigurationManager::ForcedRoaming;
+}
+
+QNetworkSessionPrivate *QGenericEngine::createSessionBackend()
+{
+ return new QNetworkSessionPrivateImpl;
+}
+
+QNetworkConfigurationPrivatePointer QGenericEngine::defaultConfiguration()
+{
+ return QNetworkConfigurationPrivatePointer();
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/bearer/generic/qgenericengine.h b/src/plugins/bearer/generic/qgenericengine.h
new file mode 100644
index 0000000..cd9a976
--- /dev/null
+++ b/src/plugins/bearer/generic/qgenericengine.h
@@ -0,0 +1,92 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGENERICENGINE_H
+#define QGENERICENGINE_H
+
+#include "../qbearerengine_impl.h"
+
+#include <QMap>
+#include <QTimer>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkConfigurationPrivate;
+class QNetworkSessionPrivate;
+
+class QGenericEngine : public QBearerEngineImpl
+{
+ Q_OBJECT
+
+public:
+ QGenericEngine(QObject *parent = 0);
+ ~QGenericEngine();
+
+ QString getInterfaceFromId(const QString &id);
+ bool hasIdentifier(const QString &id);
+
+ QString bearerName(const QString &id);
+
+ void connectToId(const QString &id);
+ void disconnectFromId(const QString &id);
+
+ void requestUpdate();
+
+ QNetworkSession::State sessionStateForId(const QString &id);
+
+ QNetworkConfigurationManager::Capabilities capabilities() const;
+
+ QNetworkSessionPrivate *createSessionBackend();
+
+ QNetworkConfigurationPrivatePointer defaultConfiguration();
+
+private Q_SLOTS:
+ void doRequestUpdate();
+
+private:
+ QMap<QString, QString> configurationInterface;
+ QTimer pollTimer;
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/plugins/bearer/icd/icd.pro b/src/plugins/bearer/icd/icd.pro
new file mode 100644
index 0000000..5eaf5af
--- /dev/null
+++ b/src/plugins/bearer/icd/icd.pro
@@ -0,0 +1,22 @@
+TARGET = qicdbearer
+include(../../qpluginbase.pri)
+
+QT += network dbus
+
+CONFIG += link_pkgconfig
+PKGCONFIG += glib-2.0 dbus-glib-1 gconf-2.0 osso-ic conninet
+
+HEADERS += qicdengine.h \
+ monitor.h \
+ qnetworksession_impl.h
+
+SOURCES += main.cpp \
+ qicdengine.cpp \
+ monitor.cpp \
+ qnetworksession_impl.cpp
+
+#DEFINES += BEARER_MANAGEMENT_DEBUG
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/bearer
+target.path += $$[QT_INSTALL_PLUGINS]/bearer
+INSTALLS += target
diff --git a/src/plugins/bearer/icd/main.cpp b/src/plugins/bearer/icd/main.cpp
new file mode 100644
index 0000000..ad1a918
--- /dev/null
+++ b/src/plugins/bearer/icd/main.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qicdengine.h"
+
+#include <QtNetwork/private/qbearerplugin_p.h>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QIcdEnginePlugin : public QBearerEnginePlugin
+{
+public:
+ QIcdEnginePlugin();
+ ~QIcdEnginePlugin();
+
+ QStringList keys() const;
+ QBearerEngine *create(const QString &key) const;
+};
+
+QIcdEnginePlugin::QIcdEnginePlugin()
+{
+}
+
+QIcdEnginePlugin::~QIcdEnginePlugin()
+{
+}
+
+QStringList QIcdEnginePlugin::keys() const
+{
+ return QStringList() << QLatin1String("icd");
+}
+
+QBearerEngine *QIcdEnginePlugin::create(const QString &key) const
+{
+ if (key == QLatin1String("icd"))
+ return new QIcdEngine;
+ else
+ return 0;
+}
+
+Q_EXPORT_STATIC_PLUGIN(QIcdEnginePlugin)
+Q_EXPORT_PLUGIN2(qicdbearer, QIcdEnginePlugin)
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/icd/monitor.cpp b/src/plugins/bearer/icd/monitor.cpp
new file mode 100644
index 0000000..0ff45d2
--- /dev/null
+++ b/src/plugins/bearer/icd/monitor.cpp
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "monitor.h"
+#include "qicdengine.h"
+
+#include <wlancond.h>
+#include <libicd-network-wlan-dev.h>
+#include <maemo_icd.h>
+#include <iapconf.h>
+
+#define IAP "/system/osso/connectivity/IAP"
+
+static int iap_prefix_len;
+
+/* Notify func that is called when IAP is added or deleted */
+void notify_iap(GConfClient *, guint, GConfEntry *entry, gpointer user_data)
+{
+ const char *key = gconf_entry_get_key(entry);
+ if (key && g_str_has_prefix(key, IAP)) {
+ IapMonitor *ptr = (IapMonitor *)user_data;
+ if (gconf_entry_get_value(entry)) {
+ ptr->iapAdded(key, entry);
+ } else {
+ ptr->iapDeleted(key, entry);
+ }
+ }
+}
+
+
+void IapMonitor::setup(QIcdEngine *d_ptr)
+{
+ if (first_call) {
+ d = d_ptr;
+ iap_prefix_len = strlen(IAP);
+ iap = new Maemo::IAPMonitor(notify_iap, (gpointer)this);
+ first_call = false;
+ }
+}
+
+
+void IapMonitor::cleanup()
+{
+ if (!first_call) {
+ delete iap;
+ timers.removeAll();
+ first_call = true;
+ }
+}
+
+
+void IapMonitor::iapAdded(const char *key, GConfEntry * /*entry*/)
+{
+ //qDebug("Notify called for added element: %s=%s",
+ // gconf_entry_get_key(entry), gconf_value_to_string(gconf_entry_get_value(entry)));
+
+ /* We cannot know when the IAP is fully added to gconf, so a timer is
+ * installed instead. When the timer expires we hope that IAP is added ok.
+ */
+ QString iap_id = QString(key + iap_prefix_len + 1).section('/',0,0);
+ timers.add(iap_id, d);
+}
+
+
+void IapMonitor::iapDeleted(const char *key, GConfEntry * /*entry*/)
+{
+ //qDebug("Notify called for deleted element: %s", gconf_entry_get_key(entry));
+
+ /* We are only interested in IAP deletions so we skip the config entries
+ */
+ if (strstr(key + iap_prefix_len + 1, "/")) {
+ //qDebug("Deleting IAP config %s", key+iap_prefix_len);
+ return;
+ }
+
+ QString iap_id = key + iap_prefix_len + 1;
+ d->deleteConfiguration(iap_id);
+}
diff --git a/src/plugins/bearer/icd/monitor.h b/src/plugins/bearer/icd/monitor.h
new file mode 100644
index 0000000..82b0f36
--- /dev/null
+++ b/src/plugins/bearer/icd/monitor.h
@@ -0,0 +1,116 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef MONITOR_H
+#define MONITOR_H
+
+#include <QtCore/qhash.h>
+#include <QtCore/qtimer.h>
+
+#include <gconf/gconf.h>
+#include <gconf/gconf-client.h>
+
+#include <iapmonitor.h>
+
+class QIcdEngine;
+
+/* The IapAddTimer is a helper class that makes sure we update
+ * the configuration only after all gconf additions to certain
+ * iap are finished (after a certain timeout)
+ */
+class _IapAddTimer : public QObject
+{
+ Q_OBJECT
+
+public:
+ _IapAddTimer() {}
+ ~_IapAddTimer()
+ {
+ if (timer.isActive()) {
+ QObject::disconnect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
+ timer.stop();
+ }
+ }
+
+ void add(QString& iap_id, QIcdEngine *d);
+
+ QString iap_id;
+ QTimer timer;
+ QIcdEngine *d;
+
+public Q_SLOTS:
+ void timeout();
+};
+
+class IapAddTimer {
+ QHash<QString, _IapAddTimer* > timers;
+
+public:
+ IapAddTimer() {}
+ ~IapAddTimer() {}
+
+ void add(QString& iap_id, QIcdEngine *d);
+ void del(QString& iap_id);
+ void removeAll();
+};
+
+class IapMonitor
+{
+public:
+ IapMonitor() : first_call(true) { }
+ friend void notify_iap(GConfClient *, guint,
+ GConfEntry *entry, gpointer user_data);
+
+ void setup(QIcdEngine *d);
+ void cleanup();
+
+private:
+ bool first_call;
+
+ void iapAdded(const char *key, GConfEntry *entry);
+ void iapDeleted(const char *key, GConfEntry *entry);
+
+ Maemo::IAPMonitor *iap;
+ QIcdEngine *d;
+ IapAddTimer timers;
+};
+
+#endif // MONITOR_H
diff --git a/src/plugins/bearer/icd/qicdengine.cpp b/src/plugins/bearer/icd/qicdengine.cpp
new file mode 100644
index 0000000..f10042a
--- /dev/null
+++ b/src/plugins/bearer/icd/qicdengine.cpp
@@ -0,0 +1,426 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qicdengine.h"
+#include "monitor.h"
+#include "qnetworksession_impl.h"
+
+#include <libicd-network-wlan-dev.h>
+#include <maemo_icd.h>
+#include <iapconf.h>
+
+QT_BEGIN_NAMESPACE
+
+IcdNetworkConfigurationPrivate::IcdNetworkConfigurationPrivate()
+: network_attrs(0), service_attrs(0)
+{
+}
+
+IcdNetworkConfigurationPrivate::~IcdNetworkConfigurationPrivate()
+{
+}
+
+QString IcdNetworkConfigurationPrivate::bearerName() const
+{
+ if (iap_type == QLatin1String("WLAN_INFRA") ||
+ iap_type == QLatin1String("WLAN_ADHOC")) {
+ return QLatin1String("WLAN");
+ } else if (iap_type == QLatin1String("GPRS")) {
+ return QLatin1String("HSPA");
+ } else {
+ return iap_type;
+ }
+}
+
+static inline QString network_attrs_to_security(uint network_attrs)
+{
+ uint cap = 0;
+ nwattr2cap(network_attrs, &cap); /* from libicd-network-wlan-dev.h */
+ if (cap & WLANCOND_OPEN)
+ return "NONE";
+ else if (cap & WLANCOND_WEP)
+ return "WEP";
+ else if (cap & WLANCOND_WPA_PSK)
+ return "WPA_PSK";
+ else if (cap & WLANCOND_WPA_EAP)
+ return "WPA_EAP";
+ return "";
+}
+
+QIcdEngine::QIcdEngine(QObject *parent)
+: QBearerEngine(parent), iapMonitor(new IapMonitor)
+{
+ /* Turn on IAP monitoring */
+ iapMonitor->setup(this);
+
+ doRequestUpdate();
+}
+
+QIcdEngine::~QIcdEngine()
+{
+}
+
+bool QIcdEngine::hasIdentifier(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ return accessPointConfigurations.contains(id) ||
+ snapConfigurations.contains(id) ||
+ userChoiceConfigurations.contains(id);
+}
+
+void QIcdEngine::requestUpdate()
+{
+ QMutexLocker locker(&mutex);
+
+ QTimer::singleShot(0, this, SLOT(doRequestUpdate()));
+}
+
+static uint32_t getNetworkAttrs(bool is_iap_id,
+ QString& iap_id,
+ QString& iap_type,
+ QString security_method)
+{
+ guint network_attr = 0;
+ dbus_uint32_t cap = 0;
+
+ if (iap_type == "WLAN_INFRA")
+ cap |= WLANCOND_INFRA;
+ else if (iap_type == "WLAN_ADHOC")
+ cap |= WLANCOND_ADHOC;
+
+ if (security_method.isEmpty() && (cap & (WLANCOND_INFRA | WLANCOND_ADHOC))) {
+ Maemo::IAPConf saved_ap(iap_id);
+ security_method = saved_ap.value("wlan_security").toString();
+ }
+
+ if (!security_method.isEmpty()) {
+ if (security_method == "WEP")
+ cap |= WLANCOND_WEP;
+ else if (security_method == "WPA_PSK")
+ cap |= WLANCOND_WPA_PSK;
+ else if (security_method == "WPA_EAP")
+ cap |= WLANCOND_WPA_EAP;
+ else if (security_method == "NONE")
+ cap |= WLANCOND_OPEN;
+
+ if (cap & (WLANCOND_WPA_PSK | WLANCOND_WPA_EAP)) {
+ Maemo::IAPConf saved_iap(iap_id);
+ bool wpa2_only = saved_iap.value("EAP_wpa2_only_mode").toBool();
+ if (wpa2_only) {
+ cap |= WLANCOND_WPA2;
+ }
+ }
+ }
+
+ cap2nwattr(cap, &network_attr);
+ if (is_iap_id)
+ network_attr |= ICD_NW_ATTR_IAPNAME;
+
+ return (uint32_t)network_attr;
+}
+
+void QIcdEngine::doRequestUpdate()
+{
+ QMutexLocker locker(&mutex);
+
+ QStringList previous = accessPointConfigurations.keys();
+
+ /* All the scanned access points */
+ QList<Maemo::IcdScanResult> scanned;
+
+ /* We create a default configuration which is a pseudo config */
+ if (!userChoiceConfigurations.contains(OSSO_IAP_ANY)) {
+ QNetworkConfigurationPrivatePointer ptr(new IcdNetworkConfigurationPrivate);
+
+ ptr->name = QLatin1String("UserChoice");
+ ptr->state = QNetworkConfiguration::Discovered;
+ ptr->isValid = true;
+ ptr->id = OSSO_IAP_ANY;
+ ptr->type = QNetworkConfiguration::UserChoice;
+ ptr->purpose = QNetworkConfiguration::UnknownPurpose;
+ ptr->roamingSupported = false;
+
+ userChoiceConfigurations.insert(ptr->id, ptr);
+ emit configurationAdded(ptr);
+ }
+
+ /* We return currently configured IAPs in the first run and do the WLAN
+ * scan in subsequent runs.
+ */
+ QList<QString> all_iaps;
+ Maemo::IAPConf::getAll(all_iaps);
+
+ foreach (QString escaped_iap_id, all_iaps) {
+ QByteArray ssid;
+
+ /* The key that is returned by getAll() needs to be unescaped */
+ gchar *unescaped_id = gconf_unescape_key(escaped_iap_id.toUtf8().data(), -1);
+ QString iap_id = QString((char *)unescaped_id);
+ g_free(unescaped_id);
+
+ previous.removeAll(iap_id);
+
+ Maemo::IAPConf saved_ap(iap_id);
+ bool is_temporary = saved_ap.value("temporary").toBool();
+ if (is_temporary) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "IAP" << iap_id << "is temporary, skipping it.";
+#endif
+ continue;
+ }
+
+ QString iap_type = saved_ap.value("type").toString();
+ if (iap_type.startsWith("WLAN")) {
+ ssid = saved_ap.value("wlan_ssid").toByteArray();
+ if (ssid.isEmpty()) {
+ qWarning() << "Cannot get ssid for" << iap_id;
+ continue;
+ }
+
+ QString security_method = saved_ap.value("wlan_security").toString();
+ } else if (iap_type.isEmpty()) {
+ qWarning() << "IAP" << iap_id << "network type is not set! Skipping it";
+ continue;
+ } else {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "IAP" << iap_id << "network type is" << iap_type;
+#endif
+ ssid.clear();
+ }
+
+ if (!accessPointConfigurations.contains(iap_id)) {
+ IcdNetworkConfigurationPrivate *cpPriv = new IcdNetworkConfigurationPrivate;
+
+ cpPriv->name = saved_ap.value("name").toString();
+ if (cpPriv->name.isEmpty())
+ if (!ssid.isEmpty() && ssid.size() > 0)
+ cpPriv->name = ssid.data();
+ else
+ cpPriv->name = iap_id;
+ cpPriv->isValid = true;
+ cpPriv->id = iap_id;
+ cpPriv->network_id = ssid;
+ cpPriv->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
+ cpPriv->iap_type = iap_type;
+ cpPriv->service_id = saved_ap.value("service_id").toString();
+ cpPriv->service_type = saved_ap.value("service_type").toString();
+ cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
+ cpPriv->state = QNetworkConfiguration::Defined;
+
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ accessPointConfigurations.insert(iap_id, ptr);
+ emit configurationAdded(ptr);
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug("IAP: %s, name: %s, ssid: %s, added to known list",
+ iap_id.toAscii().data(), ptr->name.toAscii().data(),
+ !ssid.isEmpty() ? ssid.data() : "-");
+#endif
+ } else {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug("IAP: %s, ssid: %s, already exists in the known list",
+ iap_id.toAscii().data(), !ssid.isEmpty() ? ssid.data() : "-");
+#endif
+ }
+ }
+
+ if (sender()) {
+ QStringList scannedNetworkTypes;
+ QStringList networkTypesToScan;
+ QString error;
+ Maemo::Icd icd(ICD_SHORT_SCAN_TIMEOUT);
+
+ scannedNetworkTypes = icd.scan(ICD_SCAN_REQUEST_ACTIVE,
+ networkTypesToScan,
+ scanned,
+ error);
+ if (!error.isEmpty()) {
+ qWarning() << "Network scanning failed" << error;
+ } else {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ if (!scanned.isEmpty())
+ qDebug() << "Scan returned" << scanned.size() << "networks";
+ else
+ qDebug() << "Scan returned nothing.";
+#endif
+ }
+ }
+
+ /* This is skipped in the first update as scanned size is zero */
+ if (!scanned.isEmpty()) {
+ for (int i=0; i<scanned.size(); ++i) {
+ const Maemo::IcdScanResult ap = scanned.at(i);
+
+ QByteArray scanned_ssid = ap.scan.network_id;
+
+ if (ap.scan.network_attrs & ICD_NW_ATTR_IAPNAME) {
+ /* The network_id is IAP id, so the IAP is a known one */
+ QString iapid = ap.scan.network_id.data();
+
+ previous.removeAll(iapid);
+
+ if (accessPointConfigurations.contains(iapid)) {
+ QNetworkConfigurationPrivatePointer ptr =
+ accessPointConfigurations.value(iapid);
+
+ bool changed = false;
+
+ if (!ptr->isValid) {
+ ptr->isValid = true;
+ changed = true;
+ }
+
+ if (ptr->state != QNetworkConfiguration::Discovered) {
+ ptr->state = QNetworkConfiguration::Discovered;
+ changed = true;
+ }
+
+ toIcdConfig(ptr)->network_attrs = ap.scan.network_attrs;
+ toIcdConfig(ptr)->service_id = ap.scan.service_id;
+ toIcdConfig(ptr)->service_type = ap.scan.service_type;
+ toIcdConfig(ptr)->service_attrs = ap.scan.service_attrs;
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug("IAP: %s, ssid: %s, discovered",
+ iapid.toAscii().data(), scanned_ssid.data());
+#endif
+
+ if (changed)
+ emit configurationChanged(ptr);
+
+ if (!ap.scan.network_type.startsWith("WLAN"))
+ continue; // not a wlan AP
+ }
+ } else {
+ IcdNetworkConfigurationPrivate *cpPriv = new IcdNetworkConfigurationPrivate;
+
+ QString hrs = scanned_ssid.data();
+
+ cpPriv->name = ap.network_name.isEmpty() ? hrs : ap.network_name;
+ cpPriv->isValid = true;
+ // Note: id is now ssid, it should be set to IAP id if the IAP is saved
+ cpPriv->id = scanned_ssid.data();
+ cpPriv->network_id = scanned_ssid;
+ cpPriv->iap_type = ap.scan.network_type;
+ if (cpPriv->iap_type.isEmpty())
+ cpPriv->iap_type = QLatin1String("WLAN");
+ cpPriv->network_attrs = ap.scan.network_attrs;
+ cpPriv->service_id = ap.scan.service_id;
+ cpPriv->service_type = ap.scan.service_type;
+ cpPriv->service_attrs = ap.scan.service_attrs;
+
+ cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
+ cpPriv->state = QNetworkConfiguration::Undefined;
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "IAP with network id" << cpPriv->id << "was found in the scan.";
+#endif
+
+ previous.removeAll(cpPriv->id);
+
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ accessPointConfigurations.insert(ptr->id, ptr);
+ emit configurationAdded(ptr);
+ }
+ }
+ }
+
+ while (!previous.isEmpty()) {
+ QNetworkConfigurationPrivatePointer ptr =
+ accessPointConfigurations.take(previous.takeFirst());
+
+ emit configurationRemoved(ptr);
+ }
+
+ if (sender())
+ emit updateCompleted();
+}
+
+void QIcdEngine::deleteConfiguration(const QString &iap_id)
+{
+ QMutexLocker locker(&mutex);
+
+ /* Called when IAPs are deleted in gconf, in this case we do not scan
+ * or read all the IAPs from gconf because it might take too much power
+ * (multiple applications would need to scan and read all IAPs from gconf)
+ */
+ if (accessPointConfigurations.contains(iap_id)) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(iap_id);
+
+ if (ptr) {
+ ptr->isValid = false;
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "IAP" << iap_id << "was removed from storage.";
+#endif
+
+ emit configurationRemoved(ptr);
+ } else {
+ qWarning("Configuration not found for IAP %s", iap_id.toAscii().data());
+ }
+ } else {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug("IAP: %s, already missing from the known list", iap_id.toAscii().data());
+#endif
+ }
+}
+
+QNetworkConfigurationManager::Capabilities QIcdEngine::capabilities() const
+{
+ return QNetworkConfigurationManager::CanStartAndStopInterfaces |
+ QNetworkConfigurationManager::DataStatistics |
+ QNetworkConfigurationManager::ForcedRoaming;
+}
+
+QNetworkSessionPrivate *QIcdEngine::createSessionBackend()
+{
+ return new QNetworkSessionPrivateImpl(this);
+}
+
+QNetworkConfigurationPrivatePointer QIcdEngine::defaultConfiguration()
+{
+ QMutexLocker locker(&mutex);
+
+ // Here we just return [ANY] request to icd and let the icd decide which IAP to connect.
+ return userChoiceConfigurations.value(OSSO_IAP_ANY);
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/icd/qicdengine.h b/src/plugins/bearer/icd/qicdengine.h
new file mode 100644
index 0000000..6ebe40d
--- /dev/null
+++ b/src/plugins/bearer/icd/qicdengine.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QICDENGINE_H
+#define QICDENGINE_H
+
+#include <QtNetwork/private/qbearerengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkConfigurationPrivate;
+class IapMonitor;
+
+class IcdNetworkConfigurationPrivate : public QNetworkConfigurationPrivate
+{
+public:
+ IcdNetworkConfigurationPrivate();
+ ~IcdNetworkConfigurationPrivate();
+
+ QString bearerName() const;
+
+ // In Maemo the id field (defined in QNetworkConfigurationPrivate)
+ // is the IAP id (which typically is UUID)
+ QByteArray network_id; // typically WLAN ssid or similar
+ QString iap_type; // is this one WLAN or GPRS
+
+ // Network attributes for this IAP, this is the value returned by icd and
+ // passed to it when connecting.
+ uint32_t network_attrs;
+
+ QString service_type;
+ QString service_id;
+ uint32_t service_attrs;
+};
+
+inline IcdNetworkConfigurationPrivate *toIcdConfig(QNetworkConfigurationPrivatePointer ptr)
+{
+ return static_cast<IcdNetworkConfigurationPrivate *>(ptr.data());
+}
+
+class QIcdEngine : public QBearerEngine
+{
+ Q_OBJECT
+
+public:
+ QIcdEngine(QObject *parent = 0);
+ ~QIcdEngine();
+
+ bool hasIdentifier(const QString &id);
+
+ void requestUpdate();
+
+ QNetworkConfigurationManager::Capabilities capabilities() const;
+
+ QNetworkSessionPrivate *createSessionBackend();
+
+ QNetworkConfigurationPrivatePointer defaultConfiguration();
+
+ void deleteConfiguration(const QString &iap_id);
+
+ inline QNetworkConfigurationPrivatePointer configuration(const QString &id)
+ {
+ QMutexLocker locker(&mutex);
+
+ return accessPointConfigurations.value(id);
+ }
+
+ inline void addSessionConfiguration(QNetworkConfigurationPrivatePointer ptr)
+ {
+ QMutexLocker locker(&mutex);
+
+ accessPointConfigurations.insert(ptr->id, ptr);
+ emit configurationAdded(ptr);
+ }
+
+ inline void changedSessionConfiguration(QNetworkConfigurationPrivatePointer ptr)
+ {
+ QMutexLocker locker(&mutex);
+
+ emit configurationChanged(ptr);
+ }
+
+private Q_SLOTS:
+ void doRequestUpdate();
+
+private:
+ IapMonitor *iapMonitor;
+};
+
+QT_END_NAMESPACE
+
+#endif // QICDENGINE_H
diff --git a/src/plugins/bearer/icd/qnetworksession_impl.cpp b/src/plugins/bearer/icd/qnetworksession_impl.cpp
new file mode 100644
index 0000000..a9e93e0
--- /dev/null
+++ b/src/plugins/bearer/icd/qnetworksession_impl.cpp
@@ -0,0 +1,1104 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnetworksession_impl.h"
+#include "qicdengine.h"
+
+#include <QHash>
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include <maemo_icd.h>
+#include <iapconf.h>
+
+#include <sys/types.h>
+#include <ifaddrs.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+QT_BEGIN_NAMESPACE
+
+static QHash<QString, QVariant> properties;
+
+static QString get_network_interface();
+static DBusConnection *dbus_connection;
+static DBusHandlerResult signal_handler(DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data);
+
+#define ICD_DBUS_MATCH "type='signal'," \
+ "interface='" ICD_DBUS_INTERFACE "'," \
+ "path='" ICD_DBUS_PATH "'"
+
+
+static inline DBusConnection *get_dbus_conn(DBusError *error)
+{
+ DBusConnection *conn = dbus_bus_get(DBUS_BUS_SYSTEM, error);
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "Listening to bus" << dbus_bus_get_unique_name(conn);
+#endif
+
+ return conn;
+}
+
+
+/* Helper class that monitors the Icd status messages and
+ * can change the IAP status accordingly. This is a singleton.
+ */
+class IcdListener : public QObject
+{
+ Q_OBJECT
+
+public:
+ IcdListener() : first_call(true) { }
+ friend DBusHandlerResult signal_handler(DBusConnection *connection,
+ DBusMessage *message,
+ void *user_data);
+ void setup(QNetworkSessionPrivateImpl *d);
+ void cleanup();
+ void cleanupSession(QNetworkSessionPrivateImpl *ptr);
+
+ enum IapConnectionStatus {
+ /* The IAP was connected */
+ CONNECTED = 0,
+ /* The IAP was disconnected */
+ DISCONNECTED,
+ /* The IAP is disconnecting */
+ DISCONNECTING,
+ /* The IAP has a network address, but is not yet fully connected */
+ NETWORK_UP
+ };
+
+private:
+ void icdSignalReceived(QString&, QString&, QString&);
+ bool first_call;
+ QHash<QString, QNetworkSessionPrivateImpl *> sessions;
+};
+
+Q_GLOBAL_STATIC(IcdListener, icdListener);
+
+
+static DBusHandlerResult signal_handler(DBusConnection *,
+ DBusMessage *message,
+ void *user_data)
+{
+ if (dbus_message_is_signal(message,
+ ICD_DBUS_INTERFACE,
+ ICD_STATUS_CHANGED_SIG)) {
+
+ IcdListener *icd = (IcdListener *)user_data;
+ DBusError error;
+ dbus_error_init(&error);
+
+ char *iap_id = 0;
+ char *network_type = 0;
+ char *state = 0;
+
+ if (dbus_message_get_args(message, &error,
+ DBUS_TYPE_STRING, &iap_id,
+ DBUS_TYPE_STRING, &network_type,
+ DBUS_TYPE_STRING, &state,
+ DBUS_TYPE_INVALID) == FALSE) {
+ qWarning() << QString("Failed to parse icd status signal: %1").arg(error.message);
+ } else {
+ QString _iap_id(iap_id);
+ QString _network_type(network_type);
+ QString _state(state);
+
+ icd->icdSignalReceived(_iap_id, _network_type, _state);
+ }
+
+ dbus_error_free(&error);
+ return DBUS_HANDLER_RESULT_HANDLED;
+ }
+
+ return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+
+void IcdListener::setup(QNetworkSessionPrivateImpl *d)
+{
+ if (first_call) {
+ // We use the old Icd dbus interface like in ConIC
+ DBusError error;
+ dbus_error_init(&error);
+
+ dbus_connection = get_dbus_conn(&error);
+ if (dbus_error_is_set(&error)) {
+ qWarning() << "Cannot get dbus connection.";
+ dbus_error_free(&error);
+ return;
+ }
+
+ static struct DBusObjectPathVTable icd_vtable;
+ icd_vtable.message_function = signal_handler;
+
+ dbus_bus_add_match(dbus_connection, ICD_DBUS_MATCH, &error);
+ if (dbus_error_is_set(&error)) {
+ qWarning() << "Cannot add match" << ICD_DBUS_MATCH;
+ dbus_error_free(&error);
+ return;
+ }
+
+ if (dbus_connection_register_object_path(dbus_connection,
+ ICD_DBUS_PATH,
+ &icd_vtable,
+ (void*)this) == FALSE) {
+ qWarning() << "Cannot register dbus signal handler, interface"<< ICD_DBUS_INTERFACE << "path" << ICD_DBUS_PATH;
+ dbus_error_free(&error);
+ return;
+ }
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "Listening" << ICD_STATUS_CHANGED_SIG << "signal from" << ICD_DBUS_SERVICE;
+#endif
+ first_call = false;
+ dbus_error_free(&error);
+ }
+
+ QString id = d->activeConfig.identifier();
+ if (!sessions.contains(id)) {
+ QNetworkSessionPrivateImpl *ptr = d;
+ sessions.insert(id, ptr);
+ }
+}
+
+
+void IcdListener::icdSignalReceived(QString& iap_id,
+#ifdef BEARER_MANAGEMENT_DEBUG
+ QString& network_type,
+#else
+ QString&,
+#endif
+ QString& state)
+{
+ if (iap_id == OSSO_IAP_SCAN) // icd sends scan status signals which we will ignore
+ return;
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "Status received:" << iap_id << "type" << network_type << "state" << state;
+#endif
+
+ if (!sessions.contains(iap_id)) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "No session for IAP" << iap_id;
+#endif
+ return;
+ }
+
+ QNetworkSessionPrivateImpl *session = sessions.value(iap_id);
+ QNetworkConfiguration ap_conf =
+ QNetworkConfigurationManager().configurationFromIdentifier(iap_id);
+ if (!ap_conf.isValid()) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "Unknown IAP" << iap_id;
+#endif
+ return;
+ }
+
+ IapConnectionStatus status;
+
+ if (state == "IDLE") {
+ status = DISCONNECTED;
+ } else if (state == "CONNECTED") {
+ status = CONNECTED;
+ } else if (state == "NETWORKUP") {
+ status = NETWORK_UP;
+ } else {
+ //qDebug() << "Unknown state" << state;
+ return;
+ }
+
+ if (status == DISCONNECTED) {
+ if (ap_conf.state() == QNetworkConfiguration::Active) {
+ /* The IAP was just disconnected by Icd */
+ session->updateState(QNetworkSession::Disconnected);
+ } else {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "Got a network disconnect when in state" << ap_conf.state();
+#endif
+ }
+ } else if (status == CONNECTED) {
+ /* The IAP was just connected by Icd */
+ session->updateState(QNetworkSession::Connected);
+ session->updateIdentifier(iap_id);
+
+ if (session->publicConfig.identifier() == OSSO_IAP_ANY) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "IAP" << iap_id << "connected when connecting to" << OSSO_IAP_ANY;
+#endif
+ } else {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "IAP" << iap_id << "connected";
+#endif
+ }
+ }
+
+ return;
+}
+
+
+void IcdListener::cleanup()
+{
+ if (!first_call) {
+ dbus_bus_remove_match(dbus_connection, ICD_DBUS_MATCH, NULL);
+ dbus_connection_unref(dbus_connection);
+ }
+}
+
+
+void IcdListener::cleanupSession(QNetworkSessionPrivateImpl *ptr)
+{
+ if (ptr->publicConfig.type() == QNetworkConfiguration::UserChoice)
+ (void)sessions.take(ptr->activeConfig.identifier());
+ else
+ (void)sessions.take(ptr->publicConfig.identifier());
+}
+
+
+void QNetworkSessionPrivateImpl::cleanupSession(void)
+{
+ icdListener()->cleanupSession(this);
+}
+
+
+void QNetworkSessionPrivateImpl::updateState(QNetworkSession::State newState)
+{
+ if (newState == state)
+ return;
+
+ state = newState;
+
+ if (state == QNetworkSession::Disconnected) {
+ isOpen = false;
+ currentNetworkInterface.clear();
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice)
+ privateConfiguration(activeConfig)->state = QNetworkConfiguration::Defined;
+ privateConfiguration(publicConfig)->state = QNetworkConfiguration::Defined;
+
+ } else if (state == QNetworkSession::Connected) {
+ isOpen = true;
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ privateConfiguration(activeConfig)->state = QNetworkConfiguration::Active;
+ privateConfiguration(activeConfig)->type = QNetworkConfiguration::InternetAccessPoint;
+ }
+ privateConfiguration(publicConfig)->state = QNetworkConfiguration::Active;
+ }
+
+ emit stateChanged(newState);
+}
+
+
+void QNetworkSessionPrivateImpl::updateIdentifier(QString &newId)
+{
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ toIcdConfig(privateConfiguration(activeConfig))->network_attrs |= ICD_NW_ATTR_IAPNAME;
+ privateConfiguration(activeConfig)->id = newId;
+ } else {
+ toIcdConfig(privateConfiguration(publicConfig))->network_attrs |= ICD_NW_ATTR_IAPNAME;
+ if (privateConfiguration(publicConfig)->id != newId) {
+ qWarning() << "Your config id changed from" << privateConfiguration(publicConfig)->id
+ << "to" << newId;
+ privateConfiguration(publicConfig)->id = newId;
+ }
+ }
+}
+
+
+quint64 QNetworkSessionPrivateImpl::getStatistics(bool sent) const
+{
+ /* This could be also implemented by using the Maemo::Icd::statistics()
+ * that gets the statistics data for a specific IAP. Change if
+ * necessary.
+ */
+ Maemo::Icd icd;
+ QList<Maemo::IcdStatisticsResult> stats_results;
+ quint64 counter_rx = 0, counter_tx = 0;
+
+ if (!icd.statistics(stats_results)) {
+ return 0;
+ }
+
+ foreach (Maemo::IcdStatisticsResult res, stats_results) {
+ if (res.params.network_attrs & ICD_NW_ATTR_IAPNAME) {
+ /* network_id is the IAP UUID */
+ if (QString(res.params.network_id.data()) == activeConfig.identifier()) {
+ counter_tx = res.bytes_sent;
+ counter_rx = res.bytes_received;
+ }
+ } else {
+ /* We probably will never get to this branch */
+ if (res.params.network_id == toIcdConfig(privateConfiguration(activeConfig))->network_id) {
+ counter_tx = res.bytes_sent;
+ counter_rx = res.bytes_received;
+ }
+ }
+ }
+
+ if (sent)
+ return counter_tx;
+ else
+ return counter_rx;
+}
+
+
+quint64 QNetworkSessionPrivateImpl::bytesWritten() const
+{
+ return getStatistics(true);
+}
+
+quint64 QNetworkSessionPrivateImpl::bytesReceived() const
+{
+ return getStatistics(false);
+}
+
+quint64 QNetworkSessionPrivateImpl::activeTime() const
+{
+ if (startTime.isNull()) {
+ return 0;
+ }
+ return startTime.secsTo(QDateTime::currentDateTime());
+}
+
+
+QNetworkConfiguration& QNetworkSessionPrivateImpl::copyConfig(QNetworkConfiguration &fromConfig,
+ QNetworkConfiguration &toConfig,
+ bool deepCopy)
+{
+ IcdNetworkConfigurationPrivate *cpPriv;
+ if (deepCopy) {
+ cpPriv = new IcdNetworkConfigurationPrivate;
+ setPrivateConfiguration(toConfig, QNetworkConfigurationPrivatePointer(cpPriv));
+ } else {
+ cpPriv = toIcdConfig(privateConfiguration(toConfig));
+ }
+
+ cpPriv->name = privateConfiguration(fromConfig)->name;
+ cpPriv->isValid = privateConfiguration(fromConfig)->isValid;
+ // Note that we do not copy id field here as the publicConfig does
+ // not contain a valid IAP id.
+ cpPriv->state = privateConfiguration(fromConfig)->state;
+ cpPriv->type = privateConfiguration(fromConfig)->type;
+ cpPriv->roamingSupported = privateConfiguration(fromConfig)->roamingSupported;
+ cpPriv->purpose = privateConfiguration(fromConfig)->purpose;
+ cpPriv->network_id = toIcdConfig(privateConfiguration(fromConfig))->network_id;
+ cpPriv->iap_type = toIcdConfig(privateConfiguration(fromConfig))->iap_type;
+ cpPriv->network_attrs = toIcdConfig(privateConfiguration(fromConfig))->network_attrs;
+ cpPriv->service_type = toIcdConfig(privateConfiguration(fromConfig))->service_type;
+ cpPriv->service_id = toIcdConfig(privateConfiguration(fromConfig))->service_id;
+ cpPriv->service_attrs = toIcdConfig(privateConfiguration(fromConfig))->service_attrs;
+
+ return toConfig;
+}
+
+
+/* This is called by QNetworkSession constructor and it updates the current
+ * state of the configuration.
+ */
+void QNetworkSessionPrivateImpl::syncStateWithInterface()
+{
+ /* Start to listen Icd status messages. */
+ icdListener()->setup(this);
+
+ /* Initially we are not active although the configuration might be in
+ * connected state.
+ */
+ isOpen = false;
+ opened = false;
+
+ connect(&manager, SIGNAL(updateCompleted()), this, SLOT(networkConfigurationsChanged()));
+
+ connect(&manager, SIGNAL(configurationChanged(QNetworkConfiguration)),
+ this, SLOT(configurationChanged(QNetworkConfiguration)));
+
+ state = QNetworkSession::Invalid;
+ lastError = QNetworkSession::UnknownSessionError;
+
+ switch (publicConfig.type()) {
+ case QNetworkConfiguration::InternetAccessPoint:
+ activeConfig = publicConfig;
+ break;
+ case QNetworkConfiguration::ServiceNetwork:
+ serviceConfig = publicConfig;
+ break;
+ case QNetworkConfiguration::UserChoice:
+ // active config will contain correct data after open() has succeeded
+ copyConfig(publicConfig, activeConfig);
+
+ /* We create new configuration that holds the actual configuration
+ * returned by icd. This way publicConfig still contains the
+ * original user specified configuration.
+ *
+ * Note that the new activeConfig configuration is not inserted
+ * to configurationManager as manager class will get the newly
+ * connected configuration from gconf when the IAP is saved.
+ * This configuration manager update is done by IapMonitor class.
+ * If the ANY connection fails in open(), then the configuration
+ * data is not saved to gconf and will not be added to
+ * configuration manager IAP list.
+ */
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug()<<"New configuration created for" << publicConfig.identifier();
+#endif
+ break;
+ default:
+ /* Invalid configuration, no point continuing */
+ return;
+ }
+
+ if (!activeConfig.isValid())
+ return;
+
+ /* Get the initial state from icd */
+ Maemo::Icd icd;
+ QList<Maemo::IcdStateResult> state_results;
+
+ /* Update the active config from first connection, this is ok as icd
+ * supports only one connection anyway.
+ */
+ if (icd.state(state_results) && !state_results.isEmpty()) {
+
+ /* If we did not get full state back, then we are not
+ * connected and can skip the next part.
+ */
+ if (!(state_results.first().params.network_attrs == 0 &&
+ state_results.first().params.network_id.isEmpty())) {
+
+ /* If we try to connect to specific IAP and we get results back
+ * that tell the icd is actually connected to another IAP,
+ * then do not update current state etc.
+ */
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice ||
+ privateConfiguration(publicConfig)->id == state_results.first().params.network_id) {
+
+ switch (state_results.first().state) {
+ case ICD_STATE_DISCONNECTED:
+ state = QNetworkSession::Disconnected;
+ if (privateConfiguration(activeConfig))
+ privateConfiguration(activeConfig)->isValid = true;
+ break;
+ case ICD_STATE_CONNECTING:
+ state = QNetworkSession::Connecting;
+ if (privateConfiguration(activeConfig))
+ privateConfiguration(activeConfig)->isValid = true;
+ break;
+ case ICD_STATE_CONNECTED:
+ {
+ if (!state_results.first().error.isEmpty())
+ break;
+
+ const QString id = state_results.first().params.network_id;
+
+ QNetworkConfiguration config = manager.configurationFromIdentifier(id);
+ if (config.isValid()) {
+ //we don't want the copied data if the config is already known by the manager
+ //just reuse it so that existing references to the old data get the same update
+ setPrivateConfiguration(activeConfig, privateConfiguration(config));
+ }
+
+ QNetworkConfigurationPrivatePointer ptr = privateConfiguration(activeConfig);
+
+ state = QNetworkSession::Connected;
+ toIcdConfig(ptr)->network_id = state_results.first().params.network_id;
+ ptr->id = toIcdConfig(ptr)->network_id;
+ toIcdConfig(ptr)->network_attrs = state_results.first().params.network_attrs;
+ toIcdConfig(ptr)->iap_type = state_results.first().params.network_type;
+ toIcdConfig(ptr)->service_type = state_results.first().params.service_type;
+ toIcdConfig(ptr)->service_id = state_results.first().params.service_id;
+ toIcdConfig(ptr)->service_attrs = state_results.first().params.service_attrs;
+ ptr->type = QNetworkConfiguration::InternetAccessPoint;
+ ptr->state = QNetworkConfiguration::Active;
+ ptr->isValid = true;
+ currentNetworkInterface = get_network_interface();
+
+ Maemo::IAPConf iap_name(privateConfiguration(activeConfig)->id);
+ QString name_value = iap_name.value("name").toString();
+ if (!name_value.isEmpty())
+ privateConfiguration(activeConfig)->name = name_value;
+ else
+ privateConfiguration(activeConfig)->name = privateConfiguration(activeConfig)->id;
+
+
+ // Add the new active configuration to manager or update the old config
+ if (!engine->hasIdentifier(privateConfiguration(activeConfig)->id))
+ engine->addSessionConfiguration(privateConfiguration(activeConfig));
+ else
+ engine->changedSessionConfiguration(privateConfiguration(activeConfig));
+ }
+ break;
+
+ case ICD_STATE_DISCONNECTING:
+ state = QNetworkSession::Closing;
+ if (privateConfiguration(activeConfig))
+ privateConfiguration(activeConfig)->isValid = true;
+ break;
+ default:
+ break;
+ }
+ }
+ } else {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "status_req tells icd is not connected";
+#endif
+ }
+ } else {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "status_req did not return any results from icd";
+#endif
+ }
+
+ networkConfigurationsChanged();
+}
+
+
+void QNetworkSessionPrivateImpl::networkConfigurationsChanged()
+{
+ if (serviceConfig.isValid())
+ updateStateFromServiceNetwork();
+ else
+ updateStateFromActiveConfig();
+}
+
+
+void QNetworkSessionPrivateImpl::updateStateFromServiceNetwork()
+{
+ QNetworkSession::State oldState = state;
+
+ foreach (const QNetworkConfiguration &config, serviceConfig.children()) {
+ if ((config.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active)
+ continue;
+
+ if (activeConfig != config) {
+ activeConfig = config;
+ emit newConfigurationActivated();
+ }
+
+ state = QNetworkSession::Connected;
+ if (state != oldState)
+ emit stateChanged(state);
+
+ return;
+ }
+
+ if (serviceConfig.children().isEmpty())
+ state = QNetworkSession::NotAvailable;
+ else
+ state = QNetworkSession::Disconnected;
+
+ if (state != oldState)
+ emit stateChanged(state);
+}
+
+
+void QNetworkSessionPrivateImpl::clearConfiguration(QNetworkConfiguration &config)
+{
+ toIcdConfig(privateConfiguration(config))->network_id.clear();
+ toIcdConfig(privateConfiguration(config))->iap_type.clear();
+ toIcdConfig(privateConfiguration(config))->network_attrs = 0;
+ toIcdConfig(privateConfiguration(config))->service_type.clear();
+ toIcdConfig(privateConfiguration(config))->service_id.clear();
+ toIcdConfig(privateConfiguration(config))->service_attrs = 0;
+}
+
+
+void QNetworkSessionPrivateImpl::updateStateFromActiveConfig()
+{
+ QNetworkSession::State oldState = state;
+
+ bool newActive = false;
+
+ if (!privateConfiguration(activeConfig))
+ return;
+
+ if (!activeConfig.isValid()) {
+ state = QNetworkSession::Invalid;
+ clearConfiguration(activeConfig);
+ } else if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ state = QNetworkSession::Connected;
+ newActive = opened;
+ } else if ((activeConfig.state() & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) {
+ state = QNetworkSession::Disconnected;
+ } else if ((activeConfig.state() & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
+ state = QNetworkSession::NotAvailable;
+ } else if ((activeConfig.state() & QNetworkConfiguration::Undefined) == QNetworkConfiguration::Undefined) {
+ state = QNetworkSession::NotAvailable;
+ //clearConfiguration(activeConfig);
+ }
+
+ bool oldActive = isOpen;
+ isOpen = newActive;
+
+ if (!oldActive && isOpen)
+ emit quitPendingWaitsForOpened();
+
+ if (oldActive && !isOpen)
+ emit closed();
+
+ if (oldState != state) {
+ emit stateChanged(state);
+
+ if (state == QNetworkSession::Disconnected) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ //qDebug()<<"session aborted error emitted for"<<activeConfig.identifier();
+#endif
+ lastError = QNetworkSession::SessionAbortedError;
+ emit QNetworkSessionPrivate::error(lastError);
+ }
+ }
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ //qDebug()<<"oldState ="<<oldState<<" state ="<<state<<" oldActive ="<<oldActive<<" newActive ="<<newActive<<" opened ="<<opened;
+#endif
+}
+
+
+void QNetworkSessionPrivateImpl::configurationChanged(const QNetworkConfiguration &config)
+{
+ if (serviceConfig.isValid() && (config == serviceConfig || config == activeConfig))
+ updateStateFromServiceNetwork();
+ else if (config == activeConfig)
+ updateStateFromActiveConfig();
+}
+
+
+static QString get_network_interface()
+{
+ Maemo::Icd icd;
+ QList<Maemo::IcdAddressInfoResult> addr_results;
+ uint ret;
+ QString iface;
+
+ ret = icd.addrinfo(addr_results);
+ if (ret == 0) {
+ /* No results */
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "Cannot get addrinfo from icd, are you connected or is icd running?";
+#endif
+ return iface;
+ }
+
+ const char *address = addr_results.first().ip_info.first().address.toAscii().constData();
+ struct in_addr addr;
+ if (inet_aton(address, &addr) == 0) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "address" << address << "invalid";
+#endif
+ return iface;
+ }
+
+ struct ifaddrs *ifaddr, *ifa;
+ int family;
+
+ if (getifaddrs(&ifaddr) == -1) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "getifaddrs() failed";
+#endif
+ return iface;
+ }
+
+ for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
+ family = ifa->ifa_addr->sa_family;
+ if (family != AF_INET) {
+ continue; /* Currently only IPv4 is supported by icd dbus interface */
+ }
+ if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == addr.s_addr) {
+ iface = QString(ifa->ifa_name);
+ break;
+ }
+ }
+
+ freeifaddrs(ifaddr);
+ return iface;
+}
+
+
+void QNetworkSessionPrivateImpl::open()
+{
+ if (serviceConfig.isValid()) {
+ lastError = QNetworkSession::OperationNotSupportedError;
+ emit QNetworkSessionPrivate::error(lastError);
+ } else if (!isOpen) {
+
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ /* Caller is trying to connect to default IAP.
+ * At this time we will not know the IAP details so we just
+ * connect and update the active config when the IAP is
+ * connected.
+ */
+ opened = true;
+ state = QNetworkSession::Connecting;
+ emit stateChanged(state);
+ QTimer::singleShot(0, this, SLOT(do_open()));
+ return;
+ }
+
+ /* User is connecting to one specific IAP. If that IAP is not
+ * in discovered state we cannot continue.
+ */
+ if ((activeConfig.state() & QNetworkConfiguration::Discovered) !=
+ QNetworkConfiguration::Discovered) {
+ lastError =QNetworkSession::InvalidConfigurationError;
+ emit QNetworkSessionPrivate::error(lastError);
+ return;
+ }
+ opened = true;
+
+ if ((activeConfig.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active) {
+ state = QNetworkSession::Connecting;
+ emit stateChanged(state);
+
+ QTimer::singleShot(0, this, SLOT(do_open()));
+ return;
+ }
+
+ isOpen = (activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active;
+ if (isOpen)
+ emit quitPendingWaitsForOpened();
+ } else {
+ /* We seem to be active so inform caller */
+ emit quitPendingWaitsForOpened();
+ }
+}
+
+
+void QNetworkSessionPrivateImpl::do_open()
+{
+ icd_connection_flags flags = connectFlags;
+ bool st;
+ QString result;
+ QString iap = publicConfig.identifier();
+
+ if (state == QNetworkSession::Connected) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "Already connected to" << activeConfig.identifier();
+#endif
+ emit stateChanged(QNetworkSession::Connected);
+ emit quitPendingWaitsForOpened();
+ return;
+ }
+
+ Maemo::IcdConnectResult connect_result;
+ Maemo::Icd icd(ICD_LONG_CONNECT_TIMEOUT);
+ QNetworkConfiguration config;
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice)
+ config = activeConfig;
+ else
+ config = publicConfig;
+
+ if (iap == OSSO_IAP_ANY) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "connecting to default IAP" << iap;
+#endif
+ st = icd.connect(flags, connect_result);
+
+ } else {
+
+ QList<Maemo::ConnectParams> params;
+ Maemo::ConnectParams param;
+ param.connect.service_type = toIcdConfig(privateConfiguration(config))->service_type;
+ param.connect.service_attrs = toIcdConfig(privateConfiguration(config))->service_attrs;
+ param.connect.service_id = toIcdConfig(privateConfiguration(config))->service_id;
+ param.connect.network_type = toIcdConfig(privateConfiguration(config))->iap_type;
+ param.connect.network_attrs = toIcdConfig(privateConfiguration(config))->network_attrs;
+ if (toIcdConfig(privateConfiguration(config))->network_attrs & ICD_NW_ATTR_IAPNAME)
+ param.connect.network_id = QByteArray(iap.toLatin1());
+ else
+ param.connect.network_id = toIcdConfig(privateConfiguration(config))->network_id;
+ params.append(param);
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug("connecting to %s/%s/0x%x/%s/0x%x/%s",
+ param.connect.network_id.data(),
+ param.connect.network_type.toAscii().constData(),
+ param.connect.network_attrs,
+ param.connect.service_type.toAscii().constData(),
+ param.connect.service_attrs,
+ param.connect.service_id.toAscii().constData());
+#endif
+ st = icd.connect(flags, params, connect_result);
+ }
+
+ if (st) {
+ result = connect_result.connect.network_id.data();
+ QString connected_iap = result;
+
+ if (connected_iap.isEmpty()) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "connect to"<< iap << "failed, result is empty";
+#endif
+ updateState(QNetworkSession::Disconnected);
+ emit quitPendingWaitsForOpened();
+ emit QNetworkSessionPrivate::error(QNetworkSession::InvalidConfigurationError);
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice)
+ cleanupAnyConfiguration();
+ return;
+ }
+
+ /* If the user tried to connect to some specific connection (foo)
+ * and we were already connected to some other connection (bar),
+ * then we cannot activate this session although icd has a valid
+ * connection to somewhere.
+ */
+ if ((publicConfig.type() != QNetworkConfiguration::UserChoice) &&
+ (connected_iap != config.identifier())) {
+ updateState(QNetworkSession::Disconnected);
+ emit quitPendingWaitsForOpened();
+ emit QNetworkSessionPrivate::error(QNetworkSession::InvalidConfigurationError);
+ return;
+ }
+
+
+ /* Did we connect to non saved IAP? */
+ if (!(toIcdConfig(privateConfiguration(config))->network_attrs & ICD_NW_ATTR_IAPNAME)) {
+ /* Because the connection succeeded, the IAP is now known.
+ */
+ toIcdConfig(privateConfiguration(config))->network_attrs |= ICD_NW_ATTR_IAPNAME;
+ privateConfiguration(config)->id = connected_iap;
+ }
+
+ /* User might have changed the IAP name when a new IAP was saved */
+ Maemo::IAPConf iap_name(privateConfiguration(config)->id);
+ QString name = iap_name.value("name").toString();
+ if (!name.isEmpty())
+ privateConfiguration(config)->name = name;
+
+ toIcdConfig(privateConfiguration(config))->iap_type = connect_result.connect.network_type;
+
+ privateConfiguration(config)->isValid = true;
+ privateConfiguration(config)->state = QNetworkConfiguration::Active;
+ privateConfiguration(config)->type = QNetworkConfiguration::InternetAccessPoint;
+
+ startTime = QDateTime::currentDateTime();
+ updateState(QNetworkSession::Connected);
+
+ currentNetworkInterface = get_network_interface();
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "connected to" << result << config.name() << "at" << currentNetworkInterface;
+#endif
+
+ /* We first check if the configuration already exists in the manager
+ * and if it is not found there, we then insert it. Note that this
+ * is only done for user choice config only because it can be missing
+ * from config manager list.
+ */
+
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ if (!engine->hasIdentifier(result)) {
+ engine->addSessionConfiguration(privateConfiguration(config));
+ } else {
+ QNetworkConfigurationPrivatePointer priv = engine->configuration(result);
+ QNetworkConfiguration reference;
+ setPrivateConfiguration(reference, priv);
+ copyConfig(config, reference, false);
+ config = reference;
+ activeConfig = reference;
+ engine->changedSessionConfiguration(privateConfiguration(config));
+ }
+ }
+
+ emit quitPendingWaitsForOpened();
+
+ } else {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "connect to"<< iap << "failed, status:" << connect_result.status;
+#endif
+ updateState(QNetworkSession::Disconnected);
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice)
+ cleanupAnyConfiguration();
+ emit quitPendingWaitsForOpened();
+ emit QNetworkSessionPrivate::error(QNetworkSession::UnknownSessionError);
+ }
+}
+
+
+void QNetworkSessionPrivateImpl::cleanupAnyConfiguration()
+{
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug()<<"Removing configuration created for" << activeConfig.identifier();
+#endif
+ activeConfig = publicConfig;
+}
+
+
+void QNetworkSessionPrivateImpl::close()
+{
+ if (serviceConfig.isValid()) {
+ lastError = QNetworkSession::OperationNotSupportedError;
+ emit QNetworkSessionPrivate::error(lastError);
+ } else if (isOpen) {
+ opened = false;
+ isOpen = false;
+ emit closed();
+ }
+}
+
+
+void QNetworkSessionPrivateImpl::stop()
+{
+ if (serviceConfig.isValid()) {
+ lastError = QNetworkSession::OperationNotSupportedError;
+ emit QNetworkSessionPrivate::error(lastError);
+ } else {
+ if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ state = QNetworkSession::Closing;
+ emit stateChanged(state);
+
+ Maemo::Icd icd;
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "stopping session" << publicConfig.identifier();
+#endif
+ icd.disconnect(ICD_CONNECTION_FLAG_APPLICATION_EVENT);
+ startTime = QDateTime();
+
+ /* Note that the state will go disconnected in
+ * updateStateFromActiveConfig() which gets called after
+ * configurationChanged is emitted (below).
+ */
+
+ privateConfiguration(activeConfig)->state = QNetworkConfiguration::Discovered;
+ engine->changedSessionConfiguration(privateConfiguration(activeConfig));
+
+ opened = false;
+ isOpen = false;
+
+ } else {
+ opened = false;
+ isOpen = false;
+ emit closed();
+ }
+ }
+}
+
+
+void QNetworkSessionPrivateImpl::migrate()
+{
+ qWarning("This platform does not support roaming (%s).", __FUNCTION__);
+}
+
+
+void QNetworkSessionPrivateImpl::accept()
+{
+ qWarning("This platform does not support roaming (%s).", __FUNCTION__);
+}
+
+
+void QNetworkSessionPrivateImpl::ignore()
+{
+ qWarning("This platform does not support roaming (%s).", __FUNCTION__);
+}
+
+
+void QNetworkSessionPrivateImpl::reject()
+{
+ qWarning("This platform does not support roaming (%s).", __FUNCTION__);
+}
+
+
+QNetworkInterface QNetworkSessionPrivateImpl::currentInterface() const
+{
+ if (!publicConfig.isValid() || state != QNetworkSession::Connected)
+ return QNetworkInterface();
+
+ if (currentNetworkInterface.isEmpty())
+ return QNetworkInterface();
+
+ return QNetworkInterface::interfaceFromName(currentNetworkInterface);
+}
+
+
+void QNetworkSessionPrivateImpl::setSessionProperty(const QString& key, const QVariant& value)
+{
+ if (value.isValid()) {
+ properties.insert(key, value);
+
+ if (key == "ConnectInBackground") {
+ bool v = value.toBool();
+ if (v)
+ connectFlags = ICD_CONNECTION_FLAG_APPLICATION_EVENT;
+ else
+ connectFlags = ICD_CONNECTION_FLAG_USER_EVENT;
+ }
+ } else {
+ properties.remove(key);
+
+ /* Set default value when property is removed */
+ if (key == "ConnectInBackground")
+ connectFlags = ICD_CONNECTION_FLAG_USER_EVENT;
+ }
+}
+
+
+QVariant QNetworkSessionPrivateImpl::sessionProperty(const QString& key) const
+{
+ return properties.value(key);
+}
+
+
+QString QNetworkSessionPrivateImpl::errorString() const
+{
+ QString errorStr;
+ switch(q->error()) {
+ case QNetworkSession::RoamingError:
+ errorStr = QObject::tr("Roaming error");
+ break;
+ case QNetworkSession::SessionAbortedError:
+ errorStr = QObject::tr("Session aborted by user or system");
+ break;
+ default:
+ case QNetworkSession::UnknownSessionError:
+ errorStr = QObject::tr("Unidentified Error");
+ break;
+ }
+ return errorStr;
+}
+
+
+QNetworkSession::SessionError QNetworkSessionPrivateImpl::error() const
+{
+ return QNetworkSession::UnknownSessionError;
+}
+
+#include "qnetworksession_impl.moc"
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/icd/qnetworksession_impl.h b/src/plugins/bearer/icd/qnetworksession_impl.h
new file mode 100644
index 0000000..b7461dc
--- /dev/null
+++ b/src/plugins/bearer/icd/qnetworksession_impl.h
@@ -0,0 +1,147 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNETWORKSESSION_IMPL_H
+#define QNETWORKSESSION_IMPL_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtNetwork/private/qnetworksession_p.h>
+#include <QtNetwork/qnetworkconfigmanager.h>
+
+//#include "qnetworkconfigmanager_maemo_p.h"
+//#include "qnetworksession.h"
+
+//#include <qnetworksession.h>
+//#include <QNetworkInterface>
+#include <QtCore/qdatetime.h>
+
+#include <icd/dbus_api.h>
+
+QT_BEGIN_NAMESPACE
+
+class QIcdEngine;
+
+class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate
+{
+ Q_OBJECT
+
+public:
+ QNetworkSessionPrivateImpl(QIcdEngine *engine)
+ : engine(engine), connectFlags(ICD_CONNECTION_FLAG_USER_EVENT)
+ {
+ }
+
+ ~QNetworkSessionPrivateImpl()
+ {
+ cleanupSession();
+ }
+
+ //called by QNetworkSession constructor and ensures
+ //that the state is immediately updated (w/o actually opening
+ //a session). Also this function should take care of
+ //notification hooks to discover future state changes.
+ void syncStateWithInterface();
+
+ QNetworkInterface currentInterface() const;
+ QVariant sessionProperty(const QString& key) const;
+ void setSessionProperty(const QString& key, const QVariant& value);
+
+ void open();
+ void close();
+ void stop();
+
+ void migrate();
+ void accept();
+ void ignore();
+ void reject();
+
+ QString errorString() const; //must return translated string
+ QNetworkSession::SessionError error() const;
+
+ quint64 bytesWritten() const;
+ quint64 bytesReceived() const;
+ quint64 activeTime() const;
+
+private:
+ void updateStateFromServiceNetwork();
+ void updateStateFromActiveConfig();
+
+private Q_SLOTS:
+ void do_open();
+ void networkConfigurationsChanged();
+ void configurationChanged(const QNetworkConfiguration &config);
+
+private:
+ QNetworkConfigurationManager manager;
+ QIcdEngine *engine;
+
+ QNetworkConfiguration& copyConfig(QNetworkConfiguration &fromConfig, QNetworkConfiguration &toConfig, bool deepCopy = true);
+ void clearConfiguration(QNetworkConfiguration &config);
+ void cleanupAnyConfiguration();
+
+ bool opened;
+ icd_connection_flags connectFlags;
+
+ QNetworkSession::SessionError lastError;
+
+ QDateTime startTime;
+ QString currentNetworkInterface;
+ friend class IcdListener;
+ void updateState(QNetworkSession::State);
+ void updateIdentifier(QString &newId);
+ quint64 getStatistics(bool sent) const;
+ void cleanupSession(void);
+};
+
+QT_END_NAMESPACE
+
+#endif //QNETWORKSESSIONPRIVATE_H
+
diff --git a/src/plugins/bearer/nativewifi/main.cpp b/src/plugins/bearer/nativewifi/main.cpp
new file mode 100644
index 0000000..d77462e
--- /dev/null
+++ b/src/plugins/bearer/nativewifi/main.cpp
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnativewifiengine.h"
+#include "platformdefs.h"
+
+#include <QtCore/qmutex.h>
+#include <QtCore/private/qmutexpool_p.h>
+#include <QtCore/qlibrary.h>
+
+#include <QtNetwork/private/qbearerplugin_p.h>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+static void resolveLibrary()
+{
+ static volatile bool triedResolve = false;
+
+ if (!triedResolve) {
+#ifndef QT_NO_THREAD
+ QMutexLocker locker(QMutexPool::globalInstanceGet(&local_WlanOpenHandle));
+#endif
+
+ if (!triedResolve) {
+ local_WlanOpenHandle = (WlanOpenHandleProto)
+ QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanOpenHandle");
+ local_WlanRegisterNotification = (WlanRegisterNotificationProto)
+ QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanRegisterNotification");
+ local_WlanEnumInterfaces = (WlanEnumInterfacesProto)
+ QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanEnumInterfaces");
+ local_WlanGetAvailableNetworkList = (WlanGetAvailableNetworkListProto)
+ QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanGetAvailableNetworkList");
+ local_WlanQueryInterface = (WlanQueryInterfaceProto)
+ QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanQueryInterface");
+ local_WlanConnect = (WlanConnectProto)
+ QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanConnect");
+ local_WlanDisconnect = (WlanDisconnectProto)
+ QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanDisconnect");
+ local_WlanScan = (WlanScanProto)
+ QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanScan");
+ local_WlanFreeMemory = (WlanFreeMemoryProto)
+ QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanFreeMemory");
+ local_WlanCloseHandle = (WlanCloseHandleProto)
+ QLibrary::resolve(QLatin1String("wlanapi.dll"), "WlanCloseHandle");
+
+ triedResolve = true;
+ }
+ }
+}
+
+class QNativeWifiEnginePlugin : public QBearerEnginePlugin
+{
+public:
+ QNativeWifiEnginePlugin();
+ ~QNativeWifiEnginePlugin();
+
+ QStringList keys() const;
+ QBearerEngine *create(const QString &key) const;
+};
+
+QNativeWifiEnginePlugin::QNativeWifiEnginePlugin()
+{
+}
+
+QNativeWifiEnginePlugin::~QNativeWifiEnginePlugin()
+{
+}
+
+QStringList QNativeWifiEnginePlugin::keys() const
+{
+ return QStringList() << QLatin1String("nativewifi");
+}
+
+QBearerEngine *QNativeWifiEnginePlugin::create(const QString &key) const
+{
+ if (key != QLatin1String("nativewifi"))
+ return 0;
+
+ resolveLibrary();
+
+ // native wifi dll not available
+ if (!local_WlanOpenHandle)
+ return 0;
+
+ QNativeWifiEngine *engine = new QNativeWifiEngine;
+
+ // could not initialise subsystem
+ if (engine && !engine->available()) {
+ delete engine;
+ return 0;
+ }
+
+ return engine;
+}
+
+Q_EXPORT_STATIC_PLUGIN(QNativeWifiEnginePlugin)
+Q_EXPORT_PLUGIN2(qnativewifibearer, QNativeWifiEnginePlugin)
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/nativewifi/nativewifi.pro b/src/plugins/bearer/nativewifi/nativewifi.pro
new file mode 100644
index 0000000..f277a04
--- /dev/null
+++ b/src/plugins/bearer/nativewifi/nativewifi.pro
@@ -0,0 +1,17 @@
+TARGET = qnativewifibearer
+include(../../qpluginbase.pri)
+
+QT += network
+
+HEADERS += qnativewifiengine.h \
+ platformdefs.h \
+ ../qnetworksession_impl.h \
+ ../qbearerengine_impl.h
+
+SOURCES += main.cpp \
+ qnativewifiengine.cpp \
+ ../qnetworksession_impl.cpp
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/bearer
+target.path += $$[QT_INSTALL_PLUGINS]/bearer
+INSTALLS += target
diff --git a/src/plugins/bearer/nativewifi/platformdefs.h b/src/plugins/bearer/nativewifi/platformdefs.h
new file mode 100644
index 0000000..57ae852
--- /dev/null
+++ b/src/plugins/bearer/nativewifi/platformdefs.h
@@ -0,0 +1,322 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef PLATFORMDEFS_H
+#define PLATFORMDEFS_H
+
+#include <wtypes.h>
+#undef interface
+
+#define WLAN_MAX_NAME_LENGTH 256
+#define WLAN_MAX_PHY_TYPE_NUMBER 8
+#define WLAN_NOTIFICATION_SOURCE_ALL 0x0000ffff
+#define WLAN_AVAILABLE_NETWORK_CONNECTED 1
+#define WLAN_AVAILABLE_NETWORK_HAS_PROFILE 2
+#define DOT11_SSID_MAX_LENGTH 32
+
+struct WLAN_NOTIFICATION_DATA {
+ DWORD NotificationSource;
+ DWORD NotificationCode;
+ GUID InterfaceGuid;
+ DWORD dwDataSize;
+ PVOID pData;
+};
+
+enum WLAN_INTERFACE_STATE {
+ wlan_interface_state_not_ready = 0,
+ wlan_interface_state_connected,
+ wlan_interface_state_ad_hoc_network_formed,
+ wlan_interface_state_disconnecting,
+ wlan_interface_state_disconnected,
+ wlan_interface_state_associating,
+ wlan_interface_state_discovering,
+ wlan_interface_state_authenticating
+};
+
+struct WLAN_INTERFACE_INFO {
+ GUID InterfaceGuid;
+ WCHAR strInterfaceDescription[WLAN_MAX_NAME_LENGTH];
+ WLAN_INTERFACE_STATE isState;
+};
+
+struct WLAN_INTERFACE_INFO_LIST {
+ DWORD dwNumberOfItems;
+ DWORD dwIndex;
+ WLAN_INTERFACE_INFO InterfaceInfo[1];
+};
+
+struct DOT11_SSID {
+ ULONG uSSIDLength;
+ UCHAR ucSSID[DOT11_SSID_MAX_LENGTH];
+};
+
+struct NDIS_OBJECT_HEADER {
+ UCHAR Type;
+ UCHAR Revision;
+ USHORT Size;
+};
+
+typedef UCHAR DOT11_MAC_ADDRESS[6];
+struct DOT11_BSSID_LIST {
+ NDIS_OBJECT_HEADER Header;
+ ULONG uNumberOfEntries;
+ ULONG uTotalNumOfEntries;
+ DOT11_MAC_ADDRESS BSSIDs[1];
+};
+
+enum DOT11_BSS_TYPE {
+ dot11_BSS_type_infrastructure = 1,
+ dot11_BSS_type_independent = 2,
+ dot11_BSS_type_any = 3
+};
+
+enum DOT11_PHY_TYPE {
+ dot11_phy_type_unknown = 0,
+ dot11_phy_type_any = dot11_phy_type_unknown,
+ dot11_phy_type_fhss = 1,
+ dot11_phy_type_dsss = 2,
+ dot11_phy_type_irbaseband = 3,
+ dot11_phy_type_ofdm = 4,
+ dot11_phy_type_hrdsss = 5,
+ dot11_phy_type_erp = 6,
+ dot11_phy_type_ht = 7,
+ dot11_phy_type_IHV_start = 0x80000000,
+ dot11_phy_type_IHV_end = 0xffffffff
+};
+
+enum DOT11_AUTH_ALGORITHM {
+ DOT11_AUTH_ALGO_80211_OPEN = 1,
+ DOT11_AUTH_ALGO_80211_SHARED_KEY = 2,
+ DOT11_AUTH_ALGO_WPA = 3,
+ DOT11_AUTH_ALGO_WPA_PSK = 4,
+ DOT11_AUTH_ALGO_WPA_NONE = 5,
+ DOT11_AUTH_ALGO_RSNA = 6,
+ DOT11_AUTH_ALGO_RSNA_PSK = 7,
+ DOT11_AUTH_ALGO_IHV_START = 0x80000000,
+ DOT11_AUTH_ALGO_IHV_END = 0xffffffff
+};
+
+enum DOT11_CIPHER_ALGORITHM {
+ DOT11_CIPHER_ALGO_NONE = 0x00,
+ DOT11_CIPHER_ALGO_WEP40 = 0x01,
+ DOT11_CIPHER_ALGO_TKIP = 0x02,
+ DOT11_CIPHER_ALGO_CCMP = 0x04,
+ DOT11_CIPHER_ALGO_WEP104 = 0x05,
+ DOT11_CIPHER_ALGO_WPA_USE_GROUP = 0x100,
+ DOT11_CIPHER_ALGO_RSN_USE_GROUP = 0x100,
+ DOT11_CIPHER_ALGO_WEP = 0x101,
+ DOT11_CIPHER_ALGO_IHV_START = 0x80000000,
+ DOT11_CIPHER_ALGO_IHV_END = 0xffffffff
+};
+
+struct WLAN_AVAILABLE_NETWORK {
+ WCHAR strProfileName[WLAN_MAX_NAME_LENGTH];
+ DOT11_SSID dot11Ssid;
+ DOT11_BSS_TYPE dot11BssType;
+ ULONG uNumberOfBssids;
+ BOOL bNetworkConnectable;
+ DWORD wlanNotConnectableReason;
+ ULONG uNumberOfPhyTypes;
+ DOT11_PHY_TYPE dot11PhyTypes[WLAN_MAX_PHY_TYPE_NUMBER];
+ BOOL bMorePhyTypes;
+ ULONG wlanSignalQuality;
+ BOOL bSecurityEnabled;
+ DOT11_AUTH_ALGORITHM dot11DefaultAuthAlgorithm;
+ DOT11_CIPHER_ALGORITHM dot11DefaultCipherAlgorithm;
+ DWORD dwFlags;
+ DWORD dwReserved;
+};
+
+struct WLAN_AVAILABLE_NETWORK_LIST {
+ DWORD dwNumberOfItems;
+ DWORD dwIndex;
+ WLAN_AVAILABLE_NETWORK Network[1];
+};
+
+enum WLAN_INTF_OPCODE {
+ wlan_intf_opcode_autoconf_start = 0x000000000,
+ wlan_intf_opcode_autoconf_enabled,
+ wlan_intf_opcode_background_scan_enabled,
+ wlan_intf_opcode_media_streaming_mode,
+ wlan_intf_opcode_radio_state,
+ wlan_intf_opcode_bss_type,
+ wlan_intf_opcode_interface_state,
+ wlan_intf_opcode_current_connection,
+ wlan_intf_opcode_channel_number,
+ wlan_intf_opcode_supported_infrastructure_auth_cipher_pairs,
+ wlan_intf_opcode_supported_adhoc_auth_cipher_pairs,
+ wlan_intf_opcode_supported_country_or_region_string_list,
+ wlan_intf_opcode_current_operation_mode,
+ wlan_intf_opcode_supported_safe_mode,
+ wlan_intf_opcode_certified_safe_mode,
+ wlan_intf_opcode_autoconf_end = 0x0fffffff,
+ wlan_intf_opcode_msm_start = 0x10000100,
+ wlan_intf_opcode_statistics,
+ wlan_intf_opcode_rssi,
+ wlan_intf_opcode_msm_end = 0x1fffffff,
+ wlan_intf_opcode_security_start = 0x20010000,
+ wlan_intf_opcode_security_end = 0x2fffffff,
+ wlan_intf_opcode_ihv_start = 0x30000000,
+ wlan_intf_opcode_ihv_end = 0x3fffffff
+};
+
+enum WLAN_OPCODE_VALUE_TYPE {
+ wlan_opcode_value_type_query_only = 0,
+ wlan_opcode_value_type_set_by_group_policy,
+ wlan_opcode_value_type_set_by_user,
+ wlan_opcode_value_type_invalid
+};
+
+enum WLAN_CONNECTION_MODE {
+ wlan_connection_mode_profile = 0,
+ wlan_connection_mode_temporary_profile,
+ wlan_connection_mode_discovery_secure,
+ wlan_connection_mode_discovery_unsecure,
+ wlan_connection_mode_auto,
+ wlan_connection_mode_invalid
+};
+
+struct WLAN_CONNECTION_PARAMETERS {
+ WLAN_CONNECTION_MODE wlanConnectionMode;
+ LPCWSTR strProfile;
+ DOT11_SSID *pDot11Ssid;
+ DOT11_BSSID_LIST *pDesiredBssidList;
+ DOT11_BSS_TYPE dot11BssType;
+ DWORD dwFlags;
+};
+
+struct WLAN_RAW_DATA {
+ DWORD dwDataSize;
+ BYTE DataBlob[1];
+};
+
+enum WLAN_NOTIFICATION_ACM {
+ wlan_notification_acm_start = 0,
+ wlan_notification_acm_autoconf_enabled,
+ wlan_notification_acm_autoconf_disabled,
+ wlan_notification_acm_background_scan_enabled,
+ wlan_notification_acm_background_scan_disabled,
+ wlan_notification_acm_bss_type_change,
+ wlan_notification_acm_power_setting_change,
+ wlan_notification_acm_scan_complete,
+ wlan_notification_acm_scan_fail,
+ wlan_notification_acm_connection_start,
+ wlan_notification_acm_connection_complete,
+ wlan_notification_acm_connection_attempt_fail,
+ wlan_notification_acm_filter_list_change,
+ wlan_notification_acm_interface_arrival,
+ wlan_notification_acm_interface_removal,
+ wlan_notification_acm_profile_change,
+ wlan_notification_acm_profile_name_change,
+ wlan_notification_acm_profiles_exhausted,
+ wlan_notification_acm_network_not_available,
+ wlan_notification_acm_network_available,
+ wlan_notification_acm_disconnecting,
+ wlan_notification_acm_disconnected,
+ wlan_notification_acm_adhoc_network_state_change,
+ wlan_notification_acm_end
+};
+
+struct WLAN_ASSOCIATION_ATTRIBUTES {
+ DOT11_SSID dot11Ssid;
+ DOT11_BSS_TYPE dot11BssType;
+ DOT11_MAC_ADDRESS dot11Bssid;
+ DOT11_PHY_TYPE dot11PhyType;
+ ULONG uDot11PhyIndex;
+ ULONG wlanSignalQuality;
+ ULONG ulRxRate;
+ ULONG ulTxRate;
+};
+
+struct WLAN_SECURITY_ATTRIBUTES {
+ BOOL bSecurityEnabled;
+ BOOL bOneXEnabled;
+ DOT11_AUTH_ALGORITHM dot11AuthAlgorithm;
+ DOT11_CIPHER_ALGORITHM dot11CipherAlgorithm;
+};
+
+struct WLAN_CONNECTION_ATTRIBUTES {
+ WLAN_INTERFACE_STATE isState;
+ WLAN_CONNECTION_MODE wlanConnectionMode;
+ WCHAR strProfileName[WLAN_MAX_NAME_LENGTH];
+ WLAN_ASSOCIATION_ATTRIBUTES wlanAssociationAttributes;
+ WLAN_SECURITY_ATTRIBUTES wlanSecurityAttributes;
+};
+
+typedef void (WINAPI *WLAN_NOTIFICATION_CALLBACK)(WLAN_NOTIFICATION_DATA *, PVOID);
+
+typedef DWORD (WINAPI *WlanOpenHandleProto)
+ (DWORD dwClientVersion, PVOID pReserved, PDWORD pdwNegotiatedVersion, PHANDLE phClientHandle);
+typedef DWORD (WINAPI *WlanRegisterNotificationProto)
+ (HANDLE hClientHandle, DWORD dwNotifSource, BOOL bIgnoreDuplicate,
+ WLAN_NOTIFICATION_CALLBACK funcCallback, PVOID pCallbackContext,
+ PVOID pReserved, PDWORD pdwPrevNotifSource);
+typedef DWORD (WINAPI *WlanEnumInterfacesProto)
+ (HANDLE hClientHandle, PVOID pReserved, WLAN_INTERFACE_INFO_LIST **ppInterfaceList);
+typedef DWORD (WINAPI *WlanGetAvailableNetworkListProto)
+ (HANDLE hClientHandle, const GUID* pInterfaceGuid, DWORD dwFlags, PVOID pReserved,
+ WLAN_AVAILABLE_NETWORK_LIST **ppAvailableNetworkList);
+typedef DWORD (WINAPI *WlanQueryInterfaceProto)
+ (HANDLE hClientHandle, const GUID *pInterfaceGuid, WLAN_INTF_OPCODE OpCode, PVOID pReserved,
+ PDWORD pdwDataSize, PVOID *ppData, WLAN_OPCODE_VALUE_TYPE *pWlanOpcodeValueType);
+typedef DWORD (WINAPI *WlanConnectProto)
+ (HANDLE hClientHandle, const GUID *pInterfaceGuid,
+ const WLAN_CONNECTION_PARAMETERS *pConnectionParameters, PVOID pReserved);
+typedef DWORD (WINAPI *WlanDisconnectProto)
+ (HANDLE hClientHandle, const GUID *pInterfaceGuid, PVOID pReserved);
+typedef DWORD (WINAPI *WlanScanProto)
+ (HANDLE hClientHandle, const GUID *pInterfaceGuid, const DOT11_SSID *pDot11Ssid,
+ const WLAN_RAW_DATA *pIeData, PVOID pReserved);
+typedef VOID (WINAPI *WlanFreeMemoryProto)(PVOID pMemory);
+typedef DWORD (WINAPI *WlanCloseHandleProto)(HANDLE hClientHandle, PVOID pReserved);
+
+extern WlanOpenHandleProto local_WlanOpenHandle;
+extern WlanRegisterNotificationProto local_WlanRegisterNotification;
+extern WlanEnumInterfacesProto local_WlanEnumInterfaces;
+extern WlanGetAvailableNetworkListProto local_WlanGetAvailableNetworkList;
+extern WlanQueryInterfaceProto local_WlanQueryInterface;
+extern WlanConnectProto local_WlanConnect;
+extern WlanDisconnectProto local_WlanDisconnect;
+extern WlanScanProto local_WlanScan;
+extern WlanFreeMemoryProto local_WlanFreeMemory;
+extern WlanCloseHandleProto local_WlanCloseHandle;
+
+#endif // PLATFORMDEFS_H
diff --git a/src/plugins/bearer/nativewifi/qnativewifiengine.cpp b/src/plugins/bearer/nativewifi/qnativewifiengine.cpp
new file mode 100644
index 0000000..c8015d8
--- /dev/null
+++ b/src/plugins/bearer/nativewifi/qnativewifiengine.cpp
@@ -0,0 +1,495 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnativewifiengine.h"
+#include "platformdefs.h"
+#include "../qnetworksession_impl.h"
+
+#include <QtNetwork/private/qnetworkconfiguration_p.h>
+
+#include <QtCore/qstringlist.h>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+WlanOpenHandleProto local_WlanOpenHandle = 0;
+WlanRegisterNotificationProto local_WlanRegisterNotification = 0;
+WlanEnumInterfacesProto local_WlanEnumInterfaces = 0;
+WlanGetAvailableNetworkListProto local_WlanGetAvailableNetworkList = 0;
+WlanQueryInterfaceProto local_WlanQueryInterface = 0;
+WlanConnectProto local_WlanConnect = 0;
+WlanDisconnectProto local_WlanDisconnect = 0;
+WlanScanProto local_WlanScan = 0;
+WlanFreeMemoryProto local_WlanFreeMemory = 0;
+WlanCloseHandleProto local_WlanCloseHandle = 0;
+
+void qNotificationCallback(WLAN_NOTIFICATION_DATA *data, QNativeWifiEngine *d)
+{
+ Q_UNUSED(d);
+
+ switch (data->NotificationCode) {
+ case wlan_notification_acm_connection_complete:
+ case wlan_notification_acm_disconnected:
+ QMetaObject::invokeMethod(d, "scanComplete", Qt::QueuedConnection);
+ break;
+ default:
+ ;
+ }
+}
+
+QNativeWifiEngine::QNativeWifiEngine(QObject *parent)
+: QBearerEngineImpl(parent), handle(0)
+{
+ DWORD clientVersion;
+
+ DWORD result = local_WlanOpenHandle(1, 0, &clientVersion, &handle);
+ if (result != ERROR_SUCCESS) {
+ if (result != ERROR_SERVICE_NOT_ACTIVE)
+ qWarning("%s: WlanOpenHandle failed with error %ld\n", __FUNCTION__, result);
+
+ return;
+ }
+
+ result = local_WlanRegisterNotification(handle, WLAN_NOTIFICATION_SOURCE_ALL, true,
+ WLAN_NOTIFICATION_CALLBACK(qNotificationCallback),
+ this, 0, 0);
+ if (result != ERROR_SUCCESS)
+ qWarning("%s: WlanRegisterNotification failed with error %ld\n", __FUNCTION__, result);
+
+ // On Windows XP SP2 and SP3 only connection and disconnection notifications are available.
+ // We need to poll for changes in available wireless networks.
+ connect(&pollTimer, SIGNAL(timeout()), this, SLOT(scanComplete()));
+ pollTimer.setInterval(10000);
+ scanComplete();
+}
+
+QNativeWifiEngine::~QNativeWifiEngine()
+{
+ local_WlanCloseHandle(handle, 0);
+}
+
+void QNativeWifiEngine::scanComplete()
+{
+ QMutexLocker locker(&mutex);
+
+ QStringList previous = accessPointConfigurations.keys();
+
+ // enumerate interfaces
+ WLAN_INTERFACE_INFO_LIST *interfaceList;
+ DWORD result = local_WlanEnumInterfaces(handle, 0, &interfaceList);
+ if (result != ERROR_SUCCESS) {
+ qWarning("%s: WlanEnumInterfaces failed with error %ld\n", __FUNCTION__, result);
+ return;
+ }
+
+ for (unsigned int i = 0; i < interfaceList->dwNumberOfItems; ++i) {
+ const WLAN_INTERFACE_INFO &interface = interfaceList->InterfaceInfo[i];
+
+ WLAN_AVAILABLE_NETWORK_LIST *networkList;
+ result = local_WlanGetAvailableNetworkList(handle, &interface.InterfaceGuid,
+ 3, 0, &networkList);
+ if (result != ERROR_SUCCESS) {
+ qWarning("%s: WlanGetAvailableNetworkList failed with error %ld\n",
+ __FUNCTION__, result);
+ continue;
+ }
+
+ QStringList seenNetworks;
+
+ for (unsigned int j = 0; j < networkList->dwNumberOfItems; ++j) {
+ WLAN_AVAILABLE_NETWORK &network = networkList->Network[j];
+
+ QString networkName;
+
+ if (network.strProfileName[0] != 0) {
+ networkName = QString::fromWCharArray(network.strProfileName);
+ } else {
+ networkName = QByteArray(reinterpret_cast<char *>(network.dot11Ssid.ucSSID),
+ network.dot11Ssid.uSSIDLength);
+ }
+
+ const QString id = QString::number(qHash(QLatin1String("WLAN:") + networkName));
+
+ previous.removeAll(id);
+
+ QNetworkConfiguration::StateFlags state = QNetworkConfiguration::Undefined;
+
+ if (!(network.dwFlags & WLAN_AVAILABLE_NETWORK_HAS_PROFILE))
+ state = QNetworkConfiguration::Undefined;
+
+ if (network.strProfileName[0] != 0) {
+ if (network.bNetworkConnectable) {
+ if (network.dwFlags & WLAN_AVAILABLE_NETWORK_CONNECTED)
+ state = QNetworkConfiguration::Active;
+ else
+ state = QNetworkConfiguration::Discovered;
+ } else {
+ state = QNetworkConfiguration::Defined;
+ }
+ }
+
+ if (seenNetworks.contains(networkName))
+ continue;
+ else
+ seenNetworks.append(networkName);
+
+ if (accessPointConfigurations.contains(id)) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+
+ bool changed = false;
+
+ if (!ptr->isValid) {
+ ptr->isValid = true;
+ changed = true;
+ }
+
+ if (ptr->name != networkName) {
+ ptr->name = networkName;
+ changed = true;
+ }
+
+ if (ptr->state != state) {
+ ptr->state = state;
+ changed = true;
+ }
+
+ if (changed)
+ emit configurationChanged(ptr);
+ } else {
+ QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate);
+
+ ptr->name = networkName;
+ ptr->isValid = true;
+ ptr->id = id;
+ ptr->state = state;
+ ptr->type = QNetworkConfiguration::InternetAccessPoint;
+ ptr->bearer = QLatin1String("WLAN");
+
+ accessPointConfigurations.insert(id, ptr);
+
+ emit configurationAdded(ptr);
+ }
+ }
+
+ local_WlanFreeMemory(networkList);
+ }
+
+ local_WlanFreeMemory(interfaceList);
+
+ while (!previous.isEmpty()) {
+ QNetworkConfigurationPrivatePointer ptr =
+ accessPointConfigurations.take(previous.takeFirst());
+
+ emit configurationRemoved(ptr);
+ }
+
+ pollTimer.start();
+
+ emit updateCompleted();
+}
+
+QString QNativeWifiEngine::getInterfaceFromId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ // enumerate interfaces
+ WLAN_INTERFACE_INFO_LIST *interfaceList;
+ DWORD result = local_WlanEnumInterfaces(handle, 0, &interfaceList);
+ if (result != ERROR_SUCCESS) {
+ qWarning("%s: WlanEnumInterfaces failed with error %ld\n", __FUNCTION__, result);
+ return QString();
+ }
+
+ for (unsigned int i = 0; i < interfaceList->dwNumberOfItems; ++i) {
+ const WLAN_INTERFACE_INFO &interface = interfaceList->InterfaceInfo[i];
+
+ DWORD dataSize;
+ WLAN_CONNECTION_ATTRIBUTES *connectionAttributes;
+ result = local_WlanQueryInterface(handle, &interface.InterfaceGuid,
+ wlan_intf_opcode_current_connection, 0, &dataSize,
+ reinterpret_cast<PVOID *>(&connectionAttributes), 0);
+ if (result != ERROR_SUCCESS) {
+ if (result != ERROR_INVALID_STATE)
+ qWarning("%s: WlanQueryInterface failed with error %ld\n", __FUNCTION__, result);
+
+ continue;
+ }
+
+ if (qHash(QLatin1String("WLAN:") +
+ QString::fromWCharArray(connectionAttributes->strProfileName)) == id.toUInt()) {
+ QString guid("{%1-%2-%3-%4%5-%6%7%8%9%10%11}");
+
+ guid = guid.arg(interface.InterfaceGuid.Data1, 8, 16, QChar('0'));
+ guid = guid.arg(interface.InterfaceGuid.Data2, 4, 16, QChar('0'));
+ guid = guid.arg(interface.InterfaceGuid.Data3, 4, 16, QChar('0'));
+ for (int i = 0; i < 8; ++i)
+ guid = guid.arg(interface.InterfaceGuid.Data4[i], 2, 16, QChar('0'));
+
+ local_WlanFreeMemory(connectionAttributes);
+ local_WlanFreeMemory(interfaceList);
+
+ return guid.toUpper();
+ }
+
+ local_WlanFreeMemory(connectionAttributes);
+ }
+
+ local_WlanFreeMemory(interfaceList);
+
+ return QString();
+}
+
+bool QNativeWifiEngine::hasIdentifier(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ // enumerate interfaces
+ WLAN_INTERFACE_INFO_LIST *interfaceList;
+ DWORD result = local_WlanEnumInterfaces(handle, 0, &interfaceList);
+ if (result != ERROR_SUCCESS) {
+ qWarning("%s: WlanEnumInterfaces failed with error %ld\n", __FUNCTION__, result);
+ return false;
+ }
+
+ for (unsigned int i = 0; i < interfaceList->dwNumberOfItems; ++i) {
+ const WLAN_INTERFACE_INFO &interface = interfaceList->InterfaceInfo[i];
+
+ WLAN_AVAILABLE_NETWORK_LIST *networkList;
+ result = local_WlanGetAvailableNetworkList(handle, &interface.InterfaceGuid,
+ 3, 0, &networkList);
+ if (result != ERROR_SUCCESS) {
+ qWarning("%s: WlanGetAvailableNetworkList failed with error %ld\n",
+ __FUNCTION__, result);
+ continue;
+ }
+
+ for (unsigned int j = 0; j < networkList->dwNumberOfItems; ++j) {
+ WLAN_AVAILABLE_NETWORK &network = networkList->Network[j];
+
+ QString networkName;
+
+ if (network.strProfileName[0] != 0) {
+ networkName = QString::fromWCharArray(network.strProfileName);
+ } else {
+ networkName = QByteArray(reinterpret_cast<char *>(network.dot11Ssid.ucSSID),
+ network.dot11Ssid.uSSIDLength);
+ }
+
+ if (qHash(QLatin1String("WLAN:") + networkName) == id.toUInt()) {
+ local_WlanFreeMemory(networkList);
+ local_WlanFreeMemory(interfaceList);
+ return true;
+ }
+ }
+
+ local_WlanFreeMemory(networkList);
+ }
+
+ local_WlanFreeMemory(interfaceList);
+
+ return false;
+}
+
+/*QString QNativeWifiEngine::bearerName(const QString &)
+{
+ return QLatin1String("WLAN");
+}*/
+
+void QNativeWifiEngine::connectToId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ WLAN_INTERFACE_INFO_LIST *interfaceList;
+ DWORD result = local_WlanEnumInterfaces(handle, 0, &interfaceList);
+ if (result != ERROR_SUCCESS) {
+ qWarning("%s: WlanEnumInterfaces failed with error %ld\n", __FUNCTION__, result);
+ emit connectionError(id, InterfaceLookupError);
+ return;
+ }
+
+ QString profile;
+
+ for (unsigned int i = 0; i < interfaceList->dwNumberOfItems; ++i) {
+ const WLAN_INTERFACE_INFO &interface = interfaceList->InterfaceInfo[i];
+
+ WLAN_AVAILABLE_NETWORK_LIST *networkList;
+ result = local_WlanGetAvailableNetworkList(handle, &interface.InterfaceGuid,
+ 3, 0, &networkList);
+ if (result != ERROR_SUCCESS) {
+ qWarning("%s: WlanGetAvailableNetworkList failed with error %ld\n",
+ __FUNCTION__, result);
+ continue;
+ }
+
+ for (unsigned int j = 0; j < networkList->dwNumberOfItems; ++j) {
+ WLAN_AVAILABLE_NETWORK &network = networkList->Network[j];
+
+ profile = QString::fromWCharArray(network.strProfileName);
+
+ if (qHash(QLatin1String("WLAN:") + profile) == id.toUInt())
+ break;
+ else
+ profile.clear();
+ }
+
+ local_WlanFreeMemory(networkList);
+
+ if (!profile.isEmpty()) {
+ WLAN_CONNECTION_PARAMETERS parameters;
+ parameters.wlanConnectionMode = wlan_connection_mode_profile;
+ parameters.strProfile = reinterpret_cast<LPCWSTR>(profile.utf16());
+ parameters.pDot11Ssid = 0;
+ parameters.pDesiredBssidList = 0;
+ parameters.dot11BssType = dot11_BSS_type_any;
+ parameters.dwFlags = 0;
+
+ DWORD result = local_WlanConnect(handle, &interface.InterfaceGuid, &parameters, 0);
+ if (result != ERROR_SUCCESS) {
+ qWarning("%s: WlanConnect failed with error %ld\n", __FUNCTION__, result);
+ emit connectionError(id, ConnectError);
+ break;
+ }
+
+ break;
+ }
+ }
+
+ local_WlanFreeMemory(interfaceList);
+
+ if (profile.isEmpty())
+ emit connectionError(id, InterfaceLookupError);
+}
+
+void QNativeWifiEngine::disconnectFromId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ QString interface = getInterfaceFromId(id);
+
+ if (interface.isEmpty()) {
+ emit connectionError(id, InterfaceLookupError);
+ return;
+ }
+
+ QStringList split = interface.mid(1, interface.length() - 2).split('-');
+
+ GUID guid;
+ guid.Data1 = split.at(0).toUInt(0, 16);
+ guid.Data2 = split.at(1).toUShort(0, 16);
+ guid.Data3 = split.at(2).toUShort(0, 16);
+ guid.Data4[0] = split.at(3).left(2).toUShort(0, 16);
+ guid.Data4[1] = split.at(3).right(2).toUShort(0, 16);
+ for (int i = 0; i < 6; ++i)
+ guid.Data4[i + 2] = split.at(4).mid(i*2, 2).toUShort(0, 16);
+
+ DWORD result = local_WlanDisconnect(handle, &guid, 0);
+ if (result != ERROR_SUCCESS) {
+ qWarning("%s: WlanDisconnect failed with error %ld\n", __FUNCTION__, result);
+ emit connectionError(id, DisconnectionError);
+ return;
+ }
+}
+
+void QNativeWifiEngine::requestUpdate()
+{
+ QMutexLocker locker(&mutex);
+
+ // enumerate interfaces
+ WLAN_INTERFACE_INFO_LIST *interfaceList;
+ DWORD result = local_WlanEnumInterfaces(handle, 0, &interfaceList);
+ if (result != ERROR_SUCCESS) {
+ qWarning("%s: WlanEnumInterfaces failed with error %ld\n", __FUNCTION__, result);
+ return;
+ }
+
+ for (unsigned int i = 0; i < interfaceList->dwNumberOfItems; ++i) {
+ result = local_WlanScan(handle, &interfaceList->InterfaceInfo[i].InterfaceGuid, 0, 0, 0);
+ if (result != ERROR_SUCCESS)
+ qWarning("%s: WlanScan failed with error %ld\n", __FUNCTION__, result);
+ }
+
+ local_WlanFreeMemory(interfaceList);
+}
+
+QNetworkSession::State QNativeWifiEngine::sessionStateForId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+
+ if (!ptr)
+ return QNetworkSession::Invalid;
+
+ if (!ptr->isValid) {
+ return QNetworkSession::Invalid;
+ } else if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ return QNetworkSession::Connected;
+ } else if ((ptr->state & QNetworkConfiguration::Discovered) ==
+ QNetworkConfiguration::Discovered) {
+ return QNetworkSession::Disconnected;
+ } else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
+ return QNetworkSession::NotAvailable;
+ } else if ((ptr->state & QNetworkConfiguration::Undefined) ==
+ QNetworkConfiguration::Undefined) {
+ return QNetworkSession::NotAvailable;
+ }
+
+ return QNetworkSession::Invalid;
+}
+
+QNetworkConfigurationManager::Capabilities QNativeWifiEngine::capabilities() const
+{
+ return QNetworkConfigurationManager::ForcedRoaming |
+ QNetworkConfigurationManager::CanStartAndStopInterfaces;
+}
+
+QNetworkSessionPrivate *QNativeWifiEngine::createSessionBackend()
+{
+ return new QNetworkSessionPrivateImpl;
+}
+
+QNetworkConfigurationPrivatePointer QNativeWifiEngine::defaultConfiguration()
+{
+ return QNetworkConfigurationPrivatePointer();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/nativewifi/qnativewifiengine.h b/src/plugins/bearer/nativewifi/qnativewifiengine.h
new file mode 100644
index 0000000..a9a9375
--- /dev/null
+++ b/src/plugins/bearer/nativewifi/qnativewifiengine.h
@@ -0,0 +1,104 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNATIVEWIFIENGINE_P_H
+#define QNATIVEWIFIENGINE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "../qbearerengine_impl.h"
+
+#include <QtCore/qtimer.h>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkConfigurationPrivate;
+struct WLAN_NOTIFICATION_DATA;
+
+class QNativeWifiEngine : public QBearerEngineImpl
+{
+ Q_OBJECT
+
+public:
+ QNativeWifiEngine(QObject *parent = 0);
+ ~QNativeWifiEngine();
+
+ QString getInterfaceFromId(const QString &id);
+ bool hasIdentifier(const QString &id);
+
+ //QString bearerName(const QString &id);
+
+ void connectToId(const QString &id);
+ void disconnectFromId(const QString &id);
+
+ void requestUpdate();
+
+ QNetworkSession::State sessionStateForId(const QString &id);
+
+ QNetworkConfigurationManager::Capabilities capabilities() const;
+
+ QNetworkSessionPrivate *createSessionBackend();
+
+ QNetworkConfigurationPrivatePointer defaultConfiguration();
+
+ inline bool available() const { return handle != 0; }
+
+public Q_SLOTS:
+ void scanComplete();
+
+private:
+ QTimer pollTimer;
+
+ Qt::HANDLE handle;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/bearer/networkmanager/main.cpp b/src/plugins/bearer/networkmanager/main.cpp
new file mode 100644
index 0000000..6c97a22
--- /dev/null
+++ b/src/plugins/bearer/networkmanager/main.cpp
@@ -0,0 +1,89 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnetworkmanagerengine.h"
+
+#include <QtNetwork/private/qbearerplugin_p.h>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkManagerEnginePlugin : public QBearerEnginePlugin
+{
+public:
+ QNetworkManagerEnginePlugin();
+ ~QNetworkManagerEnginePlugin();
+
+ QStringList keys() const;
+ QBearerEngine *create(const QString &key) const;
+};
+
+QNetworkManagerEnginePlugin::QNetworkManagerEnginePlugin()
+{
+}
+
+QNetworkManagerEnginePlugin::~QNetworkManagerEnginePlugin()
+{
+}
+
+QStringList QNetworkManagerEnginePlugin::keys() const
+{
+ return QStringList() << QLatin1String("networkmanager");
+}
+
+QBearerEngine *QNetworkManagerEnginePlugin::create(const QString &key) const
+{
+ if (key == QLatin1String("networkmanager")) {
+ QNetworkManagerEngine *engine = new QNetworkManagerEngine;
+ if (engine->networkManagerAvailable())
+ return engine;
+ else
+ delete engine;
+ }
+
+ return 0;
+}
+
+Q_EXPORT_STATIC_PLUGIN(QNetworkManagerEnginePlugin)
+Q_EXPORT_PLUGIN2(qnmbearer, QNetworkManagerEnginePlugin)
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/networkmanager/networkmanager.pro b/src/plugins/bearer/networkmanager/networkmanager.pro
new file mode 100644
index 0000000..bf0d29a
--- /dev/null
+++ b/src/plugins/bearer/networkmanager/networkmanager.pro
@@ -0,0 +1,20 @@
+TARGET = qnmbearer
+include(../../qpluginbase.pri)
+
+QT += network dbus
+
+HEADERS += qnmdbushelper.h \
+ qnetworkmanagerservice.h \
+ qnetworkmanagerengine.h \
+ ../qnetworksession_impl.h \
+ ../qbearerengine_impl.h
+
+SOURCES += main.cpp \
+ qnmdbushelper.cpp \
+ qnetworkmanagerservice.cpp \
+ qnetworkmanagerengine.cpp \
+ ../qnetworksession_impl.cpp
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/bearer
+target.path += $$[QT_INSTALL_PLUGINS]/bearer
+INSTALLS += target
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
new file mode 100644
index 0000000..5c6efe3
--- /dev/null
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.cpp
@@ -0,0 +1,847 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnetworkmanagerengine.h"
+#include "qnetworkmanagerservice.h"
+#include "../qnetworksession_impl.h"
+
+#include <QtNetwork/private/qnetworkconfiguration_p.h>
+
+#include <QtNetwork/qnetworksession.h>
+
+#include <QtCore/qdebug.h>
+
+#include <NetworkManager/NetworkManager.h>
+#include <QtDBus>
+#include <QDBusConnection>
+#include <QDBusError>
+#include <QDBusInterface>
+#include <QDBusMessage>
+#include <QDBusReply>
+
+QT_BEGIN_NAMESPACE
+
+QNetworkManagerEngine::QNetworkManagerEngine(QObject *parent)
+: QBearerEngineImpl(parent),
+ interface(new QNetworkManagerInterface(this)),
+ systemSettings(new QNetworkManagerSettings(NM_DBUS_SERVICE_SYSTEM_SETTINGS, this)),
+ userSettings(new QNetworkManagerSettings(NM_DBUS_SERVICE_USER_SETTINGS, this))
+{
+ if (!interface->isValid())
+ return;
+
+ interface->setConnections();
+ connect(interface, SIGNAL(deviceAdded(QDBusObjectPath)),
+ this, SLOT(deviceAdded(QDBusObjectPath)));
+ connect(interface, SIGNAL(deviceRemoved(QDBusObjectPath)),
+ this, SLOT(deviceRemoved(QDBusObjectPath)));
+#if 0
+ connect(interface, SIGNAL(stateChanged(const QString,quint32)),
+ this, SIGNAL(configurationsChanged()));
+#endif
+ connect(interface, SIGNAL(activationFinished(QDBusPendingCallWatcher*)),
+ this, SLOT(activationFinished(QDBusPendingCallWatcher*)));
+ connect(interface, SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)),
+ this, SLOT(interfacePropertiesChanged(QString,QMap<QString,QVariant>)));
+
+ qDBusRegisterMetaType<QNmSettingsMap>();
+
+ systemSettings->setConnections();
+ connect(systemSettings, SIGNAL(newConnection(QDBusObjectPath)),
+ this, SLOT(newConnection(QDBusObjectPath)));
+
+ userSettings->setConnections();
+ connect(userSettings, SIGNAL(newConnection(QDBusObjectPath)),
+ this, SLOT(newConnection(QDBusObjectPath)));
+
+ // Get current list of access points.
+ foreach (const QDBusObjectPath &devicePath, interface->getDevices())
+ deviceAdded(devicePath);
+
+ // Get connections.
+ foreach (const QDBusObjectPath &settingsPath, systemSettings->listConnections())
+ newConnection(settingsPath, systemSettings);
+ foreach (const QDBusObjectPath &settingsPath, userSettings->listConnections())
+ newConnection(settingsPath, userSettings);
+
+ // Get active connections.
+ foreach (const QDBusObjectPath &acPath, interface->activeConnections()) {
+ QNetworkManagerConnectionActive *activeConnection =
+ new QNetworkManagerConnectionActive(acPath.path());
+ activeConnections.insert(acPath.path(), activeConnection);
+
+ activeConnection->setConnections();
+ connect(activeConnection, SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)),
+ this, SLOT(activeConnectionPropertiesChanged(QString,QMap<QString,QVariant>)));
+ }
+}
+
+QNetworkManagerEngine::~QNetworkManagerEngine()
+{
+}
+
+bool QNetworkManagerEngine::networkManagerAvailable() const
+{
+ QMutexLocker locker(&mutex);
+
+ return interface->isValid();
+}
+
+void QNetworkManagerEngine::doRequestUpdate()
+{
+ emit updateCompleted();
+}
+
+QString QNetworkManagerEngine::getInterfaceFromId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ foreach (const QDBusObjectPath &acPath, interface->activeConnections()) {
+ QNetworkManagerConnectionActive activeConnection(acPath.path());
+
+ const QString identifier = QString::number(qHash(activeConnection.serviceName() + ' ' +
+ activeConnection.connection().path()));
+
+ if (id == identifier) {
+ QList<QDBusObjectPath> devices = activeConnection.devices();
+
+ if (devices.isEmpty())
+ continue;
+
+ QNetworkManagerInterfaceDevice device(devices.at(0).path());
+ return device.interface().name();
+ }
+ }
+
+ return QString();
+}
+
+bool QNetworkManagerEngine::hasIdentifier(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ if (connectionFromId(id))
+ return true;
+
+ for (int i = 0; i < accessPoints.count(); ++i) {
+ QNetworkManagerInterfaceAccessPoint *accessPoint = accessPoints.at(i);
+
+ const QString identifier =
+ QString::number(qHash(accessPoint->connectionInterface()->path()));
+
+ if (id == identifier)
+ return true;
+ }
+
+ return false;
+}
+
+QString QNetworkManagerEngine::bearerName(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ QNetworkManagerSettingsConnection *connection = connectionFromId(id);
+
+ if (!connection)
+ return QString();
+
+ QNmSettingsMap map = connection->getSettings();
+ const QString connectionType = map.value("connection").value("type").toString();
+
+ if (connectionType == "802-3-ethernet")
+ return QLatin1String("Ethernet");
+ else if (connectionType == "802-11-wireless")
+ return QLatin1String("WLAN");
+ else if (connectionType == "gsm")
+ return QLatin1String("2G");
+ else if (connectionType == "cdma")
+ return QLatin1String("CDMA2000");
+ else
+ return QString();
+}
+
+void QNetworkManagerEngine::connectToId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ QNetworkManagerSettingsConnection *connection = connectionFromId(id);
+
+ if (!connection)
+ return;
+
+ QNmSettingsMap map = connection->getSettings();
+ const QString connectionType = map.value("connection").value("type").toString();
+
+ QString dbusDevicePath;
+ foreach (const QDBusObjectPath &devicePath, interface->getDevices()) {
+ QNetworkManagerInterfaceDevice device(devicePath.path());
+ if (device.deviceType() == DEVICE_TYPE_802_3_ETHERNET &&
+ connectionType == QLatin1String("802-3-ethernet")) {
+ dbusDevicePath = devicePath.path();
+ break;
+ } else if (device.deviceType() == DEVICE_TYPE_802_11_WIRELESS &&
+ connectionType == QLatin1String("802-11-wireless")) {
+ dbusDevicePath = devicePath.path();
+ break;
+ }
+ }
+
+ const QString service = connection->connectionInterface()->service();
+ const QString settingsPath = connection->connectionInterface()->path();
+
+ interface->activateConnection(service, QDBusObjectPath(settingsPath),
+ QDBusObjectPath(dbusDevicePath), QDBusObjectPath("/"));
+}
+
+void QNetworkManagerEngine::disconnectFromId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ foreach (const QDBusObjectPath &acPath, interface->activeConnections()) {
+ QNetworkManagerConnectionActive activeConnection(acPath.path());
+
+ const QString identifier = QString::number(qHash(activeConnection.serviceName() + ' ' +
+ activeConnection.connection().path()));
+
+ if (id == identifier && accessPointConfigurations.contains(id)) {
+ interface->deactivateConnection(acPath);
+ break;
+ }
+ }
+}
+
+void QNetworkManagerEngine::requestUpdate()
+{
+ QMutexLocker locker(&mutex);
+
+ QTimer::singleShot(0, this, SLOT(doRequestUpdate()));
+}
+
+void QNetworkManagerEngine::interfacePropertiesChanged(const QString &path,
+ const QMap<QString, QVariant> &properties)
+{
+ QMutexLocker locker(&mutex);
+
+ Q_UNUSED(path)
+
+ QMapIterator<QString, QVariant> i(properties);
+ while (i.hasNext()) {
+ i.next();
+
+ if (i.key() == QLatin1String("ActiveConnections")) {
+ // Active connections changed, update configurations.
+
+ QList<QDBusObjectPath> activeConnections =
+ qdbus_cast<QList<QDBusObjectPath> >(i.value().value<QDBusArgument>());
+
+ QStringList identifiers = accessPointConfigurations.keys();
+ foreach (const QString &id, identifiers)
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+
+ QStringList priorActiveConnections = this->activeConnections.keys();
+
+ foreach (const QDBusObjectPath &acPath, activeConnections) {
+ priorActiveConnections.removeOne(acPath.path());
+ QNetworkManagerConnectionActive *activeConnection =
+ this->activeConnections.value(acPath.path());
+ if (!activeConnection) {
+ activeConnection = new QNetworkManagerConnectionActive(acPath.path());
+ this->activeConnections.insert(acPath.path(), activeConnection);
+
+ activeConnection->setConnections();
+ connect(activeConnection, SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)),
+ this, SLOT(activeConnectionPropertiesChanged(QString,QMap<QString,QVariant>)));
+ }
+
+ const QString id = QString::number(qHash(activeConnection->serviceName() + ' ' +
+ activeConnection->connection().path()));
+
+ identifiers.removeOne(id);
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+ if (ptr) {
+ if (activeConnection->state() == 2 &&
+ ptr->state != QNetworkConfiguration::Active) {
+ ptr->state = QNetworkConfiguration::Active;
+ emit configurationChanged(ptr);
+ }
+ }
+ }
+
+ while (!priorActiveConnections.isEmpty())
+ delete this->activeConnections.take(priorActiveConnections.takeFirst());
+
+ while (!identifiers.isEmpty()) {
+ // These configurations are not active
+ QNetworkConfigurationPrivatePointer ptr =
+ accessPointConfigurations.value(identifiers.takeFirst());
+
+ if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ ptr->state = QNetworkConfiguration::Discovered;
+ emit configurationChanged(ptr);
+ }
+ }
+ }
+ }
+}
+
+void QNetworkManagerEngine::activeConnectionPropertiesChanged(const QString &path,
+ const QMap<QString, QVariant> &properties)
+{
+ QMutexLocker locker(&mutex);
+
+ Q_UNUSED(properties)
+
+ QNetworkManagerConnectionActive *activeConnection = activeConnections.value(path);
+
+ if (!activeConnection)
+ return;
+
+ const QString id = QString::number(qHash(activeConnection->serviceName() + ' ' +
+ activeConnection->connection().path()));
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+ if (ptr) {
+ if (activeConnection->state() == 2 &&
+ ptr->state != QNetworkConfiguration::Active) {
+ ptr->state = QNetworkConfiguration::Active;
+ emit configurationChanged(ptr);
+ }
+ }
+}
+
+void QNetworkManagerEngine::devicePropertiesChanged(const QString &path,
+ const QMap<QString, QVariant> &properties)
+{
+ Q_UNUSED(path);
+ Q_UNUSED(properties);
+}
+
+void QNetworkManagerEngine::deviceAdded(const QDBusObjectPath &path)
+{
+ QMutexLocker locker(&mutex);
+
+ QNetworkManagerInterfaceDevice device(path.path());
+ if (device.deviceType() == DEVICE_TYPE_802_11_WIRELESS) {
+ QNetworkManagerInterfaceDeviceWireless *wirelessDevice =
+ new QNetworkManagerInterfaceDeviceWireless(device.connectionInterface()->path());
+ wirelessDevices.insert(path.path(), wirelessDevice);
+
+ wirelessDevice->setConnections();
+ connect(wirelessDevice, SIGNAL(accessPointAdded(QString,QDBusObjectPath)),
+ this, SLOT(newAccessPoint(QString,QDBusObjectPath)));
+ connect(wirelessDevice, SIGNAL(accessPointRemoved(QString,QDBusObjectPath)),
+ this, SLOT(removeAccessPoint(QString,QDBusObjectPath)));
+ connect(wirelessDevice, SIGNAL(propertiesChanged(QString,QMap<QString,QVariant>)),
+ this, SLOT(devicePropertiesChanged(QString,QMap<QString,QVariant>)));
+
+ foreach (const QDBusObjectPath &apPath, wirelessDevice->getAccessPoints())
+ newAccessPoint(QString(), apPath);
+ }
+}
+
+void QNetworkManagerEngine::deviceRemoved(const QDBusObjectPath &path)
+{
+ QMutexLocker locker(&mutex);
+
+ delete wirelessDevices.value(path.path());
+}
+
+void QNetworkManagerEngine::newConnection(const QDBusObjectPath &path,
+ QNetworkManagerSettings *settings)
+{
+ QMutexLocker locker(&mutex);
+
+ if (!settings)
+ settings = qobject_cast<QNetworkManagerSettings *>(sender());
+
+ if (!settings)
+ return;
+
+ QNetworkManagerSettingsConnection *connection =
+ new QNetworkManagerSettingsConnection(settings->connectionInterface()->service(),
+ path.path());
+ connections.append(connection);
+
+ connect(connection, SIGNAL(removed(QString)), this, SLOT(removeConnection(QString)));
+ connect(connection, SIGNAL(updated(const QNmSettingsMap&)),
+ this, SLOT(updateConnection(const QNmSettingsMap&)));
+
+ const QString service = connection->connectionInterface()->service();
+ const QString settingsPath = connection->connectionInterface()->path();
+
+ QNetworkConfigurationPrivate *cpPriv =
+ parseConnection(service, settingsPath, connection->getSettings());
+
+ // Check if connection is active.
+ foreach (const QDBusObjectPath &acPath, interface->activeConnections()) {
+ QNetworkManagerConnectionActive activeConnection(acPath.path());
+
+ if (activeConnection.serviceName() == service &&
+ activeConnection.connection().path() == settingsPath &&
+ activeConnection.state() == 2) {
+ cpPriv->state |= QNetworkConfiguration::Active;
+ break;
+ }
+ }
+
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ accessPointConfigurations.insert(ptr->id, ptr);
+ emit configurationAdded(ptr);
+}
+
+void QNetworkManagerEngine::removeConnection(const QString &path)
+{
+ QMutexLocker locker(&mutex);
+
+ Q_UNUSED(path)
+
+ QNetworkManagerSettingsConnection *connection =
+ qobject_cast<QNetworkManagerSettingsConnection *>(sender());
+ if (!connection)
+ return;
+
+ connections.removeAll(connection);
+
+ const QString id = QString::number(qHash(connection->connectionInterface()->service() + ' ' +
+ connection->connectionInterface()->path()));
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(id);
+ ptr->isValid = false;
+ emit configurationRemoved(ptr);
+}
+
+void QNetworkManagerEngine::updateConnection(const QNmSettingsMap &settings)
+{
+ QMutexLocker locker(&mutex);
+
+ QNetworkManagerSettingsConnection *connection =
+ qobject_cast<QNetworkManagerSettingsConnection *>(sender());
+ if (!connection)
+ return;
+
+ const QString service = connection->connectionInterface()->service();
+ const QString settingsPath = connection->connectionInterface()->path();
+
+ QNetworkConfigurationPrivate *cpPriv = parseConnection(service, settingsPath, settings);
+
+ // Check if connection is active.
+ foreach (const QDBusObjectPath &acPath, interface->activeConnections()) {
+ QNetworkManagerConnectionActive activeConnection(acPath.path());
+
+ if (activeConnection.serviceName() == service &&
+ activeConnection.connection().path() == settingsPath &&
+ activeConnection.state() == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
+ cpPriv->state |= QNetworkConfiguration::Active;
+ break;
+ }
+ }
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(cpPriv->id);
+
+ ptr->isValid = cpPriv->isValid;
+ ptr->name = cpPriv->name;
+ ptr->id = cpPriv->id;
+ ptr->state = cpPriv->state;
+
+ emit configurationChanged(ptr);
+ delete cpPriv;
+}
+
+void QNetworkManagerEngine::activationFinished(QDBusPendingCallWatcher *watcher)
+{
+ QMutexLocker locker(&mutex);
+
+ QDBusPendingReply<QDBusObjectPath> reply = *watcher;
+ if (!reply.isError()) {
+ QDBusObjectPath result = reply.value();
+
+ QNetworkManagerConnectionActive activeConnection(result.path());
+
+ const QString id = QString::number(qHash(activeConnection.serviceName() + ' ' +
+ activeConnection.connection().path()));
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+ if (ptr) {
+ if (activeConnection.state() == 2 &&
+ ptr->state != QNetworkConfiguration::Active) {
+ ptr->state = QNetworkConfiguration::Active;
+ emit configurationChanged(ptr);
+ }
+ }
+ }
+}
+
+void QNetworkManagerEngine::newAccessPoint(const QString &path, const QDBusObjectPath &objectPath)
+{
+ QMutexLocker locker(&mutex);
+
+ Q_UNUSED(path)
+
+ QNetworkManagerInterfaceAccessPoint *accessPoint =
+ new QNetworkManagerInterfaceAccessPoint(objectPath.path());
+ accessPoints.append(accessPoint);
+
+ accessPoint->setConnections();
+ connect(accessPoint, SIGNAL(propertiesChanged(QMap<QString,QVariant>)),
+ this, SLOT(updateAccessPoint(QMap<QString,QVariant>)));
+
+ // Check if configuration for this SSID already exists.
+ for (int i = 0; i < accessPoints.count(); ++i) {
+ if (accessPoint != accessPoints.at(i) &&
+ accessPoint->ssid() == accessPoints.at(i)->ssid()) {
+ return;
+ }
+ }
+
+ // Check if configuration exists for connection.
+ if (!accessPoint->ssid().isEmpty()) {
+ for (int i = 0; i < connections.count(); ++i) {
+ QNetworkManagerSettingsConnection *connection = connections.at(i);
+
+ if (accessPoint->ssid() == connection->getSsid()) {
+ const QString service = connection->connectionInterface()->service();
+ const QString settingsPath = connection->connectionInterface()->path();
+ const QString connectionId = QString::number(qHash(service + ' ' + settingsPath));
+
+ QNetworkConfigurationPrivatePointer ptr =
+ accessPointConfigurations.value(connectionId);
+ ptr->state = QNetworkConfiguration::Discovered;
+ emit configurationChanged(ptr);
+ return;
+ }
+ }
+ }
+
+ // New access point.
+ QNetworkConfigurationPrivatePointer ptr(new QNetworkConfigurationPrivate);
+
+ ptr->name = accessPoint->ssid();
+ ptr->isValid = true;
+ ptr->id = QString::number(qHash(objectPath.path()));
+ ptr->type = QNetworkConfiguration::InternetAccessPoint;
+ ptr->purpose = QNetworkConfiguration::PublicPurpose;
+ ptr->state = QNetworkConfiguration::Undefined;
+ ptr->bearer = QLatin1String("WLAN");
+
+ accessPointConfigurations.insert(ptr->id, ptr);
+ emit configurationAdded(ptr);
+}
+
+void QNetworkManagerEngine::removeAccessPoint(const QString &path,
+ const QDBusObjectPath &objectPath)
+{
+ QMutexLocker locker(&mutex);
+
+ Q_UNUSED(path)
+
+ for (int i = 0; i < accessPoints.count(); ++i) {
+ QNetworkManagerInterfaceAccessPoint *accessPoint = accessPoints.at(i);
+
+ if (accessPoint->connectionInterface()->path() == objectPath.path()) {
+ accessPoints.removeOne(accessPoint);
+
+ if (configuredAccessPoints.contains(accessPoint)) {
+ // find connection and change state to Defined
+ configuredAccessPoints.removeOne(accessPoint);
+ for (int i = 0; i < connections.count(); ++i) {
+ QNetworkManagerSettingsConnection *connection = connections.at(i);
+
+ if (accessPoint->ssid() == connection->getSsid()) {
+ const QString service = connection->connectionInterface()->service();
+ const QString settingsPath = connection->connectionInterface()->path();
+ const QString connectionId =
+ QString::number(qHash(service + ' ' + settingsPath));
+
+ QNetworkConfigurationPrivatePointer ptr =
+ accessPointConfigurations.value(connectionId);
+ ptr->state = QNetworkConfiguration::Defined;
+ emit configurationChanged(ptr);
+ return;
+ }
+ }
+ } else {
+ QNetworkConfigurationPrivatePointer ptr =
+ accessPointConfigurations.take(QString::number(qHash(objectPath.path())));
+
+ if (ptr)
+ emit configurationRemoved(ptr);
+ }
+
+ delete accessPoint;
+
+ break;
+ }
+ }
+}
+
+void QNetworkManagerEngine::updateAccessPoint(const QMap<QString, QVariant> &map)
+{
+ QMutexLocker locker(&mutex);
+
+ Q_UNUSED(map)
+
+ QNetworkManagerInterfaceAccessPoint *accessPoint =
+ qobject_cast<QNetworkManagerInterfaceAccessPoint *>(sender());
+ if (!accessPoint)
+ return;
+
+ for (int i = 0; i < connections.count(); ++i) {
+ QNetworkManagerSettingsConnection *connection = connections.at(i);
+
+ if (accessPoint->ssid() == connection->getSsid()) {
+ const QString service = connection->connectionInterface()->service();
+ const QString settingsPath = connection->connectionInterface()->path();
+ const QString connectionId = QString::number(qHash(service + ' ' + settingsPath));
+
+ QNetworkConfigurationPrivatePointer ptr =
+ accessPointConfigurations.value(connectionId);
+ ptr->state = QNetworkConfiguration::Discovered;
+ emit configurationChanged(ptr);
+ return;
+ }
+ }
+}
+
+QNetworkConfigurationPrivate *QNetworkManagerEngine::parseConnection(const QString &service,
+ const QString &settingsPath,
+ const QNmSettingsMap &map)
+{
+ QMutexLocker locker(&mutex);
+
+ QNetworkConfigurationPrivate *cpPriv = new QNetworkConfigurationPrivate;
+ cpPriv->name = map.value("connection").value("id").toString();
+ cpPriv->isValid = true;
+ cpPriv->id = QString::number(qHash(service + ' ' + settingsPath));
+ cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
+
+ cpPriv->purpose = QNetworkConfiguration::PublicPurpose;
+
+ cpPriv->state = QNetworkConfiguration::Defined;
+
+ const QString connectionType = map.value("connection").value("type").toString();
+
+ if (connectionType == QLatin1String("802-3-ethernet")) {
+ cpPriv->bearer = QLatin1String("Ethernet");
+
+ foreach (const QDBusObjectPath &devicePath, interface->getDevices()) {
+ QNetworkManagerInterfaceDevice device(devicePath.path());
+ if (device.deviceType() == DEVICE_TYPE_802_3_ETHERNET) {
+ QNetworkManagerInterfaceDeviceWired wiredDevice(device.connectionInterface()->path());
+ if (wiredDevice.carrier()) {
+ cpPriv->state |= QNetworkConfiguration::Discovered;
+ break;
+ }
+
+ }
+ }
+ } else if (connectionType == QLatin1String("802-11-wireless")) {
+ cpPriv->bearer = QLatin1String("WLAN");
+
+ const QString connectionSsid = map.value("802-11-wireless").value("ssid").toString();
+
+ for (int i = 0; i < accessPoints.count(); ++i) {
+ if (connectionSsid == accessPoints.at(i)->ssid()) {
+ cpPriv->state |= QNetworkConfiguration::Discovered;
+ if (!configuredAccessPoints.contains(accessPoints.at(i))) {
+ configuredAccessPoints.append(accessPoints.at(i));
+
+ const QString accessPointId =
+ QString::number(qHash(accessPoints.at(i)->connectionInterface()->path()));
+ QNetworkConfigurationPrivatePointer ptr =
+ accessPointConfigurations.take(accessPointId);
+ emit configurationRemoved(ptr);
+ }
+ break;
+ }
+ }
+ } else if (connectionType == "gsm") {
+ cpPriv->bearer = QLatin1String("2G");
+ } else if (connectionType == "cdma") {
+ cpPriv->bearer = QLatin1String("CDMA2000");
+ }
+
+ return cpPriv;
+}
+
+QNetworkManagerSettingsConnection *QNetworkManagerEngine::connectionFromId(const QString &id) const
+{
+ QMutexLocker locker(&mutex);
+
+ for (int i = 0; i < connections.count(); ++i) {
+ QNetworkManagerSettingsConnection *connection = connections.at(i);
+ const QString service = connection->connectionInterface()->service();
+ const QString settingsPath = connection->connectionInterface()->path();
+
+ const QString identifier = QString::number(qHash(service + ' ' + settingsPath));
+
+ if (id == identifier)
+ return connection;
+ }
+
+ return 0;
+}
+
+QNetworkSession::State QNetworkManagerEngine::sessionStateForId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+
+ if (!ptr)
+ return QNetworkSession::Invalid;
+
+ if (!ptr->isValid)
+ return QNetworkSession::Invalid;
+
+ foreach (const QString &acPath, activeConnections.keys()) {
+ QNetworkManagerConnectionActive *activeConnection = activeConnections.value(acPath);
+
+ const QString identifier = QString::number(qHash(activeConnection->serviceName() + ' ' +
+ activeConnection->connection().path()));
+
+ if (id == identifier) {
+ switch (activeConnection->state()) {
+ case 0:
+ return QNetworkSession::Disconnected;
+ case 1:
+ return QNetworkSession::Connecting;
+ case 2:
+ return QNetworkSession::Connected;
+ }
+ }
+ }
+
+ if ((ptr->state & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered)
+ return QNetworkSession::Disconnected;
+ else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined)
+ return QNetworkSession::NotAvailable;
+ else if ((ptr->state & QNetworkConfiguration::Undefined) == QNetworkConfiguration::Undefined)
+ return QNetworkSession::NotAvailable;
+
+ return QNetworkSession::Invalid;
+}
+
+quint64 QNetworkManagerEngine::bytesWritten(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+ if (ptr && (ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ const QString networkInterface = getInterfaceFromId(id);
+ if (!networkInterface.isEmpty()) {
+ const QString devFile = QLatin1String("/sys/class/net/") +
+ networkInterface +
+ QLatin1String("/statistics/tx_bytes");
+
+ quint64 result = Q_UINT64_C(0);
+
+ QFile tx(devFile);
+ if (tx.exists() && tx.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ QTextStream in(&tx);
+ in >> result;
+ tx.close();
+ }
+
+ return result;
+ }
+ }
+
+ return Q_UINT64_C(0);
+}
+
+quint64 QNetworkManagerEngine::bytesReceived(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+ if (ptr && (ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ const QString networkInterface = getInterfaceFromId(id);
+ if (!networkInterface.isEmpty()) {
+ const QString devFile = QLatin1String("/sys/class/net/") +
+ networkInterface +
+ QLatin1String("/statistics/rx_bytes");
+
+ quint64 result = Q_UINT64_C(0);
+
+ QFile tx(devFile);
+ if (tx.exists() && tx.open(QIODevice::ReadOnly | QIODevice::Text)) {
+ QTextStream in(&tx);
+ in >> result;
+ tx.close();
+ }
+
+ return result;
+ }
+ }
+
+ return Q_UINT64_C(0);
+}
+
+quint64 QNetworkManagerEngine::startTime(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ QNetworkManagerSettingsConnection *connection = connectionFromId(id);
+ if (connection)
+ return connection->getTimestamp();
+ else
+ return Q_UINT64_C(0);
+}
+
+QNetworkConfigurationManager::Capabilities QNetworkManagerEngine::capabilities() const
+{
+ return QNetworkConfigurationManager::ForcedRoaming |
+ QNetworkConfigurationManager::CanStartAndStopInterfaces;
+}
+
+QNetworkSessionPrivate *QNetworkManagerEngine::createSessionBackend()
+{
+ return new QNetworkSessionPrivateImpl;
+}
+
+QNetworkConfigurationPrivatePointer QNetworkManagerEngine::defaultConfiguration()
+{
+ return QNetworkConfigurationPrivatePointer();
+}
+
+QT_END_NAMESPACE
+
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h
new file mode 100644
index 0000000..ca1f857
--- /dev/null
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerengine.h
@@ -0,0 +1,139 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNETWORKMANAGERENGINE_P_H
+#define QNETWORKMANAGERENGINE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of the QLibrary class. This header file may change from
+// version to version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "../qbearerengine_impl.h"
+
+#include "qnetworkmanagerservice.h"
+
+#include <QMap>
+#include <QVariant>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkManagerEngine : public QBearerEngineImpl
+{
+ Q_OBJECT
+
+public:
+ QNetworkManagerEngine(QObject *parent = 0);
+ ~QNetworkManagerEngine();
+
+ bool networkManagerAvailable() const;
+
+ QString getInterfaceFromId(const QString &id);
+ bool hasIdentifier(const QString &id);
+
+ QString bearerName(const QString &id);
+
+ void connectToId(const QString &id);
+ void disconnectFromId(const QString &id);
+
+ void requestUpdate();
+
+ QNetworkSession::State sessionStateForId(const QString &id);
+
+ quint64 bytesWritten(const QString &id);
+ quint64 bytesReceived(const QString &id);
+ quint64 startTime(const QString &id);
+
+ QNetworkConfigurationManager::Capabilities capabilities() const;
+
+ QNetworkSessionPrivate *createSessionBackend();
+
+ QNetworkConfigurationPrivatePointer defaultConfiguration();
+
+private Q_SLOTS:
+ void interfacePropertiesChanged(const QString &path,
+ const QMap<QString, QVariant> &properties);
+ void activeConnectionPropertiesChanged(const QString &path,
+ const QMap<QString, QVariant> &properties);
+ void devicePropertiesChanged(const QString &path,
+ const QMap<QString, QVariant> &properties);
+
+ void deviceAdded(const QDBusObjectPath &path);
+ void deviceRemoved(const QDBusObjectPath &path);
+
+ void newConnection(const QDBusObjectPath &path, QNetworkManagerSettings *settings = 0);
+ void removeConnection(const QString &path);
+ void updateConnection(const QNmSettingsMap &settings);
+ void activationFinished(QDBusPendingCallWatcher *watcher);
+
+ void newAccessPoint(const QString &path, const QDBusObjectPath &objectPath);
+ void removeAccessPoint(const QString &path, const QDBusObjectPath &objectPath);
+ void updateAccessPoint(const QMap<QString, QVariant> &map);
+
+ void doRequestUpdate();
+
+private:
+ QNetworkConfigurationPrivate *parseConnection(const QString &service,
+ const QString &settingsPath,
+ const QNmSettingsMap &map);
+ QNetworkManagerSettingsConnection *connectionFromId(const QString &id) const;
+
+private:
+ QNetworkManagerInterface *interface;
+ QNetworkManagerSettings *systemSettings;
+ QNetworkManagerSettings *userSettings;
+ QHash<QString, QNetworkManagerInterfaceDeviceWireless *> wirelessDevices;
+ QHash<QString, QNetworkManagerConnectionActive *> activeConnections;
+ QList<QNetworkManagerSettingsConnection *> connections;
+ QList<QNetworkManagerInterfaceAccessPoint *> accessPoints;
+ QList<QNetworkManagerInterfaceAccessPoint *> configuredAccessPoints;
+};
+
+QT_END_NAMESPACE
+
+#endif
+
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp
new file mode 100644
index 0000000..5dc0ea4
--- /dev/null
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.cpp
@@ -0,0 +1,1046 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <QObject>
+#include <QList>
+#include <QtDBus>
+#include <QDBusConnection>
+#include <QDBusError>
+#include <QDBusInterface>
+#include <QDBusMessage>
+#include <QDBusReply>
+#include <QDBusPendingCallWatcher>
+#include <QDBusObjectPath>
+#include <QDBusPendingCall>
+
+#include <NetworkManager/NetworkManager.h>
+
+#include "qnmdbushelper.h"
+#include "qnetworkmanagerservice.h"
+
+//Q_DECLARE_METATYPE(QList<uint>)
+QT_BEGIN_NAMESPACE
+
+static QDBusConnection dbusConnection = QDBusConnection::systemBus();
+//static QDBusInterface iface(NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, dbusConnection);
+
+class QNetworkManagerInterfacePrivate
+{
+public:
+ QDBusInterface *connectionInterface;
+ bool valid;
+};
+
+QNetworkManagerInterface::QNetworkManagerInterface(QObject *parent)
+ : QObject(parent), nmDBusHelper(0)
+{
+ d = new QNetworkManagerInterfacePrivate();
+ d->connectionInterface = new QDBusInterface(NM_DBUS_SERVICE,
+ NM_DBUS_PATH,
+ NM_DBUS_INTERFACE,
+ dbusConnection);
+ if (!d->connectionInterface->isValid()) {
+ d->valid = false;
+ return;
+ }
+ d->valid = true;
+ nmDBusHelper = new QNmDBusHelper;
+ connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(const QString &,QMap<QString,QVariant>)),
+ this,SIGNAL(propertiesChanged( const QString &, QMap<QString,QVariant>)));
+ connect(nmDBusHelper,SIGNAL(pathForStateChanged(const QString &, quint32)),
+ this, SIGNAL(stateChanged(const QString&, quint32)));
+
+}
+
+QNetworkManagerInterface::~QNetworkManagerInterface()
+{
+ if (nmDBusHelper)
+ delete nmDBusHelper;
+ delete d->connectionInterface;
+ delete d;
+}
+
+bool QNetworkManagerInterface::isValid()
+{
+ return d->valid;
+}
+
+bool QNetworkManagerInterface::setConnections()
+{
+ if(!isValid() )
+ return false;
+ bool allOk = false;
+ if (!dbusConnection.connect(NM_DBUS_SERVICE,
+ NM_DBUS_PATH,
+ NM_DBUS_INTERFACE,
+ "PropertiesChanged",
+ nmDBusHelper,SLOT(slotPropertiesChanged( QMap<QString,QVariant>)))) {
+ allOk = true;
+ }
+ if (!dbusConnection.connect(NM_DBUS_SERVICE,
+ NM_DBUS_PATH,
+ NM_DBUS_INTERFACE,
+ "DeviceAdded",
+ this,SIGNAL(deviceAdded(QDBusObjectPath)))) {
+ allOk = true;
+ }
+ if (!dbusConnection.connect(NM_DBUS_SERVICE,
+ NM_DBUS_PATH,
+ NM_DBUS_INTERFACE,
+ "DeviceRemoved",
+ this,SIGNAL(deviceRemoved(QDBusObjectPath)))) {
+ allOk = true;
+ }
+
+ return allOk;
+}
+
+QDBusInterface *QNetworkManagerInterface::connectionInterface() const
+{
+ return d->connectionInterface;
+}
+
+QList <QDBusObjectPath> QNetworkManagerInterface::getDevices() const
+{
+ QDBusReply<QList<QDBusObjectPath> > reply = d->connectionInterface->call("GetDevices");
+ return reply.value();
+}
+
+void QNetworkManagerInterface::activateConnection( const QString &serviceName,
+ QDBusObjectPath connectionPath,
+ QDBusObjectPath devicePath,
+ QDBusObjectPath specificObject)
+{
+ QDBusPendingCall pendingCall = d->connectionInterface->asyncCall("ActivateConnection",
+ QVariant(serviceName),
+ QVariant::fromValue(connectionPath),
+ QVariant::fromValue(devicePath),
+ QVariant::fromValue(specificObject));
+
+ QDBusPendingCallWatcher *callWatcher = new QDBusPendingCallWatcher(pendingCall, this);
+ connect(callWatcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
+ this, SIGNAL(activationFinished(QDBusPendingCallWatcher*)));
+}
+
+void QNetworkManagerInterface::deactivateConnection(QDBusObjectPath connectionPath) const
+{
+ d->connectionInterface->call("DeactivateConnection", QVariant::fromValue(connectionPath));
+}
+
+bool QNetworkManagerInterface::wirelessEnabled() const
+{
+ return d->connectionInterface->property("WirelessEnabled").toBool();
+}
+
+bool QNetworkManagerInterface::wirelessHardwareEnabled() const
+{
+ return d->connectionInterface->property("WirelessHardwareEnabled").toBool();
+}
+
+QList <QDBusObjectPath> QNetworkManagerInterface::activeConnections() const
+{
+ QVariant prop = d->connectionInterface->property("ActiveConnections");
+ return prop.value<QList<QDBusObjectPath> >();
+}
+
+quint32 QNetworkManagerInterface::state()
+{
+ return d->connectionInterface->property("State").toUInt();
+}
+
+/////////////
+class QNetworkManagerInterfaceAccessPointPrivate
+{
+public:
+ QDBusInterface *connectionInterface;
+ QString path;
+ bool valid;
+};
+
+QNetworkManagerInterfaceAccessPoint::QNetworkManagerInterfaceAccessPoint(const QString &dbusPathName, QObject *parent)
+ : QObject(parent), nmDBusHelper(0)
+{
+ d = new QNetworkManagerInterfaceAccessPointPrivate();
+ d->path = dbusPathName;
+ d->connectionInterface = new QDBusInterface(NM_DBUS_SERVICE,
+ d->path,
+ NM_DBUS_INTERFACE_ACCESS_POINT,
+ dbusConnection);
+ if (!d->connectionInterface->isValid()) {
+ d->valid = false;
+ qWarning() << "Could not find InterfaceAccessPoint";
+ return;
+ }
+ d->valid = true;
+
+}
+
+QNetworkManagerInterfaceAccessPoint::~QNetworkManagerInterfaceAccessPoint()
+{
+ if (nmDBusHelper)
+ delete nmDBusHelper;
+ delete d->connectionInterface;
+ delete d;
+}
+
+bool QNetworkManagerInterfaceAccessPoint::isValid()
+{
+ return d->valid;
+}
+
+bool QNetworkManagerInterfaceAccessPoint::setConnections()
+{
+ if(!isValid() )
+ return false;
+
+ bool allOk = false;
+ if (nmDBusHelper)
+ delete nmDBusHelper;
+ nmDBusHelper = 0;
+ nmDBusHelper = new QNmDBusHelper;
+ connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(const QString &,QMap<QString,QVariant>)),
+ this,SIGNAL(propertiesChanged( const QString &, QMap<QString,QVariant>)));
+
+ if(dbusConnection.connect(NM_DBUS_SERVICE,
+ d->path,
+ NM_DBUS_INTERFACE_ACCESS_POINT,
+ "PropertiesChanged",
+ nmDBusHelper,SLOT(slotPropertiesChanged( QMap<QString,QVariant>))) ) {
+ allOk = true;
+
+ }
+ return allOk;
+}
+
+QDBusInterface *QNetworkManagerInterfaceAccessPoint::connectionInterface() const
+{
+ return d->connectionInterface;
+}
+
+quint32 QNetworkManagerInterfaceAccessPoint::flags() const
+{
+ return d->connectionInterface->property("Flags").toUInt();
+}
+
+quint32 QNetworkManagerInterfaceAccessPoint::wpaFlags() const
+{
+ return d->connectionInterface->property("WpaFlags").toUInt();
+}
+
+quint32 QNetworkManagerInterfaceAccessPoint::rsnFlags() const
+{
+ return d->connectionInterface->property("RsnFlags").toUInt();
+}
+
+QString QNetworkManagerInterfaceAccessPoint::ssid() const
+{
+ return d->connectionInterface->property("Ssid").toString();
+}
+
+quint32 QNetworkManagerInterfaceAccessPoint::frequency() const
+{
+ return d->connectionInterface->property("Frequency").toUInt();
+}
+
+QString QNetworkManagerInterfaceAccessPoint::hwAddress() const
+{
+ return d->connectionInterface->property("HwAddress").toString();
+}
+
+quint32 QNetworkManagerInterfaceAccessPoint::mode() const
+{
+ return d->connectionInterface->property("Mode").toUInt();
+}
+
+quint32 QNetworkManagerInterfaceAccessPoint::maxBitrate() const
+{
+ return d->connectionInterface->property("MaxBitrate").toUInt();
+}
+
+quint32 QNetworkManagerInterfaceAccessPoint::strength() const
+{
+ return d->connectionInterface->property("Strength").toUInt();
+}
+
+/////////////
+class QNetworkManagerInterfaceDevicePrivate
+{
+public:
+ QDBusInterface *connectionInterface;
+ QString path;
+ bool valid;
+};
+
+QNetworkManagerInterfaceDevice::QNetworkManagerInterfaceDevice(const QString &deviceObjectPath, QObject *parent)
+ : QObject(parent), nmDBusHelper(0)
+{
+ d = new QNetworkManagerInterfaceDevicePrivate();
+ d->path = deviceObjectPath;
+ d->connectionInterface = new QDBusInterface(NM_DBUS_SERVICE,
+ d->path,
+ NM_DBUS_INTERFACE_DEVICE,
+ dbusConnection);
+ if (!d->connectionInterface->isValid()) {
+ d->valid = false;
+ qWarning() << "Could not find NetworkManagerInterfaceDevice";
+ return;
+ }
+ d->valid = true;
+}
+
+QNetworkManagerInterfaceDevice::~QNetworkManagerInterfaceDevice()
+{
+ if (nmDBusHelper)
+ delete nmDBusHelper;
+ delete d->connectionInterface;
+ delete d;
+}
+
+bool QNetworkManagerInterfaceDevice::isValid()
+{
+ return d->valid;
+}
+
+bool QNetworkManagerInterfaceDevice::setConnections()
+{
+ if(!isValid() )
+ return false;
+
+ bool allOk = false;
+ if (nmDBusHelper)
+ delete nmDBusHelper;
+ nmDBusHelper = 0;
+ nmDBusHelper = new QNmDBusHelper;
+ connect(nmDBusHelper,SIGNAL(pathForStateChanged(const QString &, quint32)),
+ this, SIGNAL(stateChanged(const QString&, quint32)));
+ if(dbusConnection.connect(NM_DBUS_SERVICE,
+ d->path,
+ NM_DBUS_INTERFACE_DEVICE,
+ "StateChanged",
+ nmDBusHelper,SLOT(deviceStateChanged(quint32)))) {
+ allOk = true;
+ }
+ return allOk;
+}
+
+QDBusInterface *QNetworkManagerInterfaceDevice::connectionInterface() const
+{
+ return d->connectionInterface;
+}
+
+QString QNetworkManagerInterfaceDevice::udi() const
+{
+ return d->connectionInterface->property("Udi").toString();
+}
+
+QNetworkInterface QNetworkManagerInterfaceDevice::interface() const
+{
+ return QNetworkInterface::interfaceFromName(d->connectionInterface->property("Interface").toString());
+}
+
+quint32 QNetworkManagerInterfaceDevice::ip4Address() const
+{
+ return d->connectionInterface->property("Ip4Address").toUInt();
+}
+
+quint32 QNetworkManagerInterfaceDevice::state() const
+{
+ return d->connectionInterface->property("State").toUInt();
+}
+
+quint32 QNetworkManagerInterfaceDevice::deviceType() const
+{
+ return d->connectionInterface->property("DeviceType").toUInt();
+}
+
+QDBusObjectPath QNetworkManagerInterfaceDevice::ip4config() const
+{
+ QVariant prop = d->connectionInterface->property("Ip4Config");
+ return prop.value<QDBusObjectPath>();
+}
+
+/////////////
+class QNetworkManagerInterfaceDeviceWiredPrivate
+{
+public:
+ QDBusInterface *connectionInterface;
+ QString path;
+ bool valid;
+};
+
+QNetworkManagerInterfaceDeviceWired::QNetworkManagerInterfaceDeviceWired(const QString &ifaceDevicePath, QObject *parent)
+ : QObject(parent), nmDBusHelper(0)
+{
+ d = new QNetworkManagerInterfaceDeviceWiredPrivate();
+ d->path = ifaceDevicePath;
+ d->connectionInterface = new QDBusInterface(NM_DBUS_SERVICE,
+ d->path,
+ NM_DBUS_INTERFACE_DEVICE_WIRED,
+ dbusConnection, parent);
+ if (!d->connectionInterface->isValid()) {
+ d->valid = false;
+ qWarning() << "Could not find InterfaceDeviceWired";
+ return;
+ }
+ d->valid = true;
+}
+
+QNetworkManagerInterfaceDeviceWired::~QNetworkManagerInterfaceDeviceWired()
+{
+ if (nmDBusHelper)
+ delete nmDBusHelper;
+ delete d->connectionInterface;
+ delete d;
+}
+
+bool QNetworkManagerInterfaceDeviceWired::isValid()
+{
+
+ return d->valid;
+}
+
+bool QNetworkManagerInterfaceDeviceWired::setConnections()
+{
+ if(!isValid() )
+ return false;
+
+ bool allOk = false;
+
+ if (nmDBusHelper)
+ delete nmDBusHelper;
+ nmDBusHelper = 0;
+ nmDBusHelper = new QNmDBusHelper;
+ connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(const QString &,QMap<QString,QVariant>)),
+ this,SIGNAL(propertiesChanged( const QString &, QMap<QString,QVariant>)));
+ if(dbusConnection.connect(NM_DBUS_SERVICE,
+ d->path,
+ NM_DBUS_INTERFACE_DEVICE_WIRED,
+ "PropertiesChanged",
+ nmDBusHelper,SLOT(slotPropertiesChanged( QMap<QString,QVariant>))) ) {
+ allOk = true;
+ }
+ return allOk;
+}
+
+QDBusInterface *QNetworkManagerInterfaceDeviceWired::connectionInterface() const
+{
+ return d->connectionInterface;
+}
+
+QString QNetworkManagerInterfaceDeviceWired::hwAddress() const
+{
+ return d->connectionInterface->property("HwAddress").toString();
+}
+
+quint32 QNetworkManagerInterfaceDeviceWired::speed() const
+{
+ return d->connectionInterface->property("Speed").toUInt();
+}
+
+bool QNetworkManagerInterfaceDeviceWired::carrier() const
+{
+ return d->connectionInterface->property("Carrier").toBool();
+}
+
+/////////////
+class QNetworkManagerInterfaceDeviceWirelessPrivate
+{
+public:
+ QDBusInterface *connectionInterface;
+ QString path;
+ bool valid;
+};
+
+QNetworkManagerInterfaceDeviceWireless::QNetworkManagerInterfaceDeviceWireless(const QString &ifaceDevicePath, QObject *parent)
+ : QObject(parent), nmDBusHelper(0)
+{
+ d = new QNetworkManagerInterfaceDeviceWirelessPrivate();
+ d->path = ifaceDevicePath;
+ d->connectionInterface = new QDBusInterface(NM_DBUS_SERVICE,
+ d->path,
+ NM_DBUS_INTERFACE_DEVICE_WIRELESS,
+ dbusConnection, parent);
+ if (!d->connectionInterface->isValid()) {
+ d->valid = false;
+ qWarning() << "Could not find InterfaceDeviceWireless";
+ return;
+ }
+ d->valid = true;
+}
+
+QNetworkManagerInterfaceDeviceWireless::~QNetworkManagerInterfaceDeviceWireless()
+{
+ if (nmDBusHelper)
+ delete nmDBusHelper;
+ delete d->connectionInterface;
+ delete d;
+}
+
+bool QNetworkManagerInterfaceDeviceWireless::isValid()
+{
+ return d->valid;
+}
+
+bool QNetworkManagerInterfaceDeviceWireless::setConnections()
+{
+ if(!isValid() )
+ return false;
+
+ bool allOk = false;
+ if (nmDBusHelper)
+ delete nmDBusHelper;
+ nmDBusHelper = 0;
+ nmDBusHelper = new QNmDBusHelper;
+ connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(const QString &,QMap<QString,QVariant>)),
+ this,SIGNAL(propertiesChanged( const QString &, QMap<QString,QVariant>)));
+
+ connect(nmDBusHelper, SIGNAL(pathForAccessPointAdded(const QString &,QDBusObjectPath)),
+ this,SIGNAL(accessPointAdded(const QString &,QDBusObjectPath)));
+
+ connect(nmDBusHelper, SIGNAL(pathForAccessPointRemoved(const QString &,QDBusObjectPath)),
+ this,SIGNAL(accessPointRemoved(const QString &,QDBusObjectPath)));
+
+ if(!dbusConnection.connect(NM_DBUS_SERVICE,
+ d->path,
+ NM_DBUS_INTERFACE_DEVICE_WIRELESS,
+ "AccessPointAdded",
+ nmDBusHelper, SLOT(slotAccessPointAdded( QDBusObjectPath )))) {
+ allOk = true;
+ }
+
+
+ if(!dbusConnection.connect(NM_DBUS_SERVICE,
+ d->path,
+ NM_DBUS_INTERFACE_DEVICE_WIRELESS,
+ "AccessPointRemoved",
+ nmDBusHelper, SLOT(slotAccessPointRemoved( QDBusObjectPath )))) {
+ allOk = true;
+ }
+
+
+ if(!dbusConnection.connect(NM_DBUS_SERVICE,
+ d->path,
+ NM_DBUS_INTERFACE_DEVICE_WIRELESS,
+ "PropertiesChanged",
+ nmDBusHelper,SLOT(slotPropertiesChanged( QMap<QString,QVariant>)))) {
+ allOk = true;
+ }
+
+ return allOk;
+}
+
+QDBusInterface *QNetworkManagerInterfaceDeviceWireless::connectionInterface() const
+{
+ return d->connectionInterface;
+}
+
+QList <QDBusObjectPath> QNetworkManagerInterfaceDeviceWireless::getAccessPoints()
+{
+ QDBusReply<QList<QDBusObjectPath> > reply = d->connectionInterface->call("GetAccessPoints");
+ return reply.value();
+}
+
+QString QNetworkManagerInterfaceDeviceWireless::hwAddress() const
+{
+ return d->connectionInterface->property("HwAddress").toString();
+}
+
+quint32 QNetworkManagerInterfaceDeviceWireless::mode() const
+{
+ return d->connectionInterface->property("Mode").toUInt();
+}
+
+quint32 QNetworkManagerInterfaceDeviceWireless::bitrate() const
+{
+ return d->connectionInterface->property("Bitrate").toUInt();
+}
+
+QDBusObjectPath QNetworkManagerInterfaceDeviceWireless::activeAccessPoint() const
+{
+ return d->connectionInterface->property("ActiveAccessPoint").value<QDBusObjectPath>();
+}
+
+quint32 QNetworkManagerInterfaceDeviceWireless::wirelessCapabilities() const
+{
+ return d->connectionInterface->property("WirelelessCapabilities").toUInt();
+}
+
+/////////////
+class QNetworkManagerSettingsPrivate
+{
+public:
+ QDBusInterface *connectionInterface;
+ QString path;
+ bool valid;
+};
+
+QNetworkManagerSettings::QNetworkManagerSettings(const QString &settingsService, QObject *parent)
+ : QObject(parent)
+{
+ d = new QNetworkManagerSettingsPrivate();
+ d->path = settingsService;
+ d->connectionInterface = new QDBusInterface(settingsService,
+ NM_DBUS_PATH_SETTINGS,
+ NM_DBUS_IFACE_SETTINGS,
+ dbusConnection);
+ if (!d->connectionInterface->isValid()) {
+ d->valid = false;
+ //qWarning() << "Could not find NetworkManagerSettings";
+ return;
+ }
+ d->valid = true;
+}
+
+QNetworkManagerSettings::~QNetworkManagerSettings()
+{
+ delete d->connectionInterface;
+ delete d;
+}
+
+bool QNetworkManagerSettings::isValid()
+{
+ return d->valid;
+}
+
+bool QNetworkManagerSettings::setConnections()
+{
+ bool allOk = false;
+
+ if (!dbusConnection.connect(d->path, NM_DBUS_PATH_SETTINGS,
+ NM_DBUS_IFACE_SETTINGS, "NewConnection",
+ this, SIGNAL(newConnection(QDBusObjectPath)))) {
+ allOk = true;
+ }
+
+ return allOk;
+}
+
+QList <QDBusObjectPath> QNetworkManagerSettings::listConnections()
+{
+ QDBusReply<QList<QDBusObjectPath> > reply = d->connectionInterface->call("ListConnections");
+ return reply.value();
+}
+
+QDBusInterface *QNetworkManagerSettings::connectionInterface() const
+{
+ return d->connectionInterface;
+}
+
+
+/////////////
+class QNetworkManagerSettingsConnectionPrivate
+{
+public:
+ QDBusInterface *connectionInterface;
+ QString path;
+ QString service;
+ QNmSettingsMap settingsMap;
+ bool valid;
+};
+
+QNetworkManagerSettingsConnection::QNetworkManagerSettingsConnection(const QString &settingsService, const QString &connectionObjectPath, QObject *parent)
+ : QObject(parent), nmDBusHelper(0)
+{
+ qDBusRegisterMetaType<QNmSettingsMap>();
+ d = new QNetworkManagerSettingsConnectionPrivate();
+ d->path = connectionObjectPath;
+ d->service = settingsService;
+ d->connectionInterface = new QDBusInterface(settingsService,
+ d->path,
+ NM_DBUS_IFACE_SETTINGS_CONNECTION,
+ dbusConnection, parent);
+ if (!d->connectionInterface->isValid()) {
+ //qWarning() << "Could not find NetworkManagerSettingsConnection";
+ d->valid = false;
+ return;
+ }
+ d->valid = true;
+ QDBusReply< QNmSettingsMap > rep = d->connectionInterface->call("GetSettings");
+ d->settingsMap = rep.value();
+}
+
+QNetworkManagerSettingsConnection::~QNetworkManagerSettingsConnection()
+{
+ if (nmDBusHelper)
+ delete nmDBusHelper;
+ delete d->connectionInterface;
+ delete d;
+}
+
+bool QNetworkManagerSettingsConnection::isValid()
+{
+ return d->valid;
+}
+
+bool QNetworkManagerSettingsConnection::setConnections()
+{
+ if(!isValid() )
+ return false;
+
+ bool allOk = false;
+ if(!dbusConnection.connect(d->service, d->path,
+ NM_DBUS_IFACE_SETTINGS_CONNECTION, "Updated",
+ this, SIGNAL(updated(QNmSettingsMap)))) {
+ allOk = true;
+ } else {
+ QDBusError error = dbusConnection.lastError();
+ }
+
+ if (nmDBusHelper)
+ delete nmDBusHelper;
+ nmDBusHelper = 0;
+ nmDBusHelper = new QNmDBusHelper;
+ connect(nmDBusHelper, SIGNAL(pathForSettingsRemoved(const QString &)),
+ this,SIGNAL(removed( const QString &)));
+
+ if (!dbusConnection.connect(d->service, d->path,
+ NM_DBUS_IFACE_SETTINGS_CONNECTION, "Removed",
+ nmDBusHelper, SIGNAL(slotSettingsRemoved()))) {
+ allOk = true;
+ }
+
+ return allOk;
+}
+//QNetworkManagerSettingsConnection::update(QNmSettingsMap map)
+//{
+// d->connectionInterface->call("Update", QVariant::fromValue(map));
+//}
+
+QDBusInterface *QNetworkManagerSettingsConnection::connectionInterface() const
+{
+ return d->connectionInterface;
+}
+
+QNmSettingsMap QNetworkManagerSettingsConnection::getSettings()
+{
+ QDBusReply< QNmSettingsMap > rep = d->connectionInterface->call("GetSettings");
+ d->settingsMap = rep.value();
+ return d->settingsMap;
+}
+
+NMDeviceType QNetworkManagerSettingsConnection::getType()
+{
+ QNmSettingsMap::const_iterator i = d->settingsMap.find("connection");
+ while (i != d->settingsMap.end() && i.key() == "connection") {
+ QMap<QString,QVariant> innerMap = i.value();
+ QMap<QString,QVariant>::const_iterator ii = innerMap.find("type");
+ while (ii != innerMap.end() && ii.key() == "type") {
+ QString devType = ii.value().toString();
+ if (devType == "802-3-ethernet") {
+ return DEVICE_TYPE_802_3_ETHERNET;
+ }
+ if (devType == "802-11-wireless") {
+ return DEVICE_TYPE_802_11_WIRELESS;
+ }
+ ii++;
+ }
+ i++;
+ }
+ return DEVICE_TYPE_UNKNOWN;
+}
+
+bool QNetworkManagerSettingsConnection::isAutoConnect()
+{
+ QNmSettingsMap::const_iterator i = d->settingsMap.find("connection");
+ while (i != d->settingsMap.end() && i.key() == "connection") {
+ QMap<QString,QVariant> innerMap = i.value();
+ QMap<QString,QVariant>::const_iterator ii = innerMap.find("autoconnect");
+ while (ii != innerMap.end() && ii.key() == "autoconnect") {
+ return ii.value().toBool();
+ ii++;
+ }
+ i++;
+ }
+ return true; //default networkmanager is autoconnect
+}
+
+quint64 QNetworkManagerSettingsConnection::getTimestamp()
+{
+ QNmSettingsMap::const_iterator i = d->settingsMap.find("connection");
+ while (i != d->settingsMap.end() && i.key() == "connection") {
+ QMap<QString,QVariant> innerMap = i.value();
+ QMap<QString,QVariant>::const_iterator ii = innerMap.find("timestamp");
+ while (ii != innerMap.end() && ii.key() == "timestamp") {
+ return ii.value().toUInt();
+ ii++;
+ }
+ i++;
+ }
+ return 0;
+}
+
+QString QNetworkManagerSettingsConnection::getId()
+{
+ QNmSettingsMap::const_iterator i = d->settingsMap.find("connection");
+ while (i != d->settingsMap.end() && i.key() == "connection") {
+ QMap<QString,QVariant> innerMap = i.value();
+ QMap<QString,QVariant>::const_iterator ii = innerMap.find("id");
+ while (ii != innerMap.end() && ii.key() == "id") {
+ return ii.value().toString();
+ ii++;
+ }
+ i++;
+ }
+ return QString();
+}
+
+QString QNetworkManagerSettingsConnection::getUuid()
+{
+ QNmSettingsMap::const_iterator i = d->settingsMap.find("connection");
+ while (i != d->settingsMap.end() && i.key() == "connection") {
+ QMap<QString,QVariant> innerMap = i.value();
+ QMap<QString,QVariant>::const_iterator ii = innerMap.find("uuid");
+ while (ii != innerMap.end() && ii.key() == "uuid") {
+ return ii.value().toString();
+ ii++;
+ }
+ i++;
+ }
+ // is no uuid, return the connection path
+ return d->connectionInterface->path();
+}
+
+QString QNetworkManagerSettingsConnection::getSsid()
+{
+ QNmSettingsMap::const_iterator i = d->settingsMap.find("802-11-wireless");
+ while (i != d->settingsMap.end() && i.key() == "802-11-wireless") {
+ QMap<QString,QVariant> innerMap = i.value();
+ QMap<QString,QVariant>::const_iterator ii = innerMap.find("ssid");
+ while (ii != innerMap.end() && ii.key() == "ssid") {
+ return ii.value().toString();
+ ii++;
+ }
+ i++;
+ }
+ return QString();
+}
+
+QString QNetworkManagerSettingsConnection::getMacAddress()
+{
+ if(getType() == DEVICE_TYPE_802_3_ETHERNET) {
+ QNmSettingsMap::const_iterator i = d->settingsMap.find("802-3-ethernet");
+ while (i != d->settingsMap.end() && i.key() == "802-3-ethernet") {
+ QMap<QString,QVariant> innerMap = i.value();
+ QMap<QString,QVariant>::const_iterator ii = innerMap.find("mac-address");
+ while (ii != innerMap.end() && ii.key() == "mac-address") {
+ return ii.value().toString();
+ ii++;
+ }
+ i++;
+ }
+ }
+
+ else if(getType() == DEVICE_TYPE_802_11_WIRELESS) {
+ QNmSettingsMap::const_iterator i = d->settingsMap.find("802-11-wireless");
+ while (i != d->settingsMap.end() && i.key() == "802-11-wireless") {
+ QMap<QString,QVariant> innerMap = i.value();
+ QMap<QString,QVariant>::const_iterator ii = innerMap.find("mac-address");
+ while (ii != innerMap.end() && ii.key() == "mac-address") {
+ return ii.value().toString();
+ ii++;
+ }
+ i++;
+ }
+ }
+ return QString();
+}
+
+QStringList QNetworkManagerSettingsConnection::getSeenBssids()
+{
+ if(getType() == DEVICE_TYPE_802_11_WIRELESS) {
+ QNmSettingsMap::const_iterator i = d->settingsMap.find("802-11-wireless");
+ while (i != d->settingsMap.end() && i.key() == "802-11-wireless") {
+ QMap<QString,QVariant> innerMap = i.value();
+ QMap<QString,QVariant>::const_iterator ii = innerMap.find("seen-bssids");
+ while (ii != innerMap.end() && ii.key() == "seen-bssids") {
+ return ii.value().toStringList();
+ ii++;
+ }
+ i++;
+ }
+ }
+ return QStringList();
+}
+
+/////////////
+class QNetworkManagerConnectionActivePrivate
+{
+public:
+ QDBusInterface *connectionInterface;
+ QString path;
+ bool valid;
+};
+
+QNetworkManagerConnectionActive::QNetworkManagerConnectionActive( const QString &activeConnectionObjectPath, QObject *parent)
+ : QObject(parent), nmDBusHelper(0)
+{
+ d = new QNetworkManagerConnectionActivePrivate();
+ d->path = activeConnectionObjectPath;
+ d->connectionInterface = new QDBusInterface(NM_DBUS_SERVICE,
+ d->path,
+ NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
+ dbusConnection, parent);
+ if (!d->connectionInterface->isValid()) {
+ d->valid = false;
+ //qWarning() << "Could not find NetworkManagerSettingsConnection";
+ return;
+ }
+ d->valid = true;
+}
+
+QNetworkManagerConnectionActive::~QNetworkManagerConnectionActive()
+{
+ if (nmDBusHelper)
+ delete nmDBusHelper;
+ delete d->connectionInterface;
+ delete d;
+}
+
+bool QNetworkManagerConnectionActive::isValid()
+{
+ return d->valid;
+}
+
+bool QNetworkManagerConnectionActive::setConnections()
+{
+ if(!isValid() )
+ return false;
+
+ bool allOk = false;
+ if (nmDBusHelper)
+ delete nmDBusHelper;
+ nmDBusHelper = 0;
+ nmDBusHelper = new QNmDBusHelper;
+ connect(nmDBusHelper, SIGNAL(pathForPropertiesChanged(const QString &,QMap<QString,QVariant>)),
+ this,SIGNAL(propertiesChanged( const QString &, QMap<QString,QVariant>)));
+ if(dbusConnection.connect(NM_DBUS_SERVICE,
+ d->path,
+ NM_DBUS_INTERFACE_ACTIVE_CONNECTION,
+ "PropertiesChanged",
+ nmDBusHelper,SLOT(slotPropertiesChanged( QMap<QString,QVariant>))) ) {
+ allOk = true;
+ }
+
+ return allOk;
+}
+
+QDBusInterface *QNetworkManagerConnectionActive::connectionInterface() const
+{
+ return d->connectionInterface;
+}
+
+QString QNetworkManagerConnectionActive::serviceName() const
+{
+ return d->connectionInterface->property("ServiceName").toString();
+}
+
+QDBusObjectPath QNetworkManagerConnectionActive::connection() const
+{
+ QVariant prop = d->connectionInterface->property("Connection");
+ return prop.value<QDBusObjectPath>();
+}
+
+QDBusObjectPath QNetworkManagerConnectionActive::specificObject() const
+{
+ QVariant prop = d->connectionInterface->property("SpecificObject");
+ return prop.value<QDBusObjectPath>();
+}
+
+QList<QDBusObjectPath> QNetworkManagerConnectionActive::devices() const
+{
+ QVariant prop = d->connectionInterface->property("Devices");
+ return prop.value<QList<QDBusObjectPath> >();
+}
+
+quint32 QNetworkManagerConnectionActive::state() const
+{
+ return d->connectionInterface->property("State").toUInt();
+}
+
+bool QNetworkManagerConnectionActive::defaultRoute() const
+{
+ return d->connectionInterface->property("Default").toBool();
+}
+
+
+////
+class QNetworkManagerIp4ConfigPrivate
+{
+public:
+ QDBusInterface *connectionInterface;
+ QString path;
+ bool valid;
+};
+
+QNetworkManagerIp4Config::QNetworkManagerIp4Config( const QString &deviceObjectPath, QObject *parent)
+ : QObject(parent)
+{
+ d = new QNetworkManagerIp4ConfigPrivate();
+ d->path = deviceObjectPath;
+ d->connectionInterface = new QDBusInterface(NM_DBUS_SERVICE,
+ d->path,
+ NM_DBUS_INTERFACE_IP4_CONFIG,
+ dbusConnection, parent);
+ if (!d->connectionInterface->isValid()) {
+ d->valid = false;
+ //qWarning() << "Could not find NetworkManagerIp4Config";
+ return;
+ }
+ d->valid = true;
+}
+
+QNetworkManagerIp4Config::~QNetworkManagerIp4Config()
+{
+ delete d->connectionInterface;
+ delete d;
+}
+
+bool QNetworkManagerIp4Config::isValid()
+{
+ return d->valid;
+}
+
+QStringList QNetworkManagerIp4Config::domains() const
+{
+ return d->connectionInterface->property("Domains").toStringList();
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h
new file mode 100644
index 0000000..81903ec
--- /dev/null
+++ b/src/plugins/bearer/networkmanager/qnetworkmanagerservice.h
@@ -0,0 +1,397 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNETWORKMANAGERSERVICE_H
+#define QNETWORKMANAGERSERVICE_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <NetworkManager/NetworkManager.h>
+#include <QtDBus>
+#include <QDBusConnection>
+#include <QDBusError>
+#include <QDBusInterface>
+#include <QDBusMessage>
+#include <QDBusReply>
+#include <QNetworkInterface>
+
+
+#include <QDBusPendingCallWatcher>
+#include "qnmdbushelper.h"
+
+QT_BEGIN_NAMESPACE
+
+typedef QMap< QString, QMap<QString,QVariant> > QNmSettingsMap;
+typedef QList<quint32> ServerThing;
+
+Q_DECLARE_METATYPE(QNmSettingsMap)
+Q_DECLARE_METATYPE(ServerThing)
+
+class QNetworkManagerInterfacePrivate;
+class QNetworkManagerInterface : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ QNetworkManagerInterface(QObject *parent = 0);
+ ~QNetworkManagerInterface();
+
+ QList <QDBusObjectPath> getDevices() const;
+ void activateConnection(const QString &serviceName, QDBusObjectPath connection, QDBusObjectPath device, QDBusObjectPath specificObject);
+ void deactivateConnection(QDBusObjectPath connectionPath) const;
+
+ QDBusObjectPath path() const;
+ QDBusInterface *connectionInterface() const;
+
+ bool wirelessEnabled() const;
+ bool wirelessHardwareEnabled() const;
+ QList <QDBusObjectPath> activeConnections() const;
+ quint32 state();
+ bool setConnections();
+ bool isValid();
+
+Q_SIGNALS:
+ void deviceAdded(QDBusObjectPath);
+ void deviceRemoved(QDBusObjectPath);
+ void propertiesChanged( const QString &, QMap<QString,QVariant>);
+ void stateChanged(const QString&, quint32);
+ void activationFinished(QDBusPendingCallWatcher*);
+
+private Q_SLOTS:
+private:
+// Q_DISABLE_COPY(QNetworkManagerInterface); ??
+ QNetworkManagerInterfacePrivate *d;
+ QNmDBusHelper *nmDBusHelper;
+}; //end QNetworkManagerInterface
+
+////////
+class QNetworkManagerInterfaceAccessPointPrivate;
+class QNetworkManagerInterfaceAccessPoint : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ // NM_DEVICE_STATE
+ enum DeviceState {
+ Unknown = 0,
+ Unmanaged,
+ Unavailable,
+ Disconnected,
+ Prepare,
+ Config,
+ NeedAuthentication,
+ IpConfig,
+ Activated,
+ Failed
+ };
+
+ enum ApFlag {
+ ApNone = 0x0,
+ Privacy = 0x1
+ };
+
+ Q_DECLARE_FLAGS(ApFlags, ApFlag);
+
+ enum ApSecurityFlag {
+ ApSecurityNone = 0x0,
+ PairWep40 = 0x1,
+ PairWep104 = 0x2,
+ PairTkip = 0x4,
+ PairCcmp = 0x8,
+ GroupWep40 = 0x10,
+ GroupWep104 = 0x20,
+ GroupTkip = 0x40,
+ GroupCcmp = 0x80,
+ KeyPsk = 0x100,
+ Key8021x = 0x200
+ };
+
+ Q_DECLARE_FLAGS(ApSecurityFlags, ApSecurityFlag);
+
+ QNetworkManagerInterfaceAccessPoint(const QString &dbusPathName, QObject *parent = 0);
+ ~QNetworkManagerInterfaceAccessPoint();
+
+ QDBusInterface *connectionInterface() const;
+
+ quint32 flags() const;
+ quint32 wpaFlags() const;
+ quint32 rsnFlags() const;
+ QString ssid() const;
+ quint32 frequency() const;
+ QString hwAddress() const;
+ quint32 mode() const;
+ quint32 maxBitrate() const;
+ quint32 strength() const;
+ bool setConnections();
+ bool isValid();
+
+Q_SIGNALS:
+ void propertiesChanged(QMap <QString,QVariant>);
+ void propertiesChanged( const QString &, QMap<QString,QVariant>);
+private:
+ QNetworkManagerInterfaceAccessPointPrivate *d;
+ QNmDBusHelper *nmDBusHelper;
+
+}; //end QNetworkManagerInterfaceAccessPoint
+
+////////
+class QNetworkManagerInterfaceDevicePrivate;
+class QNetworkManagerInterfaceDevice : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ QNetworkManagerInterfaceDevice(const QString &deviceObjectPath, QObject *parent = 0);
+ ~QNetworkManagerInterfaceDevice();
+
+ QString udi() const;
+ QNetworkInterface interface() const;
+ QDBusInterface *connectionInterface() const;
+ quint32 ip4Address() const;
+ quint32 state() const;
+ quint32 deviceType() const;
+
+ QDBusObjectPath ip4config() const;
+ bool setConnections();
+ bool isValid();
+
+Q_SIGNALS:
+ void stateChanged(const QString &, quint32);
+
+private:
+ QNetworkManagerInterfaceDevicePrivate *d;
+ QNmDBusHelper *nmDBusHelper;
+}; //end QNetworkManagerInterfaceDevice
+
+////////
+class QNetworkManagerInterfaceDeviceWiredPrivate;
+class QNetworkManagerInterfaceDeviceWired : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ QNetworkManagerInterfaceDeviceWired(const QString &ifaceDevicePath, QObject *parent = 0);
+ ~QNetworkManagerInterfaceDeviceWired();
+
+ QDBusInterface *connectionInterface() const;
+ QString hwAddress() const;
+ quint32 speed() const;
+ bool carrier() const;
+ bool setConnections();
+ bool isValid();
+
+Q_SIGNALS:
+ void propertiesChanged( const QString &, QMap<QString,QVariant>);
+private:
+ QNetworkManagerInterfaceDeviceWiredPrivate *d;
+ QNmDBusHelper *nmDBusHelper;
+}; // end QNetworkManagerInterfaceDeviceWired
+
+////
+class QNetworkManagerInterfaceDeviceWirelessPrivate;
+class QNetworkManagerInterfaceDeviceWireless : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ enum DeviceCapability {
+ None = 0x0,
+ Wep40 = 0x1,
+ Wep104 = 0x2,
+ Tkip = 0x4,
+ Ccmp = 0x8,
+ Wpa = 0x10,
+ Rsn = 0x20
+ };
+
+ QNetworkManagerInterfaceDeviceWireless(const QString &ifaceDevicePath, QObject *parent = 0);
+ ~QNetworkManagerInterfaceDeviceWireless();
+
+ QDBusObjectPath path() const;
+ QList <QDBusObjectPath> getAccessPoints();
+ QDBusInterface *connectionInterface() const;
+
+ QString hwAddress() const;
+ quint32 mode() const;
+ quint32 bitrate() const;
+ QDBusObjectPath activeAccessPoint() const;
+ quint32 wirelessCapabilities() const;
+ bool setConnections();
+ bool isValid();
+
+Q_SIGNALS:
+ void propertiesChanged( const QString &, QMap<QString,QVariant>);
+ void accessPointAdded(const QString &,QDBusObjectPath);
+ void accessPointRemoved(const QString &,QDBusObjectPath);
+private:
+ QNetworkManagerInterfaceDeviceWirelessPrivate *d;
+ QNmDBusHelper *nmDBusHelper;
+}; // end QNetworkManagerInterfaceDeviceWireless
+
+////
+class QNetworkManagerSettingsPrivate;
+class QNetworkManagerSettings : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ QNetworkManagerSettings(const QString &settingsService, QObject *parent = 0);
+ ~QNetworkManagerSettings();
+
+ QDBusInterface *connectionInterface() const;
+ QList <QDBusObjectPath> listConnections();
+ bool setConnections();
+ bool isValid();
+
+Q_SIGNALS:
+ void newConnection(QDBusObjectPath);
+private:
+ QNetworkManagerSettingsPrivate *d;
+}; //end QNetworkManagerSettings
+
+////
+class QNetworkManagerSettingsConnectionPrivate;
+class QNetworkManagerSettingsConnection : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ QNetworkManagerSettingsConnection(const QString &settingsService, const QString &connectionObjectPath, QObject *parent = 0);
+ ~QNetworkManagerSettingsConnection();
+
+ QDBusInterface *connectionInterface() const;
+ QNmSettingsMap getSettings();
+ // void update(QNmSettingsMap map);
+ bool setConnections();
+ NMDeviceType getType();
+ bool isAutoConnect();
+ quint64 getTimestamp();
+ QString getId();
+ QString getUuid();
+ QString getSsid();
+ QString getMacAddress();
+ QStringList getSeenBssids();
+ bool isValid();
+
+Q_SIGNALS:
+
+ void updated(const QNmSettingsMap &settings);
+ void removed(const QString &path);
+
+private:
+ QNmDBusHelper *nmDBusHelper;
+ QNetworkManagerSettingsConnectionPrivate *d;
+}; //end QNetworkManagerSettingsConnection
+
+////
+class QNetworkManagerConnectionActivePrivate;
+class QNetworkManagerConnectionActive : public QObject
+{
+ Q_OBJECT
+
+public:
+
+ enum ActiveConnectionState {
+ Unknown = 0,
+ Activating = 1,
+ Activated = 2
+ };
+
+ QNetworkManagerConnectionActive(const QString &dbusPathName, QObject *parent = 0);
+ ~ QNetworkManagerConnectionActive();
+
+ QDBusInterface *connectionInterface() const;
+ QString serviceName() const;
+ QDBusObjectPath connection() const;
+ QDBusObjectPath specificObject() const;
+ QList<QDBusObjectPath> devices() const;
+ quint32 state() const;
+ bool defaultRoute() const;
+ bool setConnections();
+ bool isValid();
+
+
+Q_SIGNALS:
+ void propertiesChanged(QList<QDBusObjectPath>);
+ void propertiesChanged( const QString &, QMap<QString,QVariant>);
+private:
+ QNetworkManagerConnectionActivePrivate *d;
+ QNmDBusHelper *nmDBusHelper;
+}; //QNetworkManagerConnectionActive
+
+////
+class QNetworkManagerIp4ConfigPrivate;
+class QNetworkManagerIp4Config : public QObject
+{
+ Q_OBJECT
+
+public:
+ QNetworkManagerIp4Config(const QString &dbusPathName, QObject *parent = 0);
+ ~QNetworkManagerIp4Config();
+
+ // QList<quint32> nameservers();
+ QStringList domains() const;
+ bool isValid();
+
+ private:
+ QNetworkManagerIp4ConfigPrivate *d;
+};
+////
+
+QT_END_NAMESPACE
+
+#endif //QNETWORKMANAGERSERVICE_H
diff --git a/src/plugins/bearer/networkmanager/qnmdbushelper.cpp b/src/plugins/bearer/networkmanager/qnmdbushelper.cpp
new file mode 100644
index 0000000..d5e20f3
--- /dev/null
+++ b/src/plugins/bearer/networkmanager/qnmdbushelper.cpp
@@ -0,0 +1,117 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+// this class is for helping qdbus get stuff
+
+#include "qnmdbushelper.h"
+
+#include <NetworkManager/NetworkManager.h>
+
+#include <QDBusError>
+#include <QDBusInterface>
+#include <QDBusMessage>
+#include <QDBusReply>
+
+#include <QDebug>
+
+QT_BEGIN_NAMESPACE
+
+void QNmDBusHelper::deviceStateChanged(quint32 state)
+ {
+ QDBusMessage msg = this->message();
+ if(state == NM_DEVICE_STATE_ACTIVATED
+ || state == NM_DEVICE_STATE_DISCONNECTED
+ || state == NM_DEVICE_STATE_UNAVAILABLE
+ || state == NM_DEVICE_STATE_FAILED) {
+ emit pathForStateChanged(msg.path(), state);
+ }
+ }
+
+void QNmDBusHelper::slotAccessPointAdded(QDBusObjectPath path)
+{
+ if(path.path().length() > 2) {
+ QDBusMessage msg = this->message();
+ emit pathForAccessPointAdded(msg.path(), path);
+ }
+}
+
+void QNmDBusHelper::slotAccessPointRemoved(QDBusObjectPath path)
+{
+ if(path.path().length() > 2) {
+ QDBusMessage msg = this->message();
+ emit pathForAccessPointRemoved(msg.path(), path);
+ }
+}
+
+void QNmDBusHelper::slotPropertiesChanged(QMap<QString,QVariant> map)
+{
+ QDBusMessage msg = this->message();
+ QMapIterator<QString, QVariant> i(map);
+ while (i.hasNext()) {
+ i.next();
+ if( i.key() == "State") { //state only applies to device interfaces
+ quint32 state = i.value().toUInt();
+ if( state == NM_DEVICE_STATE_ACTIVATED
+ || state == NM_DEVICE_STATE_DISCONNECTED
+ || state == NM_DEVICE_STATE_UNAVAILABLE
+ || state == NM_DEVICE_STATE_FAILED) {
+ emit pathForPropertiesChanged( msg.path(), map);
+ }
+ } else if( i.key() == "ActiveAccessPoint") {
+ emit pathForPropertiesChanged(msg.path(), map);
+ // qWarning() << __PRETTY_FUNCTION__ << i.key() << ": " << i.value().value<QDBusObjectPath>().path();
+ // } else if( i.key() == "Strength")
+ // qWarning() << __PRETTY_FUNCTION__ << i.key() << ": " << i.value().toUInt();
+ // else
+ // qWarning() << __PRETTY_FUNCTION__ << i.key() << ": " << i.value();
+ } else if (i.key() == "ActiveConnections") {
+ emit pathForPropertiesChanged(msg.path(), map);
+ }
+ }
+}
+
+void QNmDBusHelper::slotSettingsRemoved()
+{
+ QDBusMessage msg = this->message();
+ emit pathForSettingsRemoved(msg.path());
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/networkmanager/qnmdbushelper.h b/src/plugins/bearer/networkmanager/qnmdbushelper.h
new file mode 100644
index 0000000..862290c
--- /dev/null
+++ b/src/plugins/bearer/networkmanager/qnmdbushelper.h
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNMDBUSHELPERPRIVATE_H
+#define QNMDBUSHELPERPRIVATE_H
+
+#include <QDBusObjectPath>
+#include <QDBusContext>
+#include <QMap>
+
+QT_BEGIN_NAMESPACE
+
+class QNmDBusHelper: public QObject, protected QDBusContext
+ {
+ Q_OBJECT
+ public:
+
+ public slots:
+ void deviceStateChanged(quint32);
+ void slotAccessPointAdded( QDBusObjectPath );
+ void slotAccessPointRemoved( QDBusObjectPath );
+ void slotPropertiesChanged( QMap<QString,QVariant>);
+ void slotSettingsRemoved();
+
+Q_SIGNALS:
+ void pathForStateChanged(const QString &, quint32);
+ void pathForAccessPointAdded(const QString &, QDBusObjectPath );
+ void pathForAccessPointRemoved(const QString &, QDBusObjectPath );
+ void pathForPropertiesChanged(const QString &, QMap<QString,QVariant>);
+ void pathForSettingsRemoved(const QString &);
+};
+
+QT_END_NAMESPACE
+
+#endif// QNMDBUSHELPERPRIVATE_H
diff --git a/src/plugins/bearer/nla/main.cpp b/src/plugins/bearer/nla/main.cpp
new file mode 100644
index 0000000..479a933
--- /dev/null
+++ b/src/plugins/bearer/nla/main.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnlaengine.h"
+
+#include <QtNetwork/private/qbearerplugin_p.h>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QNlaEnginePlugin : public QBearerEnginePlugin
+{
+public:
+ QNlaEnginePlugin();
+ ~QNlaEnginePlugin();
+
+ QStringList keys() const;
+ QBearerEngine *create(const QString &key) const;
+};
+
+QNlaEnginePlugin::QNlaEnginePlugin()
+{
+}
+
+QNlaEnginePlugin::~QNlaEnginePlugin()
+{
+}
+
+QStringList QNlaEnginePlugin::keys() const
+{
+ return QStringList() << QLatin1String("nla");
+}
+
+QBearerEngine *QNlaEnginePlugin::create(const QString &key) const
+{
+ if (key == QLatin1String("nla"))
+ return new QNlaEngine;
+ else
+ return 0;
+}
+
+Q_EXPORT_STATIC_PLUGIN(QNlaEnginePlugin)
+Q_EXPORT_PLUGIN2(qnlabearer, QNlaEnginePlugin)
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/nla/nla.pro b/src/plugins/bearer/nla/nla.pro
new file mode 100644
index 0000000..5148b09
--- /dev/null
+++ b/src/plugins/bearer/nla/nla.pro
@@ -0,0 +1,23 @@
+TARGET = qnlabearer
+include(../../qpluginbase.pri)
+
+QT += network
+
+!wince* {
+ LIBS += -lWs2_32
+} else {
+ LIBS += -lWs2
+}
+
+HEADERS += qnlaengine.h \
+ ../platformdefs_win.h \
+ ../qnetworksession_impl.h \
+ ../qbearerengine_impl.h
+
+SOURCES += main.cpp \
+ qnlaengine.cpp \
+ ../qnetworksession_impl.cpp
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/bearer
+target.path += $$[QT_INSTALL_PLUGINS]/bearer
+INSTALLS += target
diff --git a/src/plugins/bearer/nla/qnlaengine.cpp b/src/plugins/bearer/nla/qnlaengine.cpp
new file mode 100644
index 0000000..ff334e5
--- /dev/null
+++ b/src/plugins/bearer/nla/qnlaengine.cpp
@@ -0,0 +1,661 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnlaengine.h"
+#include "../qnetworksession_impl.h"
+
+#include <QtNetwork/private/qnetworkconfiguration_p.h>
+
+#include <QtCore/qthread.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qcoreapplication.h>
+#include <QtCore/qstringlist.h>
+
+#include <QtCore/qdebug.h>
+
+#include "../platformdefs_win.h"
+
+QT_BEGIN_NAMESPACE
+
+QWindowsSockInit2::QWindowsSockInit2()
+: version(0)
+{
+ //### should we try for 2.2 on all platforms ??
+ WSAData wsadata;
+
+ // IPv6 requires Winsock v2.0 or better.
+ if (WSAStartup(MAKEWORD(2,0), &wsadata) != 0) {
+ qWarning("QBearerManagementAPI: WinSock v2.0 initialization failed.");
+ } else {
+ version = 0x20;
+ }
+}
+
+QWindowsSockInit2::~QWindowsSockInit2()
+{
+ WSACleanup();
+}
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+static void printBlob(NLA_BLOB *blob)
+{
+ qDebug() << "==== BEGIN NLA_BLOB ====";
+
+ qDebug() << "type:" << blob->header.type;
+ qDebug() << "size:" << blob->header.dwSize;
+ qDebug() << "next offset:" << blob->header.nextOffset;
+
+ switch (blob->header.type) {
+ case NLA_RAW_DATA:
+ qDebug() << "Raw Data";
+ qDebug() << '\t' << blob->data.rawData;
+ break;
+ case NLA_INTERFACE:
+ qDebug() << "Interface";
+ qDebug() << "\ttype:" << blob->data.interfaceData.dwType;
+ qDebug() << "\tspeed:" << blob->data.interfaceData.dwSpeed;
+ qDebug() << "\tadapter:" << blob->data.interfaceData.adapterName;
+ break;
+ case NLA_802_1X_LOCATION:
+ qDebug() << "802.1x Location";
+ qDebug() << '\t' << blob->data.locationData.information;
+ break;
+ case NLA_CONNECTIVITY:
+ qDebug() << "Connectivity";
+ qDebug() << "\ttype:" << blob->data.connectivity.type;
+ qDebug() << "\tinternet:" << blob->data.connectivity.internet;
+ break;
+ case NLA_ICS:
+ qDebug() << "ICS";
+ qDebug() << "\tspeed:" << blob->data.ICS.remote.speed;
+ qDebug() << "\ttype:" << blob->data.ICS.remote.type;
+ qDebug() << "\tstate:" << blob->data.ICS.remote.state;
+ qDebug() << "\tmachine name:" << blob->data.ICS.remote.machineName;
+ qDebug() << "\tshared adapter name:" << blob->data.ICS.remote.sharedAdapterName;
+ break;
+ default:
+ qDebug() << "UNKNOWN BLOB TYPE";
+ }
+
+ qDebug() << "===== END NLA_BLOB =====";
+}
+#endif
+
+static QString qGetInterfaceType(const QString &interface)
+{
+#ifdef Q_OS_WINCE
+ Q_UNUSED(interface)
+#else
+ unsigned long oid;
+ DWORD bytesWritten;
+
+ NDIS_MEDIUM medium;
+ NDIS_PHYSICAL_MEDIUM physicalMedium;
+
+ HANDLE handle = CreateFile((TCHAR *)QString(QLatin1String("\\\\.\\%1")).arg(interface).utf16(),
+ 0, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
+ if (handle == INVALID_HANDLE_VALUE)
+ return QLatin1String("Unknown");
+
+ oid = OID_GEN_MEDIA_SUPPORTED;
+ bytesWritten = 0;
+ bool result = DeviceIoControl(handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof(oid),
+ &medium, sizeof(medium), &bytesWritten, 0);
+ if (!result) {
+ CloseHandle(handle);
+ return QLatin1String("Unknown");
+ }
+
+ oid = OID_GEN_PHYSICAL_MEDIUM;
+ bytesWritten = 0;
+ result = DeviceIoControl(handle, IOCTL_NDIS_QUERY_GLOBAL_STATS, &oid, sizeof(oid),
+ &physicalMedium, sizeof(physicalMedium), &bytesWritten, 0);
+ if (!result) {
+ CloseHandle(handle);
+
+ if (medium == NdisMedium802_3)
+ return QLatin1String("Ethernet");
+ else
+ return QLatin1String("Unknown");
+ }
+
+ CloseHandle(handle);
+
+ if (medium == NdisMedium802_3) {
+ switch (physicalMedium) {
+ case NdisPhysicalMediumWirelessLan:
+ return QLatin1String("WLAN");
+ case NdisPhysicalMediumBluetooth:
+ return QLatin1String("Bluetooth");
+ case NdisPhysicalMediumWiMax:
+ return QLatin1String("WiMAX");
+ default:
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "Physical Medium" << physicalMedium;
+#endif
+ return QLatin1String("Ethernet");
+ }
+ }
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << medium << physicalMedium;
+#endif
+
+#endif
+
+ return QLatin1String("Unknown");
+}
+
+class QNlaThread : public QThread
+{
+ Q_OBJECT
+
+public:
+ QNlaThread(QNlaEngine *parent = 0);
+ ~QNlaThread();
+
+ QList<QNetworkConfigurationPrivate *> getConfigurations();
+
+ void forceUpdate();
+
+protected:
+ virtual void run();
+
+private:
+ void updateConfigurations(QList<QNetworkConfigurationPrivate *> &configs);
+ DWORD parseBlob(NLA_BLOB *blob, QNetworkConfigurationPrivate *cpPriv) const;
+ QNetworkConfigurationPrivate *parseQuerySet(const WSAQUERYSET *querySet) const;
+ void fetchConfigurations();
+
+signals:
+ void networksChanged();
+
+private:
+ QMutex mutex;
+ HANDLE handle;
+ bool done;
+ QList<QNetworkConfigurationPrivate *> fetchedConfigurations;
+};
+
+QNlaThread::QNlaThread(QNlaEngine *parent)
+: QThread(parent), handle(0), done(false)
+{
+}
+
+QNlaThread::~QNlaThread()
+{
+ mutex.lock();
+
+ done = true;
+
+ if (handle) {
+ /* cancel completion event */
+ if (WSALookupServiceEnd(handle) == SOCKET_ERROR)
+ qWarning("WSALookupServiceEnd error %d", WSAGetLastError());
+ }
+ mutex.unlock();
+
+ wait();
+}
+
+QList<QNetworkConfigurationPrivate *> QNlaThread::getConfigurations()
+{
+ QMutexLocker locker(&mutex);
+
+ QList<QNetworkConfigurationPrivate *> foundConfigurations = fetchedConfigurations;
+ fetchedConfigurations.clear();
+
+ return foundConfigurations;
+}
+
+void QNlaThread::forceUpdate()
+{
+ mutex.lock();
+
+ if (handle) {
+ /* cancel completion event */
+ if (WSALookupServiceEnd(handle) == SOCKET_ERROR)
+ qWarning("WSALookupServiceEnd error %d", WSAGetLastError());
+ handle = 0;
+ }
+ mutex.unlock();
+}
+
+void QNlaThread::run()
+{
+ WSAEVENT changeEvent = WSACreateEvent();
+ if (changeEvent == WSA_INVALID_EVENT) {
+ qWarning("WSACreateEvent error %d", WSAGetLastError());
+ return;
+ }
+
+ while (true) {
+ fetchConfigurations();
+
+ WSAQUERYSET qsRestrictions;
+
+ memset(&qsRestrictions, 0, sizeof(qsRestrictions));
+ qsRestrictions.dwSize = sizeof(qsRestrictions);
+ qsRestrictions.dwNameSpace = NS_NLA;
+
+ mutex.lock();
+ if (done) {
+ mutex.unlock();
+ break;
+ }
+ int result = WSALookupServiceBegin(&qsRestrictions, LUP_RETURN_ALL, &handle);
+ mutex.unlock();
+
+ if (result == SOCKET_ERROR) {
+ qWarning("%s: WSALookupServiceBegin error %d", __FUNCTION__, WSAGetLastError());
+ break;
+ }
+
+ WSACOMPLETION completion;
+ WSAOVERLAPPED overlapped;
+
+ memset(&overlapped, 0, sizeof(overlapped));
+ overlapped.hEvent = changeEvent;
+
+ memset(&completion, 0, sizeof(completion));
+ completion.Type = NSP_NOTIFY_EVENT;
+ completion.Parameters.Event.lpOverlapped = &overlapped;
+
+ DWORD bytesReturned = 0;
+ result = WSANSPIoctl(handle, SIO_NSP_NOTIFY_CHANGE, 0, 0, 0, 0,
+ &bytesReturned, &completion);
+ if (result == SOCKET_ERROR) {
+ int error = WSAGetLastError();
+ if (error != WSA_IO_PENDING) {
+ qWarning("WSANSPIoctl error %d", error);
+ break;
+ }
+ }
+
+#ifndef Q_OS_WINCE
+ // Not interested in unrelated IO completion events
+ // although we also don't want to block them
+ while (WaitForSingleObjectEx(changeEvent, WSA_INFINITE, true) != WAIT_IO_COMPLETION &&
+ handle)
+ {
+ }
+#else
+ WaitForSingleObject(changeEvent, WSA_INFINITE);
+#endif
+
+ mutex.lock();
+ if (handle) {
+ result = WSALookupServiceEnd(handle);
+ if (result == SOCKET_ERROR) {
+ qWarning("WSALookupServiceEnd error %d", WSAGetLastError());
+ mutex.unlock();
+ break;
+ }
+ handle = 0;
+ }
+ mutex.unlock();
+ }
+
+ WSACloseEvent(changeEvent);
+}
+
+void QNlaThread::updateConfigurations(QList<QNetworkConfigurationPrivate *> &configs)
+{
+ mutex.lock();
+
+ while (!fetchedConfigurations.isEmpty())
+ delete fetchedConfigurations.takeFirst();
+
+ fetchedConfigurations = configs;
+
+ mutex.unlock();
+
+ emit networksChanged();
+}
+
+DWORD QNlaThread::parseBlob(NLA_BLOB *blob, QNetworkConfigurationPrivate *cpPriv) const
+{
+#ifdef BEARER_MANAGEMENT_DEBUG
+ printBlob(blob);
+#endif
+
+ switch (blob->header.type) {
+ case NLA_RAW_DATA:
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qWarning("%s: unhandled header type NLA_RAW_DATA", __FUNCTION__);
+#endif
+ break;
+ case NLA_INTERFACE:
+ cpPriv->state = QNetworkConfiguration::Active;
+ if (QNlaEngine *engine = qobject_cast<QNlaEngine *>(parent())) {
+ engine->configurationInterface[cpPriv->id.toUInt()] =
+ QString::fromLatin1(blob->data.interfaceData.adapterName);
+ }
+ break;
+ case NLA_802_1X_LOCATION:
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qWarning("%s: unhandled header type NLA_802_1X_LOCATION", __FUNCTION__);
+#endif
+ break;
+ case NLA_CONNECTIVITY:
+ if (blob->data.connectivity.internet == NLA_INTERNET_YES)
+ cpPriv->internet = true;
+ else
+ cpPriv->internet = false;
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qWarning("%s: unhandled header type NLA_CONNECTIVITY", __FUNCTION__);
+#endif
+ break;
+ case NLA_ICS:
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qWarning("%s: unhandled header type NLA_ICS", __FUNCTION__);
+#endif
+ break;
+ default:
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qWarning("%s: unhandled header type %d", __FUNCTION__, blob->header.type);
+#endif
+ ;
+ }
+
+ return blob->header.nextOffset;
+}
+
+QNetworkConfigurationPrivate *QNlaThread::parseQuerySet(const WSAQUERYSET *querySet) const
+{
+ QNetworkConfigurationPrivate *cpPriv = new QNetworkConfigurationPrivate;
+
+ cpPriv->name = QString::fromWCharArray(querySet->lpszServiceInstanceName);
+ cpPriv->isValid = true;
+ cpPriv->id = QString::number(qHash(QLatin1String("NLA:") + cpPriv->name));
+ cpPriv->state = QNetworkConfiguration::Defined;
+ cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "size:" << querySet->dwSize;
+ qDebug() << "service instance name:" << QString::fromUtf16(querySet->lpszServiceInstanceName);
+ qDebug() << "service class id:" << querySet->lpServiceClassId;
+ qDebug() << "version:" << querySet->lpVersion;
+ qDebug() << "comment:" << QString::fromUtf16(querySet->lpszComment);
+ qDebug() << "namespace:" << querySet->dwNameSpace;
+ qDebug() << "namespace provider id:" << querySet->lpNSProviderId;
+ qDebug() << "context:" << QString::fromUtf16(querySet->lpszContext);
+ qDebug() << "number of protocols:" << querySet->dwNumberOfProtocols;
+ qDebug() << "protocols:" << querySet->lpafpProtocols;
+ qDebug() << "query string:" << QString::fromUtf16(querySet->lpszQueryString);
+ qDebug() << "number of cs addresses:" << querySet->dwNumberOfCsAddrs;
+ qDebug() << "cs addresses:" << querySet->lpcsaBuffer;
+ qDebug() << "output flags:" << querySet->dwOutputFlags;
+#endif
+
+ if (querySet->lpBlob) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+ qDebug() << "blob size:" << querySet->lpBlob->cbSize;
+ qDebug() << "blob data:" << querySet->lpBlob->pBlobData;
+#endif
+
+ DWORD offset = 0;
+ do {
+ NLA_BLOB *blob = reinterpret_cast<NLA_BLOB *>(querySet->lpBlob->pBlobData + offset);
+ DWORD nextOffset = parseBlob(blob, cpPriv);
+ if (nextOffset == offset)
+ break;
+ else
+ offset = nextOffset;
+ } while (offset != 0 && offset < querySet->lpBlob->cbSize);
+ }
+
+ if (QNlaEngine *engine = qobject_cast<QNlaEngine *>(parent()))
+ cpPriv->bearer = engine->bearerName(cpPriv->id);
+
+ return cpPriv;
+}
+
+void QNlaThread::fetchConfigurations()
+{
+ QList<QNetworkConfigurationPrivate *> foundConfigurations;
+
+ WSAQUERYSET qsRestrictions;
+ HANDLE hLookup = 0;
+
+ memset(&qsRestrictions, 0, sizeof(qsRestrictions));
+ qsRestrictions.dwSize = sizeof(qsRestrictions);
+ qsRestrictions.dwNameSpace = NS_NLA;
+
+ int result = WSALookupServiceBegin(&qsRestrictions, LUP_RETURN_ALL | LUP_DEEP, &hLookup);
+ if (result == SOCKET_ERROR) {
+ qWarning("%s: WSALookupServiceBegin error %d", __FUNCTION__, WSAGetLastError());
+ mutex.lock();
+ fetchedConfigurations.clear();
+ mutex.unlock();
+ }
+
+ char buffer[0x10000];
+ while (result == 0) {
+ DWORD bufferLength = sizeof(buffer);
+ result = WSALookupServiceNext(hLookup, LUP_RETURN_ALL,
+ &bufferLength, reinterpret_cast<WSAQUERYSET *>(buffer));
+
+ if (result == SOCKET_ERROR) {
+ int error = WSAGetLastError();
+
+ if (error == WSA_E_NO_MORE)
+ break;
+
+ if (error == WSAEFAULT)
+ break;
+
+ qWarning("WSALookupServiceNext error %d", WSAGetLastError());
+ break;
+ }
+
+ QNetworkConfigurationPrivate *cpPriv =
+ parseQuerySet(reinterpret_cast<WSAQUERYSET *>(buffer));
+
+ foundConfigurations.append(cpPriv);
+ }
+
+ if (hLookup) {
+ result = WSALookupServiceEnd(hLookup);
+ if (result == SOCKET_ERROR) {
+ qWarning("WSALookupServiceEnd error %d", WSAGetLastError());
+ }
+ }
+
+ updateConfigurations(foundConfigurations);
+}
+
+QNlaEngine::QNlaEngine(QObject *parent)
+: QBearerEngineImpl(parent), nlaThread(0)
+{
+ nlaThread = new QNlaThread(this);
+ connect(nlaThread, SIGNAL(networksChanged()),
+ this, SLOT(networksChanged()));
+ nlaThread->start();
+
+ qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
+}
+
+QNlaEngine::~QNlaEngine()
+{
+ delete nlaThread;
+}
+
+void QNlaEngine::networksChanged()
+{
+ QMutexLocker locker(&mutex);
+
+ QStringList previous = accessPointConfigurations.keys();
+
+ QList<QNetworkConfigurationPrivate *> foundConfigurations = nlaThread->getConfigurations();
+ while (!foundConfigurations.isEmpty()) {
+ QNetworkConfigurationPrivate *cpPriv = foundConfigurations.takeFirst();
+
+ previous.removeAll(cpPriv->id);
+
+ if (accessPointConfigurations.contains(cpPriv->id)) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(cpPriv->id);
+
+ bool changed = false;
+
+ if (ptr->isValid != cpPriv->isValid) {
+ ptr->isValid = cpPriv->isValid;
+ changed = true;
+ }
+
+ if (ptr->name != cpPriv->name) {
+ ptr->name = cpPriv->name;
+ changed = true;
+ }
+
+ if (ptr->state != cpPriv->state) {
+ ptr->state = cpPriv->state;
+ changed = true;
+ }
+
+ if (changed)
+ emit configurationChanged(ptr);
+
+ delete cpPriv;
+ } else {
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+
+ accessPointConfigurations.insert(ptr->id, ptr);
+
+ emit configurationAdded(ptr);
+ }
+ }
+
+ while (!previous.isEmpty()) {
+ QNetworkConfigurationPrivatePointer ptr =
+ accessPointConfigurations.take(previous.takeFirst());
+
+ emit configurationRemoved(ptr);
+ }
+
+ emit updateCompleted();
+}
+
+QString QNlaEngine::getInterfaceFromId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ return configurationInterface.value(id.toUInt());
+}
+
+bool QNlaEngine::hasIdentifier(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ return configurationInterface.contains(id.toUInt());
+}
+
+QString QNlaEngine::bearerName(const QString &id)
+{
+ QString interface = getInterfaceFromId(id);
+
+ if (interface.isEmpty())
+ return QString();
+
+ return qGetInterfaceType(interface);
+}
+
+void QNlaEngine::connectToId(const QString &id)
+{
+ emit connectionError(id, OperationNotSupported);
+}
+
+void QNlaEngine::disconnectFromId(const QString &id)
+{
+ emit connectionError(id, OperationNotSupported);
+}
+
+void QNlaEngine::requestUpdate()
+{
+ QMutexLocker locker(&mutex);
+
+ nlaThread->forceUpdate();
+}
+
+QNetworkSession::State QNlaEngine::sessionStateForId(const QString &id)
+{
+ QMutexLocker locker(&mutex);
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(id);
+
+ if (!ptr)
+ return QNetworkSession::Invalid;
+
+ if (!ptr->isValid) {
+ return QNetworkSession::Invalid;
+ } else if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ return QNetworkSession::Connected;
+ } else if ((ptr->state & QNetworkConfiguration::Discovered) ==
+ QNetworkConfiguration::Discovered) {
+ return QNetworkSession::Disconnected;
+ } else if ((ptr->state & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
+ return QNetworkSession::NotAvailable;
+ } else if ((ptr->state & QNetworkConfiguration::Undefined) ==
+ QNetworkConfiguration::Undefined) {
+ return QNetworkSession::NotAvailable;
+ }
+
+ return QNetworkSession::Invalid;
+}
+
+QNetworkConfigurationManager::Capabilities QNlaEngine::capabilities() const
+{
+ return QNetworkConfigurationManager::ForcedRoaming;
+}
+
+QNetworkSessionPrivate *QNlaEngine::createSessionBackend()
+{
+ return new QNetworkSessionPrivateImpl;
+}
+
+QNetworkConfigurationPrivatePointer QNlaEngine::defaultConfiguration()
+{
+ return QNetworkConfigurationPrivatePointer();
+}
+
+#include "qnlaengine.moc"
+QT_END_NAMESPACE
+
diff --git a/src/plugins/bearer/nla/qnlaengine.h b/src/plugins/bearer/nla/qnlaengine.h
new file mode 100644
index 0000000..14c5201
--- /dev/null
+++ b/src/plugins/bearer/nla/qnlaengine.h
@@ -0,0 +1,114 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNLAENGINE_P_H
+#define QNLAENGINE_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "../qbearerengine_impl.h"
+
+#include <QtNetwork/private/qnativesocketengine_p.h>
+
+#include <QMap>
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkConfigurationPrivate;
+class QNlaThread;
+
+class QWindowsSockInit2
+{
+public:
+ QWindowsSockInit2();
+ ~QWindowsSockInit2();
+ int version;
+};
+
+class QNlaEngine : public QBearerEngineImpl
+{
+ Q_OBJECT
+
+ friend class QNlaThread;
+
+public:
+ QNlaEngine(QObject *parent = 0);
+ ~QNlaEngine();
+
+ QString getInterfaceFromId(const QString &id);
+ bool hasIdentifier(const QString &id);
+
+ QString bearerName(const QString &id);
+
+ void connectToId(const QString &id);
+ void disconnectFromId(const QString &id);
+
+ void requestUpdate();
+
+ QNetworkSession::State sessionStateForId(const QString &id);
+
+ QNetworkConfigurationManager::Capabilities capabilities() const;
+
+ QNetworkSessionPrivate *createSessionBackend();
+
+ QNetworkConfigurationPrivatePointer defaultConfiguration();
+
+private Q_SLOTS:
+ void networksChanged();
+
+private:
+ QWindowsSockInit2 winSock;
+ QNlaThread *nlaThread;
+ QMap<uint, QString> configurationInterface;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/bearer/platformdefs_win.h b/src/plugins/bearer/platformdefs_win.h
new file mode 100644
index 0000000..37d099c
--- /dev/null
+++ b/src/plugins/bearer/platformdefs_win.h
@@ -0,0 +1,134 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QPLATFORMDEFS_WIN_H
+#define QPLATFORMDEFS_WIN_H
+
+#include <winsock2.h>
+#include <mswsock.h>
+#undef interface
+#include <winioctl.h>
+
+#ifndef NS_NLA
+
+#define NS_NLA 15
+
+enum NLA_BLOB_DATA_TYPE {
+ NLA_RAW_DATA = 0,
+ NLA_INTERFACE = 1,
+ NLA_802_1X_LOCATION = 2,
+ NLA_CONNECTIVITY = 3,
+ NLA_ICS = 4
+};
+
+enum NLA_CONNECTIVITY_TYPE {
+ NLA_NETWORK_AD_HOC = 0,
+ NLA_NETWORK_MANAGED = 1,
+ NLA_NETWORK_UNMANAGED = 2,
+ NLA_NETWORK_UNKNOWN = 3
+};
+
+enum NLA_INTERNET {
+ NLA_INTERNET_UNKNOWN = 0,
+ NLA_INTERNET_NO = 1,
+ NLA_INTERNET_YES = 2
+};
+
+struct NLA_BLOB {
+ struct {
+ NLA_BLOB_DATA_TYPE type;
+ DWORD dwSize;
+ DWORD nextOffset;
+ } header;
+
+ union {
+ // NLA_RAW_DATA
+ CHAR rawData[1];
+
+ // NLA_INTERFACE
+ struct {
+ DWORD dwType;
+ DWORD dwSpeed;
+ CHAR adapterName[1];
+ } interfaceData;
+
+ // NLA_802_1X_LOCATION
+ struct {
+ CHAR information[1];
+ } locationData;
+
+ // NLA_CONNECTIVITY
+ struct {
+ NLA_CONNECTIVITY_TYPE type;
+ NLA_INTERNET internet;
+ } connectivity;
+
+ // NLA_ICS
+ struct {
+ struct {
+ DWORD speed;
+ DWORD type;
+ DWORD state;
+ WCHAR machineName[256];
+ WCHAR sharedAdapterName[256];
+ } remote;
+ } ICS;
+ } data;
+};
+#endif
+
+enum NDIS_MEDIUM {
+ NdisMedium802_3 = 0,
+};
+
+enum NDIS_PHYSICAL_MEDIUM {
+ NdisPhysicalMediumWirelessLan = 1,
+ NdisPhysicalMediumBluetooth = 10,
+ NdisPhysicalMediumWiMax = 12,
+};
+
+#define OID_GEN_MEDIA_SUPPORTED 0x00010103
+#define OID_GEN_PHYSICAL_MEDIUM 0x00010202
+
+#define IOCTL_NDIS_QUERY_GLOBAL_STATS \
+ CTL_CODE(FILE_DEVICE_PHYSICAL_NETCARD, 0, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
+
+#endif
diff --git a/src/plugins/bearer/qbearerengine_impl.h b/src/plugins/bearer/qbearerengine_impl.h
new file mode 100644
index 0000000..740def3
--- /dev/null
+++ b/src/plugins/bearer/qbearerengine_impl.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QBEARERENGINE_IMPL_H
+#define QBEARERENGINE_IMPL_H
+
+#include <QtNetwork/private/qbearerengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QBearerEngineImpl : public QBearerEngine
+{
+ Q_OBJECT
+
+public:
+ enum ConnectionError {
+ InterfaceLookupError = 0,
+ ConnectError,
+ OperationNotSupported,
+ DisconnectionError,
+ };
+
+ QBearerEngineImpl(QObject *parent = 0) : QBearerEngine(parent) { }
+ ~QBearerEngineImpl() { }
+
+ virtual void connectToId(const QString &id) = 0;
+ virtual void disconnectFromId(const QString &id) = 0;
+
+ virtual QString getInterfaceFromId(const QString &id) = 0;
+
+ virtual QNetworkSession::State sessionStateForId(const QString &id) = 0;
+
+ virtual quint64 bytesWritten(const QString &) { return Q_UINT64_C(0); }
+ virtual quint64 bytesReceived(const QString &) { return Q_UINT64_C(0); }
+ virtual quint64 startTime(const QString &) { return Q_UINT64_C(0); }
+
+Q_SIGNALS:
+ void connectionError(const QString &id, QBearerEngineImpl::ConnectionError error);
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/bearer/qnetworksession_impl.cpp b/src/plugins/bearer/qnetworksession_impl.cpp
new file mode 100644
index 0000000..f41fdba
--- /dev/null
+++ b/src/plugins/bearer/qnetworksession_impl.cpp
@@ -0,0 +1,408 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnetworksession_impl.h"
+#include "qbearerengine_impl.h"
+
+#include <QtNetwork/qnetworksession.h>
+#include <QtNetwork/private/qnetworkconfigmanager_p.h>
+
+#include <QtCore/qstringlist.h>
+#include <QtCore/qdebug.h>
+#include <QtCore/qmutex.h>
+
+#include <QtNetwork/qnetworkinterface.h>
+
+QT_BEGIN_NAMESPACE
+
+static QBearerEngineImpl *getEngineFromId(const QString &id)
+{
+ QNetworkConfigurationManagerPrivate *priv = qNetworkConfigurationManagerPrivate();
+
+ foreach (QBearerEngine *engine, priv->engines()) {
+ QBearerEngineImpl *engineImpl = qobject_cast<QBearerEngineImpl *>(engine);
+ if (engineImpl && engineImpl->hasIdentifier(id))
+ return engineImpl;
+ }
+
+ return 0;
+}
+
+class QNetworkSessionManagerPrivate : public QObject
+{
+ Q_OBJECT
+
+public:
+ QNetworkSessionManagerPrivate(QObject *parent = 0);
+ ~QNetworkSessionManagerPrivate();
+
+ void forceSessionClose(const QNetworkConfiguration &config);
+
+Q_SIGNALS:
+ void forcedSessionClose(const QNetworkConfiguration &config);
+};
+
+#include "qnetworksession_impl.moc"
+
+Q_GLOBAL_STATIC(QNetworkSessionManagerPrivate, sessionManager);
+
+QNetworkSessionManagerPrivate::QNetworkSessionManagerPrivate(QObject *parent)
+: QObject(parent)
+{
+}
+
+QNetworkSessionManagerPrivate::~QNetworkSessionManagerPrivate()
+{
+}
+
+void QNetworkSessionManagerPrivate::forceSessionClose(const QNetworkConfiguration &config)
+{
+ emit forcedSessionClose(config);
+}
+
+void QNetworkSessionPrivateImpl::syncStateWithInterface()
+{
+ connect(&manager, SIGNAL(updateCompleted()), this, SLOT(networkConfigurationsChanged()));
+ connect(&manager, SIGNAL(configurationChanged(QNetworkConfiguration)),
+ this, SLOT(configurationChanged(QNetworkConfiguration)));
+ connect(sessionManager(), SIGNAL(forcedSessionClose(QNetworkConfiguration)),
+ this, SLOT(forcedSessionClose(QNetworkConfiguration)));
+
+ opened = false;
+ isOpen = false;
+ state = QNetworkSession::Invalid;
+ lastError = QNetworkSession::UnknownSessionError;
+
+ qRegisterMetaType<QBearerEngineImpl::ConnectionError>
+ ("QBearerEngineImpl::ConnectionError");
+
+ switch (publicConfig.type()) {
+ case QNetworkConfiguration::InternetAccessPoint:
+ activeConfig = publicConfig;
+ engine = getEngineFromId(activeConfig.identifier());
+ if (engine) {
+ connect(engine, SIGNAL(connectionError(QString,QBearerEngineImpl::ConnectionError)),
+ this, SLOT(connectionError(QString,QBearerEngineImpl::ConnectionError)),
+ Qt::QueuedConnection);
+ }
+ break;
+ case QNetworkConfiguration::ServiceNetwork:
+ serviceConfig = publicConfig;
+ // Defer setting engine and signals until open().
+ // fall through
+ case QNetworkConfiguration::UserChoice:
+ // Defer setting serviceConfig and activeConfig until open().
+ // fall through
+ default:
+ engine = 0;
+ }
+
+ networkConfigurationsChanged();
+}
+
+void QNetworkSessionPrivateImpl::open()
+{
+ if (serviceConfig.isValid()) {
+ lastError = QNetworkSession::OperationNotSupportedError;
+ emit QNetworkSessionPrivate::error(lastError);
+ } else if (!isOpen) {
+ if ((activeConfig.state() & QNetworkConfiguration::Discovered) !=
+ QNetworkConfiguration::Discovered) {
+ lastError =QNetworkSession::InvalidConfigurationError;
+ emit QNetworkSessionPrivate::error(lastError);
+ return;
+ }
+ opened = true;
+
+ if ((activeConfig.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active &&
+ (activeConfig.state() & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) {
+ state = QNetworkSession::Connecting;
+ emit stateChanged(state);
+
+ engine->connectToId(activeConfig.identifier());
+ }
+
+ isOpen = (activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active;
+ if (isOpen)
+ emit quitPendingWaitsForOpened();
+ }
+}
+
+void QNetworkSessionPrivateImpl::close()
+{
+ if (serviceConfig.isValid()) {
+ lastError = QNetworkSession::OperationNotSupportedError;
+ emit QNetworkSessionPrivate::error(lastError);
+ } else if (isOpen) {
+ opened = false;
+ isOpen = false;
+ emit closed();
+ }
+}
+
+void QNetworkSessionPrivateImpl::stop()
+{
+ if (serviceConfig.isValid()) {
+ lastError = QNetworkSession::OperationNotSupportedError;
+ emit QNetworkSessionPrivate::error(lastError);
+ } else {
+ if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+ state = QNetworkSession::Closing;
+ emit stateChanged(state);
+
+ engine->disconnectFromId(activeConfig.identifier());
+
+ sessionManager()->forceSessionClose(activeConfig);
+ }
+
+ opened = false;
+ isOpen = false;
+ emit closed();
+ }
+}
+
+void QNetworkSessionPrivateImpl::migrate()
+{
+ qWarning("This platform does not support roaming (%s).", __FUNCTION__);
+}
+
+void QNetworkSessionPrivateImpl::accept()
+{
+ qWarning("This platform does not support roaming (%s).", __FUNCTION__);
+}
+
+void QNetworkSessionPrivateImpl::ignore()
+{
+ qWarning("This platform does not support roaming (%s).", __FUNCTION__);
+}
+
+void QNetworkSessionPrivateImpl::reject()
+{
+ qWarning("This platform does not support roaming (%s).", __FUNCTION__);
+}
+
+QNetworkInterface QNetworkSessionPrivateImpl::currentInterface() const
+{
+ if (!publicConfig.isValid() || !engine || state != QNetworkSession::Connected)
+ return QNetworkInterface();
+
+ QString interface = engine->getInterfaceFromId(activeConfig.identifier());
+
+ if (interface.isEmpty())
+ return QNetworkInterface();
+ return QNetworkInterface::interfaceFromName(interface);
+}
+
+QVariant QNetworkSessionPrivateImpl::sessionProperty(const QString& /*key*/) const
+{
+ return QVariant();
+}
+
+void QNetworkSessionPrivateImpl::setSessionProperty(const QString& /*key*/, const QVariant& /*value*/)
+{
+}
+
+QString QNetworkSessionPrivateImpl::errorString() const
+{
+ switch (lastError) {
+ case QNetworkSession::UnknownSessionError:
+ return tr("Unknown session error.");
+ case QNetworkSession::SessionAbortedError:
+ return tr("The session was aborted by the user or system.");
+ case QNetworkSession::OperationNotSupportedError:
+ return tr("The requested operation is not supported by the system.");
+ case QNetworkSession::InvalidConfigurationError:
+ return tr("The specified configuration cannot be used.");
+ case QNetworkSession::RoamingError:
+ return tr("Roaming was aborted or is not possible.");
+
+ }
+
+ return QString();
+}
+
+QNetworkSession::SessionError QNetworkSessionPrivateImpl::error() const
+{
+ return lastError;
+}
+
+quint64 QNetworkSessionPrivateImpl::bytesWritten() const
+{
+ if (engine && state == QNetworkSession::Connected)
+ return engine->bytesWritten(activeConfig.identifier());
+ else
+ return Q_UINT64_C(0);
+}
+
+quint64 QNetworkSessionPrivateImpl::bytesReceived() const
+{
+ if (engine && state == QNetworkSession::Connected)
+ return engine->bytesReceived(activeConfig.identifier());
+ else
+ return Q_UINT64_C(0);
+}
+
+quint64 QNetworkSessionPrivateImpl::activeTime() const
+{
+ if (state == QNetworkSession::Connected && startTime != Q_UINT64_C(0))
+ return QDateTime::currentDateTime().toTime_t() - startTime;
+ else
+ return Q_UINT64_C(0);
+}
+
+void QNetworkSessionPrivateImpl::updateStateFromServiceNetwork()
+{
+ QNetworkSession::State oldState = state;
+
+ foreach (const QNetworkConfiguration &config, serviceConfig.children()) {
+ if ((config.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active)
+ continue;
+
+ if (activeConfig != config) {
+ if (engine) {
+ disconnect(engine,
+ SIGNAL(connectionError(QString,QBearerEngineImpl::ConnectionError)),
+ this,
+ SLOT(connectionError(QString,QBearerEngineImpl::ConnectionError)));
+ }
+
+ activeConfig = config;
+ engine = getEngineFromId(activeConfig.identifier());
+ if (engine) {
+ connect(engine,
+ SIGNAL(connectionError(QString,QBearerEngineImpl::ConnectionError)),
+ this, SLOT(connectionError(QString,QBearerEngineImpl::ConnectionError)),
+ Qt::QueuedConnection);
+ }
+ emit newConfigurationActivated();
+ }
+
+ state = QNetworkSession::Connected;
+ if (state != oldState)
+ emit stateChanged(state);
+
+ return;
+ }
+
+ if (serviceConfig.children().isEmpty())
+ state = QNetworkSession::NotAvailable;
+ else
+ state = QNetworkSession::Disconnected;
+
+ if (state != oldState)
+ emit stateChanged(state);
+}
+
+void QNetworkSessionPrivateImpl::updateStateFromActiveConfig()
+{
+ if (!engine)
+ return;
+
+ QNetworkSession::State oldState = state;
+
+ state = engine->sessionStateForId(activeConfig.identifier());
+
+ bool oldActive = isOpen;
+ isOpen = (state == QNetworkSession::Connected) ? opened : false;
+
+ if (!oldActive && isOpen)
+ emit quitPendingWaitsForOpened();
+ if (oldActive && !isOpen)
+ emit closed();
+
+ if (oldState != state)
+ emit stateChanged(state);
+}
+
+void QNetworkSessionPrivateImpl::networkConfigurationsChanged()
+{
+ if (serviceConfig.isValid())
+ updateStateFromServiceNetwork();
+ else
+ updateStateFromActiveConfig();
+
+ startTime = engine->startTime(activeConfig.identifier());
+}
+
+void QNetworkSessionPrivateImpl::configurationChanged(const QNetworkConfiguration &config)
+{
+ if (serviceConfig.isValid() && (config == serviceConfig || config == activeConfig))
+ updateStateFromServiceNetwork();
+ else if (config == activeConfig)
+ updateStateFromActiveConfig();
+}
+
+void QNetworkSessionPrivateImpl::forcedSessionClose(const QNetworkConfiguration &config)
+{
+ if (activeConfig == config) {
+ opened = false;
+ isOpen = false;
+
+ emit closed();
+
+ lastError = QNetworkSession::SessionAbortedError;
+ emit QNetworkSessionPrivate::error(lastError);
+ }
+}
+
+void QNetworkSessionPrivateImpl::connectionError(const QString &id,
+ QBearerEngineImpl::ConnectionError error)
+{
+ if (activeConfig.identifier() == id) {
+ networkConfigurationsChanged();
+ switch (error) {
+ case QBearerEngineImpl::OperationNotSupported:
+ lastError = QNetworkSession::OperationNotSupportedError;
+ opened = false;
+ break;
+ case QBearerEngineImpl::InterfaceLookupError:
+ case QBearerEngineImpl::ConnectError:
+ case QBearerEngineImpl::DisconnectionError:
+ default:
+ lastError = QNetworkSession::UnknownSessionError;
+ }
+
+ emit quitPendingWaitsForOpened();
+ emit QNetworkSessionPrivate::error(lastError);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/qnetworksession_impl.h b/src/plugins/bearer/qnetworksession_impl.h
new file mode 100644
index 0000000..7349e77
--- /dev/null
+++ b/src/plugins/bearer/qnetworksession_impl.h
@@ -0,0 +1,130 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNETWORKSESSION_IMPL_H
+#define QNETWORKSESSION_IMPL_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qbearerengine_impl.h"
+
+#include <QtNetwork/private/qnetworkconfigmanager_p.h>
+#include <QtNetwork/private/qnetworksession_p.h>
+
+#include <QtCore/qdatetime.h>
+
+QT_BEGIN_NAMESPACE
+
+class QBearerEngineImpl;
+
+class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate
+{
+ Q_OBJECT
+public:
+ QNetworkSessionPrivateImpl()
+ : startTime(0)
+ {
+ }
+
+ ~QNetworkSessionPrivateImpl()
+ {
+ }
+
+ //called by QNetworkSession constructor and ensures
+ //that the state is immediately updated (w/o actually opening
+ //a session). Also this function should take care of
+ //notification hooks to discover future state changes.
+ void syncStateWithInterface();
+
+ QNetworkInterface currentInterface() const;
+ QVariant sessionProperty(const QString& key) const;
+ void setSessionProperty(const QString& key, const QVariant& value);
+
+ void open();
+ void close();
+ void stop();
+ void migrate();
+ void accept();
+ void ignore();
+ void reject();
+
+ QString errorString() const; //must return translated string
+ QNetworkSession::SessionError error() const;
+
+ quint64 bytesWritten() const;
+ quint64 bytesReceived() const;
+ quint64 activeTime() const;
+
+private:
+ void updateStateFromServiceNetwork();
+ void updateStateFromActiveConfig();
+
+private Q_SLOTS:
+ void networkConfigurationsChanged();
+ void configurationChanged(const QNetworkConfiguration &config);
+ void forcedSessionClose(const QNetworkConfiguration &config);
+ void connectionError(const QString &id, QBearerEngineImpl::ConnectionError error);
+
+private:
+ QNetworkConfigurationManager manager;
+
+ bool opened;
+
+ QBearerEngineImpl *engine;
+
+ QNetworkSession::SessionError lastError;
+
+ quint64 startTime;
+};
+
+QT_END_NAMESPACE
+
+#endif //QNETWORKSESSION_IMPL_H
+
diff --git a/src/plugins/bearer/symbian/main.cpp b/src/plugins/bearer/symbian/main.cpp
new file mode 100644
index 0000000..0321451
--- /dev/null
+++ b/src/plugins/bearer/symbian/main.cpp
@@ -0,0 +1,84 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "symbianengine.h"
+
+#include <QtNetwork/private/qbearerplugin_p.h>
+
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_NAMESPACE
+
+class QSymbianEnginePlugin : public QBearerEnginePlugin
+{
+public:
+ QSymbianEnginePlugin();
+ ~QSymbianEnginePlugin();
+
+ QStringList keys() const;
+ QBearerEngine *create(const QString &key) const;
+};
+
+QSymbianEnginePlugin::QSymbianEnginePlugin()
+{
+}
+
+QSymbianEnginePlugin::~QSymbianEnginePlugin()
+{
+}
+
+QStringList QSymbianEnginePlugin::keys() const
+{
+ return QStringList() << QLatin1String("symbian");
+}
+
+QBearerEngine *QSymbianEnginePlugin::create(const QString &key) const
+{
+ if (key == QLatin1String("symbian"))
+ return new SymbianEngine;
+ else
+ return 0;
+}
+
+Q_EXPORT_STATIC_PLUGIN(QSymbianEnginePlugin)
+Q_EXPORT_PLUGIN2(qsymbianbearer, QSymbianEnginePlugin)
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.cpp b/src/plugins/bearer/symbian/qnetworksession_impl.cpp
new file mode 100644
index 0000000..9af1fe9
--- /dev/null
+++ b/src/plugins/bearer/symbian/qnetworksession_impl.cpp
@@ -0,0 +1,1135 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qnetworksession_impl.h"
+#include "symbianengine.h"
+
+#include <es_enum.h>
+#include <es_sock.h>
+#include <in_sock.h>
+#include <stdapis/sys/socket.h>
+#include <stdapis/net/if.h>
+
+QT_BEGIN_NAMESPACE
+
+QNetworkSessionPrivateImpl::QNetworkSessionPrivateImpl(SymbianEngine *engine)
+ : CActive(CActive::EPriorityStandard), engine(engine), ipConnectionNotifier(0),
+ iError(QNetworkSession::UnknownSessionError),
+ iALREnabled(0)
+{
+ CActiveScheduler::Add(this);
+
+ // Try to load "Open C" dll dynamically and
+ // try to attach to setdefaultif function dynamically.
+ if (iOpenCLibrary.Load(_L("libc")) == KErrNone) {
+ iDynamicSetdefaultif = (TOpenCSetdefaultifFunction)iOpenCLibrary.Lookup(564);
+ }
+
+ TRAP_IGNORE(iConnectionMonitor.ConnectL());
+}
+
+QNetworkSessionPrivateImpl::~QNetworkSessionPrivateImpl()
+{
+ isOpen = false;
+
+ // Cancel Connection Progress Notifications first.
+ // Note: ConnectionNotifier must be destroyed before Canceling RConnection::Start()
+ // => deleting ipConnectionNotifier results RConnection::CancelProgressNotification()
+ delete ipConnectionNotifier;
+ ipConnectionNotifier = NULL;
+
+ // Cancel possible RConnection::Start()
+ Cancel();
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (iMobility) {
+ delete iMobility;
+ iMobility = NULL;
+ }
+#endif
+
+ iConnection.Close();
+ iSocketServ.Close();
+ if (iDynamicSetdefaultif) {
+ iDynamicSetdefaultif(0);
+ }
+
+ iConnectionMonitor.CancelNotifications();
+ iConnectionMonitor.Close();
+
+ iOpenCLibrary.Close();
+}
+
+void QNetworkSessionPrivateImpl::syncStateWithInterface()
+{
+ if (!privateConfiguration(publicConfig))
+ return;
+
+ // Start monitoring changes in IAP states
+ TRAP_IGNORE(iConnectionMonitor.NotifyEventL(*this));
+
+ // Check open connections to see if there is already
+ // an open connection to selected IAP or SNAP
+ TUint count;
+ TRequestStatus status;
+ iConnectionMonitor.GetConnectionCount(count, status);
+ User::WaitForRequest(status);
+ if (status.Int() != KErrNone) {
+ return;
+ }
+
+ TUint numSubConnections;
+ TUint connectionId;
+ for (TUint i = 1; i <= count; i++) {
+ TInt ret = iConnectionMonitor.GetConnectionInfo(i, connectionId, numSubConnections);
+ if (ret == KErrNone) {
+ TUint apId;
+ iConnectionMonitor.GetUintAttribute(connectionId, 0, KIAPId, apId, status);
+ User::WaitForRequest(status);
+ if (status.Int() == KErrNone) {
+ TInt connectionStatus;
+ iConnectionMonitor.GetIntAttribute(connectionId, 0, KConnectionStatus, connectionStatus, status);
+ User::WaitForRequest(status);
+ if (connectionStatus == KLinkLayerOpen) {
+ if (state != QNetworkSession::Closing) {
+ if (newState(QNetworkSession::Connected, apId)) {
+ return;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (state != QNetworkSession::Connected) {
+ // There were no open connections to used IAP or SNAP
+ if ((privateConfiguration(publicConfig)->state & QNetworkConfiguration::Discovered) ==
+ QNetworkConfiguration::Discovered) {
+ newState(QNetworkSession::Disconnected);
+ } else {
+ newState(QNetworkSession::NotAvailable);
+ }
+ }
+}
+
+QNetworkInterface QNetworkSessionPrivateImpl::interface(TUint iapId) const
+{
+ QString interfaceName;
+
+ TSoInetInterfaceInfo ifinfo;
+ TPckg<TSoInetInterfaceInfo> ifinfopkg(ifinfo);
+ TSoInetIfQuery ifquery;
+ TPckg<TSoInetIfQuery> ifquerypkg(ifquery);
+
+ // Open dummy socket for interface queries
+ RSocket socket;
+ TInt retVal = socket.Open(iSocketServ, _L("udp"));
+ if (retVal != KErrNone) {
+ return QNetworkInterface();
+ }
+
+ // Start enumerating interfaces
+ socket.SetOpt(KSoInetEnumInterfaces, KSolInetIfCtrl);
+ while(socket.GetOpt(KSoInetNextInterface, KSolInetIfCtrl, ifinfopkg) == KErrNone) {
+ ifquery.iName = ifinfo.iName;
+ TInt err = socket.GetOpt(KSoInetIfQueryByName, KSolInetIfQuery, ifquerypkg);
+ if(err == KErrNone && ifquery.iZone[1] == iapId) { // IAP ID is index 1 of iZone
+ if(ifinfo.iAddress.Address() > 0) {
+ interfaceName = QString::fromUtf16(ifinfo.iName.Ptr(),ifinfo.iName.Length());
+ break;
+ }
+ }
+ }
+
+ socket.Close();
+
+ if (interfaceName.isEmpty()) {
+ return QNetworkInterface();
+ }
+
+ return QNetworkInterface::interfaceFromName(interfaceName);
+}
+
+QNetworkInterface QNetworkSessionPrivateImpl::currentInterface() const
+{
+ if (!publicConfig.isValid() || state != QNetworkSession::Connected) {
+ return QNetworkInterface();
+ }
+
+ return activeInterface;
+}
+
+QVariant QNetworkSessionPrivateImpl::sessionProperty(const QString& /*key*/) const
+{
+ return QVariant();
+}
+
+void QNetworkSessionPrivateImpl::setSessionProperty(const QString& /*key*/, const QVariant& /*value*/)
+{
+}
+
+QString QNetworkSessionPrivateImpl::errorString() const
+{
+ switch (iError) {
+ case QNetworkSession::UnknownSessionError:
+ return tr("Unknown session error.");
+ case QNetworkSession::SessionAbortedError:
+ return tr("The session was aborted by the user or system.");
+ case QNetworkSession::OperationNotSupportedError:
+ return tr("The requested operation is not supported by the system.");
+ case QNetworkSession::InvalidConfigurationError:
+ return tr("The specified configuration cannot be used.");
+ case QNetworkSession::RoamingError:
+ return tr("Roaming was aborted or is not possible.");
+ }
+
+ return QString();
+}
+
+QNetworkSession::SessionError QNetworkSessionPrivateImpl::error() const
+{
+ return iError;
+}
+
+void QNetworkSessionPrivateImpl::open()
+{
+ if (isOpen || !privateConfiguration(publicConfig) || (state == QNetworkSession::Connecting)) {
+ return;
+ }
+
+ // Cancel notifications from RConnectionMonitor
+ // => RConnection::ProgressNotification will be used for IAP/SNAP monitoring
+ iConnectionMonitor.CancelNotifications();
+
+ TInt error = iSocketServ.Connect();
+ if (error != KErrNone) {
+ // Could not open RSocketServ
+ newState(QNetworkSession::Invalid);
+ iError = QNetworkSession::UnknownSessionError;
+ emit QNetworkSessionPrivate::error(iError);
+ syncStateWithInterface();
+ return;
+ }
+
+ error = iConnection.Open(iSocketServ);
+ if (error != KErrNone) {
+ // Could not open RConnection
+ iSocketServ.Close();
+ newState(QNetworkSession::Invalid);
+ iError = QNetworkSession::UnknownSessionError;
+ emit QNetworkSessionPrivate::error(iError);
+ syncStateWithInterface();
+ return;
+ }
+
+ // Use RConnection::ProgressNotification for IAP/SNAP monitoring
+ // (<=> ConnectionProgressNotifier uses RConnection::ProgressNotification)
+ if (!ipConnectionNotifier) {
+ ipConnectionNotifier = new ConnectionProgressNotifier(*this,iConnection);
+ }
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StartNotifications();
+ }
+
+ if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
+ // Search through existing connections.
+ // If there is already connection which matches to given IAP
+ // try to attach to existing connection.
+ TBool connected(EFalse);
+ TConnectionInfoBuf connInfo;
+ TUint count;
+ if (iConnection.EnumerateConnections(count) == KErrNone) {
+ for (TUint i=1; i<=count; i++) {
+ // Note: GetConnectionInfo expects 1-based index.
+ if (iConnection.GetConnectionInfo(i, connInfo) == KErrNone) {
+ if (connInfo().iIapId == toSymbianConfig(privateConfiguration(publicConfig))->numericId) {
+ if (iConnection.Attach(connInfo, RConnection::EAttachTypeNormal) == KErrNone) {
+ activeConfig = publicConfig;
+ activeInterface = interface(toSymbianConfig(privateConfiguration(activeConfig))->numericId);
+ connected = ETrue;
+ startTime = QDateTime::currentDateTime();
+ if (iDynamicSetdefaultif) {
+ // Use name of the IAP to set default IAP
+ QByteArray nameAsByteArray = publicConfig.name().toUtf8();
+ ifreq ifr;
+ strcpy(ifr.ifr_name, nameAsByteArray.constData());
+
+ error = iDynamicSetdefaultif(&ifr);
+ }
+ isOpen = true;
+ // Make sure that state will be Connected
+ newState(QNetworkSession::Connected);
+ emit quitPendingWaitsForOpened();
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (!connected) {
+ TCommDbConnPref pref;
+ pref.SetDialogPreference(ECommDbDialogPrefDoNotPrompt);
+ pref.SetIapId(toSymbianConfig(privateConfiguration(publicConfig))->numericId);
+ iConnection.Start(pref, iStatus);
+ if (!IsActive()) {
+ SetActive();
+ }
+ newState(QNetworkSession::Connecting);
+ }
+ } else if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
+ TConnSnapPref snapPref(toSymbianConfig(privateConfiguration(publicConfig))->numericId);
+ iConnection.Start(snapPref, iStatus);
+ if (!IsActive()) {
+ SetActive();
+ }
+ newState(QNetworkSession::Connecting);
+ } else if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ iKnownConfigsBeforeConnectionStart = engine->accessPointConfigurationIdentifiers();
+ iConnection.Start(iStatus);
+ if (!IsActive()) {
+ SetActive();
+ }
+ newState(QNetworkSession::Connecting);
+ }
+
+ if (error != KErrNone) {
+ isOpen = false;
+ iError = QNetworkSession::UnknownSessionError;
+ emit QNetworkSessionPrivate::error(iError);
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StopNotifications();
+ }
+ syncStateWithInterface();
+ }
+}
+
+TUint QNetworkSessionPrivateImpl::iapClientCount(TUint aIAPId) const
+{
+ TRequestStatus status;
+ TUint connectionCount;
+ iConnectionMonitor.GetConnectionCount(connectionCount, status);
+ User::WaitForRequest(status);
+ if (status.Int() == KErrNone) {
+ for (TUint i = 1; i <= connectionCount; i++) {
+ TUint connectionId;
+ TUint subConnectionCount;
+ iConnectionMonitor.GetConnectionInfo(i, connectionId, subConnectionCount);
+ TUint apId;
+ iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
+ User::WaitForRequest(status);
+ if (apId == aIAPId) {
+ TConnMonClientEnumBuf buf;
+ iConnectionMonitor.GetPckgAttribute(connectionId, 0, KClientInfo, buf, status);
+ User::WaitForRequest(status);
+ if (status.Int() == KErrNone) {
+ return buf().iCount;
+ }
+ }
+ }
+ }
+ return 0;
+}
+
+void QNetworkSessionPrivateImpl::close(bool allowSignals)
+{
+ if (!isOpen) {
+ return;
+ }
+
+ TUint activeIap = toSymbianConfig(privateConfiguration(activeConfig))->numericId;
+ isOpen = false;
+ activeConfig = QNetworkConfiguration();
+ serviceConfig = QNetworkConfiguration();
+
+ Cancel();
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (iMobility) {
+ delete iMobility;
+ iMobility = NULL;
+ }
+#endif
+
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StopNotifications();
+ }
+
+ iConnection.Close();
+ iSocketServ.Close();
+ if (iDynamicSetdefaultif) {
+ iDynamicSetdefaultif(0);
+ }
+
+#ifdef Q_CC_NOKIAX86
+ if ((allowSignals && iapClientCount(activeIap) <= 0) ||
+#else
+ if ((allowSignals && iapClientCount(activeIap) <= 1) ||
+#endif
+ (publicConfig.type() == QNetworkConfiguration::UserChoice)) {
+ newState(QNetworkSession::Closing);
+ }
+
+ syncStateWithInterface();
+ if (allowSignals) {
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ newState(QNetworkSession::Disconnected);
+ }
+ emit closed();
+ }
+}
+
+void QNetworkSessionPrivateImpl::stop()
+{
+ if (!isOpen) {
+ return;
+ }
+ isOpen = false;
+ newState(QNetworkSession::Closing);
+ iConnection.Stop(RConnection::EStopAuthoritative);
+ isOpen = true;
+ close(false);
+ emit closed();
+}
+
+void QNetworkSessionPrivateImpl::migrate()
+{
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ iMobility->MigrateToPreferredCarrier();
+#endif
+}
+
+void QNetworkSessionPrivateImpl::ignore()
+{
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ iMobility->IgnorePreferredCarrier();
+ if (!iALRUpgradingConnection) {
+ newState(QNetworkSession::Disconnected);
+ } else {
+ newState(QNetworkSession::Connected,iOldRoamingIap);
+ }
+#endif
+}
+
+void QNetworkSessionPrivateImpl::accept()
+{
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ iMobility->NewCarrierAccepted();
+ if (iDynamicSetdefaultif) {
+ // Use name of the IAP to set default IAP
+ QByteArray nameAsByteArray = activeConfig.name().toUtf8();
+ ifreq ifr;
+ strcpy(ifr.ifr_name, nameAsByteArray.constData());
+
+ iDynamicSetdefaultif(&ifr);
+ }
+ newState(QNetworkSession::Connected, iNewRoamingIap);
+#endif
+}
+
+void QNetworkSessionPrivateImpl::reject()
+{
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ iMobility->NewCarrierRejected();
+ if (!iALRUpgradingConnection) {
+ newState(QNetworkSession::Disconnected);
+ } else {
+ newState(QNetworkSession::Connected, iOldRoamingIap);
+ }
+#endif
+}
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+void QNetworkSessionPrivateImpl::PreferredCarrierAvailable(TAccessPointInfo aOldAPInfo,
+ TAccessPointInfo aNewAPInfo,
+ TBool aIsUpgrade,
+ TBool aIsSeamless)
+{
+ iOldRoamingIap = aOldAPInfo.AccessPoint();
+ iNewRoamingIap = aNewAPInfo.AccessPoint();
+ newState(QNetworkSession::Roaming);
+ if (iALREnabled > 0) {
+ iALRUpgradingConnection = aIsUpgrade;
+ QList<QNetworkConfiguration> configs = publicConfig.children();
+ for (int i=0; i < configs.count(); i++) {
+ if (toSymbianConfig(privateConfiguration(configs[i]))->numericId == aNewAPInfo.AccessPoint()) {
+ emit preferredConfigurationChanged(configs[i], aIsSeamless);
+ }
+ }
+ } else {
+ migrate();
+ }
+}
+
+void QNetworkSessionPrivateImpl::NewCarrierActive(TAccessPointInfo /*aNewAPInfo*/, TBool /*aIsSeamless*/)
+{
+ if (iALREnabled > 0) {
+ emit newConfigurationActivated();
+ } else {
+ accept();
+ }
+}
+
+void QNetworkSessionPrivateImpl::Error(TInt /*aError*/)
+{
+ if (isOpen) {
+ isOpen = false;
+ activeConfig = QNetworkConfiguration();
+ serviceConfig = QNetworkConfiguration();
+ iError = QNetworkSession::RoamingError;
+ emit QNetworkSessionPrivate::error(iError);
+ Cancel();
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StopNotifications();
+ }
+ syncStateWithInterface();
+ // In some cases IAP is still in Connected state when
+ // syncStateWithInterface(); is called
+ // => Following call makes sure that Session state
+ // changes immediately to Disconnected.
+ newState(QNetworkSession::Disconnected);
+ emit closed();
+ }
+}
+#endif
+
+void QNetworkSessionPrivateImpl::setALREnabled(bool enabled)
+{
+ if (enabled) {
+ iALREnabled++;
+ } else {
+ iALREnabled--;
+ }
+}
+
+QNetworkConfiguration QNetworkSessionPrivateImpl::bestConfigFromSNAP(const QNetworkConfiguration& snapConfig) const
+{
+ QNetworkConfiguration config;
+ QList<QNetworkConfiguration> subConfigurations = snapConfig.children();
+ for (int i = 0; i < subConfigurations.count(); i++ ) {
+ if (subConfigurations[i].state() == QNetworkConfiguration::Active) {
+ config = subConfigurations[i];
+ break;
+ } else if (!config.isValid() && subConfigurations[i].state() == QNetworkConfiguration::Discovered) {
+ config = subConfigurations[i];
+ }
+ }
+ if (!config.isValid() && subConfigurations.count() > 0) {
+ config = subConfigurations[0];
+ }
+ return config;
+}
+
+quint64 QNetworkSessionPrivateImpl::bytesWritten() const
+{
+ return transferredData(KUplinkData);
+}
+
+quint64 QNetworkSessionPrivateImpl::bytesReceived() const
+{
+ return transferredData(KDownlinkData);
+}
+
+quint64 QNetworkSessionPrivateImpl::transferredData(TUint dataType) const
+{
+ if (!publicConfig.isValid()) {
+ return 0;
+ }
+
+ QNetworkConfiguration config;
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ if (serviceConfig.isValid()) {
+ config = serviceConfig;
+ } else {
+ if (activeConfig.isValid()) {
+ config = activeConfig;
+ }
+ }
+ } else {
+ config = publicConfig;
+ }
+
+ if (!config.isValid()) {
+ return 0;
+ }
+
+ TUint count;
+ TRequestStatus status;
+ iConnectionMonitor.GetConnectionCount(count, status);
+ User::WaitForRequest(status);
+ if (status.Int() != KErrNone) {
+ return 0;
+ }
+
+ TUint transferredData = 0;
+ TUint numSubConnections;
+ TUint connectionId;
+ bool configFound;
+ for (TUint i = 1; i <= count; i++) {
+ TInt ret = iConnectionMonitor.GetConnectionInfo(i, connectionId, numSubConnections);
+ if (ret == KErrNone) {
+ TUint apId;
+ iConnectionMonitor.GetUintAttribute(connectionId, 0, KIAPId, apId, status);
+ User::WaitForRequest(status);
+ if (status.Int() == KErrNone) {
+ configFound = false;
+ if (config.type() == QNetworkConfiguration::ServiceNetwork) {
+ QList<QNetworkConfiguration> configs = config.children();
+ for (int i=0; i < configs.count(); i++) {
+ if (toSymbianConfig(privateConfiguration(configs[i]))->numericId == apId) {
+ configFound = true;
+ break;
+ }
+ }
+ } else if (toSymbianConfig(privateConfiguration(config))->numericId == apId) {
+ configFound = true;
+ }
+ if (configFound) {
+ TUint tData;
+ iConnectionMonitor.GetUintAttribute(connectionId, 0, dataType, tData, status );
+ User::WaitForRequest(status);
+ if (status.Int() == KErrNone) {
+ transferredData += tData;
+ }
+ }
+ }
+ }
+ }
+
+ return transferredData;
+}
+
+quint64 QNetworkSessionPrivateImpl::activeTime() const
+{
+ if (!isOpen || startTime.isNull()) {
+ return 0;
+ }
+ return startTime.secsTo(QDateTime::currentDateTime());
+}
+
+QNetworkConfiguration QNetworkSessionPrivateImpl::activeConfiguration(TUint32 iapId) const
+{
+ if (iapId == 0) {
+ _LIT(KSetting, "IAP\\Id");
+ iConnection.GetIntSetting(KSetting, iapId);
+ }
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
+ // Try to search IAP from the used SNAP using IAP Id
+ QList<QNetworkConfiguration> children = publicConfig.children();
+ for (int i=0; i < children.count(); i++) {
+ if (toSymbianConfig(privateConfiguration(children[i]))->numericId == iapId) {
+ return children[i];
+ }
+ }
+
+ // Given IAP Id was not found from the used SNAP
+ // => Try to search matching IAP using mappingName
+ // mappingName contains:
+ // 1. "Access point name" for "Packet data" Bearer
+ // 2. "WLAN network name" (= SSID) for "Wireless LAN" Bearer
+ // 3. "Dial-up number" for "Data call Bearer" or "High Speed (GSM)" Bearer
+ // <=> Note: It's possible that in this case reported IAP is
+ // clone of the one of the IAPs of the used SNAP
+ // => If mappingName matches, clone has been found
+ QNetworkConfiguration pt = QNetworkConfigurationManager().configurationFromIdentifier(QString::number(qHash(iapId)));
+ if (privateConfiguration(pt)) {
+ for (int i=0; i < children.count(); i++) {
+ if (toSymbianConfig(privateConfiguration(children[i]))->mappingName == toSymbianConfig(privateConfiguration(pt))->mappingName) {
+ return children[i];
+ }
+ }
+ } else {
+ // Given IAP Id was not found from known IAPs array
+ return QNetworkConfiguration();
+ }
+
+ // Matching IAP was not found from used SNAP
+ // => IAP from another SNAP is returned
+ // (Note: Returned IAP matches to given IAP Id)
+ return pt;
+ }
+#endif
+
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ if (engine) {
+ QNetworkConfiguration pt = QNetworkConfigurationManager().configurationFromIdentifier(QString::number(qHash(iapId)));
+ // Try to found User Selected IAP from known IAPs (accessPointConfigurations)
+ if (pt.isValid()) {
+ return pt;
+ } else {
+ // Check if new (WLAN) IAP was created in IAP/SNAP dialog
+ // 1. Sync internal configurations array to commsdb first
+ engine->updateConfigurations();
+ // 2. Check if new configuration was created during connection creation
+ 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::RunL()
+{
+ TInt statusCode = iStatus.Int();
+
+ switch (statusCode) {
+ case KErrNone: // Connection created succesfully
+ {
+ TInt error = KErrNone;
+ QNetworkConfiguration newActiveConfig = activeConfiguration();
+ if (!newActiveConfig.isValid()) {
+ error = KErrGeneral;
+ } else if (iDynamicSetdefaultif) {
+ // Use name of the IAP to set default IAP
+ QByteArray nameAsByteArray = newActiveConfig.name().toUtf8();
+ ifreq ifr;
+ strcpy(ifr.ifr_name, nameAsByteArray.constData());
+
+ error = iDynamicSetdefaultif(&ifr);
+ }
+
+ if (error != KErrNone) {
+ isOpen = false;
+ iError = QNetworkSession::UnknownSessionError;
+ emit QNetworkSessionPrivate::error(iError);
+ Cancel();
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StopNotifications();
+ }
+ syncStateWithInterface();
+ return;
+ }
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
+ // Activate ALR monitoring
+ iMobility = CActiveCommsMobilityApiExt::NewL(iConnection, *this);
+ }
+#endif
+ isOpen = true;
+ activeConfig = newActiveConfig;
+ activeInterface = interface(toSymbianConfig(privateConfiguration(activeConfig))->numericId);
+ if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+ serviceConfig = QNetworkConfigurationManager().configurationFromIdentifier(toSymbianConfig(privateConfiguration(activeConfig))->serviceNetworkPtr->id);
+ }
+
+ startTime = QDateTime::currentDateTime();
+
+ newState(QNetworkSession::Connected);
+ emit quitPendingWaitsForOpened();
+ }
+ break;
+ case KErrNotFound: // Connection failed
+ isOpen = false;
+ activeConfig = QNetworkConfiguration();
+ serviceConfig = QNetworkConfiguration();
+ iError = QNetworkSession::InvalidConfigurationError;
+ emit QNetworkSessionPrivate::error(iError);
+ Cancel();
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StopNotifications();
+ }
+ syncStateWithInterface();
+ break;
+ case KErrCancel: // Connection attempt cancelled
+ case KErrAlreadyExists: // Connection already exists
+ default:
+ isOpen = false;
+ activeConfig = QNetworkConfiguration();
+ serviceConfig = QNetworkConfiguration();
+ iError = QNetworkSession::UnknownSessionError;
+ emit QNetworkSessionPrivate::error(iError);
+ Cancel();
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StopNotifications();
+ }
+ syncStateWithInterface();
+ break;
+ }
+}
+
+void QNetworkSessionPrivateImpl::DoCancel()
+{
+ iConnection.Close();
+}
+
+bool QNetworkSessionPrivateImpl::newState(QNetworkSession::State newState, TUint accessPointId)
+{
+ // Make sure that activeConfig is always updated when SNAP is signaled to be
+ // connected.
+ if (isOpen && publicConfig.type() == QNetworkConfiguration::ServiceNetwork &&
+ newState == QNetworkSession::Connected) {
+ activeConfig = activeConfiguration(accessPointId);
+ activeInterface = interface(toSymbianConfig(privateConfiguration(activeConfig))->numericId);
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ if (iDynamicSetdefaultif) {
+ // Use name of the IAP to set default IAP
+ QByteArray nameAsByteArray = activeConfig.name().toUtf8();
+ ifreq ifr;
+ strcpy(ifr.ifr_name, nameAsByteArray.constData());
+
+ iDynamicSetdefaultif(&ifr);
+ }
+#endif
+ }
+
+ // Make sure that same state is not signaled twice in a row.
+ if (state == newState) {
+ return true;
+ }
+
+ // Make sure that Connecting state does not overwrite Roaming state
+ if (state == QNetworkSession::Roaming && newState == QNetworkSession::Connecting) {
+ return false;
+ }
+
+ bool emitSessionClosed = false;
+ if (isOpen && state == QNetworkSession::Connected && newState == QNetworkSession::Disconnected) {
+ // Active & Connected state should change directly to Disconnected state
+ // only when something forces connection to close (eg. when another
+ // application or session stops connection or when network drops
+ // unexpectedly).
+ isOpen = false;
+ activeConfig = QNetworkConfiguration();
+ serviceConfig = QNetworkConfiguration();
+ iError = QNetworkSession::SessionAbortedError;
+ emit QNetworkSessionPrivate::error(iError);
+ Cancel();
+ if (ipConnectionNotifier) {
+ ipConnectionNotifier->StopNotifications();
+ }
+ // Start monitoring changes in IAP states
+ TRAP_IGNORE(iConnectionMonitor.NotifyEventL(*this));
+ emitSessionClosed = true; // Emit SessionClosed after state change has been reported
+ }
+
+ bool retVal = false;
+ if (accessPointId == 0) {
+ state = newState;
+ emit stateChanged(state);
+ retVal = true;
+ } else {
+ if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
+ if (toSymbianConfig(privateConfiguration(publicConfig))->numericId == accessPointId) {
+ state = newState;
+ emit stateChanged(state);
+ retVal = true;
+ }
+ } else if (publicConfig.type() == QNetworkConfiguration::UserChoice && isOpen) {
+ if (toSymbianConfig(privateConfiguration(activeConfig))->numericId == accessPointId) {
+ state = newState;
+ emit stateChanged(state);
+ retVal = true;
+ }
+ } else if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
+ QList<QNetworkConfiguration> subConfigurations = publicConfig.children();
+ for (int i = 0; i < subConfigurations.count(); i++) {
+ if (toSymbianConfig(privateConfiguration(subConfigurations[i]))->numericId == accessPointId) {
+ if (newState == QNetworkSession::Connected) {
+ // Make sure that when AccessPoint is reported to be Connected
+ // also state of the related configuration changes to Active.
+ privateConfiguration(subConfigurations[i])->state = QNetworkConfiguration::Active;
+
+ state = newState;
+ emit stateChanged(state);
+ retVal = true;
+ } else {
+ if (newState == QNetworkSession::Disconnected) {
+ // Make sure that when AccessPoint is reported to be disconnected
+ // also state of the related configuration changes from Active to Defined.
+ privateConfiguration(subConfigurations[i])->state = QNetworkConfiguration::Defined;
+ }
+ QNetworkConfiguration config = bestConfigFromSNAP(publicConfig);
+ if ((config.state() == QNetworkConfiguration::Defined) ||
+ (config.state() == QNetworkConfiguration::Discovered)) {
+ state = newState;
+ emit stateChanged(state);
+ retVal = true;
+ }
+ }
+ }
+ }
+ }
+ }
+
+ if (emitSessionClosed) {
+ emit closed();
+ }
+
+ return retVal;
+}
+
+void QNetworkSessionPrivateImpl::handleSymbianConnectionStatusChange(TInt aConnectionStatus,
+ TInt aError,
+ TUint accessPointId)
+{
+ switch (aConnectionStatus)
+ {
+ // Connection unitialised
+ case KConnectionUninitialised:
+ break;
+
+ // Starting connetion selection
+ case KStartingSelection:
+ break;
+
+ // Selection finished
+ case KFinishedSelection:
+ if (aError == KErrNone)
+ {
+ // The user successfully selected an IAP to be used
+ break;
+ }
+ else
+ {
+ // The user pressed e.g. "Cancel" and did not select an IAP
+ newState(QNetworkSession::Disconnected,accessPointId);
+ }
+ break;
+
+ // Connection failure
+ case KConnectionFailure:
+ newState(QNetworkSession::NotAvailable);
+ break;
+
+ // Prepearing connection (e.g. dialing)
+ case KPsdStartingConfiguration:
+ case KPsdFinishedConfiguration:
+ case KCsdFinishedDialling:
+ case KCsdScanningScript:
+ case KCsdGettingLoginInfo:
+ case KCsdGotLoginInfo:
+ break;
+
+ // Creating connection (e.g. GPRS activation)
+ case KCsdStartingConnect:
+ case KCsdFinishedConnect:
+ newState(QNetworkSession::Connecting,accessPointId);
+ break;
+
+ // Starting log in
+ case KCsdStartingLogIn:
+ break;
+
+ // Finished login
+ case KCsdFinishedLogIn:
+ break;
+
+ // Connection open
+ case KConnectionOpen:
+ break;
+
+ case KLinkLayerOpen:
+ newState(QNetworkSession::Connected,accessPointId);
+ break;
+
+ // Connection blocked or suspended
+ case KDataTransferTemporarilyBlocked:
+ break;
+
+ // Hangup or GRPS deactivation
+ case KConnectionStartingClose:
+ newState(QNetworkSession::Closing,accessPointId);
+ break;
+
+ // Connection closed
+ case KConnectionClosed:
+ break;
+
+ case KLinkLayerClosed:
+ newState(QNetworkSession::Disconnected,accessPointId);
+ break;
+
+ // Unhandled state
+ default:
+ break;
+ }
+}
+
+void QNetworkSessionPrivateImpl::EventL(const CConnMonEventBase& aEvent)
+{
+ switch (aEvent.EventType())
+ {
+ case EConnMonConnectionStatusChange:
+ {
+ CConnMonConnectionStatusChange* realEvent;
+ realEvent = (CConnMonConnectionStatusChange*) &aEvent;
+
+ TUint connectionId = realEvent->ConnectionId();
+ TInt connectionStatus = realEvent->ConnectionStatus();
+
+ // Try to Find IAP Id using connection Id
+ TUint apId = 0;
+ if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
+ QList<QNetworkConfiguration> subConfigurations = publicConfig.children();
+ for (int i = 0; i < subConfigurations.count(); i++ ) {
+ if (toSymbianConfig(privateConfiguration(subConfigurations[i]))->connectionId == connectionId) {
+ apId = toSymbianConfig(privateConfiguration(subConfigurations[i]))->numericId;
+ break;
+ }
+ }
+ } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
+ if (toSymbianConfig(privateConfiguration(publicConfig))->connectionId == connectionId) {
+ apId = toSymbianConfig(privateConfiguration(publicConfig))->numericId;
+ }
+ }
+
+ if (apId > 0) {
+ handleSymbianConnectionStatusChange(connectionStatus, KErrNone, apId);
+ }
+ }
+ break;
+
+ case EConnMonCreateConnection:
+ {
+ CConnMonCreateConnection* realEvent;
+ realEvent = (CConnMonCreateConnection*) &aEvent;
+ TUint apId;
+ TUint connectionId = realEvent->ConnectionId();
+ TRequestStatus status;
+ iConnectionMonitor.GetUintAttribute(connectionId, 0, KIAPId, apId, status);
+ User::WaitForRequest(status);
+ if (status.Int() == KErrNone) {
+ // Store connection id to related AccessPoint Configuration
+ if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
+ QList<QNetworkConfiguration> subConfigurations = publicConfig.children();
+ for (int i = 0; i < subConfigurations.count(); i++ ) {
+ if (toSymbianConfig(privateConfiguration(subConfigurations[i]))->numericId == apId) {
+ toSymbianConfig(privateConfiguration(subConfigurations[i]))->connectionId = connectionId;
+ break;
+ }
+ }
+ } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
+ if (toSymbianConfig(privateConfiguration(publicConfig))->numericId == apId) {
+ toSymbianConfig(privateConfiguration(publicConfig))->connectionId = connectionId;
+ }
+ }
+ }
+ }
+ break;
+
+ case EConnMonDeleteConnection:
+ {
+ CConnMonDeleteConnection* realEvent;
+ realEvent = (CConnMonDeleteConnection*) &aEvent;
+ TUint connectionId = realEvent->ConnectionId();
+ // Remove connection id from related AccessPoint Configuration
+ if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) {
+ QList<QNetworkConfiguration> subConfigurations = publicConfig.children();
+ for (int i = 0; i < subConfigurations.count(); i++ ) {
+ if (toSymbianConfig(privateConfiguration(subConfigurations[i]))->connectionId == connectionId) {
+ toSymbianConfig(privateConfiguration(subConfigurations[i]))->connectionId = 0;
+ break;
+ }
+ }
+ } else if (publicConfig.type() == QNetworkConfiguration::InternetAccessPoint) {
+ if (toSymbianConfig(privateConfiguration(publicConfig))->connectionId == connectionId) {
+ toSymbianConfig(privateConfiguration(publicConfig))->connectionId = 0;
+ }
+ }
+ }
+ break;
+
+ default:
+ // For unrecognized events
+ break;
+ }
+}
+
+ConnectionProgressNotifier::ConnectionProgressNotifier(QNetworkSessionPrivateImpl &owner, RConnection &connection)
+ : CActive(CActive::EPriorityStandard), iOwner(owner), iConnection(connection)
+{
+ CActiveScheduler::Add(this);
+}
+
+ConnectionProgressNotifier::~ConnectionProgressNotifier()
+{
+ Cancel();
+}
+
+void ConnectionProgressNotifier::StartNotifications()
+{
+ if (!IsActive()) {
+ SetActive();
+ }
+ iConnection.ProgressNotification(iProgress, iStatus);
+}
+
+void ConnectionProgressNotifier::StopNotifications()
+{
+ Cancel();
+}
+
+void ConnectionProgressNotifier::DoCancel()
+{
+ iConnection.CancelProgressNotification();
+}
+
+void ConnectionProgressNotifier::RunL()
+{
+ if (iStatus == KErrNone) {
+ iOwner.handleSymbianConnectionStatusChange(iProgress().iStage, iProgress().iError);
+
+ SetActive();
+ iConnection.ProgressNotification(iProgress, iStatus);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/symbian/qnetworksession_impl.h b/src/plugins/bearer/symbian/qnetworksession_impl.h
new file mode 100644
index 0000000..30f51e1
--- /dev/null
+++ b/src/plugins/bearer/symbian/qnetworksession_impl.h
@@ -0,0 +1,196 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QNETWORKSESSION_IMPL_H
+#define QNETWORKSESSION_IMPL_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtNetwork/private/qnetworksession_p.h>
+
+#include <QDateTime>
+
+#include <e32base.h>
+#include <CommDbConnPref.h>
+#include <es_sock.h>
+#include <rconnmon.h>
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ #include <comms-infras/cs_mobility_apiext.h>
+#endif
+
+typedef int(*TOpenCSetdefaultifFunction)(const struct ifreq*);
+
+QT_BEGIN_NAMESPACE
+
+class ConnectionProgressNotifier;
+class SymbianEngine;
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate, public CActive, public MMobilityProtocolResp,
+ public MConnectionMonitorObserver
+#else
+class QNetworkSessionPrivateImpl : public QNetworkSessionPrivate, public CActive, public MConnectionMonitorObserver
+#endif
+{
+ Q_OBJECT
+public:
+ QNetworkSessionPrivateImpl(SymbianEngine *engine);
+ ~QNetworkSessionPrivateImpl();
+
+ //called by QNetworkSession constructor and ensures
+ //that the state is immediately updated (w/o actually opening
+ //a session). Also this function should take care of
+ //notification hooks to discover future state changes.
+ void syncStateWithInterface();
+
+ QNetworkInterface currentInterface() const;
+ QVariant sessionProperty(const QString& key) const;
+ void setSessionProperty(const QString& key, const QVariant& value);
+
+ void setALREnabled(bool enabled);
+
+ void open();
+ inline void close() { close(true); }
+ void close(bool allowSignals);
+ void stop();
+ void migrate();
+ void accept();
+ void ignore();
+ void reject();
+
+ QString errorString() const; //must return translated string
+ QNetworkSession::SessionError error() const;
+
+ quint64 bytesWritten() const;
+ quint64 bytesReceived() const;
+ quint64 activeTime() const;
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+public: // From MMobilityProtocolResp
+ void PreferredCarrierAvailable(TAccessPointInfo aOldAPInfo,
+ TAccessPointInfo aNewAPInfo,
+ TBool aIsUpgrade,
+ TBool aIsSeamless);
+
+ void NewCarrierActive(TAccessPointInfo aNewAPInfo, TBool aIsSeamless);
+
+ void Error(TInt aError);
+#endif
+
+protected: // From CActive
+ void RunL();
+ void DoCancel();
+
+private: // MConnectionMonitorObserver
+ void EventL(const CConnMonEventBase& aEvent);
+
+private:
+ TUint iapClientCount(TUint aIAPId) const;
+ quint64 transferredData(TUint dataType) const;
+ bool newState(QNetworkSession::State newState, TUint accessPointId = 0);
+ void handleSymbianConnectionStatusChange(TInt aConnectionStatus, TInt aError, TUint accessPointId = 0);
+ QNetworkConfiguration bestConfigFromSNAP(const QNetworkConfiguration& snapConfig) const;
+ QNetworkConfiguration activeConfiguration(TUint32 iapId = 0) const;
+ QNetworkInterface interface(TUint iapId) const;
+
+private: // data
+ SymbianEngine *engine;
+
+ mutable QNetworkInterface activeInterface;
+
+ QDateTime startTime;
+
+ RLibrary iOpenCLibrary;
+ TOpenCSetdefaultifFunction iDynamicSetdefaultif;
+
+ mutable RSocketServ iSocketServ;
+ mutable RConnection iConnection;
+ mutable RConnectionMonitor iConnectionMonitor;
+ ConnectionProgressNotifier* ipConnectionNotifier;
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ CActiveCommsMobilityApiExt* iMobility;
+#endif
+
+ QNetworkSession::SessionError iError;
+ TInt iALREnabled;
+ TBool iALRUpgradingConnection;
+
+ QList<QString> iKnownConfigsBeforeConnectionStart;
+
+ TUint32 iOldRoamingIap;
+ TUint32 iNewRoamingIap;
+
+ friend class ConnectionProgressNotifier;
+};
+
+class ConnectionProgressNotifier : public CActive
+{
+public:
+ ConnectionProgressNotifier(QNetworkSessionPrivateImpl &owner, RConnection &connection);
+ ~ConnectionProgressNotifier();
+
+ void StartNotifications();
+ void StopNotifications();
+
+protected: // From CActive
+ void RunL();
+ void DoCancel();
+
+private: // Data
+ QNetworkSessionPrivateImpl &iOwner;
+ RConnection& iConnection;
+ TNifProgressBuf iProgress;
+
+};
+
+QT_END_NAMESPACE
+
+#endif //QNETWORKSESSION_IMPL_H
+
diff --git a/src/plugins/bearer/symbian/symbian.pro b/src/plugins/bearer/symbian/symbian.pro
new file mode 100644
index 0000000..9fd1a74
--- /dev/null
+++ b/src/plugins/bearer/symbian/symbian.pro
@@ -0,0 +1,37 @@
+TARGET = qsymbianbearer
+include(../../qpluginbase.pri)
+
+QT += network
+
+HEADERS += symbianengine.h \
+ qnetworksession_impl.h
+
+SOURCES += symbianengine.cpp \
+ qnetworksession_impl.cpp \
+ main.cpp
+
+exists($${EPOCROOT}epoc32/release/winscw/udeb/cmmanager.lib)| \
+exists($${EPOCROOT}epoc32/release/armv5/lib/cmmanager.lib) {
+ message("Building with SNAP support")
+ DEFINES += SNAP_FUNCTIONALITY_AVAILABLE
+ LIBS += -lcmmanager
+} else {
+ message("Building without SNAP support")
+ LIBS += -lapengine
+}
+
+INCLUDEPATH += $$APP_LAYER_SYSTEMINCLUDE
+
+LIBS += -lcommdb \
+ -lapsettingshandlerui \
+ -lconnmon \
+ -lcentralrepository \
+ -lesock \
+ -linsock \
+ -lecom \
+ -lefsrv \
+ -lnetmeta
+
+QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/bearer
+target.path += $$[QT_INSTALL_PLUGINS]/bearer
+INSTALLS += target
diff --git a/src/plugins/bearer/symbian/symbianengine.cpp b/src/plugins/bearer/symbian/symbianengine.cpp
new file mode 100644
index 0000000..b3c9cb3
--- /dev/null
+++ b/src/plugins/bearer/symbian/symbianengine.cpp
@@ -0,0 +1,1006 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "symbianengine.h"
+#include "qnetworksession_impl.h"
+
+#include <commdb.h>
+#include <cdbcols.h>
+#include <d32dbms.h>
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ #include <cmdestination.h>
+ #include <cmconnectionmethod.h>
+ #include <cmconnectionmethoddef.h>
+ #include <cmpluginwlandef.h>
+ #include <cmpluginpacketdatadef.h>
+ #include <cmplugindialcommondefs.h>
+#else
+ #include <apaccesspointitem.h>
+ #include <apdatahandler.h>
+ #include <aputils.h>
+#endif
+
+QT_BEGIN_NAMESPACE
+
+static const int KValueThatWillBeAddedToSNAPId = 1000;
+static const int KUserChoiceIAPId = 0;
+
+SymbianNetworkConfigurationPrivate::SymbianNetworkConfigurationPrivate()
+: bearer(BearerUnknown), numericId(0), connectionId(0)
+{
+}
+
+SymbianNetworkConfigurationPrivate::~SymbianNetworkConfigurationPrivate()
+{
+}
+
+QString SymbianNetworkConfigurationPrivate::bearerName() const
+{
+ switch (bearer) {
+ case BearerEthernet:
+ return QLatin1String("Ethernet");
+ case BearerWLAN:
+ return QLatin1String("WLAN");
+ case Bearer2G:
+ return QLatin1String("2G");
+ case BearerCDMA2000:
+ return QLatin1String("CDMA2000");
+ case BearerWCDMA:
+ return QLatin1String("WCDMA");
+ case BearerHSPA:
+ return QLatin1String("HSPA");
+ case BearerBluetooth:
+ return QLatin1String("Bluetooth");
+ case BearerWiMAX:
+ return QLatin1String("WiMAX");
+ default:
+ return QString();
+ }
+}
+
+SymbianEngine::SymbianEngine(QObject *parent)
+: QBearerEngine(parent), CActive(CActive::EPriorityIdle), iInitOk(true)
+{
+ CActiveScheduler::Add(this);
+
+ TRAPD(error, ipCommsDB = CCommsDatabase::NewL(EDatabaseTypeIAP));
+ if (error != KErrNone) {
+ iInitOk = false;
+ return;
+ }
+
+ TRAP_IGNORE(iConnectionMonitor.ConnectL());
+ TRAP_IGNORE(iConnectionMonitor.NotifyEventL(*this));
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ TRAP(error, iCmManager.OpenL());
+ if (error != KErrNone) {
+ iInitOk = false;
+ return;
+ }
+#endif
+
+ SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
+ cpPriv->name = "UserChoice";
+ cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerUnknown;
+ cpPriv->state = QNetworkConfiguration::Discovered;
+ cpPriv->isValid = true;
+ cpPriv->id = QString::number(qHash(KUserChoiceIAPId));
+ cpPriv->numericId = KUserChoiceIAPId;
+ cpPriv->connectionId = 0;
+ cpPriv->type = QNetworkConfiguration::UserChoice;
+ cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
+ cpPriv->roamingSupported = false;
+
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ userChoiceConfigurations.insert(ptr->id, ptr);
+
+ updateConfigurations();
+ updateStatesToSnaps();
+
+ // Start monitoring IAP and/or SNAP changes in Symbian CommsDB
+ startCommsDatabaseNotifications();
+}
+
+SymbianEngine::~SymbianEngine()
+{
+ Cancel();
+
+ iConnectionMonitor.CancelNotifications();
+ iConnectionMonitor.Close();
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ iCmManager.Close();
+#endif
+
+ delete ipAccessPointsAvailabilityScanner;
+ delete ipCommsDB;
+}
+
+bool SymbianEngine::hasIdentifier(const QString &id)
+{
+ 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;
+
+#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()
+{
+ QMutexLocker locker(&mutex);
+
+ if (!iInitOk) {
+ return;
+ }
+
+ TRAP_IGNORE(updateConfigurationsL());
+}
+
+void SymbianEngine::updateConfigurationsL()
+{
+ QMutexLocker locker(&mutex);
+
+ QList<QString> knownConfigs = accessPointConfigurations.keys();
+ QList<QString> knownSnapConfigs = snapConfigurations.keys();
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ // S60 version is >= Series60 3rd Edition Feature Pack 2
+ TInt error = KErrNone;
+
+ // Loop through all IAPs
+ RArray<TUint32> connectionMethods; // IAPs
+ CleanupClosePushL(connectionMethods);
+ iCmManager.ConnectionMethodL(connectionMethods);
+ for(int i = 0; i < connectionMethods.Count(); i++) {
+ RCmConnectionMethod connectionMethod = iCmManager.ConnectionMethodL(connectionMethods[i]);
+ CleanupClosePushL(connectionMethod);
+ TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
+ QString ident = QString::number(qHash(iapId));
+ if (accessPointConfigurations.contains(ident)) {
+ knownConfigs.removeOne(ident);
+ } else {
+ SymbianNetworkConfigurationPrivate* cpPriv = NULL;
+ TRAP(error, cpPriv = configFromConnectionMethodL(connectionMethod));
+ if (error == KErrNone) {
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ accessPointConfigurations.insert(ptr->id, ptr);
+ emit configurationAdded(ptr);
+ }
+ }
+ CleanupStack::PopAndDestroy(&connectionMethod);
+ }
+ CleanupStack::PopAndDestroy(&connectionMethods);
+
+ // Loop through all SNAPs
+ RArray<TUint32> destinations;
+ CleanupClosePushL(destinations);
+ iCmManager.AllDestinationsL(destinations);
+ for(int i = 0; i < destinations.Count(); i++) {
+ RCmDestination destination;
+ destination = iCmManager.DestinationL(destinations[i]);
+ CleanupClosePushL(destination);
+ QString ident = QString::number(qHash(destination.Id()+KValueThatWillBeAddedToSNAPId)); //TODO: Check if it's ok to add 1000 SNAP Id to prevent SNAP ids overlapping IAP ids
+ if (snapConfigurations.contains(ident)) {
+ knownSnapConfigs.removeOne(ident);
+ } else {
+ SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
+ CleanupStack::PushL(cpPriv);
+
+ HBufC *pName = destination.NameLC();
+ cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length());
+ CleanupStack::PopAndDestroy(pName);
+ pName = NULL;
+
+ cpPriv->isValid = true;
+ cpPriv->id = ident;
+ cpPriv->numericId = destination.Id();
+ cpPriv->connectionId = 0;
+ cpPriv->state = QNetworkConfiguration::Defined;
+ cpPriv->type = QNetworkConfiguration::ServiceNetwork;
+ cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
+ cpPriv->roamingSupported = false;
+
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ snapConfigurations.insert(ident, ptr);
+ emit configurationAdded(ptr);
+
+ CleanupStack::Pop(cpPriv);
+ }
+ QNetworkConfigurationPrivatePointer privSNAP = snapConfigurations.value(ident);
+
+ for (int j=0; j < destination.ConnectionMethodCount(); j++) {
+ RCmConnectionMethod connectionMethod = destination.ConnectionMethodL(j);
+ CleanupClosePushL(connectionMethod);
+
+ TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
+ QString iface = QString::number(qHash(iapId));
+ // Check that IAP can be found from accessPointConfigurations list
+ QNetworkConfigurationPrivatePointer priv = accessPointConfigurations.value(iface);
+ if (!priv) {
+ SymbianNetworkConfigurationPrivate *cpPriv = NULL;
+ TRAP(error, cpPriv = configFromConnectionMethodL(connectionMethod));
+ if (error == KErrNone) {
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ toSymbianConfig(ptr)->serviceNetworkPtr = privSNAP;
+ accessPointConfigurations.insert(ptr->id, ptr);
+ emit configurationAdded(ptr);
+ privSNAP->serviceNetworkMembers.append(ptr);
+ }
+ } else {
+ knownConfigs.removeOne(iface);
+ // Check that IAP can be found from related SNAP's configuration list
+ bool iapFound = false;
+ for (int i = 0; i < privSNAP->serviceNetworkMembers.count(); i++) {
+ if (toSymbianConfig(privSNAP->serviceNetworkMembers[i])->numericId == iapId) {
+ iapFound = true;
+ break;
+ }
+ }
+ if (!iapFound) {
+ toSymbianConfig(priv)->serviceNetworkPtr = privSNAP;
+ privSNAP->serviceNetworkMembers.append(priv);
+ }
+ }
+
+ CleanupStack::PopAndDestroy(&connectionMethod);
+ }
+
+ if (privSNAP->serviceNetworkMembers.count() > 1) {
+ // Roaming is supported only if SNAP contains more than one IAP
+ privSNAP->roamingSupported = true;
+ }
+
+ CleanupStack::PopAndDestroy(&destination);
+ }
+ CleanupStack::PopAndDestroy(&destinations);
+
+#else
+ // S60 version is < Series60 3rd Edition Feature Pack 2
+ CCommsDbTableView* pDbTView = ipCommsDB->OpenTableLC(TPtrC(IAP));
+
+ // Loop through all IAPs
+ TUint32 apId = 0;
+ TInt retVal = pDbTView->GotoFirstRecord();
+ while (retVal == KErrNone) {
+ pDbTView->ReadUintL(TPtrC(COMMDB_ID), apId);
+ QString ident = QString::number(qHash(apId));
+ if (accessPointConfigurations.contains(ident)) {
+ knownConfigs.removeOne(ident);
+ } else {
+ SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
+ if (readNetworkConfigurationValuesFromCommsDb(apId, cpPriv)) {
+ QNetworkConfigurationPrivatePointer ptr(cpPriv);
+ accessPointConfigurations.insert(ident, ptr);
+
+ emit configurationAdded(ptr);
+ } else {
+ delete cpPriv;
+ }
+ }
+ retVal = pDbTView->GotoNextRecord();
+ }
+ CleanupStack::PopAndDestroy(pDbTView);
+#endif
+ updateActiveAccessPoints();
+
+ foreach (const QString &oldIface, knownConfigs) {
+ //remove non existing IAP
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.take(oldIface);
+ emit configurationRemoved(ptr);
+
+ // Remove non existing IAP from SNAPs
+ foreach (const QString &iface, snapConfigurations.keys()) {
+ QNetworkConfigurationPrivatePointer ptr2 = snapConfigurations.value(iface);
+ // => Check if one of the IAPs of the SNAP is active
+ for (int i = 0; i < ptr2->serviceNetworkMembers.count(); ++i) {
+ if (toSymbianConfig(ptr2->serviceNetworkMembers[i])->numericId ==
+ toSymbianConfig(ptr)->numericId) {
+ ptr2->serviceNetworkMembers.removeAt(i);
+ break;
+ }
+ }
+ }
+ }
+
+ foreach (const QString &oldIface, knownSnapConfigs) {
+ //remove non existing SNAPs
+ QNetworkConfigurationPrivatePointer ptr = snapConfigurations.take(oldIface);
+ emit configurationRemoved(ptr);
+ }
+}
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+SymbianNetworkConfigurationPrivate *SymbianEngine::configFromConnectionMethodL(
+ RCmConnectionMethod& connectionMethod)
+{
+ QMutexLocker locker(&mutex);
+
+ SymbianNetworkConfigurationPrivate *cpPriv = new SymbianNetworkConfigurationPrivate;
+ CleanupStack::PushL(cpPriv);
+
+ TUint32 iapId = connectionMethod.GetIntAttributeL(CMManager::ECmIapId);
+ QString ident = QString::number(qHash(iapId));
+
+ HBufC *pName = connectionMethod.GetStringAttributeL(CMManager::ECmName);
+ CleanupStack::PushL(pName);
+ cpPriv->name = QString::fromUtf16(pName->Ptr(),pName->Length());
+ CleanupStack::PopAndDestroy(pName);
+ pName = NULL;
+
+ TUint32 bearerId = connectionMethod.GetIntAttributeL(CMManager::ECmCommsDBBearerType);
+ switch (bearerId) {
+ case KCommDbBearerCSD:
+ cpPriv->bearer = SymbianNetworkConfigurationPrivate::Bearer2G;
+ break;
+ case KCommDbBearerWcdma:
+ cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerWCDMA;
+ break;
+ case KCommDbBearerLAN:
+ cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerEthernet;
+ break;
+ case KCommDbBearerVirtual:
+ cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerUnknown;
+ break;
+ case KCommDbBearerPAN:
+ cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerUnknown;
+ break;
+ case KCommDbBearerWLAN:
+ cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerWLAN;
+ break;
+ default:
+ cpPriv->bearer = SymbianNetworkConfigurationPrivate::BearerUnknown;
+ break;
+ }
+
+ TInt error = KErrNone;
+ TUint32 bearerType = connectionMethod.GetIntAttributeL(CMManager::ECmBearerType);
+ switch (bearerType) {
+ case KUidPacketDataBearerType:
+ // "Packet data" Bearer => Mapping is done using "Access point name"
+ TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EPacketDataAPName));
+ break;
+ case KUidWlanBearerType:
+ // "Wireless LAN" Bearer => Mapping is done using "WLAN network name" = SSID
+ TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EWlanSSID));
+ break;
+ }
+ if (!pName) {
+ // "Data call" Bearer or "High Speed (GSM)" Bearer => Mapping is done using "Dial-up number"
+ TRAP(error, pName = connectionMethod.GetStringAttributeL(CMManager::EDialDefaultTelNum));
+ }
+
+ if (error == KErrNone && pName) {
+ CleanupStack::PushL(pName);
+ cpPriv->mappingName = QString::fromUtf16(pName->Ptr(),pName->Length());
+ CleanupStack::PopAndDestroy(pName);
+ pName = NULL;
+ }
+
+ cpPriv->state = QNetworkConfiguration::Defined;
+ TBool isConnected = connectionMethod.GetBoolAttributeL(CMManager::ECmConnected);
+ if (isConnected) {
+ cpPriv->state = QNetworkConfiguration::Active;
+ }
+
+ cpPriv->isValid = true;
+ cpPriv->id = ident;
+ cpPriv->numericId = iapId;
+ cpPriv->connectionId = 0;
+ cpPriv->type = QNetworkConfiguration::InternetAccessPoint;
+ cpPriv->purpose = QNetworkConfiguration::UnknownPurpose;
+ cpPriv->roamingSupported = false;
+
+ CleanupStack::Pop(cpPriv);
+ return cpPriv;
+}
+#else
+bool SymbianEngine::readNetworkConfigurationValuesFromCommsDb(
+ TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration)
+{
+ QMutexLocker locker(&mutex);
+
+ TRAPD(error, readNetworkConfigurationValuesFromCommsDbL(aApId,apNetworkConfiguration));
+ if (error != KErrNone) {
+ return false;
+ }
+ return true;
+}
+
+void SymbianEngine::readNetworkConfigurationValuesFromCommsDbL(
+ TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration)
+{
+ QMutexLocker locker(&mutex);
+
+ CApDataHandler* pDataHandler = CApDataHandler::NewLC(*ipCommsDB);
+ CApAccessPointItem* pAPItem = CApAccessPointItem::NewLC();
+ TBuf<KCommsDbSvrMaxColumnNameLength> name;
+
+ CApUtils* pApUtils = CApUtils::NewLC(*ipCommsDB);
+ TUint32 apId = pApUtils->WapIdFromIapIdL(aApId);
+
+ pDataHandler->AccessPointDataL(apId,*pAPItem);
+ pAPItem->ReadTextL(EApIapName, name);
+ if (name.Compare(_L("Easy WLAN")) == 0) {
+ // "Easy WLAN" won't be accepted to the Configurations list
+ User::Leave(KErrNotFound);
+ }
+
+ QString ident = QString::number(qHash(aApId));
+
+ apNetworkConfiguration->name = QString::fromUtf16(name.Ptr(),name.Length());
+ apNetworkConfiguration->isValid = true;
+ apNetworkConfiguration->id = ident;
+ apNetworkConfiguration->numericId = aApId;
+ apNetworkConfiguration->connectionId = 0;
+ apNetworkConfiguration->state = (QNetworkConfiguration::Defined);
+ apNetworkConfiguration->type = QNetworkConfiguration::InternetAccessPoint;
+ apNetworkConfiguration->purpose = QNetworkConfiguration::UnknownPurpose;
+ apNetworkConfiguration->roamingSupported = false;
+ switch (pAPItem->BearerTypeL()) {
+ case EApBearerTypeCSD:
+ apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::Bearer2G;
+ break;
+ case EApBearerTypeGPRS:
+ apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::Bearer2G;
+ break;
+ case EApBearerTypeHSCSD:
+ apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::BearerHSPA;
+ break;
+ case EApBearerTypeCDMA:
+ apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::BearerCDMA2000;
+ break;
+ case EApBearerTypeWLAN:
+ apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::BearerWLAN;
+ break;
+ case EApBearerTypeLAN:
+ apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::BearerEthernet;
+ break;
+ case EApBearerTypeLANModem:
+ apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::BearerEthernet;
+ break;
+ default:
+ apNetworkConfiguration->bearer = SymbianNetworkConfigurationPrivate::BearerUnknown;
+ break;
+ }
+
+ CleanupStack::PopAndDestroy(pApUtils);
+ CleanupStack::PopAndDestroy(pAPItem);
+ CleanupStack::PopAndDestroy(pDataHandler);
+}
+#endif
+
+QNetworkConfigurationPrivatePointer SymbianEngine::defaultConfiguration()
+{
+ QMutexLocker locker(&mutex);
+
+ QNetworkConfigurationPrivatePointer ptr;
+
+ if (iInitOk) {
+ stopCommsDatabaseNotifications();
+ TRAP_IGNORE(ptr = defaultConfigurationL());
+ startCommsDatabaseNotifications();
+ }
+
+ return ptr;
+}
+
+QStringList SymbianEngine::accessPointConfigurationIdentifiers()
+{
+ QMutexLocker locker(&mutex);
+
+ return accessPointConfigurations.keys();
+}
+
+QNetworkConfigurationPrivatePointer SymbianEngine::defaultConfigurationL()
+{
+ QMutexLocker locker(&mutex);
+
+ QNetworkConfigurationPrivatePointer ptr;
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ // Check Default Connection (SNAP or IAP)
+ TCmDefConnValue defaultConnectionValue;
+ iCmManager.ReadDefConnL(defaultConnectionValue);
+ if (defaultConnectionValue.iType == ECmDefConnDestination) {
+ QString iface = QString::number(qHash(defaultConnectionValue.iId+KValueThatWillBeAddedToSNAPId));
+ ptr = snapConfigurations.value(iface);
+ } else if (defaultConnectionValue.iType == ECmDefConnConnectionMethod) {
+ QString iface = QString::number(qHash(defaultConnectionValue.iId));
+ ptr = accessPointConfigurations.value(iface);
+ }
+#endif
+
+ if (!ptr->isValid) {
+ QString iface = QString::number(qHash(KUserChoiceIAPId));
+ ptr = userChoiceConfigurations.value(iface);
+ }
+
+ return ptr;
+}
+
+void SymbianEngine::updateActiveAccessPoints()
+{
+ QMutexLocker locker(&mutex);
+
+ bool online = false;
+ QList<QString> inactiveConfigs = accessPointConfigurations.keys();
+
+ TRequestStatus status;
+ TUint connectionCount;
+ iConnectionMonitor.GetConnectionCount(connectionCount, status);
+ User::WaitForRequest(status);
+
+ // Go through all connections and set state of related IAPs to Active
+ TUint connectionId;
+ TUint subConnectionCount;
+ TUint apId;
+ if (status.Int() == KErrNone) {
+ for (TUint i = 1; i <= connectionCount; i++) {
+ iConnectionMonitor.GetConnectionInfo(i, connectionId, subConnectionCount);
+ iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
+ User::WaitForRequest(status);
+ QString ident = QString::number(qHash(apId));
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+ if (ptr) {
+ online = true;
+ inactiveConfigs.removeOne(ident);
+
+ toSymbianConfig(ptr)->connectionId = connectionId;
+
+ // Configuration is Active
+ changeConfigurationStateTo(ptr, QNetworkConfiguration::Active);
+ }
+ }
+ }
+
+ // Make sure that state of rest of the IAPs won't be Active
+ foreach (const QString &iface, inactiveConfigs) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
+ if (ptr) {
+ // Configuration is either Defined or Discovered
+ changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered);
+ }
+ }
+
+ if (iOnline != online) {
+ iOnline = online;
+ emit this->onlineStateChanged(iOnline);
+ }
+}
+
+void SymbianEngine::updateAvailableAccessPoints()
+{
+ QMutexLocker locker(&mutex);
+
+ 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)
+{
+ QMutexLocker locker(&mutex);
+
+ iUpdateGoingOn = false;
+ if (scanSuccessful) {
+ QList<QString> unavailableConfigs = accessPointConfigurations.keys();
+
+ // Set state of returned IAPs to Discovered
+ // if state is not already Active
+ for(TUint i=0; i<iapInfo.iCount; i++) {
+ QString ident = QString::number(qHash(iapInfo.iIap[i].iIapId));
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+ if (ptr) {
+ unavailableConfigs.removeOne(ident);
+ if (ptr->state < QNetworkConfiguration::Active) {
+ // Configuration is either Discovered or Active
+ changeConfigurationStateAtMinTo(ptr, QNetworkConfiguration::Discovered);
+ }
+ }
+ }
+
+ // Make sure that state of rest of the IAPs won't be Discovered or Active
+ foreach (const QString &iface, unavailableConfigs) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
+ if (ptr) {
+ // Configuration is Defined
+ changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Defined);
+ }
+ }
+ }
+
+ updateStatesToSnaps();
+
+ startCommsDatabaseNotifications();
+
+ emit updateCompleted();
+}
+
+void SymbianEngine::updateStatesToSnaps()
+{
+ QMutexLocker locker(&mutex);
+
+ // Go through SNAPs and set correct state to SNAPs
+ QList<QString> snapConfigIdents = snapConfigurations.keys();
+ foreach (QString iface, snapConfigIdents) {
+ bool discovered = false;
+ bool active = false;
+ QNetworkConfigurationPrivatePointer ptr = snapConfigurations.value(iface);
+ // => Check if one of the IAPs of the SNAP is discovered or active
+ // => If one of IAPs is active, also SNAP is active
+ // => If one of IAPs is discovered but none of the IAPs is active, SNAP is discovered
+ for (int i=0; i<ptr->serviceNetworkMembers.count(); i++) {
+ if ((ptr->serviceNetworkMembers[i]->state & QNetworkConfiguration::Active)
+ == QNetworkConfiguration::Active) {
+ active = true;
+ break;
+ } else if ((ptr->serviceNetworkMembers[i]->state & QNetworkConfiguration::Discovered)
+ == QNetworkConfiguration::Discovered) {
+ discovered = true;
+ }
+ }
+ if (active) {
+ changeConfigurationStateTo(ptr, QNetworkConfiguration::Active);
+ } else if (discovered) {
+ changeConfigurationStateTo(ptr, QNetworkConfiguration::Discovered);
+ } else {
+ changeConfigurationStateTo(ptr, QNetworkConfiguration::Defined);
+ }
+ }
+}
+
+bool SymbianEngine::changeConfigurationStateTo(QNetworkConfigurationPrivatePointer ptr,
+ QNetworkConfiguration::StateFlags newState)
+{
+ QMutexLocker locker(&mutex);
+
+ if (newState != ptr->state) {
+ ptr->state = newState;
+ emit configurationChanged(ptr);
+ return true;
+ }
+ return false;
+}
+
+/* changeConfigurationStateAtMinTo function does not overwrite possible better
+ * state (e.g. Discovered state does not overwrite Active state) but
+ * makes sure that state is at minimum given state.
+*/
+bool SymbianEngine::changeConfigurationStateAtMinTo(QNetworkConfigurationPrivatePointer ptr,
+ QNetworkConfiguration::StateFlags newState)
+{
+ QMutexLocker locker(&mutex);
+
+ if ((newState | ptr->state) != ptr->state) {
+ ptr->state = (ptr->state | newState);
+ emit configurationChanged(ptr);
+ return true;
+ }
+ return false;
+}
+
+/* changeConfigurationStateAtMaxTo function overwrites possible better
+ * state (e.g. Discovered state overwrites Active state) and
+ * makes sure that state is at maximum given state (e.g. Discovered state
+ * does not overwrite Defined state).
+*/
+bool SymbianEngine::changeConfigurationStateAtMaxTo(QNetworkConfigurationPrivatePointer ptr,
+ QNetworkConfiguration::StateFlags newState)
+{
+ QMutexLocker locker(&mutex);
+
+ if ((newState & ptr->state) != ptr->state) {
+ ptr->state = (newState & ptr->state);
+ emit configurationChanged(ptr);
+ return true;
+ }
+ return false;
+}
+
+void SymbianEngine::startCommsDatabaseNotifications()
+{
+ QMutexLocker locker(&mutex);
+
+ if (!iWaitingCommsDatabaseNotifications) {
+ iWaitingCommsDatabaseNotifications = ETrue;
+ if (!IsActive()) {
+ SetActive();
+ // Start waiting for new notification
+ ipCommsDB->RequestNotification(iStatus);
+ }
+ }
+}
+
+void SymbianEngine::stopCommsDatabaseNotifications()
+{
+ QMutexLocker locker(&mutex);
+
+ if (iWaitingCommsDatabaseNotifications) {
+ iWaitingCommsDatabaseNotifications = EFalse;
+ if (!IsActive()) {
+ SetActive();
+ // Make sure that notifier recorded events will not be returned
+ // as soon as the client issues the next RequestNotification() request.
+ ipCommsDB->RequestNotification(iStatus);
+ ipCommsDB->CancelRequestNotification();
+ } else {
+ ipCommsDB->CancelRequestNotification();
+ }
+ }
+}
+
+void SymbianEngine::RunL()
+{
+ QMutexLocker locker(&mutex);
+
+ if (iStatus != KErrCancel) {
+ RDbNotifier::TEvent event = STATIC_CAST(RDbNotifier::TEvent, iStatus.Int());
+ switch (event) {
+ case RDbNotifier::EUnlock: /** All read locks have been removed. */
+ case RDbNotifier::ECommit: /** A transaction has been committed. */
+ case RDbNotifier::ERollback: /** A transaction has been rolled back */
+ case RDbNotifier::ERecover: /** The database has been recovered */
+ // Note that if further database events occur while a client is handling
+ // a request completion, the notifier records the most significant database
+ // event and this is signalled as soon as the client issues the next
+ // RequestNotification() request.
+ // => Stop recording notifications
+ stopCommsDatabaseNotifications();
+ TRAPD(error, updateConfigurationsL());
+ if (error == KErrNone) {
+ updateStatesToSnaps();
+ }
+ iWaitingCommsDatabaseNotifications = true;
+ break;
+ default:
+ // Do nothing
+ break;
+ }
+ }
+
+ if (iWaitingCommsDatabaseNotifications) {
+ if (!IsActive()) {
+ SetActive();
+ // Start waiting for new notification
+ ipCommsDB->RequestNotification(iStatus);
+ }
+ }
+}
+
+void SymbianEngine::DoCancel()
+{
+ QMutexLocker locker(&mutex);
+
+ ipCommsDB->CancelRequestNotification();
+}
+
+
+void SymbianEngine::EventL(const CConnMonEventBase& aEvent)
+{
+ QMutexLocker locker(&mutex);
+
+ switch (aEvent.EventType()) {
+ case EConnMonCreateConnection:
+ {
+ CConnMonCreateConnection* realEvent;
+ realEvent = (CConnMonCreateConnection*) &aEvent;
+ TUint subConnectionCount = 0;
+ TUint apId;
+ TUint connectionId = realEvent->ConnectionId();
+ TRequestStatus status;
+ iConnectionMonitor.GetUintAttribute(connectionId, subConnectionCount, KIAPId, apId, status);
+ User::WaitForRequest(status);
+ QString ident = QString::number(qHash(apId));
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+ if (ptr) {
+ toSymbianConfig(ptr)->connectionId = connectionId;
+ // Configuration is Active
+ if (changeConfigurationStateTo(ptr, QNetworkConfiguration::Active))
+ updateStatesToSnaps();
+
+ if (!iOnline) {
+ iOnline = true;
+ emit this->onlineStateChanged(iOnline);
+ }
+ }
+ }
+ break;
+
+ case EConnMonDeleteConnection:
+ {
+ CConnMonDeleteConnection* realEvent;
+ realEvent = (CConnMonDeleteConnection*) &aEvent;
+ TUint connectionId = realEvent->ConnectionId();
+
+ QNetworkConfigurationPrivatePointer ptr = dataByConnectionId(connectionId);
+ if (ptr) {
+ toSymbianConfig(ptr)->connectionId = 0;
+ // Configuration is either Defined or Discovered
+ if (changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Discovered))
+ updateStatesToSnaps();
+ }
+
+ bool online = false;
+ foreach (const QString &iface, accessPointConfigurations.keys()) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
+ if (ptr->state == QNetworkConfiguration::Active) {
+ online = true;
+ break;
+ }
+ }
+ if (iOnline != online) {
+ iOnline = online;
+ emit this->onlineStateChanged(iOnline);
+ }
+ }
+ break;
+
+ case EConnMonIapAvailabilityChange:
+ {
+ CConnMonIapAvailabilityChange* realEvent;
+ realEvent = (CConnMonIapAvailabilityChange*) &aEvent;
+ TConnMonIapInfo iaps = realEvent->IapAvailability();
+ QList<QString> unDiscoveredConfigs = accessPointConfigurations.keys();
+ for ( TUint i = 0; i < iaps.Count(); i++ ) {
+ QString ident = QString::number(qHash(iaps.iIap[i].iIapId));
+
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(ident);
+ if (ptr) {
+ // Configuration is either Discovered or Active
+ changeConfigurationStateAtMinTo(ptr, QNetworkConfiguration::Discovered);
+ unDiscoveredConfigs.removeOne(ident);
+ }
+ }
+ foreach (const QString &iface, unDiscoveredConfigs) {
+ QNetworkConfigurationPrivatePointer ptr = accessPointConfigurations.value(iface);
+ if (ptr) {
+ // Configuration is Defined
+ changeConfigurationStateAtMaxTo(ptr, QNetworkConfiguration::Defined);
+ }
+ }
+ }
+ break;
+
+ default:
+ // For unrecognized events
+ break;
+ }
+}
+
+QNetworkConfigurationPrivatePointer SymbianEngine::dataByConnectionId(TUint aConnectionId)
+{
+ QMutexLocker locker(&mutex);
+
+ QNetworkConfiguration item;
+
+ QHash<QString, QNetworkConfigurationPrivatePointer>::const_iterator i =
+ accessPointConfigurations.constBegin();
+ while (i != accessPointConfigurations.constEnd()) {
+ QNetworkConfigurationPrivatePointer ptr = i.value();
+ if (toSymbianConfig(ptr)->connectionId == aConnectionId)
+ return ptr;
+
+ ++i;
+ }
+
+ return QNetworkConfigurationPrivatePointer();
+}
+
+AccessPointsAvailabilityScanner::AccessPointsAvailabilityScanner(SymbianEngine& owner,
+ RConnectionMonitor& connectionMonitor)
+ : CActive(CActive::EPriorityStandard), iOwner(owner), iConnectionMonitor(connectionMonitor)
+{
+ CActiveScheduler::Add(this);
+}
+
+AccessPointsAvailabilityScanner::~AccessPointsAvailabilityScanner()
+{
+ Cancel();
+}
+
+void AccessPointsAvailabilityScanner::DoCancel()
+{
+ iConnectionMonitor.CancelAsyncRequest(EConnMonGetPckgAttribute);
+}
+
+void AccessPointsAvailabilityScanner::StartScanning()
+{
+ iConnectionMonitor.GetPckgAttribute(EBearerIdAll, 0, KIapAvailability, iIapBuf, iStatus);
+ if (!IsActive()) {
+ SetActive();
+ }
+}
+
+void AccessPointsAvailabilityScanner::RunL()
+{
+ if (iStatus.Int() != KErrNone) {
+ iIapBuf().iCount = 0;
+ iOwner.accessPointScanningReady(false,iIapBuf());
+ } else {
+ iOwner.accessPointScanningReady(true,iIapBuf());
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/plugins/bearer/symbian/symbianengine.h b/src/plugins/bearer/symbian/symbianengine.h
new file mode 100644
index 0000000..5448813
--- /dev/null
+++ b/src/plugins/bearer/symbian/symbianengine.h
@@ -0,0 +1,205 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef SYMBIANENGINE_H
+#define SYMBIANENGINE_H
+
+#include <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
+
+class CCommsDatabase;
+
+QT_BEGIN_NAMESPACE
+class QTimer;
+QT_END_NAMESPACE
+
+QT_BEGIN_NAMESPACE
+
+class QNetworkSessionPrivate;
+class AccessPointsAvailabilityScanner;
+
+class SymbianNetworkConfigurationPrivate : public QNetworkConfigurationPrivate
+{
+public:
+ enum Bearer {
+ BearerEthernet,
+ BearerWLAN,
+ Bearer2G,
+ BearerCDMA2000,
+ BearerWCDMA,
+ BearerHSPA,
+ BearerBluetooth,
+ BearerWiMAX,
+ BearerUnknown = -1
+ };
+
+ SymbianNetworkConfigurationPrivate();
+ ~SymbianNetworkConfigurationPrivate();
+
+ QString bearerName() const;
+
+ Bearer bearer;
+
+ TUint32 numericId;
+ TUint connectionId;
+
+ QNetworkConfigurationPrivatePointer serviceNetworkPtr;
+
+ QString mappingName;
+};
+
+inline SymbianNetworkConfigurationPrivate *toSymbianConfig(QNetworkConfigurationPrivatePointer ptr)
+{
+ return static_cast<SymbianNetworkConfigurationPrivate *>(ptr.data());
+}
+
+class SymbianEngine : public QBearerEngine, public CActive,
+ public MConnectionMonitorObserver
+{
+ Q_OBJECT
+
+public:
+ SymbianEngine(QObject *parent = 0);
+ virtual ~SymbianEngine();
+
+ bool hasIdentifier(const QString &id);
+
+ void requestUpdate();
+
+ QNetworkConfigurationManager::Capabilities capabilities() const;
+
+ QNetworkSessionPrivate *createSessionBackend();
+
+ QNetworkConfigurationPrivatePointer defaultConfiguration();
+
+ QStringList accessPointConfigurationIdentifiers();
+
+Q_SIGNALS:
+ void onlineStateChanged(bool isOnline);
+
+public Q_SLOTS:
+ void updateConfigurations();
+
+private:
+ void updateStatesToSnaps();
+ bool changeConfigurationStateTo(QNetworkConfigurationPrivatePointer ptr,
+ QNetworkConfiguration::StateFlags newState);
+ bool changeConfigurationStateAtMinTo(QNetworkConfigurationPrivatePointer ptr,
+ QNetworkConfiguration::StateFlags newState);
+ bool changeConfigurationStateAtMaxTo(QNetworkConfigurationPrivatePointer ptr,
+ QNetworkConfiguration::StateFlags newState);
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ SymbianNetworkConfigurationPrivate *configFromConnectionMethodL(RCmConnectionMethod& connectionMethod);
+#else
+ bool readNetworkConfigurationValuesFromCommsDb(
+ TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration);
+ void readNetworkConfigurationValuesFromCommsDbL(
+ TUint32 aApId, SymbianNetworkConfigurationPrivate *apNetworkConfiguration);
+#endif
+
+ void updateConfigurationsL();
+ void updateActiveAccessPoints();
+ void updateAvailableAccessPoints();
+ void accessPointScanningReady(TBool scanSuccessful, TConnMonIapInfo iapInfo);
+ void startCommsDatabaseNotifications();
+ void stopCommsDatabaseNotifications();
+
+ QNetworkConfigurationPrivatePointer defaultConfigurationL();
+ TBool GetS60PlatformVersion(TUint& aMajor, TUint& aMinor) const;
+ void startMonitoringIAPData(TUint32 aIapId);
+ QNetworkConfigurationPrivatePointer dataByConnectionId(TUint aConnectionId);
+
+protected: // From CActive
+ void RunL();
+ void DoCancel();
+
+private: // MConnectionMonitorObserver
+ void EventL(const CConnMonEventBase& aEvent);
+
+private: // Data
+ CCommsDatabase* ipCommsDB;
+ RConnectionMonitor iConnectionMonitor;
+
+ TBool iWaitingCommsDatabaseNotifications;
+ TBool iOnline;
+ TBool iInitOk;
+ TBool iUpdateGoingOn;
+
+
+ AccessPointsAvailabilityScanner* ipAccessPointsAvailabilityScanner;
+
+ friend class QNetworkSessionPrivate;
+ friend class AccessPointsAvailabilityScanner;
+
+#ifdef SNAP_FUNCTIONALITY_AVAILABLE
+ RCmManager iCmManager;
+#endif
+};
+
+class AccessPointsAvailabilityScanner : public CActive
+{
+public:
+ AccessPointsAvailabilityScanner(SymbianEngine& owner,
+ RConnectionMonitor& connectionMonitor);
+ ~AccessPointsAvailabilityScanner();
+
+ void StartScanning();
+
+protected: // From CActive
+ void RunL();
+ void DoCancel();
+
+private: // Data
+ SymbianEngine& iOwner;
+ RConnectionMonitor& iConnectionMonitor;
+ TConnMonIapInfoBuf iIapBuf;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/plugins/plugins.pro b/src/plugins/plugins.pro
index be861a4..418fd81 100644
--- a/src/plugins/plugins.pro
+++ b/src/plugins/plugins.pro
@@ -1,6 +1,6 @@
TEMPLATE = subdirs
-SUBDIRS *= accessible imageformats sqldrivers iconengines script
+SUBDIRS *= accessible imageformats sqldrivers iconengines script bearer
unix:!symbian {
contains(QT_CONFIG,iconv)|contains(QT_CONFIG,gnu-libiconv):SUBDIRS *= codecs
} else {
diff --git a/src/s60installs/s60installs.pro b/src/s60installs/s60installs.pro
index 1f3b4a6..5d5bee9 100644
--- a/src/s60installs/s60installs.pro
+++ b/src/s60installs/s60installs.pro
@@ -88,7 +88,16 @@ symbian: {
qtbackup.sources = backup_registration.xml
qtbackup.path = c:/private/10202D56/import/packages/$$replace(TARGET.UID3, 0x,)
- DEPLOYMENT += qtresources qtlibraries qtbackup imageformats_plugins codecs_plugins graphicssystems_plugins
+ bearer_plugins.path = c:$$QT_PLUGINS_BASE_DIR/bearer
+ bearer_plugins.sources += qsymbianbearer.dll
+
+ DEPLOYMENT += qtresources \
+ qtlibraries \
+ qtbackup \
+ imageformats_plugins \
+ codecs_plugins \
+ graphicssystems_plugins \
+ bearer_plugins
contains(QT_CONFIG, svg): {
qtlibraries.sources += QtSvg.dll