|
1 /**************************************************************************** |
|
2 ** |
|
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
4 ** All rights reserved. |
|
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
|
6 ** |
|
7 ** This file is part of the Qt Mobility Components. |
|
8 ** |
|
9 ** $QT_BEGIN_LICENSE:LGPL$ |
|
10 ** No Commercial Usage |
|
11 ** This file contains pre-release code and may not be distributed. |
|
12 ** You may use this file in accordance with the terms and conditions |
|
13 ** contained in the Technology Preview License Agreement accompanying |
|
14 ** this package. |
|
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 ** If you have questions regarding the use of this file, please contact |
|
29 ** Nokia at qt-info@nokia.com. |
|
30 ** |
|
31 ** |
|
32 ** |
|
33 ** |
|
34 ** |
|
35 ** |
|
36 ** |
|
37 ** |
|
38 ** $QT_END_LICENSE$ |
|
39 ** |
|
40 ****************************************************************************/ |
|
41 |
|
42 #include "qnetworksession_p.h" |
|
43 #include "qnetworksession.h" |
|
44 #include "qnetworksessionengine_p.h" |
|
45 #include "qgenericengine_p.h" |
|
46 |
|
47 #ifdef Q_OS_WIN |
|
48 #include "qnlaengine_win_p.h" |
|
49 #endif |
|
50 #ifdef Q_OS_WIN32 |
|
51 #include "qnativewifiengine_win_p.h" |
|
52 #endif |
|
53 #ifdef Q_OS_DARWIN |
|
54 #include "qcorewlanengine_mac_p.h" |
|
55 #endif |
|
56 #include <QtCore/qstringlist.h> |
|
57 #include <QtCore/qdebug.h> |
|
58 #include <QtCore/qmutex.h> |
|
59 |
|
60 #include <QtNetwork/qnetworkinterface.h> |
|
61 |
|
62 #if defined(BACKEND_NM) |
|
63 #include "qnmwifiengine_unix_p.h" |
|
64 #endif |
|
65 |
|
66 QTM_BEGIN_NAMESPACE |
|
67 |
|
68 #if defined(BACKEND_NM) |
|
69 static bool NetworkManagerAvailable() |
|
70 { |
|
71 QDBusConnection dbusConnection = QDBusConnection::systemBus(); |
|
72 if (dbusConnection.isConnected()) { |
|
73 QDBusConnectionInterface *dbiface = dbusConnection.interface(); |
|
74 QDBusReply<bool> reply = dbiface->isServiceRegistered("org.freedesktop.NetworkManager"); |
|
75 if (reply.isValid()) |
|
76 return reply.value(); |
|
77 } |
|
78 return false; |
|
79 } |
|
80 #endif |
|
81 |
|
82 static QNetworkSessionEngine *getEngineFromId(const QString &id) |
|
83 { |
|
84 #ifdef Q_OS_WIN |
|
85 QNlaEngine *nla = QNlaEngine::instance(); |
|
86 if (nla && nla->hasIdentifier(id)) |
|
87 return nla; |
|
88 #endif |
|
89 |
|
90 #ifdef Q_OS_WIN32 |
|
91 QNativeWifiEngine *nativeWifi = QNativeWifiEngine::instance(); |
|
92 if (nativeWifi && nativeWifi->hasIdentifier(id)) |
|
93 return nativeWifi; |
|
94 #endif |
|
95 |
|
96 #if defined(BACKEND_NM) |
|
97 if(NetworkManagerAvailable()) { |
|
98 QNmWifiEngine *nmwiifi = QNmWifiEngine::instance(); |
|
99 if (nmwiifi && nmwiifi->hasIdentifier(id)) |
|
100 return nmwiifi; |
|
101 } |
|
102 #endif |
|
103 #ifdef Q_OS_DARWIN |
|
104 QCoreWlanEngine *coreWifi = QCoreWlanEngine::instance(); |
|
105 if (coreWifi && coreWifi->hasIdentifier(id)) |
|
106 return coreWifi; |
|
107 |
|
108 #endif |
|
109 QGenericEngine *generic = QGenericEngine::instance(); |
|
110 if (generic && generic->hasIdentifier(id)) |
|
111 return generic; |
|
112 |
|
113 return 0; |
|
114 } |
|
115 |
|
116 class QNetworkSessionManagerPrivate : public QObject |
|
117 { |
|
118 Q_OBJECT |
|
119 |
|
120 public: |
|
121 QNetworkSessionManagerPrivate(QObject *parent = 0); |
|
122 ~QNetworkSessionManagerPrivate(); |
|
123 |
|
124 void forceSessionClose(const QNetworkConfiguration &config); |
|
125 |
|
126 Q_SIGNALS: |
|
127 void forcedSessionClose(const QNetworkConfiguration &config); |
|
128 }; |
|
129 |
|
130 #include "qnetworksession_p.moc" |
|
131 |
|
132 Q_GLOBAL_STATIC(QNetworkSessionManagerPrivate, sessionManager); |
|
133 |
|
134 QNetworkSessionManagerPrivate::QNetworkSessionManagerPrivate(QObject *parent) |
|
135 : QObject(parent) |
|
136 { |
|
137 } |
|
138 |
|
139 QNetworkSessionManagerPrivate::~QNetworkSessionManagerPrivate() |
|
140 { |
|
141 } |
|
142 |
|
143 void QNetworkSessionManagerPrivate::forceSessionClose(const QNetworkConfiguration &config) |
|
144 { |
|
145 emit forcedSessionClose(config); |
|
146 } |
|
147 |
|
148 void QNetworkSessionPrivate::syncStateWithInterface() |
|
149 { |
|
150 connect(&manager, SIGNAL(updateCompleted()), this, SLOT(networkConfigurationsChanged())); |
|
151 connect(&manager, SIGNAL(configurationChanged(QNetworkConfiguration)), |
|
152 this, SLOT(configurationChanged(QNetworkConfiguration))); |
|
153 connect(sessionManager(), SIGNAL(forcedSessionClose(QNetworkConfiguration)), |
|
154 this, SLOT(forcedSessionClose(QNetworkConfiguration))); |
|
155 |
|
156 opened = false; |
|
157 state = QNetworkSession::Invalid; |
|
158 lastError = QNetworkSession::UnknownSessionError; |
|
159 |
|
160 qRegisterMetaType<QNetworkSessionEngine::ConnectionError> |
|
161 ("QNetworkSessionEngine::ConnectionError"); |
|
162 |
|
163 switch (publicConfig.type()) { |
|
164 case QNetworkConfiguration::InternetAccessPoint: |
|
165 activeConfig = publicConfig; |
|
166 engine = getEngineFromId(activeConfig.identifier()); |
|
167 if (engine) { |
|
168 connect(engine, SIGNAL(connectionError(QString,QNetworkSessionEngine::ConnectionError)), |
|
169 this, SLOT(connectionError(QString,QNetworkSessionEngine::ConnectionError)), |
|
170 Qt::QueuedConnection); |
|
171 } |
|
172 break; |
|
173 case QNetworkConfiguration::ServiceNetwork: |
|
174 serviceConfig = publicConfig; |
|
175 // Defer setting engine and signals until open(). |
|
176 // fall through |
|
177 case QNetworkConfiguration::UserChoice: |
|
178 // Defer setting serviceConfig and activeConfig until open(). |
|
179 // fall through |
|
180 default: |
|
181 engine = 0; |
|
182 } |
|
183 |
|
184 networkConfigurationsChanged(); |
|
185 } |
|
186 |
|
187 void QNetworkSessionPrivate::open() |
|
188 { |
|
189 if (serviceConfig.isValid()) { |
|
190 lastError = QNetworkSession::OperationNotSupportedError; |
|
191 emit q->error(lastError); |
|
192 } else if (!isOpen) { |
|
193 if ((activeConfig.state() & QNetworkConfiguration::Discovered) != |
|
194 QNetworkConfiguration::Discovered) { |
|
195 lastError =QNetworkSession::InvalidConfigurationError; |
|
196 emit q->error(lastError); |
|
197 return; |
|
198 } |
|
199 opened = true; |
|
200 |
|
201 if ((activeConfig.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active && |
|
202 (activeConfig.state() & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) { |
|
203 state = QNetworkSession::Connecting; |
|
204 emit q->stateChanged(state); |
|
205 |
|
206 engine->connectToId(activeConfig.identifier()); |
|
207 } |
|
208 |
|
209 isOpen = (activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active; |
|
210 if (isOpen) |
|
211 emit quitPendingWaitsForOpened(); |
|
212 } |
|
213 } |
|
214 |
|
215 void QNetworkSessionPrivate::close() |
|
216 { |
|
217 if (serviceConfig.isValid()) { |
|
218 lastError = QNetworkSession::OperationNotSupportedError; |
|
219 emit q->error(lastError); |
|
220 } else if (isOpen) { |
|
221 opened = false; |
|
222 isOpen = false; |
|
223 emit q->closed(); |
|
224 } |
|
225 } |
|
226 |
|
227 void QNetworkSessionPrivate::stop() |
|
228 { |
|
229 if (serviceConfig.isValid()) { |
|
230 lastError = QNetworkSession::OperationNotSupportedError; |
|
231 emit q->error(lastError); |
|
232 } else { |
|
233 if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { |
|
234 state = QNetworkSession::Closing; |
|
235 emit q->stateChanged(state); |
|
236 |
|
237 engine->disconnectFromId(activeConfig.identifier()); |
|
238 |
|
239 sessionManager()->forceSessionClose(activeConfig); |
|
240 } |
|
241 |
|
242 opened = false; |
|
243 isOpen = false; |
|
244 emit q->closed(); |
|
245 } |
|
246 } |
|
247 |
|
248 void QNetworkSessionPrivate::migrate() |
|
249 { |
|
250 qWarning("This platform does not support roaming (%s).", __FUNCTION__); |
|
251 } |
|
252 |
|
253 void QNetworkSessionPrivate::accept() |
|
254 { |
|
255 qWarning("This platform does not support roaming (%s).", __FUNCTION__); |
|
256 } |
|
257 |
|
258 void QNetworkSessionPrivate::ignore() |
|
259 { |
|
260 qWarning("This platform does not support roaming (%s).", __FUNCTION__); |
|
261 } |
|
262 |
|
263 void QNetworkSessionPrivate::reject() |
|
264 { |
|
265 qWarning("This platform does not support roaming (%s).", __FUNCTION__); |
|
266 } |
|
267 |
|
268 QNetworkInterface QNetworkSessionPrivate::currentInterface() const |
|
269 { |
|
270 if (!publicConfig.isValid() || !engine || state != QNetworkSession::Connected) |
|
271 return QNetworkInterface(); |
|
272 |
|
273 QString interface = engine->getInterfaceFromId(activeConfig.identifier()); |
|
274 |
|
275 if (interface.isEmpty()) |
|
276 return QNetworkInterface(); |
|
277 return QNetworkInterface::interfaceFromName(interface); |
|
278 } |
|
279 |
|
280 QVariant QNetworkSessionPrivate::sessionProperty(const QString& /*key*/) const |
|
281 { |
|
282 return QVariant(); |
|
283 } |
|
284 |
|
285 void QNetworkSessionPrivate::setSessionProperty(const QString& /*key*/, const QVariant& /*value*/) |
|
286 { |
|
287 } |
|
288 |
|
289 /*QString QNetworkSessionPrivate::bearerName() const |
|
290 { |
|
291 if (!publicConfig.isValid() || !engine) |
|
292 return QString(); |
|
293 |
|
294 return engine->bearerName(activeConfig.identifier()); |
|
295 }*/ |
|
296 |
|
297 QString QNetworkSessionPrivate::errorString() const |
|
298 { |
|
299 switch (lastError) { |
|
300 case QNetworkSession::UnknownSessionError: |
|
301 return tr("Unknown session error."); |
|
302 case QNetworkSession::SessionAbortedError: |
|
303 return tr("The session was aborted by the user or system."); |
|
304 case QNetworkSession::OperationNotSupportedError: |
|
305 return tr("The requested operation is not supported by the system."); |
|
306 case QNetworkSession::InvalidConfigurationError: |
|
307 return tr("The specified configuration cannot be used."); |
|
308 case QNetworkSession::RoamingError: |
|
309 return tr("Roaming was aborted or is not possible."); |
|
310 |
|
311 } |
|
312 |
|
313 return QString(); |
|
314 } |
|
315 |
|
316 QNetworkSession::SessionError QNetworkSessionPrivate::error() const |
|
317 { |
|
318 return lastError; |
|
319 } |
|
320 |
|
321 quint64 QNetworkSessionPrivate::bytesWritten() const |
|
322 { |
|
323 #if defined(BACKEND_NM) |
|
324 if( NetworkManagerAvailable() && state == QNetworkSession::Connected ) { |
|
325 if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) { |
|
326 foreach (const QNetworkConfiguration &config, publicConfig.children()) { |
|
327 if ((config.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { |
|
328 return static_cast<QNmWifiEngine*>(getEngineFromId(config.d->id))->sentDataForId(config.d->id); |
|
329 } |
|
330 } |
|
331 } else { |
|
332 return static_cast<QNmWifiEngine*>(getEngineFromId(activeConfig.d->id))->sentDataForId(activeConfig.d->id); |
|
333 } |
|
334 } |
|
335 #endif |
|
336 return tx_data; |
|
337 } |
|
338 |
|
339 quint64 QNetworkSessionPrivate::bytesReceived() const |
|
340 { |
|
341 #if defined(BACKEND_NM) |
|
342 if( NetworkManagerAvailable() && state == QNetworkSession::Connected ) { |
|
343 if (publicConfig.type() == QNetworkConfiguration::ServiceNetwork) { |
|
344 foreach (const QNetworkConfiguration &config, publicConfig.children()) { |
|
345 if ((config.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { |
|
346 return static_cast<QNmWifiEngine*>(getEngineFromId(activeConfig.d->id))->receivedDataForId(config.d->id); |
|
347 } |
|
348 } |
|
349 } else { |
|
350 return static_cast<QNmWifiEngine*>(getEngineFromId(activeConfig.d->id))->receivedDataForId(activeConfig.d->id); |
|
351 } |
|
352 } |
|
353 #endif |
|
354 return rx_data; |
|
355 } |
|
356 |
|
357 quint64 QNetworkSessionPrivate::activeTime() const |
|
358 { |
|
359 #if defined(BACKEND_NM) |
|
360 if (startTime.isNull()) { |
|
361 return 0; |
|
362 } |
|
363 if(state == QNetworkSession::Connected ) |
|
364 return startTime.secsTo(QDateTime::currentDateTime()); |
|
365 #endif |
|
366 return m_activeTime; |
|
367 } |
|
368 |
|
369 void QNetworkSessionPrivate::updateStateFromServiceNetwork() |
|
370 { |
|
371 QNetworkSession::State oldState = state; |
|
372 |
|
373 foreach (const QNetworkConfiguration &config, serviceConfig.children()) { |
|
374 if ((config.state() & QNetworkConfiguration::Active) != QNetworkConfiguration::Active) |
|
375 continue; |
|
376 |
|
377 if (activeConfig != config) { |
|
378 if (engine) { |
|
379 disconnect(engine, SIGNAL(connectionError(QString,QNetworkSessionEngine::ConnectionError)), |
|
380 this, SLOT(connectionError(QString,QNetworkSessionEngine::ConnectionError))); |
|
381 } |
|
382 |
|
383 activeConfig = config; |
|
384 engine = getEngineFromId(activeConfig.identifier()); |
|
385 if (engine) { |
|
386 connect(engine, SIGNAL(connectionError(QString,QNetworkSessionEngine::ConnectionError)), |
|
387 this, SLOT(connectionError(QString,QNetworkSessionEngine::ConnectionError)), |
|
388 Qt::QueuedConnection); |
|
389 } |
|
390 emit q->newConfigurationActivated(); |
|
391 } |
|
392 |
|
393 state = QNetworkSession::Connected; |
|
394 if (state != oldState) |
|
395 emit q->stateChanged(state); |
|
396 |
|
397 return; |
|
398 } |
|
399 |
|
400 if (serviceConfig.children().isEmpty()) |
|
401 state = QNetworkSession::NotAvailable; |
|
402 else |
|
403 state = QNetworkSession::Disconnected; |
|
404 |
|
405 if (state != oldState) |
|
406 emit q->stateChanged(state); |
|
407 } |
|
408 |
|
409 void QNetworkSessionPrivate::updateStateFromActiveConfig() |
|
410 { |
|
411 QNetworkSession::State oldState = state; |
|
412 |
|
413 bool newActive = false; |
|
414 |
|
415 if (!activeConfig.isValid()) { |
|
416 state = QNetworkSession::Invalid; |
|
417 } else if ((activeConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active) { |
|
418 state = QNetworkSession::Connected; |
|
419 newActive = opened; |
|
420 } else if ((activeConfig.state() & QNetworkConfiguration::Discovered) == QNetworkConfiguration::Discovered) { |
|
421 state = QNetworkSession::Disconnected; |
|
422 } else if ((activeConfig.state() & QNetworkConfiguration::Defined) == QNetworkConfiguration::Defined) { |
|
423 state = QNetworkSession::NotAvailable; |
|
424 } else if ((activeConfig.state() & QNetworkConfiguration::Undefined) == QNetworkConfiguration::Undefined) { |
|
425 state = QNetworkSession::NotAvailable; |
|
426 } |
|
427 |
|
428 bool oldActive = isOpen; |
|
429 isOpen = newActive; |
|
430 |
|
431 if (!oldActive && isOpen) |
|
432 emit quitPendingWaitsForOpened(); |
|
433 if (oldActive && !isOpen) |
|
434 emit q->closed(); |
|
435 |
|
436 if (oldState != state) |
|
437 emit q->stateChanged(state); |
|
438 } |
|
439 |
|
440 void QNetworkSessionPrivate::networkConfigurationsChanged() |
|
441 { |
|
442 if (serviceConfig.isValid()) |
|
443 updateStateFromServiceNetwork(); |
|
444 else |
|
445 updateStateFromActiveConfig(); |
|
446 #if defined(BACKEND_NM) |
|
447 setActiveTimeStamp(); |
|
448 #endif |
|
449 } |
|
450 |
|
451 void QNetworkSessionPrivate::configurationChanged(const QNetworkConfiguration &config) |
|
452 { |
|
453 if (serviceConfig.isValid() && (config == serviceConfig || config == activeConfig)) |
|
454 updateStateFromServiceNetwork(); |
|
455 else if (config == activeConfig) |
|
456 updateStateFromActiveConfig(); |
|
457 } |
|
458 |
|
459 void QNetworkSessionPrivate::forcedSessionClose(const QNetworkConfiguration &config) |
|
460 { |
|
461 if (activeConfig == config) { |
|
462 opened = false; |
|
463 isOpen = false; |
|
464 |
|
465 emit q->closed(); |
|
466 |
|
467 lastError = QNetworkSession::SessionAbortedError; |
|
468 emit q->error(lastError); |
|
469 } |
|
470 } |
|
471 |
|
472 void QNetworkSessionPrivate::connectionError(const QString &id, QNetworkSessionEngine::ConnectionError error) |
|
473 { |
|
474 if (activeConfig.identifier() == id) { |
|
475 networkConfigurationsChanged(); |
|
476 switch (error) { |
|
477 case QNetworkSessionEngine::OperationNotSupported: |
|
478 lastError = QNetworkSession::OperationNotSupportedError; |
|
479 opened = false; |
|
480 break; |
|
481 case QNetworkSessionEngine::InterfaceLookupError: |
|
482 case QNetworkSessionEngine::ConnectError: |
|
483 case QNetworkSessionEngine::DisconnectionError: |
|
484 default: |
|
485 lastError = QNetworkSession::UnknownSessionError; |
|
486 } |
|
487 emit q->error(lastError); |
|
488 } |
|
489 } |
|
490 |
|
491 #if defined(BACKEND_NM) |
|
492 void QNetworkSessionPrivate::setActiveTimeStamp() |
|
493 { |
|
494 if(NetworkManagerAvailable()) { |
|
495 startTime = QDateTime(); |
|
496 return; |
|
497 } |
|
498 QString interface = currentInterface().hardwareAddress().toLower(); |
|
499 const QString devicePath = QLatin1String("/org/freedesktop/Hal/devices/net_") + |
|
500 interface.replace(QLatin1Char(':'), QLatin1Char('_')); |
|
501 |
|
502 QString path; |
|
503 QString serviceName; |
|
504 QScopedPointer<QNetworkManagerInterface> ifaceD(new QNetworkManagerInterface()); |
|
505 |
|
506 foreach (const QDBusObjectPath &conpath, ifaceD->activeConnections()) { |
|
507 QScopedPointer<QNetworkManagerConnectionActive> conDetails(new QNetworkManagerConnectionActive(conpath.path())); |
|
508 const QDBusObjectPath connection = conDetails->connection(); |
|
509 serviceName = conDetails->serviceName(); |
|
510 foreach (const QDBusObjectPath &device, conDetails->devices()) { |
|
511 if(device.path() == devicePath) { |
|
512 path = connection.path(); |
|
513 } |
|
514 break; |
|
515 } |
|
516 } |
|
517 |
|
518 if(serviceName.isEmpty()) |
|
519 return; |
|
520 |
|
521 QScopedPointer<QNetworkManagerSettings> settingsiface(new QNetworkManagerSettings(serviceName)); |
|
522 foreach (const QDBusObjectPath &path, settingsiface->listConnections()) { |
|
523 QScopedPointer<QNetworkManagerSettingsConnection> sysIface; |
|
524 sysIface.reset(new QNetworkManagerSettingsConnection(serviceName, path.path())); |
|
525 startTime = QDateTime::fromTime_t(sysIface->getTimestamp()); |
|
526 // isOpen = (publicConfig.state() & QNetworkConfiguration::Active) == QNetworkConfiguration::Active; |
|
527 } |
|
528 if(startTime.isNull()) |
|
529 startTime = QDateTime::currentDateTime(); |
|
530 } |
|
531 #endif |
|
532 |
|
533 #include "moc_qnetworksession_p.cpp" |
|
534 QTM_END_NAMESPACE |
|
535 |