source: source/ariba/utility/bootstrap/modules/multicastdns/MulticastDns.cpp@ 4828

Last change on this file since 4828 was 4758, checked in by Christoph Mayer, 15 years ago

avahi paar sachen gefixt, initiale tests mit poolrechnern klappen

File size: 11.1 KB
RevLine 
[4733]1// [License]
2// The Ariba-Underlay Copyright
3//
4// Copyright (c) 2008-2009, Institute of Telematics, UniversitÀt Karlsruhe (TH)
5//
6// Institute of Telematics
7// UniversitÀt Karlsruhe (TH)
8// Zirkel 2, 76128 Karlsruhe
9// Germany
10//
11// Redistribution and use in source and binary forms, with or without
12// modification, are permitted provided that the following conditions are
13// met:
14//
15// 1. Redistributions of source code must retain the above copyright
16// notice, this list of conditions and the following disclaimer.
17// 2. Redistributions in binary form must reproduce the above copyright
18// notice, this list of conditions and the following disclaimer in the
19// documentation and/or other materials provided with the distribution.
20//
21// THIS SOFTWARE IS PROVIDED BY THE INSTITUTE OF TELEMATICS ``AS IS'' AND
22// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ARIBA PROJECT OR
25// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
26// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
27// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
28// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
29// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
30// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
31// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32//
33// The views and conclusions contained in the software and documentation
34// are those of the authors and should not be interpreted as representing
35// official policies, either expressed or implied, of the Institute of
36// Telematics.
37// [License]
38
39#include "MulticastDns.h"
40
41namespace ariba {
42namespace utility {
43
[4758]44const string MulticastDns::serviceType = "_spovnet._tcp";
[4733]45use_logging_cpp(MulticastDns);
46
[4758]47MulticastDns::MulticastDns(BootstrapInformationCallback* _callback) : BootstrapModule(_callback) {
[4733]48 #ifdef HAVE_LIBAVAHI_CLIENT
49 avahiclient = NULL;
50 avahipoll = NULL;
51 avahibrowser = NULL;
52 #endif // HAVE_LIBAVAHI_CLIENT
53}
54
55MulticastDns::~MulticastDns(){
56}
57
58string MulticastDns::getName(){
59 return "MulticastDns";
60}
61
62string MulticastDns::getInformation(){
63 return "bootstrap module based on multicast-dns using the avahi library";
64}
65
66bool MulticastDns::isFunctional(){
67 #ifdef HAVE_LIBAVAHI_CLIENT
68 return true;
69 #else
70 return false;
71 #endif
72}
73
74void MulticastDns::start(){
75 #ifdef HAVE_LIBAVAHI_CLIENT
76
77 int error = 0;
78
79 // create a new avahi polling thread
80 avahipoll = avahi_threaded_poll_new();
[4758]81 if( avahipoll == NULL){
82 logging_error("creating avahi poll failed");
83 return;
84 }
[4733]85
86 // create a new avahi client
87 avahiclient = avahi_client_new( avahi_threaded_poll_get(avahipoll),
88 (AvahiClientFlags)0, MulticastDns::client_callback, this, &error );
[4758]89 if( avahiclient == NULL){
90 logging_error("creating avahi client failed");
91 return;
92 }
[4733]93
94 // block the event loop
95 avahi_threaded_poll_lock( avahipoll );
96
[4758]97 // create the service browser for the specified type
[4733]98 avahibrowser = avahi_service_browser_new(
99 avahiclient, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
100 serviceType.c_str(), NULL,
101 (AvahiLookupFlags)0, MulticastDns::browse_callback, this);
102
[4758]103 if( avahibrowser == NULL){
104 logging_error("creating avahi browser failed");
105 return;
106 }
107
[4733]108 //unblock the event loop and let it run
109 avahi_threaded_poll_unlock( avahipoll );
110 avahi_threaded_poll_start( avahipoll );
111
112 #endif // HAVE_LIBAVAHI_CLIENT
113}
114
115void MulticastDns::stop(){
116 #ifdef HAVE_LIBAVAHI_CLIENT
117
[4758]118 //
119 // stop poll and free browser
120 //
121
[4733]122 avahi_threaded_poll_stop( avahipoll );
123 avahi_service_browser_free( avahibrowser );
[4758]124 avahibrowser = NULL;
125
126 //
127 // free all registered groups
128 //
129
130 AvahiGroupMap::iterator i = avahigroups.begin();
131 AvahiGroupMap::iterator iend = avahigroups.end();
132
133 for( ; i != iend; i++)
134 avahi_entry_group_free( i->second );
135
136 //
137 // free client and poll
138 //
139
[4733]140 avahi_client_free( avahiclient );
[4758]141 avahiclient = NULL;
142
[4733]143 avahi_threaded_poll_free( avahipoll );
[4758]144 avahipoll = NULL;
[4733]145
146 #endif // HAVE_LIBAVAHI_CLIENT
147}
148
149void MulticastDns::publishService(string name, string info){
150 #ifdef HAVE_LIBAVAHI_CLIENT
151
[4758]152 if(name.length() > 63){
153 logging_error("service name length must not exceed 63 characters. "
154 << name << " is " << name.length() << " characters");
155 return;
156 }
157
158
[4733]159 avahi_threaded_poll_lock(avahipoll);
160 assert( avahiclient != NULL );
161
162 int ret = 0;
163
[4758]164 //
165 // if we have no group for this service, create one
166 //
[4733]167
[4758]168 AvahiGroupMap::iterator igroup = avahigroups.find(name);
169 AvahiEntryGroup* currentgroup = (igroup != avahigroups.end() ? igroup->second : NULL);
170
171 if( currentgroup == NULL ){
172
173 logging_debug("creating group for service " << name);
174 currentgroup = avahi_entry_group_new(avahiclient, MulticastDns::entry_group_callback, this);
175
176 if(currentgroup == NULL){
177 logging_error("failed creating avahi group for service "
178 << name << ": " << avahi_strerror(avahi_client_errno(avahiclient)));
179 avahi_threaded_poll_unlock(avahipoll);
[4733]180 return;
181 }
[4758]182
183 avahigroups.insert( make_pair(name, currentgroup) );
[4733]184 }
185
[4758]186 assert( currentgroup != NULL );
[4733]187
[4758]188 logging_debug("avahi adding service " << name << " to new group");
189
[4733]190 ret = avahi_entry_group_add_service(
[4758]191 currentgroup, // group to add service to
192 AVAHI_IF_UNSPEC, // interface to announce, we use all interfaces
193 AVAHI_PROTO_UNSPEC, // protocol to announce, we use all protocols
194 (AvahiPublishFlags)0, // no special flags
195 name.c_str(), // name of the service, no more than 63 characters
196 serviceType.c_str(), // type of the service: _spovnet._tcp (tcp does not mean anything here, just have to stick with this structure
197 NULL, // publish in all domains
198 NULL, // host name of our machine, let avahi find out
199 3333, // port number the service is on, just dummy, everything is encoded in TXT
200 info.c_str(), // arbitrary info
201 NULL); // make that this is the last info field
[4733]202
203 if( ret < 0 ){
204 logging_warn("failed to add service " << name << ": " << avahi_strerror(ret));
[4758]205 avahigroups.erase(name);
206 avahi_threaded_poll_unlock(avahipoll);
[4733]207 return;
208 }
209
210 // tell the server to register the service
[4758]211 ret = avahi_entry_group_commit( currentgroup );
[4733]212 if(ret < 0) {
213 logging_warn("failed to commit entry group: " << avahi_strerror(ret));
[4758]214 avahigroups.erase(name);
215 avahi_threaded_poll_unlock(avahipoll);
216 return;
[4733]217 }
218
219 avahi_threaded_poll_unlock(avahipoll);
220
221 #endif // HAVE_LIBAVAHI_CLIENT
222}
223
224void MulticastDns::revokeService(string name){
225 #ifdef HAVE_LIBAVAHI_CLIENT
226
[4758]227 avahi_threaded_poll_lock(avahipoll);
[4733]228
[4758]229 AvahiGroupMap::iterator i = avahigroups.find(name);
230 if( i != avahigroups.end() ){
231
232 logging_debug("revoking service " << name);
233 avahi_entry_group_reset( i->second );
234
235 } else {
236 logging_warn("service " << name << " is not registered, cannot revoke");
237 }
238
239 avahi_threaded_poll_unlock(avahipoll);
240
[4733]241 #endif // HAVE_LIBAVAHI_CLIENT
242}
243
244#ifdef HAVE_LIBAVAHI_CLIENT
245
246void MulticastDns::client_callback(AvahiClient* client, AvahiClientState state, void* userdata){
247
248 MulticastDns* obj = (MulticastDns*)userdata;
249 assert( obj != NULL );
250
251 switch (state) {
252 case AVAHI_CLIENT_S_RUNNING:
253
254 // server has startup successfully and registered its host
255 // name on the network, so it's time to create our services
256
257 logging_debug("avahi client is running");
258 break;
259
260 case AVAHI_CLIENT_FAILURE:
261
[4758]262 logging_warn( "avahi client failure "
263 << avahi_strerror(avahi_client_errno(client)) << ". quitting" );
[4733]264 avahi_threaded_poll_quit(obj->avahipoll);
265
266 break;
267
268 case AVAHI_CLIENT_S_COLLISION:
269
270 logging_warn("avahi client collision");
271 break;
272
273 case AVAHI_CLIENT_S_REGISTERING:
274
[4758]275 logging_debug("avahi client registering");
[4733]276 break;
277
278 case AVAHI_CLIENT_CONNECTING:
[4758]279
280 logging_debug("avahi client conencting");
[4733]281 break;
282 }
283}
284
285void MulticastDns::entry_group_callback(AvahiEntryGroup* group, AvahiEntryGroupState state, void* userdata){
286
287 AvahiClient* client = avahi_entry_group_get_client( group );
288 assert( client != NULL);
289
290 MulticastDns* obj = (MulticastDns*)userdata;
291 assert(obj != NULL);
292
293 //
294 // called whenever the entry group state changes
295 //
296
297 switch(state) {
298 case AVAHI_ENTRY_GROUP_ESTABLISHED:
299
300 logging_debug( "service entry group successfully established" );
301 break;
302
303 case AVAHI_ENTRY_GROUP_COLLISION:
304
305 logging_warn("service name collision for name");
306 break;
307
308 case AVAHI_ENTRY_GROUP_FAILURE:
309
310 logging_warn("service group failure: " << avahi_strerror(avahi_client_errno(client)));
311 avahi_threaded_poll_quit(obj->avahipoll);
312
313 break;
314
315 case AVAHI_ENTRY_GROUP_UNCOMMITED:
[4758]316
317 logging_debug("avahi entry group uncommited");
[4733]318 break;
319
320 case AVAHI_ENTRY_GROUP_REGISTERING:
[4758]321
322 logging_debug("avahi entry group registering");
[4733]323 break;
[4758]324
[4733]325 } //switch(state)
326}
327
328void MulticastDns::browse_callback(AvahiServiceBrowser* browser, AvahiIfIndex interface,
329 AvahiProtocol protocol, AvahiBrowserEvent event, const char* name,
330 const char* type, const char* domain, AvahiLookupResultFlags flags, void* userdata){
331
332 AvahiClient* client = avahi_service_browser_get_client(browser);
333 MulticastDns* obj = (MulticastDns*)userdata;
334
335 assert( client != NULL);
336 assert( obj != NULL );
337
338 switch (event) {
339 case AVAHI_BROWSER_FAILURE:
340
341 logging_warn("avahi browser failure " << avahi_strerror(avahi_client_errno(client)));
342 avahi_threaded_poll_quit( obj->avahipoll );
343
344 break;
345
346 case AVAHI_BROWSER_NEW:
347
348 if (!(avahi_service_resolver_new(client,
349 interface, protocol, name, type, domain,
350 AVAHI_PROTO_UNSPEC, (AvahiLookupFlags)0,
351 MulticastDns::resolve_callback, obj))){
[4758]352 logging_warn( "failed to resolve service " << name
353 << ", error " << avahi_strerror(avahi_client_errno(client)));
[4733]354 }
355
356 break;
357
358 case AVAHI_BROWSER_REMOVE:
[4758]359
360 logging_debug("avahi browser remove");
[4733]361 break;
362
363 case AVAHI_BROWSER_ALL_FOR_NOW:
[4758]364
365 logging_debug("avahi all for now");
[4733]366 break;
367
368 case AVAHI_BROWSER_CACHE_EXHAUSTED:
[4758]369
370 logging_debug("avahi browser cache exhausted");
[4733]371 break;
372 }
373}
374
375void MulticastDns::resolve_callback(AvahiServiceResolver* resolver, AvahiIfIndex interface,
376 AvahiProtocol protocol, AvahiResolverEvent event, const char *name,
377 const char* type, const char* domain, const char* host_name,
378 const AvahiAddress* address, uint16_t port, AvahiStringList* txt,
379 AvahiLookupResultFlags flags, void* userdata){
380
381 AvahiClient* client = avahi_service_resolver_get_client(resolver);
382 MulticastDns* obj = (MulticastDns*)userdata;
383
384 assert( client != NULL );
385 assert( obj != NULL );
386
387 switch(event) {
388 case AVAHI_RESOLVER_FAILURE:
389
[4758]390 logging_warn("resolver failed to resolve service " << name
391 << ", error " << avahi_strerror(avahi_client_errno(client)));
[4733]392 break;
393
[4758]394 case AVAHI_RESOLVER_FOUND:
[4733]395
[4758]396 char addr[AVAHI_ADDRESS_STR_MAX];
397 char* text = NULL;
[4733]398
[4758]399 avahi_address_snprint(addr, sizeof(addr), address);
400 text = avahi_string_list_to_string(txt);
[4733]401
[4758]402 if(obj != NULL && obj->callback != NULL)
403 obj->callback->onBootstrapServiceFound(name, text);
[4733]404
[4758]405 avahi_free( text );
[4733]406 break;
407 }
408
409 avahi_service_resolver_free( resolver );
410}
411
412#endif // HAVE_LIBAVAHI_CLIENT
413
414}} //namespace ariba, utility
Note: See TracBrowser for help on using the repository browser.