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