From 2622544691d10c8a2f35b21647823bf7470b51c3 Mon Sep 17 00:00:00 2001 From: Jonathan Bagg Date: Mon, 9 Oct 2017 21:23:00 -0400 Subject: [PATCH 1/5] Emit removeService() for all discovered services when browser is stopped. --- avahiclient.cpp | 4 +++- avahicore.cpp | 4 +++- bonjour.cpp | 4 +++- qzeroconf.h | 2 ++ 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/avahiclient.cpp b/avahiclient.cpp index 8f3036c..99b38a7 100644 --- a/avahiclient.cpp +++ b/avahiclient.cpp @@ -208,8 +208,10 @@ public: browser = NULL; QMap::iterator i; - for (i = pub->services.begin(); i != pub->services.end(); i++) + for (i = pub->services.begin(); i != pub->services.end(); i++) { + emit pub->serviceRemoved(*i); delete *i; + } pub->services.clear(); QMap::iterator r; diff --git a/avahicore.cpp b/avahicore.cpp index c9536cf..f98195a 100644 --- a/avahicore.cpp +++ b/avahicore.cpp @@ -220,8 +220,10 @@ public: browser = NULL; QMap::iterator i; - for (i = pub->services.begin(); i != pub->services.end(); i++) + for (i = pub->services.begin(); i != pub->services.end(); i++) { + emit pub->serviceRemoved(*i); delete *i; + } pub->services.clear(); QMap::iterator r; diff --git a/bonjour.cpp b/bonjour.cpp index 8ded869..4bb2355 100644 --- a/bonjour.cpp +++ b/bonjour.cpp @@ -250,8 +250,10 @@ void QZeroConfPrivate::cleanUp(DNSServiceRef toClean) browserSocket = NULL; } QMap::iterator i; - for (i = pub->services.begin(); i != pub->services.end(); i++) + for (i = pub->services.begin(); i != pub->services.end(); i++) { + emit pub->serviceRemoved(*i); delete *i; + } pub->services.clear(); } else if (toClean == dnssRef) { diff --git a/qzeroconf.h b/qzeroconf.h index ff28105..9053d5e 100644 --- a/qzeroconf.h +++ b/qzeroconf.h @@ -74,12 +74,14 @@ public: ~QZeroConf(); void startServicePublish(const char *name, const char *type, const char *domain, quint16 port); void stopServicePublish(void); + bool publishExists(void); inline void startBrowser(QString type) { startBrowser(type, QAbstractSocket::IPv4Protocol); } void startBrowser(QString type, QAbstractSocket::NetworkLayerProtocol protocol); void stopBrowser(void); + bool browserExists(void); void addServiceTxtRecord(QString nameOnly); void addServiceTxtRecord(QString name, QString value); void clearServiceTxtRecords(); From 8a9936a4a5a59ccd971e6a6c76eb6cc9d9056e21 Mon Sep 17 00:00:00 2001 From: Jonathan Bagg Date: Mon, 9 Oct 2017 21:25:58 -0400 Subject: [PATCH 2/5] Add publishExists() and browserExists() api calls. --- avahiclient.cpp | 16 ++++++++++++++++ avahicore.cpp | 16 ++++++++++++++++ bonjour.cpp | 16 ++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/avahiclient.cpp b/avahiclient.cpp index 99b38a7..a7672e2 100644 --- a/avahiclient.cpp +++ b/avahiclient.cpp @@ -271,6 +271,14 @@ void QZeroConf::stopServicePublish(void) } } +bool QZeroConf::publishExists(void) +{ + if (pri->group) + return true; + else + return false; +} + // http://www.zeroconf.org/rendezvous/txtrecords.html void QZeroConf::addServiceTxtRecord(QString nameOnly) @@ -314,3 +322,11 @@ void QZeroConf::stopBrowser(void) { pri->broswerCleanUp(); } + +bool QZeroConf::browserExists(void) +{ + if (pri->browser) + return true; + else + return false; +} diff --git a/avahicore.cpp b/avahicore.cpp index f98195a..ce9a202 100644 --- a/avahicore.cpp +++ b/avahicore.cpp @@ -311,6 +311,14 @@ void QZeroConf::stopServicePublish(void) } } +bool QZeroConf::publishExists(void) +{ + if (pri->group) + return true; + else + return false; +} + // http://www.zeroconf.org/rendezvous/txtrecords.html void QZeroConf::addServiceTxtRecord(QString nameOnly) @@ -354,3 +362,11 @@ void QZeroConf::stopBrowser(void) { pri->broswerCleanUp(); } + +bool QZeroConf::browserExists(void) +{ + if (pri->browser) + return true; + else + return false; +} diff --git a/bonjour.cpp b/bonjour.cpp index 4bb2355..7b43222 100644 --- a/bonjour.cpp +++ b/bonjour.cpp @@ -320,6 +320,14 @@ void QZeroConf::stopServicePublish(void) pri->cleanUp(pri->dnssRef); } +bool QZeroConf::publishExists(void) +{ + if (pri->dnssRef) + return true; + else + return false; +} + void QZeroConf::addServiceTxtRecord(QString nameOnly) { pri->txt.append((quint8) nameOnly.size()); @@ -376,3 +384,11 @@ void QZeroConf::stopBrowser(void) { pri->cleanUp(pri->browser); } + +bool QZeroConf::browserExists(void) +{ + if (pri->browser) + return true; + else + return false; +} From c130cb697d530aa6d626782292f6aa495922fbd6 Mon Sep 17 00:00:00 2001 From: Jonathan Bagg Date: Mon, 9 Oct 2017 21:30:17 -0400 Subject: [PATCH 3/5] Example now stops and starts service publish and service discovery when application is suspended (device sleeps) and becomes active (device wakes). Important on iOS devices as device sleep kills browser and service publisher. --- README.md | 10 +++++++++- example/window.cpp | 37 ++++++++++++++++++++++++++++--------- example/window.h | 6 ++++-- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index a78174d..63c71ca 100644 --- a/README.md +++ b/README.md @@ -107,4 +107,12 @@ qDebug() << zcs->txt["Qt"]; Qt5 -On Linux, libavahi-client-dev and libavahi-common-dev \ No newline at end of file +On Linux, libavahi-client-dev and libavahi-common-dev + +### Apple App Store deployment + +Publishing GPL software in the App Store is a [violation of the GPL](https://news.ycombinator.com/item?id=3488833). If you need to publish an app in the Apple App Store that uses QZeroConf, please contact me for a copy of QZeroConf with a BSD licence. + +### iOS device sleep + +When iOS puts the device to sleep, it breaks the DNS-SD browser and service publisher. The only way around this is to call stopServicePublish() and stopBrowser() when the application state changes to Qt::ApplicationSuspended (sleep) and then call start startPublish() and startBrowser() when the application state changes to Qt::ApplicationActive (wake). See appStateChanged() in example. diff --git a/example/window.cpp b/example/window.cpp index f58e85f..757f4a9 100644 --- a/example/window.cpp +++ b/example/window.cpp @@ -24,6 +24,7 @@ Example app to demonstrate service publishing and service discovery --------------------------------------------------------------------------------------------------- **************************************************************************************************/ +#include #include #include #include @@ -54,9 +55,9 @@ mainWindow::mainWindow() connect(&zeroConf, SIGNAL(serviceAdded(QZeroConfService *)), this, SLOT(addService(QZeroConfService *))); connect(&zeroConf, SIGNAL(serviceRemoved(QZeroConfService *)), this, SLOT(removeService(QZeroConfService *))); + connect(qGuiApp, SIGNAL(applicationStateChanged(Qt::ApplicationState)), this, SLOT(appStateChanged(Qt::ApplicationState))); - zeroConf.startBrowser("_qtzeroconf_test._tcp"); - startPublish(); + publishEnabled = 1; } void mainWindow::buildGUI() @@ -68,13 +69,13 @@ void mainWindow::buildGUI() button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); layout->addWidget(button); layout->setAlignment(button, Qt::AlignHCenter); - connect(button, SIGNAL(clicked()), this, SLOT(startPublish())); + connect(button, &QPushButton::clicked, this, &mainWindow::startPublishClicked); button = new QPushButton(tr(" Disable Publish ")); button->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); layout->addWidget(button); layout->setAlignment(button, Qt::AlignHCenter); - connect(button, SIGNAL(clicked()), this, SLOT(stopPublish())); + connect(button, &QPushButton::clicked, this, &mainWindow::stopPublishClicked); table.verticalHeader()->hide(); table.horizontalHeader()->hide(); @@ -102,21 +103,39 @@ QString mainWindow::buildName(void) return name; } +void mainWindow::appStateChanged(Qt::ApplicationState state) +{ + if (state == Qt::ApplicationSuspended) { + zeroConf.stopServicePublish(); + zeroConf.stopBrowser(); + } + else if (state == Qt::ApplicationActive) { + if (publishEnabled && !zeroConf.publishExists()) + startPublish(); + if (!zeroConf.browserExists()) + zeroConf.startBrowser("_qtzeroconf_test._tcp"); + } +} + // ---------- Service Publish ---------- void mainWindow::startPublish() { - if (publishEnabled) - return; - publishEnabled = 1; - zeroConf.clearServiceTxtRecords(); zeroConf.addServiceTxtRecord("Qt", "the best!"); zeroConf.addServiceTxtRecord("ZeroConf is nice too"); zeroConf.startServicePublish(buildName().toUtf8(), "_qtzeroconf_test._tcp", "local", 11437); } -void mainWindow::stopPublish() +void mainWindow::startPublishClicked() +{ + if (publishEnabled) + return; + publishEnabled = 1; + startPublish(); +} + +void mainWindow::stopPublishClicked() { if (!publishEnabled) return; diff --git a/example/window.h b/example/window.h index b259b50..b4a53f1 100644 --- a/example/window.h +++ b/example/window.h @@ -40,14 +40,16 @@ public: private: void buildGUI(); + void startPublish(); QString buildName(void); QTableWidget table; QZeroConf zeroConf; bool publishEnabled; private slots: - void startPublish(); - void stopPublish(); + void appStateChanged(Qt::ApplicationState state); + void startPublishClicked(); + void stopPublishClicked(); void addService(QZeroConfService *item); void removeService(QZeroConfService *item); }; From a8f3dac8b836ded09a1af691d7b1dacd0e74c474 Mon Sep 17 00:00:00 2001 From: Jonathan Bagg Date: Mon, 9 Oct 2017 21:33:40 -0400 Subject: [PATCH 4/5] Example now stops and starts service publish and service discovery when application is suspended (device sleeps) and becomes active (device wakes). Important on iOS devices as device sleep kills browser and service publisher. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 63c71ca..2d646f0 100644 --- a/README.md +++ b/README.md @@ -115,4 +115,4 @@ Publishing GPL software in the App Store is a [violation of the GPL](https://new ### iOS device sleep -When iOS puts the device to sleep, it breaks the DNS-SD browser and service publisher. The only way around this is to call stopServicePublish() and stopBrowser() when the application state changes to Qt::ApplicationSuspended (sleep) and then call start startPublish() and startBrowser() when the application state changes to Qt::ApplicationActive (wake). See appStateChanged() in example. +When iOS puts the device to sleep, it breaks the DNS-SD browser and service publisher. The only way around this is to call stopServicePublish() and stopBrowser() when the application state changes to Qt::ApplicationSuspended (sleep) and then call startPublish() and startBrowser() when the application state changes to Qt::ApplicationActive (wake). See appStateChanged() in example. From e9ecf39c369578fa38ed15dfd4941c2a907df28c Mon Sep 17 00:00:00 2001 From: Matthias Kollmann Date: Mon, 16 Oct 2017 17:12:09 +0200 Subject: [PATCH 5/5] added parent to QZeroconf constructor --- avahiclient.cpp | 2 +- avahicore.cpp | 2 +- bonjour.cpp | 2 +- qzeroconf.h | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/avahiclient.cpp b/avahiclient.cpp index 8f3036c..55ce737 100644 --- a/avahiclient.cpp +++ b/avahiclient.cpp @@ -230,7 +230,7 @@ public: }; -QZeroConf::QZeroConf() +QZeroConf::QZeroConf(QObject *parent) : QObject (parent) { pri = new QZeroConfPrivate(this); } diff --git a/avahicore.cpp b/avahicore.cpp index c9536cf..04b7a91 100644 --- a/avahicore.cpp +++ b/avahicore.cpp @@ -269,7 +269,7 @@ public: }; -QZeroConf::QZeroConf() +QZeroConf::QZeroConf(QObject *parent) : QObject (parent) { pri = new QZeroConfPrivate(this); } diff --git a/bonjour.cpp b/bonjour.cpp index 8ded869..05d2b07 100644 --- a/bonjour.cpp +++ b/bonjour.cpp @@ -265,7 +265,7 @@ void QZeroConfPrivate::cleanUp(DNSServiceRef toClean) DNSServiceRefDeallocate(toClean); } -QZeroConf::QZeroConf() +QZeroConf::QZeroConf(QObject *parent) : QObject (parent) { pri = new QZeroConfPrivate(this); } diff --git a/qzeroconf.h b/qzeroconf.h index ff28105..e28a90a 100644 --- a/qzeroconf.h +++ b/qzeroconf.h @@ -70,7 +70,7 @@ public: serviceNameCollision = -2, browserFailed = -3, }; - QZeroConf(); + QZeroConf(QObject *parent = Q_NULLPTR); ~QZeroConf(); void startServicePublish(const char *name, const char *type, const char *domain, quint16 port); void stopServicePublish(void);