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
56QT_BEGIN_NAMESPACE
57
58QDBusArgument &operator<<(QDBusArgument &argument, const ConnmanMap &map)
59{
60 argument.beginStructure();
61 argument << map.objectPath << map.propertyMap;
62 argument.endStructure();
63 return argument;
64}
65
66const 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
74QConnmanManagerInterface::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
116QConnmanManagerInterface::~QConnmanManagerInterface()
117{
118}
119
120void QConnmanManagerInterface::changedProperty(const QString &name, const QDBusVariant &value)
121{
122 propertiesCacheMap[name] = value.variant();
123}
124
125void 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
137void 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
153void 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
178void 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
189QVariant QConnmanManagerInterface::getProperty(const QString &property)
190{
191 QVariant var;
192 var = propertiesCacheMap.value(akey: property);
193 return var;
194}
195
196QVariantMap 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
208QString QConnmanManagerInterface::getState()
209{
210 return getProperty(QStringLiteral("State")).toString();
211}
212
213bool QConnmanManagerInterface::getOfflineMode()
214{
215 QVariant var = getProperty(QStringLiteral("OfflineMode"));
216 return qdbus_cast<bool>(v: var);
217}
218
219QStringList 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
236QStringList 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
250bool 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
264void 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
275void 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
284QConnmanServiceInterface::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
304QConnmanServiceInterface::~QConnmanServiceInterface()
305{
306}
307
308QVariantMap 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
321void 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
332void 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
344void 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
351QVariant QConnmanServiceInterface::getProperty(const QString &property)
352{
353 QVariant var;
354 QVariantMap map = getProperties();
355 var = map.value(akey: property);
356 return var;
357}
358
359void QConnmanServiceInterface::connect()
360{
361 asyncCall(method: QLatin1String("Connect"));
362}
363
364void QConnmanServiceInterface::disconnect()
365{
366 asyncCall(method: QLatin1String("Disconnect"));
367}
368
369void QConnmanServiceInterface::remove()
370{
371 asyncCall(method: QLatin1String("Remove"));
372}
373
374// properties
375QString QConnmanServiceInterface::state()
376{
377 QVariant var = getProperty(QStringLiteral("State"));
378 return qdbus_cast<QString>(v: var);
379}
380
381QString QConnmanServiceInterface::lastError()
382{
383 QVariant var = getProperty(QStringLiteral("Error"));
384 return qdbus_cast<QString>(v: var);
385}
386
387QString QConnmanServiceInterface::name()
388{
389 QVariant var = getProperty(QStringLiteral("Name"));
390 return qdbus_cast<QString>(v: var);
391}
392
393QString QConnmanServiceInterface::type()
394{
395 QVariant var = getProperty(QStringLiteral("Type"));
396 return qdbus_cast<QString>(v: var);
397}
398
399QString QConnmanServiceInterface::security()
400{
401 QVariant var = getProperty(QStringLiteral("Security"));
402 return qdbus_cast<QString>(v: var);
403}
404
405bool QConnmanServiceInterface::favorite()
406{
407 QVariant var = getProperty(QStringLiteral("Favorite"));
408 return qdbus_cast<bool>(v: var);
409}
410
411bool QConnmanServiceInterface::autoConnect()
412{
413 QVariant var = getProperty(QStringLiteral("AutoConnect"));
414 return qdbus_cast<bool>(v: var);
415}
416
417bool QConnmanServiceInterface::roaming()
418{
419 QVariant var = getProperty(QStringLiteral("Roaming"));
420 return qdbus_cast<bool>(v: var);
421}
422
423QVariantMap QConnmanServiceInterface::ethernet()
424{
425 QVariant var = getProperty(QStringLiteral("Ethernet"));
426 return qdbus_cast<QVariantMap >(v: var);
427}
428
429QString QConnmanServiceInterface::serviceInterface()
430{
431 QVariantMap map = ethernet();
432 return map.value(QStringLiteral("Interface")).toString();
433}
434
435bool QConnmanServiceInterface::isOfflineMode()
436{
437 QVariant var = getProperty(QStringLiteral("OfflineMode"));
438 return qdbus_cast<bool>(v: var);
439}
440
441QStringList QConnmanServiceInterface::services()
442{
443 QVariant var = getProperty(QStringLiteral("Services"));
444 return qdbus_cast<QStringList>(v: var);
445}
446
447//////////////////////////
448QConnmanTechnologyInterface::QConnmanTechnologyInterface(const QString &dbusPathName,QObject *parent)
449 : QDBusAbstractInterface(QLatin1String(CONNMAN_SERVICE),
450 dbusPathName,
451 CONNMAN_TECHNOLOGY_INTERFACE,
452 QDBusConnection::systemBus(), parent)
453{
454}
455
456QConnmanTechnologyInterface::~QConnmanTechnologyInterface()
457{
458}
459
460void 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
472QVariantMap 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
482QVariant QConnmanTechnologyInterface::getProperty(const QString &property)
483{
484 QVariant var;
485 QVariantMap map = properties();
486 var = map.value(akey: property);
487 return var;
488}
489
490QString QConnmanTechnologyInterface::type()
491{
492 QVariant var = getProperty(QStringLiteral("Type"));
493 return qdbus_cast<QString>(v: var);
494}
495
496void 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
504void 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
514QT_END_NAMESPACE
515
516#endif // QT_NO_DBUS
517

source code of qtbase/src/plugins/bearer/connman/qconnmanservice_linux.cpp