Fawkes API  Fawkes Development Version
service.cpp
00001 
00002 /***************************************************************************
00003  *  service.cpp - Network service representation
00004  *
00005  *  Generated: Tue Nov 07 18:02:23 2006
00006  *  Copyright  2006-2007  Tim Niemueller [www.niemueller.de]
00007  *
00008  ****************************************************************************/
00009 
00010 /*  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2 of the License, or
00013  *  (at your option) any later version. A runtime exception applies to
00014  *  this software (see LICENSE.GPL_WRE file mentioned below for details).
00015  *
00016  *  This program is distributed in the hope that it will be useful,
00017  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00018  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00019  *  GNU Library General Public License for more details.
00020  *
00021  *  Read the full text in the LICENSE.GPL_WRE file in the doc directory.
00022  */
00023 
00024 #include <netcomm/service_discovery/service.h>
00025 #include <netcomm/utils/resolver.h>
00026 #include <core/exceptions/system.h>
00027 
00028 #include <sys/types.h>
00029 #include <arpa/inet.h>
00030 #include <netinet/in.h>
00031 #include <inttypes.h>
00032 #include <cstddef>
00033 #include <cstring>
00034 #include <cstdlib>
00035 #include <cstdarg>
00036 #include <cstdio>
00037 
00038 namespace fawkes {
00039 #if 0 /* just to make Emacs auto-indent happy */
00040 }
00041 #endif
00042 
00043 /** @class NetworkService <netcomm/service_discovery/service.h>
00044  * Representation of a service announced or found via service
00045  * discovery (i.e. mDNS/DNS-SD via Avahi).
00046  * This class is used in the C++ wrapper to talk about services.
00047  *
00048  * @ingroup NetComm
00049  * @author Tim Niemueller
00050  */
00051 
00052 /** Constructor.
00053  * This constructor sets all parameters.
00054  * @param name name of service
00055  * @param type type of service
00056  * @param domain domain of service
00057  * @param host host of service
00058  * @param port port of service
00059  */
00060 NetworkService::NetworkService(const char         *name,
00061                                const char         *type,
00062                                const char         *domain,
00063                                const char         *host,
00064                                unsigned short int  port)
00065 {
00066   _name   = strdup(name);
00067   _type   = strdup(type);
00068   _domain = strdup(domain);
00069   _host   = strdup(host);
00070   _port   = port;
00071 
00072   _modified_name = NULL;
00073 
00074   _addr = NULL;
00075   _addr_size = 0;
00076 }
00077 
00078 
00079 /** Constructor.
00080  * This constructor sets all parameters.
00081  * @param name name of service
00082  * @param type type of service
00083  * @param domain domain of service
00084  * @param host host of service
00085  * @param port port of service
00086  * @param addr address of the service
00087  * @param addr_size size in bytes of addr parameter
00088  * @param txt list of TXT records
00089  */
00090 NetworkService::NetworkService(const char         *name,
00091                                const char         *type,
00092                                const char         *domain,
00093                                const char         *host,
00094                                unsigned short int  port,
00095                                const struct sockaddr *addr,
00096                                const socklen_t     addr_size,
00097                                std::list<std::string> &txt)
00098 
00099 {
00100   _name   = strdup(name);
00101   _type   = strdup(type);
00102   _domain = strdup(domain);
00103   _host   = strdup(host);
00104   _port   = port;
00105 
00106   _modified_name = NULL;
00107 
00108   _addr = (struct sockaddr *)malloc(addr_size);
00109   memcpy(_addr, addr, addr_size);
00110   _addr_size = addr_size;
00111   list = txt;
00112 }
00113 
00114 
00115 /** Constructor.
00116  * This constructor sets all parameters. Host and domain are the
00117  * default values, which means local host name in domain .local
00118  * (if not set otherwise in Avahi system configuration).
00119  * @param name name of service
00120  * @param type type of service
00121  * @param port port of service
00122  */
00123 NetworkService::NetworkService(const char         *name,
00124                                const char         *type,
00125                                unsigned short int  port)
00126 {
00127   _name   = strdup(name);
00128   _type   = strdup(type);
00129   _domain = NULL;
00130   _host   = NULL;
00131   _port   = port;
00132 
00133   _modified_name = NULL;
00134 
00135   _addr = NULL;
00136   _addr_size = 0;
00137 }
00138 
00139 
00140 /** Constructor.
00141  * This constructor sets all parameters. Host and domain are the
00142  * default values, which means local host name in domain .local
00143  * (if not set otherwise in Avahi system configuration).
00144  * This specific constructor allows the usage of a "%h" token in
00145  * the name, which is replaced with the short hostname.
00146  * @param nnresolver network name resolver to get the host from for
00147  * the replacement of a %h token.
00148  * @param name name of service
00149  * @param type type of service
00150  * @param port port of service
00151  */
00152 NetworkService::NetworkService(NetworkNameResolver *nnresolver,
00153                                const char         *name,
00154                                const char         *type,
00155                                unsigned short int  port)
00156 {
00157   std::string s = name;
00158   std::string::size_type hpos = s.find("%h");
00159   if (nnresolver && (hpos != std::string::npos)) {
00160     s.replace(hpos, 2, nnresolver->short_hostname());
00161   }
00162   _name   = strdup(s.c_str());
00163   _type   = strdup(type);
00164   _domain = NULL;
00165   _host   = NULL;
00166   _port   = port;
00167 
00168   _modified_name = NULL;
00169 
00170   _addr = NULL;
00171   _addr_size = 0;
00172 }
00173 
00174 /** Constructor.
00175  * This constructor sets all parameters.
00176  * @param name name of service
00177  * @param type type of service
00178  * @param domain domain of service
00179  */
00180 NetworkService::NetworkService(const char         *name,
00181                                const char         *type,
00182                                const char         *domain)
00183 {
00184   _name   = strdup(name);
00185   _type   = strdup(type);
00186   _domain = strdup(domain);
00187 
00188   _modified_name = NULL;
00189 
00190   _host   = NULL;
00191   _port   = 0;
00192   _addr = NULL;
00193   _addr_size = 0;
00194 }
00195 
00196 
00197 /** Destructor. */
00198 NetworkService::~NetworkService()
00199 {
00200   if ( _name   != NULL)  free( _name );
00201   if ( _type   != NULL)  free( _type );
00202   if ( _domain != NULL)  free( _domain );
00203   if ( _host   != NULL)  free( _host );
00204   if ( _addr   != NULL)  free( _addr );
00205   if ( _modified_name   != NULL)  free( _modified_name );
00206 }
00207 
00208 
00209 /** Copy constructor (pointer).
00210  * Create a copy of given NetworkService.
00211  * @param s network service to copy from
00212  */
00213 NetworkService::NetworkService(const NetworkService *s)
00214 {
00215   _name = strdup(s->_name);
00216   _type = strdup(s->_type);
00217   _port = s->_port;
00218   if ( s->_domain != NULL ) {
00219     _domain = strdup(s->_domain);
00220   } else {
00221     _domain = NULL;
00222   }
00223   if ( s->_host != NULL ) {
00224     _host = strdup(s->_host);
00225   } else {
00226     _host = NULL;
00227   }
00228 
00229   _modified_name = NULL;
00230   if (s->_modified_name != NULL) {
00231     _modified_name = strdup(s->_modified_name);
00232   }
00233 
00234   _addr = NULL;
00235   _addr_size = 0;
00236 
00237   list = s->list;
00238 }
00239 
00240 
00241 /** Copy constructor (reference).
00242  * Create a copy of given NetworkService.
00243  * @param s network service to copy from
00244  */
00245 NetworkService::NetworkService(const NetworkService &s)
00246 {
00247   _name = strdup(s._name);
00248   _type = strdup(s._type);
00249   _port = s._port;
00250   if ( s._domain != NULL ) {
00251     _domain = strdup(s._domain);
00252   } else {
00253     _domain = NULL;
00254   }
00255   if ( s._host != NULL ) {
00256     _host = strdup(s._host);
00257   } else {
00258     _host = NULL;
00259   }
00260 
00261   _modified_name = NULL;
00262   if (s._modified_name != NULL) {
00263     _modified_name = strdup(s._modified_name);
00264   }
00265 
00266   _addr = NULL;
00267   _addr_size = 0;
00268 
00269   list = s.list;
00270 }
00271 
00272 
00273 /** Add a TXT record.
00274  * @param format format for TXT record to add, must be a "key=value" string,
00275  * takes the same arguments as sprintf.
00276  */
00277 void
00278 NetworkService::add_txt(const char *format, ...)
00279 {
00280   va_list arg;
00281   va_start(arg, format);
00282   char *tmp;
00283   if (vasprintf(&tmp, format, arg) == -1) {
00284     throw OutOfMemoryException("Cannot add txt record, no memory");
00285   }
00286   list.push_back(tmp);
00287   free(tmp);
00288   va_end(arg);
00289 }
00290 
00291 
00292 /** Set TXT records all at once.
00293  * @param txtlist list of TXT records
00294  */
00295 void
00296 NetworkService::set_txt(std::list<std::string> &txtlist)
00297 {
00298   list = txtlist;
00299 }
00300 
00301 
00302 /** Set name of service.
00303  * @param new_name new name
00304  */
00305 void
00306 NetworkService::set_name(const char *new_name)
00307 {
00308   free( _name );
00309   _name = strdup(new_name);
00310 }
00311 
00312 
00313 /** Get name of service.
00314  * @return name of service
00315  */
00316 const char *
00317 NetworkService::name() const
00318 {
00319   return _name;
00320 }
00321 
00322 
00323 /** Set modified name of service.
00324  * The modified name is the original name with a suffix that has been added
00325  * to resolve a name collision.
00326  * @param new_name new name
00327  */
00328 void
00329 NetworkService::set_modified_name(const char *new_name) const
00330 {
00331   if (_modified_name)  free(_modified_name);
00332   _modified_name = strdup(new_name);
00333 }
00334 
00335 
00336 /** Get modified name of service.
00337  * The modified name is the original name with a suffix that has been added
00338  * to resolve a name collision.
00339  * @return modified name of service, this may be NULL if the name has not
00340  * been modified
00341  */
00342 const char *
00343 NetworkService::modified_name() const
00344 {
00345   return _modified_name;
00346 }
00347 
00348 
00349 /** Get type of service.
00350  * @return type of service
00351  */
00352 const char *
00353 NetworkService::type() const
00354 {
00355   return _type;
00356 }
00357 
00358 
00359 /** Get domain of service.
00360  * @return domain of service
00361  */
00362 const char *
00363 NetworkService::domain() const
00364 {
00365   return _domain;
00366 }
00367 
00368 
00369 /** Get host of service.
00370  * @return host of service
00371  */
00372 const char *
00373 NetworkService::host() const
00374 {
00375   return _host;
00376 }
00377 
00378 
00379 /** Get port of service.
00380  * @return port of service
00381  */
00382 unsigned short int
00383 NetworkService::port() const
00384 {
00385   return _port;
00386 }
00387 
00388 
00389 /** Get IP address of entry as string.
00390  * @return IP address as string
00391  * @exception NullPointerException thrown if the address has not been set
00392  */
00393 std::string
00394 NetworkService::addr_string() const
00395 {
00396   char ipaddr[INET_ADDRSTRLEN];
00397   struct sockaddr_in *saddr = (struct sockaddr_in *)_addr;
00398   return std::string(inet_ntop(AF_INET, &(saddr->sin_addr), ipaddr, sizeof(ipaddr)));
00399 }
00400 
00401 
00402 /** Get TXT record list of service.
00403  * @return TXT record list of service
00404  */
00405 const std::list<std::string> &
00406 NetworkService::txt() const
00407 {
00408   return list;
00409 }
00410 
00411 
00412 /** Equal operator for NetworkService reference.
00413  * @param s reference of service to compare to.
00414  * @return true, if the services are the same (same name and type), false otherwise
00415  */
00416 bool
00417 NetworkService::operator==(const NetworkService &s) const
00418 {
00419   return ( (strcmp(_name, s._name) == 0) &&
00420            (strcmp(_type, s._type) == 0) );
00421 }
00422 
00423 
00424 /** Equal operator for NetworkService pointer.
00425  * @param s pointer to service to compare to.
00426  * @return true, if the services are the same (same name and type), false otherwise
00427  */
00428 bool
00429 NetworkService::operator==(const NetworkService *s) const
00430 {
00431   return ( (strcmp(_name, s->_name) == 0) &&
00432            (strcmp(_type, s->_type) == 0) );
00433 }
00434 
00435 
00436 /** Less than operator.
00437  * @param s reference of service to compare to
00438  * @return true, if either the type is less than (according to strcmp) or if types
00439  * are equal if the service name is less than the given service's name.
00440  */
00441 bool
00442 NetworkService::operator<(const NetworkService &s) const
00443 {
00444   int typediff = strcmp(_type, s._type);
00445   if ( typediff == 0 ) {
00446     return (strcmp(_name, s._name) < 0);
00447   } else {
00448     return (typediff < 0);
00449   }
00450 }
00451 
00452 } // end namespace fawkes