qtmobility/src/bearer/qnetworksession_maemo.cpp
changeset 0 cfcbf08528c4
child 2 5822d84012fb
child 4 90517678cc4f
equal deleted inserted replaced
-1:000000000000 0:cfcbf08528c4
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the Qt Mobility Components.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <QHash>
       
    43 
       
    44 #include "qnetworksession_maemo_p.h"
       
    45 #include <dbus/dbus.h>
       
    46 #include <dbus/dbus-glib-lowlevel.h>
       
    47 
       
    48 #include <maemo_icd.h>
       
    49 #include <iapconf.h>
       
    50 #include <proxyconf.h>
       
    51 
       
    52 #include <sys/types.h>
       
    53 #include <ifaddrs.h>
       
    54 #include <sys/socket.h>
       
    55 #include <netinet/in.h>
       
    56 #include <arpa/inet.h>
       
    57 
       
    58 QTM_BEGIN_NAMESPACE
       
    59 
       
    60 static QHash<QString, QVariant> properties;
       
    61 
       
    62 static QString get_network_interface();
       
    63 static DBusConnection *dbus_connection;
       
    64 static DBusHandlerResult signal_handler(DBusConnection *connection,
       
    65 					DBusMessage *message,
       
    66 					void *user_data);
       
    67 
       
    68 #define ICD_DBUS_MATCH		"type='signal'," \
       
    69 				"interface='" ICD_DBUS_INTERFACE "'," \
       
    70 				"path='" ICD_DBUS_PATH "'"
       
    71 
       
    72 
       
    73 static inline DBusConnection *get_dbus_conn(DBusError *error)
       
    74 {
       
    75     DBusConnection *conn = dbus_bus_get(DBUS_BUS_SYSTEM, error);
       
    76 #ifdef BEARER_MANAGEMENT_DEBUG
       
    77     qDebug() << "Listening to bus" << dbus_bus_get_unique_name(conn);
       
    78 #endif
       
    79 
       
    80     return conn;
       
    81 }
       
    82 
       
    83 
       
    84 /* Helper class that monitors the Icd status messages and
       
    85  * can change the IAP status accordingly. This is a singleton.
       
    86  */
       
    87 class IcdListener : public QObject
       
    88 {
       
    89     Q_OBJECT
       
    90 
       
    91 public:
       
    92     IcdListener() : first_call(true) { }
       
    93     friend DBusHandlerResult signal_handler(DBusConnection *connection,
       
    94 					    DBusMessage *message,
       
    95 					    void *user_data);
       
    96     void setup(QNetworkSessionPrivate *d);
       
    97     void cleanup();
       
    98     void cleanupSession(QNetworkSessionPrivate *ptr);
       
    99 
       
   100     enum IapConnectionStatus {
       
   101 	/* The IAP was connected */
       
   102 	CONNECTED = 0,
       
   103 	/* The IAP was disconnected */
       
   104 	DISCONNECTED,
       
   105 	/* The IAP is disconnecting */
       
   106 	DISCONNECTING,
       
   107 	/* The IAP has a network address, but is not yet fully connected */
       
   108 	NETWORK_UP
       
   109     };
       
   110 
       
   111 private:
       
   112     void icdSignalReceived(QString&, QString&, QString&);
       
   113     bool first_call;
       
   114     QHash<QString, QNetworkSessionPrivate* > sessions;
       
   115 };
       
   116 
       
   117 Q_GLOBAL_STATIC(IcdListener, icdListener);
       
   118  
       
   119 
       
   120 static DBusHandlerResult signal_handler(DBusConnection *,
       
   121 					DBusMessage *message,
       
   122 					void *user_data)
       
   123 {
       
   124     if (dbus_message_is_signal(message,
       
   125 				ICD_DBUS_INTERFACE,
       
   126 				ICD_STATUS_CHANGED_SIG)) {
       
   127 
       
   128 	IcdListener *icd = (IcdListener *)user_data;
       
   129 	DBusError error;
       
   130 	dbus_error_init(&error);
       
   131 
       
   132 	char *iap_id = 0;
       
   133 	char *network_type = 0;
       
   134 	char *state = 0;
       
   135 
       
   136 	if (dbus_message_get_args(message, &error,
       
   137 				    DBUS_TYPE_STRING, &iap_id,
       
   138 				    DBUS_TYPE_STRING, &network_type,
       
   139 				    DBUS_TYPE_STRING, &state,
       
   140 				    DBUS_TYPE_INVALID) == FALSE) {
       
   141 	    qWarning() << QString("Failed to parse icd status signal: %1").arg(error.message);
       
   142         } else {
       
   143 	    QString _iap_id(iap_id);
       
   144 	    QString _network_type(network_type);
       
   145 	    QString _state(state);
       
   146 
       
   147 	    icd->icdSignalReceived(_iap_id, _network_type, _state);
       
   148 	}
       
   149 
       
   150 	dbus_error_free(&error);
       
   151         return DBUS_HANDLER_RESULT_HANDLED;
       
   152     }
       
   153 
       
   154     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
       
   155 }
       
   156 
       
   157 
       
   158 void IcdListener::setup(QNetworkSessionPrivate *d)
       
   159 {
       
   160     if (first_call) {
       
   161 	// We use the old Icd dbus interface like in ConIC
       
   162 	DBusError error;
       
   163 	dbus_error_init(&error);
       
   164 
       
   165 	dbus_connection = get_dbus_conn(&error);
       
   166 	if (dbus_error_is_set(&error)) {
       
   167 	    qWarning() << "Cannot get dbus connection.";
       
   168 	    dbus_error_free(&error);
       
   169 	    return;
       
   170 	}
       
   171 
       
   172 	static struct DBusObjectPathVTable icd_vtable;
       
   173 	icd_vtable.message_function = signal_handler;
       
   174 
       
   175 	dbus_bus_add_match(dbus_connection, ICD_DBUS_MATCH, &error);
       
   176 	if (dbus_error_is_set(&error)) {
       
   177 	    qWarning() << "Cannot add match" << ICD_DBUS_MATCH;
       
   178 	    dbus_error_free(&error);
       
   179 	    return;
       
   180 	}
       
   181 
       
   182 	if (dbus_connection_register_object_path(dbus_connection,
       
   183 						    ICD_DBUS_PATH,
       
   184 						    &icd_vtable,
       
   185 						    (void*)this) == FALSE) {
       
   186 	    qWarning() << "Cannot register dbus signal handler, interface"<< ICD_DBUS_INTERFACE << "path" << ICD_DBUS_PATH;
       
   187 	    dbus_error_free(&error);
       
   188 	    return;
       
   189 	}
       
   190 
       
   191 #ifdef BEARER_MANAGEMENT_DEBUG
       
   192 	qDebug() << "Listening" << ICD_STATUS_CHANGED_SIG << "signal from" << ICD_DBUS_SERVICE;
       
   193 #endif
       
   194 	first_call = false;
       
   195 	dbus_error_free(&error);
       
   196     }
       
   197 
       
   198     QString id = d->activeConfig.identifier();
       
   199     if (!sessions.contains(id)) {
       
   200 	QNetworkSessionPrivate *ptr = d;
       
   201 	sessions.insert(id, ptr);
       
   202     }
       
   203 }
       
   204 
       
   205 
       
   206 void IcdListener::icdSignalReceived(QString& iap_id,
       
   207 #ifdef BEARER_MANAGEMENT_DEBUG
       
   208 				    QString& network_type,
       
   209 #else
       
   210 				    QString&,
       
   211 #endif
       
   212 				    QString& state)
       
   213 {
       
   214     if (iap_id == OSSO_IAP_SCAN) // icd sends scan status signals which we will ignore
       
   215 	return;
       
   216 
       
   217 #ifdef BEARER_MANAGEMENT_DEBUG
       
   218     qDebug() << "Status received:" << iap_id << "type" << network_type << "state" << state;
       
   219 #endif
       
   220 
       
   221     if (!sessions.contains(iap_id)) {
       
   222 #ifdef BEARER_MANAGEMENT_DEBUG
       
   223 	qDebug() << "No session for IAP" << iap_id;
       
   224 #endif
       
   225 	return;
       
   226     }
       
   227 
       
   228     QNetworkSessionPrivate *session = sessions.value(iap_id);
       
   229     QNetworkConfiguration ap_conf = session->manager.configurationFromIdentifier(iap_id);
       
   230     if (!ap_conf.isValid()) {
       
   231 #ifdef BEARER_MANAGEMENT_DEBUG
       
   232 	qDebug() << "Unknown IAP" << iap_id;
       
   233 #endif
       
   234 	return;
       
   235     }
       
   236 
       
   237     IapConnectionStatus status;
       
   238 
       
   239     if (state == "IDLE") {
       
   240 	status = DISCONNECTED;
       
   241     } else if (state == "CONNECTED") {
       
   242 	status = CONNECTED;
       
   243     } else if (state == "NETWORKUP") {
       
   244 	status = NETWORK_UP;
       
   245     } else {
       
   246 	//qDebug() << "Unknown state" << state;
       
   247 	return;
       
   248     }
       
   249 
       
   250     if (status == DISCONNECTED) {
       
   251 	if (ap_conf.state() == QNetworkConfiguration::Active) {
       
   252 	    /* The IAP was just disconnected by Icd */
       
   253 	    session->updateState(QNetworkSession::Disconnected);
       
   254 	} else {
       
   255 #ifdef BEARER_MANAGEMENT_DEBUG
       
   256 	    qDebug() << "Got a network disconnect when in state" << ap_conf.state();
       
   257 #endif
       
   258 	}
       
   259     } else if (status == CONNECTED) {
       
   260 	/* The IAP was just connected by Icd */
       
   261 	session->updateState(QNetworkSession::Connected);
       
   262 	session->updateIdentifier(iap_id);
       
   263 
       
   264 	if (session->publicConfig.identifier() == OSSO_IAP_ANY) {
       
   265 #ifdef BEARER_MANAGEMENT_DEBUG
       
   266 	    qDebug() << "IAP" << iap_id << "connected when connecting to" << OSSO_IAP_ANY;
       
   267 #endif
       
   268 	} else {
       
   269 #ifdef BEARER_MANAGEMENT_DEBUG
       
   270 	    qDebug() << "IAP" << iap_id << "connected";
       
   271 #endif
       
   272 	}
       
   273     }
       
   274 
       
   275     return;
       
   276 }
       
   277 
       
   278 
       
   279 void IcdListener::cleanup()
       
   280 {
       
   281     if (!first_call) {
       
   282 	dbus_bus_remove_match(dbus_connection, ICD_DBUS_MATCH, NULL);
       
   283 	dbus_connection_unref(dbus_connection);
       
   284     }
       
   285 }
       
   286 
       
   287 
       
   288 void IcdListener::cleanupSession(QNetworkSessionPrivate *ptr)
       
   289 {
       
   290     if (ptr->publicConfig.type() == QNetworkConfiguration::UserChoice)
       
   291         (void)sessions.take(ptr->activeConfig.identifier());
       
   292     else
       
   293         (void)sessions.take(ptr->publicConfig.identifier());
       
   294 }
       
   295 
       
   296 
       
   297 void QNetworkSessionPrivate::cleanupSession(void)
       
   298 {
       
   299     icdListener()->cleanupSession(this);
       
   300 
       
   301     QObject::disconnect(q, SIGNAL(stateChanged(QNetworkSession::State)), this, SLOT(updateProxies(QNetworkSession::State)));
       
   302 }
       
   303 
       
   304 
       
   305 void QNetworkSessionPrivate::updateState(QNetworkSession::State newState)
       
   306 {
       
   307     if( newState != state) {
       
   308         state = newState;
       
   309 
       
   310 	if (state == QNetworkSession::Disconnected) {
       
   311             isOpen = false;
       
   312 	    currentNetworkInterface.clear();
       
   313 	    if (publicConfig.type() == QNetworkConfiguration::UserChoice)
       
   314 		activeConfig.d->state = QNetworkConfiguration::Defined;
       
   315 	    publicConfig.d->state = QNetworkConfiguration::Defined;
       
   316 
       
   317 	} else if (state == QNetworkSession::Connected) {
       
   318             isOpen = true;
       
   319 	    if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
       
   320 		activeConfig.d->state = QNetworkConfiguration::Active;
       
   321 		activeConfig.d->type = QNetworkConfiguration::InternetAccessPoint;
       
   322 	    }
       
   323 	    publicConfig.d->state = QNetworkConfiguration::Active;
       
   324 	}
       
   325 
       
   326 	emit q->stateChanged(newState);
       
   327     }
       
   328 }
       
   329 
       
   330 
       
   331 void QNetworkSessionPrivate::updateIdentifier(QString &newId)
       
   332 {
       
   333     if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
       
   334 	activeConfig.d->network_attrs |= ICD_NW_ATTR_IAPNAME;
       
   335 	activeConfig.d->id = newId;
       
   336     } else {
       
   337 	publicConfig.d->network_attrs |= ICD_NW_ATTR_IAPNAME;
       
   338 	if (publicConfig.d->id != newId) {
       
   339 	    qWarning() << "Your config id changed from" << publicConfig.d->id << "to" << newId;
       
   340 	    publicConfig.d->id = newId;
       
   341 	}
       
   342     }
       
   343 }
       
   344 
       
   345 
       
   346 quint64 QNetworkSessionPrivate::getStatistics(bool sent) const
       
   347 {
       
   348     /* This could be also implemented by using the Maemo::Icd::statistics()
       
   349      * that gets the statistics data for a specific IAP. Change if
       
   350      * necessary.
       
   351      */
       
   352     Maemo::Icd icd;
       
   353     QList<Maemo::IcdStatisticsResult> stats_results;
       
   354     quint64 counter_rx = 0, counter_tx = 0;
       
   355 
       
   356     if (!icd.statistics(stats_results)) {
       
   357 	return 0;
       
   358     }
       
   359 
       
   360     foreach (Maemo::IcdStatisticsResult res, stats_results) {
       
   361 	if (res.params.network_attrs & ICD_NW_ATTR_IAPNAME) {
       
   362 	    /* network_id is the IAP UUID */
       
   363 	    if (QString(res.params.network_id.data()) == activeConfig.identifier()) {
       
   364 		counter_tx = res.bytes_sent;
       
   365 		counter_rx = res.bytes_received;
       
   366 	    }
       
   367 	} else {
       
   368 	    /* We probably will never get to this branch */
       
   369 	    QNetworkConfigurationPrivate *d = activeConfig.d.data();
       
   370 	    if (res.params.network_id == d->network_id) {
       
   371 		counter_tx = res.bytes_sent;
       
   372 		counter_rx = res.bytes_received;
       
   373 	    }
       
   374 	}
       
   375     }
       
   376 
       
   377     if (sent)
       
   378 	return counter_tx;
       
   379     else
       
   380 	return counter_rx;
       
   381 }
       
   382 
       
   383 
       
   384 quint64 QNetworkSessionPrivate::bytesWritten() const
       
   385 {
       
   386     return getStatistics(true);
       
   387 }
       
   388 
       
   389 quint64 QNetworkSessionPrivate::bytesReceived() const
       
   390 {
       
   391     return getStatistics(false);
       
   392 }
       
   393 
       
   394 quint64 QNetworkSessionPrivate::activeTime() const
       
   395 {
       
   396     if (startTime.isNull()) {
       
   397         return 0;
       
   398     }
       
   399     return startTime.secsTo(QDateTime::currentDateTime());
       
   400 }
       
   401 
       
   402 
       
   403 QNetworkConfiguration& QNetworkSessionPrivate::copyConfig(QNetworkConfiguration &fromConfig, QNetworkConfiguration &toConfig, bool deepCopy)
       
   404 {
       
   405     if (deepCopy) {
       
   406         QNetworkConfigurationPrivate* cpPriv = new QNetworkConfigurationPrivate();
       
   407         QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr(cpPriv);
       
   408         toConfig.d = ptr;
       
   409     }
       
   410 
       
   411     toConfig.d->name = fromConfig.d->name;
       
   412     toConfig.d->isValid = fromConfig.d->isValid;
       
   413     // Note that we do not copy id field here as the publicConfig does
       
   414     // not contain a valid IAP id.
       
   415     toConfig.d->state = fromConfig.d->state;
       
   416     toConfig.d->type = fromConfig.d->type;
       
   417     toConfig.d->roamingSupported = fromConfig.d->roamingSupported;
       
   418     toConfig.d->purpose = fromConfig.d->purpose;
       
   419     toConfig.d->network_id = fromConfig.d->network_id;
       
   420     toConfig.d->iap_type = fromConfig.d->iap_type;
       
   421     toConfig.d->network_attrs = fromConfig.d->network_attrs;
       
   422     toConfig.d->service_type = fromConfig.d->service_type;
       
   423     toConfig.d->service_id = fromConfig.d->service_id;
       
   424     toConfig.d->service_attrs = fromConfig.d->service_attrs;
       
   425     toConfig.d->manager = fromConfig.d->manager;
       
   426 
       
   427     return toConfig;
       
   428 }
       
   429 
       
   430 
       
   431 /* This is called by QNetworkSession constructor and it updates the current
       
   432  * state of the configuration.
       
   433  */
       
   434 void QNetworkSessionPrivate::syncStateWithInterface()
       
   435 {
       
   436     /* Start to listen Icd status messages. */
       
   437     icdListener()->setup(this);
       
   438 
       
   439     /* Initially we are not active although the configuration might be in
       
   440      * connected state.
       
   441      */
       
   442     isOpen = false;
       
   443     opened = false;
       
   444 
       
   445     QObject::connect(&manager, SIGNAL(updateCompleted()), this, SLOT(networkConfigurationsChanged()));
       
   446 
       
   447     if (publicConfig.d.data()) {
       
   448 	QNetworkConfigurationManagerPrivate* mgr = (QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager;
       
   449 	if (mgr) {
       
   450 	    QObject::connect(mgr, SIGNAL(configurationChanged(QNetworkConfiguration)),
       
   451 			    this, SLOT(configurationChanged(QNetworkConfiguration)));
       
   452 	} else {
       
   453 	    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?";
       
   454 	    state = QNetworkSession::Invalid;
       
   455 	    lastError = QNetworkSession::UnknownSessionError;
       
   456 	    return;
       
   457 	}
       
   458     }
       
   459 
       
   460     QObject::connect(q, SIGNAL(stateChanged(QNetworkSession::State)), this, SLOT(updateProxies(QNetworkSession::State)));
       
   461 
       
   462     state = QNetworkSession::Invalid;
       
   463     lastError = QNetworkSession::UnknownSessionError;
       
   464 
       
   465     switch (publicConfig.type()) {
       
   466     case QNetworkConfiguration::InternetAccessPoint:
       
   467 	activeConfig = publicConfig;
       
   468         break;
       
   469     case QNetworkConfiguration::ServiceNetwork:
       
   470 	serviceConfig = publicConfig;
       
   471 	break;
       
   472     case QNetworkConfiguration::UserChoice:
       
   473 	// active config will contain correct data after open() has succeeded
       
   474 	copyConfig(publicConfig, activeConfig);
       
   475 
       
   476 	/* We create new configuration that holds the actual configuration
       
   477 	 * returned by icd. This way publicConfig still contains the
       
   478 	 * original user specified configuration.
       
   479 	 *
       
   480 	 * Note that the new activeConfig configuration is not inserted
       
   481 	 * to configurationManager as manager class will get the newly
       
   482 	 * connected configuration from gconf when the IAP is saved.
       
   483 	 * This configuration manager update is done by IapMonitor class.
       
   484 	 * If the ANY connection fails in open(), then the configuration
       
   485 	 * data is not saved to gconf and will not be added to
       
   486 	 * configuration manager IAP list.
       
   487 	 */
       
   488 #ifdef BEARER_MANAGEMENT_DEBUG
       
   489 	qDebug()<<"New configuration created for" << publicConfig.identifier();
       
   490 #endif
       
   491 	break;
       
   492     default:
       
   493 	/* Invalid configuration, no point continuing */
       
   494 	return;
       
   495     }
       
   496 
       
   497     if (!activeConfig.isValid())
       
   498 	return;
       
   499 
       
   500     /* Get the initial state from icd */
       
   501     Maemo::Icd icd;
       
   502     QList<Maemo::IcdStateResult> state_results;
       
   503 
       
   504     /* Update the active config from first connection, this is ok as icd
       
   505      * supports only one connection anyway.
       
   506      */
       
   507     if (icd.state(state_results) && !state_results.isEmpty()) {
       
   508 
       
   509 	/* If we did not get full state back, then we are not
       
   510 	 * connected and can skip the next part.
       
   511 	 */
       
   512 	if (!(state_results.first().params.network_attrs == 0 &&
       
   513 		state_results.first().params.network_id.isEmpty())) {
       
   514 
       
   515 	    /* If we try to connect to specific IAP and we get results back
       
   516 	     * that tell the icd is actually connected to another IAP,
       
   517 	     * then do not update current state etc.
       
   518 	     */
       
   519 	    if (publicConfig.type() == QNetworkConfiguration::UserChoice ||
       
   520 		    publicConfig.d->id == state_results.first().params.network_id) {
       
   521 
       
   522 		switch (state_results.first().state) {
       
   523 		case ICD_STATE_DISCONNECTED:
       
   524 		    state = QNetworkSession::Disconnected;
       
   525 		    if (activeConfig.d.data())
       
   526 			activeConfig.d->isValid = true;
       
   527 		    break;
       
   528 		case ICD_STATE_CONNECTING:
       
   529 		    state = QNetworkSession::Connecting;
       
   530 		    if (activeConfig.d.data())
       
   531 			activeConfig.d->isValid = true;
       
   532 		    break;
       
   533 		case ICD_STATE_CONNECTED:
       
   534 		    {
       
   535 			if (!state_results.first().error.isEmpty())
       
   536 			    break;
       
   537                         
       
   538                         const QString id = state_results.first().params.network_id;
       
   539 
       
   540 			QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)activeConfig.d.data()->manager;
       
   541 			if (mgr->accessPointConfigurations.contains(id)) {
       
   542                             //we don't want the copied data if the config is already known by the manager
       
   543                             //just reuse it so that existing references to the old data get the same update
       
   544 			    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = mgr->accessPointConfigurations.value(activeConfig.d->id);
       
   545                             activeConfig.d = priv;
       
   546                         }
       
   547 
       
   548 
       
   549 			state = QNetworkSession::Connected;
       
   550 			activeConfig.d->network_id = state_results.first().params.network_id;
       
   551 			activeConfig.d->id = activeConfig.d->network_id;
       
   552 			activeConfig.d->network_attrs = state_results.first().params.network_attrs;
       
   553 			activeConfig.d->iap_type = state_results.first().params.network_type;
       
   554 			activeConfig.d->service_type = state_results.first().params.service_type;
       
   555 			activeConfig.d->service_id = state_results.first().params.service_id;
       
   556 			activeConfig.d->service_attrs = state_results.first().params.service_attrs;
       
   557 			activeConfig.d->type = QNetworkConfiguration::InternetAccessPoint;
       
   558 			activeConfig.d->state = QNetworkConfiguration::Active;
       
   559 			activeConfig.d->isValid = true;
       
   560 			currentNetworkInterface = get_network_interface();
       
   561 
       
   562 			Maemo::IAPConf iap_name(activeConfig.d->id);
       
   563 			QString name_value = iap_name.value("name").toString();
       
   564 			if (!name_value.isEmpty())
       
   565 			    activeConfig.d->name = name_value;
       
   566 			else
       
   567 			    activeConfig.d->name = activeConfig.d->id;
       
   568 
       
   569 
       
   570 			// Add the new active configuration to manager or update the old config
       
   571 			mgr = (QNetworkConfigurationManagerPrivate*)activeConfig.d.data()->manager;
       
   572 			if (!(mgr->accessPointConfigurations.contains(activeConfig.d->id))) {
       
   573 			    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = activeConfig.d;
       
   574 			    mgr->accessPointConfigurations.insert(activeConfig.d->id, ptr);
       
   575 
       
   576 			    QNetworkConfiguration item;
       
   577 			    item.d = ptr;
       
   578 			    emit mgr->configurationAdded(item);
       
   579 
       
   580 #ifdef BEARER_MANAGEMENT_DEBUG
       
   581 			    //qDebug()<<"New configuration"<<activeConfig.d->id<<"added to manager in sync";
       
   582 #endif
       
   583 
       
   584 			} else {
       
   585 			    mgr->configurationChanged((QNetworkConfigurationPrivate*)(activeConfig.d.data()));
       
   586 #ifdef BEARER_MANAGEMENT_DEBUG
       
   587 			    //qDebug()<<"Existing configuration"<<activeConfig.d->id<<"updated in manager in sync";
       
   588 #endif
       
   589 			}
       
   590 
       
   591 		    }
       
   592 		    break;
       
   593 
       
   594 		case ICD_STATE_DISCONNECTING:
       
   595 		    state = QNetworkSession::Closing;
       
   596 		    if (activeConfig.d.data())
       
   597 			activeConfig.d->isValid = true;
       
   598 		    break;
       
   599 		default:
       
   600 		    break;
       
   601 		}
       
   602 	    }
       
   603 	} else {
       
   604 #ifdef BEARER_MANAGEMENT_DEBUG
       
   605 	    qDebug() << "status_req tells icd is not connected";
       
   606 #endif
       
   607 	}
       
   608     } else {
       
   609 #ifdef BEARER_MANAGEMENT_DEBUG
       
   610 	qDebug() << "status_req did not return any results from icd";
       
   611 #endif
       
   612     }
       
   613 
       
   614     networkConfigurationsChanged();
       
   615 }
       
   616 
       
   617 
       
   618 void QNetworkSessionPrivate::networkConfigurationsChanged()
       
   619 {
       
   620     if (serviceConfig.isValid())
       
   621         updateStateFromServiceNetwork();
       
   622     else
       
   623         updateStateFromActiveConfig();
       
   624 }
       
   625 
       
   626 
       
   627 void QNetworkSessionPrivate::updateStateFromServiceNetwork()
       
   628 {
       
   629     QNetworkSession::State oldState = state;
       
   630 
       
   631     foreach (const QNetworkConfiguration &config, serviceConfig.children()) {
       
   632         if ((config.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active)
       
   633             continue;
       
   634 
       
   635         if (activeConfig != config) {
       
   636             activeConfig = config;
       
   637             emit q->newConfigurationActivated();
       
   638         }
       
   639 
       
   640         state = QNetworkSession::Connected;
       
   641         if (state != oldState)
       
   642             emit q->stateChanged(state);
       
   643 
       
   644         return;
       
   645     }
       
   646 
       
   647     if (serviceConfig.children().isEmpty())
       
   648         state = QNetworkSession::NotAvailable;
       
   649     else
       
   650         state = QNetworkSession::Disconnected;
       
   651 
       
   652     if (state != oldState)
       
   653         emit q->stateChanged(state);
       
   654 }
       
   655 
       
   656 
       
   657 void QNetworkSessionPrivate::clearConfiguration(QNetworkConfiguration &config)
       
   658 {
       
   659     config.d->network_id.clear();
       
   660     config.d->iap_type.clear();
       
   661     config.d->network_attrs = 0;
       
   662     config.d->service_type.clear();
       
   663     config.d->service_id.clear();
       
   664     config.d->service_attrs = 0;
       
   665 }
       
   666 
       
   667 
       
   668 void QNetworkSessionPrivate::updateStateFromActiveConfig()
       
   669 {
       
   670     QNetworkSession::State oldState = state;
       
   671 
       
   672     bool newActive = false;
       
   673 
       
   674     if (!activeConfig.d.data())
       
   675 	return;
       
   676 
       
   677     if (!activeConfig.isValid()) {
       
   678         state = QNetworkSession::Invalid;
       
   679 	clearConfiguration(activeConfig);
       
   680     } else if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
       
   681         state = QNetworkSession::Connected;
       
   682         newActive = opened;
       
   683     } else if ((activeConfig.state() & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) {
       
   684         state = QNetworkSession::Disconnected;
       
   685     } else if ((activeConfig.state() & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
       
   686         state = QNetworkSession::NotAvailable;
       
   687     } else if ((activeConfig.state() & QNetworkConfiguration::Undefined) == QNetworkConfiguration::Undefined) {
       
   688         state = QNetworkSession::NotAvailable;
       
   689 	clearConfiguration(activeConfig);
       
   690     }
       
   691 
       
   692     bool oldActive = isOpen;
       
   693     isOpen = newActive;
       
   694 
       
   695     if (!oldActive && isOpen)
       
   696         emit quitPendingWaitsForOpened();
       
   697 
       
   698     if (oldActive && !isOpen)
       
   699         emit q->closed();
       
   700 
       
   701     if (oldState != state) {
       
   702         emit q->stateChanged(state);
       
   703 
       
   704 	if (state == QNetworkSession::Disconnected) {
       
   705 #ifdef BEARER_MANAGEMENT_DEBUG
       
   706 	    //qDebug()<<"session aborted error emitted for"<<activeConfig.identifier();
       
   707 #endif
       
   708 	    lastError = QNetworkSession::SessionAbortedError;
       
   709 	    emit q->error(lastError);
       
   710 	}
       
   711     }
       
   712 
       
   713 #ifdef BEARER_MANAGEMENT_DEBUG
       
   714     //qDebug()<<"oldState ="<<oldState<<" state ="<<state<<" oldActive ="<<oldActive<<" newActive ="<<newActive<<" opened ="<<opened;
       
   715 #endif
       
   716 }
       
   717 
       
   718 
       
   719 void QNetworkSessionPrivate::configurationChanged(const QNetworkConfiguration &config)
       
   720 {
       
   721     if (serviceConfig.isValid() && (config == serviceConfig || config == activeConfig))
       
   722         updateStateFromServiceNetwork();
       
   723     else if (config == activeConfig)
       
   724         updateStateFromActiveConfig();
       
   725 }
       
   726 
       
   727 
       
   728 static QString get_network_interface()
       
   729 {
       
   730     Maemo::Icd icd;
       
   731     QList<Maemo::IcdAddressInfoResult> addr_results;
       
   732     uint ret;
       
   733     QString iface;
       
   734 
       
   735     ret = icd.addrinfo(addr_results);
       
   736     if (ret == 0) {
       
   737 	/* No results */
       
   738 #ifdef BEARER_MANAGEMENT_DEBUG
       
   739 	qDebug() << "Cannot get addrinfo from icd, are you connected or is icd running?";
       
   740 #endif
       
   741 	return iface;
       
   742     }
       
   743 
       
   744     const char *address = addr_results.first().ip_info.first().address.toAscii().constData();
       
   745     struct in_addr addr;
       
   746     if (inet_aton(address, &addr) == 0) {
       
   747 #ifdef BEARER_MANAGEMENT_DEBUG
       
   748 	qDebug() << "address" << address << "invalid";
       
   749 #endif
       
   750 	return iface;
       
   751     }
       
   752 
       
   753     struct ifaddrs *ifaddr, *ifa;
       
   754     int family;
       
   755 
       
   756     if (getifaddrs(&ifaddr) == -1) {
       
   757 #ifdef BEARER_MANAGEMENT_DEBUG
       
   758 	qDebug() << "getifaddrs() failed";
       
   759 #endif
       
   760 	return iface;
       
   761     }
       
   762 
       
   763     for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
       
   764 	family = ifa->ifa_addr->sa_family;
       
   765 	if (family != AF_INET) {
       
   766 	    continue; /* Currently only IPv4 is supported by icd dbus interface */
       
   767 	}
       
   768 	if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == addr.s_addr) {
       
   769 	    iface = QString(ifa->ifa_name);
       
   770 	    break;
       
   771 	}
       
   772     }
       
   773 
       
   774     freeifaddrs(ifaddr);
       
   775     return iface;
       
   776 }
       
   777 
       
   778 
       
   779 void QNetworkSessionPrivate::open()
       
   780 {
       
   781     if (serviceConfig.isValid()) {
       
   782         lastError = QNetworkSession::OperationNotSupportedError;
       
   783         emit q->error(lastError);
       
   784     } else if (!isOpen) {
       
   785 
       
   786 	if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
       
   787 	    /* Caller is trying to connect to default IAP.
       
   788 	     * At this time we will not know the IAP details so we just
       
   789 	     * connect and update the active config when the IAP is
       
   790 	     * connected.
       
   791 	     */
       
   792 	    opened = true;
       
   793             state = QNetworkSession::Connecting;
       
   794             emit q->stateChanged(state);
       
   795 	    QTimer::singleShot(0, this, SLOT(do_open()));
       
   796 	    return;
       
   797 	}
       
   798 
       
   799 	/* User is connecting to one specific IAP. If that IAP is not
       
   800 	 * in discovered state we cannot continue.
       
   801 	 */
       
   802         if ((activeConfig.state() & QNetworkConfiguration::Discovered) !=
       
   803             QNetworkConfiguration::Discovered) {
       
   804             lastError =QNetworkSession::InvalidConfigurationError;
       
   805             emit q->error(lastError);
       
   806             return;
       
   807         }
       
   808         opened = true;
       
   809 
       
   810         if ((activeConfig.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active) {
       
   811             state = QNetworkSession::Connecting;
       
   812             emit q->stateChanged(state);
       
   813 
       
   814 	    QTimer::singleShot(0, this, SLOT(do_open()));
       
   815 	    return;
       
   816         }
       
   817 
       
   818         isOpen = (activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active;
       
   819         if (isOpen)
       
   820             emit quitPendingWaitsForOpened();
       
   821     } else {
       
   822 	/* We seem to be active so inform caller */
       
   823 	emit quitPendingWaitsForOpened();
       
   824     }
       
   825 }
       
   826 
       
   827 
       
   828 void QNetworkSessionPrivate::do_open()
       
   829 {
       
   830     icd_connection_flags flags = connectFlags;
       
   831     bool st;
       
   832     QString result;
       
   833     QString iap = publicConfig.identifier();
       
   834 
       
   835     if (state == QNetworkSession::Connected) {
       
   836 #ifdef BEARER_MANAGEMENT_DEBUG
       
   837 	qDebug() << "Already connected to" << activeConfig.identifier();
       
   838 #endif
       
   839         emit q->stateChanged(QNetworkSession::Connected);
       
   840 	emit quitPendingWaitsForOpened();
       
   841 	return;
       
   842     }
       
   843 
       
   844     Maemo::IcdConnectResult connect_result;
       
   845     Maemo::Icd icd(ICD_LONG_CONNECT_TIMEOUT);
       
   846     QNetworkConfiguration config;
       
   847     if (publicConfig.type() == QNetworkConfiguration::UserChoice)
       
   848 	config = activeConfig;
       
   849     else
       
   850 	config = publicConfig;
       
   851 
       
   852     if (iap == OSSO_IAP_ANY) {
       
   853 #ifdef BEARER_MANAGEMENT_DEBUG
       
   854 	qDebug() << "connecting to default IAP" << iap;
       
   855 #endif
       
   856 	st = icd.connect(flags, connect_result);
       
   857 
       
   858     } else {
       
   859 
       
   860 	QList<Maemo::ConnectParams> params;
       
   861 	Maemo::ConnectParams param;
       
   862 	param.connect.service_type = config.d->service_type;
       
   863 	param.connect.service_attrs = config.d->service_attrs;
       
   864 	param.connect.service_id = config.d->service_id;
       
   865 	param.connect.network_type = config.d->iap_type;
       
   866 	param.connect.network_attrs = config.d->network_attrs;
       
   867 	if (config.d->network_attrs & ICD_NW_ATTR_IAPNAME)
       
   868 	    param.connect.network_id = QByteArray(iap.toLatin1());
       
   869 	else
       
   870 	    param.connect.network_id = config.d->network_id;
       
   871 	params.append(param);
       
   872 
       
   873 #ifdef BEARER_MANAGEMENT_DEBUG
       
   874 	qDebug("connecting to %s/%s/0x%x/%s/0x%x/%s",
       
   875 	    param.connect.network_id.data(),
       
   876 	    param.connect.network_type.toAscii().constData(),
       
   877 	    param.connect.network_attrs,
       
   878 	    param.connect.service_type.toAscii().constData(),
       
   879 	    param.connect.service_attrs,
       
   880 	    param.connect.service_id.toAscii().constData());
       
   881 #endif
       
   882 	st = icd.connect(flags, params, connect_result);
       
   883     }
       
   884 
       
   885     if (st) {
       
   886 	result = connect_result.connect.network_id.data();
       
   887 	QString connected_iap = result;
       
   888 
       
   889 	if (connected_iap.isEmpty()) {
       
   890 #ifdef BEARER_MANAGEMENT_DEBUG
       
   891 	    qDebug() << "connect to"<< iap << "failed, result is empty";
       
   892 #endif
       
   893 	    updateState(QNetworkSession::Disconnected);
       
   894 	    emit q->error(QNetworkSession::InvalidConfigurationError);
       
   895 	    if (publicConfig.type() == QNetworkConfiguration::UserChoice)
       
   896 		cleanupAnyConfiguration();
       
   897 	    return;
       
   898 	}
       
   899 
       
   900 	/* If the user tried to connect to some specific connection (foo)
       
   901 	 * and we were already connected to some other connection (bar),
       
   902 	 * then we cannot activate this session although icd has a valid
       
   903 	 * connection to somewhere.
       
   904 	 */
       
   905 	if ((publicConfig.type() != QNetworkConfiguration::UserChoice) &&
       
   906 	    (connected_iap != config.identifier())) {
       
   907 	    updateState(QNetworkSession::Disconnected);
       
   908 	    emit q->error(QNetworkSession::InvalidConfigurationError);
       
   909 	    return;
       
   910 	}
       
   911 
       
   912 
       
   913 	/* Did we connect to non saved IAP? */
       
   914 	if (!(config.d->network_attrs & ICD_NW_ATTR_IAPNAME)) {
       
   915 	    /* Because the connection succeeded, the IAP is now known.
       
   916 	     */
       
   917 	    config.d->network_attrs |= ICD_NW_ATTR_IAPNAME;
       
   918 	    config.d->id = connected_iap;
       
   919 	}
       
   920 
       
   921 	/* User might have changed the IAP name when a new IAP was saved */
       
   922 	Maemo::IAPConf iap_name(config.d->id);
       
   923 	QString name = iap_name.value("name").toString();
       
   924 	if (!name.isEmpty())
       
   925 	    config.d->name = name;
       
   926 
       
   927         config.d->iap_type = connect_result.connect.network_type;
       
   928 
       
   929 	config.d->isValid = true;
       
   930 	config.d->state = QNetworkConfiguration::Active;
       
   931 	config.d->type = QNetworkConfiguration::InternetAccessPoint;
       
   932 
       
   933 	startTime = QDateTime::currentDateTime();
       
   934 	updateState(QNetworkSession::Connected);
       
   935 
       
   936 	currentNetworkInterface = get_network_interface();
       
   937 
       
   938 #ifdef BEARER_MANAGEMENT_DEBUG
       
   939 	qDebug() << "connected to" << result << config.d->name << "at" << currentNetworkInterface;
       
   940 #endif
       
   941 
       
   942 	/* We first check if the configuration already exists in the manager
       
   943 	 * and if it is not found there, we then insert it. Note that this
       
   944 	 * is only done for user choice config only because it can be missing
       
   945 	 * from config manager list.
       
   946 	 */
       
   947 
       
   948 	if (publicConfig.d->type == QNetworkConfiguration::UserChoice) {
       
   949 
       
   950 #ifdef BEARER_MANAGEMENT_DEBUG
       
   951 #if 0
       
   952 	    QList<QNetworkConfiguration> configs;
       
   953 	    QNetworkConfigurationManagerPrivate *conPriv = (QNetworkConfigurationManagerPrivate*)config.d.data()->manager;
       
   954 	    QList<QString> cpsIdents = conPriv->accessPointConfigurations.keys();
       
   955 	    foreach( QString ii, cpsIdents) {
       
   956 		QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> p = 
       
   957 		    conPriv->accessPointConfigurations.value(ii);
       
   958 		QNetworkConfiguration pt;
       
   959 		pt.d = conPriv->accessPointConfigurations.value(ii);
       
   960 		configs << pt;
       
   961 	    }
       
   962 
       
   963 	    int all = configs.count();
       
   964 	    qDebug() << "All configurations:" << all;
       
   965 	    foreach(QNetworkConfiguration p, configs) {
       
   966 		qDebug() << p.name() <<":  isvalid->" <<p.isValid() << " type->"<< p.type() << 
       
   967 		    " roaming->" << p.isRoamingAvailable() << "identifier->" << p.identifier() <<
       
   968 		    " purpose->" << p.purpose() << " state->" << p.state();
       
   969 	    }
       
   970 #endif
       
   971 #endif
       
   972 
       
   973 	    QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)config.d.data()->manager;
       
   974             if (!mgr->accessPointConfigurations.contains(result)) {
       
   975 		QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = config.d;
       
   976 		mgr->accessPointConfigurations.insert(result, ptr);
       
   977 
       
   978 		QNetworkConfiguration item;
       
   979 		item.d = ptr;
       
   980 		emit mgr->configurationAdded(item);
       
   981 
       
   982 #ifdef BEARER_MANAGEMENT_DEBUG
       
   983 		//qDebug()<<"New configuration"<<result<<"added to manager in open";
       
   984 #endif
       
   985 
       
   986 	    } else {
       
   987 		QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = mgr->accessPointConfigurations.value(result);
       
   988 		QNetworkConfiguration reference;
       
   989 		reference.d = priv;
       
   990                 copyConfig(config, reference, false);
       
   991                 config = reference;
       
   992                 activeConfig = reference;
       
   993 		mgr->configurationChanged((QNetworkConfigurationPrivate*)(config.d.data()));
       
   994 
       
   995 #ifdef BEARER_MANAGEMENT_DEBUG
       
   996 		//qDebug()<<"Existing configuration"<<result<<"updated in manager in open";
       
   997 #endif
       
   998 	    }
       
   999 	}
       
  1000 
       
  1001 	emit quitPendingWaitsForOpened();
       
  1002 
       
  1003     } else {
       
  1004 #ifdef BEARER_MANAGEMENT_DEBUG
       
  1005 	qDebug() << "connect to"<< iap << "failed, status:" << connect_result.status;
       
  1006 #endif
       
  1007 	updateState(QNetworkSession::Disconnected);
       
  1008 	if (publicConfig.type() == QNetworkConfiguration::UserChoice)
       
  1009 	    cleanupAnyConfiguration();
       
  1010 	emit q->error(QNetworkSession::UnknownSessionError);
       
  1011     }
       
  1012 }
       
  1013 
       
  1014 
       
  1015 void QNetworkSessionPrivate::cleanupAnyConfiguration()
       
  1016 {
       
  1017 #ifdef BEARER_MANAGEMENT_DEBUG
       
  1018     qDebug()<<"Removing configuration created for" << activeConfig.d->id;
       
  1019 #endif
       
  1020     activeConfig = publicConfig;
       
  1021 }
       
  1022 
       
  1023 
       
  1024 void QNetworkSessionPrivate::close()
       
  1025 {
       
  1026     if (serviceConfig.isValid()) {
       
  1027         lastError = QNetworkSession::OperationNotSupportedError;
       
  1028         emit q->error(lastError);
       
  1029     } else if (isOpen) {
       
  1030         opened = false;
       
  1031         isOpen = false;
       
  1032         emit q->closed();
       
  1033     }
       
  1034 }
       
  1035 
       
  1036 
       
  1037 void QNetworkSessionPrivate::stop()
       
  1038 {
       
  1039     if (serviceConfig.isValid()) {
       
  1040         lastError = QNetworkSession::OperationNotSupportedError;
       
  1041         emit q->error(lastError);
       
  1042     } else {
       
  1043         if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
       
  1044             state = QNetworkSession::Closing;
       
  1045             emit q->stateChanged(state);
       
  1046 
       
  1047 	    Maemo::Icd icd;
       
  1048 #ifdef BEARER_MANAGEMENT_DEBUG
       
  1049 	    qDebug() << "stopping session" << publicConfig.identifier();
       
  1050 #endif
       
  1051 	    icd.disconnect(ICD_CONNECTION_FLAG_APPLICATION_EVENT);
       
  1052 	    startTime = QDateTime();
       
  1053 
       
  1054 	    /* Note that the state will go disconnected in
       
  1055 	     * updateStateFromActiveConfig() which gets called after
       
  1056 	     * configurationChanged is emitted (below).
       
  1057 	     */
       
  1058 
       
  1059 	    activeConfig.d->state = QNetworkConfiguration::Discovered;
       
  1060 	    QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)activeConfig.d.data()->manager;
       
  1061 	    mgr->configurationChanged((QNetworkConfigurationPrivate*)activeConfig.d.data());
       
  1062 
       
  1063 	    opened = false;
       
  1064 	    isOpen = false;
       
  1065 
       
  1066         } else {
       
  1067 	    opened = false;
       
  1068 	    isOpen = false;
       
  1069 	    emit q->closed();
       
  1070 	}
       
  1071     }
       
  1072 }
       
  1073 
       
  1074 
       
  1075 void QNetworkSessionPrivate::migrate()
       
  1076 {
       
  1077     qWarning("This platform does not support roaming (%s).", __FUNCTION__);
       
  1078 }
       
  1079 
       
  1080 
       
  1081 void QNetworkSessionPrivate::accept()
       
  1082 {
       
  1083     qWarning("This platform does not support roaming (%s).", __FUNCTION__);
       
  1084 }
       
  1085 
       
  1086 
       
  1087 void QNetworkSessionPrivate::ignore()
       
  1088 {
       
  1089     qWarning("This platform does not support roaming (%s).", __FUNCTION__);
       
  1090 }
       
  1091 
       
  1092 
       
  1093 void QNetworkSessionPrivate::reject()
       
  1094 {
       
  1095     qWarning("This platform does not support roaming (%s).", __FUNCTION__);
       
  1096 }
       
  1097 
       
  1098 
       
  1099 QNetworkInterface QNetworkSessionPrivate::currentInterface() const
       
  1100 {
       
  1101     if (!publicConfig.isValid() || state != QNetworkSession::Connected)
       
  1102         return QNetworkInterface();
       
  1103 
       
  1104     if (currentNetworkInterface.isEmpty())
       
  1105         return QNetworkInterface();
       
  1106 
       
  1107     return QNetworkInterface::interfaceFromName(currentNetworkInterface);
       
  1108 }
       
  1109 
       
  1110 
       
  1111 void QNetworkSessionPrivate::setSessionProperty(const QString& key, const QVariant& value)
       
  1112 {
       
  1113     if (value.isValid()) {
       
  1114 	properties.insert(key, value);
       
  1115 
       
  1116 	if (key == "ConnectInBackground") {
       
  1117 	    bool v = value.toBool();
       
  1118 	    if (v)
       
  1119 		connectFlags = ICD_CONNECTION_FLAG_APPLICATION_EVENT;
       
  1120 	    else
       
  1121 		connectFlags = ICD_CONNECTION_FLAG_USER_EVENT;
       
  1122 	}
       
  1123     } else {
       
  1124 	properties.remove(key);
       
  1125 
       
  1126 	/* Set default value when property is removed */
       
  1127 	if (key == "ConnectInBackground")
       
  1128 	    connectFlags = ICD_CONNECTION_FLAG_USER_EVENT;
       
  1129     }
       
  1130 }
       
  1131 
       
  1132 
       
  1133 QVariant QNetworkSessionPrivate::sessionProperty(const QString& key) const
       
  1134 {
       
  1135     return properties.value(key);
       
  1136 }
       
  1137 
       
  1138 
       
  1139 QString QNetworkSessionPrivate::errorString() const
       
  1140 {
       
  1141     QString errorStr;
       
  1142     switch(q->error()) {
       
  1143     case QNetworkSession::RoamingError:
       
  1144         errorStr = QObject::tr("Roaming error");
       
  1145         break;
       
  1146     case QNetworkSession::SessionAbortedError:
       
  1147         errorStr = QObject::tr("Session aborted by user or system");
       
  1148         break;
       
  1149     default:
       
  1150     case QNetworkSession::UnknownSessionError:
       
  1151         errorStr = QObject::tr("Unidentified Error");
       
  1152         break;
       
  1153     }
       
  1154     return errorStr;
       
  1155 }
       
  1156 
       
  1157 
       
  1158 QNetworkSession::SessionError QNetworkSessionPrivate::error() const
       
  1159 {
       
  1160     return QNetworkSession::UnknownSessionError;
       
  1161 }
       
  1162 
       
  1163 
       
  1164 void QNetworkSessionPrivate::updateProxies(QNetworkSession::State newState)
       
  1165 {
       
  1166     if ((newState == QNetworkSession::Connected) &&
       
  1167 	(newState != currentState))
       
  1168 	updateProxyInformation();
       
  1169     else if ((newState == QNetworkSession::Disconnected) &&
       
  1170 	    (currentState == QNetworkSession::Closing))
       
  1171 	clearProxyInformation();
       
  1172 
       
  1173     currentState = newState;
       
  1174 }
       
  1175 
       
  1176 
       
  1177 void QNetworkSessionPrivate::updateProxyInformation()
       
  1178 {
       
  1179     Maemo::ProxyConf::update();
       
  1180 }
       
  1181 
       
  1182 
       
  1183 void QNetworkSessionPrivate::clearProxyInformation()
       
  1184 {
       
  1185     Maemo::ProxyConf::clear();
       
  1186 }
       
  1187 
       
  1188 
       
  1189 #include "qnetworksession_maemo.moc"
       
  1190 #include "moc_qnetworksession_maemo_p.cpp"
       
  1191 
       
  1192 QTM_END_NAMESPACE