KDNSSD

mdnsd-publicservice.cpp
1 /*
2  This file is part of the KDE project
3 
4  SPDX-FileCopyrightText: 2004, 2005 Jakub Stachowski <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #include <QCoreApplication>
10 #include <QStringList>
11 #include <netinet/in.h>
12 #include "publicservice.h"
13 #include "servicebase_p.h"
14 #include "mdnsd-sdevent.h"
15 #include "mdnsd-responder.h"
16 
17 #define K_D PublicServicePrivate* d=static_cast<PublicServicePrivate*>(this->d)
18 
19 namespace KDNSSD
20 {
21 void publish_callback(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name,
22  const char *, const char *, void *context);
23 class PublicServicePrivate : public Responder, public ServiceBasePrivate
24 {
25 public:
26  PublicServicePrivate(PublicService *parent, const QString &name, const QString &type, unsigned int port,
27  const QString &domain) : Responder(), ServiceBasePrivate(name, type, domain, QString(), port),
28  m_published(false), m_parent(parent)
29  {}
30  bool m_published;
31  PublicService *m_parent;
32  QStringList m_subtypes;
33  virtual void customEvent(QEvent *event);
34 };
35 
36 PublicService::PublicService(const QString &name, const QString &type, unsigned int port,
37  const QString &domain, const QStringList &subtypes)
38  : QObject(), ServiceBase(new PublicServicePrivate(this, name, type, port, domain))
39 {
40  K_D;
41  if (domain.isNull()) {
42  d->m_domain = "local.";
43  }
44  d->m_subtypes = subtypes;
45 }
46 
47 PublicService::~PublicService()
48 {
49  stop();
50 }
51 
52 void PublicService::setServiceName(const QString &serviceName)
53 {
54  K_D;
55  d->m_serviceName = serviceName;
56  if (d->isRunning()) {
57  stop();
58  publishAsync();
59  }
60 }
61 
62 void PublicService::setDomain(const QString &domain)
63 {
64  K_D;
65  d->m_domain = domain;
66  if (d->isRunning()) {
67  stop();
68  publishAsync();
69  }
70 }
71 
73 {
74  K_D;
75  return d->m_subtypes;
76 }
77 
78 void PublicService::setType(const QString &type)
79 {
80  K_D;
81  d->m_type = type;
82  if (d->isRunning()) {
83  stop();
84  publishAsync();
85  }
86 }
87 
88 void PublicService::setSubTypes(const QStringList &subtypes)
89 {
90  K_D;
91  d->m_subtypes = subtypes;
92  if (d->isRunning()) {
93  stop();
94  publishAsync();
95  }
96 }
97 
98 void PublicService::setPort(unsigned short port)
99 {
100  K_D;
101  d->m_port = port;
102  if (d->isRunning()) {
103  stop();
104  publishAsync();
105  }
106 }
107 
108 bool PublicService::isPublished() const
109 {
110  K_D;
111  return d->m_published;
112 }
113 
115 {
116  K_D;
117  d->m_textData = textData;
118  if (d->isRunning()) {
119  stop();
120  publishAsync();
121  }
122 }
123 
125 {
126  K_D;
127  publishAsync();
128  while (d->isRunning() && !d->m_published) {
129  d->process();
130  }
131  return d->m_published;
132 }
133 
134 void PublicService::stop()
135 {
136  K_D;
137  d->stop();
138  d->m_published = false;
139 }
140 
142 {
143  K_D;
144  if (d->isRunning()) {
145  stop();
146  }
147  TXTRecordRef txt;
148  TXTRecordCreate(&txt, 0, 0);
149  QMap<QString, QByteArray>::ConstIterator itEnd = d->m_textData.cend();
150  for (QMap<QString, QByteArray>::ConstIterator it = d->m_textData.cbegin(); it != itEnd; ++it) {
151  if (TXTRecordSetValue(&txt, it.key().toUtf8().constData(), it.value().length(), it.value().constData()) != kDNSServiceErr_NoError) {
152  TXTRecordDeallocate(&txt);
153  emit published(false);
154  return;
155  }
156  }
157  DNSServiceRef ref;
158  QString fullType = d->m_type;
159  for (const QString &subtype : qAsConst(d->m_subtypes)) {
160  fullType += ',' + subtype;
161  }
162  if (DNSServiceRegister(&ref, 0, 0, d->m_serviceName.toUtf8().constData(), fullType.toLatin1().constData(), domainToDNS(d->m_domain).constData(), NULL,
163  htons(d->m_port), TXTRecordGetLength(&txt), TXTRecordGetBytesPtr(&txt), publish_callback,
164  reinterpret_cast<void *>(d)) == kDNSServiceErr_NoError) {
165  d->setRef(ref);
166  }
167  TXTRecordDeallocate(&txt);
168  if (!d->isRunning()) {
169  emit published(false);
170  }
171 }
172 
173 void publish_callback(DNSServiceRef, DNSServiceFlags, DNSServiceErrorType errorCode, const char *name,
174  const char *, const char *, void *context)
175 {
176  QObject *obj = reinterpret_cast<QObject *>(context);
177  if (errorCode != kDNSServiceErr_NoError) {
178  ErrorEvent err;
179  QCoreApplication::sendEvent(obj, &err);
180  } else {
181  PublishEvent pev(QString::fromUtf8(name));
182  QCoreApplication::sendEvent(obj, &pev);
183  }
184 }
185 
186 void PublicServicePrivate::customEvent(QEvent *event)
187 {
188  if (event->type() == QEvent::User + SD_ERROR) {
189  m_parent->stop();
190  emit m_parent->published(false);
191  }
192  if (event->type() == QEvent::User + SD_PUBLISH) {
193  m_published = true;
194  emit m_parent->published(true);
195  m_serviceName = static_cast<PublishEvent *>(event)->m_name;
196  }
197 }
198 
199 void PublicService::virtual_hook(int, void *)
200 {
201 }
202 
203 }
204 
205 #include "moc_publicservice.cpp"
void setPort(unsigned short port)
Sets the port.
QEvent::Type type() const const
const QChar * constData() const const
void setTextData(const QMap< QString, QByteArray > &textData)
Sets new text properties.
void setType(const QString &type)
Sets the service type.
void ref()
bool isNull() const const
virtual bool event(QEvent *e)
PublicService(const QString &name=QString(), const QString &type=QString(), unsigned int port=0, const QString &domain=QString(), const QStringList &subtypes=QStringList())
Creates a service description that can be published.
bool publish()
Publish the service synchronously.
void publishAsync()
Publish the service asynchronously.
QString fromUtf8(const char *str, int size)
KGuiItem stop()
const char * constData() const const
bool sendEvent(QObject *receiver, QEvent *event)
void setSubTypes(const QStringList &subtypes)
Sets the subtypetypes of the service.
void setServiceName(const QString &serviceName)
Sets the name of the service.
void stop()
Stops publishing or aborts an incomplete publish request.
QByteArray toLatin1() const const
QStringList subtypes() const
The subtypes of service.
void setDomain(const QString &domain)
Sets the domain where the service is published.
bool isPublished() const
Whether the service is currently published.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Thu Aug 13 2020 22:40:26 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.