diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -19,6 +19,7 @@ avahi_serviceresolver_interface.cpp avahi_entrygroup_interface.cpp avahi_listener.cpp + avahi-disconn-handler.cpp ) qt5_add_dbus_interface (kdnssd_LIB_SRCS org.freedesktop.Avahi.DomainBrowser.xml avahi_domainbrowser_interface ) qt5_add_dbus_interface (kdnssd_LIB_SRCS org.freedesktop.Avahi.ServiceBrowser.xml avahi_servicebrowser_interface ) diff --git a/src/avahi-disconn-handler.h b/src/avahi-disconn-handler.h new file mode 100644 --- /dev/null +++ b/src/avahi-disconn-handler.h @@ -0,0 +1,20 @@ +#ifndef AVAHI_DISCONNECT_HANDLER___H_ +#define AVAHI_DISCONNECT_HANDLER___H_ + +#include + +namespace KDNSSD { + + class AvahiDisconnectHandler : public QObject + { + Q_OBJECT + + AvahiDisconnectHandler(); + Q_SIGNALS: + void avahiDisconnected(); + public: + static AvahiDisconnectHandler& instance(); + }; +} + +#endif diff --git a/src/avahi-disconn-handler.cpp b/src/avahi-disconn-handler.cpp new file mode 100644 --- /dev/null +++ b/src/avahi-disconn-handler.cpp @@ -0,0 +1,20 @@ +#include +#include + +#include "avahi-disconn-handler.h" +KDNSSD::AvahiDisconnectHandler::AvahiDisconnectHandler() +{ + auto nameChangeObserver = new QDBusServiceWatcher("org.freedesktop.Avahi", QDBusConnection::systemBus(), QDBusServiceWatcher::WatchForOwnerChange, this); + QObject::connect(nameChangeObserver, &QDBusServiceWatcher::serviceOwnerChanged, this, + [this](const QString& name, const QString& oldO, const QString& newO) { + if (newO.isEmpty()) + emit avahiDisconnected(); + }); +} + +auto KDNSSD::AvahiDisconnectHandler::instance() -> AvahiDisconnectHandler& +{ + static AvahiDisconnectHandler h; + return h; +} + diff --git a/src/avahi-domainbrowser.cpp b/src/avahi-domainbrowser.cpp --- a/src/avahi-domainbrowser.cpp +++ b/src/avahi-domainbrowser.cpp @@ -28,12 +28,19 @@ #include "avahi_server_interface.h" #include "domainbrowser.h" #include "avahi_domainbrowser_interface.h" +#include "avahi-disconn-handler.h" namespace KDNSSD { DomainBrowser::DomainBrowser(DomainType type, QObject *parent) : QObject(parent), d(new DomainBrowserPrivate(type, this)) -{} +{ + QObject::connect(&AvahiDisconnectHandler::instance(), &AvahiDisconnectHandler::avahiDisconnected, this, + [this]() { + delete d->m_browser; + d->m_browser = 0; + }); +} DomainBrowser::~DomainBrowser() { diff --git a/src/avahi-publicservice.cpp b/src/avahi-publicservice.cpp --- a/src/avahi-publicservice.cpp +++ b/src/avahi-publicservice.cpp @@ -19,6 +19,7 @@ */ #include "avahi-publicservice_p.h" +#include "avahi-disconn-handler.h" #include #include @@ -45,6 +46,11 @@ d->m_domain = "local."; } d->m_subtypes = subtypes; + QObject::connect(&AvahiDisconnectHandler::instance(), &AvahiDisconnectHandler::avahiDisconnected, d, + [d]() { + d->clean(); + d->serverStateChanged(AVAHI_SERVER_INVALID, QStringLiteral("Avahi disconnected")); + }); } PublicService::~PublicService() @@ -269,6 +275,14 @@ } } +void PublicServicePrivate::clean() +{ + delete m_group; + m_group = nullptr; + m_collision = false; + m_published = false; +} + void PublicService::publishAsync() { K_D; diff --git a/src/avahi-publicservice_p.h b/src/avahi-publicservice_p.h --- a/src/avahi-publicservice_p.h +++ b/src/avahi-publicservice_p.h @@ -39,7 +39,7 @@ Q_OBJECT public: PublicServicePrivate(PublicService *parent, const QString &name, const QString &type, const QString &domain, unsigned int port) : - QObject(), ServiceBasePrivate(name, type, domain, QString(), port), m_published(false), m_running(false), m_group(nullptr), + QObject(parent), ServiceBasePrivate(name, type, domain, QString(), port), m_published(false), m_running(false), m_group(nullptr), m_server(nullptr), m_collision(false), m_parent(parent) {} ~PublicServicePrivate() @@ -68,6 +68,7 @@ void stop(); bool fillEntryGroup(); void tryApply(); + void clean(); public Q_SLOTS: // NB: The global slots are runtime connected! If their signature changes diff --git a/src/avahi-remoteservice.cpp b/src/avahi-remoteservice.cpp --- a/src/avahi-remoteservice.cpp +++ b/src/avahi-remoteservice.cpp @@ -27,12 +27,23 @@ #include "remoteservice.h" #include "avahi_server_interface.h" #include "avahi_serviceresolver_interface.h" +#include "avahi-disconn-handler.h" namespace KDNSSD { RemoteService::RemoteService(const QString &name, const QString &type, const QString &domain) : ServiceBase(new RemoteServicePrivate(this, name, type, domain)) { + QObject::connect(&AvahiDisconnectHandler::instance (), &AvahiDisconnectHandler::avahiDisconnected, this, + [this]() { + K_D; + if(d->m_resolver) { + delete d->m_resolver; + d->m_resolver = nullptr; + d->m_running = false; + emit resolved(false); + } + }); } RemoteService::~RemoteService() diff --git a/src/avahi-servicebrowser.cpp b/src/avahi-servicebrowser.cpp --- a/src/avahi-servicebrowser.cpp +++ b/src/avahi-servicebrowser.cpp @@ -26,6 +26,7 @@ #include "avahi_server_interface.h" #include #include +#include "avahi-disconn-handler.h" namespace KDNSSD { @@ -38,6 +39,7 @@ d->m_autoResolve = autoResolve; d->m_domain = domain; d->m_timer.setSingleShot(true); + QObject::connect(&AvahiDisconnectHandler::instance (), &AvahiDisconnectHandler::avahiDisconnected, d, [this]() { d->clean(); }); } ServiceBrowser::State ServiceBrowser::isAvailable() @@ -125,6 +127,17 @@ d->m_timer.start(domainIsLocal(d->m_domain) ? TIMEOUT_LAST_SERVICE : TIMEOUT_START_WAN); } +void ServiceBrowserPrivate::clean() +{ + m_running = false; + m_browserFinished = true; + delete m_browser; + m_browser = nullptr; + + m_duringResolve.clear(); + m_services.clear(); +} + void ServiceBrowserPrivate::serviceResolved(bool success) { QObject *sender_obj = const_cast(sender()); diff --git a/src/avahi-servicebrowser_p.h b/src/avahi-servicebrowser_p.h --- a/src/avahi-servicebrowser_p.h +++ b/src/avahi-servicebrowser_p.h @@ -35,6 +35,7 @@ { Q_OBJECT friend class ServiceBrowser; // So the public class may functor connect. + void clean(); public: ServiceBrowserPrivate(ServiceBrowser *parent) : QObject(), m_running(false), m_browser(nullptr), m_parent(parent) {} diff --git a/src/avahi-servicetypebrowser.cpp b/src/avahi-servicetypebrowser.cpp --- a/src/avahi-servicetypebrowser.cpp +++ b/src/avahi-servicetypebrowser.cpp @@ -24,6 +24,7 @@ #include "avahi_server_interface.h" #include "servicetypebrowser.h" #include "avahi_servicetypebrowser_interface.h" +#include "avahi-disconn-handler.h" #define UNSPEC -1 namespace KDNSSD @@ -33,6 +34,11 @@ { d->m_domain = domain; d->m_timer.setSingleShot(true); + QObject::connect(&AvahiDisconnectHandler::instance(), &AvahiDisconnectHandler::avahiDisconnected, this, + [this]() { + delete d->m_browser; + d->m_browser = 0; + }); } ServiceTypeBrowser::~ServiceTypeBrowser() diff --git a/src/avahi_listener.cpp b/src/avahi_listener.cpp --- a/src/avahi_listener.cpp +++ b/src/avahi_listener.cpp @@ -19,15 +19,21 @@ */ #include "avahi_listener_p.h" +#include "avahi-disconn-handler.h" namespace KDNSSD { AvahiListener::AvahiListener() { + m_connection = QObject::connect(&AvahiDisconnectHandler::instance(), &AvahiDisconnectHandler::avahiDisconnected, + [this]() { + m_dbusObjectPath.clear(); + }); } AvahiListener::~AvahiListener() { + QObject::disconnect(m_connection); } diff --git a/src/avahi_listener_p.h b/src/avahi_listener_p.h --- a/src/avahi_listener_p.h +++ b/src/avahi_listener_p.h @@ -23,6 +23,7 @@ #include #include +#include namespace KDNSSD { @@ -33,6 +34,7 @@ // object at hand. class AvahiListener { + QMetaObject::Connection m_connection; public: explicit AvahiListener(); virtual ~AvahiListener();