kdeconnect-kde/core/daemon.cpp

323 lines
9 KiB
C++
Raw Normal View History

2013-06-06 04:57:06 +01:00
/**
* SPDX-FileCopyrightText: 2013 Albert Vaca <albertvaka@gmail.com>
2013-06-06 04:57:06 +01:00
*
* SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
2013-06-06 04:57:06 +01:00
*/
#include "daemon.h"
#include <QDBusMetaType>
#include <QDebug>
#include <QNetworkAccessManager>
#include <QPointer>
#include <QProcess>
2013-06-06 04:57:06 +01:00
#include "core_debug.h"
#include "dbushelper.h"
#include "kdeconnectconfig.h"
#include "networkpacket.h"
#include "notificationserverinfo.h"
#ifdef KDECONNECT_BLUETOOTH
#include "backends/bluetooth/bluetoothlinkprovider.h"
#endif
#include "backends/devicelink.h"
#include "backends/lan/lanlinkprovider.h"
#include "backends/linkprovider.h"
#include "backends/loopback/loopbacklinkprovider.h"
#include "device.h"
static Daemon *s_instance = nullptr;
struct DaemonPrivate {
// Different ways to find devices and connect to them
QSet<LinkProvider *> m_linkProviders;
// Every known device
QMap<QString, Device *> m_devices;
2019-05-13 23:35:25 +01:00
bool m_testMode;
};
Daemon *Daemon::instance()
{
Q_ASSERT(s_instance != nullptr);
return s_instance;
}
Daemon::Daemon(QObject *parent, bool testMode)
: QObject(parent)
, d(new DaemonPrivate)
2013-06-06 04:57:06 +01:00
{
Q_ASSERT(!s_instance);
s_instance = this;
2019-05-13 23:35:25 +01:00
d->m_testMode = testMode;
// HACK init may call pure virtual functions from this class so it can't be called directly from the ctor
QTimer::singleShot(0, this, &Daemon::init);
}
void Daemon::init()
{
2019-05-26 19:30:39 +01:00
qCDebug(KDECONNECT_CORE) << "Daemon starting";
2014-08-11 17:53:08 +01:00
// Register on DBus
// This must happen as early as possible in the process startup to ensure
// the absolute minimum amount of blocking on logon/autostart
qDBusRegisterMetaType<QMap<QString, QString>>();
QDBusConnection::sessionBus().registerService(QStringLiteral("org.kde.kdeconnect"));
QDBusConnection::sessionBus().registerObject(QStringLiteral("/modules/kdeconnect"), this, QDBusConnection::ExportScriptableContents);
qCDebug(KDECONNECT_CORE) << "DBus registration complete";
// Load backends
2019-05-13 23:35:25 +01:00
if (d->m_testMode)
d->m_linkProviders.insert(new LoopbackLinkProvider());
2016-11-11 14:55:16 +00:00
else {
d->m_linkProviders.insert(new LanLinkProvider());
#ifdef KDECONNECT_BLUETOOTH
d->m_linkProviders.insert(new BluetoothLinkProvider());
#endif
#ifdef KDECONNECT_LOOPBACK
d->m_linkProviders.insert(new LoopbackLinkProvider());
#endif
2016-11-11 14:55:16 +00:00
}
qCDebug(KDECONNECT_CORE) << "Backends loaded";
// Read remembered paired devices
const QStringList &list = KdeConnectConfig::instance().trustedDevices();
for (const QString &id : list) {
Device *d = new Device(this, id);
// prune away devices with malformed certificates
if (d->hasInvalidCertificate()) {
qCDebug(KDECONNECT_CORE) << "Certificate for device " << id << "illegal, deleting the device";
KdeConnectConfig::instance().removeTrustedDevice(id);
} else {
addDevice(d);
}
2013-07-02 01:46:41 +01:00
}
qCDebug(KDECONNECT_CORE) << "Paired devices added";
// Listen to new devices
for (LinkProvider *a : std::as_const(d->m_linkProviders)) {
connect(a, &LinkProvider::onConnectionReceived, this, &Daemon::onNewDeviceLink);
a->onStart();
2013-06-06 04:57:06 +01:00
}
2013-06-17 11:23:08 +01:00
qCDebug(KDECONNECT_CORE) << "Link providers started";
NotificationServerInfo::instance().init();
2019-05-26 19:30:39 +01:00
qCDebug(KDECONNECT_CORE) << "Daemon started";
2013-06-17 11:23:08 +01:00
}
2013-09-26 16:49:40 +01:00
void Daemon::removeDevice(Device *device)
{
d->m_devices.remove(device->id());
device->deleteLater();
Q_EMIT deviceRemoved(device->id());
Q_EMIT deviceListChanged();
}
2013-08-07 10:29:56 +01:00
void Daemon::forceOnNetworkChange()
{
qCDebug(KDECONNECT_CORE) << "Sending onNetworkChange to" << d->m_linkProviders.size() << "LinkProviders";
for (LinkProvider *a : std::as_const(d->m_linkProviders)) {
qCDebug(KDECONNECT_CORE) << "Sending onNetworkChange to: " << a->name();
a->onNetworkChange();
2013-08-07 10:29:56 +01:00
}
}
Device *Daemon::getDevice(const QString &deviceId)
2016-07-07 00:09:07 +01:00
{
for (Device *device : std::as_const(d->m_devices)) {
2015-07-09 22:51:08 +01:00
if (device->id() == deviceId) {
return device;
}
}
2019-05-05 14:45:50 +01:00
return nullptr;
2015-07-09 22:51:08 +01:00
}
QSet<LinkProvider *> Daemon::getLinkProviders() const
{
return d->m_linkProviders;
}
QStringList Daemon::linkProviders() const
{
/*
QString allStr = QStringLiteral("all");
QString enabledStr = QStringLiteral("enabled");
QMap<QString, QString> returnValue;
for (LinkProvider *a : std::as_const(d->m_linkProviders)) {
returnValue[allStr] += a->name();
// TODO add filtering by enabled config
returnValue[enabledStr] += a->name();
}
return returnValue;*/
return QStringList();
}
2015-12-01 18:45:14 +00:00
QStringList Daemon::devices(bool onlyReachable, bool onlyTrusted) const
{
QStringList ret;
for (Device *device : std::as_const(d->m_devices)) {
if (onlyReachable && !device->isReachable())
continue;
if (onlyTrusted && !device->isPaired())
continue;
ret.append(device->id());
}
return ret;
}
QMap<QString, QString> Daemon::deviceNames(bool onlyReachable, bool onlyTrusted) const
{
QMap<QString, QString> ret;
for (Device *device : std::as_const(d->m_devices)) {
if (onlyReachable && !device->isReachable())
continue;
if (onlyTrusted && !device->isPaired())
continue;
ret[device->id()] = device->name();
}
return ret;
}
void Daemon::onNewDeviceLink(DeviceLink *link)
{
2023-07-26 20:40:52 +01:00
QString id = link->deviceId();
qCDebug(KDECONNECT_CORE) << "Device discovered" << id << "via link with priority" << link->priority();
if (d->m_devices.contains(id)) {
qCDebug(KDECONNECT_CORE) << "It is a known device" << link->deviceInfo().name;
Device *device = d->m_devices[id];
2015-06-22 03:39:04 +01:00
bool wasReachable = device->isReachable();
device->addLink(link);
2015-06-22 03:39:04 +01:00
if (!wasReachable) {
Q_EMIT deviceVisibilityChanged(id, true);
Q_EMIT deviceListChanged();
2015-06-22 03:39:04 +01:00
}
} else {
qCDebug(KDECONNECT_CORE) << "It is a new device" << link->deviceInfo().name;
Device *device = new Device(this, link);
addDevice(device);
}
}
void Daemon::onDeviceStatusChanged()
{
Device *device = (Device *)sender();
// qCDebug(KDECONNECT_CORE) << "Device" << device->name() << "status changed. Reachable:" << device->isReachable() << ". Paired: " << device->isPaired();
if (!device->isReachable() && !device->isPaired()) {
// qCDebug(KDECONNECT_CORE) << "Destroying device" << device->name();
removeDevice(device);
2015-06-22 03:39:04 +01:00
} else {
Q_EMIT deviceVisibilityChanged(device->id(), device->isReachable());
Q_EMIT deviceListChanged();
}
}
void Daemon::setAnnouncedName(const QString &name)
{
2024-05-19 15:15:39 +01:00
QString filteredName = DeviceInfo::filterName(name);
2020-08-18 15:55:48 +01:00
qCDebug(KDECONNECT_CORE) << "Announcing name";
2024-05-19 15:15:39 +01:00
KdeConnectConfig::instance().setName(filteredName);
forceOnNetworkChange();
2024-05-19 15:15:39 +01:00
Q_EMIT announcedNameChanged(filteredName);
}
void Daemon::setCustomDevices(const QStringList &addresses)
2020-08-18 15:55:48 +01:00
{
auto &config = KdeConnectConfig::instance();
2020-08-18 15:55:48 +01:00
auto customDevices = config.customDevices();
if (customDevices != addresses) {
qCDebug(KDECONNECT_CORE) << "Changed list of custom device addresses:" << addresses;
config.setCustomDevices(addresses);
Q_EMIT customDevicesChanged(addresses);
forceOnNetworkChange();
}
}
QStringList Daemon::customDevices() const
{
return KdeConnectConfig::instance().customDevices();
}
QString Daemon::announcedName()
{
return KdeConnectConfig::instance().name();
}
QNetworkAccessManager *Daemon::networkAccessManager()
{
static QPointer<QNetworkAccessManager> manager;
if (!manager) {
manager = new QNetworkAccessManager(this);
}
return manager;
}
QList<Device *> Daemon::devicesList() const
2013-06-06 04:57:06 +01:00
{
return d->m_devices.values();
}
QString Daemon::deviceIdByName(const QString &name) const
{
for (Device *device : std::as_const(d->m_devices)) {
if (device->name() == name && device->isPaired())
return device->id();
}
return {};
}
void Daemon::addDevice(Device *device)
{
const QString id = device->id();
connect(device, &Device::reachableChanged, this, &Daemon::onDeviceStatusChanged);
connect(device, &Device::pairStateChanged, this, &Daemon::onDeviceStatusChanged);
connect(device, &Device::pairStateChanged, this, &Daemon::pairingRequestsChanged);
connect(device, &Device::pairStateChanged, this, [this, device](int pairStateAsInt) {
PairState pairState = (PairState)pairStateAsInt;
if (pairState == PairState::RequestedByPeer)
askPairingConfirmation(device);
});
d->m_devices[id] = device;
Q_EMIT deviceAdded(id);
Q_EMIT deviceListChanged();
}
QStringList Daemon::pairingRequests() const
{
QStringList ret;
for (Device *dev : std::as_const(d->m_devices)) {
if (dev->isPairRequestedByPeer())
ret += dev->id();
}
return ret;
}
2013-06-06 04:57:06 +01:00
Daemon::~Daemon()
{
}
QString Daemon::selfId() const
{
return KdeConnectConfig::instance().deviceId();
}
#include "moc_daemon.cpp"