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

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

avahi paar sachen gefixt, initiale tests mit poolrechnern klappen

File size: 11.1 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_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();
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");
91 return;
92 }
93
94 // block the event loop
95 avahi_threaded_poll_lock( avahipoll );
96
97 // create the service browser for the specified type
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
103 if( avahibrowser == NULL){
104 logging_error("creating avahi browser failed");
105 return;
106 }
107
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
118 //
119 // stop poll and free browser
120 //
121
122 avahi_threaded_poll_stop( avahipoll );
123 avahi_service_browser_free( avahibrowser );
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
140 avahi_client_free( avahiclient );
141 avahiclient = NULL;
142
143 avahi_threaded_poll_free( avahipoll );
144 avahipoll = NULL;
145
146 #endif // HAVE_LIBAVAHI_CLIENT
147}
148
149void MulticastDns::publishService(string name, string info){
150 #ifdef HAVE_LIBAVAHI_CLIENT
151
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
159 avahi_threaded_poll_lock(avahipoll);
160 assert( avahiclient != NULL );
161
162 int ret = 0;
163
164 //
165 // if we have no group for this service, create one
166 //
167
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);
180 return;
181 }
182
183 avahigroups.insert( make_pair(name, currentgroup) );
184 }
185
186 assert( currentgroup != NULL );
187
188 logging_debug("avahi adding service " << name << " to new group");
189
190 ret = avahi_entry_group_add_service(
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
202
203 if( ret < 0 ){
204 logging_warn("failed to add service " << name << ": " << avahi_strerror(ret));
205 avahigroups.erase(name);
206 avahi_threaded_poll_unlock(avahipoll);
207 return;
208 }
209
210 // tell the server to register the service
211 ret = avahi_entry_group_commit( currentgroup );
212 if(ret < 0) {
213 logging_warn("failed to commit entry group: " << avahi_strerror(ret));
214 avahigroups.erase(name);
215 avahi_threaded_poll_unlock(avahipoll);
216 return;
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
227 avahi_threaded_poll_lock(avahipoll);
228
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
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
262 logging_warn( "avahi client failure "
263 << avahi_strerror(avahi_client_errno(client)) << ". quitting" );
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
275 logging_debug("avahi client registering");
276 break;
277
278 case AVAHI_CLIENT_CONNECTING:
279
280 logging_debug("avahi client conencting");
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:
316
317 logging_debug("avahi entry group uncommited");
318 break;
319
320 case AVAHI_ENTRY_GROUP_REGISTERING:
321
322 logging_debug("avahi entry group registering");
323 break;
324
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))){
352 logging_warn( "failed to resolve service " << name
353 << ", error " << avahi_strerror(avahi_client_errno(client)));
354 }
355
356 break;
357
358 case AVAHI_BROWSER_REMOVE:
359
360 logging_debug("avahi browser remove");
361 break;
362
363 case AVAHI_BROWSER_ALL_FOR_NOW:
364
365 logging_debug("avahi all for now");
366 break;
367
368 case AVAHI_BROWSER_CACHE_EXHAUSTED:
369
370 logging_debug("avahi browser cache exhausted");
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
390 logging_warn("resolver failed to resolve service " << name
391 << ", error " << avahi_strerror(avahi_client_errno(client)));
392 break;
393
394 case AVAHI_RESOLVER_FOUND:
395
396 char addr[AVAHI_ADDRESS_STR_MAX];
397 char* text = NULL;
398
399 avahi_address_snprint(addr, sizeof(addr), address);
400 text = avahi_string_list_to_string(txt);
401
402 if(obj != NULL && obj->callback != NULL)
403 obj->callback->onBootstrapServiceFound(name, text);
404
405 avahi_free( text );
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.