1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the plugins of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file. Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qnetworksession_impl.h"
43 #include "qicdengine.h"
44
45 #include <QHash>
46
47 #include <maemo_icd.h>
48 #include <iapconf.h>
49 #include <proxyconf.h>
50
51 #include <ifaddrs.h>
52 #include <netinet/in.h>
53 #include <arpa/inet.h>
54
55 #ifndef QT_NO_BEARERMANAGEMENT
56
57 QT_BEGIN_NAMESPACE
58
operator <<(QDBusArgument & argument,const ICd2DetailsDBusStruct & icd2)59 QDBusArgument &operator<<(QDBusArgument &argument,
60 const ICd2DetailsDBusStruct &icd2)
61 {
62 argument.beginStructure();
63
64 argument << icd2.serviceType;
65 argument << icd2.serviceAttributes;
66 argument << icd2.setviceId;
67 argument << icd2.networkType;
68 argument << icd2.networkAttributes;
69 argument << icd2.networkId;
70
71 argument.endStructure();
72
73 return argument;
74 }
75
operator >>(const QDBusArgument & argument,ICd2DetailsDBusStruct & icd2)76 const QDBusArgument &operator>>(const QDBusArgument &argument,
77 ICd2DetailsDBusStruct &icd2)
78 {
79 argument.beginStructure();
80
81 argument >> icd2.serviceType;
82 argument >> icd2.serviceAttributes;
83 argument >> icd2.setviceId;
84 argument >> icd2.networkType;
85 argument >> icd2.networkAttributes;
86 argument >> icd2.networkId;
87
88 argument.endStructure();
89
90 return argument;
91 }
92
operator >>(const QDBusArgument & argument,ICd2DetailsList & detailsList)93 const QDBusArgument &operator>>(const QDBusArgument &argument,
94 ICd2DetailsList &detailsList)
95 {
96 argument.beginArray();
97 detailsList.clear();
98
99 while (!argument.atEnd()) {
100 ICd2DetailsDBusStruct element;
101 argument >> element;
102 detailsList.append(element);
103 }
104
105 argument.endArray();
106 return argument;
107 }
108
operator <<(QDBusArgument & argument,const ICd2DetailsList & detailsList)109 QDBusArgument &operator<<(QDBusArgument &argument,
110 const ICd2DetailsList &detailsList)
111 {
112 argument.beginArray(qMetaTypeId<ICd2DetailsDBusStruct>());
113
114 for (int i = 0; i < detailsList.count(); ++i)
115 argument << detailsList[i];
116
117 argument.endArray();
118
119 return argument;
120 }
121
122 static QHash<QString, QVariant> properties;
123
124 static QString get_network_interface();
125
iapStateChanged(const QString & iapid,uint icd_connection_state)126 void QNetworkSessionPrivateImpl::iapStateChanged(const QString& iapid, uint icd_connection_state)
127 {
128
129 if (((publicConfig.type() == QNetworkConfiguration::UserChoice) &&
130 (activeConfig.identifier() == iapid)) ||
131 (publicConfig.identifier() == iapid)) {
132 switch (icd_connection_state) {
133 case ICD_STATE_CONNECTING:
134 updateState(QNetworkSession::Connecting);
135 break;
136 case ICD_STATE_CONNECTED:
137 updateState(QNetworkSession::Connected);
138 break;
139 case ICD_STATE_DISCONNECTING:
140 updateState(QNetworkSession::Closing);
141 break;
142 case ICD_STATE_DISCONNECTED:
143 updateState(QNetworkSession::Disconnected);
144 break;
145 default:
146 break;
147 }
148 }
149 if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
150 updateIdentifier(iapid);
151 }
152 }
153
cleanupSession(void)154 void QNetworkSessionPrivateImpl::cleanupSession(void)
155 {
156 QObject::disconnect(q, SIGNAL(stateChanged(QNetworkSession::State)),
157 this, SLOT(updateProxies(QNetworkSession::State)));
158 }
159
160
updateState(QNetworkSession::State newState)161 void QNetworkSessionPrivateImpl::updateState(QNetworkSession::State newState)
162 {
163 if (newState != state) {
164 if (newState == QNetworkSession::Disconnected) {
165 if (isOpen) {
166 // The Session was aborted by the user or system
167 lastError = QNetworkSession::SessionAbortedError;
168 emit QNetworkSessionPrivate::error(lastError);
169 emit closed();
170 }
171 if (m_stopTimer.isActive()) {
172 // Session was closed by calling stop()
173 m_stopTimer.stop();
174 }
175 isOpen = false;
176 opened = false;
177 currentNetworkInterface.clear();
178 if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
179 copyConfig(publicConfig, activeConfig);
180 IcdNetworkConfigurationPrivate *icdConfig =
181 toIcdConfig(privateConfiguration(activeConfig));
182
183 icdConfig->mutex.lock();
184 icdConfig->state = QNetworkConfiguration::Defined;
185 icdConfig->mutex.unlock();
186
187 // Reset the state of the default configuration to Discovered
188 icdConfig = toIcdConfig(privateConfiguration(publicConfig));
189 icdConfig->mutex.lock();
190 icdConfig->state = QNetworkConfiguration::Discovered;
191 icdConfig->mutex.unlock();
192 } else {
193 if (!activeConfig.isValid()) {
194 // Active configuration (IAP) was removed from system
195 // => Connection was disconnected and configuration became
196 // invalid
197 // => Also Session state must be changed to invalid
198 newState = QNetworkSession::Invalid;
199 }
200 }
201 } else if (newState == QNetworkSession::Connected) {
202 if (opened) {
203 isOpen = true;
204 }
205 if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
206 IcdNetworkConfigurationPrivate *icdConfig =
207 toIcdConfig(privateConfiguration(activeConfig));
208
209 icdConfig->mutex.lock();
210 icdConfig->state = QNetworkConfiguration::Active;
211 icdConfig->type = QNetworkConfiguration::InternetAccessPoint;
212 icdConfig->mutex.unlock();
213 }
214
215 IcdNetworkConfigurationPrivate *icdConfig =
216 toIcdConfig(privateConfiguration(publicConfig));
217
218 icdConfig->mutex.lock();
219 icdConfig->state = QNetworkConfiguration::Active;
220 icdConfig->mutex.unlock();
221 }
222
223 if (newState != state) {
224 state = newState;
225 emit stateChanged(newState);
226 }
227 }
228 }
229
230
updateIdentifier(const QString & newId)231 void QNetworkSessionPrivateImpl::updateIdentifier(const QString &newId)
232 {
233 if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
234 IcdNetworkConfigurationPrivate *icdConfig =
235 toIcdConfig(privateConfiguration(activeConfig));
236
237 icdConfig->mutex.lock();
238 icdConfig->network_attrs |= ICD_NW_ATTR_IAPNAME;
239 icdConfig->id = newId;
240 icdConfig->mutex.unlock();
241 } else {
242 IcdNetworkConfigurationPrivate *icdConfig =
243 toIcdConfig(privateConfiguration(publicConfig));
244
245 icdConfig->mutex.lock();
246 icdConfig->network_attrs |= ICD_NW_ATTR_IAPNAME;
247 if (icdConfig->id != newId)
248 icdConfig->id = newId;
249 icdConfig->mutex.unlock();
250 }
251 }
252
253
getStatistics() const254 QNetworkSessionPrivateImpl::Statistics QNetworkSessionPrivateImpl::getStatistics() const
255 {
256 /* This could be also implemented by using the Maemo::Icd::statistics()
257 * that gets the statistics data for a specific IAP. Change if
258 * necessary.
259 */
260 Maemo::Icd icd;
261 QList<Maemo::IcdStatisticsResult> stats_results;
262 Statistics stats = { 0, 0, 0};
263
264 if (!icd.statistics(stats_results))
265 return stats;
266
267 foreach (const Maemo::IcdStatisticsResult &res, stats_results) {
268 if (res.params.network_attrs & ICD_NW_ATTR_IAPNAME) {
269 /* network_id is the IAP UUID */
270 if (QString(res.params.network_id.data()) == activeConfig.identifier()) {
271 stats.txData = res.bytes_sent;
272 stats.rxData = res.bytes_received;
273 stats.activeTime = res.time_active;
274 }
275 } else {
276 /* We probably will never get to this branch */
277 IcdNetworkConfigurationPrivate *icdConfig =
278 toIcdConfig(privateConfiguration(activeConfig));
279
280 icdConfig->mutex.lock();
281 if (res.params.network_id == icdConfig->network_id) {
282 stats.txData = res.bytes_sent;
283 stats.rxData = res.bytes_received;
284 stats.activeTime = res.time_active;
285 }
286 icdConfig->mutex.unlock();
287 }
288 }
289
290 return stats;
291 }
292
293
bytesWritten() const294 quint64 QNetworkSessionPrivateImpl::bytesWritten() const
295 {
296 return getStatistics().txData;
297 }
298
bytesReceived() const299 quint64 QNetworkSessionPrivateImpl::bytesReceived() const
300 {
301 return getStatistics().rxData;
302 }
303
activeTime() const304 quint64 QNetworkSessionPrivateImpl::activeTime() const
305 {
306 return getStatistics().activeTime;
307 }
308
309
copyConfig(QNetworkConfiguration & fromConfig,QNetworkConfiguration & toConfig,bool deepCopy)310 QNetworkConfiguration& QNetworkSessionPrivateImpl::copyConfig(QNetworkConfiguration &fromConfig,
311 QNetworkConfiguration &toConfig,
312 bool deepCopy)
313 {
314 IcdNetworkConfigurationPrivate *cpPriv;
315 if (deepCopy) {
316 cpPriv = new IcdNetworkConfigurationPrivate;
317 setPrivateConfiguration(toConfig, QNetworkConfigurationPrivatePointer(cpPriv));
318 } else {
319 cpPriv = toIcdConfig(privateConfiguration(toConfig));
320 }
321
322 IcdNetworkConfigurationPrivate *fromPriv = toIcdConfig(privateConfiguration(fromConfig));
323
324 QMutexLocker toLocker(&cpPriv->mutex);
325 QMutexLocker fromLocker(&fromPriv->mutex);
326
327 cpPriv->name = fromPriv->name;
328 cpPriv->isValid = fromPriv->isValid;
329 // Note that we do not copy id field here as the publicConfig does
330 // not contain a valid IAP id.
331 cpPriv->state = fromPriv->state;
332 cpPriv->type = fromPriv->type;
333 cpPriv->roamingSupported = fromPriv->roamingSupported;
334 cpPriv->purpose = fromPriv->purpose;
335 cpPriv->network_id = fromPriv->network_id;
336 cpPriv->iap_type = fromPriv->iap_type;
337 cpPriv->bearerType = fromPriv->bearerType;
338 cpPriv->network_attrs = fromPriv->network_attrs;
339 cpPriv->service_type = fromPriv->service_type;
340 cpPriv->service_id = fromPriv->service_id;
341 cpPriv->service_attrs = fromPriv->service_attrs;
342
343 return toConfig;
344 }
345
346
347 /* This is called by QNetworkSession constructor and it updates the current
348 * state of the configuration.
349 */
syncStateWithInterface()350 void QNetworkSessionPrivateImpl::syncStateWithInterface()
351 {
352 /* Initially we are not active although the configuration might be in
353 * connected state.
354 */
355 isOpen = false;
356 opened = false;
357
358 connect(engine, SIGNAL(iapStateChanged(const QString&, uint)),
359 this, SLOT(iapStateChanged(const QString&, uint)));
360
361 QObject::connect(q, SIGNAL(stateChanged(QNetworkSession::State)), this, SLOT(updateProxies(QNetworkSession::State)));
362
363 state = QNetworkSession::Invalid;
364 lastError = QNetworkSession::UnknownSessionError;
365
366 switch (publicConfig.type()) {
367 case QNetworkConfiguration::InternetAccessPoint:
368 activeConfig = publicConfig;
369 break;
370 case QNetworkConfiguration::ServiceNetwork:
371 serviceConfig = publicConfig;
372 break;
373 case QNetworkConfiguration::UserChoice:
374 // active config will contain correct data after open() has succeeded
375 copyConfig(publicConfig, activeConfig);
376
377 /* We create new configuration that holds the actual configuration
378 * returned by icd. This way publicConfig still contains the
379 * original user specified configuration.
380 *
381 * Note that the new activeConfig configuration is not inserted
382 * to configurationManager as manager class will get the newly
383 * connected configuration from gconf when the IAP is saved.
384 * This configuration manager update is done by IapMonitor class.
385 * If the ANY connection fails in open(), then the configuration
386 * data is not saved to gconf and will not be added to
387 * configuration manager IAP list.
388 */
389 #ifdef BEARER_MANAGEMENT_DEBUG
390 qDebug()<<"New configuration created for" << publicConfig.identifier();
391 #endif
392 break;
393 default:
394 /* Invalid configuration, no point continuing */
395 return;
396 }
397
398 if (!activeConfig.isValid())
399 return;
400
401 /* Get the initial state from icd */
402 Maemo::Icd icd;
403 QList<Maemo::IcdStateResult> state_results;
404
405 /* Update the active config from first connection, this is ok as icd
406 * supports only one connection anyway.
407 */
408 if (icd.state(state_results) && !state_results.isEmpty()) {
409 /* If we did not get full state back, then we are not
410 * connected and can skip the next part.
411 */
412 if (!(state_results.first().params.network_attrs == 0 &&
413 state_results.first().params.network_id.isEmpty())) {
414
415 /* If we try to connect to specific IAP and we get results back
416 * that tell the icd is actually connected to another IAP,
417 * then do not update current state etc.
418 */
419 if (publicConfig.type() == QNetworkConfiguration::UserChoice ||
420 publicConfig.identifier() == state_results.first().params.network_id) {
421 switch (state_results.first().state) {
422 case ICD_STATE_DISCONNECTED:
423 state = QNetworkSession::Disconnected;
424 if (QNetworkConfigurationPrivatePointer ptr = privateConfiguration(activeConfig)) {
425 ptr->mutex.lock();
426 ptr->isValid = true;
427 ptr->mutex.unlock();
428 }
429 break;
430 case ICD_STATE_CONNECTING:
431 state = QNetworkSession::Connecting;
432 if (QNetworkConfigurationPrivatePointer ptr = privateConfiguration(activeConfig)) {
433 ptr->mutex.lock();
434 ptr->isValid = true;
435 ptr->mutex.unlock();
436 }
437 break;
438 case ICD_STATE_CONNECTED:
439 {
440 if (!state_results.first().error.isEmpty())
441 break;
442
443 const QString id = state_results.first().params.network_id;
444
445 QNetworkConfiguration config = manager.configurationFromIdentifier(id);
446 if (config.isValid()) {
447 //we don't want the copied data if the config is already known by the manager
448 //just reuse it so that existing references to the old data get the same update
449 setPrivateConfiguration(activeConfig, privateConfiguration(config));
450 }
451
452 QNetworkConfigurationPrivatePointer ptr = privateConfiguration(activeConfig);
453
454 QMutexLocker configLocker(&ptr->mutex);
455
456 state = QNetworkSession::Connected;
457 toIcdConfig(ptr)->network_id = state_results.first().params.network_id;
458 ptr->id = toIcdConfig(ptr)->network_id;
459 toIcdConfig(ptr)->network_attrs = state_results.first().params.network_attrs;
460 toIcdConfig(ptr)->iap_type = state_results.first().params.network_type;
461 ptr->bearerType = bearerTypeFromIapType(toIcdConfig(ptr)->iap_type);
462 toIcdConfig(ptr)->service_type = state_results.first().params.service_type;
463 toIcdConfig(ptr)->service_id = state_results.first().params.service_id;
464 toIcdConfig(ptr)->service_attrs = state_results.first().params.service_attrs;
465 ptr->type = QNetworkConfiguration::InternetAccessPoint;
466 ptr->state = QNetworkConfiguration::Active;
467 ptr->isValid = true;
468 currentNetworkInterface = get_network_interface();
469
470 Maemo::IAPConf iap_name(ptr->id);
471 QString name_value = iap_name.value("name").toString();
472 if (!name_value.isEmpty())
473 ptr->name = name_value;
474 else
475 ptr->name = ptr->id;
476
477 const QString identifier = ptr->id;
478
479 configLocker.unlock();
480
481 // Add the new active configuration to manager or update the old config
482 if (!engine->hasIdentifier(identifier))
483 engine->addSessionConfiguration(ptr);
484 else
485 engine->changedSessionConfiguration(ptr);
486 }
487 break;
488
489 case ICD_STATE_DISCONNECTING:
490 state = QNetworkSession::Closing;
491 if (QNetworkConfigurationPrivatePointer ptr = privateConfiguration(activeConfig)) {
492 ptr->mutex.lock();
493 ptr->isValid = true;
494 ptr->mutex.unlock();
495 }
496 break;
497 default:
498 break;
499 }
500 }
501 } else {
502 #ifdef BEARER_MANAGEMENT_DEBUG
503 qDebug() << "status_req tells icd is not connected";
504 #endif
505 }
506 } else {
507 #ifdef BEARER_MANAGEMENT_DEBUG
508 qDebug() << "status_req did not return any results from icd";
509 #endif
510 }
511
512 networkConfigurationsChanged();
513 }
514
515
networkConfigurationsChanged()516 void QNetworkSessionPrivateImpl::networkConfigurationsChanged()
517 {
518 if (serviceConfig.isValid())
519 updateStateFromServiceNetwork();
520 else
521 updateStateFromActiveConfig();
522 }
523
524
updateStateFromServiceNetwork()525 void QNetworkSessionPrivateImpl::updateStateFromServiceNetwork()
526 {
527 QNetworkSession::State oldState = state;
528
529 foreach (const QNetworkConfiguration &config, serviceConfig.children()) {
530 if ((config.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active)
531 continue;
532
533 if (activeConfig != config) {
534 activeConfig = config;
535 emit newConfigurationActivated();
536 }
537
538 state = QNetworkSession::Connected;
539 if (state != oldState)
540 emit stateChanged(state);
541
542 return;
543 }
544
545 if (serviceConfig.children().isEmpty())
546 state = QNetworkSession::NotAvailable;
547 else
548 state = QNetworkSession::Disconnected;
549
550 if (state != oldState)
551 emit stateChanged(state);
552 }
553
554
clearConfiguration(QNetworkConfiguration & config)555 void QNetworkSessionPrivateImpl::clearConfiguration(QNetworkConfiguration &config)
556 {
557 IcdNetworkConfigurationPrivate *icdConfig = toIcdConfig(privateConfiguration(config));
558
559 QMutexLocker locker(&icdConfig->mutex);
560
561 icdConfig->network_id.clear();
562 icdConfig->iap_type.clear();
563 icdConfig->network_attrs = 0;
564 icdConfig->service_type.clear();
565 icdConfig->service_id.clear();
566 icdConfig->service_attrs = 0;
567 }
568
569
updateStateFromActiveConfig()570 void QNetworkSessionPrivateImpl::updateStateFromActiveConfig()
571 {
572 QNetworkSession::State oldState = state;
573
574 bool newActive = false;
575
576 if (!activeConfig.isValid())
577 return;
578
579 if (!activeConfig.isValid()) {
580 state = QNetworkSession::Invalid;
581 clearConfiguration(activeConfig);
582 } else if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
583 state = QNetworkSession::Connected;
584 newActive = opened;
585 } else if ((activeConfig.state() & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) {
586 state = QNetworkSession::Disconnected;
587 } else if ((activeConfig.state() & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) {
588 state = QNetworkSession::NotAvailable;
589 } else if ((activeConfig.state() & QNetworkConfiguration::Undefined) == QNetworkConfiguration::Undefined) {
590 state = QNetworkSession::NotAvailable;
591 }
592
593 bool oldActive = isOpen;
594 isOpen = newActive;
595
596 if (!oldActive && isOpen)
597 emit quitPendingWaitsForOpened();
598
599 if (oldActive && !isOpen)
600 emit closed();
601
602 if (oldState != state) {
603 emit stateChanged(state);
604
605 if (state == QNetworkSession::Disconnected && oldActive) {
606 #ifdef BEARER_MANAGEMENT_DEBUG
607 //qDebug()<<"session aborted error emitted for"<<activeConfig.identifier();
608 #endif
609 lastError = QNetworkSession::SessionAbortedError;
610 emit QNetworkSessionPrivate::error(lastError);
611 }
612 }
613
614 #ifdef BEARER_MANAGEMENT_DEBUG
615 //qDebug()<<"oldState ="<<oldState<<" state ="<<state<<" oldActive ="<<oldActive<<" newActive ="<<newActive<<" opened ="<<opened;
616 #endif
617 }
618
get_network_interface()619 static QString get_network_interface()
620 {
621 Maemo::Icd icd;
622 QList<Maemo::IcdAddressInfoResult> addr_results;
623 uint ret;
624 QString iface;
625
626 ret = icd.addrinfo(addr_results);
627 if (ret == 0) {
628 /* No results */
629 #ifdef BEARER_MANAGEMENT_DEBUG
630 qDebug() << "Cannot get addrinfo from icd, are you connected or is icd running?";
631 #endif
632 return iface;
633 }
634
635 if (addr_results.first().ip_info.isEmpty())
636 return QString();
637
638 QByteArray data = addr_results.first().ip_info.first().address.toAscii();
639 struct in_addr addr;
640 if (inet_aton(data.constData(), &addr) == 0) {
641 #ifdef BEARER_MANAGEMENT_DEBUG
642 qDebug() << "address" << data.constData() << "invalid";
643 #endif
644 return iface;
645 }
646
647 struct ifaddrs *ifaddr, *ifa;
648 int family;
649
650 if (getifaddrs(&ifaddr) == -1) {
651 #ifdef BEARER_MANAGEMENT_DEBUG
652 qDebug() << "getifaddrs() failed";
653 #endif
654 return iface;
655 }
656
657 for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
658 if (ifa->ifa_addr) {
659 family = ifa->ifa_addr->sa_family;
660 if (family != AF_INET) {
661 continue; /* Currently only IPv4 is supported by icd dbus interface */
662 }
663 if (((struct sockaddr_in *)ifa->ifa_addr)->sin_addr.s_addr == addr.s_addr) {
664 iface = QString(ifa->ifa_name);
665 break;
666 }
667 }
668 }
669
670 freeifaddrs(ifaddr);
671 return iface;
672 }
673
674
open()675 void QNetworkSessionPrivateImpl::open()
676 {
677 if (m_stopTimer.isActive()) {
678 m_stopTimer.stop();
679 }
680 if (!publicConfig.isValid()) {
681 lastError = QNetworkSession::InvalidConfigurationError;
682 emit QNetworkSessionPrivate::error(lastError);
683 return;
684 }
685 if (serviceConfig.isValid()) {
686 lastError = QNetworkSession::OperationNotSupportedError;
687 emit QNetworkSessionPrivate::error(lastError);
688 } else if (!opened) {
689 if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
690 /* Caller is trying to connect to default IAP.
691 * At this time we will not know the IAP details so we just
692 * connect and update the active config when the IAP is
693 * connected.
694 */
695 opened = true;
696 state = QNetworkSession::Connecting;
697 emit stateChanged(state);
698 QTimer::singleShot(0, this, SLOT(do_open()));
699 return;
700 }
701
702 /* User is connecting to one specific IAP. If that IAP is not
703 * in discovered state we cannot continue.
704 */
705 if ((activeConfig.state() & QNetworkConfiguration::Discovered) !=
706 QNetworkConfiguration::Discovered) {
707 lastError =QNetworkSession::InvalidConfigurationError;
708 emit QNetworkSessionPrivate::error(lastError);
709 return;
710 }
711 opened = true;
712
713 if ((activeConfig.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active) {
714 state = QNetworkSession::Connecting;
715 emit stateChanged(state);
716 QTimer::singleShot(0, this, SLOT(do_open()));
717 return;
718 }
719 isOpen = (activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active;
720 if (isOpen)
721 emit quitPendingWaitsForOpened();
722 } else {
723 /* We seem to be active so inform caller */
724 emit quitPendingWaitsForOpened();
725 }
726 }
727
do_open()728 void QNetworkSessionPrivateImpl::do_open()
729 {
730 icd_connection_flags flags = connectFlags;
731 QString iap = publicConfig.identifier();
732
733 if (state == QNetworkSession::Connected) {
734 #ifdef BEARER_MANAGEMENT_DEBUG
735 qDebug() << "Already connected to" << activeConfig.identifier();
736 #endif
737 emit stateChanged(QNetworkSession::Connected);
738 emit quitPendingWaitsForOpened();
739 return;
740 }
741
742 if (publicConfig.type() == QNetworkConfiguration::UserChoice)
743 config = activeConfig;
744 else
745 config = publicConfig;
746
747 if (iap == OSSO_IAP_ANY) {
748 #ifdef BEARER_MANAGEMENT_DEBUG
749 qDebug() << "connecting to default IAP" << iap;
750 #endif
751 m_connectRequestTimer.start(ICD_LONG_CONNECT_TIMEOUT);
752 m_dbusInterface->asyncCall(ICD_DBUS_API_CONNECT_REQ, (uint)flags); // Return value ignored
753 m_asynchCallActive = true;
754 } else {
755 IcdNetworkConfigurationPrivate *icdConfig = toIcdConfig(privateConfiguration(config));
756
757 icdConfig->mutex.lock();
758 ICd2DetailsDBusStruct icd2;
759 icd2.serviceType = icdConfig->service_type;
760 icd2.serviceAttributes = icdConfig->service_attrs;
761 icd2.setviceId = icdConfig->service_id;
762 icd2.networkType = icdConfig->iap_type;
763 icd2.networkAttributes = icdConfig->network_attrs;
764 if (icdConfig->network_attrs & ICD_NW_ATTR_IAPNAME) {
765 icd2.networkId = QByteArray(iap.toLatin1());
766 } else {
767 icd2.networkId = icdConfig->network_id;
768 }
769 icdConfig->mutex.unlock();
770
771 #ifdef BEARER_MANAGEMENT_DEBUG
772 qDebug("connecting to %s/%s/0x%x/%s/0x%x/%s",
773 icd2.networkId.data(),
774 icd2.networkType.toAscii().constData(),
775 icd2.networkAttributes,
776 icd2.serviceType.toAscii().constData(),
777 icd2.serviceAttributes,
778 icd2.setviceId.toAscii().constData());
779 #endif
780
781 ICd2DetailsList paramArray;
782 paramArray.append(icd2);
783 m_connectRequestTimer.start(ICD_LONG_CONNECT_TIMEOUT);
784 m_dbusInterface->asyncCall(ICD_DBUS_API_CONNECT_REQ, (uint)flags, QVariant::fromValue(paramArray)); // Return value ignored
785 m_asynchCallActive = true;
786 }
787 }
788
stateChange(const QDBusMessage & rep)789 void QNetworkSessionPrivateImpl::stateChange(const QDBusMessage& rep)
790 {
791 if (m_asynchCallActive == true) {
792 if (m_connectRequestTimer.isActive())
793 m_connectRequestTimer.stop();
794 m_asynchCallActive = false;
795
796 QString result = rep.arguments().at(5).toString(); // network id or empty string
797 QString connected_iap = result;
798 if (connected_iap.isEmpty()) {
799 #ifdef BEARER_MANAGEMENT_DEBUG
800 qDebug() << "connect to"<< publicConfig.identifier() << "failed, result is empty";
801 #endif
802 updateState(QNetworkSession::Disconnected);
803 emit QNetworkSessionPrivate::error(QNetworkSession::SessionAbortedError);
804 if (publicConfig.type() == QNetworkConfiguration::UserChoice)
805 copyConfig(publicConfig, activeConfig);
806 return;
807 }
808
809 /* If the user tried to connect to some specific connection (foo)
810 * and we were already connected to some other connection (bar),
811 * then we cannot activate this session although icd has a valid
812 * connection to somewhere.
813 */
814 if ((publicConfig.type() != QNetworkConfiguration::UserChoice) &&
815 (connected_iap != config.identifier())) {
816 updateState(QNetworkSession::Disconnected);
817 emit QNetworkSessionPrivate::error(QNetworkSession::UnknownSessionError);
818 return;
819 }
820
821 IcdNetworkConfigurationPrivate *icdConfig = toIcdConfig(privateConfiguration(config));
822
823 /* Did we connect to non saved IAP? */
824 icdConfig->mutex.lock();
825 if (!(icdConfig->network_attrs & ICD_NW_ATTR_IAPNAME)) {
826 /* Because the connection succeeded, the IAP is now known.
827 */
828 icdConfig->network_attrs |= ICD_NW_ATTR_IAPNAME;
829 icdConfig->id = connected_iap;
830 }
831
832 /* User might have changed the IAP name when a new IAP was saved */
833 Maemo::IAPConf iap_name(icdConfig->id);
834 QString name = iap_name.value("name").toString();
835 if (!name.isEmpty())
836 icdConfig->name = name;
837
838 icdConfig->iap_type = rep.arguments().at(3).toString(); // connect_result.connect.network_type;
839 icdConfig->bearerType = bearerTypeFromIapType(icdConfig->iap_type);
840 icdConfig->isValid = true;
841 icdConfig->state = QNetworkConfiguration::Active;
842 icdConfig->type = QNetworkConfiguration::InternetAccessPoint;
843
844 icdConfig->mutex.unlock();
845
846 startTime = QDateTime::currentDateTime();
847 updateState(QNetworkSession::Connected);
848 //currentNetworkInterface = get_network_interface();
849 #ifdef BEARER_MANAGEMENT_DEBUG
850 //qDebug() << "connected to" << result << config.name() << "at" << currentNetworkInterface;
851 #endif
852
853 /* We first check if the configuration already exists in the manager
854 * and if it is not found there, we then insert it. Note that this
855 * is only done for user choice config only because it can be missing
856 * from config manager list.
857 */
858 if (publicConfig.type() == QNetworkConfiguration::UserChoice) {
859 if (!engine->hasIdentifier(result)) {
860 engine->addSessionConfiguration(privateConfiguration(config));
861 } else {
862 QNetworkConfigurationPrivatePointer priv = engine->configuration(result);
863 QNetworkConfiguration reference;
864 setPrivateConfiguration(reference, priv);
865 copyConfig(config, reference, false);
866 privateConfiguration(reference)->id = result; // Note: Id was not copied in copyConfig() function
867 config = reference;
868 activeConfig = reference;
869 engine->changedSessionConfiguration(privateConfiguration(config));
870
871 #ifdef BEARER_MANAGEMENT_DEBUG
872 qDebug()<<"Existing configuration"<<result<<"updated in manager in open";
873 #endif
874 }
875 }
876
877 emit quitPendingWaitsForOpened();
878 }
879 }
880
connectTimeout()881 void QNetworkSessionPrivateImpl::connectTimeout()
882 {
883 updateState(QNetworkSession::Disconnected);
884 if (publicConfig.type() == QNetworkConfiguration::UserChoice)
885 copyConfig(publicConfig, activeConfig);
886 emit QNetworkSessionPrivate::error(QNetworkSession::UnknownSessionError);
887 }
888
close()889 void QNetworkSessionPrivateImpl::close()
890 {
891 if (m_connectRequestTimer.isActive())
892 m_connectRequestTimer.stop();
893
894 if (serviceConfig.isValid()) {
895 lastError = QNetworkSession::OperationNotSupportedError;
896 emit QNetworkSessionPrivate::error(lastError);
897 } else if (isOpen) {
898 if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
899 // We will not wait any disconnect from icd as it might never come
900 #ifdef BEARER_MANAGEMENT_DEBUG
901 qDebug() << "closing session" << publicConfig.identifier();
902 #endif
903 state = QNetworkSession::Closing;
904 emit stateChanged(state);
905
906 // we fake a disconnection, session error is sent
907 updateState(QNetworkSession::Disconnected);
908
909 opened = false;
910 isOpen = false;
911
912 m_dbusInterface->call(ICD_DBUS_API_DISCONNECT_REQ, ICD_CONNECTION_FLAG_APPLICATION_EVENT);
913 startTime = QDateTime();
914 } else {
915 opened = false;
916 isOpen = false;
917 emit closed();
918 }
919 }
920 }
921
922
stop()923 void QNetworkSessionPrivateImpl::stop()
924 {
925 if (m_connectRequestTimer.isActive())
926 m_connectRequestTimer.stop();
927
928 if (serviceConfig.isValid()) {
929 lastError = QNetworkSession::OperationNotSupportedError;
930 emit QNetworkSessionPrivate::error(lastError);
931 } else {
932 if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
933 #ifdef BEARER_MANAGEMENT_DEBUG
934 qDebug() << "stopping session" << publicConfig.identifier();
935 #endif
936 state = QNetworkSession::Closing;
937 emit stateChanged(state);
938
939 // we fake a disconnection, a session error is sent also
940 updateState(QNetworkSession::Disconnected);
941
942 opened = false;
943 isOpen = false;
944
945 m_dbusInterface->call(ICD_DBUS_API_DISCONNECT_REQ, ICD_CONNECTION_FLAG_APPLICATION_EVENT);
946 startTime = QDateTime();
947 } else {
948 opened = false;
949 isOpen = false;
950 emit closed();
951 }
952 }
953 }
954
finishStopBySendingClosedSignal()955 void QNetworkSessionPrivateImpl::finishStopBySendingClosedSignal()
956 {
957 if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
958 state = QNetworkSession::Connected;
959 emit stateChanged(state);
960 }
961
962 emit closed();
963 }
964
migrate()965 void QNetworkSessionPrivateImpl::migrate()
966 {
967 }
968
969
accept()970 void QNetworkSessionPrivateImpl::accept()
971 {
972 }
973
974
ignore()975 void QNetworkSessionPrivateImpl::ignore()
976 {
977 }
978
979
reject()980 void QNetworkSessionPrivateImpl::reject()
981 {
982 }
983
984 #ifndef QT_NO_NETWORKINTERFACE
currentInterface() const985 QNetworkInterface QNetworkSessionPrivateImpl::currentInterface() const
986 {
987 if (!publicConfig.isValid() || state != QNetworkSession::Connected)
988 return QNetworkInterface();
989
990 if (currentNetworkInterface.isEmpty())
991 return QNetworkInterface();
992
993 return QNetworkInterface::interfaceFromName(currentNetworkInterface);
994 }
995 #endif
996
setSessionProperty(const QString & key,const QVariant & value)997 void QNetworkSessionPrivateImpl::setSessionProperty(const QString& key, const QVariant& value)
998 {
999 if (value.isValid()) {
1000 properties.insert(key, value);
1001
1002 if (key == "ConnectInBackground") {
1003 bool v = value.toBool();
1004 if (v)
1005 connectFlags = ICD_CONNECTION_FLAG_APPLICATION_EVENT;
1006 else
1007 connectFlags = ICD_CONNECTION_FLAG_USER_EVENT;
1008 }
1009 } else {
1010 properties.remove(key);
1011
1012 /* Set default value when property is removed */
1013 if (key == "ConnectInBackground")
1014 connectFlags = ICD_CONNECTION_FLAG_USER_EVENT;
1015 }
1016 }
1017
1018
sessionProperty(const QString & key) const1019 QVariant QNetworkSessionPrivateImpl::sessionProperty(const QString& key) const
1020 {
1021 return properties.value(key);
1022 }
1023
1024
errorString() const1025 QString QNetworkSessionPrivateImpl::errorString() const
1026 {
1027 QString errorStr;
1028 switch(q->error()) {
1029 case QNetworkSession::RoamingError:
1030 errorStr = QNetworkSessionPrivateImpl::tr("Roaming error");
1031 break;
1032 case QNetworkSession::SessionAbortedError:
1033 errorStr = QNetworkSessionPrivateImpl::tr("Session aborted by user or system");
1034 break;
1035 case QNetworkSession::InvalidConfigurationError:
1036 errorStr = QNetworkSessionPrivateImpl::tr("The specified configuration cannot be used.");
1037 break;
1038 default:
1039 case QNetworkSession::UnknownSessionError:
1040 errorStr = QNetworkSessionPrivateImpl::tr("Unidentified Error");
1041 break;
1042 }
1043 return errorStr;
1044 }
1045
1046
error() const1047 QNetworkSession::SessionError QNetworkSessionPrivateImpl::error() const
1048 {
1049 return QNetworkSession::UnknownSessionError;
1050 }
1051
updateProxies(QNetworkSession::State newState)1052 void QNetworkSessionPrivateImpl::updateProxies(QNetworkSession::State newState)
1053 {
1054 if ((newState == QNetworkSession::Connected) &&
1055 (newState != currentState))
1056 updateProxyInformation();
1057 else if ((newState == QNetworkSession::Disconnected) &&
1058 (currentState == QNetworkSession::Closing))
1059 clearProxyInformation();
1060
1061 currentState = newState;
1062 }
1063
1064
updateProxyInformation()1065 void QNetworkSessionPrivateImpl::updateProxyInformation()
1066 {
1067 Maemo::ProxyConf::update();
1068 }
1069
1070
clearProxyInformation()1071 void QNetworkSessionPrivateImpl::clearProxyInformation()
1072 {
1073 Maemo::ProxyConf::clear();
1074 }
1075
1076 QT_END_NAMESPACE
1077
1078 #endif // QT_NO_BEARERMANAGEMENT
1079