qtmobility/src/bearer/qnetworksession_maemo.cpp
branchRCL_3
changeset 2 5822d84012fb
parent 0 cfcbf08528c4
child 6 eb34711bcc75
equal deleted inserted replaced
0:cfcbf08528c4 2:5822d84012fb
    40 ****************************************************************************/
    40 ****************************************************************************/
    41 
    41 
    42 #include <QHash>
    42 #include <QHash>
    43 
    43 
    44 #include "qnetworksession_maemo_p.h"
    44 #include "qnetworksession_maemo_p.h"
    45 #include <dbus/dbus.h>
       
    46 #include <dbus/dbus-glib-lowlevel.h>
       
    47 
    45 
    48 #include <maemo_icd.h>
    46 #include <maemo_icd.h>
    49 #include <iapconf.h>
    47 #include <iapconf.h>
    50 #include <proxyconf.h>
    48 #include <proxyconf.h>
    51 
    49 
    52 #include <sys/types.h>
       
    53 #include <ifaddrs.h>
    50 #include <ifaddrs.h>
    54 #include <sys/socket.h>
       
    55 #include <netinet/in.h>
    51 #include <netinet/in.h>
    56 #include <arpa/inet.h>
    52 #include <arpa/inet.h>
    57 
    53 
    58 QTM_BEGIN_NAMESPACE
    54 QTM_BEGIN_NAMESPACE
    59 
    55 
    60 static QHash<QString, QVariant> properties;
    56 static QHash<QString, QVariant> properties;
    61 
    57 
    62 static QString get_network_interface();
    58 static QString get_network_interface();
    63 static DBusConnection *dbus_connection;
    59 
    64 static DBusHandlerResult signal_handler(DBusConnection *connection,
    60 void QNetworkSessionPrivate::iapStateChanged(const QString& iapid, uint icd_connection_state)
    65 					DBusMessage *message,
    61 {
    66 					void *user_data);
    62     if ((publicConfig.type() == QNetworkConfiguration::UserChoice) && opened) {
    67 
    63         updateIdentifier(iapid);
    68 #define ICD_DBUS_MATCH		"type='signal'," \
    64     }
    69 				"interface='" ICD_DBUS_INTERFACE "'," \
    65 
    70 				"path='" ICD_DBUS_PATH "'"
    66     if (((publicConfig.type() == QNetworkConfiguration::UserChoice) && (activeConfig.d->id == iapid)) ||
    71 
    67         (publicConfig.d->id == iapid)) {
    72 
    68         switch (icd_connection_state) {
    73 static inline DBusConnection *get_dbus_conn(DBusError *error)
    69         case ICD_STATE_CONNECTING:
    74 {
    70             updateState(QNetworkSession::Connecting);
    75     DBusConnection *conn = dbus_bus_get(DBUS_BUS_SYSTEM, error);
    71             break;
    76 #ifdef BEARER_MANAGEMENT_DEBUG
    72         case ICD_STATE_CONNECTED:
    77     qDebug() << "Listening to bus" << dbus_bus_get_unique_name(conn);
    73             updateState(QNetworkSession::Connected);
    78 #endif
    74             break;
    79 
    75         case ICD_STATE_DISCONNECTING:
    80     return conn;
    76             updateState(QNetworkSession::Closing);
    81 }
    77             break;
    82 
    78         case ICD_STATE_DISCONNECTED:
    83 
    79             updateState(QNetworkSession::Disconnected);
    84 /* Helper class that monitors the Icd status messages and
    80             break;
    85  * can change the IAP status accordingly. This is a singleton.
    81         default:
    86  */
    82             break;
    87 class IcdListener : public QObject
    83         }
    88 {
    84     }
    89     Q_OBJECT
    85 }
    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 
    86 
   297 void QNetworkSessionPrivate::cleanupSession(void)
    87 void QNetworkSessionPrivate::cleanupSession(void)
   298 {
    88 {
   299     icdListener()->cleanupSession(this);
       
   300 
       
   301     QObject::disconnect(q, SIGNAL(stateChanged(QNetworkSession::State)), this, SLOT(updateProxies(QNetworkSession::State)));
    89     QObject::disconnect(q, SIGNAL(stateChanged(QNetworkSession::State)), this, SLOT(updateProxies(QNetworkSession::State)));
   302 }
    90 }
   303 
    91 
   304 
    92 
   305 void QNetworkSessionPrivate::updateState(QNetworkSession::State newState)
    93 void QNetworkSessionPrivate::updateState(QNetworkSession::State newState)
   306 {
    94 {
   307     if( newState != state) {
    95     if (newState != state) {
   308         state = newState;
    96         if (newState == QNetworkSession::Disconnected) {
   309 
    97             if (isOpen) {
   310 	if (state == QNetworkSession::Disconnected) {
    98                 // The Session was aborted by the user or system
       
    99                 lastError = QNetworkSession::SessionAbortedError;
       
   100                 emit q->error(lastError);
       
   101                 emit q->closed();
       
   102             }
       
   103             if (m_stopTimer.isActive()) {
       
   104                 // Session was closed by calling stop()
       
   105                 m_stopTimer.stop();
       
   106             }
   311             isOpen = false;
   107             isOpen = false;
       
   108             opened = false;
   312 	    currentNetworkInterface.clear();
   109 	    currentNetworkInterface.clear();
   313 	    if (publicConfig.type() == QNetworkConfiguration::UserChoice)
   110             if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
   314 		activeConfig.d->state = QNetworkConfiguration::Defined;
   111                 copyConfig(publicConfig, activeConfig);
   315 	    publicConfig.d->state = QNetworkConfiguration::Defined;
   112                 activeConfig.d->state = QNetworkConfiguration::Defined;
   316 
   113             } else {
   317 	} else if (state == QNetworkSession::Connected) {
   114                 if (!activeConfig.isValid()) {
   318             isOpen = true;
   115                     // Active configuration (IAP) was removed from system
       
   116                     // => Connection was disconnected and configuration became
       
   117                     //    invalid
       
   118                     // => Also Session state must be changed to invalid
       
   119                     newState = QNetworkSession::Invalid;
       
   120                 }
       
   121             }
       
   122         } else if (newState == QNetworkSession::Connected) {
       
   123             if (opened) {
       
   124                 isOpen = true;
       
   125             }
   319 	    if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
   126 	    if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
   320 		activeConfig.d->state = QNetworkConfiguration::Active;
   127 		activeConfig.d->state = QNetworkConfiguration::Active;
   321 		activeConfig.d->type = QNetworkConfiguration::InternetAccessPoint;
   128 		activeConfig.d->type = QNetworkConfiguration::InternetAccessPoint;
   322 	    }
   129 	    }
   323 	    publicConfig.d->state = QNetworkConfiguration::Active;
   130 	    publicConfig.d->state = QNetworkConfiguration::Active;
   324 	}
   131 	}
   325 
   132 
   326 	emit q->stateChanged(newState);
   133         if (newState != state) {
   327     }
   134             state = newState;
   328 }
   135             emit q->stateChanged(newState);
   329 
   136         }
   330 
   137     }
   331 void QNetworkSessionPrivate::updateIdentifier(QString &newId)
   138 }
       
   139 
       
   140 
       
   141 void QNetworkSessionPrivate::updateIdentifier(const QString &newId)
   332 {
   142 {
   333     if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
   143     if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
   334 	activeConfig.d->network_attrs |= ICD_NW_ATTR_IAPNAME;
   144 	activeConfig.d->network_attrs |= ICD_NW_ATTR_IAPNAME;
   335 	activeConfig.d->id = newId;
   145 	activeConfig.d->id = newId;
   336     } else {
   146     } else {
   355 
   165 
   356     if (!icd.statistics(stats_results)) {
   166     if (!icd.statistics(stats_results)) {
   357 	return 0;
   167 	return 0;
   358     }
   168     }
   359 
   169 
   360     foreach (Maemo::IcdStatisticsResult res, stats_results) {
   170     foreach (const Maemo::IcdStatisticsResult &res, stats_results) {
   361 	if (res.params.network_attrs & ICD_NW_ATTR_IAPNAME) {
   171 	if (res.params.network_attrs & ICD_NW_ATTR_IAPNAME) {
   362 	    /* network_id is the IAP UUID */
   172 	    /* network_id is the IAP UUID */
   363 	    if (QString(res.params.network_id.data()) == activeConfig.identifier()) {
   173 	    if (QString(res.params.network_id.data()) == activeConfig.identifier()) {
   364 		counter_tx = res.bytes_sent;
   174 		counter_tx = res.bytes_sent;
   365 		counter_rx = res.bytes_received;
   175 		counter_rx = res.bytes_received;
   431 /* This is called by QNetworkSession constructor and it updates the current
   241 /* This is called by QNetworkSession constructor and it updates the current
   432  * state of the configuration.
   242  * state of the configuration.
   433  */
   243  */
   434 void QNetworkSessionPrivate::syncStateWithInterface()
   244 void QNetworkSessionPrivate::syncStateWithInterface()
   435 {
   245 {
   436     /* Start to listen Icd status messages. */
       
   437     icdListener()->setup(this);
       
   438 
       
   439     /* Initially we are not active although the configuration might be in
   246     /* Initially we are not active although the configuration might be in
   440      * connected state.
   247      * connected state.
   441      */
   248      */
   442     isOpen = false;
   249     isOpen = false;
   443     opened = false;
   250     opened = false;
   445     QObject::connect(&manager, SIGNAL(updateCompleted()), this, SLOT(networkConfigurationsChanged()));
   252     QObject::connect(&manager, SIGNAL(updateCompleted()), this, SLOT(networkConfigurationsChanged()));
   446 
   253 
   447     if (publicConfig.d.data()) {
   254     if (publicConfig.d.data()) {
   448 	QNetworkConfigurationManagerPrivate* mgr = (QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager;
   255 	QNetworkConfigurationManagerPrivate* mgr = (QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager;
   449 	if (mgr) {
   256 	if (mgr) {
   450 	    QObject::connect(mgr, SIGNAL(configurationChanged(QNetworkConfiguration)),
   257             connect(mgr, SIGNAL(iapStateChanged(const QString&, uint)),
   451 			    this, SLOT(configurationChanged(QNetworkConfiguration)));
   258                     this, SLOT(iapStateChanged(const QString&, uint)));
   452 	} else {
   259 	} 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?";
   260             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?";
   454 	    state = QNetworkSession::Invalid;
   261 	    state = QNetworkSession::Invalid;
   455 	    lastError = QNetworkSession::UnknownSessionError;
   262 	    lastError = QNetworkSession::UnknownSessionError;
   456 	    return;
   263 	    return;
   457 	}
   264 	}
   458     }
   265     }
   462     state = QNetworkSession::Invalid;
   269     state = QNetworkSession::Invalid;
   463     lastError = QNetworkSession::UnknownSessionError;
   270     lastError = QNetworkSession::UnknownSessionError;
   464 
   271 
   465     switch (publicConfig.type()) {
   272     switch (publicConfig.type()) {
   466     case QNetworkConfiguration::InternetAccessPoint:
   273     case QNetworkConfiguration::InternetAccessPoint:
   467 	activeConfig = publicConfig;
   274         activeConfig = publicConfig;
   468         break;
   275         break;
   469     case QNetworkConfiguration::ServiceNetwork:
   276     case QNetworkConfiguration::ServiceNetwork:
   470 	serviceConfig = publicConfig;
   277         serviceConfig = publicConfig;
   471 	break;
   278 	break;
   472     case QNetworkConfiguration::UserChoice:
   279     case QNetworkConfiguration::UserChoice:
   473 	// active config will contain correct data after open() has succeeded
   280 	// active config will contain correct data after open() has succeeded
   474 	copyConfig(publicConfig, activeConfig);
   281         copyConfig(publicConfig, activeConfig);
   475 
   282 
   476 	/* We create new configuration that holds the actual configuration
   283 	/* We create new configuration that holds the actual configuration
   477 	 * returned by icd. This way publicConfig still contains the
   284 	 * returned by icd. This way publicConfig still contains the
   478 	 * original user specified configuration.
   285 	 * original user specified configuration.
   479 	 *
   286 	 *
   503 
   310 
   504     /* Update the active config from first connection, this is ok as icd
   311     /* Update the active config from first connection, this is ok as icd
   505      * supports only one connection anyway.
   312      * supports only one connection anyway.
   506      */
   313      */
   507     if (icd.state(state_results) && !state_results.isEmpty()) {
   314     if (icd.state(state_results) && !state_results.isEmpty()) {
   508 
       
   509 	/* If we did not get full state back, then we are not
   315 	/* If we did not get full state back, then we are not
   510 	 * connected and can skip the next part.
   316 	 * connected and can skip the next part.
   511 	 */
   317 	 */
   512 	if (!(state_results.first().params.network_attrs == 0 &&
   318 	if (!(state_results.first().params.network_attrs == 0 &&
   513 		state_results.first().params.network_id.isEmpty())) {
   319 		state_results.first().params.network_id.isEmpty())) {
   516 	     * that tell the icd is actually connected to another IAP,
   322 	     * that tell the icd is actually connected to another IAP,
   517 	     * then do not update current state etc.
   323 	     * then do not update current state etc.
   518 	     */
   324 	     */
   519 	    if (publicConfig.type() == QNetworkConfiguration::UserChoice ||
   325 	    if (publicConfig.type() == QNetworkConfiguration::UserChoice ||
   520 		    publicConfig.d->id == state_results.first().params.network_id) {
   326 		    publicConfig.d->id == state_results.first().params.network_id) {
   521 
       
   522 		switch (state_results.first().state) {
   327 		switch (state_results.first().state) {
   523 		case ICD_STATE_DISCONNECTED:
   328 		case ICD_STATE_DISCONNECTED:
   524 		    state = QNetworkSession::Disconnected;
   329                     state = QNetworkSession::Disconnected;
   525 		    if (activeConfig.d.data())
   330 		    if (activeConfig.d.data())
   526 			activeConfig.d->isValid = true;
   331 			activeConfig.d->isValid = true;
   527 		    break;
   332 		    break;
   528 		case ICD_STATE_CONNECTING:
   333 		case ICD_STATE_CONNECTING:
   529 		    state = QNetworkSession::Connecting;
   334                     state = QNetworkSession::Connecting;
   530 		    if (activeConfig.d.data())
   335 		    if (activeConfig.d.data())
   531 			activeConfig.d->isValid = true;
   336 			activeConfig.d->isValid = true;
   532 		    break;
   337 		    break;
   533 		case ICD_STATE_CONNECTED:
   338 		case ICD_STATE_CONNECTED:
   534 		    {
   339 		    {
   535 			if (!state_results.first().error.isEmpty())
   340                         if (!state_results.first().error.isEmpty())
   536 			    break;
   341 			    break;
   537                         
   342 
   538                         const QString id = state_results.first().params.network_id;
   343                         const QString id = state_results.first().params.network_id;
   539 
   344 
   540 			QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)activeConfig.d.data()->manager;
   345                         QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager;
   541 			if (mgr->accessPointConfigurations.contains(id)) {
   346 			if (mgr->accessPointConfigurations.contains(id)) {
   542                             //we don't want the copied data if the config is already known by the manager
   347                             //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
   348                             //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);
   349                             QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = mgr->accessPointConfigurations.value(id);
   545                             activeConfig.d = priv;
   350                             activeConfig.d = priv;
   546                         }
   351                         }
   547 
   352 
   548 
       
   549 			state = QNetworkSession::Connected;
   353 			state = QNetworkSession::Connected;
   550 			activeConfig.d->network_id = state_results.first().params.network_id;
   354                         activeConfig.d->network_id = state_results.first().params.network_id;
   551 			activeConfig.d->id = activeConfig.d->network_id;
   355                         activeConfig.d->id = activeConfig.d->network_id;
   552 			activeConfig.d->network_attrs = state_results.first().params.network_attrs;
   356                         activeConfig.d->network_attrs = state_results.first().params.network_attrs;
   553 			activeConfig.d->iap_type = state_results.first().params.network_type;
   357                         activeConfig.d->iap_type = state_results.first().params.network_type;
   554 			activeConfig.d->service_type = state_results.first().params.service_type;
   358                         activeConfig.d->service_type = state_results.first().params.service_type;
   555 			activeConfig.d->service_id = state_results.first().params.service_id;
   359                         activeConfig.d->service_id = state_results.first().params.service_id;
   556 			activeConfig.d->service_attrs = state_results.first().params.service_attrs;
   360                         activeConfig.d->service_attrs = state_results.first().params.service_attrs;
   557 			activeConfig.d->type = QNetworkConfiguration::InternetAccessPoint;
   361                         activeConfig.d->type = QNetworkConfiguration::InternetAccessPoint;
   558 			activeConfig.d->state = QNetworkConfiguration::Active;
   362                         activeConfig.d->state = QNetworkConfiguration::Active;
   559 			activeConfig.d->isValid = true;
   363                         activeConfig.d->isValid = true;
   560 			currentNetworkInterface = get_network_interface();
   364                         currentNetworkInterface = get_network_interface();
   561 
   365 
   562 			Maemo::IAPConf iap_name(activeConfig.d->id);
   366 			Maemo::IAPConf iap_name(activeConfig.d->id);
   563 			QString name_value = iap_name.value("name").toString();
   367 			QString name_value = iap_name.value("name").toString();
   564 			if (!name_value.isEmpty())
   368 			if (!name_value.isEmpty())
   565 			    activeConfig.d->name = name_value;
   369 			    activeConfig.d->name = name_value;
   566 			else
   370 			else
   567 			    activeConfig.d->name = activeConfig.d->id;
   371 			    activeConfig.d->name = activeConfig.d->id;
   568 
   372 
   569 
       
   570 			// Add the new active configuration to manager or update the old config
   373 			// Add the new active configuration to manager or update the old config
   571 			mgr = (QNetworkConfigurationManagerPrivate*)activeConfig.d.data()->manager;
   374 			mgr = (QNetworkConfigurationManagerPrivate*)activeConfig.d.data()->manager;
   572 			if (!(mgr->accessPointConfigurations.contains(activeConfig.d->id))) {
   375 			if (!(mgr->accessPointConfigurations.contains(activeConfig.d->id))) {
   573 			    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = activeConfig.d;
   376 			    QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = activeConfig.d;
   574 			    mgr->accessPointConfigurations.insert(activeConfig.d->id, ptr);
   377 			    mgr->accessPointConfigurations.insert(activeConfig.d->id, ptr);
   579 
   382 
   580 #ifdef BEARER_MANAGEMENT_DEBUG
   383 #ifdef BEARER_MANAGEMENT_DEBUG
   581 			    //qDebug()<<"New configuration"<<activeConfig.d->id<<"added to manager in sync";
   384 			    //qDebug()<<"New configuration"<<activeConfig.d->id<<"added to manager in sync";
   582 #endif
   385 #endif
   583 
   386 
   584 			} else {
   387                         }
   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 		    }
   388 		    }
   592 		    break;
   389 		    break;
   593 
   390 
   594 		case ICD_STATE_DISCONNECTING:
   391 		case ICD_STATE_DISCONNECTING:
   595 		    state = QNetworkSession::Closing;
   392                     state = QNetworkSession::Closing;
   596 		    if (activeConfig.d.data())
   393 		    if (activeConfig.d.data())
   597 			activeConfig.d->isValid = true;
   394 			activeConfig.d->isValid = true;
   598 		    break;
   395 		    break;
   599 		default:
   396 		default:
   600 		    break;
   397                     break;
   601 		}
   398 		}
   602 	    }
   399 	    }
   603 	} else {
   400 	} else {
   604 #ifdef BEARER_MANAGEMENT_DEBUG
   401 #ifdef BEARER_MANAGEMENT_DEBUG
   605 	    qDebug() << "status_req tells icd is not connected";
   402 	    qDebug() << "status_req tells icd is not connected";
   684         state = QNetworkSession::Disconnected;
   481         state = QNetworkSession::Disconnected;
   685     } else if ((activeConfig.state() & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
   482     } else if ((activeConfig.state() & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
   686         state = QNetworkSession::NotAvailable;
   483         state = QNetworkSession::NotAvailable;
   687     } else if ((activeConfig.state() & QNetworkConfiguration::Undefined) == QNetworkConfiguration::Undefined) {
   484     } else if ((activeConfig.state() & QNetworkConfiguration::Undefined) == QNetworkConfiguration::Undefined) {
   688         state = QNetworkSession::NotAvailable;
   485         state = QNetworkSession::NotAvailable;
   689 	clearConfiguration(activeConfig);
       
   690     }
   486     }
   691 
   487 
   692     bool oldActive = isOpen;
   488     bool oldActive = isOpen;
   693     isOpen = newActive;
   489     isOpen = newActive;
   694 
   490 
   699         emit q->closed();
   495         emit q->closed();
   700 
   496 
   701     if (oldState != state) {
   497     if (oldState != state) {
   702         emit q->stateChanged(state);
   498         emit q->stateChanged(state);
   703 
   499 
   704 	if (state == QNetworkSession::Disconnected) {
   500         if (state == QNetworkSession::Disconnected && oldActive) {
   705 #ifdef BEARER_MANAGEMENT_DEBUG
   501 #ifdef BEARER_MANAGEMENT_DEBUG
   706 	    //qDebug()<<"session aborted error emitted for"<<activeConfig.identifier();
   502 	    //qDebug()<<"session aborted error emitted for"<<activeConfig.identifier();
   707 #endif
   503 #endif
   708 	    lastError = QNetworkSession::SessionAbortedError;
   504 	    lastError = QNetworkSession::SessionAbortedError;
   709 	    emit q->error(lastError);
   505 	    emit q->error(lastError);
   712 
   508 
   713 #ifdef BEARER_MANAGEMENT_DEBUG
   509 #ifdef BEARER_MANAGEMENT_DEBUG
   714     //qDebug()<<"oldState ="<<oldState<<" state ="<<state<<" oldActive ="<<oldActive<<" newActive ="<<newActive<<" opened ="<<opened;
   510     //qDebug()<<"oldState ="<<oldState<<" state ="<<state<<" oldActive ="<<oldActive<<" newActive ="<<newActive<<" opened ="<<opened;
   715 #endif
   511 #endif
   716 }
   512 }
   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 
   513 
   728 static QString get_network_interface()
   514 static QString get_network_interface()
   729 {
   515 {
   730     Maemo::Icd icd;
   516     Maemo::Icd icd;
   731     QList<Maemo::IcdAddressInfoResult> addr_results;
   517     QList<Maemo::IcdAddressInfoResult> addr_results;
   759 #endif
   545 #endif
   760 	return iface;
   546 	return iface;
   761     }
   547     }
   762 
   548 
   763     for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
   549     for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
   764 	family = ifa->ifa_addr->sa_family;
   550         if (ifa->ifa_addr) {
   765 	if (family != AF_INET) {
   551             family = ifa->ifa_addr->sa_family;
   766 	    continue; /* Currently only IPv4 is supported by icd dbus interface */
   552             if (family != AF_INET) {
   767 	}
   553                 continue; /* Currently only IPv4 is supported by icd dbus interface */
   768 	if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == addr.s_addr) {
   554             }
   769 	    iface = QString(ifa->ifa_name);
   555             if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == addr.s_addr) {
   770 	    break;
   556                 iface = QString(ifa->ifa_name);
   771 	}
   557                 break;
       
   558             }
       
   559         }
   772     }
   560     }
   773 
   561 
   774     freeifaddrs(ifaddr);
   562     freeifaddrs(ifaddr);
   775     return iface;
   563     return iface;
   776 }
   564 }
   777 
   565 
   778 
   566 
   779 void QNetworkSessionPrivate::open()
   567 void QNetworkSessionPrivate::open()
   780 {
   568 {
       
   569     if (m_stopTimer.isActive()) {
       
   570         m_stopTimer.stop();
       
   571     }
       
   572     if (!publicConfig.isValid()) {
       
   573         lastError = QNetworkSession::InvalidConfigurationError;
       
   574         emit q->error(lastError);
       
   575         return;
       
   576     }
   781     if (serviceConfig.isValid()) {
   577     if (serviceConfig.isValid()) {
   782         lastError = QNetworkSession::OperationNotSupportedError;
   578         lastError = QNetworkSession::OperationNotSupportedError;
   783         emit q->error(lastError);
   579         emit q->error(lastError);
   784     } else if (!isOpen) {
   580     } else if (!isOpen) {
   785 
       
   786 	if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
   581 	if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
   787 	    /* Caller is trying to connect to default IAP.
   582 	    /* Caller is trying to connect to default IAP.
   788 	     * At this time we will not know the IAP details so we just
   583 	     * At this time we will not know the IAP details so we just
   789 	     * connect and update the active config when the IAP is
   584 	     * connect and update the active config when the IAP is
   790 	     * connected.
   585 	     * connected.
   891 	    qDebug() << "connect to"<< iap << "failed, result is empty";
   686 	    qDebug() << "connect to"<< iap << "failed, result is empty";
   892 #endif
   687 #endif
   893 	    updateState(QNetworkSession::Disconnected);
   688 	    updateState(QNetworkSession::Disconnected);
   894 	    emit q->error(QNetworkSession::InvalidConfigurationError);
   689 	    emit q->error(QNetworkSession::InvalidConfigurationError);
   895 	    if (publicConfig.type() == QNetworkConfiguration::UserChoice)
   690 	    if (publicConfig.type() == QNetworkConfiguration::UserChoice)
   896 		cleanupAnyConfiguration();
   691                 copyConfig(publicConfig, activeConfig);
   897 	    return;
   692 	    return;
   898 	}
   693 	}
   899 
   694 
   900 	/* If the user tried to connect to some specific connection (foo)
   695 	/* If the user tried to connect to some specific connection (foo)
   901 	 * and we were already connected to some other connection (bar),
   696 	 * and we were already connected to some other connection (bar),
   967 		    " roaming->" << p.isRoamingAvailable() << "identifier->" << p.identifier() <<
   762 		    " roaming->" << p.isRoamingAvailable() << "identifier->" << p.identifier() <<
   968 		    " purpose->" << p.purpose() << " state->" << p.state();
   763 		    " purpose->" << p.purpose() << " state->" << p.state();
   969 	    }
   764 	    }
   970 #endif
   765 #endif
   971 #endif
   766 #endif
   972 
   767             QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager;
   973 	    QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)config.d.data()->manager;
       
   974             if (!mgr->accessPointConfigurations.contains(result)) {
   768             if (!mgr->accessPointConfigurations.contains(result)) {
   975 		QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = config.d;
   769 		QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = config.d;
   976 		mgr->accessPointConfigurations.insert(result, ptr);
   770 		mgr->accessPointConfigurations.insert(result, ptr);
   977 
   771 
   978 		QNetworkConfiguration item;
   772 		QNetworkConfiguration item;
   982 #ifdef BEARER_MANAGEMENT_DEBUG
   776 #ifdef BEARER_MANAGEMENT_DEBUG
   983 		//qDebug()<<"New configuration"<<result<<"added to manager in open";
   777 		//qDebug()<<"New configuration"<<result<<"added to manager in open";
   984 #endif
   778 #endif
   985 
   779 
   986 	    } else {
   780 	    } else {
   987 		QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = mgr->accessPointConfigurations.value(result);
   781                 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = mgr->accessPointConfigurations.value(result);
   988 		QNetworkConfiguration reference;
   782 		QNetworkConfiguration reference;
   989 		reference.d = priv;
   783 		reference.d = priv;
   990                 copyConfig(config, reference, false);
   784                 copyConfig(config, reference, false);
       
   785                 reference.d.data()->id = result; // Note: Id was not copied in copyConfig() function
   991                 config = reference;
   786                 config = reference;
   992                 activeConfig = reference;
   787                 activeConfig = reference;
   993 		mgr->configurationChanged((QNetworkConfigurationPrivate*)(config.d.data()));
       
   994 
   788 
   995 #ifdef BEARER_MANAGEMENT_DEBUG
   789 #ifdef BEARER_MANAGEMENT_DEBUG
   996 		//qDebug()<<"Existing configuration"<<result<<"updated in manager in open";
   790 		//qDebug()<<"Existing configuration"<<result<<"updated in manager in open";
   997 #endif
   791 #endif
   998 	    }
   792 	    }
  1004 #ifdef BEARER_MANAGEMENT_DEBUG
   798 #ifdef BEARER_MANAGEMENT_DEBUG
  1005 	qDebug() << "connect to"<< iap << "failed, status:" << connect_result.status;
   799 	qDebug() << "connect to"<< iap << "failed, status:" << connect_result.status;
  1006 #endif
   800 #endif
  1007 	updateState(QNetworkSession::Disconnected);
   801 	updateState(QNetworkSession::Disconnected);
  1008 	if (publicConfig.type() == QNetworkConfiguration::UserChoice)
   802 	if (publicConfig.type() == QNetworkConfiguration::UserChoice)
  1009 	    cleanupAnyConfiguration();
   803             copyConfig(publicConfig, activeConfig);
  1010 	emit q->error(QNetworkSession::UnknownSessionError);
   804 	emit q->error(QNetworkSession::UnknownSessionError);
  1011     }
   805     }
  1012 }
   806 }
  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 
   807 
  1024 void QNetworkSessionPrivate::close()
   808 void QNetworkSessionPrivate::close()
  1025 {
   809 {
  1026     if (serviceConfig.isValid()) {
   810     if (serviceConfig.isValid()) {
  1027         lastError = QNetworkSession::OperationNotSupportedError;
   811         lastError = QNetworkSession::OperationNotSupportedError;
  1039     if (serviceConfig.isValid()) {
   823     if (serviceConfig.isValid()) {
  1040         lastError = QNetworkSession::OperationNotSupportedError;
   824         lastError = QNetworkSession::OperationNotSupportedError;
  1041         emit q->error(lastError);
   825         emit q->error(lastError);
  1042     } else {
   826     } else {
  1043         if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
   827         if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
  1044             state = QNetworkSession::Closing;
   828             if (!m_stopTimer.isActive()) {
  1045             emit q->stateChanged(state);
   829                 Maemo::Icd icd;
  1046 
   830 #ifdef BEARER_MANAGEMENT_DEBUG
  1047 	    Maemo::Icd icd;
   831                 qDebug() << "stopping session" << publicConfig.identifier();
  1048 #ifdef BEARER_MANAGEMENT_DEBUG
   832 #endif
  1049 	    qDebug() << "stopping session" << publicConfig.identifier();
   833                 state = QNetworkSession::Closing;
  1050 #endif
   834                 emit q->stateChanged(state);
  1051 	    icd.disconnect(ICD_CONNECTION_FLAG_APPLICATION_EVENT);
   835 
  1052 	    startTime = QDateTime();
   836                 opened = false;
  1053 
   837                 isOpen = false;
  1054 	    /* Note that the state will go disconnected in
   838 
  1055 	     * updateStateFromActiveConfig() which gets called after
   839                 icd.disconnect(ICD_CONNECTION_FLAG_APPLICATION_EVENT);
  1056 	     * configurationChanged is emitted (below).
   840                 startTime = QDateTime();
  1057 	     */
   841 
  1058 
   842                 /* Note: Session state will change to disconnected
  1059 	    activeConfig.d->state = QNetworkConfiguration::Discovered;
   843                  *       as soon as QNetworkConfigurationManager sends
  1060 	    QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)activeConfig.d.data()->manager;
   844                  *       corresponding iapStateChanged signal.
  1061 	    mgr->configurationChanged((QNetworkConfigurationPrivate*)activeConfig.d.data());
   845                  */
  1062 
   846 
  1063 	    opened = false;
   847                 // Make sure that this Session will send closed signal
  1064 	    isOpen = false;
   848                 // even though ICD connection will not ever get closed
  1065 
   849                 m_stopTimer.start(ICD_SHORT_CONNECT_TIMEOUT); // 10 seconds wait
       
   850             }
  1066         } else {
   851         } else {
  1067 	    opened = false;
   852 	    opened = false;
  1068 	    isOpen = false;
   853 	    isOpen = false;
  1069 	    emit q->closed();
   854 	    emit q->closed();
  1070 	}
   855 	}
  1071     }
   856     }
  1072 }
   857 }
  1073 
   858 
       
   859 void QNetworkSessionPrivate::finishStopBySendingClosedSignal()
       
   860 {
       
   861     if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
       
   862         state = QNetworkSession::Connected;
       
   863         emit q->stateChanged(state);
       
   864     }
       
   865     emit q->closed();
       
   866 }
  1074 
   867 
  1075 void QNetworkSessionPrivate::migrate()
   868 void QNetworkSessionPrivate::migrate()
  1076 {
   869 {
  1077     qWarning("This platform does not support roaming (%s).", __FUNCTION__);
   870     qWarning("This platform does not support roaming (%s).", __FUNCTION__);
  1078 }
   871 }
  1184 {
   977 {
  1185     Maemo::ProxyConf::clear();
   978     Maemo::ProxyConf::clear();
  1186 }
   979 }
  1187 
   980 
  1188 
   981 
  1189 #include "qnetworksession_maemo.moc"
       
  1190 #include "moc_qnetworksession_maemo_p.cpp"
   982 #include "moc_qnetworksession_maemo_p.cpp"
  1191 
   983 
  1192 QTM_END_NAMESPACE
   984 QTM_END_NAMESPACE