From 27515546a0389ee35514a646b41e28f9a811b180 Mon Sep 17 00:00:00 2001 From: Vineet Garg Date: Sat, 25 Jul 2015 17:15:19 +0530 Subject: [PATCH] Now per device per link type pairing handlers are there --- core/backends/devicelink.h | 4 ++ core/backends/lan/landevicelink.cpp | 13 +++- core/backends/lan/landevicelink.h | 2 + core/backends/lan/lanlinkprovider.cpp | 3 - core/backends/lan/lanpairinghandler.cpp | 61 ++++++++++++++----- core/backends/lan/lanpairinghandler.h | 26 +++++--- core/backends/lan/server.h | 1 + core/backends/linkprovider.h | 5 -- core/backends/loopback/loopbackdevicelink.cpp | 10 +++ core/backends/loopback/loopbackdevicelink.h | 2 + core/backends/pairinghandler.cpp | 19 +++++- core/backends/pairinghandler.h | 34 +++++++---- core/device.cpp | 57 ++++++++--------- core/device.h | 10 +-- plugins/sftp/mounter.h | 2 + 15 files changed, 172 insertions(+), 77 deletions(-) diff --git a/core/backends/devicelink.h b/core/backends/devicelink.h index 0ae6c0090..e0725079c 100644 --- a/core/backends/devicelink.h +++ b/core/backends/devicelink.h @@ -25,6 +25,7 @@ #include #include "core/networkpackage.h" +#include "pairinghandler.h" class NetworkPackage; class LinkProvider; @@ -38,9 +39,12 @@ public: DeviceLink(const QString& deviceId, LinkProvider* parent); virtual ~DeviceLink() { }; + virtual QString name() = 0; + const QString& deviceId() { return mDeviceId; } LinkProvider* provider() { return mLinkProvider; } + virtual PairingHandler* createPairingHandler(Device* device) = 0; virtual bool sendPackage(NetworkPackage& np) = 0; virtual bool sendPackageEncrypted(QCA::PublicKey& publicKey, NetworkPackage& np) = 0; diff --git a/core/backends/lan/landevicelink.cpp b/core/backends/lan/landevicelink.cpp index 8021396c5..3cd26cbc6 100644 --- a/core/backends/lan/landevicelink.cpp +++ b/core/backends/lan/landevicelink.cpp @@ -30,6 +30,7 @@ #include "uploadjob.h" #include "downloadjob.h" #include "socketlinereader.h" +#include "lanpairinghandler.h" LanDeviceLink::LanDeviceLink(const QString& deviceId, LinkProvider* parent, QSslSocket* socket) : DeviceLink(deviceId, parent) @@ -49,10 +50,20 @@ LanDeviceLink::LanDeviceLink(const QString& deviceId, LinkProvider* parent, QSsl socket->setParent(this); } -void LanDeviceLink::setOnSsl(bool value) { +QString LanDeviceLink::name() +{ + return "LanDeviceLink"; +} + +void LanDeviceLink::setOnSsl(bool value) +{ onSsl = value; } +PairingHandler* LanDeviceLink::createPairingHandler(Device* device) +{ + return new LanPairingHandler(device); +} bool LanDeviceLink::sendPackageEncrypted(QCA::PublicKey& key, NetworkPackage& np) { diff --git a/core/backends/lan/landevicelink.h b/core/backends/lan/landevicelink.h index d4507ecf6..4d59f9247 100644 --- a/core/backends/lan/landevicelink.h +++ b/core/backends/lan/landevicelink.h @@ -38,7 +38,9 @@ class LanDeviceLink public: LanDeviceLink(const QString& deviceId, LinkProvider* parent, QSslSocket* socket); + virtual QString name(); void setOnSsl(bool value); + virtual PairingHandler* createPairingHandler(Device* device); bool sendPackage(NetworkPackage& np); bool sendPackageEncrypted(QCA::PublicKey& key, NetworkPackage& np); UploadJob* sendPayload(NetworkPackage&); diff --git a/core/backends/lan/lanlinkprovider.cpp b/core/backends/lan/lanlinkprovider.cpp index bfab2681e..b1a059f59 100644 --- a/core/backends/lan/lanlinkprovider.cpp +++ b/core/backends/lan/lanlinkprovider.cpp @@ -51,8 +51,6 @@ LanLinkProvider::LanLinkProvider() mServer = new Server(this); connect(mServer,SIGNAL(newConnection()),this, SLOT(newConnection())); - m_pairingHandler = new LanPairingHandler(); - //Detect when a network interface changes status, so we announce ourelves in the new network QNetworkConfigurationManager* networkManager; networkManager = new QNetworkConfigurationManager(this); @@ -66,7 +64,6 @@ LanLinkProvider::LanLinkProvider() LanLinkProvider::~LanLinkProvider() { - delete m_pairingHandler; } void LanLinkProvider::onStart() diff --git a/core/backends/lan/lanpairinghandler.cpp b/core/backends/lan/lanpairinghandler.cpp index 38464adda..82cc3c152 100644 --- a/core/backends/lan/lanpairinghandler.cpp +++ b/core/backends/lan/lanpairinghandler.cpp @@ -21,9 +21,15 @@ #include #include "lanpairinghandler.h" #include "networkpackagetypes.h" +#include "landevicelink.h" -LanPairingHandler::LanPairingHandler() +LanPairingHandler::LanPairingHandler(Device* device) + : PairingHandler(device) { + m_pairingTimeout.setSingleShot(true); + m_pairingTimeout.setInterval(30 * 1000); //30 seconds of timeout + connect(&m_pairingTimeout, SIGNAL(timeout()), + this, SLOT(pairingTimeout())); } void LanPairingHandler::createPairPackage(NetworkPackage& np) @@ -32,51 +38,74 @@ void LanPairingHandler::createPairPackage(NetworkPackage& np) np.set("publicKey", KdeConnectConfig::instance()->publicKey().toPEM()); } -bool LanPairingHandler::packageReceived(Device *device,const NetworkPackage& np) +bool LanPairingHandler::packageReceived(const NetworkPackage& np) { + m_pairingTimeout.stop(); //Retrieve their public key QString keyString = np.get("publicKey"); - device->setPublicKey(QCA::RSAPublicKey::fromPEM(keyString)); - if (device->publicKey().isNull()) { + m_device->setPublicKey(QCA::RSAPublicKey::fromPEM(keyString)); + if (m_device->publicKey().isNull()) { return false; } return true; } -bool LanPairingHandler::requestPairing(Device *device) +bool LanPairingHandler::requestPairing() { NetworkPackage np(PACKAGE_TYPE_PAIR); createPairPackage(np); - bool success = device->sendPackage(np); + bool success; + Q_FOREACH(DeviceLink* dl, m_deviceLinks) { + success = dl->sendPackage(np); + } + m_pairingTimeout.start(); return success; } -bool LanPairingHandler::acceptPairing(Device *device) +bool LanPairingHandler::acceptPairing() { NetworkPackage np(PACKAGE_TYPE_PAIR); createPairPackage(np); - bool success = device->sendPackage(np); + bool success; + Q_FOREACH(DeviceLink* dl, m_deviceLinks) { + success = dl->sendPackage(np); + } return success; } -void LanPairingHandler::rejectPairing(Device *device) +void LanPairingHandler::rejectPairing() { // TODO : check status of reject pairing NetworkPackage np(PACKAGE_TYPE_PAIR); np.set("pair", false); - device->sendPackage(np); + Q_FOREACH(DeviceLink* dl, m_deviceLinks) { + dl->sendPackage(np); + } } -void LanPairingHandler::pairingDone(Device *device) +void LanPairingHandler::pairingDone() { // No need to worry, if either of certificate or public key is null an empty qstring will be returned - KdeConnectConfig::instance()->setDeviceProperty(device->id(), "key", device->publicKey().toPEM()); - KdeConnectConfig::instance()->setDeviceProperty(device->id(), "certificate", QString(device->certificate().toPem())); + KdeConnectConfig::instance()->setDeviceProperty(m_device->id(), "key", m_device->publicKey().toPEM()); + KdeConnectConfig::instance()->setDeviceProperty(m_device->id(), "certificate", QString(m_device->certificate().toPem())); + + m_pairingTimeout.stop(); // Just in case it is started } -void LanPairingHandler::unpair(Device *device) { +void LanPairingHandler::unpair() { NetworkPackage np(PACKAGE_TYPE_PAIR); np.set("pair", false); - bool success = device->sendPackage(np); - Q_UNUSED(success); + Q_FOREACH(DeviceLink* dl, m_deviceLinks) { + dl->sendPackage(np); + } +} + +void LanPairingHandler::pairingTimeout() +{ + NetworkPackage np(PACKAGE_TYPE_PAIR); + np.set("pair", false); + Q_FOREACH(DeviceLink* dl, m_deviceLinks) { + dl->sendPackage(np); + } + m_device->pairingTimeout(); } diff --git a/core/backends/lan/lanpairinghandler.h b/core/backends/lan/lanpairinghandler.h index e953f38fe..3651aef66 100644 --- a/core/backends/lan/lanpairinghandler.h +++ b/core/backends/lan/lanpairinghandler.h @@ -21,22 +21,34 @@ #ifndef KDECONNECT_LANPAIRINGHANDLER_H #define KDECONNECT_LANPAIRINGHANDLER_H +#include +#include + +#include "../../device.h" #include "../pairinghandler.h" +// This class is used pairing related stuff. It has direct access to links and can directly send packages class LanPairingHandler : public PairingHandler { + +private: + QTimer m_pairingTimeout; + +private Q_SLOTS: + void pairingTimeout(); + public: - LanPairingHandler(); + LanPairingHandler(Device* device); virtual ~LanPairingHandler() { } virtual void createPairPackage(NetworkPackage& np) Q_DECL_OVERRIDE; - virtual bool packageReceived(Device *device,const NetworkPackage& np) Q_DECL_OVERRIDE; - virtual bool requestPairing(Device *device) Q_DECL_OVERRIDE; - virtual bool acceptPairing(Device *device) Q_DECL_OVERRIDE; - virtual void rejectPairing(Device *device) Q_DECL_OVERRIDE; - virtual void pairingDone(Device *device) Q_DECL_OVERRIDE; - virtual void unpair(Device* device) Q_DECL_OVERRIDE; + virtual bool packageReceived(const NetworkPackage& np) Q_DECL_OVERRIDE; + virtual bool requestPairing() Q_DECL_OVERRIDE; + virtual bool acceptPairing() Q_DECL_OVERRIDE; + virtual void rejectPairing() Q_DECL_OVERRIDE; + virtual void pairingDone() Q_DECL_OVERRIDE; + virtual void unpair() Q_DECL_OVERRIDE; }; diff --git a/core/backends/lan/server.h b/core/backends/lan/server.h index a4e04ba7c..e0cabe694 100644 --- a/core/backends/lan/server.h +++ b/core/backends/lan/server.h @@ -25,6 +25,7 @@ #include #include +// This class overrides QTcpServer to bind QSslSocket to native socket descriptor instead of QTcpSocket class Server : public QTcpServer { diff --git a/core/backends/linkprovider.h b/core/backends/linkprovider.h index 0907756fe..4b1cf831b 100644 --- a/core/backends/linkprovider.h +++ b/core/backends/linkprovider.h @@ -46,11 +46,6 @@ public: virtual QString name() = 0; virtual int priority() = 0; - PairingHandler* pairingHandler() { return m_pairingHandler;} - -protected: - PairingHandler* m_pairingHandler; - public Q_SLOTS: virtual void onStart() = 0; diff --git a/core/backends/loopback/loopbackdevicelink.cpp b/core/backends/loopback/loopbackdevicelink.cpp index 718c5b8fd..b95cffacb 100644 --- a/core/backends/loopback/loopbackdevicelink.cpp +++ b/core/backends/loopback/loopbackdevicelink.cpp @@ -21,6 +21,7 @@ #include "loopbackdevicelink.h" #include "loopbacklinkprovider.h" +#include "../lan/lanpairinghandler.h" LoopbackDeviceLink::LoopbackDeviceLink(const QString& deviceId, LoopbackLinkProvider* provider) : DeviceLink(deviceId, provider) @@ -28,6 +29,15 @@ LoopbackDeviceLink::LoopbackDeviceLink(const QString& deviceId, LoopbackLinkProv } +QString LoopbackDeviceLink::name() +{ + return "LoopbackDeviceLink"; +} + +PairingHandler* LoopbackDeviceLink::createPairingHandler(Device *device) +{ + return new LanPairingHandler(device); +} bool LoopbackDeviceLink::sendPackageEncrypted(QCA::PublicKey& key, NetworkPackage& input) { if (mPrivateKey.isNull() || key.isNull()) { diff --git a/core/backends/loopback/loopbackdevicelink.h b/core/backends/loopback/loopbackdevicelink.h index 9d1ae14e6..906456aeb 100644 --- a/core/backends/loopback/loopbackdevicelink.h +++ b/core/backends/loopback/loopbackdevicelink.h @@ -32,6 +32,8 @@ class LoopbackDeviceLink public: LoopbackDeviceLink(const QString& d, LoopbackLinkProvider* a); + virtual QString name(); + virtual PairingHandler* createPairingHandler(Device* device); virtual bool sendPackage(NetworkPackage& np); virtual bool sendPackageEncrypted(QCA::PublicKey& publicKey, NetworkPackage& np); diff --git a/core/backends/pairinghandler.cpp b/core/backends/pairinghandler.cpp index 6a1eab722..38ad968db 100644 --- a/core/backends/pairinghandler.cpp +++ b/core/backends/pairinghandler.cpp @@ -20,6 +20,21 @@ #include "pairinghandler.h" -PairingHandler::PairingHandler() { - //gcc complains if we don't add something to compile on a class with virtual functions +PairingHandler::PairingHandler(Device* device) +{ + m_device = device; +} + +void PairingHandler::addLink(DeviceLink *dl) +{ + m_deviceLinks.append(dl); +} + +void PairingHandler::linkDestroyed(QObject* o) +{ + DeviceLink* dl = static_cast(o); + m_deviceLinks.removeOne(dl); + if (m_deviceLinks.isEmpty()) { + Q_EMIT noLinkAvailable(); + } } \ No newline at end of file diff --git a/core/backends/pairinghandler.h b/core/backends/pairinghandler.h index 8aece5c0b..7b4eea7dc 100644 --- a/core/backends/pairinghandler.h +++ b/core/backends/pairinghandler.h @@ -21,23 +21,35 @@ #ifndef KDECONNECT_PAIRINGHANDLER_H #define KDECONNECT_PAIRINGHANDLER_H +#include "device.h" +#include "networkpackage.h" +#include "devicelink.h" -#include -#include - -class PairingHandler { +class PairingHandler : public QObject +{ + Q_OBJECT +protected: + Device* m_device; + QVector m_deviceLinks; public: - PairingHandler(); + PairingHandler(Device* device); virtual ~PairingHandler() { } + void addLink(DeviceLink* dl); virtual void createPairPackage(NetworkPackage& np) = 0; - virtual bool packageReceived(Device *device,const NetworkPackage& np) = 0; - virtual bool requestPairing(Device *device) = 0; - virtual bool acceptPairing(Device *device) = 0; - virtual void rejectPairing(Device *device) = 0; - virtual void pairingDone(Device *device) = 0; - virtual void unpair(Device *device) = 0; + virtual bool packageReceived(const NetworkPackage& np) = 0; + virtual bool requestPairing() = 0; + virtual bool acceptPairing() = 0; + virtual void rejectPairing() = 0; + virtual void pairingDone() = 0; + virtual void unpair() = 0; + +public Q_SLOTS: + void linkDestroyed(QObject*); + +Q_SIGNALS: + void noLinkAvailable(); }; diff --git a/core/device.cpp b/core/device.cpp index 327edfe4f..4c9c19ada 100644 --- a/core/device.cpp +++ b/core/device.cpp @@ -58,11 +58,6 @@ Device::Device(QObject* parent, const QString& id) m_deviceType = str2type(info.deviceType); m_publicKey = QCA::RSAPublicKey::fromPEM(info.publicKey); - m_pairingTimeout.setSingleShot(true); - m_pairingTimeout.setInterval(30 * 1000); //30 seconds of timeout - connect(&m_pairingTimeout, SIGNAL(timeout()), - this, SLOT(pairingTimeout())); - //Register in bus QDBusConnection::sessionBus().registerObject(dbusPath(), this, QDBusConnection::ExportScriptableContents | QDBusConnection::ExportAdaptors); } @@ -93,7 +88,7 @@ Device::Device(QObject* parent, const NetworkPackage& identityPackage, DeviceLin Device::~Device() { - + Q_FOREACH(PairingHandler* ph, m_pairingHandlers) delete ph; // Delete all pairing handlers on deletion of device } bool Device::hasPlugin(const QString& name) const @@ -209,8 +204,8 @@ void Device::requestPair() m_pairStatus = Device::Requested; //Send our own public key - Q_FOREACH(DeviceLink* dl, m_deviceLinks) { - bool success = dl->provider()->pairingHandler()->requestPairing(this); + Q_FOREACH(PairingHandler* ph, m_pairingHandlers.values()) { + bool success = ph->requestPairing(); if (!success) { m_pairStatus = Device::NotPaired; @@ -222,15 +217,13 @@ void Device::requestPair() if (m_pairStatus == Device::Paired) { return; } - - m_pairingTimeout.start(); } void Device::unpair() { - Q_FOREACH(DeviceLink* dl, m_deviceLinks) { - dl->provider()->pairingHandler()->unpair(this); + Q_FOREACH(PairingHandler* ph, m_pairingHandlers.values()) { + ph->unpair(); } unpairInternal(); @@ -249,9 +242,6 @@ void Device::unpairInternal() void Device::pairingTimeout() { - NetworkPackage np(PACKAGE_TYPE_PAIR); - np.set("pair", false); - sendPackage(np); m_pairStatus = Device::NotPaired; Q_EMIT pairingFailed(i18n("Timed out")); } @@ -302,6 +292,15 @@ void Device::addLink(const NetworkPackage& identityPackage, DeviceLink* link) plugin->connected(); } } + + // One pairing handler per type of device link, so check if there is already a pairing handler of same type, if not add it to the list + if (!m_pairingHandlers.contains(link->name())) { + PairingHandler* pairingHandler = link->createPairingHandler(this); + m_pairingHandlers.insert(link->name(), pairingHandler); + connect(m_pairingHandlers[link->name()], SIGNAL(noLinkAvailable()), this, SLOT(destroyPairingHandler())); + } + m_pairingHandlers[link->name()]->addLink(link); + connect(link, SIGNAL(destroyed(QObject*)), m_pairingHandlers[link->name()], SLOT(linkDestroyed(QObject*))); } void Device::linkDestroyed(QObject* o) @@ -321,6 +320,13 @@ void Device::removeLink(DeviceLink* link) } } +void Device::destroyPairingHandler() +{ + PairingHandler* ph = qobject_cast(sender()); + m_pairingHandlers.remove(m_pairingHandlers.key(ph)); + delete ph; +} + bool Device::sendPackage(NetworkPackage& np) { if (np.type() != PACKAGE_TYPE_PAIR && isPaired()) { @@ -349,12 +355,11 @@ void Device::privateReceivedPackage(const NetworkPackage& np) qCDebug(KDECONNECT_CORE) << "Already" << (wantsPair? "paired":"unpaired"); if (m_pairStatus == Device::Requested) { m_pairStatus = Device::NotPaired; - m_pairingTimeout.stop(); Q_EMIT pairingFailed(i18n("Canceled by other peer")); } else if (m_pairStatus == Device::Paired) { // If other request's pairing, and we have pair status Paired, send accept pairing - Q_FOREACH(DeviceLink* dl, m_deviceLinks) { - dl->provider()->pairingHandler()->acceptPairing(this); + Q_FOREACH(PairingHandler* ph, m_pairingHandlers.values()) { + ph->acceptPairing(); } } return; @@ -362,12 +367,11 @@ void Device::privateReceivedPackage(const NetworkPackage& np) if (wantsPair) { - Q_FOREACH(DeviceLink* dl, m_deviceLinks) { - bool success = dl->provider()->pairingHandler()->packageReceived(this, np); + Q_FOREACH(PairingHandler* ph, m_pairingHandlers.values()) { + bool success = ph->packageReceived(np); if (!success) { if (m_pairStatus == Device::Requested) { m_pairStatus = Device::NotPaired; - m_pairingTimeout.stop(); } Q_EMIT pairingFailed(i18n("Received incorrect key")); return; @@ -395,7 +399,6 @@ void Device::privateReceivedPackage(const NetworkPackage& np) m_pairStatus = Device::NotPaired; if (prevPairStatus == Device::Requested) { - m_pairingTimeout.stop(); Q_EMIT pairingFailed(i18n("Canceled by other peer")); } else if (prevPairStatus == Device::Paired) { unpairInternal(); @@ -431,8 +434,8 @@ void Device::rejectPairing() m_pairStatus = Device::NotPaired; - Q_FOREACH(DeviceLink* link, m_deviceLinks) { - link->provider()->pairingHandler()->rejectPairing(this); + Q_FOREACH(PairingHandler* ph, m_pairingHandlers.values()) { + ph->rejectPairing(); } Q_EMIT pairingFailed(i18n("Canceled by the user")); @@ -446,8 +449,8 @@ void Device::acceptPairing() qCDebug(KDECONNECT_CORE) << "Accepted pairing"; bool success; - Q_FOREACH(DeviceLink* link, m_deviceLinks) { - success = link->provider()->pairingHandler()->acceptPairing(this); + Q_FOREACH(PairingHandler* ph, m_pairingHandlers.values()) { + success = ph->acceptPairing(); } if (!success) { @@ -466,8 +469,6 @@ void Device::setAsPaired() m_pairStatus = Device::Paired; - m_pairingTimeout.stop(); //Just in case it was started - //Save device info in the config KdeConnectConfig::instance()->addTrustedDevice(id(), name(), type2str(m_deviceType), m_publicKey.toPEM(), QString::fromLatin1(m_certificate.toPem())); diff --git a/core/device.h b/core/device.h index 4416b1fae..1c88dfd4e 100644 --- a/core/device.h +++ b/core/device.h @@ -26,14 +26,14 @@ #include #include #include -#include #include -#include +#include #include "networkpackage.h" class DeviceLink; class KdeConnectPlugin; +class PairingHandler; class KDECONNECTCORE_EXPORT Device : public QObject @@ -109,6 +109,8 @@ public: Q_SCRIPTABLE QString pluginsConfigFile() const; + void pairingTimeout(); + public Q_SLOTS: ///sends a @p np package to the device virtual bool sendPackage(NetworkPackage& np); @@ -124,7 +126,7 @@ public Q_SLOTS: private Q_SLOTS: void privateReceivedPackage(const NetworkPackage& np); void linkDestroyed(QObject* o); - void pairingTimeout(); + void destroyPairingHandler(); Q_SIGNALS: Q_SCRIPTABLE void pluginsChanged(); @@ -154,10 +156,10 @@ private: //Fields (TODO: dPointer!) QVector m_deviceLinks; QHash m_plugins; + QMap m_pairingHandlers; QMultiMap m_pluginsByIncomingInterface; QMultiMap m_pluginsByOutgoingInterface; - QTimer m_pairingTimeout; const QSet m_incomingCapabilities; const QSet m_outgoingCapabilities; diff --git a/plugins/sftp/mounter.h b/plugins/sftp/mounter.h index 76ac860f8..41a7cbf9f 100644 --- a/plugins/sftp/mounter.h +++ b/plugins/sftp/mounter.h @@ -24,6 +24,8 @@ #include #include +#include + #include "sftpplugin.h" class Mounter