qtmobility/src/bearer/qnetworksession_maemo.cpp
changeset 4 90517678cc4f
parent 0 cfcbf08528c4
child 11 06b8e2af4411
--- a/qtmobility/src/bearer/qnetworksession_maemo.cpp	Fri Apr 16 15:51:22 2010 +0300
+++ b/qtmobility/src/bearer/qnetworksession_maemo.cpp	Mon May 03 13:18:40 2010 +0300
@@ -42,280 +42,142 @@
 #include <QHash>
 
 #include "qnetworksession_maemo_p.h"
-#include <dbus/dbus.h>
-#include <dbus/dbus-glib-lowlevel.h>
 
 #include <maemo_icd.h>
 #include <iapconf.h>
 #include <proxyconf.h>
 
-#include <sys/types.h>
 #include <ifaddrs.h>
-#include <sys/socket.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
 
+
+QDBusArgument &operator<<(QDBusArgument &argument,
+                          const QtMobility::ICd2DetailsDBusStruct &icd2)
+{
+    argument.beginStructure();
+    argument << icd2.serviceType;
+    argument << icd2.serviceAttributes;
+    argument << icd2.setviceId;
+    argument << icd2.networkType;
+    argument << icd2.networkAttributes;
+    argument << icd2.networkId;
+    argument.endStructure();
+    return argument;
+}
+
+const QDBusArgument &operator>>(const QDBusArgument &argument,
+                                QtMobility::ICd2DetailsDBusStruct &icd2)
+{
+    argument.beginStructure();
+    argument >> icd2.serviceType;
+    argument >> icd2.serviceAttributes;
+    argument >> icd2.setviceId;
+    argument >> icd2.networkType;
+    argument >> icd2.networkAttributes;
+    argument >> icd2.networkId;
+    argument.endStructure();
+    return argument;
+}
+
+const QDBusArgument &operator>>(const QDBusArgument &argument,
+                                QtMobility::ICd2DetailsList &detailsList)
+{
+     argument.beginArray();
+     detailsList.clear();
+
+     while (!argument.atEnd()) {
+         QtMobility::ICd2DetailsDBusStruct element;
+         argument >> element;
+         detailsList.append(element);
+     }
+
+     argument.endArray();
+     return argument;
+}
+
+QDBusArgument &operator<<(QDBusArgument &argument,
+                          const QtMobility::ICd2DetailsList &detailsList)
+{
+     argument.beginArray(qMetaTypeId<QtMobility::ICd2DetailsDBusStruct>());
+     for (int i = 0; i < detailsList.count(); ++i)
+         argument << detailsList[i];
+     argument.endArray();
+     return argument;
+}
+
 QTM_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
+void QNetworkSessionPrivate::iapStateChanged(const QString& iapid, uint icd_connection_state)
 {
-    Q_OBJECT
-
-public:
-    IcdListener() : first_call(true) { }
-    friend DBusHandlerResult signal_handler(DBusConnection *connection,
-					    DBusMessage *message,
-					    void *user_data);
-    void setup(QNetworkSessionPrivate *d);
-    void cleanup();
-    void cleanupSession(QNetworkSessionPrivate *ptr);
-
-    enum IapConnectionStatus {
-	/* The IAP was connected */
-	CONNECTED = 0,
-	/* The IAP was disconnected */
-	DISCONNECTED,
-	/* The IAP is disconnecting */
-	DISCONNECTING,
-	/* The IAP has a network address, but is not yet fully connected */
-	NETWORK_UP
-    };
-
-private:
-    void icdSignalReceived(QString&, QString&, QString&);
-    bool first_call;
-    QHash<QString, QNetworkSessionPrivate* > 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;
+    if ((publicConfig.type() == QNetworkConfiguration::UserChoice) && opened) {
+        updateIdentifier(iapid);
     }
 
-    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-
-void IcdListener::setup(QNetworkSessionPrivate *d)
-{
-    if (first_call) {
-	// We use the old Icd dbus interface like in ConIC
-	DBusError error;
-	dbus_error_init(&error);
-
-	dbus_connection = get_dbus_conn(&error);
-	if (dbus_error_is_set(&error)) {
-	    qWarning() << "Cannot get dbus connection.";
-	    dbus_error_free(&error);
-	    return;
-	}
-
-	static struct DBusObjectPathVTable icd_vtable;
-	icd_vtable.message_function = signal_handler;
-
-	dbus_bus_add_match(dbus_connection, ICD_DBUS_MATCH, &error);
-	if (dbus_error_is_set(&error)) {
-	    qWarning() << "Cannot add match" << ICD_DBUS_MATCH;
-	    dbus_error_free(&error);
-	    return;
-	}
-
-	if (dbus_connection_register_object_path(dbus_connection,
-						    ICD_DBUS_PATH,
-						    &icd_vtable,
-						    (void*)this) == FALSE) {
-	    qWarning() << "Cannot register dbus signal handler, interface"<< ICD_DBUS_INTERFACE << "path" << ICD_DBUS_PATH;
-	    dbus_error_free(&error);
-	    return;
-	}
-
-#ifdef BEARER_MANAGEMENT_DEBUG
-	qDebug() << "Listening" << ICD_STATUS_CHANGED_SIG << "signal from" << ICD_DBUS_SERVICE;
-#endif
-	first_call = false;
-	dbus_error_free(&error);
-    }
-
-    QString id = d->activeConfig.identifier();
-    if (!sessions.contains(id)) {
-	QNetworkSessionPrivate *ptr = d;
-	sessions.insert(id, ptr);
+    if (((publicConfig.type() == QNetworkConfiguration::UserChoice) && (activeConfig.d->id == iapid)) ||
+        (publicConfig.d->id == iapid)) {
+        switch (icd_connection_state) {
+        case ICD_STATE_CONNECTING:
+            updateState(QNetworkSession::Connecting);
+            break;
+        case ICD_STATE_CONNECTED:
+            updateState(QNetworkSession::Connected);
+            break;
+        case ICD_STATE_DISCONNECTING:
+            updateState(QNetworkSession::Closing);
+            break;
+        case ICD_STATE_DISCONNECTED:
+            updateState(QNetworkSession::Disconnected);
+            break;
+        default:
+            break;
+        }
     }
 }
 
-
-void IcdListener::icdSignalReceived(QString& iap_id,
-#ifdef BEARER_MANAGEMENT_DEBUG
-				    QString& network_type,
-#else
-				    QString&,
-#endif
-				    QString& state)
-{
-    if (iap_id == OSSO_IAP_SCAN) // icd sends scan status signals which we will ignore
-	return;
-
-#ifdef BEARER_MANAGEMENT_DEBUG
-    qDebug() << "Status received:" << iap_id << "type" << network_type << "state" << state;
-#endif
-
-    if (!sessions.contains(iap_id)) {
-#ifdef BEARER_MANAGEMENT_DEBUG
-	qDebug() << "No session for IAP" << iap_id;
-#endif
-	return;
-    }
-
-    QNetworkSessionPrivate *session = sessions.value(iap_id);
-    QNetworkConfiguration ap_conf = session->manager.configurationFromIdentifier(iap_id);
-    if (!ap_conf.isValid()) {
-#ifdef BEARER_MANAGEMENT_DEBUG
-	qDebug() << "Unknown IAP" << iap_id;
-#endif
-	return;
-    }
-
-    IapConnectionStatus status;
-
-    if (state == "IDLE") {
-	status = DISCONNECTED;
-    } else if (state == "CONNECTED") {
-	status = CONNECTED;
-    } else if (state == "NETWORKUP") {
-	status = NETWORK_UP;
-    } else {
-	//qDebug() << "Unknown state" << state;
-	return;
-    }
-
-    if (status == DISCONNECTED) {
-	if (ap_conf.state() == QNetworkConfiguration::Active) {
-	    /* The IAP was just disconnected by Icd */
-	    session->updateState(QNetworkSession::Disconnected);
-	} else {
-#ifdef BEARER_MANAGEMENT_DEBUG
-	    qDebug() << "Got a network disconnect when in state" << ap_conf.state();
-#endif
-	}
-    } else if (status == CONNECTED) {
-	/* The IAP was just connected by Icd */
-	session->updateState(QNetworkSession::Connected);
-	session->updateIdentifier(iap_id);
-
-	if (session->publicConfig.identifier() == OSSO_IAP_ANY) {
-#ifdef BEARER_MANAGEMENT_DEBUG
-	    qDebug() << "IAP" << iap_id << "connected when connecting to" << OSSO_IAP_ANY;
-#endif
-	} else {
-#ifdef BEARER_MANAGEMENT_DEBUG
-	    qDebug() << "IAP" << iap_id << "connected";
-#endif
-	}
-    }
-
-    return;
-}
-
-
-void IcdListener::cleanup()
-{
-    if (!first_call) {
-	dbus_bus_remove_match(dbus_connection, ICD_DBUS_MATCH, NULL);
-	dbus_connection_unref(dbus_connection);
-    }
-}
-
-
-void IcdListener::cleanupSession(QNetworkSessionPrivate *ptr)
-{
-    if (ptr->publicConfig.type() == QNetworkConfiguration::UserChoice)
-        (void)sessions.take(ptr->activeConfig.identifier());
-    else
-        (void)sessions.take(ptr->publicConfig.identifier());
-}
-
-
 void QNetworkSessionPrivate::cleanupSession(void)
 {
-    icdListener()->cleanupSession(this);
-
     QObject::disconnect(q, SIGNAL(stateChanged(QNetworkSession::State)), this, SLOT(updateProxies(QNetworkSession::State)));
 }
 
 
 void QNetworkSessionPrivate::updateState(QNetworkSession::State newState)
 {
-    if( newState != state) {
-        state = newState;
-
-	if (state == QNetworkSession::Disconnected) {
+    if (newState != state) {
+        if (newState == QNetworkSession::Disconnected) {
+            if (isOpen) {
+                // The Session was aborted by the user or system
+                lastError = QNetworkSession::SessionAbortedError;
+                emit q->error(lastError);
+                emit q->closed();
+            }
+            if (m_stopTimer.isActive()) {
+                // Session was closed by calling stop()
+                m_stopTimer.stop();
+            }
             isOpen = false;
+            opened = false;
 	    currentNetworkInterface.clear();
-	    if (publicConfig.type() == QNetworkConfiguration::UserChoice)
-		activeConfig.d->state = QNetworkConfiguration::Defined;
-	    publicConfig.d->state = QNetworkConfiguration::Defined;
-
-	} else if (state == QNetworkSession::Connected) {
-            isOpen = true;
+            if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
+                copyConfig(publicConfig, activeConfig);
+                activeConfig.d->state = QNetworkConfiguration::Defined;
+            } else {
+                if (!activeConfig.isValid()) {
+                    // Active configuration (IAP) was removed from system
+                    // => Connection was disconnected and configuration became
+                    //    invalid
+                    // => Also Session state must be changed to invalid
+                    newState = QNetworkSession::Invalid;
+                }
+            }
+        } else if (newState == QNetworkSession::Connected) {
+            if (opened) {
+                isOpen = true;
+            }
 	    if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
 		activeConfig.d->state = QNetworkConfiguration::Active;
 		activeConfig.d->type = QNetworkConfiguration::InternetAccessPoint;
@@ -323,12 +185,15 @@
 	    publicConfig.d->state = QNetworkConfiguration::Active;
 	}
 
-	emit q->stateChanged(newState);
+        if (newState != state) {
+            state = newState;
+            emit q->stateChanged(newState);
+        }
     }
 }
 
 
-void QNetworkSessionPrivate::updateIdentifier(QString &newId)
+void QNetworkSessionPrivate::updateIdentifier(const QString &newId)
 {
     if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
 	activeConfig.d->network_attrs |= ICD_NW_ATTR_IAPNAME;
@@ -357,7 +222,7 @@
 	return 0;
     }
 
-    foreach (Maemo::IcdStatisticsResult res, stats_results) {
+    foreach (const 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()) {
@@ -433,9 +298,6 @@
  */
 void QNetworkSessionPrivate::syncStateWithInterface()
 {
-    /* Start to listen Icd status messages. */
-    icdListener()->setup(this);
-
     /* Initially we are not active although the configuration might be in
      * connected state.
      */
@@ -447,10 +309,10 @@
     if (publicConfig.d.data()) {
 	QNetworkConfigurationManagerPrivate* mgr = (QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager;
 	if (mgr) {
-	    QObject::connect(mgr, SIGNAL(configurationChanged(QNetworkConfiguration)),
-			    this, SLOT(configurationChanged(QNetworkConfiguration)));
+            connect(mgr, SIGNAL(iapStateChanged(const QString&, uint)),
+                    this, SLOT(iapStateChanged(const QString&, uint)));
 	} else {
-	    qWarning()<<"Manager object not set when trying to connect configurationChanged signal. Your configuration object is not correctly setup, did you remember to call manager.updateConfigurations() before creating session object?";
+            qWarning()<<"Manager object not set when trying to connect iapStateChanged signal. Your configuration object is not correctly setup, did you remember to call manager.updateConfigurations() before creating session object?";
 	    state = QNetworkSession::Invalid;
 	    lastError = QNetworkSession::UnknownSessionError;
 	    return;
@@ -464,14 +326,14 @@
 
     switch (publicConfig.type()) {
     case QNetworkConfiguration::InternetAccessPoint:
-	activeConfig = publicConfig;
+        activeConfig = publicConfig;
         break;
     case QNetworkConfiguration::ServiceNetwork:
-	serviceConfig = publicConfig;
+        serviceConfig = publicConfig;
 	break;
     case QNetworkConfiguration::UserChoice:
 	// active config will contain correct data after open() has succeeded
-	copyConfig(publicConfig, activeConfig);
+        copyConfig(publicConfig, activeConfig);
 
 	/* We create new configuration that holds the actual configuration
 	 * returned by icd. This way publicConfig still contains the
@@ -505,7 +367,6 @@
      * 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.
 	 */
@@ -518,46 +379,44 @@
 	     */
 	    if (publicConfig.type() == QNetworkConfiguration::UserChoice ||
 		    publicConfig.d->id == state_results.first().params.network_id) {
-
 		switch (state_results.first().state) {
 		case ICD_STATE_DISCONNECTED:
-		    state = QNetworkSession::Disconnected;
+                    state = QNetworkSession::Disconnected;
 		    if (activeConfig.d.data())
 			activeConfig.d->isValid = true;
 		    break;
 		case ICD_STATE_CONNECTING:
-		    state = QNetworkSession::Connecting;
+                    state = QNetworkSession::Connecting;
 		    if (activeConfig.d.data())
 			activeConfig.d->isValid = true;
 		    break;
 		case ICD_STATE_CONNECTED:
 		    {
-			if (!state_results.first().error.isEmpty())
+                        if (!state_results.first().error.isEmpty())
 			    break;
-                        
+
                         const QString id = state_results.first().params.network_id;
 
-			QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)activeConfig.d.data()->manager;
+                        QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager;
 			if (mgr->accessPointConfigurations.contains(id)) {
                             //we don't want the copied data if the config is already known by the manager
                             //just reuse it so that existing references to the old data get the same update
-			    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = mgr->accessPointConfigurations.value(activeConfig.d->id);
+                            QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = mgr->accessPointConfigurations.value(id);
                             activeConfig.d = priv;
                         }
 
-
 			state = QNetworkSession::Connected;
-			activeConfig.d->network_id = state_results.first().params.network_id;
-			activeConfig.d->id = activeConfig.d->network_id;
-			activeConfig.d->network_attrs = state_results.first().params.network_attrs;
-			activeConfig.d->iap_type = state_results.first().params.network_type;
-			activeConfig.d->service_type = state_results.first().params.service_type;
-			activeConfig.d->service_id = state_results.first().params.service_id;
-			activeConfig.d->service_attrs = state_results.first().params.service_attrs;
-			activeConfig.d->type = QNetworkConfiguration::InternetAccessPoint;
-			activeConfig.d->state = QNetworkConfiguration::Active;
-			activeConfig.d->isValid = true;
-			currentNetworkInterface = get_network_interface();
+                        activeConfig.d->network_id = state_results.first().params.network_id;
+                        activeConfig.d->id = activeConfig.d->network_id;
+                        activeConfig.d->network_attrs = state_results.first().params.network_attrs;
+                        activeConfig.d->iap_type = state_results.first().params.network_type;
+                        activeConfig.d->service_type = state_results.first().params.service_type;
+                        activeConfig.d->service_id = state_results.first().params.service_id;
+                        activeConfig.d->service_attrs = state_results.first().params.service_attrs;
+                        activeConfig.d->type = QNetworkConfiguration::InternetAccessPoint;
+                        activeConfig.d->state = QNetworkConfiguration::Active;
+                        activeConfig.d->isValid = true;
+                        currentNetworkInterface = get_network_interface();
 
 			Maemo::IAPConf iap_name(activeConfig.d->id);
 			QString name_value = iap_name.value("name").toString();
@@ -566,7 +425,6 @@
 			else
 			    activeConfig.d->name = activeConfig.d->id;
 
-
 			// Add the new active configuration to manager or update the old config
 			mgr = (QNetworkConfigurationManagerPrivate*)activeConfig.d.data()->manager;
 			if (!(mgr->accessPointConfigurations.contains(activeConfig.d->id))) {
@@ -581,23 +439,17 @@
 			    //qDebug()<<"New configuration"<<activeConfig.d->id<<"added to manager in sync";
 #endif
 
-			} else {
-			    mgr->configurationChanged((QNetworkConfigurationPrivate*)(activeConfig.d.data()));
-#ifdef BEARER_MANAGEMENT_DEBUG
-			    //qDebug()<<"Existing configuration"<<activeConfig.d->id<<"updated in manager in sync";
-#endif
-			}
-
+                        }
 		    }
 		    break;
 
 		case ICD_STATE_DISCONNECTING:
-		    state = QNetworkSession::Closing;
+                    state = QNetworkSession::Closing;
 		    if (activeConfig.d.data())
 			activeConfig.d->isValid = true;
 		    break;
 		default:
-		    break;
+                    break;
 		}
 	    }
 	} else {
@@ -686,7 +538,6 @@
         state = QNetworkSession::NotAvailable;
     } else if ((activeConfig.state() & QNetworkConfiguration::Undefined) == QNetworkConfiguration::Undefined) {
         state = QNetworkSession::NotAvailable;
-	clearConfiguration(activeConfig);
     }
 
     bool oldActive = isOpen;
@@ -701,7 +552,7 @@
     if (oldState != state) {
         emit q->stateChanged(state);
 
-	if (state == QNetworkSession::Disconnected) {
+        if (state == QNetworkSession::Disconnected && oldActive) {
 #ifdef BEARER_MANAGEMENT_DEBUG
 	    //qDebug()<<"session aborted error emitted for"<<activeConfig.identifier();
 #endif
@@ -715,16 +566,6 @@
 #endif
 }
 
-
-void QNetworkSessionPrivate::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;
@@ -761,14 +602,16 @@
     }
 
     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;
-	}
+        if (ifa->ifa_addr) {
+            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);
@@ -778,11 +621,18 @@
 
 void QNetworkSessionPrivate::open()
 {
+    if (m_stopTimer.isActive()) {
+        m_stopTimer.stop();
+    }
+    if (!publicConfig.isValid()) {
+        lastError = QNetworkSession::InvalidConfigurationError;
+        emit q->error(lastError);
+        return;
+    }
     if (serviceConfig.isValid()) {
         lastError = QNetworkSession::OperationNotSupportedError;
         emit q->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
@@ -810,219 +660,206 @@
         if ((activeConfig.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active) {
             state = QNetworkSession::Connecting;
             emit q->stateChanged(state);
-
-	    QTimer::singleShot(0, this, SLOT(do_open()));
-	    return;
+            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();
+        /* We seem to be active so inform caller */
+        emit quitPendingWaitsForOpened();
     }
 }
 
-
 void QNetworkSessionPrivate::do_open()
 {
     icd_connection_flags flags = connectFlags;
-    bool st;
-    QString result;
     QString iap = publicConfig.identifier();
 
     if (state == QNetworkSession::Connected) {
 #ifdef BEARER_MANAGEMENT_DEBUG
-	qDebug() << "Already connected to" << activeConfig.identifier();
+        qDebug() << "Already connected to" << activeConfig.identifier();
 #endif
         emit q->stateChanged(QNetworkSession::Connected);
-	emit quitPendingWaitsForOpened();
+        emit quitPendingWaitsForOpened();
 	return;
     }
 
-    Maemo::IcdConnectResult connect_result;
-    Maemo::Icd icd(ICD_LONG_CONNECT_TIMEOUT);
-    QNetworkConfiguration config;
     if (publicConfig.type() == QNetworkConfiguration::UserChoice)
-	config = activeConfig;
+        config = activeConfig;
     else
-	config = publicConfig;
+        config = publicConfig;
 
     if (iap == OSSO_IAP_ANY) {
 #ifdef BEARER_MANAGEMENT_DEBUG
-	qDebug() << "connecting to default IAP" << iap;
+        qDebug() << "connecting to default IAP" << iap;
 #endif
-	st = icd.connect(flags, connect_result);
-
+        m_connectRequestTimer.start(ICD_LONG_CONNECT_TIMEOUT);
+        m_dbusInterface->asyncCall(ICD_DBUS_API_CONNECT_REQ, (uint)flags); // Return value ignored
+        m_asynchCallActive = true;
     } else {
-
-	QList<Maemo::ConnectParams> params;
-	Maemo::ConnectParams param;
-	param.connect.service_type = config.d->service_type;
-	param.connect.service_attrs = config.d->service_attrs;
-	param.connect.service_id = config.d->service_id;
-	param.connect.network_type = config.d->iap_type;
-	param.connect.network_attrs = config.d->network_attrs;
-	if (config.d->network_attrs & ICD_NW_ATTR_IAPNAME)
-	    param.connect.network_id = QByteArray(iap.toLatin1());
-	else
-	    param.connect.network_id = config.d->network_id;
-	params.append(param);
+        ICd2DetailsDBusStruct icd2;
+        icd2.serviceType = config.d->service_type;
+        icd2.serviceAttributes = config.d->service_attrs;
+        icd2.setviceId = config.d->service_id;
+        icd2.networkType = config.d->iap_type;
+        icd2.networkAttributes = config.d->network_attrs;
+        if (config.d->network_attrs & ICD_NW_ATTR_IAPNAME) {
+            icd2.networkId  = QByteArray(iap.toLatin1());
+        } else {
+            icd2.networkId  = config.d->network_id;
+        }
 
 #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 q->error(QNetworkSession::InvalidConfigurationError);
-	    if (publicConfig.type() == QNetworkConfiguration::UserChoice)
-		cleanupAnyConfiguration();
-	    return;
-	}
-
-	/* If the user tried to connect to some specific connection (foo)
-	 * and we were already connected to some other connection (bar),
-	 * then we cannot activate this session although icd has a valid
-	 * connection to somewhere.
-	 */
-	if ((publicConfig.type() != QNetworkConfiguration::UserChoice) &&
-	    (connected_iap != config.identifier())) {
-	    updateState(QNetworkSession::Disconnected);
-	    emit q->error(QNetworkSession::InvalidConfigurationError);
-	    return;
-	}
-
-
-	/* Did we connect to non saved IAP? */
-	if (!(config.d->network_attrs & ICD_NW_ATTR_IAPNAME)) {
-	    /* Because the connection succeeded, the IAP is now known.
-	     */
-	    config.d->network_attrs |= ICD_NW_ATTR_IAPNAME;
-	    config.d->id = connected_iap;
-	}
-
-	/* User might have changed the IAP name when a new IAP was saved */
-	Maemo::IAPConf iap_name(config.d->id);
-	QString name = iap_name.value("name").toString();
-	if (!name.isEmpty())
-	    config.d->name = name;
-
-        config.d->iap_type = connect_result.connect.network_type;
-
-	config.d->isValid = true;
-	config.d->state = QNetworkConfiguration::Active;
-	config.d->type = QNetworkConfiguration::InternetAccessPoint;
-
-	startTime = QDateTime::currentDateTime();
-	updateState(QNetworkSession::Connected);
-
-	currentNetworkInterface = get_network_interface();
-
-#ifdef BEARER_MANAGEMENT_DEBUG
-	qDebug() << "connected to" << result << config.d->name << "at" << currentNetworkInterface;
+    qDebug("connecting to %s/%s/0x%x/%s/0x%x/%s",
+        icd2.networkId.data(),
+        icd2.networkType.toAscii().constData(),
+        icd2.networkAttributes,
+        icd2.serviceType.toAscii().constData(),
+        icd2.serviceAttributes,
+        icd2.setviceId.toAscii().constData());
 #endif
 
-	/* We first check if the configuration already exists in the manager
-	 * and if it is not found there, we then insert it. Note that this
-	 * is only done for user choice config only because it can be missing
-	 * from config manager list.
-	 */
-
-	if (publicConfig.d->type == QNetworkConfiguration::UserChoice) {
-
-#ifdef BEARER_MANAGEMENT_DEBUG
-#if 0
-	    QList<QNetworkConfiguration> configs;
-	    QNetworkConfigurationManagerPrivate *conPriv = (QNetworkConfigurationManagerPrivate*)config.d.data()->manager;
-	    QList<QString> cpsIdents = conPriv->accessPointConfigurations.keys();
-	    foreach( QString ii, cpsIdents) {
-		QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> p = 
-		    conPriv->accessPointConfigurations.value(ii);
-		QNetworkConfiguration pt;
-		pt.d = conPriv->accessPointConfigurations.value(ii);
-		configs << pt;
-	    }
-
-	    int all = configs.count();
-	    qDebug() << "All configurations:" << all;
-	    foreach(QNetworkConfiguration p, configs) {
-		qDebug() << p.name() <<":  isvalid->" <<p.isValid() << " type->"<< p.type() << 
-		    " roaming->" << p.isRoamingAvailable() << "identifier->" << p.identifier() <<
-		    " purpose->" << p.purpose() << " state->" << p.state();
-	    }
-#endif
-#endif
-
-	    QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)config.d.data()->manager;
-            if (!mgr->accessPointConfigurations.contains(result)) {
-		QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = config.d;
-		mgr->accessPointConfigurations.insert(result, ptr);
-
-		QNetworkConfiguration item;
-		item.d = ptr;
-		emit mgr->configurationAdded(item);
-
-#ifdef BEARER_MANAGEMENT_DEBUG
-		//qDebug()<<"New configuration"<<result<<"added to manager in open";
-#endif
-
-	    } else {
-		QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = mgr->accessPointConfigurations.value(result);
-		QNetworkConfiguration reference;
-		reference.d = priv;
-                copyConfig(config, reference, false);
-                config = reference;
-                activeConfig = reference;
-		mgr->configurationChanged((QNetworkConfigurationPrivate*)(config.d.data()));
-
-#ifdef BEARER_MANAGEMENT_DEBUG
-		//qDebug()<<"Existing configuration"<<result<<"updated in manager in open";
-#endif
-	    }
-	}
-
-	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 q->error(QNetworkSession::UnknownSessionError);
+        ICd2DetailsList paramArray;
+        paramArray.append(icd2);
+        m_connectRequestTimer.start(ICD_LONG_CONNECT_TIMEOUT);
+        m_dbusInterface->asyncCall(ICD_DBUS_API_CONNECT_REQ, (uint)flags, QVariant::fromValue(paramArray)); // Return value ignored
+        m_asynchCallActive = true;
     }
 }
 
+ void QNetworkSessionPrivate::stateChange(const QDBusMessage& rep)
+{
+     if (m_asynchCallActive == true) {
+        if (m_connectRequestTimer.isActive())
+            m_connectRequestTimer.stop();
+        m_asynchCallActive = false;
 
-void QNetworkSessionPrivate::cleanupAnyConfiguration()
-{
+        QString result = rep.arguments().at(5).toString(); // network id or empty string
+        QString connected_iap = result;
+        if (connected_iap.isEmpty()) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+            qDebug() << "connect to"<< publicConfig.identifier() << "failed, result is empty";
+#endif
+            updateState(QNetworkSession::Disconnected);
+            emit q->error(QNetworkSession::InvalidConfigurationError);
+            if (publicConfig.type() == QNetworkConfiguration::UserChoice)
+                    copyConfig(publicConfig, activeConfig);
+            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 q->error(QNetworkSession::InvalidConfigurationError);
+            return;
+        }
+
+        /* Did we connect to non saved IAP? */
+        if (!(config.d->network_attrs & ICD_NW_ATTR_IAPNAME)) {
+            /* Because the connection succeeded, the IAP is now known.
+             */
+            config.d->network_attrs |= ICD_NW_ATTR_IAPNAME;
+            config.d->id = connected_iap;
+        }
+
+        /* User might have changed the IAP name when a new IAP was saved */
+        Maemo::IAPConf iap_name(config.d->id);
+        QString name = iap_name.value("name").toString();
+        if (!name.isEmpty())
+            config.d->name = name;
+
+        config.d->iap_type = rep.arguments().at(3).toString(); // connect_result.connect.network_type;
+        config.d->isValid = true;
+        config.d->state = QNetworkConfiguration::Active;
+        config.d->type = QNetworkConfiguration::InternetAccessPoint;
+
+        startTime = QDateTime::currentDateTime();
+        updateState(QNetworkSession::Connected);
+        //currentNetworkInterface = get_network_interface();
 #ifdef BEARER_MANAGEMENT_DEBUG
-    qDebug()<<"Removing configuration created for" << activeConfig.d->id;
+        //qDebug() << "connected to" << result << config.d->name << "at" << currentNetworkInterface;
+#endif
+
+        /* We first check if the configuration already exists in the manager
+         * and if it is not found there, we then insert it. Note that this
+         * is only done for user choice config only because it can be missing
+         * from config manager list.
+         */
+        if (publicConfig.d->type == QNetworkConfiguration::UserChoice) {
+#ifdef BEARER_MANAGEMENT_DEBUG
+#if 0
+            QList<QNetworkConfiguration> configs;
+            QNetworkConfigurationManagerPrivate *conPriv = (QNetworkConfigurationManagerPrivate*)config.d.data()->manager;
+            QList<QString> cpsIdents = conPriv->accessPointConfigurations.keys();
+            foreach( QString ii, cpsIdents) {
+                QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> p =
+                        conPriv->accessPointConfigurations.value(ii);
+                QNetworkConfiguration pt;
+                pt.d = conPriv->accessPointConfigurations.value(ii);
+                configs << pt;
+            }
+
+            int all = configs.count();
+            qDebug() << "All configurations:" << all;
+            foreach(QNetworkConfiguration p, configs) {
+                qDebug() << p.name() <<":  isvalid->" <<p.isValid() << " type->"<< p.type() <<
+                        " roaming->" << p.isRoamingAvailable() << "identifier->" << p.identifier() <<
+                        " purpose->" << p.purpose() << " state->" << p.state();
+            }
+#endif
 #endif
-    activeConfig = publicConfig;
+            QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager;
+            if (!mgr->accessPointConfigurations.contains(result)) {
+                QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = config.d;
+                mgr->accessPointConfigurations.insert(result, ptr);
+
+                QNetworkConfiguration item;
+                item.d = ptr;
+                emit mgr->configurationAdded(item);
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+            qDebug()<<"New configuration"<<result<<"added to manager in open";
+#endif
+
+            } else {
+                QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = mgr->accessPointConfigurations.value(result);
+                QNetworkConfiguration reference;
+                reference.d = priv;
+                copyConfig(config, reference, false);
+                reference.d.data()->id = result; // Note: Id was not copied in copyConfig() function
+                config = reference;
+                activeConfig = reference;
+
+#ifdef BEARER_MANAGEMENT_DEBUG
+                qDebug()<<"Existing configuration"<<result<<"updated in manager in open";
+#endif
+            }
+        }
+
+        emit quitPendingWaitsForOpened();
+    }
 }
 
+void QNetworkSessionPrivate::connectTimeout()
+{
+    updateState(QNetworkSession::Disconnected);
+    if (publicConfig.type() == QNetworkConfiguration::UserChoice)
+            copyConfig(publicConfig, activeConfig);
+        emit q->error(QNetworkSession::UnknownSessionError);
+}
 
 void QNetworkSessionPrivate::close()
 {
+    if (m_connectRequestTimer.isActive())
+        m_connectRequestTimer.stop();
+
     if (serviceConfig.isValid()) {
         lastError = QNetworkSession::OperationNotSupportedError;
         emit q->error(lastError);
@@ -1036,33 +873,37 @@
 
 void QNetworkSessionPrivate::stop()
 {
+    if (m_connectRequestTimer.isActive())
+        m_connectRequestTimer.stop();
+
     if (serviceConfig.isValid()) {
         lastError = QNetworkSession::OperationNotSupportedError;
         emit q->error(lastError);
     } else {
         if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
-            state = QNetworkSession::Closing;
-            emit q->stateChanged(state);
-
-	    Maemo::Icd icd;
+            if (!m_stopTimer.isActive()) {
+                Maemo::Icd icd;
 #ifdef BEARER_MANAGEMENT_DEBUG
-	    qDebug() << "stopping session" << publicConfig.identifier();
+                qDebug() << "stopping session" << publicConfig.identifier();
 #endif
-	    icd.disconnect(ICD_CONNECTION_FLAG_APPLICATION_EVENT);
-	    startTime = QDateTime();
+                state = QNetworkSession::Closing;
+                emit q->stateChanged(state);
+
+                opened = false;
+                isOpen = false;
 
-	    /* Note that the state will go disconnected in
-	     * updateStateFromActiveConfig() which gets called after
-	     * configurationChanged is emitted (below).
-	     */
+                icd.disconnect(ICD_CONNECTION_FLAG_APPLICATION_EVENT);
+                startTime = QDateTime();
 
-	    activeConfig.d->state = QNetworkConfiguration::Discovered;
-	    QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)activeConfig.d.data()->manager;
-	    mgr->configurationChanged((QNetworkConfigurationPrivate*)activeConfig.d.data());
+                /* Note: Session state will change to disconnected
+                 *       as soon as QNetworkConfigurationManager sends
+                 *       corresponding iapStateChanged signal.
+                 */
 
-	    opened = false;
-	    isOpen = false;
-
+                // Make sure that this Session will send closed signal
+                // even though ICD connection will not ever get closed
+                m_stopTimer.start(ICD_SHORT_CONNECT_TIMEOUT); // 10 seconds wait
+            }
         } else {
 	    opened = false;
 	    isOpen = false;
@@ -1071,6 +912,14 @@
     }
 }
 
+void QNetworkSessionPrivate::finishStopBySendingClosedSignal()
+{
+    if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
+        state = QNetworkSession::Connected;
+        emit q->stateChanged(state);
+    }
+    emit q->closed();
+}
 
 void QNetworkSessionPrivate::migrate()
 {
@@ -1186,7 +1035,6 @@
 }
 
 
-#include "qnetworksession_maemo.moc"
 #include "moc_qnetworksession_maemo_p.cpp"
 
 QTM_END_NAMESPACE