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

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

avahi fehler logging

File size: 11.8 KB
Line 
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
44const string MulticastDns::serviceType = "_spovnet._tcp";
45use_logging_cpp(MulticastDns);
46
47MulticastDns::MulticastDns(BootstrapInformationCallback* _callback) : BootstrapModule(_callback) {
48 #ifdef HAVE_AVAHI_CLIENT_CLIENT_H
49 avahiclient = NULL;
50 avahipoll = NULL;
51 avahibrowser = NULL;
52 #endif // HAVE_AVAHI_CLIENT_CLIENT_H
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_AVAHI_CLIENT_CLIENT_H
68 return true;
69 #else
70 return false;
71 #endif
72}
73
74void MulticastDns::start(){
75 #ifdef HAVE_AVAHI_CLIENT_CLIENT_H
76
77 int error = 0;
78
79 // create a new avahi polling thread
80 avahipoll = avahi_threaded_poll_new();
81 if( avahipoll == NULL){
82 logging_error("creating avahi poll failed");
83 return;
84 }
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 );
89 if( avahiclient == NULL){
90 logging_error("creating avahi client failed with error "
91 << error << ". make sure that the avahi-daemon is running. e.g. by installing avahi-utils);
92 return;
93 }
94
95 // block the event loop
96 avahi_threaded_poll_lock( avahipoll );
97
98 // create the service browser for the specified type
99 avahibrowser = avahi_service_browser_new(
100 avahiclient, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
101 serviceType.c_str(), NULL,
102 (AvahiLookupFlags)0, MulticastDns::browse_callback, this);
103
104 if( avahibrowser == NULL){
105 logging_error("creating avahi browser failed");
106 return;
107 }
108
109 //unblock the event loop and let it run
110 avahi_threaded_poll_unlock( avahipoll );
111 avahi_threaded_poll_start( avahipoll );
112
113 #endif // HAVE_AVAHI_CLIENT_CLIENT_H
114}
115
116void MulticastDns::stop(){
117 #ifdef HAVE_AVAHI_CLIENT_CLIENT_H
118
119 //
120 // stop poll and free browser
121 //
122
123 avahi_threaded_poll_stop( avahipoll );
124 avahi_service_browser_free( avahibrowser );
125 avahibrowser = NULL;
126
127 //
128 // free all registered groups
129 //
130
131 AvahiGroupMap::iterator i = avahigroups.begin();
132 AvahiGroupMap::iterator iend = avahigroups.end();
133
134 for( ; i != iend; i++)
135 avahi_entry_group_free( i->second );
136
137 //
138 // free client and poll
139 //
140
141 if(avahiclient != NULL)
142 avahi_client_free( avahiclient );
143 avahiclient = NULL;
144
145 if(avahipoll != NULL)
146 avahi_threaded_poll_free( avahipoll );
147 avahipoll = NULL;
148
149 #endif // HAVE_AVAHI_CLIENT_CLIENT_H
150}
151
152void MulticastDns::publishService(string name, string info1, string info2, string info3){
153 #ifdef HAVE_AVAHI_CLIENT_CLIENT_H
154
155 if(name.length() > 63){
156 logging_error("service name length must not exceed 63 characters. "
157 << name << " is " << name.length() << " characters");
158 return;
159 }
160
161 if( avahiclient == NULL ){
162 logging_error("avahi client is invalid");
163 return;
164 }
165
166 avahi_threaded_poll_lock(avahipoll);
167 int ret = 0;
168
169 //
170 // if we have no group for this service, create one
171 //
172
173 AvahiGroupMap::iterator igroup = avahigroups.find(name);
174 AvahiEntryGroup* currentgroup = (igroup != avahigroups.end() ? igroup->second : NULL);
175
176 if( currentgroup == NULL ){
177
178 logging_debug("creating group for service " << name);
179 currentgroup = avahi_entry_group_new(avahiclient, MulticastDns::entry_group_callback, this);
180
181 if(currentgroup == NULL){
182 logging_error("failed creating avahi group for service "
183 << name << ": " << avahi_strerror(avahi_client_errno(avahiclient)));
184 avahi_threaded_poll_unlock(avahipoll);
185 return;
186 }
187
188 avahigroups.insert( make_pair(name, currentgroup) );
189 }
190
191 assert( currentgroup != NULL );
192
193 logging_debug("avahi adding service " << name << " to new group");
194
195 ret = avahi_entry_group_add_service(
196 currentgroup, // group to add service to
197 AVAHI_IF_UNSPEC, // interface to announce, we use all interfaces
198 AVAHI_PROTO_UNSPEC, // protocol to announce, we use all protocols
199 (AvahiPublishFlags)0, // no special flags
200 name.c_str(), // name of the service, no more than 63 characters
201 serviceType.c_str(), // type of the service: _spovnet._tcp (tcp does not mean anything here, just have to stick with this structure
202 NULL, // publish in all domains
203 NULL, // host name of our machine, let avahi find out
204 3333, // port number the service is on, just dummy, everything is encoded in TXT
205 info1.c_str(), // arbitrary info
206 info2.c_str(), // arbitrary info
207 info3.c_str(), // arbitrary info
208 NULL); // make that this is the last info field
209
210 if( ret < 0 ){
211 logging_warn("failed to add service " << name << ": " << avahi_strerror(ret));
212 avahigroups.erase(name);
213 avahi_threaded_poll_unlock(avahipoll);
214 return;
215 }
216
217 // tell the server to register the service
218 ret = avahi_entry_group_commit( currentgroup );
219 if(ret < 0) {
220 logging_warn("failed to commit entry group: " << avahi_strerror(ret));
221 avahigroups.erase(name);
222 avahi_threaded_poll_unlock(avahipoll);
223 return;
224 }
225
226 avahi_threaded_poll_unlock(avahipoll);
227
228 #endif // HAVE_AVAHI_CLIENT_CLIENT_H
229}
230
231void MulticastDns::revokeService(string name){
232 #ifdef HAVE_AVAHI_CLIENT_CLIENT_H
233
234 avahi_threaded_poll_lock(avahipoll);
235
236 AvahiGroupMap::iterator i = avahigroups.find(name);
237 if( i != avahigroups.end() ){
238
239 logging_debug("revoking service " << name);
240 avahi_entry_group_reset( i->second );
241
242 } else {
243 logging_warn("service " << name << " is not registered, cannot revoke");
244 }
245
246 avahi_threaded_poll_unlock(avahipoll);
247
248 #endif // HAVE_AVAHI_CLIENT_CLIENT_H
249}
250
251#ifdef HAVE_AVAHI_CLIENT_CLIENT_H
252
253void MulticastDns::client_callback(AvahiClient* client, AvahiClientState state, void* userdata){
254
255 MulticastDns* obj = (MulticastDns*)userdata;
256 assert( obj != NULL );
257
258 switch (state) {
259 case AVAHI_CLIENT_S_RUNNING:
260
261 // server has startup successfully and registered its host
262 // name on the network, so it's time to create our services
263
264 logging_debug("avahi client is running");
265 break;
266
267 case AVAHI_CLIENT_FAILURE:
268
269 logging_warn( "avahi client failure "
270 << avahi_strerror(avahi_client_errno(client)) << ". quitting" );
271 avahi_threaded_poll_quit(obj->avahipoll);
272
273 break;
274
275 case AVAHI_CLIENT_S_COLLISION:
276
277 logging_warn("avahi client collision");
278 break;
279
280 case AVAHI_CLIENT_S_REGISTERING:
281
282 logging_debug("avahi client registering");
283 break;
284
285 case AVAHI_CLIENT_CONNECTING:
286
287 logging_debug("avahi client conencting");
288 break;
289 }
290}
291
292void MulticastDns::entry_group_callback(AvahiEntryGroup* group, AvahiEntryGroupState state, void* userdata){
293
294 AvahiClient* client = avahi_entry_group_get_client( group );
295 assert( client != NULL);
296
297 MulticastDns* obj = (MulticastDns*)userdata;
298 assert(obj != NULL);
299
300 //
301 // called whenever the entry group state changes
302 //
303
304 switch(state) {
305 case AVAHI_ENTRY_GROUP_ESTABLISHED:
306
307 logging_debug( "service entry group successfully established" );
308 break;
309
310 case AVAHI_ENTRY_GROUP_COLLISION:
311
312 logging_warn("service name collision for name");
313 break;
314
315 case AVAHI_ENTRY_GROUP_FAILURE:
316
317 logging_warn("service group failure: " << avahi_strerror(avahi_client_errno(client)));
318 avahi_threaded_poll_quit(obj->avahipoll);
319
320 break;
321
322 case AVAHI_ENTRY_GROUP_UNCOMMITED:
323
324 logging_debug("avahi entry group uncommited");
325 break;
326
327 case AVAHI_ENTRY_GROUP_REGISTERING:
328
329 logging_debug("avahi entry group registering");
330 break;
331
332 } //switch(state)
333}
334
335void MulticastDns::browse_callback(AvahiServiceBrowser* browser, AvahiIfIndex interface,
336 AvahiProtocol protocol, AvahiBrowserEvent event, const char* name,
337 const char* type, const char* domain, AvahiLookupResultFlags flags, void* userdata){
338
339 AvahiClient* client = avahi_service_browser_get_client(browser);
340 MulticastDns* obj = (MulticastDns*)userdata;
341
342 assert( client != NULL);
343 assert( obj != NULL );
344
345 switch (event) {
346 case AVAHI_BROWSER_FAILURE:
347
348 logging_warn("avahi browser failure " << avahi_strerror(avahi_client_errno(client)));
349 avahi_threaded_poll_quit( obj->avahipoll );
350
351 break;
352
353 case AVAHI_BROWSER_NEW:
354
355 if (!(avahi_service_resolver_new(client,
356 interface, protocol, name, type, domain,
357 AVAHI_PROTO_UNSPEC, (AvahiLookupFlags)0,
358 MulticastDns::resolve_callback, obj))){
359 logging_warn( "failed to resolve service " << name
360 << ", error " << avahi_strerror(avahi_client_errno(client)));
361 }
362
363 break;
364
365 case AVAHI_BROWSER_REMOVE:
366
367 logging_debug("avahi browser remove");
368 break;
369
370 case AVAHI_BROWSER_ALL_FOR_NOW:
371
372 logging_debug("avahi all for now");
373 break;
374
375 case AVAHI_BROWSER_CACHE_EXHAUSTED:
376
377 logging_debug("avahi browser cache exhausted");
378 break;
379 }
380}
381
382void MulticastDns::resolve_callback(AvahiServiceResolver* resolver, AvahiIfIndex interface,
383 AvahiProtocol protocol, AvahiResolverEvent event, const char *name,
384 const char* type, const char* domain, const char* host_name,
385 const AvahiAddress* address, uint16_t port, AvahiStringList* txt,
386 AvahiLookupResultFlags flags, void* userdata){
387
388 AvahiClient* client = avahi_service_resolver_get_client(resolver);
389 MulticastDns* obj = (MulticastDns*)userdata;
390
391 assert( client != NULL );
392 assert( obj != NULL );
393
394 switch(event) {
395 case AVAHI_RESOLVER_FAILURE:
396
397 logging_warn("resolver failed to resolve service " << name
398 << ", error " << avahi_strerror(avahi_client_errno(client)));
399 break;
400
401 case AVAHI_RESOLVER_FOUND:
402
403 string info1 = "";
404 string info2 = "";
405 string info3 = "";
406
407 if(txt != NULL){
408 char* cinfo = (char*)avahi_string_list_get_text(txt);
409 info1 = string(cinfo);
410 txt = avahi_string_list_get_next(txt);
411 }
412
413 if(txt != NULL){
414 char* cinfo = (char*)avahi_string_list_get_text(txt);
415 info2 = string(cinfo);
416 txt = avahi_string_list_get_next(txt);
417 }
418
419 if(txt != NULL){
420 char* cinfo = (char*)avahi_string_list_get_text(txt);
421 info3 = string(cinfo);
422 txt = avahi_string_list_get_next(txt);
423 }
424
425 if(obj != NULL && obj->callback != NULL)
426 obj->callback->onBootstrapServiceFound(name, info1, info2, info3);
427
428 break;
429 }
430
431 avahi_service_resolver_free( resolver );
432}
433
434#endif // HAVE_AVAHI_CLIENT_CLIENT_H
435
436}} //namespace ariba, utility
Note: See TracBrowser for help on using the repository browser.