Qt 4.8
qnetworkconfigmanager_p.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 QtNetwork module 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 
43 #include "qbearerplugin_p.h"
44 
45 #include <QtCore/private/qfactoryloader_p.h>
46 
47 #include <QtCore/qdebug.h>
48 #include <QtCore/qtimer.h>
49 #include <QtCore/qstringlist.h>
50 #include <QtCore/qthread.h>
51 #include <QtCore/private/qcoreapplication_p.h>
52 
53 #ifndef QT_NO_BEARERMANAGEMENT
54 
56 
57 #ifndef QT_NO_LIBRARY
60 #endif
61 
63  : QObject(), pollTimer(0), bearerThread(0), mutex(QMutex::Recursive), forcedPolling(0), firstUpdate(true)
64 {
65  qRegisterMetaType<QNetworkConfiguration>("QNetworkConfiguration");
66  qRegisterMetaType<QNetworkConfigurationPrivatePointer>("QNetworkConfigurationPrivatePointer");
67 }
68 
70 {
71  //Two stage construction, because we only want to do this heavyweight work for the winner of the Q_GLOBAL_STATIC race.
72  bearerThread = new QThread();
73  bearerThread->moveToThread(QCoreApplicationPrivate::mainThread()); // because cleanup() is called in main thread context.
77 }
78 
80 {
81  QMutexLocker locker(&mutex);
82 
84  if (bearerThread)
85  bearerThread->quit();
86 }
87 
89 {
91  deleteLater();
92  if(thread->wait(5000))
93  delete thread;
94 }
95 
97 {
98  QMutexLocker locker(&mutex);
99 
100  foreach (QBearerEngine *engine, sessionEngines) {
102  if (ptr) {
103  QNetworkConfiguration config;
104  config.d = ptr;
105  return config;
106  }
107  }
108 
109  // Engines don't have a default configuration.
110 
111  // Return first active snap
113 
114  foreach (QBearerEngine *engine, sessionEngines) {
117 
118  QMutexLocker locker(&engine->mutex);
119 
120  for (it = engine->snapConfigurations.begin(),
121  end = engine->snapConfigurations.end(); it != end; ++it) {
123 
124  QMutexLocker configLocker(&ptr->mutex);
125 
127  QNetworkConfiguration config;
128  config.d = ptr;
129  return config;
130  } else if (!defaultConfiguration) {
132  defaultConfiguration = ptr;
133  }
134  }
135  }
136 
137  // No Active SNAPs return first Discovered SNAP.
138  if (defaultConfiguration) {
139  QNetworkConfiguration config;
140  config.d = defaultConfiguration;
141  return config;
142  }
143 
144  /*
145  No Active or Discovered SNAPs, find the perferred access point.
146  The following priority order is used:
147 
148  1. Active Ethernet
149  2. Active WLAN
150  3. Active Other
151  4. Discovered Ethernet
152  5. Discovered WLAN
153  6. Discovered Other
154  */
155 
156  foreach (QBearerEngine *engine, sessionEngines) {
159 
160  QMutexLocker locker(&engine->mutex);
161 
162  for (it = engine->accessPointConfigurations.begin(),
163  end = engine->accessPointConfigurations.end(); it != end; ++it) {
165 
166  QMutexLocker configLocker(&ptr->mutex);
168 
170  if (!defaultConfiguration) {
171  defaultConfiguration = ptr;
172  } else {
173  QMutexLocker defaultConfigLocker(&defaultConfiguration->mutex);
174 
175  if (defaultConfiguration->state == ptr->state) {
176  switch (defaultConfiguration->bearerType) {
178  // do nothing
179  break;
181  // Ethernet beats WLAN
182  defaultConfiguration = ptr;
183  break;
184  default:
185  // Ethernet and WLAN beats other
186  if (bearerType == QNetworkConfiguration::BearerEthernet ||
187  bearerType == QNetworkConfiguration::BearerWLAN) {
188  defaultConfiguration = ptr;
189  }
190  }
191  } else {
192  // active beats discovered
193  if ((defaultConfiguration->state & QNetworkConfiguration::Active) !=
195  defaultConfiguration = ptr;
196  }
197  }
198  }
199  }
200  }
201  }
202 
203  // No Active InternetAccessPoint return first Discovered InternetAccessPoint.
204  if (defaultConfiguration) {
205  QNetworkConfiguration config;
206  config.d = defaultConfiguration;
207  return config;
208  }
209 
210  return QNetworkConfiguration();
211 }
212 
214 {
216 
217  QMutexLocker locker(&mutex);
218 
219  foreach (QBearerEngine *engine, sessionEngines) {
222 
223  QMutexLocker locker(&engine->mutex);
224 
225  //find all InternetAccessPoints
226  for (it = engine->accessPointConfigurations.begin(),
227  end = engine->accessPointConfigurations.end(); it != end; ++it) {
229 
230  QMutexLocker configLocker(&ptr->mutex);
231 
232  if ((ptr->state & filter) == filter) {
234  pt.d = ptr;
235  result << pt;
236  }
237  }
238 
239  //find all service networks
240  for (it = engine->snapConfigurations.begin(),
241  end = engine->snapConfigurations.end(); it != end; ++it) {
243 
244  QMutexLocker configLocker(&ptr->mutex);
245 
246  if ((ptr->state & filter) == filter) {
248  pt.d = ptr;
249  result << pt;
250  }
251  }
252  }
253 
254  return result;
255 }
256 
258 {
260 
261  QMutexLocker locker(&mutex);
262 
263  foreach (QBearerEngine *engine, sessionEngines) {
264  QMutexLocker locker(&engine->mutex);
265 
266  if (engine->accessPointConfigurations.contains(identifier))
267  item.d = engine->accessPointConfigurations[identifier];
268  else if (engine->snapConfigurations.contains(identifier))
269  item.d = engine->snapConfigurations[identifier];
270  else if (engine->userChoiceConfigurations.contains(identifier))
271  item.d = engine->userChoiceConfigurations[identifier];
272  else
273  continue;
274 
275  return item;
276  }
277 
278  return item;
279 }
280 
282 {
283  QMutexLocker locker(&mutex);
284 
285  return !onlineConfigurations.isEmpty();
286 }
287 
288 QNetworkConfigurationManager::Capabilities QNetworkConfigurationManagerPrivate::capabilities() const
289 {
290  QMutexLocker locker(&mutex);
291 
292  QNetworkConfigurationManager::Capabilities capFlags;
293 
294  foreach (QBearerEngine *engine, sessionEngines)
295  capFlags |= engine->capabilities();
296 
297  return capFlags;
298 }
299 
301 {
302  QMutexLocker locker(&mutex);
303 
304  if (!firstUpdate) {
306  item.d = ptr;
307  emit configurationAdded(item);
308  }
309 
310  ptr->mutex.lock();
311  if (ptr->state == QNetworkConfiguration::Active) {
312  ptr->mutex.unlock();
314  if (!firstUpdate && onlineConfigurations.count() == 1)
315  emit onlineStateChanged(true);
316  } else {
317  ptr->mutex.unlock();
318  }
319 }
320 
322 {
323  QMutexLocker locker(&mutex);
324 
325  ptr->mutex.lock();
326  ptr->isValid = false;
327  ptr->mutex.unlock();
328 
329  if (!firstUpdate) {
331  item.d = ptr;
333  }
334 
337  emit onlineStateChanged(false);
338 }
339 
341 {
342  QMutexLocker locker(&mutex);
343 
344  if (!firstUpdate) {
346  item.d = ptr;
348  }
349 
350  bool previous = !onlineConfigurations.isEmpty();
351 
352  ptr->mutex.lock();
355  else
357  ptr->mutex.unlock();
358 
359  bool online = !onlineConfigurations.isEmpty();
360 
361  if (!firstUpdate && online != previous)
362  emit onlineStateChanged(online);
363 }
364 
366 {
367  QMutexLocker locker(&mutex);
368 
369  if (firstUpdate) {
370  if (qobject_cast<QBearerEngine *>(sender()))
371  return;
372 
373  updating = false;
374 
375 #ifndef QT_NO_LIBRARY
376  QBearerEngine *generic = 0;
377 
378  QFactoryLoader *l = loader();
379  foreach (const QString &key, l->keys()) {
381  if (plugin) {
382  QBearerEngine *engine = plugin->create(key);
383  if (!engine)
384  continue;
385 
386  if (key == QLatin1String("generic"))
387  generic = engine;
388  else
389  sessionEngines.append(engine);
390 
391  engine->moveToThread(bearerThread);
392 
393  connect(engine, SIGNAL(updateCompleted()),
394  this, SLOT(updateConfigurations()),
405  }
406  }
407 
408  if (generic)
409  sessionEngines.append(generic);
410 #endif // QT_NO_LIBRARY
411  }
412 
414  if (engine && !updatingEngines.isEmpty())
415  updatingEngines.remove(engine);
416 
417  if (updating && updatingEngines.isEmpty()) {
418  updating = false;
420  }
421 
422  if (engine && !pollingEngines.isEmpty()) {
423  pollingEngines.remove(engine);
424  if (pollingEngines.isEmpty())
425  startPolling();
426  }
427 
428  if (firstUpdate) {
429  firstUpdate = false;
430  QList<QBearerEngine*> enginesToInitialize = sessionEngines; //shallow copy the list in case it is modified when we unlock mutex
431  locker.unlock();
432  foreach (QBearerEngine* engine, enginesToInitialize) {
434  }
435  }
436 }
437 
439 {
440  QMutexLocker locker(&mutex);
441 
442  if (sessionEngines.isEmpty()) {
444  return;
445  }
446 
447  updating = true;
448 
449  foreach (QBearerEngine *engine, sessionEngines) {
450  updatingEngines.insert(engine);
451  QMetaObject::invokeMethod(engine, "requestUpdate");
452  }
453 }
454 
456 {
457  QMutexLocker locker(&mutex);
458 
459  return sessionEngines;
460 }
461 
463 {
464  QMutexLocker locker(&mutex);
465 
466  if(!pollTimer) {
467  pollTimer = new QTimer(this);
468  pollTimer->setInterval(10000);
469  pollTimer->setSingleShot(true);
470  connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollEngines()));
471  }
472 
473  if(pollTimer->isActive())
474  return;
475 
476  foreach (QBearerEngine *engine, sessionEngines) {
477  if (engine->requiresPolling() && (forcedPolling || engine->configurationsInUse())) {
478  pollTimer->start();
479  break;
480  }
481  }
482 }
483 
485 {
486  QMutexLocker locker(&mutex);
487 
488  foreach (QBearerEngine *engine, sessionEngines) {
489  if (engine->requiresPolling() && (forcedPolling || engine->configurationsInUse())) {
490  pollingEngines.insert(engine);
491  QMetaObject::invokeMethod(engine, "requestUpdate");
492  }
493  }
494 }
495 
497 {
498  QMutexLocker locker(&mutex);
499 
500  ++forcedPolling;
501 
502  if (forcedPolling == 1)
503  QMetaObject::invokeMethod(this, "startPolling");
504 }
505 
507 {
508  QMutexLocker locker(&mutex);
509 
510  --forcedPolling;
511 }
512 
514 
515 #endif // QT_NO_BEARERMANAGEMENT
BearerType
Specifies the type of bearer used by a configuration.
void setSingleShot(bool singleShot)
Definition: qtimer.h:108
QExplicitlySharedDataPointer< QNetworkConfigurationPrivate > d
#define QT_END_NAMESPACE
This macro expands to.
Definition: qglobal.h:90
void lock()
Locks the mutex.
Definition: qmutex.cpp:151
The QMutex class provides access serialization between threads.
Definition: qmutex.h:60
QHash< QString, QNetworkConfigurationPrivatePointer > userChoiceConfigurations
Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,(QBearerEngineFactoryInterface_iid, QLatin1String("/bearer"))) QNetworkConfigurationManagerPrivate
#define it(className, varName)
QNetworkConfiguration::StateFlags state
bool remove(const T &value)
Definition: qset.h:89
bool isEmpty() const
Definition: qset.h:77
#define SLOT(a)
Definition: qobjectdefs.h:226
void unlock()
Unlocks this mutex locker.
Definition: qmutex.h:117
QLatin1String(DBUS_INTERFACE_DBUS))) Q_GLOBAL_STATIC_WITH_ARGS(QString
T & value() const
Returns a modifiable reference to the current item&#39;s value.
Definition: qhash.h:348
The QString class provides a Unicode character string.
Definition: qstring.h:83
T * qobject_cast(QObject *object)
Definition: qobject.h:375
virtual QBearerEngine * create(const QString &key) const =0
The QObject class is the base class of all Qt objects.
Definition: qobject.h:111
void quit()
Tells the thread&#39;s event loop to exit with return code 0 (success).
Definition: qthread.cpp:614
QNetworkConfiguration::BearerType bearerType
bool isEmpty() const
Returns true if the list contains no items; otherwise returns false.
Definition: qlist.h:152
QObject * sender() const
Returns a pointer to the object that sent the signal, if called in a slot activated by a signal; othe...
Definition: qobject.cpp:2327
#define SIGNAL(a)
Definition: qobjectdefs.h:227
QNetworkConfiguration defaultConfiguration() const
void append(const T &t)
Inserts value at the end of the list.
Definition: qlist.h:507
QStringList keys() const
The QNetworkConfiguration class provides an abstraction of one or more access point configurations...
#define QT_BEGIN_NAMESPACE
This macro expands to.
Definition: qglobal.h:89
void onlineStateChanged(bool isOnline)
QHash< QString, QNetworkConfigurationPrivatePointer > accessPointConfigurations
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
#define emit
Definition: qobjectdefs.h:76
const_iterator insert(const T &value)
Definition: qset.h:179
QList< QNetworkConfiguration > allConfigurations(QNetworkConfiguration::StateFlags filter) const
bool isActive() const
Returns true if the timer is running (pending); otherwise returns false.
Definition: qtimer.h:69
void moveToThread(QThread *thread)
Changes the thread affinity for this object and its children.
Definition: qobject.cpp:1458
int count() const
Definition: qset.h:178
const T * ptr(const T &t)
QHash< QString, QNetworkConfigurationPrivatePointer > snapConfigurations
void configurationRemoved(const QNetworkConfiguration &config)
void unlock()
Unlocks the mutex.
Definition: qmutex.cpp:296
void setInterval(int msec)
Definition: qtimer.cpp:419
virtual bool requiresPolling() const
The QMutexLocker class is a convenience class that simplifies locking and unlocking mutexes...
Definition: qmutex.h:101
bool configurationsInUse() const
virtual QNetworkConfigurationManager::Capabilities capabilities() const =0
static QThread * mainThread()
void start(Priority=InheritPriority)
Begins execution of the thread by calling run().
QObject * instance(const QString &key) const
bool wait(unsigned long time=ULONG_MAX)
Blocks the thread until either of these conditions is met:
int key
The QHash::iterator class provides an STL-style non-const iterator for QHash and QMultiHash.
Definition: qhash.h:330
void configurationAdded(const QNetworkConfiguration &config)
QList< QBearerEngine * > engines() const
if(void) toggleToolbarShown
QFuture< void > filter(Sequence &sequence, FilterFunction filterFunction)
QFactoryLoader * l
void configurationChanged(const QNetworkConfiguration &config)
static bool invokeMethod(QObject *obj, const char *member, Qt::ConnectionType, QGenericReturnArgument ret, QGenericArgument val0=QGenericArgument(0), QGenericArgument val1=QGenericArgument(), QGenericArgument val2=QGenericArgument(), QGenericArgument val3=QGenericArgument(), QGenericArgument val4=QGenericArgument(), QGenericArgument val5=QGenericArgument(), QGenericArgument val6=QGenericArgument(), QGenericArgument val7=QGenericArgument(), QGenericArgument val8=QGenericArgument(), QGenericArgument val9=QGenericArgument())
Invokes the member (a signal or a slot name) on the object obj.
virtual QNetworkConfigurationPrivatePointer defaultConfiguration()=0
QThread * thread() const
Returns the thread in which the object lives.
Definition: qobject.cpp:1419
The QTimer class provides repetitive and single-shot timers.
Definition: qtimer.h:56
#define QBearerEngineFactoryInterface_iid
QNetworkConfiguration configurationFromIdentifier(const QString &identifier) const
static const KeyPair *const end
QNetworkConfigurationManager::Capabilities capabilities() const
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
Definition: qtimer.cpp:249
The QThread class provides a platform-independent way to manage threads.
Definition: qthread.h:59
Q_OUTOFLINE_TEMPLATE void qDeleteAll(ForwardIterator begin, ForwardIterator end)
Definition: qalgorithms.h:319
void deleteLater()
Schedules this object for deletion.
Definition: qobject.cpp:2145
The QList class is a template class that provides lists.
Definition: qdatastream.h:62