source: trunk/src/network/bearer/qnetworkconfigmanager_p.cpp@ 1168

Last change on this file since 1168 was 846, checked in by Dmitry A. Kuminov, 14 years ago

trunk: Merged in qt 4.7.2 sources from branches/vendor/nokia/qt.

File size: 16.2 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4** All rights reserved.
5** Contact: Nokia Corporation ([email protected])
6**
7** This file is part of the QtNetwork module of the Qt Toolkit.
8**
9** $QT_BEGIN_LICENSE:LGPL$
10** Commercial Usage
11** Licensees holding valid Qt Commercial licenses may use this file in
12** accordance with the Qt Commercial License Agreement provided with the
13** Software or, alternatively, in accordance with the terms contained in
14** a written agreement between you and Nokia.
15**
16** GNU Lesser General Public License Usage
17** Alternatively, this file may be used under the terms of the GNU Lesser
18** General Public License version 2.1 as published by the Free Software
19** Foundation and appearing in the file LICENSE.LGPL included in the
20** packaging of this file. Please review the following information to
21** ensure the GNU Lesser General Public License version 2.1 requirements
22** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
23**
24** In addition, as a special exception, Nokia gives you certain additional
25** rights. These rights are described in the Nokia Qt LGPL Exception
26** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you have questions regarding the use of this file, please contact
37** Nokia at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qnetworkconfigmanager_p.h"
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
55QT_BEGIN_NAMESPACE
56
57#ifndef QT_NO_LIBRARY
58Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader,
59 (QBearerEngineFactoryInterface_iid, QLatin1String("/bearer")))
60#endif
61
62QNetworkConfigurationManagerPrivate::QNetworkConfigurationManagerPrivate()
63: pollTimer(0), mutex(QMutex::Recursive), forcedPolling(0), firstUpdate(true)
64{
65 qRegisterMetaType<QNetworkConfiguration>("QNetworkConfiguration");
66 qRegisterMetaType<QNetworkConfigurationPrivatePointer>("QNetworkConfigurationPrivatePointer");
67}
68
69QNetworkConfigurationManagerPrivate::~QNetworkConfigurationManagerPrivate()
70{
71 QMutexLocker locker(&mutex);
72
73 qDeleteAll(sessionEngines);
74}
75
76QNetworkConfiguration QNetworkConfigurationManagerPrivate::defaultConfiguration()
77{
78 QMutexLocker locker(&mutex);
79
80 foreach (QBearerEngine *engine, sessionEngines) {
81 QNetworkConfigurationPrivatePointer ptr = engine->defaultConfiguration();
82
83 if (ptr) {
84 QNetworkConfiguration config;
85 config.d = ptr;
86 return config;
87 }
88 }
89
90 // Engines don't have a default configuration.
91
92 // Return first active snap
93 QNetworkConfigurationPrivatePointer defaultConfiguration;
94
95 foreach (QBearerEngine *engine, sessionEngines) {
96 QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator it;
97 QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator end;
98
99 QMutexLocker locker(&engine->mutex);
100
101 for (it = engine->snapConfigurations.begin(), end = engine->snapConfigurations.end();
102 it != end; ++it) {
103 QNetworkConfigurationPrivatePointer ptr = it.value();
104
105 QMutexLocker configLocker(&ptr->mutex);
106
107 if ((ptr->state & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) {
108 QNetworkConfiguration config;
109 config.d = ptr;
110 return config;
111 } else if (!defaultConfiguration) {
112 if ((ptr->state & QNetworkConfiguration::Discovered) ==
113 QNetworkConfiguration::Discovered) {
114 defaultConfiguration = ptr;
115 }
116 }
117 }
118 }
119
120 // No Active SNAPs return first Discovered SNAP.
121 if (defaultConfiguration) {
122 QNetworkConfiguration config;
123 config.d = defaultConfiguration;
124 return config;
125 }
126
127 /*
128 No Active or Discovered SNAPs, find the perferred access point.
129 The following priority order is used:
130
131 1. Active Ethernet
132 2. Active WLAN
133 3. Active Other
134 4. Discovered Ethernet
135 5. Discovered WLAN
136 6. Discovered Other
137 */
138
139 defaultConfiguration.reset();
140
141 foreach (QBearerEngine *engine, sessionEngines) {
142 QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator it;
143 QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator end;
144
145 QMutexLocker locker(&engine->mutex);
146
147 for (it = engine->accessPointConfigurations.begin(),
148 end = engine->accessPointConfigurations.end(); it != end; ++it) {
149 QNetworkConfigurationPrivatePointer ptr = it.value();
150
151 QMutexLocker configLocker(&ptr->mutex);
152 QNetworkConfiguration::BearerType bearerType = ptr->bearerType;
153
154 if ((ptr->state & QNetworkConfiguration::Discovered) ==
155 QNetworkConfiguration::Discovered) {
156 if (!defaultConfiguration) {
157 defaultConfiguration = ptr;
158 } else {
159 QMutexLocker defaultConfigLocker(&defaultConfiguration->mutex);
160
161 if (defaultConfiguration->state == ptr->state) {
162 switch (defaultConfiguration->bearerType) {
163 case QNetworkConfiguration::BearerEthernet:
164 // do nothing
165 break;
166 case QNetworkConfiguration::BearerWLAN:
167 // Ethernet beats WLAN
168 defaultConfiguration = ptr;
169 break;
170 default:
171 // Ethernet and WLAN beats other
172 if (bearerType == QNetworkConfiguration::BearerEthernet ||
173 bearerType == QNetworkConfiguration::BearerWLAN) {
174 defaultConfiguration = ptr;
175 }
176 }
177 } else {
178 // active beats discovered
179 if ((defaultConfiguration->state & QNetworkConfiguration::Active) !=
180 QNetworkConfiguration::Active) {
181 defaultConfiguration = ptr;
182 }
183 }
184 }
185 }
186 }
187 }
188
189 // No Active InternetAccessPoint return first Discovered InternetAccessPoint.
190 if (defaultConfiguration) {
191 QNetworkConfiguration config;
192 config.d = defaultConfiguration;
193 return config;
194 }
195
196 return QNetworkConfiguration();
197}
198
199QList<QNetworkConfiguration> QNetworkConfigurationManagerPrivate::allConfigurations(QNetworkConfiguration::StateFlags filter)
200{
201 QList<QNetworkConfiguration> result;
202
203 QMutexLocker locker(&mutex);
204
205 foreach (QBearerEngine *engine, sessionEngines) {
206 QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator it;
207 QHash<QString, QNetworkConfigurationPrivatePointer>::Iterator end;
208
209 QMutexLocker locker(&engine->mutex);
210
211 //find all InternetAccessPoints
212 for (it = engine->accessPointConfigurations.begin(),
213 end = engine->accessPointConfigurations.end(); it != end; ++it) {
214 QNetworkConfigurationPrivatePointer ptr = it.value();
215
216 QMutexLocker configLocker(&ptr->mutex);
217
218 if ((ptr->state & filter) == filter) {
219 QNetworkConfiguration pt;
220 pt.d = ptr;
221 result << pt;
222 }
223 }
224
225 //find all service networks
226 for (it = engine->snapConfigurations.begin(),
227 end = engine->snapConfigurations.end(); it != end; ++it) {
228 QNetworkConfigurationPrivatePointer ptr = it.value();
229
230 QMutexLocker configLocker(&ptr->mutex);
231
232 if ((ptr->state & filter) == filter) {
233 QNetworkConfiguration pt;
234 pt.d = ptr;
235 result << pt;
236 }
237 }
238 }
239
240 return result;
241}
242
243QNetworkConfiguration QNetworkConfigurationManagerPrivate::configurationFromIdentifier(const QString &identifier)
244{
245 QNetworkConfiguration item;
246
247 QMutexLocker locker(&mutex);
248
249 foreach (QBearerEngine *engine, sessionEngines) {
250 QMutexLocker locker(&engine->mutex);
251
252 if (engine->accessPointConfigurations.contains(identifier))
253 item.d = engine->accessPointConfigurations.value(identifier);
254 else if (engine->snapConfigurations.contains(identifier))
255 item.d = engine->snapConfigurations.value(identifier);
256 else if (engine->userChoiceConfigurations.contains(identifier))
257 item.d = engine->userChoiceConfigurations.value(identifier);
258 else
259 continue;
260
261 return item;
262 }
263
264 return item;
265}
266
267bool QNetworkConfigurationManagerPrivate::isOnline()
268{
269 QMutexLocker locker(&mutex);
270
271 return !onlineConfigurations.isEmpty();
272}
273
274QNetworkConfigurationManager::Capabilities QNetworkConfigurationManagerPrivate::capabilities()
275{
276 QMutexLocker locker(&mutex);
277
278 QNetworkConfigurationManager::Capabilities capFlags;
279
280 foreach (QBearerEngine *engine, sessionEngines)
281 capFlags |= engine->capabilities();
282
283 return capFlags;
284}
285
286void QNetworkConfigurationManagerPrivate::configurationAdded(QNetworkConfigurationPrivatePointer ptr)
287{
288 QMutexLocker locker(&mutex);
289
290 if (!firstUpdate) {
291 QNetworkConfiguration item;
292 item.d = ptr;
293 emit configurationAdded(item);
294 }
295
296 ptr->mutex.lock();
297 if (ptr->state == QNetworkConfiguration::Active) {
298 ptr->mutex.unlock();
299 onlineConfigurations.insert(ptr->id);
300 if (!firstUpdate && onlineConfigurations.count() == 1)
301 emit onlineStateChanged(true);
302 } else {
303 ptr->mutex.unlock();
304 }
305}
306
307void QNetworkConfigurationManagerPrivate::configurationRemoved(QNetworkConfigurationPrivatePointer ptr)
308{
309 QMutexLocker locker(&mutex);
310
311 ptr->mutex.lock();
312 ptr->isValid = false;
313 ptr->mutex.unlock();
314
315 if (!firstUpdate) {
316 QNetworkConfiguration item;
317 item.d = ptr;
318 emit configurationRemoved(item);
319 }
320
321 onlineConfigurations.remove(ptr->id);
322 if (!firstUpdate && onlineConfigurations.isEmpty())
323 emit onlineStateChanged(false);
324}
325
326void QNetworkConfigurationManagerPrivate::configurationChanged(QNetworkConfigurationPrivatePointer ptr)
327{
328 QMutexLocker locker(&mutex);
329
330 if (!firstUpdate) {
331 QNetworkConfiguration item;
332 item.d = ptr;
333 emit configurationChanged(item);
334 }
335
336 bool previous = !onlineConfigurations.isEmpty();
337
338 ptr->mutex.lock();
339 if (ptr->state == QNetworkConfiguration::Active)
340 onlineConfigurations.insert(ptr->id);
341 else
342 onlineConfigurations.remove(ptr->id);
343 ptr->mutex.unlock();
344
345 bool online = !onlineConfigurations.isEmpty();
346
347 if (!firstUpdate && online != previous)
348 emit onlineStateChanged(online);
349}
350
351void QNetworkConfigurationManagerPrivate::updateConfigurations()
352{
353 QMutexLocker locker(&mutex);
354
355 if (firstUpdate) {
356 if (sender())
357 return;
358
359 if (thread() != QCoreApplicationPrivate::mainThread()) {
360 if (thread() != QThread::currentThread())
361 return;
362
363 moveToThread(QCoreApplicationPrivate::mainThread());
364 }
365
366 updating = false;
367
368#ifndef QT_NO_LIBRARY
369 QFactoryLoader *l = loader();
370
371 QBearerEngine *generic = 0;
372
373 foreach (const QString &key, l->keys()) {
374 QBearerEnginePlugin *plugin = qobject_cast<QBearerEnginePlugin *>(l->instance(key));
375 if (plugin) {
376 QBearerEngine *engine = plugin->create(key);
377 if (!engine)
378 continue;
379
380 if (key == QLatin1String("generic"))
381 generic = engine;
382 else
383 sessionEngines.append(engine);
384
385 engine->moveToThread(QCoreApplicationPrivate::mainThread());
386
387 connect(engine, SIGNAL(updateCompleted()),
388 this, SLOT(updateConfigurations()));
389 connect(engine, SIGNAL(configurationAdded(QNetworkConfigurationPrivatePointer)),
390 this, SLOT(configurationAdded(QNetworkConfigurationPrivatePointer)));
391 connect(engine, SIGNAL(configurationRemoved(QNetworkConfigurationPrivatePointer)),
392 this, SLOT(configurationRemoved(QNetworkConfigurationPrivatePointer)));
393 connect(engine, SIGNAL(configurationChanged(QNetworkConfigurationPrivatePointer)),
394 this, SLOT(configurationChanged(QNetworkConfigurationPrivatePointer)));
395
396 QMetaObject::invokeMethod(engine, "initialize");
397 }
398 }
399
400 if (generic)
401 sessionEngines.append(generic);
402#endif // QT_NO_LIBRARY
403 }
404
405 QBearerEngine *engine = qobject_cast<QBearerEngine *>(sender());
406 if (!updatingEngines.isEmpty() && engine) {
407 int index = sessionEngines.indexOf(engine);
408 if (index >= 0)
409 updatingEngines.remove(index);
410 }
411
412 if (updating && updatingEngines.isEmpty()) {
413 updating = false;
414 emit configurationUpdateComplete();
415 }
416
417 if (engine && !pollingEngines.isEmpty()) {
418 int index = sessionEngines.indexOf(engine);
419 if (index >= 0)
420 pollingEngines.remove(index);
421
422 if (pollingEngines.isEmpty())
423 startPolling();
424 }
425
426 if (firstUpdate)
427 firstUpdate = false;
428}
429
430void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate()
431{
432 QMutexLocker locker(&mutex);
433
434 if (sessionEngines.isEmpty()) {
435 emit configurationUpdateComplete();
436 return;
437 }
438
439 updating = true;
440
441 for (int i = 0; i < sessionEngines.count(); ++i) {
442 updatingEngines.insert(i);
443 QMetaObject::invokeMethod(sessionEngines.at(i), "requestUpdate");
444 }
445}
446
447QList<QBearerEngine *> QNetworkConfigurationManagerPrivate::engines()
448{
449 QMutexLocker locker(&mutex);
450
451 return sessionEngines;
452}
453
454void QNetworkConfigurationManagerPrivate::startPolling()
455{
456 QMutexLocker locker(&mutex);
457
458 bool pollingRequired = false;
459
460 if (forcedPolling > 0) {
461 foreach (QBearerEngine *engine, sessionEngines) {
462 if (engine->requiresPolling()) {
463 pollingRequired = true;
464 break;
465 }
466 }
467 }
468
469 if (!pollingRequired) {
470 foreach (QBearerEngine *engine, sessionEngines) {
471 if (engine->configurationsInUse()) {
472 pollingRequired = true;
473 break;
474 }
475 }
476 }
477
478 if (pollingRequired) {
479 if (!pollTimer) {
480 pollTimer = new QTimer(this);
481 pollTimer->setInterval(10000);
482 pollTimer->setSingleShot(true);
483 connect(pollTimer, SIGNAL(timeout()), this, SLOT(pollEngines()));
484 }
485
486 pollTimer->start();
487 }
488}
489
490void QNetworkConfigurationManagerPrivate::pollEngines()
491{
492 QMutexLocker locker(&mutex);
493
494 for (int i = 0; i < sessionEngines.count(); ++i) {
495 if (!sessionEngines.at(i)->requiresPolling())
496 continue;
497
498 if (forcedPolling || sessionEngines.at(i)->configurationsInUse()) {
499 pollingEngines.insert(i);
500 QMetaObject::invokeMethod(sessionEngines.at(i), "requestUpdate");
501 }
502 }
503}
504
505void QNetworkConfigurationManagerPrivate::enablePolling()
506{
507 QMutexLocker locker(&mutex);
508
509 ++forcedPolling;
510
511 if (forcedPolling == 1)
512 QMetaObject::invokeMethod(this, "startPolling");
513}
514
515void QNetworkConfigurationManagerPrivate::disablePolling()
516{
517 QMutexLocker locker(&mutex);
518
519 --forcedPolling;
520}
521
522QT_END_NAMESPACE
523
524#endif // QT_NO_BEARERMANAGEMENT
Note: See TracBrowser for help on using the repository browser.