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 
operator <<(QDBusArgument & argument,const ConnmanMap & map)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 
operator >>(const QDBusArgument & argument,ConnmanMap & map)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 
QConnmanManagerInterface(QObject * parent)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(QLatin1String("GetProperties"));
84     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(props_reply, this);
85 
86     QObject::connect(watcher,SIGNAL(finished(QDBusPendingCallWatcher*)),
87                      this, SLOT(propertiesReply(QDBusPendingCallWatcher*)));
88 
89     QDBusConnection::systemBus().connect(QLatin1String(CONNMAN_SERVICE),
90                            QLatin1String(CONNMAN_MANAGER_PATH),
91                            QLatin1String(CONNMAN_SERVICE_INTERFACE),
92                            QLatin1String("PropertyChanged"),
93                            this,SLOT(changedProperty(QString,QDBusVariant)));
94 
95 
96     QDBusConnection::systemBus().connect(QLatin1String(CONNMAN_SERVICE),
97                            QLatin1String(CONNMAN_MANAGER_PATH),
98                            QLatin1String(CONNMAN_SERVICE_INTERFACE),
99                            QLatin1String("TechnologyAdded"),
100                            this,SLOT(technologyAdded(QDBusObjectPath,QVariantMap)));
101 
102     QDBusConnection::systemBus().connect(QLatin1String(CONNMAN_SERVICE),
103                            QLatin1String(CONNMAN_MANAGER_PATH),
104                            QLatin1String(CONNMAN_SERVICE_INTERFACE),
105                            QLatin1String("TechnologyRemoved"),
106                            this,SLOT(technologyRemoved(QDBusObjectPath)));
107 
108     QDBusPendingReply<ConnmanMapList> serv_reply = asyncCall(QLatin1String("GetServices"));
109     QDBusPendingCallWatcher *watcher2 = new QDBusPendingCallWatcher(serv_reply, this);
110 
111     QObject::connect(watcher2,SIGNAL(finished(QDBusPendingCallWatcher*)),
112                 this, SLOT(servicesReply(QDBusPendingCallWatcher*)));
113 
114 }
115 
~QConnmanManagerInterface()116 QConnmanManagerInterface::~QConnmanManagerInterface()
117 {
118 }
119 
changedProperty(const QString & name,const QDBusVariant & value)120 void QConnmanManagerInterface::changedProperty(const QString &name, const QDBusVariant &value)
121 {
122     propertiesCacheMap[name] = value.variant();
123 }
124 
propertiesReply(QDBusPendingCallWatcher * call)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 
servicesReply(QDBusPendingCallWatcher * call)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 
connectNotify(const QMetaMethod & signal)153 void QConnmanManagerInterface::connectNotify(const QMetaMethod &signal)
154 {
155     static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QConnmanManagerInterface::propertyChanged);
156     if (signal == propertyChangedSignal) {
157         if (!connection().connect(QLatin1String(CONNMAN_SERVICE),
158                                QLatin1String(CONNMAN_MANAGER_PATH),
159                                QLatin1String(CONNMAN_MANAGER_INTERFACE),
160                                QLatin1String("PropertyChanged"),
161                                    this,SIGNAL(propertyChanged(QString,QDBusVariant)))) {
162             qWarning("PropertyChanged not connected");
163         }
164     }
165 
166     static const QMetaMethod servicesChangedSignal = QMetaMethod::fromSignal(&QConnmanManagerInterface::servicesChanged);
167     if (signal == servicesChangedSignal) {
168         if (!connection().connect(QLatin1String(CONNMAN_SERVICE),
169                                QLatin1String(CONNMAN_MANAGER_PATH),
170                                QLatin1String(CONNMAN_MANAGER_INTERFACE),
171                                QLatin1String("ServicesChanged"),
172                                this,SLOT(onServicesChanged(ConnmanMapList,QList<QDBusObjectPath>)))) {
173             qWarning("servicesChanged not connected");
174         }
175     }
176 }
177 
onServicesChanged(const ConnmanMapList & changed,const QList<QDBusObjectPath> & removed)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 
getProperty(const QString & property)189 QVariant QConnmanManagerInterface::getProperty(const QString &property)
190 {
191     QVariant var;
192     var = propertiesCacheMap.value(property);
193     return var;
194 }
195 
getProperties()196 QVariantMap QConnmanManagerInterface::getProperties()
197 {
198     if (propertiesCacheMap.isEmpty()) {
199         QDBusPendingReply<QVariantMap> reply = call(QLatin1String("GetProperties"));
200         reply.waitForFinished();
201         if (!reply.isError()) {
202             propertiesCacheMap = reply.value();
203         }
204     }
205     return propertiesCacheMap;
206 }
207 
getState()208 QString QConnmanManagerInterface::getState()
209 {
210     return getProperty(QStringLiteral("State")).toString();
211 }
212 
getOfflineMode()213 bool QConnmanManagerInterface::getOfflineMode()
214 {
215     QVariant var = getProperty(QStringLiteral("OfflineMode"));
216     return qdbus_cast<bool>(var);
217 }
218 
getTechnologies()219 QStringList QConnmanManagerInterface::getTechnologies()
220 {
221     if (technologiesMap.isEmpty()) {
222         QDBusPendingReply<ConnmanMapList> reply = call(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(map.objectPath.path())) {
228                     technologyAdded(map.objectPath, map.propertyMap);
229                 }
230             }
231         }
232     }
233     return technologiesMap.keys();
234 }
235 
getServices()236 QStringList QConnmanManagerInterface::getServices()
237 {
238     if (servicesList.isEmpty()) {
239         QDBusPendingReply<ConnmanMapList> reply = call(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 
requestScan(const QString & type)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 
technologyAdded(const QDBusObjectPath & path,const QVariantMap &)264 void QConnmanManagerInterface::technologyAdded(const QDBusObjectPath &path, const QVariantMap &)
265 {
266     if (!technologiesList.contains(path.path())) {
267         technologiesList << path.path();
268         QConnmanTechnologyInterface *tech;
269         tech = new QConnmanTechnologyInterface(path.path(),this);
270         technologiesMap.insert(path.path(),tech);
271         connect(tech,SIGNAL(scanFinished(bool)),this,SIGNAL(scanFinished(bool)));
272     }
273 }
274 
technologyRemoved(const QDBusObjectPath & path)275 void QConnmanManagerInterface::technologyRemoved(const QDBusObjectPath &path)
276 {
277     if (technologiesList.contains(path.path())) {
278         technologiesList.removeOne(path.path());
279         QConnmanTechnologyInterface * tech = technologiesMap.take(path.path());
280         delete tech;
281     }
282 }
283 
QConnmanServiceInterface(const QString & dbusPathName,QObject * parent)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(QLatin1String("GetProperties"));
291 
292     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(props_reply, this);
293 
294     QObject::connect(watcher,SIGNAL(finished(QDBusPendingCallWatcher*)),
295             this, SLOT(propertiesReply(QDBusPendingCallWatcher*)));
296 
297     QDBusConnection::systemBus().connect(QLatin1String(CONNMAN_SERVICE),
298                            path(),
299                            QLatin1String(CONNMAN_SERVICE_INTERFACE),
300                            QLatin1String("PropertyChanged"),
301                            this,SLOT(changedProperty(QString,QDBusVariant)));
302 }
303 
~QConnmanServiceInterface()304 QConnmanServiceInterface::~QConnmanServiceInterface()
305 {
306 }
307 
getProperties()308 QVariantMap QConnmanServiceInterface::getProperties()
309 {
310     if (propertiesCacheMap.isEmpty()) {
311         QDBusPendingReply<QVariantMap> reply = call(QLatin1String("GetProperties"));
312         reply.waitForFinished();
313         if (!reply.isError()) {
314             propertiesCacheMap = reply.value();
315             Q_EMIT propertiesReady();
316         }
317     }
318     return propertiesCacheMap;
319 }
320 
propertiesReply(QDBusPendingCallWatcher * call)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 
connectNotify(const QMetaMethod & signal)332 void QConnmanServiceInterface::connectNotify(const QMetaMethod &signal)
333 {
334     static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QConnmanServiceInterface::propertyChanged);
335     if (signal == propertyChangedSignal) {
336         QDBusConnection::systemBus().connect(QLatin1String(CONNMAN_SERVICE),
337                                path(),
338                                QLatin1String(CONNMAN_SERVICE_INTERFACE),
339                                QLatin1String("PropertyChanged"),
340                                this,SIGNAL(propertyChanged(QString,QDBusVariant)));
341     }
342 }
343 
changedProperty(const QString & name,const QDBusVariant & value)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(value.variant().toString());
349 }
350 
getProperty(const QString & property)351 QVariant QConnmanServiceInterface::getProperty(const QString &property)
352 {
353     QVariant var;
354     QVariantMap map = getProperties();
355     var = map.value(property);
356     return var;
357 }
358 
connect()359 void QConnmanServiceInterface::connect()
360 {
361     asyncCall(QLatin1String("Connect"));
362 }
363 
disconnect()364 void QConnmanServiceInterface::disconnect()
365 {
366     asyncCall(QLatin1String("Disconnect"));
367 }
368 
remove()369 void QConnmanServiceInterface::remove()
370 {
371     asyncCall(QLatin1String("Remove"));
372 }
373 
374 // properties
state()375 QString QConnmanServiceInterface::state()
376 {
377     QVariant var = getProperty(QStringLiteral("State"));
378     return qdbus_cast<QString>(var);
379 }
380 
lastError()381 QString QConnmanServiceInterface::lastError()
382 {
383     QVariant var = getProperty(QStringLiteral("Error"));
384     return qdbus_cast<QString>(var);
385 }
386 
name()387 QString QConnmanServiceInterface::name()
388 {
389     QVariant var = getProperty(QStringLiteral("Name"));
390     return qdbus_cast<QString>(var);
391 }
392 
type()393 QString QConnmanServiceInterface::type()
394 {
395     QVariant var = getProperty(QStringLiteral("Type"));
396     return qdbus_cast<QString>(var);
397 }
398 
security()399 QString QConnmanServiceInterface::security()
400 {
401     QVariant var = getProperty(QStringLiteral("Security"));
402     return qdbus_cast<QString>(var);
403 }
404 
favorite()405 bool QConnmanServiceInterface::favorite()
406 {
407     QVariant var = getProperty(QStringLiteral("Favorite"));
408     return qdbus_cast<bool>(var);
409 }
410 
autoConnect()411 bool QConnmanServiceInterface::autoConnect()
412 {
413     QVariant var = getProperty(QStringLiteral("AutoConnect"));
414     return qdbus_cast<bool>(var);
415 }
416 
roaming()417 bool QConnmanServiceInterface::roaming()
418 {
419     QVariant var = getProperty(QStringLiteral("Roaming"));
420     return qdbus_cast<bool>(var);
421 }
422 
ethernet()423 QVariantMap QConnmanServiceInterface::ethernet()
424 {
425     QVariant var = getProperty(QStringLiteral("Ethernet"));
426     return qdbus_cast<QVariantMap >(var);
427 }
428 
serviceInterface()429 QString QConnmanServiceInterface::serviceInterface()
430 {
431     QVariantMap map = ethernet();
432     return map.value(QStringLiteral("Interface")).toString();
433 }
434 
isOfflineMode()435 bool QConnmanServiceInterface::isOfflineMode()
436 {
437     QVariant var = getProperty(QStringLiteral("OfflineMode"));
438     return qdbus_cast<bool>(var);
439 }
440 
services()441 QStringList QConnmanServiceInterface::services()
442 {
443     QVariant var = getProperty(QStringLiteral("Services"));
444     return qdbus_cast<QStringList>(var);
445 }
446 
447 //////////////////////////
QConnmanTechnologyInterface(const QString & dbusPathName,QObject * parent)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 
~QConnmanTechnologyInterface()456 QConnmanTechnologyInterface::~QConnmanTechnologyInterface()
457 {
458 }
459 
connectNotify(const QMetaMethod & signal)460 void QConnmanTechnologyInterface::connectNotify(const QMetaMethod &signal)
461 {
462     static const QMetaMethod propertyChangedSignal = QMetaMethod::fromSignal(&QConnmanTechnologyInterface::propertyChanged);
463     if (signal == propertyChangedSignal) {
464         QDBusConnection::systemBus().connect(QLatin1String(CONNMAN_SERVICE),
465                                path(),
466                                QLatin1String(CONNMAN_TECHNOLOGY_INTERFACE),
467                                QLatin1String("PropertyChanged"),
468                                this,SIGNAL(propertyChanged(QString,QDBusVariant)));
469     }
470 }
471 
properties()472 QVariantMap QConnmanTechnologyInterface::properties()
473 {
474     if (propertiesMap.isEmpty()) {
475         QDBusPendingReply<QVariantMap> reply = call(QLatin1String("GetProperties"));
476         reply.waitForFinished();
477         propertiesMap = reply.value();
478     }
479     return propertiesMap;
480 }
481 
getProperty(const QString & property)482 QVariant QConnmanTechnologyInterface::getProperty(const QString &property)
483 {
484     QVariant var;
485     QVariantMap map = properties();
486     var = map.value(property);
487     return var;
488 }
489 
type()490 QString QConnmanTechnologyInterface::type()
491 {
492     QVariant var = getProperty(QStringLiteral("Type"));
493     return qdbus_cast<QString>(var);
494 }
495 
scan()496 void QConnmanTechnologyInterface::scan()
497 {
498     QDBusPendingReply<> reply = asyncCall(QLatin1String("Scan"));
499     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
500     connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
501             this, SLOT(scanReply(QDBusPendingCallWatcher*)));
502 }
503 
scanReply(QDBusPendingCallWatcher * call)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(props_reply.isError());
511     call->deleteLater();
512 }
513 
514 QT_END_NAMESPACE
515 
516 #endif // QT_NO_DBUS
517