• Skip to content
  • Skip to link menu
Trinity API Reference
  • Trinity API Reference
  • dnssd
 

dnssd

  • dnssd
publicservice.cpp
1 /* This file is part of the KDE project
2  *
3  * Copyright (C) 2004, 2005 Jakub Stachowski <qbast@go2.pl>
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Library General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13  * Library General Public License for more details.
14  *
15  * You should have received a copy of the GNU Library General Public License
16  * along with this library; see the file COPYING.LIB. If not, write to
17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18  * Boston, MA 02110-1301, USA.
19  */
20 
21 #include "config.h"
22 
23 #include "publicservice.h"
24 #ifdef HAVE_SYS_TYPES_H
25 #include <sys/types.h>
26 #endif
27 #include <netinet/in.h>
28 #include <sys/socket.h>
29 #include <tqapplication.h>
30 #include <network/tdesocketaddress.h>
31 #include <kurl.h>
32 #include <unistd.h>
33 #ifdef HAVE_DNSSD
34 #include <avahi-client/client.h>
35 #ifdef AVAHI_API_0_6
36 #include <avahi-client/publish.h>
37 #endif
38 #include <avahi-common/alternative.h>
39 #include <avahi-common/strlst.h>
40 #endif
41 #include "sdevent.h"
42 #include "responder.h"
43 #include "servicebrowser.h"
44 #include "settings.h"
45 
46 namespace DNSSD
47 {
48 static unsigned long publicIP();
49 
50 #ifdef HAVE_DNSSD
51 void publish_callback (AvahiEntryGroup*, AvahiEntryGroupState s, void *context);
52 #endif
53 
54 class PublicServicePrivate
55 {
56 public:
57  PublicServicePrivate() : m_published(false), m_running(false), m_collision(false)
58 #ifdef HAVE_DNSSD
59  , m_group(0)
60 #endif
61  {}
62  bool m_published;
63  bool m_running;
64  bool m_collision;
65 #ifdef HAVE_DNSSD
66  AvahiEntryGroup* m_group;
67 #endif
68  void commit()
69  {
70 #ifdef HAVE_DNSSD
71  if (!m_collision) avahi_entry_group_commit(m_group);
72 #endif
73  }
74 
75 };
76 
77 PublicService::PublicService(const TQString& name, const TQString& type, unsigned int port,
78  const TQString& domain)
79  : TQObject(), ServiceBase(name, type, TQString::null, domain, port)
80 {
81  d = new PublicServicePrivate;
82 #ifdef HAVE_DNSSD
83  if (Responder::self().client()) {
84  d->m_group = avahi_entry_group_new(Responder::self().client(), publish_callback,this);
85  connect(&Responder::self(),TQ_SIGNAL(stateChanged(AvahiClientState)),this,TQ_SLOT(clientState(AvahiClientState)));
86  }
87 #endif
88  if (domain.isNull())
89  if (Configuration::publishType()==Configuration::EnumPublishType::LAN) m_domain="local.";
90  else m_domain=Configuration::publishDomain();
91 }
92 
93 
94 PublicService::~PublicService()
95 {
96 #ifdef HAVE_DNSSD
97  if (d->m_group) avahi_entry_group_free(d->m_group);
98 #endif
99  delete d;
100 }
101 
102 void PublicService::tryApply()
103 {
104  if (fillEntryGroup()) d->commit();
105  else {
106  stop();
107  emit published(false);
108  }
109 }
110 
111 void PublicService::setServiceName(const TQString& serviceName)
112 {
113  m_serviceName = serviceName;
114 #ifdef HAVE_DNSSD
115  if (d->m_running) {
116  avahi_entry_group_reset(d->m_group);
117  tryApply();
118  }
119 #endif
120 }
121 
122 void PublicService::setDomain(const TQString& domain)
123 {
124  m_domain = domain;
125 #ifdef HAVE_DNSSD
126  if (d->m_running) {
127  avahi_entry_group_reset(d->m_group);
128  tryApply();
129  }
130 #endif
131 }
132 
133 
134 void PublicService::setType(const TQString& type)
135 {
136  m_type = type;
137 #ifdef HAVE_DNSSD
138  if (d->m_running) {
139  avahi_entry_group_reset(d->m_group);
140  tryApply();
141  }
142 #endif
143 }
144 
145 void PublicService::setPort(unsigned short port)
146 {
147  m_port = port;
148 #ifdef HAVE_DNSSD
149  if (d->m_running) {
150  avahi_entry_group_reset(d->m_group);
151  tryApply();
152  }
153 #endif
154 }
155 
156 void PublicService::setTextData(const TQMap<TQString,TQString>& textData)
157 {
158  m_textData = textData;
159 #ifdef HAVE_DNSSD
160  if (d->m_running) {
161  avahi_entry_group_reset(d->m_group);
162  tryApply();
163  }
164 #endif
165 }
166 
167 bool PublicService::isPublished() const
168 {
169  return d->m_published;
170 }
171 
172 bool PublicService::publish()
173 {
174  publishAsync();
175  while (d->m_running && !d->m_published) Responder::self().process();
176  return d->m_published;
177 }
178 
179 void PublicService::stop()
180 {
181 #ifdef HAVE_DNSSD
182  if (d->m_group) avahi_entry_group_reset(d->m_group);
183 #endif
184  d->m_published = false;
185 }
186 bool PublicService::fillEntryGroup()
187 {
188 #ifdef HAVE_DNSSD
189  AvahiStringList *s=0;
190  TQMap<TQString,TQString>::ConstIterator itEnd = m_textData.end();
191  for (TQMap<TQString,TQString>::ConstIterator it = m_textData.begin(); it!=itEnd ; ++it)
192  s = avahi_string_list_add_pair(s, it.key().utf8(),it.data().utf8());
193 #ifdef AVAHI_API_0_6
194  bool res = (!avahi_entry_group_add_service_strlst(d->m_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, (AvahiPublishFlags)0,
195  m_serviceName.isNull() ? avahi_client_get_host_name(Responder::self().client()) : m_serviceName.utf8().data(),
196  m_type.ascii(),domainToDNS(m_domain),m_hostName.utf8(),m_port,s));
197 #else
198  bool res = (!avahi_entry_group_add_service_strlst(d->m_group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
199  m_serviceName.isNull() ? avahi_client_get_host_name(Responder::self().client()) : m_serviceName.utf8().data(),
200  m_type.ascii(),m_domain.utf8(),m_hostName.utf8(),m_port,s));
201 #endif
202  avahi_string_list_free(s);
203  return res;
204 #else
205  return FALSE;
206 #endif
207 }
208 
209 void PublicService::clientState(AvahiClientState s)
210 {
211  if (!d->m_running) return;
212 #ifdef HAVE_DNSSD
213  switch (s) {
214 #ifdef AVAHI_API_0_6
215  case AVAHI_CLIENT_FAILURE:
216 #else
217  case AVAHI_CLIENT_S_INVALID:
218  case AVAHI_CLIENT_DISCONNECTED:
219 #endif
220  stop();
221  emit published(false);
222  break;
223  case AVAHI_CLIENT_S_REGISTERING:
224  case AVAHI_CLIENT_S_COLLISION:
225  avahi_entry_group_reset(d->m_group);
226  d->m_collision=true;
227  break;
228  case AVAHI_CLIENT_S_RUNNING:
229  if (d->m_collision) {
230  d->m_collision=false;
231  tryApply();
232  }
233  }
234 #endif
235 }
236 
237 void PublicService::publishAsync()
238 {
239  if (d->m_running) stop();
240 
241 #ifdef HAVE_DNSSD
242  if (!d->m_group) {
243  emit published(false);
244  return;
245  }
246  AvahiClientState s=Responder::self().state();
247 #endif
248  d->m_running=true;
249  d->m_collision=true; // make it look like server is getting out of collision to force registering
250 #ifdef HAVE_DNSSD
251  clientState(s);
252 #endif
253 }
254 
255 #ifdef HAVE_DNSSD
256 void publish_callback (AvahiEntryGroup*, AvahiEntryGroupState s, void *context)
257 {
258  TQObject *obj = reinterpret_cast<TQObject*>(context);
259  if (s!=AVAHI_ENTRY_GROUP_ESTABLISHED && s!=AVAHI_ENTRY_GROUP_COLLISION) return;
260  PublishEvent* pev=new PublishEvent(s==AVAHI_ENTRY_GROUP_ESTABLISHED);
261  TQApplication::postEvent(obj, pev);
262 }
263 #endif
264 
265 const KURL PublicService::toInvitation(const TQString& host)
266 {
267  KURL url;
268  url.setProtocol("invitation");
269  if (host.isEmpty()) { // select best address
270  unsigned long s_address = publicIP();
271  if (!s_address) return KURL();
272  KNetwork::KIpAddress addr(s_address);
273  url.setHost(addr.toString());
274  } else url.setHost(host);
275  //FIXME: if there is no public interface, select any non-loopback
276  url.setPort(m_port);
277  url.setPath("/"+m_type+"/"+KURL::encode_string(m_serviceName));
278  TQString query;
279  TQMap<TQString,TQString>::ConstIterator itEnd = m_textData.end();
280  for (TQMap<TQString,TQString>::ConstIterator it = m_textData.begin(); it!=itEnd ; ++it)
281  url.addQueryItem(it.key(),it.data());;
282  return url;
283 }
284 
285 void PublicService::customEvent(TQCustomEvent* event)
286 {
287 #ifdef HAVE_DNSSD
288  if (event->type()==TQEvent::User+SD_PUBLISH) {
289  if (!static_cast<PublishEvent*>(event)->m_ok) {
290  setServiceName(TQString::fromUtf8(avahi_alternative_service_name(m_serviceName.utf8())));
291  return;
292  }
293  d->m_published=true;
294  emit published(true);
295  }
296 #endif
297 }
298 
299 void PublicService::virtual_hook(int, void*)
300 {
301 }
302 
303 static unsigned long publicIP()
304 {
305  struct sockaddr_in addr;
306  socklen_t len = sizeof(addr);
307  int sock = socket(AF_INET,SOCK_DGRAM,0);
308  if (sock == -1) return 0;
309  addr.sin_family = AF_INET;
310  addr.sin_port = 1; // Not important, any port and public address will do
311  addr.sin_addr.s_addr = 0x11111111;
312  if ((connect(sock,(const struct sockaddr*)&addr,sizeof(addr))) == -1) { close(sock); return 0; }
313  if ((getsockname(sock,(struct sockaddr*)&addr, &len)) == -1) { close(sock); return 0; }
314  ::close(sock);
315  return addr.sin_addr.s_addr;
316 }
317 
318 
319 }
320 
321 #include "publicservice.moc"
DNSSD::PublicService::setType
void setType(const TQString &type)
Sets type of service.
Definition: publicservice.cpp:134
DNSSD::PublicService::isPublished
bool isPublished() const
Returns true is currently published.
Definition: publicservice.cpp:167
DNSSD::PublicService::setTextData
void setTextData(const TQMap< TQString, TQString > &textData)
Sets new text properties.
Definition: publicservice.cpp:156
DNSSD::PublicService::published
void published(bool)
Emitted when publishing is complete - parameter is set to true if it was successfull.
DNSSD::PublicService::setPort
void setPort(unsigned short port)
Sets port.
Definition: publicservice.cpp:145
DNSSD::PublicService::toInvitation
const KURL toInvitation(const TQString &host=TQString::null)
Translates service into URL that can be sent to another user.
Definition: publicservice.cpp:265
DNSSD::PublicService::publishAsync
void publishAsync()
Asynchronous version of publish().
Definition: publicservice.cpp:237
DNSSD::PublicService::PublicService
PublicService(const TQString &name=TQString::null, const TQString &type=TQString::null, unsigned int port=0, const TQString &domain=TQString::null)
Definition: publicservice.cpp:77
DNSSD::PublicService::publish
bool publish()
Synchrounous publish.
Definition: publicservice.cpp:172
DNSSD::PublicService::setServiceName
void setServiceName(const TQString &serviceName)
Sets name of the service.
Definition: publicservice.cpp:111
DNSSD::PublicService::stop
void stop()
Stops publishing or abort incomplete publish request.
Definition: publicservice.cpp:179
DNSSD::PublicService::setDomain
void setDomain(const TQString &domain)
Sets domain where service is published.
Definition: publicservice.cpp:122
DNSSD::ServiceBase
This class is used to carry information about service.
Definition: servicebase.h:41
DNSSD::ServiceBase::domain
const TQString & domain() const
Returns domain that given service belongs to.
Definition: servicebase.cpp:79
DNSSD::ServiceBase::m_textData
TQMap< TQString, TQString > m_textData
Map of TXT properties.
Definition: servicebase.h:99
DNSSD::ServiceBase::type
const TQString & type() const
Returns type of service.
Definition: servicebase.cpp:74
DNSSD::ServiceBase::textData
const TQMap< TQString, TQString > & textData() const
Returns read only map of text properties.
Definition: servicebase.cpp:93
DNSSD::ServiceBase::port
unsigned short port() const
Returns port number.
Definition: servicebase.cpp:89
DNSSD::ServiceBase::serviceName
const TQString & serviceName() const
Returns name of service.
Definition: servicebase.cpp:69

dnssd

Skip menu "dnssd"
  • Main Page
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

dnssd

Skip menu "dnssd"
  • arts
  • dcop
  • dnssd
  • interfaces
  •   kspeech
  •     interface
  •     library
  •   tdetexteditor
  • kate
  • kded
  • kdoctools
  • kimgio
  • kjs
  • libtdemid
  • libtdescreensaver
  • tdeabc
  • tdecmshell
  • tdecore
  • tdefx
  • tdehtml
  • tdeinit
  • tdeio
  •   bookmarks
  •   httpfilter
  •   kpasswdserver
  •   kssl
  •   tdefile
  •   tdeio
  •   tdeioexec
  • tdeioslave
  •   http
  • tdemdi
  •   tdemdi
  • tdenewstuff
  • tdeparts
  • tdeprint
  • tderandr
  • tderesources
  • tdespell2
  • tdesu
  • tdeui
  • tdeunittest
  • tdeutils
  • tdewallet
Generated for dnssd by doxygen 1.9.1
This website is maintained by Timothy Pearson.