Members of the KDE Community are recommended to subscribe to the kde-community mailing list at https://mail.kde.org/mailman/listinfo/kde-community to allow them to participate in important discussions and receive other important announcements

Commit cf6cbd29 authored by Albert Vaca Cintora's avatar Albert Vaca Cintora

WIPx3!

parent 82bc73dd
......@@ -28,9 +28,18 @@ DeviceLink::DeviceLink(const QString& deviceId, LinkProvider* parent, Connection
, mDeviceId(deviceId)
, mConnectionSource(connectionSource)
, mLinkProvider(parent)
, mPairStatus(NotPaired)
{
Q_ASSERT(!deviceId.isEmpty());
setProperty("deviceId", deviceId);
}
void DeviceLink::setPairStatus(DeviceLink::PairStatus status)
{
if (mPairStatus != status) {
mPairStatus = status;
Q_EMIT pairStatusChanged(status);
}
}
......@@ -37,6 +37,7 @@ class DeviceLink
Q_OBJECT
public:
enum PairStatus : bool { NotPaired, Paired };
enum ConnectionStarted : bool { Locally, Remotely };
DeviceLink(const QString& deviceId, LinkProvider* parent, ConnectionStarted connectionSource);
......@@ -47,16 +48,21 @@ public:
const QString& deviceId() { return mDeviceId; }
LinkProvider* provider() { return mLinkProvider; }
virtual PairingHandler* createPairingHandler(Device* device) = 0;
virtual bool sendPackage(NetworkPackage& np) = 0;
virtual bool sendPackageEncrypted(NetworkPackage& np) = 0;
ConnectionStarted connectionSource() const {
return mConnectionSource;
}
//user actions
virtual void requestPairing() = 0;
virtual void unpair() = 0;
ConnectionStarted connectionSource() const { return mConnectionSource; }
PairStatus pairStatus() const { return mPairStatus; }
void setPairStatus(PairStatus status);
Q_SIGNALS:
void receivedPackage(const NetworkPackage& np);
void pairStatusChanged(DeviceLink::PairStatus status);
protected:
QCA::PrivateKey mPrivateKey;
......@@ -65,6 +71,7 @@ private:
const QString mDeviceId;
const ConnectionStarted mConnectionSource;
LinkProvider* mLinkProvider;
PairStatus mPairStatus;
};
......
......@@ -25,7 +25,7 @@
#include "uploadjob.h"
#include "downloadjob.h"
#include "socketlinereader.h"
#include "lanpairinghandler.h"
#include "lanlinkprovider.h"
LanDeviceLink::LanDeviceLink(const QString& deviceId, LinkProvider* parent, QSslSocket* socket, ConnectionStarted connectionSource)
: DeviceLink(deviceId, parent, connectionSource)
......@@ -49,11 +49,6 @@ QString LanDeviceLink::name()
return "LanLink"; // Should be same in both android and kde version
}
PairingHandler* LanDeviceLink::createPairingHandler(Device* device)
{
return new LanPairingHandler(device->id());
}
bool LanDeviceLink::sendPackageEncrypted(NetworkPackage& np)
{
if (np.hasPayload()) {
......@@ -124,3 +119,13 @@ void LanDeviceLink::dataReceived()
}
}
void LanDeviceLink::requestPairing()
{
qobject_cast<LanLinkProvider*>(provider())->requestPairing(deviceId());
}
void LanDeviceLink::unpair()
{
setPairStatus(NotPaired);
}
......@@ -39,18 +39,22 @@ public:
LanDeviceLink(const QString& deviceId, LinkProvider* parent, QSslSocket* socket, ConnectionStarted connectionSource);
virtual QString name() Q_DECL_OVERRIDE;
virtual PairingHandler* createPairingHandler(Device* device) Q_DECL_OVERRIDE;
bool sendPackage(NetworkPackage& np) override;
bool sendPackageEncrypted(NetworkPackage& np) override;
UploadJob* sendPayload(NetworkPackage& np);
virtual void unpair() override;
void requestPairing();
private Q_SLOTS:
void dataReceived();
private:
SocketLineReader* mSocketLineReader;
bool onSsl;
QCA::PublicKey m_publicKey;
QSslCertificate m_certificate;
};
#endif
......@@ -37,6 +37,7 @@
#include "../../daemon.h"
#include "landevicelink.h"
#include "lanpairinghandler.h"
#include <kdeconnectconfig.h>
#include <QDBusPendingReply>
#include <QtNetwork/qsslcipher.h>
......@@ -269,7 +270,7 @@ void LanLinkProvider::sslErrors(const QList<QSslError>& errors)
disconnect(socket, SIGNAL(encrypted()), this, SLOT(encrypted()));
disconnect(socket, SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrors(QList<QSslError>)));
foreach(QSslError error, errors) {
foreach(const QSslError &error, errors) {
qCDebug(KDECONNECT_CORE) << "SSL Error :" << error.errorString();
switch (error.error()) {
case QSslError::CertificateSignatureFailed:
......@@ -438,7 +439,23 @@ void LanLinkProvider::addLink(const QString& deviceId, QSslSocket* socket, Netwo
}
mLinks[deviceLink->deviceId()] = deviceLink;
LanPairingHandler* ph = mPairingHandlers.value(deviceLink->deviceId());
if (ph) {
ph->setDeviceLink(deviceLink);
}
Q_EMIT onConnectionReceived(*receivedPackage, deviceLink);
}
void LanLinkProvider::requestPairing(const QString& deviceId)
{
LanPairingHandler* ph = mPairingHandlers.value(deviceId);
if (!ph) {
new LanPairingHandler(deviceId);
ph->setDeviceLink(mLinks[deviceId]);
mPairingHandlers[deviceId] = ph;
}
ph->requestPairing();
}
......@@ -31,6 +31,7 @@
#include "server.h"
#include "landevicelink.h"
class LanPairingHandler;
class LanLinkProvider
: public LinkProvider
{
......@@ -43,6 +44,8 @@ public:
QString name() override { return "LanLinkProvider"; }
int priority() override { return PRIORITY_HIGH; }
void requestPairing(const QString &deviceId);
public Q_SLOTS:
virtual void onNetworkChange() override;
virtual void onStart() override;
......@@ -70,6 +73,7 @@ private:
quint16 mTcpPort;
QMap<QString, DeviceLink*> mLinks;
QMap<QString, LanPairingHandler*> mPairingHandlers;
struct PendingConnect {
NetworkPackage* np;
......
......@@ -30,20 +30,12 @@
LanPairingHandler::LanPairingHandler(const QString& deviceId)
: PairingHandler()
, m_deviceId(deviceId)
, m_status(NotPaired)
{
m_pairingTimeout.setSingleShot(true);
m_pairingTimeout.setInterval(30 * 1000); //30 seconds of timeout
connect(&m_pairingTimeout, SIGNAL(timeout()),
this, SLOT(pairingTimeout()));
/*
m_publicKey = KdeConnectConfig::instance()->getDeviceProperty(deviceId, "publicKey", QString());
m_certificate = KdeConnectConfig::instance()->getDeviceProperty(deviceId, "certificate", QString());
*/
if (!m_publicKey.isNull()) {
setPairStatus(PairStatus::Paired);
} else {
setPairStatus(PairStatus::NotPaired);
}
}
void LanPairingHandler::createPairPackage(NetworkPackage& np)
......@@ -65,8 +57,8 @@ void LanPairingHandler::packageReceived(const NetworkPackage& np)
if (wantsPair == isPaired()) {
// qCDebug(KDECONNECT_CORE) << "Already" << (wantsPair? "paired":"unpaired");
if (isPairRequested()) {
setPairStatus(PairStatus::NotPaired);
Q_EMIT pairingFailed(i18n("Canceled by other peer"));
setInternalPairStatus(NotPaired);
Q_EMIT pairingError(i18n("Canceled by other peer"));
return;
} else if (isPaired()) {
/**
......@@ -74,7 +66,7 @@ void LanPairingHandler::packageReceived(const NetworkPackage& np)
* and we don't know it, unpair it internally
*/
KdeConnectConfig::instance()->removeTrustedDevice(m_deviceId);
setPairStatus(PairingHandler::NotPaired);
setInternalPairStatus(NotPaired);
}
}
......@@ -85,9 +77,9 @@ void LanPairingHandler::packageReceived(const NetworkPackage& np)
if (QCA::RSAPublicKey::fromPEM(keyString).isNull()) {
if (isPairRequested()) {
setPairStatus(PairStatus::NotPaired);
setInternalPairStatus(NotPaired);
}
Q_EMIT pairingFailed(i18n("Received incorrect key"));
Q_EMIT pairingError(i18n("Received incorrect key"));
return;
}
......@@ -105,9 +97,8 @@ void LanPairingHandler::packageReceived(const NetworkPackage& np)
return;
}
//Daemon::instance()->requestPairing(m_device);
//m_pairStatus = PairStatus::RequestedByPeer;
setPairStatus(PairStatus::RequestedByPeer);
Daemon::instance()->requestPairing(this);
setInternalPairStatus(RequestedByPeer);
}
} else { //wantsPair == false
......@@ -115,27 +106,27 @@ void LanPairingHandler::packageReceived(const NetworkPackage& np)
qCDebug(KDECONNECT_CORE) << "Unpair request";
if (isPairRequested()) {
Q_EMIT pairingFailed(i18n("Canceled by other peer"));
Q_EMIT pairingError(i18n("Canceled by other peer"));
}
setPairStatus(PairStatus::NotPaired);
setInternalPairStatus(NotPaired);
}
}
bool LanPairingHandler::requestPairing()
{
switch (pairStatus()) {
case PairStatus::Paired:
Q_EMIT pairingFailed(i18n(deviceLink()->name().append(" : Already paired").toLatin1().data()));
switch (m_status) {
case Paired:
Q_EMIT pairingError(i18n(deviceLink()->name().append(" : Already paired").toLatin1().data()));
return false;
case PairStatus::Requested:
Q_EMIT pairingFailed(i18n(deviceLink()->name().append(" : Pairing already requested for this device").toLatin1().data()));
case Requested:
Q_EMIT pairingError(i18n(deviceLink()->name().append(" : Pairing already requested for this device").toLatin1().data()));
return false;
case PairStatus::RequestedByPeer:
case RequestedByPeer:
qCDebug(KDECONNECT_CORE) << deviceLink()->name() << " : Pairing already started by the other end, accepting their request.";
acceptPairing();
return false;
case PairStatus::NotPaired:
case NotPaired:
;
}
......@@ -144,7 +135,7 @@ bool LanPairingHandler::requestPairing()
bool success;
success = deviceLink()->sendPackage(np);
if (success) {
setPairStatus(PairStatus::Requested);
setInternalPairStatus(Requested);
m_pairingTimeout.start();
}
return success;
......@@ -158,7 +149,7 @@ bool LanPairingHandler::acceptPairing()
bool success;
success = deviceLink()->sendPackage(np);
if (success) {
setPairStatus(PairStatus::Paired);
setInternalPairStatus(Paired);
}
return success;
}
......@@ -169,7 +160,7 @@ void LanPairingHandler::rejectPairing()
np.set("pair", false);
np.set("link", deviceLink()->name());
deviceLink()->sendPackage(np);
setPairStatus(PairStatus::NotPaired);
setInternalPairStatus(NotPaired);
}
void LanPairingHandler::unpair() {
......@@ -177,7 +168,7 @@ void LanPairingHandler::unpair() {
np.set("pair", false);
np.set("link", deviceLink()->name());
deviceLink()->sendPackage(np);
setPairStatus(PairStatus::NotPaired);
setInternalPairStatus(NotPaired);
}
void LanPairingHandler::pairingTimeout()
......@@ -186,6 +177,16 @@ void LanPairingHandler::pairingTimeout()
np.set("pair", false);
np.set("name", deviceLink()->name());
deviceLink()->sendPackage(np);
setPairStatus(PairStatus::NotPaired); //Will emit the change as well
Q_EMIT pairingFailed(i18n("Timed out"));
setInternalPairStatus(NotPaired); //Will emit the change as well
Q_EMIT pairingError(i18n("Timed out"));
}
void LanPairingHandler::setInternalPairStatus(LanPairingHandler::InternalPairStatus status)
{
m_status = status;
if (status == Paired) {
deviceLink()->setPairStatus(DeviceLink::Paired);
} else {
deviceLink()->setPairStatus(DeviceLink::NotPaired);
}
}
......@@ -30,6 +30,14 @@ class LanPairingHandler
: public PairingHandler
{
public:
enum InternalPairStatus {
NotPaired,
Requested,
RequestedByPeer,
Paired,
};
LanPairingHandler(const QString& deviceId);
virtual ~LanPairingHandler() { }
......@@ -40,15 +48,19 @@ public:
virtual void rejectPairing() Q_DECL_OVERRIDE;
virtual void unpair() Q_DECL_OVERRIDE;
bool isPairRequested() const { return m_status == Requested; }
bool isPaired() const { return m_status == Paired; }
private Q_SLOTS:
virtual void pairingTimeout();
void pairingTimeout();
protected:
void setInternalPairStatus(InternalPairStatus status);
QTimer m_pairingTimeout;
QString m_deviceId;
QCA::PublicKey m_publicKey;
QSslCertificate m_certificate;
InternalPairStatus m_status;
};
......
......@@ -30,7 +30,7 @@
class DeviceLink;
class LinkProvider
class KDECONNECTCORE_EXPORT LinkProvider
: public QObject
{
Q_OBJECT
......
......@@ -4,7 +4,7 @@ set(backends_kdeconnect_SRCS
backends/loopback/loopbacklinkprovider.cpp
backends/loopback/loopbackdevicelink.cpp
backends/loopback/loopbackpairinghandler.cpp
# backends/loopback/loopbackpairinghandler.cpp
PARENT_SCOPE
)
......@@ -34,10 +34,6 @@ QString LoopbackDeviceLink::name()
return "LoopbackLink"; // Should be similar to android
}
PairingHandler* LoopbackDeviceLink::createPairingHandler(Device *device)
{
return new LoopbackPairingHandler(device->id());
}
bool LoopbackDeviceLink::sendPackageEncrypted(NetworkPackage& input)
{
return sendPackage(input);
......
......@@ -33,10 +33,11 @@ public:
LoopbackDeviceLink(const QString& d, LoopbackLinkProvider* a);
virtual QString name() override;
virtual PairingHandler* createPairingHandler(Device* device) override;
virtual bool sendPackage(NetworkPackage& np) override;
virtual bool sendPackageEncrypted(NetworkPackage& np) override;
virtual void requestPairing() override {}
virtual void unpair() override {}
};
#endif
......@@ -39,10 +39,10 @@ bool LoopbackPairingHandler::requestPairing()
case PairStatus::Paired:
Q_EMIT pairingFailed(deviceLink()->name().append(" : Already paired").toLatin1().data());
return false;
case PairStatus ::Requested:
case PairStatus::Requested:
Q_EMIT pairingFailed(deviceLink()->name().append(" : Pairing already requested for this device").toLatin1().data());
return false;
case PairStatus ::RequestedByPeer:
case PairStatus::RequestedByPeer:
qCDebug(KDECONNECT_CORE) << deviceLink()->name() << " : Pairing already started by the other end, accepting their request.";
acceptPairing();
return false;
......
/**
* Copyright 2015 Vineet Garg <grg.vineet@gmail.com>
* Copyright 2015 Albert Vaca Cintora <albertvaka@gmail.com>
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
......@@ -20,15 +20,16 @@
#include "pairinghandler.h"
PairingHandler::PairingHandler()
: m_deviceLink(nullptr)
, m_pairStatus(NotPaired)
PairingHandler::PairingHandler(DeviceLink* parent)
: QObject(parent)
, m_deviceLink(parent)
{
}
void PairingHandler::setDeviceLink(DeviceLink *dl)
{
setParent(dl);
m_deviceLink = dl;
}
......@@ -37,26 +38,3 @@ DeviceLink* PairingHandler::deviceLink() const
return m_deviceLink;
}
void PairingHandler::linkDestroyed(QObject* o)
{
DeviceLink* dl = static_cast<DeviceLink*>(o);
if (dl == m_deviceLink) { // Check if same link is destroyed
m_deviceLink = Q_NULLPTR;
Q_EMIT linkNull();
}
}
void PairingHandler::setPairStatus(PairingHandler::PairStatus status)
{
if (m_pairStatus != status) {
PairStatus oldStatus = m_pairStatus;
m_pairStatus = status;
Q_EMIT pairStatusChanged(status, oldStatus);
}
}
PairingHandler::PairStatus PairingHandler::pairStatus() const
{
return m_pairStatus;
}
......@@ -37,56 +37,31 @@
* After that if any one of the link is paired, then we can say that device is paired, so new link will pair automatically
*/
class PairingHandler : public QObject
class KDECONNECTCORE_EXPORT PairingHandler : public QObject
{
Q_OBJECT
public:
//TODO: Can we simplify this to just Paired/NotPaired, and leave the detailed status as an backend-specific thing?
enum PairStatus {
NotPaired,
Requested,
RequestedByPeer,
Paired,
};
PairingHandler();
PairingHandler(DeviceLink* parent = 0);
virtual ~PairingHandler() { }
DeviceLink* deviceLink() const;
void setDeviceLink(DeviceLink* dl);
bool isPaired() const { return m_pairStatus == PairStatus::Paired; }
bool isPairRequested() const { return m_pairStatus == PairStatus::Requested; }
virtual void createPairPackage(NetworkPackage& np) = 0;
virtual void packageReceived(const NetworkPackage& np) = 0;
virtual bool requestPairing() = 0;
virtual bool acceptPairing() = 0;
virtual void rejectPairing() = 0;
virtual void unpair() = 0;
protected:
DeviceLink* deviceLink() const;
void setPairStatus(PairStatus status);
PairStatus pairStatus() const;
public Q_SLOTS:
void linkDestroyed(QObject*);
virtual void pairingTimeout() = 0;
virtual bool requestPairing() = 0;
virtual bool acceptPairing() = 0;
virtual void rejectPairing() = 0;
Q_SIGNALS:
void pairStatusChanged(PairStatus status, PairStatus previousStatus);
void pairingError(const QString& errorMessage);
private:
DeviceLink* m_deviceLink; // We keep the latest link here, if this is destroyed without new link, linkDestroyed is emitted and device will destroy pairing handler
PairStatus m_pairStatus;
Q_SIGNALS:
void pairingDone();
void unpairingDone();
void pairingFailed(const QString& error);
void linkNull();
};
......
......@@ -123,7 +123,7 @@ void Daemon::removeDevice(Device* device)
void Daemon::cleanDevices()
{
Q_FOREACH(Device* device, d->mDevices) {
if (device->pairStatus() == PairingHandler::NotPaired && device->connectionSource() == DeviceLink::ConnectionStarted::Remotely) {
if (!device->isTrusted() && device->connectionSource() == DeviceLink::ConnectionStarted::Remotely) {
removeDevice(device);
}
}
......@@ -148,12 +148,12 @@ Device *Daemon::getDevice(QString deviceId) {
return Q_NULLPTR;
}
QStringList Daemon::devices(bool onlyReachable, bool onlyPaired) const
QStringList Daemon::devices(bool onlyReachable, bool onlyTrusted) const
{
QStringList ret;
Q_FOREACH(Device* device, d->mDevices) {
if (onlyReachable && !device->isReachable()) continue;
if (onlyPaired && !device->isPaired()) continue;
if (onlyTrusted && !device->isTrusted()) continue;
ret.append(device->id());
}
return ret;
......@@ -179,7 +179,7 @@ void Daemon::onNewDeviceLink(const NetworkPackage& identityPackage, DeviceLink*
//we discard the connections that we created but it's not paired.
//we keep the remotely initiated ones, since the remotes require them
if (!isDiscoveringDevices() && !device->isPaired() && dl->connectionSource() == DeviceLink::ConnectionStarted::Locally) {
if (!isDiscoveringDevices() && !device->isTrusted() && dl->connectionSource() == DeviceLink::ConnectionStarted::Locally) {
device->deleteLater();
} else {
connect(device, SIGNAL(reachableStatusChanged()), this, SLOT(onDeviceStatusChanged()));
......@@ -197,7 +197,7 @@ void Daemon::onDeviceStatusChanged()
//qCDebug(KDECONNECT_CORE) << "Device" << device->name() << "status changed. Reachable:" << device->isReachable() << ". Paired: " << device->isPaired();
if (!device->isReachable() && !device->isPaired()) {
if (!device->isReachable() && !device->isTrusted()) {
//qCDebug(KDECONNECT_CORE) << "Destroying device" << device->name();
removeDevice(device);
} else {
......
......@@ -53,7 +53,7 @@ public:
QList<Device*> devicesList() const;
virtual void requestPairing(Device *d) = 0;
virtual void requestPairing(PairingHandler *d) = 0;
virtual void reportError(const QString &title, const QString &description) = 0;
virtual QNetworkAccessManager* networkAccessManager();
......
......@@ -76,7 +76,6 @@ Device::Device(QObject* parent, const NetworkPackage& identityPackage, DeviceLin
Device::~Device()
{
qDeleteAll(m_pairingHandlers);
}
bool Device::hasPlugin(const QString& name) const
......@@ -98,7 +97,7 @@ void Device::reloadPlugins()
QSet<QString> supportedOutgoingInterfaces;
QStringList unsupportedPlugins;
if (isPaired() && isReachable()) { //Do not load any plugin for unpaired devices, nor useless loading them for unreachable devices
if (isTrusted() && isReachable()) { //Do not load any plugin for unpaired devices, nor useless loading them for unreachable devices
KConfigGroup pluginStates = KSharedConfig::openConfig(pluginsConfigFile())->group("Plugins");
......@@ -169,7 +168,7 @@ void Device::reloadPlugins()
}
Q_EMIT pluginsChanged();
if (capabilitiesChanged && isReachable() && isPaired())
if (capabilitiesChanged && isReachable() && isTrusted())
{
NetworkPackage np(PACKAGE_TYPE_CAPABILITIES);
np.set<QStringList>("IncomingCapabilities", newSupportedIncomingInterfaces);
......@@ -183,59 +182,50 @@ QString Device::pluginsConfigFile() const
return KdeConnectConfig::instance()->deviceConfigDir(id()).absoluteFilePath("config");
}
bool Device::isPairRequested() const
{
bool isPairRequested = false;
Q_FOREACH(PairingHandler* ph, m_pairingHandlers) {
isPairRequested = isPairRequested || ph->isPairRequested();
}
return isPairRequested;
}
void Device::requestPair()
{
if (isPaired()) {
Q_EMIT pairingFailed(i18n("Already paired"));
if (isTrusted()) {
Q_EMIT pairingError(i18n("Already paired"));
return;
}
if (!isReachable()) {
Q_EMIT pairingFailed(i18n("Device not reachable"));
Q_EMIT pairingError(i18n("Device not reachable"));
return;
}
bool success = false;
Q_FOREACH(PairingHandler* ph, m_pairingHandlers.values()) {
success = success || ph->requestPairing(); // If one of many pairing handlers can successfully request pairing, consider it success
}
if (!success) {
Q_EMIT pairingFailed(i18n("Error contacting device"));
return;
Q_FOREACH(DeviceLink* dl, m_deviceLinks) {
dl->requestPairing();
}
}
void Device::unpair()
{
Q_FOREACH(PairingHandler* ph, m_pairingHandlers.values()) {
ph->unpair();
Q_FOREACH(DeviceLink* dl, m_deviceLinks) {
dl->unpair();
}
KdeConnectConfig::instance()->removeTrustedDevice(id());
}
void Device::pairStatusChanged(PairingHandler::PairStatus status, PairingHandler::PairStatus oldStatus)