Go to the documentation of this file.00001
00009
00010
00011
00012
00013 #include <set>
00014 #include <string>
00015
00016 #include <avahi-client/publish.h>
00017 #include <avahi-client/client.h>
00018 #include <avahi-client/lookup.h>
00019 #include <avahi-common/malloc.h>
00020 #include <avahi-common/error.h>
00021 #include <avahi-common/thread-watch.h>
00022
00023 #include <boost/thread/mutex.hpp>
00024 #include <boost/bimap/bimap.hpp>
00025 #include <boost/function.hpp>
00026 #include <boost/shared_ptr.hpp>
00027
00028 #include <zeroconf_msgs/PublishedService.h>
00029 #include <zeroconf_msgs/DiscoveredService.h>
00030
00031
00032
00033
00034
00035 namespace zeroconf_avahi
00036 {
00037
00038
00039
00040
00050 struct PublishedServiceCompare
00051 {
00052 bool operator()(const zeroconf_msgs::PublishedService &a, const zeroconf_msgs::PublishedService &b) const
00053 {
00054 if (a.name != b.name)
00055 {
00056 return a.name < b.name;
00057 }
00058 else if (a.type != b.type)
00059 {
00060 return a.type < b.type;
00061 }
00062 else
00063 {
00064 return a.port < b.port;
00065 }
00066 }
00067 };
00068
00078 class DiscoveredAvahiService
00079 {
00080 public:
00081 DiscoveredAvahiService() :
00082 resolver(NULL)
00083 {
00084 }
00085 DiscoveredAvahiService(zeroconf_msgs::DiscoveredService &discovered_service, AvahiServiceResolver *new_resolver,
00086 int protocol, int hardware_interface) :
00087 service(discovered_service), protocol(protocol), hardware_interface(hardware_interface), resolver(new_resolver)
00088 {
00089
00090 }
00091 ~DiscoveredAvahiService()
00092 {
00093 if (resolver)
00094 {
00095 avahi_service_resolver_free(resolver);
00096 }
00097 }
00098 zeroconf_msgs::DiscoveredService service;
00099 int protocol;
00100 int hardware_interface;
00101 AvahiServiceResolver *resolver;
00102 };
00103
00110 struct DiscoveredAvahiServiceCompare
00111 {
00112 bool operator()(const boost::shared_ptr<DiscoveredAvahiService> avahi_service_a,
00113 const boost::shared_ptr<DiscoveredAvahiService> avahi_service_b) const
00114 {
00115 const zeroconf_msgs::DiscoveredService &a = avahi_service_a->service;
00116 const zeroconf_msgs::DiscoveredService &b = avahi_service_b->service;
00117 if (a.name != b.name)
00118 {
00119 return a.name < b.name;
00120 }
00121 else if (a.type != b.type)
00122 {
00123 return a.type < b.type;
00124 }
00125 else if (a.domain != b.domain)
00126 {
00127 return a.domain < b.domain;
00128 }
00129 else if (avahi_service_a->hardware_interface != avahi_service_b->hardware_interface)
00130 {
00131 return avahi_service_a->hardware_interface < avahi_service_b->hardware_interface;
00132 }
00133 else
00134 {
00135 return avahi_service_a->protocol < avahi_service_b->protocol;
00136 }
00137 }
00138 };
00139
00140
00141
00142
00162 class Zeroconf
00163 {
00164 private:
00165 typedef zeroconf_msgs::PublishedService PublishedService;
00166 typedef boost::bimaps::bimap<AvahiEntryGroup*, boost::bimaps::set_of<PublishedService, PublishedServiceCompare> > service_bimap;
00167 typedef boost::bimaps::bimap<AvahiServiceBrowser*, boost::bimaps::set_of<std::string> > discovery_bimap;
00168 typedef std::set<boost::shared_ptr<DiscoveredAvahiService>, DiscoveredAvahiServiceCompare> discovered_service_set;
00169 typedef std::pair<AvahiEntryGroup*, PublishedService> service_map_pair;
00170 typedef boost::function<void(zeroconf_msgs::DiscoveredService)> connection_signal_cb;
00171
00172 public:
00173 Zeroconf();
00174 ~Zeroconf();
00175 bool add_service(PublishedService &service);
00176 bool remove_service(const PublishedService &service);
00177
00178
00179
00180
00181 bool add_listener(std::string &service_type);
00182 bool remove_listener(const std::string &service_type);
00183 bool is_alive() const { return !invalid_object; }
00184 void list_discovered_services(const std::string &service_type, std::vector<zeroconf_msgs::DiscoveredService> &list);
00185 void list_published_services(const std::string &service_type, std::vector<zeroconf_msgs::PublishedService> &list);
00186
00187 void connect_signal_callbacks(connection_signal_cb new_connections, connection_signal_cb lost_connections)
00188 {
00189 new_connection_signal = new_connections;
00190 lost_connection_signal = lost_connections;
00191 }
00192
00193 void spin();
00194
00195 private:
00196 bool invalid_object;
00197 AvahiThreadedPoll *threaded_poll;
00198 AvahiClient *client;
00199 service_bimap committed_services;
00200 service_bimap established_services;
00201 discovery_bimap discovery_service_types;
00202 discovered_service_set discovered_services;
00203 boost::mutex service_mutex;
00204 const int interface;
00205 const int permitted_protocols;
00206 connection_signal_cb new_connection_signal, lost_connection_signal;
00207
00208
00209
00210
00211 int ros_to_avahi_protocol(const int &protocol);
00212 std::string ros_to_txt_protocol(const int &protocol);
00213 int avahi_to_ros_protocol(const int &protocol);
00214 std::string avahi_to_txt_protocol(const int &protocol);
00215 discovered_service_set::iterator find_discovered_service(zeroconf_msgs::DiscoveredService &service);
00216
00217
00218
00219
00220 bool add_service_non_threaded(PublishedService &service);
00221 void fail()
00222 {
00223 avahi_threaded_poll_quit(threaded_poll);
00224 invalid_object = true;
00225 }
00226
00227
00228
00229
00230 static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata);
00231 static void client_callback(AvahiClient *c, AvahiClientState state, void * userdata);
00232 static void discovery_callback(AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol,
00233 AvahiBrowserEvent event, const char *name, const char *type, const char *domain,
00234 AvahiLookupResultFlags flags, void* userdata);
00235 static void resolve_callback(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiProtocol protocol,
00236 AvahiResolverEvent event, const char *name, const char *type, const char *domain,
00237 const char *host_name, const AvahiAddress *address, uint16_t port, AvahiStringList *txt,
00238 AvahiLookupResultFlags flags, void* userdata);
00239 static void modify_callback(AVAHI_GCC_UNUSED AvahiTimeout *e, void *userdata);
00240 };
00241
00242 }