1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the plugins of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #include <QObject> |
41 | #include <QList> |
42 | #include <QtDBus/QtDBus> |
43 | #include <QtDBus/QDBusConnection> |
44 | #include <QtDBus/QDBusError> |
45 | #include <QtDBus/QDBusInterface> |
46 | #include <QtDBus/QDBusMessage> |
47 | #include <QtDBus/QDBusReply> |
48 | #include <QtDBus/QDBusPendingCallWatcher> |
49 | #include <QtDBus/QDBusObjectPath> |
50 | #include <QtDBus/QDBusPendingCall> |
51 | |
52 | #include "qconnmanservice_linux_p.h" |
53 | |
54 | #ifndef QT_NO_DBUS |
55 | |
56 | QT_BEGIN_NAMESPACE |
57 | |
58 | QDBusArgument &operator<<(QDBusArgument &argument, const ConnmanMap &map) |
59 | { |
60 | argument.beginStructure(); |
61 | argument << map.objectPath << map.propertyMap; |
62 | argument.endStructure(); |
63 | return argument; |
64 | } |
65 | |
66 | const QDBusArgument &operator>>(const QDBusArgument &argument, ConnmanMap &map) |
67 | { |
68 | argument.beginStructure(); |
69 | argument >> map.objectPath >> map.propertyMap; |
70 | argument.endStructure(); |
71 | return argument; |
72 | } |
73 | |
74 | QConnmanManagerInterface::QConnmanManagerInterface( QObject *parent) |
75 | : QDBusAbstractInterface(QLatin1String(CONNMAN_SERVICE), |
76 | QLatin1String(CONNMAN_MANAGER_PATH), |
77 | CONNMAN_MANAGER_INTERFACE, |
78 | QDBusConnection::systemBus(), parent) |
79 | { |
80 | qDBusRegisterMetaType<ConnmanMap>(); |
81 | qDBusRegisterMetaType<ConnmanMapList>(); |
82 | |
83 | QDBusPendingReply<QVariantMap> props_reply = asyncCall(method: QLatin1String("GetProperties" )); |
84 | QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(props_reply, this); |
85 | |
86 | QObject::connect(sender: watcher,SIGNAL(finished(QDBusPendingCallWatcher*)), |
87 | receiver: this, SLOT(propertiesReply(QDBusPendingCallWatcher*))); |
88 | |
89 | QDBusConnection::systemBus().connect(service: QLatin1String(CONNMAN_SERVICE), |
90 | path: QLatin1String(CONNMAN_MANAGER_PATH), |
91 | interface: QLatin1String(CONNMAN_SERVICE_INTERFACE), |
92 | name: QLatin1String("PropertyChanged" ), |
93 | receiver: this,SLOT(changedProperty(QString,QDBusVariant))); |
94 | |
95 | |
96 | QDBusConnection::systemBus().connect(service: QLatin1String(CONNMAN_SERVICE), |
97 | path: QLatin1String(CONNMAN_MANAGER_PATH), |
98 | interface: QLatin1String(CONNMAN_SERVICE_INTERFACE), |
99 | name: QLatin1String("TechnologyAdded" ), |
100 | receiver: this,SLOT(technologyAdded(QDBusObjectPath,QVariantMap))); |
101 | |
102 | QDBusConnection::systemBus().connect(service: QLatin1String(CONNMAN_SERVICE), |
103 | path: QLatin1String(CONNMAN_MANAGER_PATH), |
104 | interface: QLatin1String(CONNMAN_SERVICE_INTERFACE), |
105 | name: QLatin1String("TechnologyRemoved" ), |
106 | receiver: this,SLOT(technologyRemoved(QDBusObjectPath))); |
107 | |
108 | QDBusPendingReply<ConnmanMapList> serv_reply = asyncCall(method: QLatin1String("GetServices" )); |
109 | QDBusPendingCallWatcher *watcher2 = new QDBusPendingCallWatcher(serv_reply, this); |
110 | |
111 | QObject::connect(sender: watcher2,SIGNAL(finished(QDBusPendingCallWatcher*)), |
112 | receiver: this, SLOT(servicesReply(QDBusPendingCallWatcher*))); |
113 | |
114 | } |
115 | |
116 | QConnmanManagerInterface::~QConnmanManagerInterface() |
117 | { |
118 | } |
119 | |
120 | void QConnmanManagerInterface::changedProperty(const QString &name, const QDBusVariant &value) |
121 | { |
122 | propertiesCacheMap[name] = value.variant(); |
123 | } |
124 | |
125 | void QConnmanManagerInterface::propertiesReply(QDBusPendingCallWatcher *call) |
126 | { |
127 | QDBusPendingReply<QVariantMap> props_reply = *call; |
128 | |
129 | if (props_reply.isError()) { |
130 | qDebug() << props_reply.error().message(); |
131 | } else { |
132 | propertiesCacheMap = props_reply.value(); |
133 | } |
134 | call->deleteLater(); |
135 | } |
136 | |
137 | void QConnmanManagerInterface::servicesReply(QDBusPendingCallWatcher *call) |
138 | { |
139 | QDBusPendingReply<ConnmanMapList> serv_reply = *call; |
140 | |
141 | if (serv_reply.isError()) { |
142 | qDebug() << serv_reply.error().message(); |
143 | } else { |
144 | servicesList.clear(); //connman list changes order |
145 | const ConnmanMapList connmanobjs = serv_reply.value(); |
146 | for (const ConnmanMap &connmanobj : connmanobjs) |
147 | servicesList << connmanobj.objectPath.path(); |
148 | Q_EMIT servicesReady(servicesList); |
149 | } |
150 | call->deleteLater(); |
151 | } |
152 | |
153 | void QConnmanManagerInterface::connectNotify(const QMetaMethod &signal) |
154 | { |
155 | static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(signal: &QConnmanManagerInterface::propertyChanged); |
156 | if (signal == propertyChangedSignal) { |
157 | if (!connection().connect(service: QLatin1String(CONNMAN_SERVICE), |
158 | path: QLatin1String(CONNMAN_MANAGER_PATH), |
159 | interface: QLatin1String(CONNMAN_MANAGER_INTERFACE), |
160 | name: QLatin1String("PropertyChanged" ), |
161 | receiver: this,SIGNAL(propertyChanged(QString,QDBusVariant)))) { |
162 | qWarning(msg: "PropertyChanged not connected" ); |
163 | } |
164 | } |
165 | |
166 | static const QMetaMethod servicesChangedSignal = QMetaMethod::fromSignal(signal: &QConnmanManagerInterface::servicesChanged); |
167 | if (signal == servicesChangedSignal) { |
168 | if (!connection().connect(service: QLatin1String(CONNMAN_SERVICE), |
169 | path: QLatin1String(CONNMAN_MANAGER_PATH), |
170 | interface: QLatin1String(CONNMAN_MANAGER_INTERFACE), |
171 | name: QLatin1String("ServicesChanged" ), |
172 | receiver: this,SLOT(onServicesChanged(ConnmanMapList,QList<QDBusObjectPath>)))) { |
173 | qWarning(msg: "servicesChanged not connected" ); |
174 | } |
175 | } |
176 | } |
177 | |
178 | void QConnmanManagerInterface::onServicesChanged(const ConnmanMapList &changed, const QList<QDBusObjectPath> &removed) |
179 | { |
180 | servicesList.clear(); //connman list changes order |
181 | for (const ConnmanMap &connmanobj : changed) { |
182 | const QString svcPath(connmanobj.objectPath.path()); |
183 | servicesList << svcPath; |
184 | } |
185 | |
186 | Q_EMIT servicesChanged(changed, removed); |
187 | } |
188 | |
189 | QVariant QConnmanManagerInterface::getProperty(const QString &property) |
190 | { |
191 | QVariant var; |
192 | var = propertiesCacheMap.value(akey: property); |
193 | return var; |
194 | } |
195 | |
196 | QVariantMap QConnmanManagerInterface::getProperties() |
197 | { |
198 | if (propertiesCacheMap.isEmpty()) { |
199 | QDBusPendingReply<QVariantMap> reply = call(method: QLatin1String("GetProperties" )); |
200 | reply.waitForFinished(); |
201 | if (!reply.isError()) { |
202 | propertiesCacheMap = reply.value(); |
203 | } |
204 | } |
205 | return propertiesCacheMap; |
206 | } |
207 | |
208 | QString QConnmanManagerInterface::getState() |
209 | { |
210 | return getProperty(QStringLiteral("State" )).toString(); |
211 | } |
212 | |
213 | bool QConnmanManagerInterface::getOfflineMode() |
214 | { |
215 | QVariant var = getProperty(QStringLiteral("OfflineMode" )); |
216 | return qdbus_cast<bool>(v: var); |
217 | } |
218 | |
219 | QStringList QConnmanManagerInterface::getTechnologies() |
220 | { |
221 | if (technologiesMap.isEmpty()) { |
222 | QDBusPendingReply<ConnmanMapList> reply = call(method: QLatin1String("GetTechnologies" )); |
223 | reply.waitForFinished(); |
224 | if (!reply.isError()) { |
225 | const ConnmanMapList maps = reply.value(); |
226 | for (const ConnmanMap &map : maps) { |
227 | if (!technologiesMap.contains(akey: map.objectPath.path())) { |
228 | technologyAdded(technology: map.objectPath, properties: map.propertyMap); |
229 | } |
230 | } |
231 | } |
232 | } |
233 | return technologiesMap.keys(); |
234 | } |
235 | |
236 | QStringList QConnmanManagerInterface::getServices() |
237 | { |
238 | if (servicesList.isEmpty()) { |
239 | QDBusPendingReply<ConnmanMapList> reply = call(method: QLatin1String("GetServices" )); |
240 | reply.waitForFinished(); |
241 | if (!reply.isError()) { |
242 | const ConnmanMapList maps = reply.value(); |
243 | for (const ConnmanMap &map : maps) |
244 | servicesList << map.objectPath.path(); |
245 | } |
246 | } |
247 | return servicesList; |
248 | } |
249 | |
250 | bool QConnmanManagerInterface::requestScan(const QString &type) |
251 | { |
252 | bool scanned = false; |
253 | if (technologiesMap.isEmpty()) |
254 | getTechnologies(); |
255 | Q_FOREACH (QConnmanTechnologyInterface *tech, technologiesMap) { |
256 | if (tech->type() == type) { |
257 | tech->scan(); |
258 | scanned = true; |
259 | } |
260 | } |
261 | return scanned; |
262 | } |
263 | |
264 | void QConnmanManagerInterface::technologyAdded(const QDBusObjectPath &path, const QVariantMap &) |
265 | { |
266 | if (!technologiesList.contains(str: path.path())) { |
267 | technologiesList << path.path(); |
268 | QConnmanTechnologyInterface *tech; |
269 | tech = new QConnmanTechnologyInterface(path.path(),this); |
270 | technologiesMap.insert(akey: path.path(),avalue: tech); |
271 | connect(sender: tech,SIGNAL(scanFinished(bool)),receiver: this,SIGNAL(scanFinished(bool))); |
272 | } |
273 | } |
274 | |
275 | void QConnmanManagerInterface::technologyRemoved(const QDBusObjectPath &path) |
276 | { |
277 | if (technologiesList.contains(str: path.path())) { |
278 | technologiesList.removeOne(t: path.path()); |
279 | QConnmanTechnologyInterface * tech = technologiesMap.take(akey: path.path()); |
280 | delete tech; |
281 | } |
282 | } |
283 | |
284 | QConnmanServiceInterface::QConnmanServiceInterface(const QString &dbusPathName,QObject *parent) |
285 | : QDBusAbstractInterface(QLatin1String(CONNMAN_SERVICE), |
286 | dbusPathName, |
287 | CONNMAN_SERVICE_INTERFACE, |
288 | QDBusConnection::systemBus(), parent) |
289 | { |
290 | QDBusPendingReply<QVariantMap> props_reply = asyncCall(method: QLatin1String("GetProperties" )); |
291 | |
292 | QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(props_reply, this); |
293 | |
294 | QObject::connect(sender: watcher,SIGNAL(finished(QDBusPendingCallWatcher*)), |
295 | receiver: this, SLOT(propertiesReply(QDBusPendingCallWatcher*))); |
296 | |
297 | QDBusConnection::systemBus().connect(service: QLatin1String(CONNMAN_SERVICE), |
298 | path: path(), |
299 | interface: QLatin1String(CONNMAN_SERVICE_INTERFACE), |
300 | name: QLatin1String("PropertyChanged" ), |
301 | receiver: this,SLOT(changedProperty(QString,QDBusVariant))); |
302 | } |
303 | |
304 | QConnmanServiceInterface::~QConnmanServiceInterface() |
305 | { |
306 | } |
307 | |
308 | QVariantMap QConnmanServiceInterface::getProperties() |
309 | { |
310 | if (propertiesCacheMap.isEmpty()) { |
311 | QDBusPendingReply<QVariantMap> reply = call(method: QLatin1String("GetProperties" )); |
312 | reply.waitForFinished(); |
313 | if (!reply.isError()) { |
314 | propertiesCacheMap = reply.value(); |
315 | Q_EMIT propertiesReady(); |
316 | } |
317 | } |
318 | return propertiesCacheMap; |
319 | } |
320 | |
321 | void QConnmanServiceInterface::propertiesReply(QDBusPendingCallWatcher *call) |
322 | { |
323 | QDBusPendingReply<QVariantMap> props_reply = *call; |
324 | if (props_reply.isError()) { |
325 | qDebug() << props_reply.error().message(); |
326 | return; |
327 | } |
328 | propertiesCacheMap = props_reply.value(); |
329 | Q_EMIT propertiesReady(); |
330 | } |
331 | |
332 | void QConnmanServiceInterface::connectNotify(const QMetaMethod &signal) |
333 | { |
334 | static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(signal: &QConnmanServiceInterface::propertyChanged); |
335 | if (signal == propertyChangedSignal) { |
336 | QDBusConnection::systemBus().connect(service: QLatin1String(CONNMAN_SERVICE), |
337 | path: path(), |
338 | interface: QLatin1String(CONNMAN_SERVICE_INTERFACE), |
339 | name: QLatin1String("PropertyChanged" ), |
340 | receiver: this,SIGNAL(propertyChanged(QString,QDBusVariant))); |
341 | } |
342 | } |
343 | |
344 | void QConnmanServiceInterface::changedProperty(const QString &name, const QDBusVariant &value) |
345 | { |
346 | propertiesCacheMap[name] = value.variant(); |
347 | if (name == QLatin1String("State" )) |
348 | Q_EMIT stateChanged(state: value.variant().toString()); |
349 | } |
350 | |
351 | QVariant QConnmanServiceInterface::getProperty(const QString &property) |
352 | { |
353 | QVariant var; |
354 | QVariantMap map = getProperties(); |
355 | var = map.value(akey: property); |
356 | return var; |
357 | } |
358 | |
359 | void QConnmanServiceInterface::connect() |
360 | { |
361 | asyncCall(method: QLatin1String("Connect" )); |
362 | } |
363 | |
364 | void QConnmanServiceInterface::disconnect() |
365 | { |
366 | asyncCall(method: QLatin1String("Disconnect" )); |
367 | } |
368 | |
369 | void QConnmanServiceInterface::remove() |
370 | { |
371 | asyncCall(method: QLatin1String("Remove" )); |
372 | } |
373 | |
374 | // properties |
375 | QString QConnmanServiceInterface::state() |
376 | { |
377 | QVariant var = getProperty(QStringLiteral("State" )); |
378 | return qdbus_cast<QString>(v: var); |
379 | } |
380 | |
381 | QString QConnmanServiceInterface::lastError() |
382 | { |
383 | QVariant var = getProperty(QStringLiteral("Error" )); |
384 | return qdbus_cast<QString>(v: var); |
385 | } |
386 | |
387 | QString QConnmanServiceInterface::name() |
388 | { |
389 | QVariant var = getProperty(QStringLiteral("Name" )); |
390 | return qdbus_cast<QString>(v: var); |
391 | } |
392 | |
393 | QString QConnmanServiceInterface::type() |
394 | { |
395 | QVariant var = getProperty(QStringLiteral("Type" )); |
396 | return qdbus_cast<QString>(v: var); |
397 | } |
398 | |
399 | QString QConnmanServiceInterface::security() |
400 | { |
401 | QVariant var = getProperty(QStringLiteral("Security" )); |
402 | return qdbus_cast<QString>(v: var); |
403 | } |
404 | |
405 | bool QConnmanServiceInterface::favorite() |
406 | { |
407 | QVariant var = getProperty(QStringLiteral("Favorite" )); |
408 | return qdbus_cast<bool>(v: var); |
409 | } |
410 | |
411 | bool QConnmanServiceInterface::autoConnect() |
412 | { |
413 | QVariant var = getProperty(QStringLiteral("AutoConnect" )); |
414 | return qdbus_cast<bool>(v: var); |
415 | } |
416 | |
417 | bool QConnmanServiceInterface::roaming() |
418 | { |
419 | QVariant var = getProperty(QStringLiteral("Roaming" )); |
420 | return qdbus_cast<bool>(v: var); |
421 | } |
422 | |
423 | QVariantMap QConnmanServiceInterface::ethernet() |
424 | { |
425 | QVariant var = getProperty(QStringLiteral("Ethernet" )); |
426 | return qdbus_cast<QVariantMap >(v: var); |
427 | } |
428 | |
429 | QString QConnmanServiceInterface::serviceInterface() |
430 | { |
431 | QVariantMap map = ethernet(); |
432 | return map.value(QStringLiteral("Interface" )).toString(); |
433 | } |
434 | |
435 | bool QConnmanServiceInterface::isOfflineMode() |
436 | { |
437 | QVariant var = getProperty(QStringLiteral("OfflineMode" )); |
438 | return qdbus_cast<bool>(v: var); |
439 | } |
440 | |
441 | QStringList QConnmanServiceInterface::services() |
442 | { |
443 | QVariant var = getProperty(QStringLiteral("Services" )); |
444 | return qdbus_cast<QStringList>(v: var); |
445 | } |
446 | |
447 | ////////////////////////// |
448 | QConnmanTechnologyInterface::QConnmanTechnologyInterface(const QString &dbusPathName,QObject *parent) |
449 | : QDBusAbstractInterface(QLatin1String(CONNMAN_SERVICE), |
450 | dbusPathName, |
451 | CONNMAN_TECHNOLOGY_INTERFACE, |
452 | QDBusConnection::systemBus(), parent) |
453 | { |
454 | } |
455 | |
456 | QConnmanTechnologyInterface::~QConnmanTechnologyInterface() |
457 | { |
458 | } |
459 | |
460 | void QConnmanTechnologyInterface::connectNotify(const QMetaMethod &signal) |
461 | { |
462 | static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(signal: &QConnmanTechnologyInterface::propertyChanged); |
463 | if (signal == propertyChangedSignal) { |
464 | QDBusConnection::systemBus().connect(service: QLatin1String(CONNMAN_SERVICE), |
465 | path: path(), |
466 | interface: QLatin1String(CONNMAN_TECHNOLOGY_INTERFACE), |
467 | name: QLatin1String("PropertyChanged" ), |
468 | receiver: this,SIGNAL(propertyChanged(QString,QDBusVariant))); |
469 | } |
470 | } |
471 | |
472 | QVariantMap QConnmanTechnologyInterface::properties() |
473 | { |
474 | if (propertiesMap.isEmpty()) { |
475 | QDBusPendingReply<QVariantMap> reply = call(method: QLatin1String("GetProperties" )); |
476 | reply.waitForFinished(); |
477 | propertiesMap = reply.value(); |
478 | } |
479 | return propertiesMap; |
480 | } |
481 | |
482 | QVariant QConnmanTechnologyInterface::getProperty(const QString &property) |
483 | { |
484 | QVariant var; |
485 | QVariantMap map = properties(); |
486 | var = map.value(akey: property); |
487 | return var; |
488 | } |
489 | |
490 | QString QConnmanTechnologyInterface::type() |
491 | { |
492 | QVariant var = getProperty(QStringLiteral("Type" )); |
493 | return qdbus_cast<QString>(v: var); |
494 | } |
495 | |
496 | void QConnmanTechnologyInterface::scan() |
497 | { |
498 | QDBusPendingReply<> reply = asyncCall(method: QLatin1String("Scan" )); |
499 | QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this); |
500 | connect(sender: watcher, SIGNAL(finished(QDBusPendingCallWatcher*)), |
501 | receiver: this, SLOT(scanReply(QDBusPendingCallWatcher*))); |
502 | } |
503 | |
504 | void QConnmanTechnologyInterface::scanReply(QDBusPendingCallWatcher *call) |
505 | { |
506 | QDBusPendingReply<> props_reply = *call; |
507 | if (props_reply.isError()) { |
508 | qDebug() << props_reply.error().message(); |
509 | } |
510 | Q_EMIT scanFinished(error: props_reply.isError()); |
511 | call->deleteLater(); |
512 | } |
513 | |
514 | QT_END_NAMESPACE |
515 | |
516 | #endif // QT_NO_DBUS |
517 | |