Skip to content
Browse files

Add a simple Bonjour/Avahi service registration class.

This should work out of the box on OS X but requires the Avahi Bonjour
compatability layer on *nix (libdns_sd).

Fairly straightforward service registration and removal that will be
used by a couple of upcoming features (and could easily be used as an
extra layer of 'advertising' by both mythfrontend and mythbackend).
  • Loading branch information...
1 parent 1222fa2 commit b1f1fc8fd2754eab77bceff4b86ab842379ab81d Mark Kendall committed
View
10 mythtv/configure
@@ -138,6 +138,7 @@ Advanced options (experts only):
--libxml2-path=HDRLOC location of directory containing
'libxml/parser.h', not the
directory with parser.h [$libxml2_path_default]
+ --disable-libdns-sd disable DNS Service Discovery (Bonjour/Zeroconf/Avahi)
--with-bindings=LIST install the bindings specified in the
comma-separated list
@@ -1354,6 +1355,7 @@ MYTHTV_CONFIG_LIST='
asi
joystick_menu
libcec
+ libdns_sd
libfftw3
libmpeg2external
libxml2
@@ -1998,6 +2000,7 @@ enable asi
enable lamemp3
enable libass
enable libcec
+enable libdns_sd
enable libxml2
enable libudf
enable lirc
@@ -4138,6 +4141,8 @@ int main(void) {
EOF
fi
+enabled libdns_sd && check_lib dns_sd.h DNSServiceRegister -ldns_sd || disable libdns_sd
+
if enabled libxml2 ; then
if pkg-config --exists libxml-2.0 ; then
libxml2_path=`pkg-config --cflags-only-I libxml-2.0|sed -n "s/-I\([^ ]*\) *$/\1/p"`
@@ -4569,6 +4574,7 @@ echo "multi threaded libavcodec ${threads-no}"
if enabled frontend; then
echo "libxml2 support ${libxml2-no} [$libxml2_path]"
fi
+echo "libdns_sd (Bonjour) ${libdns_sd-no}"
echo "Frontend ${frontend-no}"
echo "Backend ${backend-no}"
echo "OpenGL ES 2.0 ${opengles-no}"
@@ -4879,6 +4885,10 @@ if enabled libxml2; then
fi
fi
+if enabled libdns_sd; then
+ append CONFIG_DEFINES "using_libdns_sd"
+fi
+
if enabled libudf; then
append CCONFIG "using_libudf"
fi
View
102 mythtv/libs/libmythbase/bonjourregister.cpp
@@ -0,0 +1,102 @@
+#include <QSocketNotifier>
+#include <QtEndian>
+#include "mythlogging.h"
+#include "bonjourregister.h"
+
+#define LOC QString("Bonjour: ")
+
+BonjourRegister::BonjourRegister(QObject *parent)
+ : QObject(parent), m_dnssref(0), m_socket(NULL)
+{
+}
+
+BonjourRegister::~BonjourRegister()
+{
+ if (m_socket)
+ m_socket->setEnabled(false);
+
+ if (m_dnssref)
+ {
+ LOG(VB_GENERAL, LOG_INFO, LOC + "De-registering service.");
+ DNSServiceRefDeallocate(m_dnssref);
+ }
+ m_dnssref = 0;
+
+ m_socket->deleteLater();
+ m_socket = NULL;
+}
+
+bool BonjourRegister::Register(uint16_t port, const QByteArray &type,
+ const QByteArray &name, const QByteArray &txt)
+{
+ if (m_dnssref)
+ {
+ LOG(VB_GENERAL, LOG_WARNING, LOC + "Service already registered.");
+ return true;
+ }
+
+ uint16_t qport = qToBigEndian(port);
+ DNSServiceErrorType res =
+ DNSServiceRegister(&m_dnssref, 0, 0, (const char*)name.data(),
+ (const char*)type.data(),
+ NULL, 0, qport, txt.size(), (void*)txt.data(),
+ BonjourCallback, this);
+
+ if (kDNSServiceErr_NoError != res)
+ {
+ LOG(VB_GENERAL, LOG_ERR, LOC + QString("Error: %1").arg(res));
+ }
+ else
+ {
+ int fd = DNSServiceRefSockFD(m_dnssref);
+ if (fd != -1)
+ {
+ m_socket = new QSocketNotifier(fd, QSocketNotifier::Read, this);
+ m_socket->setEnabled(true);
+ connect(m_socket, SIGNAL(activated(int)),
+ this, SLOT(socketReadyRead()));
+ return true;
+ }
+ }
+
+ LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to register service.");
+ return false;
+}
+
+
+void BonjourRegister::socketReadyRead()
+{
+ DNSServiceErrorType res = DNSServiceProcessResult(m_dnssref);
+ if (kDNSServiceErr_NoError != res)
+ LOG(VB_GENERAL, LOG_ERR, LOC + QString("Read Error: %1").arg(res));
+}
+
+
+void BonjourRegister::BonjourCallback(DNSServiceRef ref, DNSServiceFlags flags,
+ DNSServiceErrorType errorcode,
+ const char *name, const char *type,
+ const char *domain, void *object)
+{
+ (void)ref;
+ (void)flags;
+
+ BonjourRegister *bonjour = static_cast<BonjourRegister *>(object);
+ if (kDNSServiceErr_NoError != errorcode)
+ {
+ LOG(VB_GENERAL, LOG_ERR, LOC + QString("Callback Error: %1")
+ .arg(errorcode));
+ }
+ else if (bonjour)
+ {
+ LOG(VB_GENERAL, LOG_INFO, LOC +
+ QString("Service registration complete: name '%1' type '%2' domain: '%3'")
+ .arg(QString::fromUtf8(name)).arg(QString::fromUtf8(type))
+ .arg(QString::fromUtf8(domain)));
+ }
+ else
+ {
+ LOG(VB_GENERAL, LOG_ERR, LOC +
+ QString("BonjourCallback for unknown object."));
+ }
+}
+
View
32 mythtv/libs/libmythbase/bonjourregister.h
@@ -0,0 +1,32 @@
+#ifndef BONJOURREGISTER_H
+#define BONJOURREGISTER_H
+
+#include <QObject>
+#include <dns_sd.h>
+#include "mythbaseexp.h"
+
+class QSocketNotifier;
+
+class MBASE_PUBLIC BonjourRegister : public QObject
+{
+ Q_OBJECT
+ public:
+ BonjourRegister(QObject *parent = 0);
+ ~BonjourRegister();
+
+ bool Register(uint16_t port, const QByteArray &type, const QByteArray &name,
+ const QByteArray &txt);
+
+ private slots:
+ void socketReadyRead();
+
+ private:
+ static void DNSSD_API BonjourCallback(DNSServiceRef ref,
+ DNSServiceFlags flags,
+ DNSServiceErrorType errorcode,
+ const char *name, const char *type,
+ const char *domain, void *object);
+ DNSServiceRef m_dnssref;
+ QSocketNotifier *m_socket;
+};
+#endif
View
9 mythtv/libs/libmythbase/libmythbase.pro
@@ -63,7 +63,7 @@ inc.files += mythcoreutil.h mythlocale.h mythdownloadmanager.h
inc.files += mythtranslation.h iso639.h iso3166.h mythmedia.h util.h
inc.files += mythcdrom.h autodeletedeque.h dbutil.h mythhttppool.h mythdeque.h
inc.files += referencecounter.h mythcommandlineparser.h mthread.h mthreadpool.h
-inc.files += filesysteminfo.h hardwareprofile.h
+inc.files += filesysteminfo.h hardwareprofile.h bonjourregister.h
# Allow both #include <blah.h> and #include <libmythbase/blah.h>
inc2.path = $${PREFIX}/include/mythtv/libmythbase
@@ -100,6 +100,13 @@ use_hidesyms {
QMAKE_CXXFLAGS += -fvisibility=hidden
}
+using_libdns_sd {
+ DEFINES += USING_LIBDNS_SD
+ HEADERS += bonjourregister.h
+ SOURCES += bonjourregister.cpp
+ LIBS += -ldns_sd
+}
+
using_libudf {
DEFINES += USING_LIBUDF
LIBS += -ludf

0 comments on commit b1f1fc8

Please sign in to comment.
Something went wrong with that request. Please try again.