Qt 4.8
qicdengine.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 **
3 ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14 ** conditions see http://qt.digia.com/licensing. For further information
15 ** use the contact form at http://qt.digia.com/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 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file. Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Digia gives you certain additional
26 ** rights. These rights are described in the Digia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** GNU General Public License Usage
30 ** Alternatively, this file may be used under the terms of the GNU
31 ** General Public License version 3.0 as published by the Free Software
32 ** Foundation and appearing in the file LICENSE.GPL included in the
33 ** packaging of this file. Please review the following information to
34 ** ensure the GNU General Public License version 3.0 requirements will be
35 ** met: http://www.gnu.org/copyleft/gpl.html.
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41 
42 #include "qicdengine.h"
43 #include "qnetworksession_impl.h"
44 
45 #include <wlancond.h>
46 #include <wlan-utils.h>
47 #include <iapconf.h>
48 #include <iapmonitor.h>
49 
50 #ifndef QT_NO_BEARERMANAGEMENT
51 
53 
55 : service_attrs(0), network_attrs(0)
56 {
57 }
58 
60 {
61 }
62 
64 {
65  QMutexLocker locker(&mutex);
66 
67  return iap_type;
68 }
69 
70 /******************************************************************************/
72 /******************************************************************************/
73 
74 /* The IapAddTimer is a helper class that makes sure we update
75  * the configuration only after all db additions to certain
76  * iap are finished (after a certain timeout)
77  */
78 class _IapAddTimer : public QObject
79 {
80  Q_OBJECT
81 
82 public:
85  {
86  if (timer.isActive()) {
87  QObject::disconnect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
88  timer.stop();
89  }
90  }
91 
92  void add(QString& iap_id, QIcdEngine *d);
93 
97 
98 public Q_SLOTS:
99  void timeout();
100 };
101 
102 
104 {
105  iap_id = id;
106  d = d_ptr;
107 
108  if (timer.isActive()) {
109  QObject::disconnect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
110  timer.stop();
111  }
112  timer.setSingleShot(true);
113  QObject::connect(&timer, SIGNAL(timeout()), this, SLOT(timeout()));
114  timer.start(1500);
115 }
116 
117 
119 {
120  d->addConfiguration(iap_id);
121 }
122 
123 
124 class IapAddTimer {
126 
127 public:
130 
131  void add(QString& iap_id, QIcdEngine *d);
132  void del(QString& iap_id);
133  void removeAll();
134 };
135 
136 
138 {
139  QHashIterator<QString, _IapAddTimer* > i(timers);
140  while (i.hasNext()) {
141  i.next();
142  _IapAddTimer *t = i.value();
143  delete t;
144  }
145  timers.clear();
146 }
147 
148 
150 {
151  if (timers.contains(iap_id)) {
152  _IapAddTimer *iap = timers.value(iap_id);
153  iap->add(iap_id, d);
154  } else {
155  _IapAddTimer *iap = new _IapAddTimer;
156  iap->add(iap_id, d);
157  timers.insert(iap_id, iap);
158  }
159 }
160 
162 {
163  if (timers.contains(iap_id)) {
164  _IapAddTimer *iap = timers.take(iap_id);
165  delete iap;
166  }
167 }
168 
169 /******************************************************************************/
171 /******************************************************************************/
172 
174 {
175 public:
176  IapMonitor() : first_call(true) { }
177 
178  void setup(QIcdEngine *d);
179  void cleanup();
180 
181 protected:
182  void iapAdded(const QString &iapId);
183  void iapRemoved(const QString &iapId);
184 
185 private:
187 
190 };
191 
193 {
194  if (first_call) {
195  d = d_ptr;
196  first_call = false;
197  }
198 }
199 
200 
202 {
203  if (!first_call) {
204  timers.removeAll();
205  first_call = true;
206  }
207 }
208 
209 
210 void IapMonitor::iapAdded(const QString &iap_id)
211 {
212  /* We cannot know when the IAP is fully added to db, so a timer is
213  * installed instead. When the timer expires we hope that IAP is added ok.
214  */
215  QString id = iap_id;
216  timers.add(id, d);
217 }
218 
219 
220 void IapMonitor::iapRemoved(const QString &iap_id)
221 {
222  QString id = iap_id;
223  d->deleteConfiguration(id);
224 }
225 
226 
227 /******************************************************************************/
229 /******************************************************************************/
230 
232 : QBearerEngine(parent), iapMonitor(0), m_dbusInterface(0), m_icdServiceWatcher(0),
233  firstUpdate(true), m_scanGoingOn(false)
234 {
235 }
236 
238 {
239  cleanup();
240  delete iapMonitor;
241 }
242 
243 QNetworkConfigurationManager::Capabilities QIcdEngine::capabilities() const
244 {
249 }
250 
252 {
253  if (m_dbusInterface)
254  return true;
255 
256  // Setup DBus Interface for ICD
257  m_dbusInterface = new QDBusInterface(ICD_DBUS_API_INTERFACE,
258  ICD_DBUS_API_PATH,
259  ICD_DBUS_API_INTERFACE,
261  this);
262 
263  if (!m_dbusInterface->isValid()) {
264  delete m_dbusInterface;
265  m_dbusInterface = 0;
266 
267  if (!m_icdServiceWatcher) {
268  m_icdServiceWatcher = new QDBusServiceWatcher(ICD_DBUS_API_INTERFACE,
271  this);
272 
273  connect(m_icdServiceWatcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)),
275  }
276 
277  return false;
278  }
279 
282 
283  /* Turn on IAP state monitoring */
285 
286  /* Turn on IAP add/remove monitoring */
287  iapMonitor = new IapMonitor;
288  iapMonitor->setup(this);
289 
290  /* We create a default configuration which is a pseudo config */
292  cpPriv->name = "UserChoice";
294  cpPriv->isValid = true;
295  cpPriv->id = OSSO_IAP_ANY;
298  cpPriv->roamingSupported = false;
299 
301  userChoiceConfigurations.insert(cpPriv->id, ptr);
302 
303  doRequestUpdate();
304 
306 
307  return true;
308 }
309 
311 {
312  QMutexLocker locker(&mutex);
313 
314  if (!ensureDBusConnection()) {
315  locker.unlock();
317  locker.relock();
318  }
319 }
320 
321 static inline QString network_attrs_to_security(uint network_attrs)
322 {
323  uint cap = 0;
324  nwattr2cap(network_attrs, &cap); /* from libicd-network-wlan-dev.h */
325  if (cap & WLANCOND_OPEN)
326  return "NONE";
327  else if (cap & WLANCOND_WEP)
328  return "WEP";
329  else if (cap & WLANCOND_WPA_PSK)
330  return "WPA_PSK";
331  else if (cap & WLANCOND_WPA_EAP)
332  return "WPA_EAP";
333  return "";
334 }
335 
336 
337 struct SSIDInfo {
340 };
341 
342 
344 {
345  QMutexLocker locker(&mutex);
346 
347  /* Called when IAPs are deleted in db, in this case we do not scan
348  * or read all the IAPs from db because it might take too much power
349  * (multiple applications would need to scan and read all IAPs from db)
350  */
352  if (ptr) {
353 #ifdef BEARER_MANAGEMENT_DEBUG
354  qDebug() << "IAP" << iap_id << "was removed from storage.";
355 #endif
356 
357  locker.unlock();
359  } else {
360 #ifdef BEARER_MANAGEMENT_DEBUG
361  qDebug("IAP: %s, already missing from the known list", iap_id.toAscii().data());
362 #endif
363  }
364 }
365 
366 
367 static quint32 getNetworkAttrs(bool is_iap_id,
368  const QString &iap_id,
369  const QString &iap_type,
370  QString security_method)
371 {
372  guint network_attr = 0;
373  dbus_uint32_t cap = 0;
374 
375  if (iap_type == "WLAN_INFRA")
376  cap |= WLANCOND_INFRA;
377  else if (iap_type == "WLAN_ADHOC")
378  cap |= WLANCOND_ADHOC;
379 
380  if (security_method.isEmpty() && (cap & (WLANCOND_INFRA | WLANCOND_ADHOC))) {
381  Maemo::IAPConf saved_ap(iap_id);
382  security_method = saved_ap.value("wlan_security").toString();
383  }
384 
385  if (!security_method.isEmpty()) {
386  if (security_method == "WEP")
387  cap |= WLANCOND_WEP;
388  else if (security_method == "WPA_PSK")
389  cap |= WLANCOND_WPA_PSK;
390  else if (security_method == "WPA_EAP")
391  cap |= WLANCOND_WPA_EAP;
392  else if (security_method == "NONE")
393  cap |= WLANCOND_OPEN;
394 
395  if (cap & (WLANCOND_WPA_PSK | WLANCOND_WPA_EAP)) {
396  Maemo::IAPConf saved_iap(iap_id);
397  bool wpa2_only = saved_iap.value("EAP_wpa2_only_mode").toBool();
398  if (wpa2_only) {
399  cap |= WLANCOND_WPA2;
400  }
401  }
402  }
403 
404  cap2nwattr(cap, &network_attr);
405  if (is_iap_id)
406  network_attr |= ICD_NW_ATTR_IAPNAME;
407 
408  return quint32(network_attr);
409 }
410 
411 
413 {
414  // Note: When new IAP is created, this function gets called multiple times
415  // in a row.
416  // For example: Empty type & name for WLAN was stored into newly
417  // created IAP data in gconf when this function gets
418  // called for the first time.
419  // WLAN type & name are updated into IAP data in gconf
420  // as soon as WLAN connection is up and running.
421  // => And this function gets called again.
422 
423  QMutexLocker locker(&mutex);
424 
425  if (!accessPointConfigurations.contains(iap_id)) {
426  Maemo::IAPConf saved_iap(iap_id);
427  QString iap_type = saved_iap.value("type").toString();
428  QString iap_name = saved_iap.value("name").toString();
429  QByteArray ssid = saved_iap.value("wlan_ssid").toByteArray();
430  if (!iap_type.isEmpty() && !iap_name.isEmpty()) {
431  // Check if new IAP is actually Undefined WLAN configuration
432  // Note: SSID is used as an iap id for Undefined WLAN configurations
433  // => configuration must be searched using SSID
434  if (!ssid.isEmpty() && accessPointConfigurations.contains(ssid)) {
436  if (ptr) {
437  ptr->mutex.lock();
438  ptr->id = iap_id;
439  toIcdConfig(ptr)->iap_type = iap_type;
440  ptr->bearerType = bearerTypeFromIapType(iap_type);
441  toIcdConfig(ptr)->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
442  toIcdConfig(ptr)->network_id = ssid;
443  toIcdConfig(ptr)->service_id = saved_iap.value("service_id").toString();
444  toIcdConfig(ptr)->service_type = saved_iap.value("service_type").toString();
445  if (m_onlineIapId == iap_id) {
447  } else {
449  }
450  ptr->mutex.unlock();
451  accessPointConfigurations.insert(iap_id, ptr);
452 
453  locker.unlock();
455  locker.relock();
456  }
457  } else {
459  cpPriv->name = saved_iap.value("name").toString();
460  if (cpPriv->name.isEmpty())
461  cpPriv->name = iap_id;
462  cpPriv->isValid = true;
463  cpPriv->id = iap_id;
464  cpPriv->iap_type = iap_type;
465  cpPriv->bearerType = bearerTypeFromIapType(iap_type);
466  cpPriv->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
467  cpPriv->service_id = saved_iap.value("service_id").toString();
468  cpPriv->service_type = saved_iap.value("service_type").toString();
469  if (iap_type.startsWith(QLatin1String("WLAN"))) {
470  QByteArray ssid = saved_iap.value("wlan_ssid").toByteArray();
471  if (ssid.isEmpty()) {
472  qWarning() << "Cannot get ssid for" << iap_id;
473  }
474  cpPriv->network_id = ssid;
475  }
477  if (m_onlineIapId == iap_id) {
479  } else {
481  }
482 
484  accessPointConfigurations.insert(iap_id, ptr);
485 
486 #ifdef BEARER_MANAGEMENT_DEBUG
487  qDebug("IAP: %s, name: %s, added to known list", iap_id.toAscii().data(), cpPriv->name.toAscii().data());
488 #endif
489  locker.unlock();
491  locker.relock();
492  }
493  } else {
494  qWarning("IAP %s does not have \"type\" or \"name\" fields defined, skipping this IAP.", iap_id.toAscii().data());
495  }
496  } else {
497 #ifdef BEARER_MANAGEMENT_DEBUG
498  qDebug() << "IAP" << iap_id << "already in db.";
499 #endif
500 
501  /* Check if the data in db changed and update configuration accordingly
502  */
504  if (ptr) {
505  Maemo::IAPConf changed_iap(iap_id);
506  QString iap_type = changed_iap.value("type").toString();
507  bool update_needed = false; /* if IAP type or ssid changed, we need to change the state */
508 
509  QMutexLocker configLocker(&ptr->mutex);
510 
511  toIcdConfig(ptr)->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
512  toIcdConfig(ptr)->service_id = changed_iap.value("service_id").toString();
513  toIcdConfig(ptr)->service_type = changed_iap.value("service_type").toString();
514 
515  if (!iap_type.isEmpty()) {
516  ptr->name = changed_iap.value("name").toString();
517  if (ptr->name.isEmpty())
518  ptr->name = iap_id;
519  ptr->isValid = true;
520  if (toIcdConfig(ptr)->iap_type != iap_type) {
521  toIcdConfig(ptr)->iap_type = iap_type;
522  ptr->bearerType = bearerTypeFromIapType(iap_type);
523  update_needed = true;
524  }
525  if (iap_type.startsWith(QLatin1String("WLAN"))) {
526  QByteArray ssid = changed_iap.value("wlan_ssid").toByteArray();
527  if (ssid.isEmpty()) {
528  qWarning() << "Cannot get ssid for" << iap_id;
529  }
530  if (toIcdConfig(ptr)->network_id != ssid) {
531  toIcdConfig(ptr)->network_id = ssid;
532  update_needed = true;
533  }
534  }
535  }
536 
537  if (update_needed) {
539  if (m_onlineIapId == iap_id) {
542 
543  configLocker.unlock();
544  locker.unlock();
546  locker.relock();
547  }
548  } else if (ptr->state < QNetworkConfiguration::Defined) {
550 
551  configLocker.unlock();
552  locker.unlock();
554  locker.relock();
555  }
556  }
557  } else {
558  qWarning("Cannot find IAP %s from current configuration although it should be there.", iap_id.toAscii().data());
559  }
560  }
561 }
562 
564 {
565  /* Contains all known iap_ids from storage */
566  QList<QString> knownConfigs = accessPointConfigurations.keys();
567 
568  /* Contains all known WLAN network ids (like ssid) from storage */
569  QMultiHash<QByteArray, SSIDInfo* > notDiscoveredWLANConfigs;
570 
571  QList<QString> all_iaps;
572  Maemo::IAPConf::getAll(all_iaps);
573 
574  foreach (const QString &iap_id, all_iaps) {
575  QByteArray ssid;
576 
577  Maemo::IAPConf saved_ap(iap_id);
578  bool is_temporary = saved_ap.value("temporary").toBool();
579  if (is_temporary) {
580 #ifdef BEARER_MANAGEMENT_DEBUG
581  qDebug() << "IAP" << iap_id << "is temporary, skipping it.";
582 #endif
583  continue;
584  }
585 
586  QString iap_type = saved_ap.value("type").toString();
587  if (iap_type.startsWith(QLatin1String("WLAN"))) {
588  ssid = saved_ap.value("wlan_ssid").toByteArray();
589  if (ssid.isEmpty())
590  continue;
591 
592  QString security_method = saved_ap.value("wlan_security").toString();
593  SSIDInfo *info = new SSIDInfo;
594  info->iap_id = iap_id;
595  info->wlan_security = security_method;
596  notDiscoveredWLANConfigs.insert(ssid, info);
597  } else if (iap_type.isEmpty()) {
598  continue;
599  } else {
600 #ifdef BEARER_MANAGEMENT_DEBUG
601  qDebug() << "IAP" << iap_id << "network type is" << iap_type;
602 #endif
603  ssid.clear();
604  }
605 
606  if (!accessPointConfigurations.contains(iap_id)) {
608 
609  cpPriv->name = saved_ap.value("name").toString();
610  if (cpPriv->name.isEmpty()) {
611  if (!ssid.isEmpty() && ssid.size() > 0)
612  cpPriv->name = ssid.data();
613  else
614  cpPriv->name = iap_id;
615  }
616  cpPriv->isValid = true;
617  cpPriv->id = iap_id;
618  cpPriv->network_id = ssid;
619  cpPriv->network_attrs = getNetworkAttrs(true, iap_id, iap_type, QString());
620  cpPriv->iap_type = iap_type;
621  cpPriv->bearerType = bearerTypeFromIapType(iap_type);
622  cpPriv->service_id = saved_ap.value("service_id").toString();
623  cpPriv->service_type = saved_ap.value("service_type").toString();
626 
628  accessPointConfigurations.insert(iap_id, ptr);
629 
630  mutex.unlock();
632  mutex.lock();
633 
634 #ifdef BEARER_MANAGEMENT_DEBUG
635  qDebug("IAP: %s, name: %s, ssid: %s, added to known list",
636  iap_id.toAscii().data(), ptr->name.toAscii().data(),
637  !ssid.isEmpty() ? ssid.data() : "-");
638 #endif
639  } else {
640  knownConfigs.removeOne(iap_id);
641 #ifdef BEARER_MANAGEMENT_DEBUG
642  qDebug("IAP: %s, ssid: %s, already exists in the known list",
643  iap_id.toAscii().data(), !ssid.isEmpty() ? ssid.data() : "-");
644 #endif
645  }
646  }
647 
648  /* This is skipped in the first update as scanned size is zero */
649  if (!scanned.isEmpty()) {
650  for (int i=0; i<scanned.size(); ++i) {
651  const Maemo::IcdScanResult ap = scanned.at(i);
652 
653  if (ap.scan.network_attrs & ICD_NW_ATTR_IAPNAME) {
654  /* The network_id is IAP id, so the IAP is a known one */
655  QString iapid = ap.scan.network_id.data();
657  if (ptr) {
658  bool changed = false;
659 
660  ptr->mutex.lock();
661 
662  if (!ptr->isValid) {
663  ptr->isValid = true;
664  changed = true;
665  }
666 
667  /* If this config is the current active one, we do not set it
668  * to discovered.
669  */
673  changed = true;
674  }
675 
680 
681 #ifdef BEARER_MANAGEMENT_DEBUG
682  qDebug("IAP: %s, ssid: %s, discovered",
683  iapid.toAscii().data(), toIcdConfig(ptr)->network_id.data());
684 #endif
685 
686  ptr->mutex.unlock();
687 
688  if (changed) {
689  mutex.unlock();
691  mutex.lock();
692  }
693 
694  if (!ap.scan.network_type.startsWith(QLatin1String("WLAN")))
695  continue; // not a wlan AP
696 
697  /* Remove scanned AP from discovered WLAN configurations so that we can
698  * emit configurationRemoved signal later
699  */
700  ptr->mutex.lock();
701  QList<SSIDInfo* > known_iaps = notDiscoveredWLANConfigs.values(toIcdConfig(ptr)->network_id);
702 rescan_list:
703  if (!known_iaps.isEmpty()) {
704  for (int k=0; k<known_iaps.size(); ++k) {
705  SSIDInfo *iap = known_iaps.at(k);
706 
707  if (iap->wlan_security ==
709  /* Remove IAP from the list */
710  notDiscoveredWLANConfigs.remove(toIcdConfig(ptr)->network_id, iap);
711 #ifdef BEARER_MANAGEMENT_DEBUG
712  qDebug() << "Removed IAP" << iap->iap_id << "from unknown config";
713 #endif
714  known_iaps.removeAt(k);
715  delete iap;
716  goto rescan_list;
717  }
718  }
719  }
720  ptr->mutex.unlock();
721  }
722  } else {
723  /* Non saved access point data */
724  QByteArray scanned_ssid = ap.scan.network_id;
725  if (!accessPointConfigurations.contains(scanned_ssid)) {
727  QString hrs = scanned_ssid.data();
728 
729  cpPriv->name = ap.network_name.isEmpty() ? hrs : ap.network_name;
730  cpPriv->isValid = true;
731  cpPriv->id = scanned_ssid.data(); // Note: id is now ssid, it should be set to IAP id if the IAP is saved
732  cpPriv->network_id = scanned_ssid;
733  cpPriv->iap_type = ap.scan.network_type;
734  cpPriv->bearerType = bearerTypeFromIapType(cpPriv->iap_type);
735  cpPriv->network_attrs = ap.scan.network_attrs;
736  cpPriv->service_id = ap.scan.service_id;
737  cpPriv->service_type = ap.scan.service_type;
738  cpPriv->service_attrs = ap.scan.service_attrs;
739 
742 
743 #ifdef BEARER_MANAGEMENT_DEBUG
744  qDebug() << "IAP with network id" << cpPriv->id << "was found in the scan.";
745 #endif
746 
748  accessPointConfigurations.insert(ptr->id, ptr);
749 
750  mutex.unlock();
752  mutex.lock();
753  } else {
754  knownConfigs.removeOne(scanned_ssid);
755  }
756  }
757  }
758  }
759 
760  if (!firstUpdate) {
761  // Update Defined status to all defined WLAN IAPs which
762  // could not be found when access points were scanned
763  QHashIterator<QByteArray, SSIDInfo* > i(notDiscoveredWLANConfigs);
764  while (i.hasNext()) {
765  i.next();
766  SSIDInfo *iap = i.value();
767  QString iap_id = iap->iap_id;
768  //qDebug() << i.key() << ": " << iap_id;
769 
771  if (ptr) {
772  QMutexLocker configLocker(&ptr->mutex);
773 
774  // WLAN AccessPoint configuration could not be Discovered
775  // => Make sure that configuration state is Defined
778 
779  configLocker.unlock();
780  mutex.unlock();
782  mutex.lock();
783  }
784  }
785  }
786 
787  /* Remove non existing iaps since last update */
788  foreach (const QString &oldIface, knownConfigs) {
790  if (ptr) {
791  mutex.unlock();
793  mutex.lock();
794  //if we would have SNAP support we would have to remove the references
795  //from existing ServiceNetworks to the removed access point configuration
796  }
797  }
798  }
799 
800  QMutableHashIterator<QByteArray, SSIDInfo* > i(notDiscoveredWLANConfigs);
801  while (i.hasNext()) {
802  i.next();
803  SSIDInfo *iap = i.value();
804  delete iap;
805  i.remove();
806  }
807 
808  if (!firstUpdate) {
809  mutex.unlock();
811  mutex.lock();
812  }
813 
814  if (firstUpdate)
815  firstUpdate = false;
816 }
817 
819 {
820  QMutexLocker locker(&mutex);
821 
822  if (!ensureDBusConnection())
824 
825  // Here we just return [ANY] request to icd and let the icd decide which IAP to connect.
826  return userChoiceConfigurations.value(OSSO_IAP_ANY);
827 }
828 
830 {
831  // Start listening ICD_DBUS_API_STATE_SIG signals
832  m_dbusInterface->connection().connect(ICD_DBUS_API_INTERFACE,
833  ICD_DBUS_API_PATH,
834  ICD_DBUS_API_INTERFACE,
835  ICD_DBUS_API_STATE_SIG,
837 }
838 
840 {
841  /* Instead of requesting ICD status asynchronously, we ask it synchronously.
842  * It ensures that we always get right icd status BEFORE initialize() ends.
843  * If not, initialize() might end before we got icd status and
844  * QNetworkConfigurationManager::updateConfigurations()
845  * call from user might also end before receiving icd status.
846  * In such case, we come up to a bug:
847  * QNetworkConfigurationManagerPrivate::isOnline() will be false even
848  * if we are connected.
849  */
850  Maemo::Icd icd;
851  QList<Maemo::IcdStateResult> state_results;
853 
854  if (icd.state(state_results) && !state_results.isEmpty()) {
855 
856  if (!(state_results.first().params.network_attrs == 0 &&
857  state_results.first().params.network_id.isEmpty())) {
858 
859  switch (state_results.first().state) {
860  case ICD_STATE_CONNECTED:
861  m_onlineIapId = state_results.first().params.network_id;
862 
864  if (ptr) {
865  QMutexLocker configLocker(&ptr->mutex);
867  configLocker.unlock();
868 
869  mutex.unlock();
871  mutex.lock();
872  }
873  break;
874  default:
875  break;
876  }
877  }
878  }
879 }
880 
882 {
883  QMutexLocker locker(&mutex);
884 
885  QList<QVariant> arguments = msg.arguments();
886  if (arguments[1].toUInt() != 0 || arguments.count() < 8) {
887  return;
888  }
889 
890  QString iapid = arguments[5].toByteArray().data();
891  uint icd_connection_state = arguments[7].toUInt();
892 
893  switch (icd_connection_state) {
894  case ICD_STATE_CONNECTED:
895  {
897  if (ptr) {
898  QMutexLocker configLocker(&ptr->mutex);
899 
901  if (ptr->state != QNetworkConfiguration::Active) {
903 
904  configLocker.unlock();
905  locker.unlock();
907  locker.relock();
908 
909  m_onlineIapId = iapid;
910  }
911  } else {
912  // This gets called when new WLAN IAP is created using Connection dialog
913  // At this point Undefined WLAN configuration has SSID as iap id
914  // => Because of that configuration can not be found from
915  // accessPointConfigurations using correct iap id
916  m_onlineIapId = iapid;
917  }
918  break;
919  }
920  case ICD_STATE_DISCONNECTED:
921  {
923  if (ptr) {
924  QMutexLocker configLocker(&ptr->mutex);
925 
927  if (ptr->state == QNetworkConfiguration::Active) {
929 
930  configLocker.unlock();
931  locker.unlock();
932  emit iapStateChanged(iapid, icd_connection_state);
934  locker.relock();
935 
936  // Note: If ICD switches used IAP from one to another:
937  // 1) new IAP is reported to be online first
938  // 2) old IAP is reported to be offline then
939  // => Device can be reported to be offline only
940  // if last known online IAP is reported to be disconnected
941  if (iapid == m_onlineIapId) {
942  // It's known that there is only one global ICD connection
943  // => Because ICD state was reported to be DISCONNECTED, Device is offline
945  }
946  }
947  } else {
948  // Disconnected IAP was not found from accessPointConfigurations
949  // => Reason: Online IAP was removed which resulted ICD to disconnect
950  if (iapid == m_onlineIapId) {
951  // It's known that there is only one global ICD connection
952  // => Because ICD state was reported to be DISCONNECTED, Device is offline
954  }
955  }
956  break;
957  }
958  default:
959  break;
960  }
961 
962  locker.unlock();
963  emit iapStateChanged(iapid, icd_connection_state);
964  locker.relock();
965 }
966 
967 void QIcdEngine::icdServiceOwnerChanged(const QString &serviceName, const QString &oldOwner,
968  const QString &newOwner)
969 {
970  Q_UNUSED(serviceName);
971  Q_UNUSED(oldOwner);
972 
973  QMutexLocker locker(&mutex);
974 
975  if (newOwner.isEmpty()) {
976  // Disconnected from ICD, remove all configurations
977  cleanup();
978  delete iapMonitor;
979  iapMonitor = 0;
980  delete m_dbusInterface;
981  m_dbusInterface = 0;
982 
983  QMutableHashIterator<QString, QNetworkConfigurationPrivatePointer> i(accessPointConfigurations);
984  while (i.hasNext()) {
985  i.next();
986 
988  i.remove();
989 
990  locker.unlock();
992  locker.relock();
993  }
994 
995  userChoiceConfigurations.clear();
996  } else {
997  // Connected to ICD ensure connection.
999  }
1000 }
1001 
1003 {
1004  QMutexLocker locker(&mutex);
1005 
1006  if (!ensureDBusConnection()) {
1007  locker.unlock();
1009  locker.relock();
1010  return;
1011  }
1012 
1013  if (m_scanGoingOn)
1014  return;
1015 
1016  m_scanGoingOn = true;
1017 
1018  m_dbusInterface->connection().connect(ICD_DBUS_API_INTERFACE,
1019  ICD_DBUS_API_PATH,
1020  ICD_DBUS_API_INTERFACE,
1021  ICD_DBUS_API_SCAN_SIG,
1023 
1024  QDBusMessage msg = m_dbusInterface->call(ICD_DBUS_API_SCAN_REQ,
1025  (uint)ICD_SCAN_REQUEST_ACTIVE);
1028 }
1029 
1031 {
1032  if (!ensureDBusConnection())
1033  return;
1034 
1035  if (!m_scanGoingOn)
1036  return;
1037 
1038  m_scanGoingOn = false;
1039 
1040  if (m_scanTimer.isActive())
1041  m_scanTimer.stop();
1042 
1043  m_dbusInterface->connection().disconnect(ICD_DBUS_API_INTERFACE,
1044  ICD_DBUS_API_PATH,
1045  ICD_DBUS_API_INTERFACE,
1046  ICD_DBUS_API_SCAN_SIG,
1048 
1049  // Stop scanning rounds by calling ICD_DBUS_API_SCAN_CANCEL
1050  // <=> If ICD_DBUS_API_SCAN_CANCEL is not called, new scanning round will
1051  // be started after the module scan timeout.
1052  m_dbusInterface->call(ICD_DBUS_API_SCAN_CANCEL);
1053 }
1054 
1056 {
1057  QMutexLocker locker(&mutex);
1058 
1061  m_scanResult.clear();
1062 }
1063 
1065 {
1066  QMutexLocker locker(&mutex);
1067 
1068  QList<QVariant> arguments = msg.arguments();
1069  uint icd_scan_status = arguments.takeFirst().toUInt();
1070  if (icd_scan_status == ICD_SCAN_COMPLETE) {
1071  m_typesToBeScanned.removeOne(arguments[6].toString());
1072  if (!m_typesToBeScanned.count()) {
1073  locker.unlock();
1075  locker.relock();
1076  }
1077  } else {
1078  Maemo::IcdScanResult scanResult;
1079  scanResult.status = icd_scan_status;
1080  scanResult.timestamp = arguments.takeFirst().toUInt();
1081  scanResult.scan.service_type = arguments.takeFirst().toString();
1082  scanResult.service_name = arguments.takeFirst().toString();
1083  scanResult.scan.service_attrs = arguments.takeFirst().toUInt();
1084  scanResult.scan.service_id = arguments.takeFirst().toString();
1085  scanResult.service_priority = arguments.takeFirst().toInt();
1086  scanResult.scan.network_type = arguments.takeFirst().toString();
1087  scanResult.network_name = arguments.takeFirst().toString();
1088  scanResult.scan.network_attrs = arguments.takeFirst().toUInt();
1089  scanResult.scan.network_id = arguments.takeFirst().toByteArray();
1090  scanResult.network_priority = arguments.takeFirst().toInt();
1091  scanResult.signal_strength = arguments.takeFirst().toInt();
1092  scanResult.station_id = arguments.takeFirst().toString();
1093  scanResult.signal_dB = arguments.takeFirst().toInt();
1094 
1095  m_scanResult.append(scanResult);
1096  }
1097 }
1098 
1100 {
1101  if (m_scanGoingOn) {
1102  m_scanTimer.stop();
1103  m_dbusInterface->call(ICD_DBUS_API_SCAN_CANCEL);
1104  }
1105  if (iapMonitor)
1106  iapMonitor->cleanup();
1107 }
1108 
1110 {
1111  QMutexLocker locker(&mutex);
1112 
1113  return accessPointConfigurations.contains(id) ||
1114  snapConfigurations.contains(id) ||
1115  userChoiceConfigurations.contains(id);
1116 }
1117 
1119 {
1120  return new QNetworkSessionPrivateImpl(this);
1121 }
1122 
1123 #include "qicdengine.moc"
1124 
1126 
1127 #endif // QT_NO_BEARERMANAGEMENT
The QMultiHash class is a convenience QHash subclass that provides multi-valued hashes.
Definition: qcontainerfwd.h:58
double d
Definition: qnumeric_p.h:62
void setSingleShot(bool singleShot)
Definition: qtimer.h:108
QList< Maemo::IcdScanResult > m_scanResult
Definition: qicdengine.h:167
static mach_timebase_info_data_t info
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
QTimer timer
Definition: qicdengine.cpp:95
void lock()
Locks the mutex.
Definition: qmutex.cpp:151
char * data()
Returns a pointer to the data stored in the byte array.
Definition: qbytearray.h:429
QHash< QString, QNetworkConfigurationPrivatePointer > userChoiceConfigurations
#define add(aName)
void add(QString &iap_id, QIcdEngine *d)
Definition: qicdengine.cpp:103
void deleteConfiguration(const QString &iap_id)
Definition: qicdengine.cpp:343
QNetworkConfiguration::StateFlags state
QString network_name
Definition: maemo_icd.h:80
bool isValid() const
Returns true if this is a valid reference to a remote object.
void addConfiguration(QString &iap_id)
Definition: qicdengine.cpp:412
void configurationChanged(QNetworkConfigurationPrivatePointer config)
QNetworkConfigurationManager::Capabilities capabilities() const
Definition: qicdengine.cpp:243
QDBusServiceWatcher * m_icdServiceWatcher
Definition: qicdengine.h:169
The QByteArray class provides an array of bytes.
Definition: qbytearray.h:135
void asyncUpdateConfigurationsSlot(QDBusMessage msg)
QString service_id
Definition: maemo_icd.h:69
QDBusConnection connection() const
Returns the connection this interface is assocated with.
#define SLOT(a)
Definition: qobjectdefs.h:226
void icdServiceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner)
Definition: qicdengine.cpp:967
struct CommonParams scan
Definition: maemo_icd.h:82
void unlock()
Unlocks this mutex locker.
Definition: qmutex.h:117
QByteArray network_id
Definition: maemo_icd.h:72
QString toString() const
Returns the variant as a QString if the variant has type() String , Bool , ByteArray ...
Definition: qvariant.cpp:2270
void updateCompleted()
bool first_call
Definition: qicdengine.cpp:186
bool startsWith(const QString &s, Qt::CaseSensitivity cs=Qt::CaseSensitive) const
Returns true if the string starts with s; otherwise returns false.
Definition: qstring.cpp:3734
The QDBusInterface class is a proxy for interfaces on remote objects.
void iapAdded(const QString &iapId)
Definition: qicdengine.cpp:210
bool toBool() const
Returns the variant as a bool if the variant has type() Bool.
Definition: qvariant.cpp:2691
static QDBusConnection systemBus()
Returns a QDBusConnection object opened with the system bus.
virtual QString bearerTypeName() const
Definition: qicdengine.cpp:63
int count(const T &t) const
Returns the number of occurrences of value in the list.
Definition: qlist.h:891
EventLoopTimerRef timer
#define Q_SLOTS
Definition: qobjectdefs.h:71
The QString class provides a Unicode character string.
Definition: qstring.h:83
The QHash class is a template class that provides a hash-table-based dictionary.
Definition: qdatastream.h:66
QString m_onlineIapId
Definition: qicdengine.h:165
Q_INVOKABLE void initialize()
Definition: qicdengine.cpp:310
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
void add(QString &iap_id, QIcdEngine *d)
Definition: qicdengine.cpp:149
Q_INVOKABLE void requestUpdate()
QNetworkConfiguration::BearerType bearerType
QByteArray toByteArray() const
Returns the variant as a QByteArray if the variant has type() ByteArray or String (converted using QS...
Definition: qvariant.cpp:2383
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
int toInt(bool *ok=0) const
Returns the variant as an int if the variant has type() Int , Bool , ByteArray , Char ...
Definition: qvariant.cpp:2625
void relock()
Relocks an unlocked mutex locker.
Definition: qmutex.h:125
Q_CORE_EXPORT void qDebug(const char *,...)
static guint cap2nwattr(dbus_uint32_t cap, guint *nwattrs)
Definition: wlan-utils.h:91
bool removeOne(const T &t)
Removes the first occurrence of value in the list and returns true on success; otherwise returns fals...
Definition: qlist.h:796
#define SIGNAL(a)
Definition: qobjectdefs.h:227
bool firstUpdate
Definition: qicdengine.h:171
bool ensureDBusConnection()
Definition: qicdengine.cpp:251
static QString toString(Register *reg, int type, bool *ok=0)
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
void connectionStateSignalsSlot(QDBusMessage msg)
Definition: qicdengine.cpp:881
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
QList< QVariant > arguments() const
Returns the list of arguments that are going to be sent or were received from D-Bus.
QString iap_id
Definition: qicdengine.cpp:94
QHash< QString, QNetworkConfigurationPrivatePointer > accessPointConfigurations
void removeAll()
Definition: qicdengine.cpp:137
T takeFirst()
Removes the first item in the list and returns it.
Definition: qlist.h:489
static bool connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
Creates a connection of the given type from the signal in the sender object to the method in the rece...
Definition: qobject.cpp:2580
bool isEmpty() const
Returns true if the string has no characters; otherwise returns false.
Definition: qstring.h:704
void iapRemoved(const QString &iapId)
Definition: qicdengine.cpp:220
static QString network_attrs_to_security(uint network_attrs)
Definition: qicdengine.cpp:321
const T & at(int i) const
Returns the item at index position i in the list.
Definition: qlist.h:468
#define emit
Definition: qobjectdefs.h:76
QStringList m_typesToBeScanned
Definition: qicdengine.h:166
The QStringList class provides a list of strings.
Definition: qstringlist.h:66
void configurationAdded(QNetworkConfigurationPrivatePointer config)
Q_CORE_EXPORT void qWarning(const char *,...)
unsigned int uint
Definition: qglobal.h:996
QIcdEngine(QObject *parent=0)
Definition: qicdengine.cpp:231
The QLatin1String class provides a thin wrapper around an US-ASCII/Latin-1 encoded string literal...
Definition: qstring.h:654
bool isActive() const
Returns true if the timer is running (pending); otherwise returns false.
Definition: qtimer.h:69
void cleanup()
void iapStateChanged(const QString &iapid, uint icd_connection_state)
T value(int i) const
Returns the value at index position i in the list.
Definition: qlist.h:661
const T * ptr(const T &t)
QHash< QString, QNetworkConfigurationPrivatePointer > snapConfigurations
QDBusInterface * m_dbusInterface
Definition: qicdengine.h:163
void clear()
Removes all items from the list.
Definition: qlist.h:764
struct CommonParams params
Definition: maemo_icd.h:95
QString service_name
Definition: maemo_icd.h:78
void timeout()
Definition: qicdengine.cpp:118
IapAddTimer timers
Definition: qicdengine.cpp:189
void unlock()
Unlocks the mutex.
Definition: qmutex.cpp:296
QTimer m_scanTimer
Definition: qicdengine.h:164
#define Q_OBJECT
Definition: qobjectdefs.h:157
IapMonitor * iapMonitor
Definition: qicdengine.h:162
T & first()
Returns a reference to the first item in the list.
Definition: qlist.h:282
uint state(QString &service_type, uint service_attrs, QString &service_id, QString &network_type, uint network_attrs, QByteArray &network_id, IcdStateResult &state_result)
Definition: maemo_icd.cpp:798
QHash< Key, T >::iterator insert(const Key &key, const T &value)
Inserts a new item with the key and a value of value.
Definition: qhash.h:934
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
Disconnects signal in object sender from method in object receiver.
Definition: qobject.cpp:2895
#define ICD_SHORT_SCAN_TIMEOUT
Definition: maemo_icd.h:60
bool connect(const QString &service, const QString &path, const QString &interface, const QString &name, QObject *receiver, const char *slot)
Connects the signal specified by the service, path, interface and name parameters to the slot slot in...
void cancelAsyncConfigurationUpdate()
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
int remove(const Key &key, const T &value)
Removes all the items that have the key and the value value from the hash.
Definition: qhash.h:1006
QNetworkConfiguration::Purpose purpose
IcdNetworkConfigurationPrivate * toIcdConfig(QNetworkConfigurationPrivatePointer ptr)
Definition: qicdengine.h:92
QExplicitlySharedDataPointer< QNetworkConfigurationPrivate > QNetworkConfigurationPrivatePointer
bool hasIdentifier(const QString &id)
bool m_scanGoingOn
Definition: qicdengine.h:172
void finishAsyncConfigurationUpdate()
void cleanup()
Definition: qicdengine.cpp:201
void clear()
Clears the contents of the string and makes it empty.
Definition: qstring.h:723
QNetworkConfiguration::Type type
QList< T > values() const
Returns a list containing all the values in the hash, in an arbitrary order.
Definition: qhash.h:693
QNetworkConfigurationPrivatePointer defaultConfiguration()
Definition: qicdengine.cpp:818
uint toUInt(bool *ok=0) const
Returns the variant as an unsigned int if the variant has type() UInt , Bool , ByteArray ...
Definition: qvariant.cpp:2644
unsigned int quint32
Definition: qglobal.h:938
void startListeningStateSignalsForAllConnections()
Definition: qicdengine.cpp:829
int size() const
Returns the number of items in the list.
Definition: qlist.h:137
void configurationRemoved(QNetworkConfigurationPrivatePointer config)
QByteArray toAscii() const Q_REQUIRED_RESULT
Returns an 8-bit representation of the string as a QByteArray.
Definition: qstring.cpp:4014
static void getAll(QList< QString > &all_iaps, bool return_path=false)
Definition: iapconf.cpp:226
static void cleanup()
Definition: qpicture.cpp:1508
if(void) toggleToolbarShown
void setup(QIcdEngine *d)
Definition: qicdengine.cpp:192
QHash< QString, _IapAddTimer *> timers
Definition: qicdengine.cpp:125
int size() const
Returns the number of bytes in this byte array.
Definition: qbytearray.h:402
QIcdEngine * d
Definition: qicdengine.cpp:96
The QDBusMessage class represents one message sent or received over the D-Bus bus.
Definition: qdbusmessage.h:59
QString iap_id
Definition: qicdengine.cpp:338
bool isEmpty() const
Returns true if the byte array has size 0; otherwise returns false.
Definition: qbytearray.h:421
QNetworkSessionPrivate * createSessionBackend()
QString service_type
Definition: maemo_icd.h:67
QIcdEngine * d
Definition: qicdengine.cpp:188
The QTimer class provides repetitive and single-shot timers.
Definition: qtimer.h:56
The QDBusServiceWatcher class allows the user to watch for a bus service change.
void stop()
Stops the timer.
Definition: qtimer.cpp:284
bool disconnect(const QString &service, const QString &path, const QString &interface, const QString &name, QObject *receiver, const char *slot)
Disconnects the signal specified by the service, path, interface and name parameters from the slot sl...
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
Definition: qtimer.cpp:249
#define Q_UNUSED(x)
Indicates to the compiler that the parameter with the specified name is not used in the body of a fun...
Definition: qglobal.h:1729
void doRequestUpdate(QList< Maemo::IcdScanResult > scanned=QList< Maemo::IcdScanResult >())
Definition: qicdengine.cpp:563
static dbus_uint32_t nwattr2cap(guint nwattrs, dbus_uint32_t *cap)
Definition: wlan-utils.h:72
QString wlan_security
Definition: qicdengine.cpp:339
void getIcdInitialState()
Definition: qicdengine.cpp:839
void clear()
Clears the contents of the byte array and makes it empty.
static quint32 getNetworkAttrs(bool is_iap_id, const QString &iap_id, const QString &iap_type, QString security_method)
Definition: qicdengine.cpp:367
void del(QString &iap_id)
Definition: qicdengine.cpp:161
QVariant value(const QString &key) const
Definition: iapconf.cpp:215
QNetworkConfiguration::BearerType bearerTypeFromIapType(const QString &iapType)
Definition: qicdengine.h:58
static void setup()
Definition: qtextcodec.cpp:718
QDBusMessage call(const QString &method, const QVariant &arg1=QVariant(), const QVariant &arg2=QVariant(), const QVariant &arg3=QVariant(), const QVariant &arg4=QVariant(), const QVariant &arg5=QVariant(), const QVariant &arg6=QVariant(), const QVariant &arg7=QVariant(), const QVariant &arg8=QVariant())
Calls the method method on this interface and passes the parameters to this function to the method...
QString network_type
Definition: maemo_icd.h:70
void removeAt(int i)
Removes the item at index position i.
Definition: qlist.h:480