Ros interface to linux's avahi daemon. More...
#include <zeroconf.hpp>
Public Member Functions | |
bool | add_listener (std::string &service_type) |
bool | add_service (PublishedService &service) |
void | connect_signal_callbacks (connection_signal_cb new_connections, connection_signal_cb lost_connections) |
bool | is_alive () const |
void | list_discovered_services (const std::string &service_type, std::vector< zeroconf_msgs::DiscoveredService > &list) |
void | list_published_services (const std::string &service_type, std::vector< zeroconf_msgs::PublishedService > &list) |
bool | remove_listener (const std::string &service_type) |
bool | remove_service (const PublishedService &service) |
void | spin () |
Zeroconf () | |
~Zeroconf () | |
Private Types | |
typedef boost::function< void(zeroconf_msgs::DiscoveredService)> | connection_signal_cb |
typedef std::set < boost::shared_ptr < DiscoveredAvahiService > , DiscoveredAvahiServiceCompare > | discovered_service_set |
typedef boost::bimaps::bimap < AvahiServiceBrowser *, boost::bimaps::set_of < std::string > > | discovery_bimap |
typedef zeroconf_msgs::PublishedService | PublishedService |
typedef boost::bimaps::bimap < AvahiEntryGroup *, boost::bimaps::set_of < PublishedService, PublishedServiceCompare > > | service_bimap |
typedef std::pair < AvahiEntryGroup *, PublishedService > | service_map_pair |
Private Member Functions | |
bool | add_service_non_threaded (PublishedService &service) |
int | avahi_to_ros_protocol (const int &protocol) |
std::string | avahi_to_txt_protocol (const int &protocol) |
void | fail () |
discovered_service_set::iterator | find_discovered_service (zeroconf_msgs::DiscoveredService &service) |
int | ros_to_avahi_protocol (const int &protocol) |
std::string | ros_to_txt_protocol (const int &protocol) |
Static Private Member Functions | |
static void | client_callback (AvahiClient *c, AvahiClientState state, void *userdata) |
static void | discovery_callback (AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void *userdata) |
static void | entry_group_callback (AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) |
static void | modify_callback (AVAHI_GCC_UNUSED AvahiTimeout *e, void *userdata) |
static void | resolve_callback (AvahiServiceResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *name, const char *type, const char *domain, const char *host_name, const AvahiAddress *address, uint16_t port, AvahiStringList *txt, AvahiLookupResultFlags flags, void *userdata) |
Private Attributes | |
AvahiClient * | client |
service_bimap | committed_services |
discovered_service_set | discovered_services |
discovery_bimap | discovery_service_types |
service_bimap | established_services |
const int | interface |
bool | invalid_object |
connection_signal_cb | lost_connection_signal |
connection_signal_cb | new_connection_signal |
const int | permitted_protocols |
boost::mutex | service_mutex |
AvahiThreadedPoll * | threaded_poll |
Ros interface to linux's avahi daemon.
Avahi code is difficult to use (alot of black magic), so this class provides a convenient c++ interface to the avahi daemon that supplies the required api useful for a ros node (separate to this class).
Constraints:
It can easily be made purely c++ by substituting ros comms with pure c++ structs and doing conversions in the ros node (possibly a future job if necessary).
Currently defaulting to ipv4 addresses only. Just hardcode the library to use AVAHI_PROTO_UNSPEC if we ever want to move to using ipv6 as well (probably need some extra logic here and there as well).
Definition at line 162 of file zeroconf.hpp.
typedef boost::function<void(zeroconf_msgs::DiscoveredService)> zeroconf_avahi::Zeroconf::connection_signal_cb [private] |
Definition at line 170 of file zeroconf.hpp.
typedef std::set<boost::shared_ptr<DiscoveredAvahiService>, DiscoveredAvahiServiceCompare> zeroconf_avahi::Zeroconf::discovered_service_set [private] |
Definition at line 168 of file zeroconf.hpp.
typedef boost::bimaps::bimap<AvahiServiceBrowser*, boost::bimaps::set_of<std::string> > zeroconf_avahi::Zeroconf::discovery_bimap [private] |
Definition at line 167 of file zeroconf.hpp.
typedef zeroconf_msgs::PublishedService zeroconf_avahi::Zeroconf::PublishedService [private] |
Definition at line 165 of file zeroconf.hpp.
typedef boost::bimaps::bimap<AvahiEntryGroup*, boost::bimaps::set_of<PublishedService, PublishedServiceCompare> > zeroconf_avahi::Zeroconf::service_bimap [private] |
Definition at line 166 of file zeroconf.hpp.
typedef std::pair<AvahiEntryGroup*, PublishedService> zeroconf_avahi::Zeroconf::service_map_pair [private] |
Definition at line 169 of file zeroconf.hpp.
Definition at line 37 of file lib/zeroconf.cpp.
Definition at line 67 of file lib/zeroconf.cpp.
bool zeroconf_avahi::Zeroconf::add_listener | ( | std::string & | service_type | ) |
Definition at line 116 of file lib/zeroconf.cpp.
bool zeroconf_avahi::Zeroconf::add_service | ( | PublishedService & | service | ) |
Add a service.
This goes through the threaded poll, so services can be added in runtime (i.e. after initial configuration).
We also keep a copy of the service to be added, so we can track through to the entry_group_callback, exactly which service is getting added.
Note that the service is not const - see add_service_non_threaded for more details.
Definition at line 213 of file lib/zeroconf.cpp.
bool zeroconf_avahi::Zeroconf::add_service_non_threaded | ( | PublishedService & | service | ) | [private] |
Non threaded add service - only for internal use because we need to be thread-safe.
Note that the service is not const - we will rename the service if it suffers from a local name collision. This is just a convenience and doesn't help the case when it is renamed in non-local collisions.
Definition at line 230 of file lib/zeroconf.cpp.
int zeroconf_avahi::Zeroconf::avahi_to_ros_protocol | ( | const int & | protocol | ) | [private] |
Definition at line 458 of file lib/zeroconf.cpp.
std::string zeroconf_avahi::Zeroconf::avahi_to_txt_protocol | ( | const int & | protocol | ) | [private] |
Definition at line 479 of file lib/zeroconf.cpp.
void zeroconf_avahi::Zeroconf::client_callback | ( | AvahiClient * | c, |
AvahiClientState | state, | ||
void * | userdata | ||
) | [static, private] |
Used to update client connection with the avahi daemon. This gets called in Zeroconf's construction where it checks to see that the avahi-daemon is actually up and running.
c | : client that is connecting. |
state | : updated state for the client-daemon connection. |
userdata | : this will always be the Zeroconf class. |
Definition at line 983 of file lib/zeroconf.cpp.
void zeroconf_avahi::Zeroconf::connect_signal_callbacks | ( | connection_signal_cb | new_connections, |
connection_signal_cb | lost_connections | ||
) | [inline] |
Definition at line 187 of file zeroconf.hpp.
void zeroconf_avahi::Zeroconf::discovery_callback | ( | AvahiServiceBrowser * | browser, |
AvahiIfIndex | interface, | ||
AvahiProtocol | protocol, | ||
AvahiBrowserEvent | event, | ||
const char * | name, | ||
const char * | type, | ||
const char * | domain, | ||
AvahiLookupResultFlags | flags, | ||
void * | userdata | ||
) | [static, private] |
Called whenever a service that is being listened to is added or removed. If you've got no listeners, this doesn't get called.
browser | |
interface | |
protocol | |
event | |
name | |
type | |
domain | |
flags | |
userdata |
Definition at line 543 of file lib/zeroconf.cpp.
void zeroconf_avahi::Zeroconf::entry_group_callback | ( | AvahiEntryGroup * | g, |
AvahiEntryGroupState | state, | ||
void * | userdata | ||
) | [static, private] |
Called whenever the the state of the entry group changes (or in english, whenever something noteworthy has happened to advertisements).
Not sure exactly, but after some testing, it seems that this also locks the threaded poll mutex for certain state changes, most notably, 'registering' and 'established'.
Making a big assumption here, but assuming that the callbacks will get processed for registering services in the order that they were committed. If this is true, we just look up the first service in the committed_services variable to see which service we're handling.
Definition at line 868 of file lib/zeroconf.cpp.
void zeroconf_avahi::Zeroconf::fail | ( | ) | [inline, private] |
Definition at line 221 of file zeroconf.hpp.
Zeroconf::discovered_service_set::iterator zeroconf_avahi::Zeroconf::find_discovered_service | ( | zeroconf_msgs::DiscoveredService & | service | ) | [private] |
Internal routine to quickly find a discovered service.
If calling from another thread, make sure its protected by service_mutex.
service | : minimally defined service by name, type, domain, interface, protocol |
Definition at line 508 of file lib/zeroconf.cpp.
bool zeroconf_avahi::Zeroconf::is_alive | ( | ) | const [inline] |
Definition at line 183 of file zeroconf.hpp.
void zeroconf_avahi::Zeroconf::list_discovered_services | ( | const std::string & | service_type, |
std::vector< zeroconf_msgs::DiscoveredService > & | list | ||
) |
Retrieves all the currently discovered services, or just those of those of the specified type that have been discovered. It goes the extra yard as well, just to make sure those services are resolvable (i.e. haven't dropped out or gone out of wireless range) which is important for robotics.
service_type | : service type specification |
list | : list of services that have been discovered (return value) |
Definition at line 355 of file lib/zeroconf.cpp.
void zeroconf_avahi::Zeroconf::list_published_services | ( | const std::string & | service_type, |
std::vector< zeroconf_msgs::PublishedService > & | list | ||
) |
Definition at line 386 of file lib/zeroconf.cpp.
static void zeroconf_avahi::Zeroconf::modify_callback | ( | AVAHI_GCC_UNUSED AvahiTimeout * | e, |
void * | userdata | ||
) | [static, private] |
bool zeroconf_avahi::Zeroconf::remove_listener | ( | const std::string & | service_type | ) |
Definition at line 155 of file lib/zeroconf.cpp.
bool zeroconf_avahi::Zeroconf::remove_service | ( | const PublishedService & | service | ) |
Definition at line 317 of file lib/zeroconf.cpp.
void zeroconf_avahi::Zeroconf::resolve_callback | ( | AvahiServiceResolver * | resolver, |
AvahiIfIndex | interface, | ||
AvahiProtocol | protocol, | ||
AvahiResolverEvent | event, | ||
const char * | name, | ||
const char * | type, | ||
const char * | domain, | ||
const char * | host_name, | ||
const AvahiAddress * | address, | ||
uint16_t | port, | ||
AvahiStringList * | txt, | ||
AvahiLookupResultFlags | flags, | ||
void * | userdata | ||
) | [static, private] |
This gets called by a resolver (created by avahi_resolver_new) whenever a discovered service goes up and down. Note that this only works if you keep the resolver open (do not free it!).
There are a couple of avahi bugs in here I think. Workarounds:
1) Sometimes when a serivce times out and the same service (name, type, domain, interface and protocol) is started on another address, it will trigger this callback before actually setting the address value. If you let it sleep for a bit, it will catch the correct address. Doing that here, but it really shouldn't call the callback until this is set internally by avahi.
2) It will sometimes RESOLVER_FOUND with an ipv6 address for an ipv4 service. This seems to happen immediately before a service times out. We check for this here and ignore it if this is the case.
resolver | |
interface | |
protocol | |
event | |
name | |
type | |
domain | |
host_name | |
address | |
port | |
txt | |
flags | |
userdata |
Definition at line 683 of file lib/zeroconf.cpp.
int zeroconf_avahi::Zeroconf::ros_to_avahi_protocol | ( | const int & | protocol | ) | [private] |
Definition at line 416 of file lib/zeroconf.cpp.
std::string zeroconf_avahi::Zeroconf::ros_to_txt_protocol | ( | const int & | protocol | ) | [private] |
Definition at line 437 of file lib/zeroconf.cpp.
void zeroconf_avahi::Zeroconf::spin | ( | ) |
Definition at line 106 of file lib/zeroconf.cpp.
AvahiClient* zeroconf_avahi::Zeroconf::client [private] |
Definition at line 198 of file zeroconf.hpp.
Definition at line 199 of file zeroconf.hpp.
Definition at line 202 of file zeroconf.hpp.
Definition at line 201 of file zeroconf.hpp.
Definition at line 200 of file zeroconf.hpp.
const int zeroconf_avahi::Zeroconf::interface [private] |
Definition at line 204 of file zeroconf.hpp.
bool zeroconf_avahi::Zeroconf::invalid_object [private] |
Definition at line 196 of file zeroconf.hpp.
Definition at line 206 of file zeroconf.hpp.
Definition at line 206 of file zeroconf.hpp.
const int zeroconf_avahi::Zeroconf::permitted_protocols [private] |
Definition at line 205 of file zeroconf.hpp.
boost::mutex zeroconf_avahi::Zeroconf::service_mutex [private] |
Definition at line 203 of file zeroconf.hpp.
AvahiThreadedPoll* zeroconf_avahi::Zeroconf::threaded_poll [private] |
Definition at line 197 of file zeroconf.hpp.