Commit 54de8fa2 authored by Albert Vaca Cintora's avatar Albert Vaca Cintora

Android: Uses Apache Mina to abstract socket management

KDE: Housekeeping
parent 87513455
set(kded_kdeconnect_SRCS
announcers/announcer.cpp
announcers/fakeannouncer.cpp
announcers/avahiannouncer.cpp
announcers/avahitcpannouncer.cpp
linkproviders/linkprovider.cpp
linkproviders/loopbacklinkprovider.cpp
linkproviders/avahitcplinkprovider.cpp
devicelinks/devicelink.cpp
devicelinks/echodevicelink.cpp
devicelinks/udpdevicelink.cpp
devicelinks/tcpdevicelink.cpp
packageinterfaces/packagereceiver.cpp
packageinterfaces/pingpackagereceiver.cpp
packageinterfaces/notificationpackagereceiver.cpp
packageinterfaces/pausemusicpackagereceiver.cpp
packageinterfaces/packageinterface.cpp
packageinterfaces/pingpackageinterface.cpp
packageinterfaces/notificationpackageinterface.cpp
packageinterfaces/pausemusicpackageinterface.cpp
packageinterfaces/clipboardpackageinterface.cpp
networkpackage.cpp
......
/**
* Copyright 2013 Albert Vaca <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
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "avahiannouncer.h"
#include "devicelinks/udpdevicelink.h"
#include <QHostInfo>
AvahiAnnouncer::AvahiAnnouncer()
{
QString serviceType = "_kdeconnect._udp";
quint16 port = 10601;
//http://api.kde.org/4.x-api/kdelibs-apidocs/dnssd/html/index.html
service = new DNSSD::PublicService(QHostInfo::localHostName(), serviceType, port);
mUdpSocket = new QUdpSocket();
mUdpSocket->bind(port);
connect(mUdpSocket, SIGNAL(readyRead()), this, SLOT(newConnection()));
qDebug() << "Listening to udp messages";
}
void AvahiAnnouncer::newConnection()
{
qDebug() << "AvahiAnnouncer newConnection";
while (mUdpSocket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(mUdpSocket->pendingDatagramSize());
NetAddress client;
mUdpSocket->readDatagram(datagram.data(), datagram.size(), &(client.ip), &(client.port));
//log.write(datagram);
qDebug() << "AvahiAnnouncer incomming udp datagram: " << datagram;
NetworkPackage np;
NetworkPackage::unserialize(datagram,&np);
if (np.type() == "kdeconnect.identity") {
const QString& id = np.get<QString>("deviceId");
//const QString& name = np.get<QString>("deviceName");
qDebug() << "AvahiAnnouncer creating link to device" << id << "(" << client.ip << "," << client.port << ")";
DeviceLink* dl = new UdpDeviceLink(id, this, client.ip);
connect(dl,SIGNAL(destroyed(QObject*)),this,SLOT(deviceLinkDestroyed(QObject*)));
emit onNewDeviceLink(np, dl);
NetworkPackage::createIdentityPackage(&np);
dl->sendPackage(np);
if (links.contains(id)) {
//Delete old link if we already know it, probably it is down if this happens.
qDebug() << "Destroying old link";
delete links[id];
}
links[id] = dl;
} else {
qDebug() << "Not an identification package (wuh?)";
}
}
}
void AvahiAnnouncer::deviceLinkDestroyed(QObject* deviceLink)
{
const QString& id = ((DeviceLink*)deviceLink)->deviceId();
if (links.contains(id)) links.remove(id);
}
AvahiAnnouncer::~AvahiAnnouncer()
{
delete service;
}
void AvahiAnnouncer::setDiscoverable(bool b)
{
qDebug() << "Avahi announcing";
if (b) service->publishAsync();
}
/**
* Copyright 2013 Albert Vaca <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
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef AVAHIANNOUNCER_H
#define AVAHIANNOUNCER_H
#include <QObject>
#include <QUdpSocket>
#include <KDE/DNSSD/PublicService>
#include "announcer.h"
#include "netaddress.h"
class AvahiAnnouncer
: public Announcer
{
Q_OBJECT
public:
AvahiAnnouncer();
~AvahiAnnouncer();
QString name() { return "Avahi"; }
int priority() { return PRIORITY_HIGH; }
void setDiscoverable(bool b);
private Q_SLOTS:
void newConnection();
void deviceLinkDestroyed(QObject*);
private:
DNSSD::PublicService* service;
QUdpSocket* mUdpSocket;
QMap<QString, DeviceLink*> links;
};
#endif
......@@ -19,15 +19,16 @@
*/
#include "daemon.h"
#include "networkpackage.h"
#include "packageinterfaces/pingpackagereceiver.h"
#include "packageinterfaces/notificationpackagereceiver.h"
#include "packageinterfaces/pausemusicpackagereceiver.h"
#include "packageinterfaces/pingpackageinterface.h"
#include "packageinterfaces/notificationpackageinterface.h"
#include "packageinterfaces/pausemusicpackageinterface.h"
#include "packageinterfaces/clipboardpackageinterface.h"
#include "announcers/avahiannouncer.h"
#include "announcers/avahitcpannouncer.h"
#include "announcers/fakeannouncer.h"
#include "devicelinks/echodevicelink.h"
#include "linkproviders/avahitcplinkprovider.h"
#include "linkproviders/loopbacklinkprovider.h"
#include <QtNetwork/QUdpSocket>
#include <QFile>
......@@ -54,23 +55,20 @@ Daemon::Daemon(QObject *parent, const QList<QVariant>&)
}
//Debugging
qDebug() << "GO GO GO!";
qDebug() << "Starting KdeConnect daemon";
config->group("devices").group("paired").group("fake_unreachable").writeEntry("name","Fake device");
//TODO: Do not hardcode the load of the package receivers
//TODO: Do not hardcode the load of the package interfaces
//use: https://techbase.kde.org/Development/Tutorials/Services/Plugins
packageReceivers.push_back(new PingPackageReceiver());
packageReceivers.push_back(new NotificationPackageReceiver());
packageReceivers.push_back(new PauseMusicPackageReceiver());
packageReceivers.push_back(new ClipboardPackageInterface());
mPackageInterfaces.push_back(new PingPackageInterface());
mPackageInterfaces.push_back(new NotificationPackageInterface());
mPackageInterfaces.push_back(new PauseMusicPackageInterface());
mPackageInterfaces.push_back(new ClipboardPackageInterface());
//TODO: Do not hardcode the load of the device locators
//use: https://techbase.kde.org/Development/Tutorials/Services/Plugins
// announcers.insert(new AvahiAnnouncer());
announcers.insert(new AvahiTcpAnnouncer());
//announcers.insert(new LoopbackAnnouncer());
//TODO: Add package emitters
mLinkProviders.insert(new AvahiTcpLinkProvider());
//mLinkProviders.insert(new LoopbackLinkProvider());
//Read remebered paired devices
const KConfigGroup& known = config->group("devices").group("paired");
......@@ -80,8 +78,8 @@ Daemon::Daemon(QObject *parent, const QList<QVariant>&)
const KConfigGroup& data = known.group(id);
const QString& name = data.readEntry<QString>("name",defaultName);
Device* device = new Device(id,name);
m_devices[id] = device;
Q_FOREACH (PackageReceiver* pr, packageReceivers) {
mDevices[id] = device;
Q_FOREACH (PackageInterface* pr, mPackageInterfaces) {
connect(device,SIGNAL(receivedPackage(const Device&, const NetworkPackage&)),
pr,SLOT(receivePackage(const Device&, const NetworkPackage&)));
connect(pr,SIGNAL(sendPackage(const NetworkPackage&)),
......@@ -90,7 +88,7 @@ Daemon::Daemon(QObject *parent, const QList<QVariant>&)
}
//Listen to incomming connections
Q_FOREACH (Announcer* a, announcers) {
Q_FOREACH (LinkProvider* a, mLinkProviders) {
connect(a,SIGNAL(onNewDeviceLink(NetworkPackage,DeviceLink*)),
this,SLOT(onNewDeviceLink(NetworkPackage,DeviceLink*)));
}
......@@ -102,9 +100,8 @@ Daemon::Daemon(QObject *parent, const QList<QVariant>&)
}
void Daemon::setDiscoveryEnabled(bool b)
{
qDebug() << "Discovery:" << b;
//Listen to incomming connections
Q_FOREACH (Announcer* a, announcers) {
Q_FOREACH (LinkProvider* a, mLinkProviders) {
a->setDiscoverable(b);
}
......@@ -112,7 +109,7 @@ void Daemon::setDiscoveryEnabled(bool b)
QStringList Daemon::devices()
{
return m_devices.keys();
return mDevices.keys();
}
......@@ -120,12 +117,12 @@ void Daemon::onNewDeviceLink(const NetworkPackage& identityPackage, DeviceLink*
{
const QString& id = identityPackage.get<QString>("deviceId");
qDebug() << "Device discovered" << id << "via" << dl->announcer()->name();
qDebug() << "Device discovered" << id << "via" << dl->provider()->name();
if (m_devices.contains(id)) {
if (mDevices.contains(id)) {
qDebug() << "It is a known device";
Device* device = m_devices[id];
Device* device = mDevices[id];
device->addLink(dl);
KNotification* notification = new KNotification("pingReceived"); //KNotification::Persistent
......@@ -142,8 +139,8 @@ void Daemon::onNewDeviceLink(const NetworkPackage& identityPackage, DeviceLink*
const QString& name = identityPackage.get<QString>("deviceName");
Device* device = new Device(id,name,dl);
m_devices[id] = device;
Q_FOREACH (PackageReceiver* pr, packageReceivers) {
mDevices[id] = device;
Q_FOREACH (PackageInterface* pr, mPackageInterfaces) {
connect(device,SIGNAL(receivedPackage(const Device&, const NetworkPackage&)),
pr,SLOT(receivePackage(const Device&, const NetworkPackage&)));
connect(pr,SIGNAL(sendPackage(const NetworkPackage&)),
......@@ -156,6 +153,6 @@ void Daemon::onNewDeviceLink(const NetworkPackage& identityPackage, DeviceLink*
Daemon::~Daemon()
{
qDebug() << "SAYONARA BABY";
}
......@@ -39,9 +39,9 @@
#include <KConfig>
#include "device.h"
#include "packageinterfaces/packagereceiver.h"
#include "packageinterfaces/packageinterface.h"
#include "devicelinks/devicelink.h"
#include "announcers/announcer.h"
#include "linkproviders/linkprovider.h"
class QUdpSocket;
......@@ -75,13 +75,13 @@ private:
//Every known device
QMap<QString, Device*> m_devices;
QMap<QString, Device*> mDevices;
//Different ways to find devices and connect to them, ordered by priority
QSet<Announcer*> announcers;
//Different ways to find devices and connect to them
QSet<LinkProvider*> mLinkProviders;
//Everybody who wants to be notified about a new package
QVector<PackageReceiver*> packageReceivers;
//The classes that send and receive the packages
QVector<PackageInterface*> mPackageInterfaces;
};
......
......@@ -2,7 +2,7 @@
#include <ksharedptr.h>
#include <ksharedconfig.h>
#include "devicelinks/devicelink.h"
#include "announcers/announcer.h"
#include "linkproviders/linkprovider.h"
#include <KConfigGroup>
#include <QDebug>
......@@ -59,12 +59,12 @@ void Device::setPair(bool b)
static bool lessThan(DeviceLink* p1, DeviceLink* p2)
{
return p1->announcer()->priority() > p2->announcer()->priority();
return p1->provider()->priority() > p2->provider()->priority();
}
void Device::addLink(DeviceLink* link)
{
qDebug() << "Adding link to " << id() << "via" << link->announcer();
qDebug() << "Adding link to " << id() << "via" << link->provider();
connect(link,SIGNAL(destroyed(QObject*)),this,SLOT(linkDestroyed(QObject*)));
......@@ -111,7 +111,7 @@ QStringList Device::availableLinks() const
{
QStringList sl;
Q_FOREACH(DeviceLink* dl, m_deviceLinks) {
sl.append(dl->announcer()->name());
sl.append(dl->provider()->name());
}
return sl;
}
......
......@@ -19,11 +19,12 @@
*/
#include "devicelink.h"
#include "linkproviders/linkprovider.h"
DeviceLink::DeviceLink(const QString& deviceId, Announcer* parent)
DeviceLink::DeviceLink(const QString& deviceId, LinkProvider* parent)
: QObject(parent)
, mDeviceId(deviceId)
, mAnnouncer(parent)
, mLinkProvider(parent)
{
//gcc complains if we don't add something to compile on a class with virtual functions
}
\ No newline at end of file
......@@ -24,10 +24,9 @@
#include <QObject>
#include "networkpackage.h"
#include <announcers/announcer.h>
class Device;
class Announcer;
class LinkProvider;
class DeviceLink
: public QObject
......@@ -35,10 +34,10 @@ class DeviceLink
Q_OBJECT
public:
DeviceLink(const QString& deviceId, Announcer* parent);
DeviceLink(const QString& deviceId, LinkProvider* parent);
const QString& deviceId() { return mDeviceId; }
Announcer* announcer() { return mAnnouncer; }
LinkProvider* provider() { return mLinkProvider; }
virtual bool sendPackage(const NetworkPackage& np) = 0;
......@@ -47,7 +46,7 @@ signals:
private:
QString mDeviceId;
Announcer* mAnnouncer;
LinkProvider* mLinkProvider;
};
......
......@@ -20,9 +20,9 @@
#include "echodevicelink.h"
#include "announcers/fakeannouncer.h"
#include "linkproviders/loopbacklinkprovider.h"
EchoDeviceLink::EchoDeviceLink(const QString& d, LoopbackAnnouncer* a)
EchoDeviceLink::EchoDeviceLink(const QString& d, LoopbackLinkProvider* a)
: DeviceLink(d, a)
{
......
......@@ -22,13 +22,14 @@
#define ECHODEVICELINK_H
#include "devicelink.h"
class LoopbackAnnouncer;
class LoopbackLinkProvider;
class EchoDeviceLink : public DeviceLink
class EchoDeviceLink
: public DeviceLink
{
Q_OBJECT
public:
EchoDeviceLink(const QString& d, LoopbackAnnouncer* a);
EchoDeviceLink(const QString& d, LoopbackLinkProvider* a);
bool sendPackage(const NetworkPackage& np) {
emit receivedPackage(np);
......
......@@ -19,9 +19,9 @@
*/
#include "tcpdevicelink.h"
#include "announcers/avahitcpannouncer.h"
#include "linkproviders/avahitcplinkprovider.h"
TcpDeviceLink::TcpDeviceLink(const QString& d, AvahiTcpAnnouncer* a, QTcpSocket* socket)
TcpDeviceLink::TcpDeviceLink(const QString& d, AvahiTcpLinkProvider* a, QTcpSocket* socket)
: DeviceLink(d, a)
{
mSocket = socket;
......@@ -29,6 +29,12 @@ TcpDeviceLink::TcpDeviceLink(const QString& d, AvahiTcpAnnouncer* a, QTcpSocket*
connect(mSocket, SIGNAL(readyRead()), this, SLOT(dataReceived()));
}
bool TcpDeviceLink::sendPackage(const NetworkPackage& np)
{
int written = mSocket->write(np.serialize());
return written != -1;
}
void TcpDeviceLink::dataReceived()
{
qDebug() << "TcpDeviceLink dataReceived";
......
......@@ -27,21 +27,18 @@
#include "devicelink.h"
#include <QTcpSocket>
#include <QTcpServer>
class AvahiTcpAnnouncer;
class AvahiTcpLinkProvider;
class TcpDeviceLink : public DeviceLink
class TcpDeviceLink
: public DeviceLink
{
Q_OBJECT
public:
TcpDeviceLink(const QString& d, AvahiTcpAnnouncer* a, QTcpSocket* socket);
TcpDeviceLink(const QString& d, AvahiTcpLinkProvider* a, QTcpSocket* socket);
bool sendPackage(const NetworkPackage& np) {
mSocket->write(np.serialize());
return true;
}
bool sendPackage(const NetworkPackage& np);
private Q_SLOTS:
void dataReceived();
......
/**
* Copyright 2013 Albert Vaca <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
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "udpdevicelink.h"
#include "announcers/avahiannouncer.h"
UdpDeviceLink::UdpDeviceLink(const QString& d, AvahiAnnouncer* a, QHostAddress ip)
: DeviceLink(d, a)
{
mIp = ip;
mSocket = new QUdpSocket();
mSocket->bind(mPort);
connect(mSocket, SIGNAL(readyRead()), this, SLOT(dataReceived()));
}
void UdpDeviceLink::dataReceived()
{
qDebug() << "UdpDeviceLink dataReceived";
while (mSocket->hasPendingDatagrams()) {
QByteArray datagram;
datagram.resize(mSocket->pendingDatagramSize());
QHostAddress sender;
quint16 senderPort;
mSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort);
//log.write(datagram);
qDebug() << datagram;
NetworkPackage np;
NetworkPackage::unserialize(datagram,&np);
emit receivedPackage(np);
}
}
/**
* Copyright 2013 Albert Vaca <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
* published by the Free Software Foundation; either version 2 of
* the License or (at your option) version 3 or any later version
* accepted by the membership of KDE e.V. (or its successor approved
* by the membership of KDE e.V.), which shall act as a proxy
* defined in Section 14 of version 3 of the license.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef UDPDEVICELINK_H
#define UDPDEVICELINK_H
#include <QObject>
#include <QString>
#include "devicelink.h"
#include <QUdpSocket>
class AvahiAnnouncer;
class UdpDeviceLink : public DeviceLink
{
Q_OBJECT
public:
UdpDeviceLink(const QString& d, AvahiAnnouncer* a, QHostAddress ip);
bool sendPackage(const NetworkPackage& np) {
mSocket->writeDatagram(np.serialize(),mIp,mPort+1);
return true;
}
private Q_SLOTS:
void dataReceived();
private:
QUdpSocket* mSocket;
QHostAddress mIp;
const quint16 mPort = 10603;
};
#endif // UDPDEVICELINK_H
......@@ -18,14 +18,14 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "avahitcpannouncer.h"
#include "avahitcplinkprovider.h"
#include "devicelinks/tcpdevicelink.h"
#include <QHostInfo>
#include <QTcpServer>
AvahiTcpAnnouncer::AvahiTcpAnnouncer()
AvahiTcpLinkProvider::AvahiTcpLinkProvider()
{
QString serviceType = "_kdeconnect._tcp";
quint16 port = 10602;
......@@ -40,9 +40,9 @@ AvahiTcpAnnouncer::AvahiTcpAnnouncer()
}
void AvahiTcpAnnouncer::newConnection()
void AvahiTcpLinkProvider::newConnection()
{
qDebug() << "AvahiTcpAnnouncer newConnection";
qDebug() << "AvahiTcpLinkProvider newConnection";
QTcpSocket* socket = mServer->nextPendingConnection();
socket->setSocketOption(QAbstractSocket::KeepAliveOption, 1);
......@@ -51,21 +51,19 @@ void AvahiTcpAnnouncer::newConnection()
NetworkPackage np;
NetworkPackage::createIdentityPackage(&np);
qDebug() << socket->isWritable();
qDebug() << socket->isOpen();
int written = socket->write(np.serialize());
qDebug() << np.serialize();
qDebug() << "AvahiTcpAnnouncer sent tcp package" << written << " bytes written, waiting for reply";
qDebug() << "AvahiTcpLinkProvider sent package." << written << " bytes written, waiting for reply";
}
void AvahiTcpAnnouncer::dataReceived()
void AvahiTcpLinkProvider::dataReceived()
{
QTcpSocket* socket = (QTcpSocket*) QObject::sender();
QByteArray data = socket->readLine();
qDebug() << "AvahiTcpAnnouncer received reply:" << data;
qDebug() << "AvahiTcpLinkProvider received reply:" << data;
NetworkPackage np;
NetworkPackage::unserialize(data,&np);
......@@ -84,32 +82,32 @@ void AvahiTcpAnnouncer::dataReceived()
}
links[id] = dl;
qDebug() << "AvahiAnnouncer creating link to device" << id << "(" << socket->peerAddress() << ")";
qDebug() << "AvahiTcpLinkProvider creating link to device" << id << "(" << socket->peerAddress() << ")";
emit onNewDeviceLink(np, dl);
disconnect(socket,SIGNAL(readyRead()),this,SLOT(dataReceived()));
} else {
qDebug() << "AvahiTcpAnnouncer/newConnection: Not an identification package (wuh?)";
qDebug() << "AvahiTcpLinkProvider/newConnection: Not an identification package (wuh?)";
}
}
void AvahiTcpAnnouncer::deviceLinkDestroyed(QObject* deviceLink)
void AvahiTcpLinkProvider::deviceLinkDestroyed(QObject* deviceLink)
{
const QString& id = ((DeviceLink*)deviceLink)->deviceId();
if (links.contains(id)) links.remove(id);
}
AvahiTcpAnnouncer::~AvahiTcpAnnouncer()
AvahiTcpLinkProvider::~AvahiTcpLinkProvider()
{
delete service;
}
void AvahiTcpAnnouncer::setDiscoverable(bool b)
void AvahiTcpLinkProvider::setDiscoverable(bool b)
{
qDebug() << "AvahiTcp announcing";
qDebug() << "AvahiTcpLinkProvider discoverable:" << b;
if (b) service->publishAsync();
}