diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 593f34ac9..d55d8cdfa 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,14 +1,14 @@ set(kded_androidshine_SRCS - fakedevicelocator.cpp + fakeannouncer.cpp echodevicelink.cpp udpdevicelink.cpp - avahidevicelocator.cpp + avahiannouncer.cpp pausemusicpackagereceiver.cpp notificationpackagereceiver.cpp networkpackage.cpp daemon.cpp devicelink.cpp - devicelocator.cpp + announcer.cpp packagereceiver.cpp ) diff --git a/src/devicelocator.cpp b/src/announcer.cpp similarity index 94% rename from src/devicelocator.cpp rename to src/announcer.cpp index 5f1d45c4e..fbfd377b8 100644 --- a/src/devicelocator.cpp +++ b/src/announcer.cpp @@ -18,8 +18,8 @@ * along with this program. If not, see . */ -#include "devicelocator.h" +#include "announcer.h" -DeviceLocator::DeviceLocator() { +Announcer::Announcer() { //gcc complains if we don't add something to compile on a class with virtual functions } \ No newline at end of file diff --git a/src/devicelocator.h b/src/announcer.h similarity index 73% rename from src/devicelocator.h rename to src/announcer.h index d9708130f..c6c3d3cef 100644 --- a/src/devicelocator.h +++ b/src/announcer.h @@ -18,8 +18,8 @@ * along with this program. If not, see . */ -#ifndef DEVICELOCATOR_H -#define DEVICELOCATOR_H +#ifndef ANNOUNCER_H +#define ANNOUNCER_H #include #include @@ -27,16 +27,14 @@ #include "devicelink.h" #include "device.h" -class DeviceLocator +class Announcer : public QObject { Q_OBJECT public: - DeviceLocator(); - virtual ~DeviceLocator() { } - - virtual QString getName() = 0; + Announcer(); + virtual ~Announcer() { } enum Priority { PRIORITY_LOW = 0, //ie: 3g @@ -44,18 +42,16 @@ public: PRIORITY_HIGH = 100 //ie: lan }; + virtual QString getName() = 0; virtual Priority getPriority() = 0; - virtual bool canLink(QString id) = 0; - virtual DeviceLink* link(QString id) = 0; - virtual bool pair(Device* d) = 0; - virtual QList discover() = 0; + + virtual void setDiscoverable(bool b) = 0; + +signals: + void deviceConnection(DeviceLink *); signals: - //TODO: Emit this to be able to see if it is a known device - //void deviceDiscovered(Device* d); - //void deviceLost(QString id); - }; -#endif // DEVICELOCATOR_H +#endif diff --git a/src/avahiannouncer.cpp b/src/avahiannouncer.cpp new file mode 100644 index 000000000..c4bdb051f --- /dev/null +++ b/src/avahiannouncer.cpp @@ -0,0 +1,79 @@ +/** + * Copyright 2013 Albert Vaca + * + * 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 . + */ + +#include "avahiannouncer.h" + +#include "udpdevicelink.h" + +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("KDE Host", serviceType, port); + + mUdpSocket = new QUdpSocket(); + mUdpSocket->bind(port); + + connect(mUdpSocket, SIGNAL(readyRead()), this, SLOT(readPendingNotifications())); + + qDebug() << "listening to udp messages"; + +} + +void AvahiAnnouncer::readPendingNotifications() +{ + + qDebug() << "readPendingNotifications"; + + while (mUdpSocket->hasPendingDatagrams()) { + + QByteArray datagram; + datagram.resize(mUdpSocket->pendingDatagramSize()); + QHostAddress sender; + quint16 senderPort; + mUdpSocket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); + + //log.write(datagram); + qDebug() << ("AvahiAnnouncer incomming udp datagram: " + datagram); + + QString id, name; + + Device* device = new Device(id, name); + DeviceLink* dl = new UdpDeviceLink(device, sender, 10600); + links.append(dl); + + emit deviceConnection(dl); + + } + +} + +AvahiAnnouncer::~AvahiAnnouncer() +{ + delete service; +} + +void AvahiAnnouncer::setDiscoverable(bool b) +{ + if (b) service->publishAsync(); +} + diff --git a/src/avahidevicelocator.h b/src/avahiannouncer.h similarity index 58% rename from src/avahidevicelocator.h rename to src/avahiannouncer.h index e95432c07..4562a5c2c 100644 --- a/src/avahidevicelocator.h +++ b/src/avahiannouncer.h @@ -18,44 +18,45 @@ * along with this program. If not, see . */ -#ifndef AVAHIDEVICELOCATOR_H -#define AVAHIDEVICELOCATOR_H +#ifndef AVAHIANNOUNCER_H +#define AVAHIANNOUNCER_H #include -#include -#include +#include -#include "devicelocator.h" +#include -class AvahiDeviceLocator - : public DeviceLocator +#include "announcer.h" + +class AvahiAnnouncer + : public Announcer { Q_OBJECT public: - AvahiDeviceLocator(); + AvahiAnnouncer(); + ~AvahiAnnouncer(); + QString getName() { return "Avahi"; } Priority getPriority() { return PRIORITY_HIGH; } - bool canLink(QString id); - DeviceLink* link(QString id); - bool pair(Device* d); - QList discover() { return visibleDevices.values(); } -private slots: - void deviceDetected(DNSSD::RemoteService::Ptr s); - void deviceLost(DNSSD::RemoteService::Ptr s); + void setDiscoverable(bool b); + + + +private Q_SLOTS: + void readPendingNotifications(); private: - DNSSD::ServiceBrowser* browser; + DNSSD::PublicService* service; + QUdpSocket* mUdpSocket; - Device* getDeviceInfo(DNSSD::RemoteService::Ptr s); + QVector links; - QMap visibleDevices; - QMap deviceRoutes; - - QList linkedDevices; + QHostAddress mIp; + quint16 mPort; }; -#endif // AVAHIDEVICELOCATOR_H +#endif diff --git a/src/avahidevicelocator.cpp b/src/avahidevicelocator.cpp index 2460da8de..e69de29bb 100644 --- a/src/avahidevicelocator.cpp +++ b/src/avahidevicelocator.cpp @@ -1,118 +0,0 @@ -/** - * Copyright 2013 Albert Vaca - * - * 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 . - */ - -#include "avahidevicelocator.h" - -#include "udpdevicelink.h" - - -AvahiDeviceLocator::AvahiDeviceLocator() -{ - //http://api.kde.org/4.x-api/kdelibs-apidocs/dnssd/html/index.html - browser = new DNSSD::ServiceBrowser("_device._tcp"); - connect(browser, SIGNAL(serviceAdded(DNSSD::RemoteService::Ptr)),this,SLOT(deviceDetected(DNSSD::RemoteService::Ptr))); - connect(browser, SIGNAL(serviceRemoved(DNSSD::RemoteService::Ptr)),this,SLOT(deviceLost(DNSSD::RemoteService::Ptr))); - browser->startBrowse(); -} - -bool AvahiDeviceLocator::canLink(QString id) { - return visibleDevices.contains(id); -} - -DeviceLink* AvahiDeviceLocator::link(QString id) { - - if (!visibleDevices.contains(id)) return NULL; - - Device* d = visibleDevices[id]; - const DNSSD::RemoteService::Ptr& rs = deviceRoutes[d]; - - DeviceLink* dl = new UdpDeviceLink(d, QHostAddress(rs->hostName()),rs->port()); - - qDebug() << "Sending pair request to device " + id; - NetworkPackage np(12345); - //TODO: Package contents - dl->sendPackage(np); - - linkedDevices.append(dl); //Store the ref to be able to delete the memory later - - return dl; -} - -bool AvahiDeviceLocator::pair(Device* d) -{ - //TODO: ? - d->pair(); - return true; -} - -void AvahiDeviceLocator::deviceDetected(DNSSD::RemoteService::Ptr s) -{ - qDebug() << "DETECTED"; - - Device* d = getDeviceInfo(s); - - if (!visibleDevices.contains(d->id())) { - visibleDevices[d->id()] = d; - deviceRoutes[d] = s; - } else { - qDebug() << "Warning: duplicate device id " + d->id(); - } -} - -void AvahiDeviceLocator::deviceLost(DNSSD::RemoteService::Ptr s) -{ - qDebug() << "LOST"; - - Device* found = NULL; - - for(QMap< Device*, DNSSD::RemoteService::Ptr >::iterator it = deviceRoutes.begin(), itEnd = deviceRoutes.end(); it != itEnd; it++) { - if (s == it.value()) { - found = it.key(); - } - } - - if (found != NULL) { - visibleDevices.remove(found->id()); - deviceRoutes.remove(found); - delete found; //created at getDeviceInfo called from deviceDetected - } else { - //TODO: Add a TAG to the debug messages - qDebug() << "Warning: lost unknown device?"; - } -} - -Device* AvahiDeviceLocator::getDeviceInfo(DNSSD::RemoteService::Ptr s) -{ - //TODO: I have no idea on how to get this info using only DNSSD, wihtout connecting to the device - Device* d = new Device("1234567890", "Unnamed"); //deleted at deviceLost - return d; -} - - - - - - - - - - - - diff --git a/src/daemon.cpp b/src/daemon.cpp index c1b6dd268..b0440ec3b 100644 --- a/src/daemon.cpp +++ b/src/daemon.cpp @@ -22,8 +22,8 @@ #include "networkpackage.h" #include "notificationpackagereceiver.h" #include "pausemusicpackagereceiver.h" -#include "avahidevicelocator.h" -#include "fakedevicelocator.h" +#include "avahiannouncer.h" +#include "fakeannouncer.h" #include #include @@ -37,32 +37,15 @@ K_PLUGIN_FACTORY(AndroidShineFactory, registerPlugin();) K_EXPORT_PLUGIN(AndroidShineFactory("androidshine", "androidshine")) -DeviceLink* Daemon::linkTo(QString id) { +void Daemon::linkTo(DeviceLink* dl) { - DeviceLink* link = NULL; + linkedDevices.append(dl); - Q_FOREACH (DeviceLocator* locator, deviceLocators) { - if (locator->canLink(id)) { - link = locator->link(id); - if (link != NULL) break; - } + Q_FOREACH (PackageReceiver* pr, packageReceivers) { + QObject::connect(dl,SIGNAL(receivedPackage(const NetworkPackage&)), + pr,SLOT(receivePackage(const NetworkPackage&))); } - if (link != NULL) { - - linkedDevices.append(link); - - Q_FOREACH (PackageReceiver* pr, packageReceivers) { - QObject::connect(link,SIGNAL(receivedPackage(const NetworkPackage&)), - pr,SLOT(receivePackage(const NetworkPackage&))); - } - - } else { - qDebug() << "Could not link device id " + id; - } - - return link; - } Daemon::Daemon(QObject *parent, const QList&) @@ -76,22 +59,21 @@ Daemon::Daemon(QObject *parent, const QList&) packageReceivers.push_back(new PauseMusicPackageReceiver()); //TODO: Do not hardcode the load of the device locators - deviceLocators.insert(new AvahiDeviceLocator()); - deviceLocators.insert(new FakeDeviceLocator()); + announcers.insert(new AvahiAnnouncer()); + announcers.insert(new FakeAnnouncer()); + + //Listen to incomming connections + Q_FOREACH (Announcer* a, announcers) { + QObject::connect(a,SIGNAL(deviceConnection(DeviceLink*)), + this,SLOT(deviceConnection(DeviceLink*))); + a->setDiscoverable(true); + } //TODO: Read paired devices from config //pairedDevices.push_back(new Device("MyAndroid","MyAndroid")); - //At boot time, try to link to all paired devices - //FIXME: This should be done for every new visible device, not only at boot - //TODO: Add a way to notify discovered/lost devices - Q_FOREACH (Device* device, pairedDevices) { - linkTo(device->id()); - } - } - QString Daemon::listVisibleDevices() { @@ -99,29 +81,22 @@ QString Daemon::listVisibleDevices() ret << std::setw(20) << "ID"; ret << std::setw(20) << "Name"; - ret << std::setw(20) << "Source"; ret << std::endl; - QList visibleDevices; - - Q_FOREACH (DeviceLocator* dl, deviceLocators) { - Q_FOREACH (Device* d, dl->discover()) { - ret << std::setw(20) << d->id().toStdString(); - ret << std::setw(20) << d->name().toStdString(); - ret << std::setw(20) << dl->getName().toStdString(); - ret << std::endl; - } + Q_FOREACH (Device* d, visibleDevices) { + ret << std::setw(20) << d->id().toStdString(); + ret << std::setw(20) << d->name().toStdString(); + ret << std::endl; } return QString::fromStdString(ret.str()); } -bool Daemon::linkDevice(QString id) +bool Daemon::pairDevice(QString id) { - - return linkTo(id); - + //TODO + return true; } QString Daemon::listLinkedDevices() @@ -133,9 +108,36 @@ QString Daemon::listLinkedDevices() } return ret; + } +void Daemon::deviceConnection(DeviceLink* dl) +{ + + QString id = dl->device()->id(); + bool paired = false; + Q_FOREACH (Device* d, pairedDevices) { + if (id == d->id()) { + paired = true; + break; + } + } + + visibleDevices.append(dl->device()); + + if (paired) { + qDebug() << "Known device connected" + dl->device()->name(); + linkTo(dl); + } + else { + qDebug() << "Unknown device connected" + dl->device()->name(); + //TODO: Not connect immediately + linkTo(dl); + } + +} + Daemon::~Daemon() { qDebug() << "SAYONARA BABY"; diff --git a/src/daemon.h b/src/daemon.h index dcfab7d1e..b69b5d312 100644 --- a/src/daemon.h +++ b/src/daemon.h @@ -39,7 +39,7 @@ #include "device.h" #include "packagereceiver.h" #include "devicelink.h" -#include "devicelocator.h" +#include "announcer.h" class QUdpSocket; @@ -54,15 +54,16 @@ public: //DBUS interface +private Q_SLOTS: + void deviceConnection(DeviceLink* dl); + public Q_SLOTS: Q_SCRIPTABLE QString listVisibleDevices(); - Q_SCRIPTABLE bool linkDevice(QString id); - -/* Q_SCRIPTABLE bool pairDevice(QString id); +/* Q_SCRIPTABLE QString listPairedDevices(QString id); Q_SCRIPTABLE bool linkAllPairedDevices(); @@ -73,17 +74,23 @@ public Q_SLOTS: private: - //Get a DeviceLink through the best DeviceLocator available - DeviceLink* linkTo(QString d); + void linkTo(DeviceLink* dl); - //All known devices (read from/stored to settings) + //Non paired visible devices + QList visibleDevices; + + //All paired devices (should be stored and read from disk) QVector pairedDevices; //Currently connected devices QVector linkedDevices; - //Different ways to find new devices and connect to them, ordered by priority - QSet deviceLocators; + + + + + //Different ways to find devices and connect to them, ordered by priority + QSet announcers; //Everybody who wants to be notified about a new package QVector packageReceivers; diff --git a/src/fakedevicelocator.cpp b/src/fakeannouncer.cpp similarity index 67% rename from src/fakedevicelocator.cpp rename to src/fakeannouncer.cpp index 246938373..3656948ac 100644 --- a/src/fakedevicelocator.cpp +++ b/src/fakeannouncer.cpp @@ -18,32 +18,23 @@ * along with this program. If not, see . */ -#include "fakedevicelocator.h" +#include "fakeannouncer.h" #include "echodevicelink.h" -FakeDeviceLocator::FakeDeviceLocator() +FakeAnnouncer::FakeAnnouncer() { fakeDevice = new Device("fake","Fake device"); echoDeviceLink = new EchoDeviceLink(fakeDevice); } -bool FakeDeviceLocator::canLink(QString id) { - return id == "fake"; +FakeAnnouncer::~FakeAnnouncer() +{ + //delete echoDeviceLink; + //delete fakeDevice; } -DeviceLink* FakeDeviceLocator::link(QString id) { - if (!canLink(id)) return NULL; - return echoDeviceLink; +void FakeAnnouncer::setDiscoverable(bool b) +{ + if (b) emit deviceConnection(echoDeviceLink); } -bool FakeDeviceLocator::pair(Device* d) { - if (d != fakeDevice) return false; - d->pair(); - return true; -} - -QList FakeDeviceLocator::discover() { - QList devices; - devices.append(fakeDevice); - return devices; -} diff --git a/src/fakedevicelocator.h b/src/fakeannouncer.h similarity index 74% rename from src/fakedevicelocator.h rename to src/fakeannouncer.h index 6ac865e73..784810fec 100644 --- a/src/fakedevicelocator.h +++ b/src/fakeannouncer.h @@ -18,23 +18,22 @@ * along with this program. If not, see . */ -#ifndef FAKEDEVICELOCATOR_H -#define FAKEDEVICELOCATOR_H -#include "devicelocator.h" +#ifndef FAKEANNOUNCER_H +#define FAKEANNOUNCER_H -class FakeDeviceLocator - : public DeviceLocator +#include "announcer.h" + +class FakeAnnouncer + : public Announcer { public: - FakeDeviceLocator(); - - QString getName() { return "FakeLocator"; } + FakeAnnouncer(); + ~FakeAnnouncer(); + QString getName() { return "FakeAnnouncer"; } Priority getPriority() { return PRIORITY_LOW; } - bool canLink(QString id); - DeviceLink* link(QString id); - bool pair(Device* d); - QList discover(); + + void setDiscoverable(bool b); private: Device* fakeDevice; @@ -42,4 +41,4 @@ private: }; -#endif // FAKEDEVICELOCATOR_H +#endif diff --git a/src/udpdevicelink.cpp b/src/udpdevicelink.cpp index f73f88c49..68931aa67 100644 --- a/src/udpdevicelink.cpp +++ b/src/udpdevicelink.cpp @@ -51,6 +51,7 @@ void UdpDeviceLink::readPendingNotifications() NetworkPackage np = NetworkPackage::fromString(datagram); emit receivedPackage(np); + } } diff --git a/src/udpdevicelink.h b/src/udpdevicelink.h index 56bd9bb92..4fa2e308d 100644 --- a/src/udpdevicelink.h +++ b/src/udpdevicelink.h @@ -37,10 +37,7 @@ public: void sendPackage(const NetworkPackage& np) { mUdpSocket->writeDatagram(np.toString(), mIp, mPort); - } - - private Q_SLOTS: void readPendingNotifications();