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