MythTV master
bonjourregister.cpp
Go to the documentation of this file.
1#include "bonjourregister.h"
2
3#include <cstdlib>
4#include <limits> // workaround QTBUG-90395
5
6#include <QSocketNotifier>
7#include <QtEndian>
8
9#include "mythrandom.h"
10#include "mythlogging.h"
11
12#define LOC QString("Bonjour: ")
13
15
17 : QObject(parent)
18{
19 setenv("AVAHI_COMPAT_NOWARN", "1", 1);
20}
21
23{
24 if (m_socket) {
25 m_socket->setEnabled(false);
26 m_socket->deleteLater();
27 m_socket = nullptr;
28 }
29
30 if (m_dnssref)
31 {
32 LOG(VB_GENERAL, LOG_INFO, LOC +
33 QString("De-registering service '%1' on '%2'")
34 .arg(m_type.data(), m_name.data()));
35 DNSServiceRefDeallocate(m_dnssref);
36 }
37 m_dnssref = nullptr;
38
39 delete m_lock;
40 m_lock = nullptr;
41}
42
43bool BonjourRegister::Register(uint16_t port, const QByteArray &type,
44 const QByteArray &name, const QByteArray &txt)
45{
46 if (m_dnssref)
47 {
48 LOG(VB_GENERAL, LOG_WARNING, LOC + "Service already registered.");
49 return true;
50 }
51
52 m_lock = new QMutexLocker(&g_lock);
53 m_data = txt;
54
55 uint16_t qport = qToBigEndian(port);
56 DNSServiceErrorType res =
57 DNSServiceRegister(&m_dnssref, 0, 0, name.data(), type.data(),
58 nullptr, nullptr, qport, txt.size(), (void*)txt.data(),
59 BonjourCallback, this);
60
61 if (kDNSServiceErr_NoError != res)
62 {
63 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Error: %1").arg(res));
64 }
65 else
66 {
67 int fd = DNSServiceRefSockFD(m_dnssref);
68 if (fd != -1)
69 {
70 m_socket = new QSocketNotifier(fd, QSocketNotifier::Read, this);
71 m_socket->setEnabled(true);
72 connect(m_socket, &QSocketNotifier::activated,
74 delete m_lock; // would already have been deleted, but just in case
75 m_lock = nullptr;
76 return true;
77 }
78 }
79
80 LOG(VB_GENERAL, LOG_ERR, LOC + "Failed to register service.");
81 delete m_lock;
82 m_lock = nullptr;
83
84 return false;
85}
86
87
89{
90 DNSServiceErrorType res = DNSServiceProcessResult(m_dnssref);
91 if (kDNSServiceErr_NoError != res)
92 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Read Error: %1").arg(res));
93}
94
95
96void BonjourRegister::BonjourCallback([[maybe_unused]] DNSServiceRef ref,
97 [[maybe_unused]] DNSServiceFlags flags,
98 DNSServiceErrorType errorcode,
99 const char *name, const char *type,
100 const char *domain, void *object)
101{
102 auto *bonjour = static_cast<BonjourRegister *>(object);
103 if (bonjour)
104 {
105 delete bonjour->m_lock;
106 bonjour->m_lock = nullptr;
107 }
108
109 if (kDNSServiceErr_NoError != errorcode)
110 {
111 LOG(VB_GENERAL, LOG_ERR, LOC + QString("Callback Error: %1")
112 .arg(errorcode));
113 }
114 else if (bonjour)
115 {
116 LOG(VB_GENERAL, LOG_INFO, LOC +
117 QString("Service registration complete: name '%1' type '%2' domain: '%3'")
118 .arg(QString::fromUtf8(name), QString::fromUtf8(type),
119 QString::fromUtf8(domain)));
120 bonjour->m_name = name;
121 bonjour->m_type = type;
122 }
123 else
124 {
125 LOG(VB_GENERAL, LOG_ERR, LOC +
126 QString("BonjourCallback for unknown object."));
127 }
128}
129
131{
132 QByteArray data = m_data;
133 QByteArray rnd;
134
135 data.append(7);
136 data.append("_rnd=");
137 rnd.append(MythRandom(33, 33 + 80 - 1));
138 data.append(rnd.toHex());
139
140 return data;
141}
142
144{
145 if (!m_dnssref)
146 {
147 // nothing to refresh
148 return false;
149 }
150
151 QByteArray data = RandomizeData();
152
153 DNSServiceErrorType res =
154 DNSServiceUpdateRecord(m_dnssref, /* DNSServiceRef sdRef */
155 nullptr, /* DNSRecordRef RecordRef */
156 0, /* DNSServiceFlags flags */
157 data.size(), /* uint16_t rdlen */
158 (void*)data.data(), /* const void *rdata */
159 0); /* uint32_t ttl */
160
161 if (kDNSServiceErr_NoError != res)
162 {
163 LOG(VB_GENERAL, LOG_ERR, LOC +
164 QString("Error ReAnnounceService(%1): %2")
165 .arg(m_name.data()).arg(res));
166 }
167 return kDNSServiceErr_NoError != res;
168}
#define LOC
static QMutex g_lock
QByteArray m_data
QByteArray m_name
QMutexLocker< QMutex > * m_lock
QByteArray m_type
QByteArray RandomizeData(void)
QSocketNotifier * m_socket
BonjourRegister(QObject *parent=nullptr)
DNSServiceRef m_dnssref
static void DNSSD_API BonjourCallback(DNSServiceRef ref, DNSServiceFlags flags, DNSServiceErrorType errorcode, const char *name, const char *type, const char *domain, void *object)
~BonjourRegister() override
bool ReAnnounceService(void)
bool Register(uint16_t port, const QByteArray &type, const QByteArray &name, const QByteArray &txt)
#define setenv(x, y, z)
Definition: compat.h:85
unsigned short uint16_t
Definition: iso6937tables.h:3
#define LOG(_MASK_, _LEVEL_, _QSTRING_)
Definition: mythlogging.h:39
Convenience inline random number generator functions.
uint32_t MythRandom()
generate 32 random bits
Definition: mythrandom.h:20