Fawkes API  Fawkes Development Version
service.cpp
1 
2 /***************************************************************************
3  * service.cpp - Network service representation
4  *
5  * Generated: Tue Nov 07 18:02:23 2006
6  * Copyright 2006-2007 Tim Niemueller [www.niemueller.de]
7  *
8  ****************************************************************************/
9 
10 /* This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version. A runtime exception applies to
14  * this software (see LICENSE.GPL_WRE file mentioned below for details).
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19  * GNU Library General Public License for more details.
20  *
21  * Read the full text in the LICENSE.GPL_WRE file in the doc directory.
22  */
23 
24 #include <arpa/inet.h>
25 #include <core/exceptions/system.h>
26 #include <netcomm/service_discovery/service.h>
27 #include <netcomm/utils/resolver.h>
28 #include <netinet/in.h>
29 #include <sys/types.h>
30 
31 #include <cstdarg>
32 #include <cstddef>
33 #include <cstdio>
34 #include <cstdlib>
35 #include <cstring>
36 #include <inttypes.h>
37 
38 namespace fawkes {
39 
40 /** @class NetworkService <netcomm/service_discovery/service.h>
41  * Representation of a service announced or found via service
42  * discovery (i.e. mDNS/DNS-SD via Avahi).
43  * This class is used in the C++ wrapper to talk about services.
44  *
45  * @ingroup NetComm
46  * @author Tim Niemueller
47  */
48 
49 /** Constructor.
50  * This constructor sets all parameters.
51  * @param name name of service
52  * @param type type of service
53  * @param domain domain of service
54  * @param host host of service
55  * @param port port of service
56  */
58  const char * type,
59  const char * domain,
60  const char * host,
61  unsigned short int port)
62 {
63  _name = strdup(name);
64  _type = strdup(type);
65  _domain = strdup(domain);
66  _host = strdup(host);
67  _port = port;
68 
69  _modified_name = NULL;
70 
71  memset(&_addr, 0, sizeof(_addr));
72 }
73 
74 /** Constructor.
75  * This constructor sets all parameters.
76  * @param name name of service
77  * @param type type of service
78  * @param domain domain of service
79  * @param host host of service
80  * @param port port of service
81  * @param addr address of the service
82  * @param addr_size size in bytes of addr parameter
83  * @param txt list of TXT records
84  */
86  const char * type,
87  const char * domain,
88  const char * host,
89  unsigned short int port,
90  const struct sockaddr * addr,
91  const socklen_t addr_size,
92  std::list<std::string> &txt)
93 {
94  _name = strdup(name);
95  _type = strdup(type);
96  _domain = strdup(domain);
97  _host = strdup(host);
98  _port = port;
99 
100  _modified_name = NULL;
101 
102  if (addr_size > sizeof(_addr)) {
103  throw Exception("Address size too large");
104  }
105  memcpy(&_addr, addr, addr_size);
106  list = txt;
107 }
108 
109 /** Constructor.
110  * This constructor sets all parameters. Host and domain are the
111  * default values, which means local host name in domain .local
112  * (if not set otherwise in Avahi system configuration).
113  * @param name name of service
114  * @param type type of service
115  * @param port port of service
116  */
117 NetworkService::NetworkService(const char *name, const char *type, unsigned short int port)
118 {
119  _name = strdup(name);
120  _type = strdup(type);
121  _domain = NULL;
122  _host = NULL;
123  _port = port;
124 
125  _modified_name = NULL;
126 
127  memset(&_addr, 0, sizeof(_addr));
128 }
129 
130 /** Constructor.
131  * This constructor sets all parameters. Host and domain are the
132  * default values, which means local host name in domain .local
133  * (if not set otherwise in Avahi system configuration).
134  * This specific constructor allows the usage of a "%h" token in
135  * the name, which is replaced with the short hostname.
136  * @param nnresolver network name resolver to get the host from for
137  * the replacement of a %h token.
138  * @param name name of service
139  * @param type type of service
140  * @param port port of service
141  */
143  const char * name,
144  const char * type,
145  unsigned short int port)
146 {
147  std::string s = name;
148  std::string::size_type hpos = s.find("%h");
149  if (nnresolver && (hpos != std::string::npos)) {
150  s.replace(hpos, 2, nnresolver->short_hostname());
151  }
152  _name = strdup(s.c_str());
153  _type = strdup(type);
154  _domain = NULL;
155  _host = NULL;
156  _port = port;
157 
158  _modified_name = NULL;
159 
160  memset(&_addr, 0, sizeof(_addr));
161 }
162 
163 /** Constructor.
164  * This constructor sets all parameters.
165  * @param name name of service
166  * @param type type of service
167  * @param domain domain of service
168  */
169 NetworkService::NetworkService(const char *name, const char *type, const char *domain)
170 {
171  _name = strdup(name);
172  _type = strdup(type);
173  _domain = strdup(domain);
174 
175  _modified_name = NULL;
176 
177  _host = NULL;
178  _port = 0;
179 
180  memset(&_addr, 0, sizeof(_addr));
181 }
182 
183 /** Destructor. */
185 {
186  if (_name != NULL)
187  free(_name);
188  if (_type != NULL)
189  free(_type);
190  if (_domain != NULL)
191  free(_domain);
192  if (_host != NULL)
193  free(_host);
194  if (_modified_name != NULL)
195  free(_modified_name);
196 }
197 
198 /** Copy constructor (pointer).
199  * Create a copy of given NetworkService.
200  * @param s network service to copy from
201  */
203 {
204  _name = strdup(s->_name);
205  _type = strdup(s->_type);
206  _port = s->_port;
207  if (s->_domain != NULL) {
208  _domain = strdup(s->_domain);
209  } else {
210  _domain = NULL;
211  }
212  if (s->_host != NULL) {
213  _host = strdup(s->_host);
214  } else {
215  _host = NULL;
216  }
217 
218  _modified_name = NULL;
219  if (s->_modified_name != NULL) {
220  _modified_name = strdup(s->_modified_name);
221  }
222 
223  memcpy(&_addr, &s->_addr, sizeof(_addr));
224 
225  list = s->list;
226 }
227 
228 /** Copy constructor (reference).
229  * Create a copy of given NetworkService.
230  * @param s network service to copy from
231  */
233 {
234  _name = strdup(s._name);
235  _type = strdup(s._type);
236  _port = s._port;
237  if (s._domain != NULL) {
238  _domain = strdup(s._domain);
239  } else {
240  _domain = NULL;
241  }
242  if (s._host != NULL) {
243  _host = strdup(s._host);
244  } else {
245  _host = NULL;
246  }
247 
248  _modified_name = NULL;
249  if (s._modified_name != NULL) {
250  _modified_name = strdup(s._modified_name);
251  }
252 
253  memcpy(&_addr, &s._addr, sizeof(_addr));
254 
255  list = s.list;
256 }
257 
258 /** Assignment operator.
259  * @param s network service to copy from
260  * @return reference to this instance
261  */
264 {
265  if (_name != NULL)
266  free(_name);
267  if (_type != NULL)
268  free(_type);
269  if (_domain != NULL)
270  free(_domain);
271  if (_host != NULL)
272  free(_host);
273  if (_modified_name != NULL)
274  free(_modified_name);
275 
276  _name = NULL;
277  _type = NULL;
278  _domain = NULL;
279  _host = NULL;
280  _modified_name = NULL;
281 
282  _name = strdup(s._name);
283  _type = strdup(s._type);
284  _port = s._port;
285  if (s._domain != NULL) {
286  _domain = strdup(s._domain);
287  } else {
288  _domain = NULL;
289  }
290  if (s._host != NULL) {
291  _host = strdup(s._host);
292  } else {
293  _host = NULL;
294  }
295 
296  _modified_name = NULL;
297  if (s._modified_name != NULL) {
298  _modified_name = strdup(s._modified_name);
299  }
300 
301  memcpy(&_addr, &s._addr, sizeof(_addr));
302 
303  list = s.list;
304 
305  return *this;
306 }
307 
308 /** Add a TXT record.
309  * @param format format for TXT record to add, must be a "key=value" string,
310  * takes the same arguments as sprintf.
311  */
312 void
313 NetworkService::add_txt(const char *format, ...)
314 {
315  va_list arg;
316  va_start(arg, format);
317  char *tmp;
318  if (vasprintf(&tmp, format, arg) == -1) {
319  throw OutOfMemoryException("Cannot add txt record, no memory");
320  }
321  list.push_back(tmp);
322  free(tmp);
323  va_end(arg);
324 }
325 
326 /** Set TXT records all at once.
327  * @param txtlist list of TXT records
328  */
329 void
330 NetworkService::set_txt(std::list<std::string> &txtlist)
331 {
332  list = txtlist;
333 }
334 
335 /** Set name of service.
336  * @param new_name new name
337  */
338 void
339 NetworkService::set_name(const char *new_name)
340 {
341  free(_name);
342  _name = strdup(new_name);
343 }
344 
345 /** Get name of service.
346  * @return name of service
347  */
348 const char *
350 {
351  return _name;
352 }
353 
354 /** Set modified name of service.
355  * The modified name is the original name with a suffix that has been added
356  * to resolve a name collision.
357  * @param new_name new name
358  */
359 void
360 NetworkService::set_modified_name(const char *new_name) const
361 {
362  if (_modified_name)
363  free(_modified_name);
364  _modified_name = strdup(new_name);
365 }
366 
367 /** Get modified name of service.
368  * The modified name is the original name with a suffix that has been added
369  * to resolve a name collision.
370  * @return modified name of service, this may be NULL if the name has not
371  * been modified
372  */
373 const char *
375 {
376  return _modified_name;
377 }
378 
379 /** Get type of service.
380  * @return type of service
381  */
382 const char *
384 {
385  return _type;
386 }
387 
388 /** Get domain of service.
389  * @return domain of service
390  */
391 const char *
393 {
394  return _domain;
395 }
396 
397 /** Get host of service.
398  * @return host of service
399  */
400 const char *
402 {
403  return _host;
404 }
405 
406 /** Get port of service.
407  * @return port of service
408  */
409 unsigned short int
411 {
412  return _port;
413 }
414 
415 /** Get IP address of entry as string.
416  * @return IP address as string
417  * @exception NullPointerException thrown if the address has not been set
418  */
419 std::string
421 {
422  if (_addr.ss_family == AF_INET) {
423  char ipaddr[INET_ADDRSTRLEN];
424  struct sockaddr_in *saddr = (struct sockaddr_in *)&_addr;
425  if (inet_ntop(AF_INET, &(saddr->sin_addr), ipaddr, sizeof(ipaddr)) != NULL) {
426  return ipaddr;
427  } else {
428  throw Exception("Failed to convert IPv4 address to string");
429  }
430  } else if (_addr.ss_family == AF_INET6) {
431  char ipaddr[INET6_ADDRSTRLEN];
432  struct sockaddr_in6 *saddr = (struct sockaddr_in6 *)&_addr;
433  if (inet_ntop(AF_INET6, &(saddr->sin6_addr), ipaddr, sizeof(ipaddr)) != NULL) {
434  return ipaddr;
435  } else {
436  throw Exception("Failed to convert IPv6 address to string");
437  }
438  } else {
439  throw Exception("Unknown address family");
440  }
441 }
442 
443 /** Get TXT record list of service.
444  * @return TXT record list of service
445  */
446 const std::list<std::string> &
448 {
449  return list;
450 }
451 
452 /** Equal operator for NetworkService reference.
453  * @param s reference of service to compare to.
454  * @return true, if the services are the same (same name and type), false otherwise
455  */
456 bool
458 {
459  return ((strcmp(_name, s._name) == 0) && (strcmp(_type, s._type) == 0));
460 }
461 
462 /** Equal operator for NetworkService pointer.
463  * @param s pointer to service to compare to.
464  * @return true, if the services are the same (same name and type), false otherwise
465  */
466 bool
468 {
469  return ((strcmp(_name, s->_name) == 0) && (strcmp(_type, s->_type) == 0));
470 }
471 
472 /** Less than operator.
473  * @param s reference of service to compare to
474  * @return true, if either the type is less than (according to strcmp) or if types
475  * are equal if the service name is less than the given service's name.
476  */
477 bool
479 {
480  int typediff = strcmp(_type, s._type);
481  if (typediff == 0) {
482  return (strcmp(_name, s._name) < 0);
483  } else {
484  return (typediff < 0);
485  }
486 }
487 
488 } // end namespace fawkes
Base class for exceptions in Fawkes.
Definition: exception.h:36
Network name and address resolver.
Definition: resolver.h:45
const char * short_hostname()
Get short hostname.
Definition: resolver.cpp:354
Representation of a service announced or found via service discovery (i.e.
Definition: service.h:38
std::string addr_string() const
Get IP address of entry as string.
Definition: service.cpp:420
~NetworkService()
Destructor.
Definition: service.cpp:184
bool operator==(const NetworkService &s) const
Equal operator for NetworkService reference.
Definition: service.cpp:457
void set_modified_name(const char *new_name) const
Set modified name of service.
Definition: service.cpp:360
const char * modified_name() const
Get modified name of service.
Definition: service.cpp:374
const char * type() const
Get type of service.
Definition: service.cpp:383
void set_txt(std::list< std::string > &txtlist)
Set TXT records all at once.
Definition: service.cpp:330
void add_txt(const char *format,...)
Add a TXT record.
Definition: service.cpp:313
unsigned short int port() const
Get port of service.
Definition: service.cpp:410
NetworkService & operator=(const NetworkService &s)
Assignment operator.
Definition: service.cpp:263
void set_name(const char *new_name)
Set name of service.
Definition: service.cpp:339
NetworkService(const char *name, const char *type, const char *domain, const char *host, unsigned short int port)
Constructor.
Definition: service.cpp:57
const char * name() const
Get name of service.
Definition: service.cpp:349
const char * host() const
Get host of service.
Definition: service.cpp:401
bool operator<(const NetworkService &s) const
Less than operator.
Definition: service.cpp:478
const char * domain() const
Get domain of service.
Definition: service.cpp:392
const std::list< std::string > & txt() const
Get TXT record list of service.
Definition: service.cpp:447
System ran out of memory and desired operation could not be fulfilled.
Definition: system.h:32
Fawkes library namespace.