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 |
|
54 |
|
55 QDBusArgument &operator<<(QDBusArgument &argument, |
|
56 const QtMobility::ICd2DetailsDBusStruct &icd2) |
|
57 { |
|
58 argument.beginStructure(); |
|
59 argument << icd2.serviceType; |
|
60 argument << icd2.serviceAttributes; |
|
61 argument << icd2.setviceId; |
|
62 argument << icd2.networkType; |
|
63 argument << icd2.networkAttributes; |
|
64 argument << icd2.networkId; |
|
65 argument.endStructure(); |
|
66 return argument; |
|
67 } |
|
68 |
|
69 const QDBusArgument &operator>>(const QDBusArgument &argument, |
|
70 QtMobility::ICd2DetailsDBusStruct &icd2) |
|
71 { |
|
72 argument.beginStructure(); |
|
73 argument >> icd2.serviceType; |
|
74 argument >> icd2.serviceAttributes; |
|
75 argument >> icd2.setviceId; |
|
76 argument >> icd2.networkType; |
|
77 argument >> icd2.networkAttributes; |
|
78 argument >> icd2.networkId; |
|
79 argument.endStructure(); |
|
80 return argument; |
|
81 } |
|
82 |
|
83 const QDBusArgument &operator>>(const QDBusArgument &argument, |
|
84 QtMobility::ICd2DetailsList &detailsList) |
|
85 { |
|
86 argument.beginArray(); |
|
87 detailsList.clear(); |
|
88 |
|
89 while (!argument.atEnd()) { |
|
90 QtMobility::ICd2DetailsDBusStruct element; |
|
91 argument >> element; |
|
92 detailsList.append(element); |
|
93 } |
|
94 |
|
95 argument.endArray(); |
|
96 return argument; |
|
97 } |
|
98 |
|
99 QDBusArgument &operator<<(QDBusArgument &argument, |
|
100 const QtMobility::ICd2DetailsList &detailsList) |
|
101 { |
|
102 argument.beginArray(qMetaTypeId<QtMobility::ICd2DetailsDBusStruct>()); |
|
103 for (int i = 0; i < detailsList.count(); ++i) |
|
104 argument << detailsList[i]; |
|
105 argument.endArray(); |
|
106 return argument; |
|
107 } |
|
108 |
58 QTM_BEGIN_NAMESPACE |
109 QTM_BEGIN_NAMESPACE |
59 |
110 |
60 static QHash<QString, QVariant> properties; |
111 static QHash<QString, QVariant> properties; |
61 |
112 |
62 static QString get_network_interface(); |
113 static QString get_network_interface(); |
63 static DBusConnection *dbus_connection; |
114 |
64 static DBusHandlerResult signal_handler(DBusConnection *connection, |
115 void QNetworkSessionPrivate::iapStateChanged(const QString& iapid, uint icd_connection_state) |
65 DBusMessage *message, |
116 { |
66 void *user_data); |
117 if ((publicConfig.type() == QNetworkConfiguration::UserChoice) && opened) { |
67 |
118 updateIdentifier(iapid); |
68 #define ICD_DBUS_MATCH "type='signal'," \ |
119 } |
69 "interface='" ICD_DBUS_INTERFACE "'," \ |
120 |
70 "path='" ICD_DBUS_PATH "'" |
121 if (((publicConfig.type() == QNetworkConfiguration::UserChoice) && (activeConfig.d->id == iapid)) || |
71 |
122 (publicConfig.d->id == iapid)) { |
72 |
123 switch (icd_connection_state) { |
73 static inline DBusConnection *get_dbus_conn(DBusError *error) |
124 case ICD_STATE_CONNECTING: |
74 { |
125 updateState(QNetworkSession::Connecting); |
75 DBusConnection *conn = dbus_bus_get(DBUS_BUS_SYSTEM, error); |
126 break; |
76 #ifdef BEARER_MANAGEMENT_DEBUG |
127 case ICD_STATE_CONNECTED: |
77 qDebug() << "Listening to bus" << dbus_bus_get_unique_name(conn); |
128 updateState(QNetworkSession::Connected); |
78 #endif |
129 break; |
79 |
130 case ICD_STATE_DISCONNECTING: |
80 return conn; |
131 updateState(QNetworkSession::Closing); |
81 } |
132 break; |
82 |
133 case ICD_STATE_DISCONNECTED: |
83 |
134 updateState(QNetworkSession::Disconnected); |
84 /* Helper class that monitors the Icd status messages and |
135 break; |
85 * can change the IAP status accordingly. This is a singleton. |
136 default: |
86 */ |
137 break; |
87 class IcdListener : public QObject |
138 } |
88 { |
139 } |
89 Q_OBJECT |
140 } |
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 |
141 |
297 void QNetworkSessionPrivate::cleanupSession(void) |
142 void QNetworkSessionPrivate::cleanupSession(void) |
298 { |
143 { |
299 icdListener()->cleanupSession(this); |
|
300 |
|
301 QObject::disconnect(q, SIGNAL(stateChanged(QNetworkSession::State)), this, SLOT(updateProxies(QNetworkSession::State))); |
144 QObject::disconnect(q, SIGNAL(stateChanged(QNetworkSession::State)), this, SLOT(updateProxies(QNetworkSession::State))); |
302 } |
145 } |
303 |
146 |
304 |
147 |
305 void QNetworkSessionPrivate::updateState(QNetworkSession::State newState) |
148 void QNetworkSessionPrivate::updateState(QNetworkSession::State newState) |
306 { |
149 { |
307 if( newState != state) { |
150 if (newState != state) { |
308 state = newState; |
151 if (newState == QNetworkSession::Disconnected) { |
309 |
152 if (isOpen) { |
310 if (state == QNetworkSession::Disconnected) { |
153 // The Session was aborted by the user or system |
|
154 lastError = QNetworkSession::SessionAbortedError; |
|
155 emit q->error(lastError); |
|
156 emit q->closed(); |
|
157 } |
|
158 if (m_stopTimer.isActive()) { |
|
159 // Session was closed by calling stop() |
|
160 m_stopTimer.stop(); |
|
161 } |
311 isOpen = false; |
162 isOpen = false; |
|
163 opened = false; |
312 currentNetworkInterface.clear(); |
164 currentNetworkInterface.clear(); |
313 if (publicConfig.type() == QNetworkConfiguration::UserChoice) |
165 if (publicConfig.type() == QNetworkConfiguration::UserChoice) { |
314 activeConfig.d->state = QNetworkConfiguration::Defined; |
166 copyConfig(publicConfig, activeConfig); |
315 publicConfig.d->state = QNetworkConfiguration::Defined; |
167 activeConfig.d->state = QNetworkConfiguration::Defined; |
316 |
168 } else { |
317 } else if (state == QNetworkSession::Connected) { |
169 if (!activeConfig.isValid()) { |
318 isOpen = true; |
170 // Active configuration (IAP) was removed from system |
|
171 // => Connection was disconnected and configuration became |
|
172 // invalid |
|
173 // => Also Session state must be changed to invalid |
|
174 newState = QNetworkSession::Invalid; |
|
175 } |
|
176 } |
|
177 } else if (newState == QNetworkSession::Connected) { |
|
178 if (opened) { |
|
179 isOpen = true; |
|
180 } |
319 if (publicConfig.type() == QNetworkConfiguration::UserChoice) { |
181 if (publicConfig.type() == QNetworkConfiguration::UserChoice) { |
320 activeConfig.d->state = QNetworkConfiguration::Active; |
182 activeConfig.d->state = QNetworkConfiguration::Active; |
321 activeConfig.d->type = QNetworkConfiguration::InternetAccessPoint; |
183 activeConfig.d->type = QNetworkConfiguration::InternetAccessPoint; |
322 } |
184 } |
323 publicConfig.d->state = QNetworkConfiguration::Active; |
185 publicConfig.d->state = QNetworkConfiguration::Active; |
324 } |
186 } |
325 |
187 |
326 emit q->stateChanged(newState); |
188 if (newState != state) { |
327 } |
189 state = newState; |
328 } |
190 emit q->stateChanged(newState); |
329 |
191 } |
330 |
192 } |
331 void QNetworkSessionPrivate::updateIdentifier(QString &newId) |
193 } |
|
194 |
|
195 |
|
196 void QNetworkSessionPrivate::updateIdentifier(const QString &newId) |
332 { |
197 { |
333 if (publicConfig.type() == QNetworkConfiguration::UserChoice) { |
198 if (publicConfig.type() == QNetworkConfiguration::UserChoice) { |
334 activeConfig.d->network_attrs |= ICD_NW_ATTR_IAPNAME; |
199 activeConfig.d->network_attrs |= ICD_NW_ATTR_IAPNAME; |
335 activeConfig.d->id = newId; |
200 activeConfig.d->id = newId; |
336 } else { |
201 } else { |
516 * that tell the icd is actually connected to another IAP, |
377 * that tell the icd is actually connected to another IAP, |
517 * then do not update current state etc. |
378 * then do not update current state etc. |
518 */ |
379 */ |
519 if (publicConfig.type() == QNetworkConfiguration::UserChoice || |
380 if (publicConfig.type() == QNetworkConfiguration::UserChoice || |
520 publicConfig.d->id == state_results.first().params.network_id) { |
381 publicConfig.d->id == state_results.first().params.network_id) { |
521 |
|
522 switch (state_results.first().state) { |
382 switch (state_results.first().state) { |
523 case ICD_STATE_DISCONNECTED: |
383 case ICD_STATE_DISCONNECTED: |
524 state = QNetworkSession::Disconnected; |
384 state = QNetworkSession::Disconnected; |
525 if (activeConfig.d.data()) |
385 if (activeConfig.d.data()) |
526 activeConfig.d->isValid = true; |
386 activeConfig.d->isValid = true; |
527 break; |
387 break; |
528 case ICD_STATE_CONNECTING: |
388 case ICD_STATE_CONNECTING: |
529 state = QNetworkSession::Connecting; |
389 state = QNetworkSession::Connecting; |
530 if (activeConfig.d.data()) |
390 if (activeConfig.d.data()) |
531 activeConfig.d->isValid = true; |
391 activeConfig.d->isValid = true; |
532 break; |
392 break; |
533 case ICD_STATE_CONNECTED: |
393 case ICD_STATE_CONNECTED: |
534 { |
394 { |
535 if (!state_results.first().error.isEmpty()) |
395 if (!state_results.first().error.isEmpty()) |
536 break; |
396 break; |
537 |
397 |
538 const QString id = state_results.first().params.network_id; |
398 const QString id = state_results.first().params.network_id; |
539 |
399 |
540 QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)activeConfig.d.data()->manager; |
400 QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager; |
541 if (mgr->accessPointConfigurations.contains(id)) { |
401 if (mgr->accessPointConfigurations.contains(id)) { |
542 //we don't want the copied data if the config is already known by the manager |
402 //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 |
403 //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); |
404 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = mgr->accessPointConfigurations.value(id); |
545 activeConfig.d = priv; |
405 activeConfig.d = priv; |
546 } |
406 } |
547 |
407 |
548 |
|
549 state = QNetworkSession::Connected; |
408 state = QNetworkSession::Connected; |
550 activeConfig.d->network_id = state_results.first().params.network_id; |
409 activeConfig.d->network_id = state_results.first().params.network_id; |
551 activeConfig.d->id = activeConfig.d->network_id; |
410 activeConfig.d->id = activeConfig.d->network_id; |
552 activeConfig.d->network_attrs = state_results.first().params.network_attrs; |
411 activeConfig.d->network_attrs = state_results.first().params.network_attrs; |
553 activeConfig.d->iap_type = state_results.first().params.network_type; |
412 activeConfig.d->iap_type = state_results.first().params.network_type; |
554 activeConfig.d->service_type = state_results.first().params.service_type; |
413 activeConfig.d->service_type = state_results.first().params.service_type; |
555 activeConfig.d->service_id = state_results.first().params.service_id; |
414 activeConfig.d->service_id = state_results.first().params.service_id; |
556 activeConfig.d->service_attrs = state_results.first().params.service_attrs; |
415 activeConfig.d->service_attrs = state_results.first().params.service_attrs; |
557 activeConfig.d->type = QNetworkConfiguration::InternetAccessPoint; |
416 activeConfig.d->type = QNetworkConfiguration::InternetAccessPoint; |
558 activeConfig.d->state = QNetworkConfiguration::Active; |
417 activeConfig.d->state = QNetworkConfiguration::Active; |
559 activeConfig.d->isValid = true; |
418 activeConfig.d->isValid = true; |
560 currentNetworkInterface = get_network_interface(); |
419 currentNetworkInterface = get_network_interface(); |
561 |
420 |
562 Maemo::IAPConf iap_name(activeConfig.d->id); |
421 Maemo::IAPConf iap_name(activeConfig.d->id); |
563 QString name_value = iap_name.value("name").toString(); |
422 QString name_value = iap_name.value("name").toString(); |
564 if (!name_value.isEmpty()) |
423 if (!name_value.isEmpty()) |
565 activeConfig.d->name = name_value; |
424 activeConfig.d->name = name_value; |
566 else |
425 else |
567 activeConfig.d->name = activeConfig.d->id; |
426 activeConfig.d->name = activeConfig.d->id; |
568 |
427 |
569 |
|
570 // Add the new active configuration to manager or update the old config |
428 // Add the new active configuration to manager or update the old config |
571 mgr = (QNetworkConfigurationManagerPrivate*)activeConfig.d.data()->manager; |
429 mgr = (QNetworkConfigurationManagerPrivate*)activeConfig.d.data()->manager; |
572 if (!(mgr->accessPointConfigurations.contains(activeConfig.d->id))) { |
430 if (!(mgr->accessPointConfigurations.contains(activeConfig.d->id))) { |
573 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = activeConfig.d; |
431 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = activeConfig.d; |
574 mgr->accessPointConfigurations.insert(activeConfig.d->id, ptr); |
432 mgr->accessPointConfigurations.insert(activeConfig.d->id, ptr); |
808 opened = true; |
658 opened = true; |
809 |
659 |
810 if ((activeConfig.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active) { |
660 if ((activeConfig.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active) { |
811 state = QNetworkSession::Connecting; |
661 state = QNetworkSession::Connecting; |
812 emit q->stateChanged(state); |
662 emit q->stateChanged(state); |
813 |
663 QTimer::singleShot(0, this, SLOT(do_open())); |
814 QTimer::singleShot(0, this, SLOT(do_open())); |
664 return; |
815 return; |
|
816 } |
665 } |
817 |
|
818 isOpen = (activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active; |
666 isOpen = (activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active; |
819 if (isOpen) |
667 if (isOpen) |
820 emit quitPendingWaitsForOpened(); |
668 emit quitPendingWaitsForOpened(); |
821 } else { |
669 } else { |
822 /* We seem to be active so inform caller */ |
670 /* We seem to be active so inform caller */ |
823 emit quitPendingWaitsForOpened(); |
671 emit quitPendingWaitsForOpened(); |
824 } |
672 } |
825 } |
673 } |
826 |
|
827 |
674 |
828 void QNetworkSessionPrivate::do_open() |
675 void QNetworkSessionPrivate::do_open() |
829 { |
676 { |
830 icd_connection_flags flags = connectFlags; |
677 icd_connection_flags flags = connectFlags; |
831 bool st; |
|
832 QString result; |
|
833 QString iap = publicConfig.identifier(); |
678 QString iap = publicConfig.identifier(); |
834 |
679 |
835 if (state == QNetworkSession::Connected) { |
680 if (state == QNetworkSession::Connected) { |
836 #ifdef BEARER_MANAGEMENT_DEBUG |
681 #ifdef BEARER_MANAGEMENT_DEBUG |
837 qDebug() << "Already connected to" << activeConfig.identifier(); |
682 qDebug() << "Already connected to" << activeConfig.identifier(); |
838 #endif |
683 #endif |
839 emit q->stateChanged(QNetworkSession::Connected); |
684 emit q->stateChanged(QNetworkSession::Connected); |
840 emit quitPendingWaitsForOpened(); |
685 emit quitPendingWaitsForOpened(); |
841 return; |
686 return; |
842 } |
687 } |
843 |
688 |
844 Maemo::IcdConnectResult connect_result; |
|
845 Maemo::Icd icd(ICD_LONG_CONNECT_TIMEOUT); |
|
846 QNetworkConfiguration config; |
|
847 if (publicConfig.type() == QNetworkConfiguration::UserChoice) |
689 if (publicConfig.type() == QNetworkConfiguration::UserChoice) |
848 config = activeConfig; |
690 config = activeConfig; |
849 else |
691 else |
850 config = publicConfig; |
692 config = publicConfig; |
851 |
693 |
852 if (iap == OSSO_IAP_ANY) { |
694 if (iap == OSSO_IAP_ANY) { |
853 #ifdef BEARER_MANAGEMENT_DEBUG |
695 #ifdef BEARER_MANAGEMENT_DEBUG |
854 qDebug() << "connecting to default IAP" << iap; |
696 qDebug() << "connecting to default IAP" << iap; |
855 #endif |
697 #endif |
856 st = icd.connect(flags, connect_result); |
698 m_connectRequestTimer.start(ICD_LONG_CONNECT_TIMEOUT); |
857 |
699 m_dbusInterface->asyncCall(ICD_DBUS_API_CONNECT_REQ, (uint)flags); // Return value ignored |
|
700 m_asynchCallActive = true; |
858 } else { |
701 } else { |
859 |
702 ICd2DetailsDBusStruct icd2; |
860 QList<Maemo::ConnectParams> params; |
703 icd2.serviceType = config.d->service_type; |
861 Maemo::ConnectParams param; |
704 icd2.serviceAttributes = config.d->service_attrs; |
862 param.connect.service_type = config.d->service_type; |
705 icd2.setviceId = config.d->service_id; |
863 param.connect.service_attrs = config.d->service_attrs; |
706 icd2.networkType = config.d->iap_type; |
864 param.connect.service_id = config.d->service_id; |
707 icd2.networkAttributes = config.d->network_attrs; |
865 param.connect.network_type = config.d->iap_type; |
708 if (config.d->network_attrs & ICD_NW_ATTR_IAPNAME) { |
866 param.connect.network_attrs = config.d->network_attrs; |
709 icd2.networkId = QByteArray(iap.toLatin1()); |
867 if (config.d->network_attrs & ICD_NW_ATTR_IAPNAME) |
710 } else { |
868 param.connect.network_id = QByteArray(iap.toLatin1()); |
711 icd2.networkId = config.d->network_id; |
869 else |
712 } |
870 param.connect.network_id = config.d->network_id; |
713 |
871 params.append(param); |
714 #ifdef BEARER_MANAGEMENT_DEBUG |
872 |
715 qDebug("connecting to %s/%s/0x%x/%s/0x%x/%s", |
873 #ifdef BEARER_MANAGEMENT_DEBUG |
716 icd2.networkId.data(), |
874 qDebug("connecting to %s/%s/0x%x/%s/0x%x/%s", |
717 icd2.networkType.toAscii().constData(), |
875 param.connect.network_id.data(), |
718 icd2.networkAttributes, |
876 param.connect.network_type.toAscii().constData(), |
719 icd2.serviceType.toAscii().constData(), |
877 param.connect.network_attrs, |
720 icd2.serviceAttributes, |
878 param.connect.service_type.toAscii().constData(), |
721 icd2.setviceId.toAscii().constData()); |
879 param.connect.service_attrs, |
722 #endif |
880 param.connect.service_id.toAscii().constData()); |
723 |
881 #endif |
724 ICd2DetailsList paramArray; |
882 st = icd.connect(flags, params, connect_result); |
725 paramArray.append(icd2); |
883 } |
726 m_connectRequestTimer.start(ICD_LONG_CONNECT_TIMEOUT); |
884 |
727 m_dbusInterface->asyncCall(ICD_DBUS_API_CONNECT_REQ, (uint)flags, QVariant::fromValue(paramArray)); // Return value ignored |
885 if (st) { |
728 m_asynchCallActive = true; |
886 result = connect_result.connect.network_id.data(); |
729 } |
887 QString connected_iap = result; |
730 } |
888 |
731 |
889 if (connected_iap.isEmpty()) { |
732 void QNetworkSessionPrivate::stateChange(const QDBusMessage& rep) |
890 #ifdef BEARER_MANAGEMENT_DEBUG |
733 { |
891 qDebug() << "connect to"<< iap << "failed, result is empty"; |
734 if (m_asynchCallActive == true) { |
892 #endif |
735 if (m_connectRequestTimer.isActive()) |
893 updateState(QNetworkSession::Disconnected); |
736 m_connectRequestTimer.stop(); |
894 emit q->error(QNetworkSession::InvalidConfigurationError); |
737 m_asynchCallActive = false; |
895 if (publicConfig.type() == QNetworkConfiguration::UserChoice) |
738 |
896 cleanupAnyConfiguration(); |
739 QString result = rep.arguments().at(5).toString(); // network id or empty string |
897 return; |
740 QString connected_iap = result; |
898 } |
741 if (connected_iap.isEmpty()) { |
899 |
742 #ifdef BEARER_MANAGEMENT_DEBUG |
900 /* If the user tried to connect to some specific connection (foo) |
743 qDebug() << "connect to"<< publicConfig.identifier() << "failed, result is empty"; |
901 * and we were already connected to some other connection (bar), |
744 #endif |
902 * then we cannot activate this session although icd has a valid |
745 updateState(QNetworkSession::Disconnected); |
903 * connection to somewhere. |
746 emit q->error(QNetworkSession::InvalidConfigurationError); |
904 */ |
747 if (publicConfig.type() == QNetworkConfiguration::UserChoice) |
905 if ((publicConfig.type() != QNetworkConfiguration::UserChoice) && |
748 copyConfig(publicConfig, activeConfig); |
906 (connected_iap != config.identifier())) { |
749 return; |
907 updateState(QNetworkSession::Disconnected); |
750 } |
908 emit q->error(QNetworkSession::InvalidConfigurationError); |
751 |
909 return; |
752 /* If the user tried to connect to some specific connection (foo) |
910 } |
753 * and we were already connected to some other connection (bar), |
911 |
754 * then we cannot activate this session although icd has a valid |
912 |
755 * connection to somewhere. |
913 /* Did we connect to non saved IAP? */ |
756 */ |
914 if (!(config.d->network_attrs & ICD_NW_ATTR_IAPNAME)) { |
757 if ((publicConfig.type() != QNetworkConfiguration::UserChoice) && |
915 /* Because the connection succeeded, the IAP is now known. |
758 (connected_iap != config.identifier())) { |
916 */ |
759 updateState(QNetworkSession::Disconnected); |
917 config.d->network_attrs |= ICD_NW_ATTR_IAPNAME; |
760 emit q->error(QNetworkSession::InvalidConfigurationError); |
918 config.d->id = connected_iap; |
761 return; |
919 } |
762 } |
920 |
763 |
921 /* User might have changed the IAP name when a new IAP was saved */ |
764 /* Did we connect to non saved IAP? */ |
922 Maemo::IAPConf iap_name(config.d->id); |
765 if (!(config.d->network_attrs & ICD_NW_ATTR_IAPNAME)) { |
923 QString name = iap_name.value("name").toString(); |
766 /* Because the connection succeeded, the IAP is now known. |
924 if (!name.isEmpty()) |
767 */ |
925 config.d->name = name; |
768 config.d->network_attrs |= ICD_NW_ATTR_IAPNAME; |
926 |
769 config.d->id = connected_iap; |
927 config.d->iap_type = connect_result.connect.network_type; |
770 } |
928 |
771 |
929 config.d->isValid = true; |
772 /* User might have changed the IAP name when a new IAP was saved */ |
930 config.d->state = QNetworkConfiguration::Active; |
773 Maemo::IAPConf iap_name(config.d->id); |
931 config.d->type = QNetworkConfiguration::InternetAccessPoint; |
774 QString name = iap_name.value("name").toString(); |
932 |
775 if (!name.isEmpty()) |
933 startTime = QDateTime::currentDateTime(); |
776 config.d->name = name; |
934 updateState(QNetworkSession::Connected); |
777 |
935 |
778 config.d->iap_type = rep.arguments().at(3).toString(); // connect_result.connect.network_type; |
936 currentNetworkInterface = get_network_interface(); |
779 config.d->isValid = true; |
937 |
780 config.d->state = QNetworkConfiguration::Active; |
938 #ifdef BEARER_MANAGEMENT_DEBUG |
781 config.d->type = QNetworkConfiguration::InternetAccessPoint; |
939 qDebug() << "connected to" << result << config.d->name << "at" << currentNetworkInterface; |
782 |
940 #endif |
783 startTime = QDateTime::currentDateTime(); |
941 |
784 updateState(QNetworkSession::Connected); |
942 /* We first check if the configuration already exists in the manager |
785 //currentNetworkInterface = get_network_interface(); |
943 * and if it is not found there, we then insert it. Note that this |
786 #ifdef BEARER_MANAGEMENT_DEBUG |
944 * is only done for user choice config only because it can be missing |
787 //qDebug() << "connected to" << result << config.d->name << "at" << currentNetworkInterface; |
945 * from config manager list. |
788 #endif |
946 */ |
789 |
947 |
790 /* We first check if the configuration already exists in the manager |
948 if (publicConfig.d->type == QNetworkConfiguration::UserChoice) { |
791 * and if it is not found there, we then insert it. Note that this |
949 |
792 * is only done for user choice config only because it can be missing |
|
793 * from config manager list. |
|
794 */ |
|
795 if (publicConfig.d->type == QNetworkConfiguration::UserChoice) { |
950 #ifdef BEARER_MANAGEMENT_DEBUG |
796 #ifdef BEARER_MANAGEMENT_DEBUG |
951 #if 0 |
797 #if 0 |
952 QList<QNetworkConfiguration> configs; |
798 QList<QNetworkConfiguration> configs; |
953 QNetworkConfigurationManagerPrivate *conPriv = (QNetworkConfigurationManagerPrivate*)config.d.data()->manager; |
799 QNetworkConfigurationManagerPrivate *conPriv = (QNetworkConfigurationManagerPrivate*)config.d.data()->manager; |
954 QList<QString> cpsIdents = conPriv->accessPointConfigurations.keys(); |
800 QList<QString> cpsIdents = conPriv->accessPointConfigurations.keys(); |
955 foreach( QString ii, cpsIdents) { |
801 foreach( QString ii, cpsIdents) { |
956 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> p = |
802 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> p = |
957 conPriv->accessPointConfigurations.value(ii); |
803 conPriv->accessPointConfigurations.value(ii); |
958 QNetworkConfiguration pt; |
804 QNetworkConfiguration pt; |
959 pt.d = conPriv->accessPointConfigurations.value(ii); |
805 pt.d = conPriv->accessPointConfigurations.value(ii); |
960 configs << pt; |
806 configs << pt; |
961 } |
807 } |
962 |
808 |
963 int all = configs.count(); |
809 int all = configs.count(); |
964 qDebug() << "All configurations:" << all; |
810 qDebug() << "All configurations:" << all; |
965 foreach(QNetworkConfiguration p, configs) { |
811 foreach(QNetworkConfiguration p, configs) { |
966 qDebug() << p.name() <<": isvalid->" <<p.isValid() << " type->"<< p.type() << |
812 qDebug() << p.name() <<": isvalid->" <<p.isValid() << " type->"<< p.type() << |
967 " roaming->" << p.isRoamingAvailable() << "identifier->" << p.identifier() << |
813 " roaming->" << p.isRoamingAvailable() << "identifier->" << p.identifier() << |
968 " purpose->" << p.purpose() << " state->" << p.state(); |
814 " purpose->" << p.purpose() << " state->" << p.state(); |
969 } |
815 } |
970 #endif |
816 #endif |
971 #endif |
817 #endif |
972 |
818 QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)publicConfig.d.data()->manager; |
973 QNetworkConfigurationManagerPrivate *mgr = (QNetworkConfigurationManagerPrivate*)config.d.data()->manager; |
|
974 if (!mgr->accessPointConfigurations.contains(result)) { |
819 if (!mgr->accessPointConfigurations.contains(result)) { |
975 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = config.d; |
820 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> ptr = config.d; |
976 mgr->accessPointConfigurations.insert(result, ptr); |
821 mgr->accessPointConfigurations.insert(result, ptr); |
977 |
822 |
978 QNetworkConfiguration item; |
823 QNetworkConfiguration item; |
979 item.d = ptr; |
824 item.d = ptr; |
980 emit mgr->configurationAdded(item); |
825 emit mgr->configurationAdded(item); |
981 |
826 |
982 #ifdef BEARER_MANAGEMENT_DEBUG |
827 #ifdef BEARER_MANAGEMENT_DEBUG |
983 //qDebug()<<"New configuration"<<result<<"added to manager in open"; |
828 qDebug()<<"New configuration"<<result<<"added to manager in open"; |
984 #endif |
829 #endif |
985 |
830 |
986 } else { |
831 } else { |
987 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = mgr->accessPointConfigurations.value(result); |
832 QExplicitlySharedDataPointer<QNetworkConfigurationPrivate> priv = mgr->accessPointConfigurations.value(result); |
988 QNetworkConfiguration reference; |
833 QNetworkConfiguration reference; |
989 reference.d = priv; |
834 reference.d = priv; |
990 copyConfig(config, reference, false); |
835 copyConfig(config, reference, false); |
|
836 reference.d.data()->id = result; // Note: Id was not copied in copyConfig() function |
991 config = reference; |
837 config = reference; |
992 activeConfig = reference; |
838 activeConfig = reference; |
993 mgr->configurationChanged((QNetworkConfigurationPrivate*)(config.d.data())); |
839 |
994 |
840 #ifdef BEARER_MANAGEMENT_DEBUG |
995 #ifdef BEARER_MANAGEMENT_DEBUG |
841 qDebug()<<"Existing configuration"<<result<<"updated in manager in open"; |
996 //qDebug()<<"Existing configuration"<<result<<"updated in manager in open"; |
842 #endif |
997 #endif |
843 } |
998 } |
844 } |
999 } |
845 |
1000 |
846 emit quitPendingWaitsForOpened(); |
1001 emit quitPendingWaitsForOpened(); |
847 } |
1002 |
848 } |
1003 } else { |
849 |
1004 #ifdef BEARER_MANAGEMENT_DEBUG |
850 void QNetworkSessionPrivate::connectTimeout() |
1005 qDebug() << "connect to"<< iap << "failed, status:" << connect_result.status; |
851 { |
1006 #endif |
852 updateState(QNetworkSession::Disconnected); |
1007 updateState(QNetworkSession::Disconnected); |
853 if (publicConfig.type() == QNetworkConfiguration::UserChoice) |
1008 if (publicConfig.type() == QNetworkConfiguration::UserChoice) |
854 copyConfig(publicConfig, activeConfig); |
1009 cleanupAnyConfiguration(); |
855 emit q->error(QNetworkSession::UnknownSessionError); |
1010 emit q->error(QNetworkSession::UnknownSessionError); |
856 } |
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 |
857 |
1024 void QNetworkSessionPrivate::close() |
858 void QNetworkSessionPrivate::close() |
1025 { |
859 { |
|
860 if (m_connectRequestTimer.isActive()) |
|
861 m_connectRequestTimer.stop(); |
|
862 |
1026 if (serviceConfig.isValid()) { |
863 if (serviceConfig.isValid()) { |
1027 lastError = QNetworkSession::OperationNotSupportedError; |
864 lastError = QNetworkSession::OperationNotSupportedError; |
1028 emit q->error(lastError); |
865 emit q->error(lastError); |
1029 } else if (isOpen) { |
866 } else if (isOpen) { |
1030 opened = false; |
867 opened = false; |