00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <netcomm/dns-sd/avahi_thread.h>
00025 #include <netcomm/dns-sd/avahi_resolver_handler.h>
00026
00027 #include <core/threading/mutex.h>
00028 #include <core/threading/wait_condition.h>
00029 #include <core/exceptions/software.h>
00030
00031 #include <avahi-client/lookup.h>
00032 #include <avahi-client/publish.h>
00033 #include <avahi-common/alternative.h>
00034 #include <avahi-common/simple-watch.h>
00035 #include <avahi-common/malloc.h>
00036 #include <avahi-common/error.h>
00037 #include <avahi-common/timeval.h>
00038
00039 #include <sys/socket.h>
00040 #include <sys/types.h>
00041 #include <netinet/in.h>
00042 #include <cstdlib>
00043 #include <cstddef>
00044 #include <cstring>
00045
00046 namespace fawkes {
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 AvahiThread::AvahiThread()
00059 : Thread("AvahiThread")
00060 {
00061 simple_poll = NULL;
00062 client = NULL;
00063
00064 need_recover = false;
00065 do_reset_groups = false;
00066
00067 init_wc = new WaitCondition();
00068
00069 set_prepfin_conc_loop(true);
00070 }
00071
00072
00073
00074 AvahiThread::~AvahiThread()
00075 {
00076 delete init_wc;
00077
00078 erase_groups();
00079 erase_browsers();
00080
00081 if ( client )
00082 avahi_client_free( client );
00083
00084 if ( simple_poll )
00085 avahi_simple_poll_free( simple_poll );
00086
00087 }
00088
00089
00090
00091
00092
00093
00094 void
00095 AvahiThread::loop()
00096 {
00097 if ( need_recover ) {
00098 if ( client ) {
00099 avahi_client_free( client );
00100 client = NULL;
00101 }
00102
00103 if ( simple_poll ) {
00104 avahi_simple_poll_free( simple_poll );
00105 simple_poll = NULL;
00106 }
00107 }
00108
00109 if ( ! simple_poll ) {
00110
00111 int error;
00112
00113 if ( (simple_poll = avahi_simple_poll_new()) ) {
00114
00115 client = avahi_client_new( avahi_simple_poll_get(simple_poll), AVAHI_CLIENT_NO_FAIL,
00116 AvahiThread::client_callback, this, &error );
00117
00118 if ( ! client ) {
00119 avahi_simple_poll_free( simple_poll );
00120 }
00121 }
00122 }
00123
00124 if ( client ) {
00125 if ( do_reset_groups ) {
00126 reset_groups();
00127 recreate_services();
00128 }
00129 if ( need_recover ) {
00130 erase_groups();
00131 erase_browsers();
00132 recreate_services();
00133 recreate_browsers();
00134 }
00135 if ( client_state == AVAHI_CLIENT_S_RUNNING ) {
00136 remove_pending_services();
00137 remove_pending_browsers();
00138 create_pending_services();
00139 create_pending_browsers();
00140 start_hostname_resolvers();
00141 start_address_resolvers();
00142 }
00143
00144 need_recover = false;
00145
00146 avahi_simple_poll_iterate( simple_poll, -1);
00147 }
00148 }
00149
00150
00151
00152
00153
00154
00155 void
00156 AvahiThread::recover()
00157 {
00158 need_recover = true;
00159 wake_poller();
00160 }
00161
00162 void
00163 AvahiThread::wake_poller()
00164 {
00165 if ( simple_poll ) {
00166 avahi_simple_poll_wakeup( simple_poll );
00167 }
00168 }
00169
00170
00171
00172
00173
00174
00175
00176 void
00177 AvahiThread::client_callback(AvahiClient *c, AvahiClientState state, void *instance)
00178 {
00179 AvahiThread *at = static_cast<AvahiThread *>(instance);
00180 at->client_state = state;
00181
00182 switch (state) {
00183 case AVAHI_CLIENT_S_RUNNING:
00184
00185
00186
00187
00188
00189 at->init_done();
00190 break;
00191
00192 case AVAHI_CLIENT_S_COLLISION:
00193
00194
00195
00196
00197 at->do_reset_groups = true;
00198 break;
00199
00200 case AVAHI_CLIENT_FAILURE:
00201
00202
00203 at->recover();
00204 break;
00205
00206 case AVAHI_CLIENT_CONNECTING:
00207
00208 break;
00209
00210 case AVAHI_CLIENT_S_REGISTERING:
00211
00212
00213 break;
00214 }
00215 }
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225 void
00226 AvahiThread::publish_service(NetworkService *service)
00227 {
00228 if ( __services.find(service) == __services.end() ) {
00229 __pending_services.push_locked(service);
00230 } else {
00231 throw Exception("Service already registered");
00232 }
00233
00234 wake_poller();
00235 }
00236
00237
00238 void
00239 AvahiThread::unpublish_service(NetworkService *service)
00240 {
00241 if ( __services.find(service) != __services.end() ) {
00242 __pending_remove_services.push_locked(service);
00243 } else {
00244 throw Exception("Service not registered");
00245 }
00246
00247 wake_poller();
00248 }
00249
00250
00251
00252 AvahiEntryGroup *
00253 AvahiThread::create_service(const NetworkService &service, AvahiEntryGroup *exgroup)
00254 {
00255
00256
00257 if ( ! client ) return NULL;
00258
00259 AvahiEntryGroup *group;
00260 if ( exgroup ) {
00261 group = exgroup;
00262 } else {
00263 if ( ! (group = avahi_entry_group_new(client,
00264 AvahiThread::entry_group_callback,
00265 this))) {
00266 throw NullPointerException("Cannot create service group");
00267 }
00268 }
00269
00270
00271 AvahiStringList *al = NULL;
00272 const std::list<std::string> &l = service.txt();
00273 for (std::list<std::string>::const_iterator j = l.begin(); j != l.end(); ++j) {
00274 al = avahi_string_list_add(al, j->c_str());
00275 }
00276 if ( avahi_entry_group_add_service_strlst(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_INET,
00277 AVAHI_PUBLISH_USE_MULTICAST,
00278 service.name(), service.type(),
00279 service.domain(), service.host(),
00280 service.port(), al) < 0) {
00281 avahi_string_list_free(al);
00282 throw Exception("Adding Avahi services failed");
00283 }
00284 avahi_string_list_free(al);
00285
00286
00287 if (avahi_entry_group_commit(group) < 0) {
00288 throw Exception("Registering Avahi services failed");
00289 }
00290
00291 return group;
00292 }
00293
00294 void
00295 AvahiThread::recreate_services()
00296 {
00297 for (__sit = __services.begin(); __sit != __services.end(); ++__sit) {
00298 (*__sit).second = create_service((*__sit).first, (*__sit).second);
00299 }
00300 }
00301
00302
00303 void
00304 AvahiThread::create_pending_services()
00305 {
00306 __pending_services.lock();
00307 while ( ! __pending_services.empty()) {
00308 NetworkService &s = __pending_services.front();
00309 __services[s] = create_service(s, NULL);
00310 __pending_services.pop();
00311 }
00312 __pending_services.unlock();
00313 }
00314
00315
00316 void
00317 AvahiThread::remove_pending_services()
00318 {
00319 __pending_remove_services.lock();
00320 while ( ! __pending_remove_services.empty()) {
00321 NetworkService &s = __pending_remove_services.front();
00322 if ( __services.find(s) != __services.end() ) {
00323 group_erase(__services[s]);
00324 __services.erase_locked(s);
00325 }
00326 __pending_remove_services.pop();
00327 }
00328 __pending_remove_services.unlock();
00329 }
00330
00331
00332
00333
00334
00335
00336 void
00337 AvahiThread::group_reset(AvahiEntryGroup *g)
00338 {
00339 if ( g ) {
00340 avahi_entry_group_reset(g);
00341 }
00342 }
00343
00344
00345
00346 void
00347 AvahiThread::group_erase(AvahiEntryGroup *g)
00348 {
00349 if ( g ) {
00350 avahi_entry_group_reset( g );
00351 avahi_entry_group_free( g );
00352 }
00353 }
00354
00355
00356 void
00357 AvahiThread::erase_groups()
00358 {
00359 for (__sit = __services.begin(); __sit != __services.end(); ++__sit) {
00360 group_erase((*__sit).second);
00361 (*__sit).second = NULL;
00362 }
00363 }
00364
00365
00366 void
00367 AvahiThread::reset_groups()
00368 {
00369 for (__sit = __services.begin(); __sit != __services.end(); ++__sit) {
00370 group_reset((*__sit).second);
00371 }
00372 }
00373
00374
00375
00376 void
00377 AvahiThread::name_collision(AvahiEntryGroup *g)
00378 {
00379 for (__sit = __services.begin(); __sit != __services.end(); ++__sit) {
00380 if ( (*__sit).second == g ) {
00381 NetworkService alternate_service((*__sit).first);
00382
00383
00384 char *n = avahi_alternative_service_name((*__sit).first.name());
00385 alternate_service.set_name(n);
00386 avahi_free(n);
00387
00388 __pending_remove_services.push_locked((*__sit).first);
00389 __pending_services.push_locked(alternate_service);
00390 }
00391 }
00392 }
00393
00394
00395
00396
00397
00398
00399
00400 void
00401 AvahiThread::entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state,
00402 void *instance)
00403 {
00404 AvahiThread *at = static_cast<AvahiThread *>(instance);
00405
00406 switch (state) {
00407 case AVAHI_ENTRY_GROUP_ESTABLISHED :
00408
00409
00410 break;
00411
00412 case AVAHI_ENTRY_GROUP_COLLISION : {
00413 at->name_collision(g);
00414 break;
00415 }
00416
00417 case AVAHI_ENTRY_GROUP_FAILURE :
00418
00419 at->recover();
00420 break;
00421
00422 case AVAHI_ENTRY_GROUP_UNCOMMITED:
00423 case AVAHI_ENTRY_GROUP_REGISTERING:
00424 break;
00425 }
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441 void
00442 AvahiThread::watch_service(const char *service_type, ServiceBrowseHandler *h)
00443 {
00444 __handlers[service_type].push_back(h);
00445 __pending_browsers.push_locked(service_type);
00446
00447 wake_poller();
00448 }
00449
00450
00451
00452
00453
00454
00455
00456
00457 void
00458 AvahiThread::unwatch_service(const char *service_type, ServiceBrowseHandler *h)
00459 {
00460 if ( __handlers.find(service_type) != __handlers.end() ) {
00461 __handlers[service_type].remove(h);
00462 if ( __handlers[service_type].size() == 0 ) {
00463 if ( __browsers.find(service_type) != __browsers.end() ) {
00464 __pending_browser_removes.push_locked(service_type);
00465
00466
00467 }
00468 __handlers.erase(service_type);
00469 }
00470 }
00471
00472 wake_poller();
00473 }
00474
00475
00476
00477
00478
00479 void
00480 AvahiThread::create_browser(const char *service_type)
00481 {
00482 if ( __browsers.find(service_type) == __browsers.end() ) {
00483 if ( client ) {
00484 AvahiServiceBrowser *b = avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
00485 AVAHI_PROTO_UNSPEC,
00486 service_type, NULL, (AvahiLookupFlags)0,
00487 AvahiThread::browse_callback, this);
00488
00489 if ( ! b ) {
00490 __handlers[service_type].pop_back();
00491 throw NullPointerException("Could not instantiate AvahiServiceBrowser");
00492 }
00493 __browsers[service_type] = b;
00494 }
00495 }
00496 }
00497
00498
00499
00500
00501
00502 void
00503 AvahiThread::recreate_browsers()
00504 {
00505 LockMap< std::string, std::list<ServiceBrowseHandler *> >::iterator i;
00506 for (i = __handlers.begin(); i != __handlers.end(); ++i) {
00507 create_browser( (*i).first.c_str() );
00508 }
00509 }
00510
00511
00512 void
00513 AvahiThread::create_pending_browsers()
00514 {
00515 __pending_browsers.lock();
00516 while ( ! __pending_browsers.empty() ) {
00517
00518 create_browser(__pending_browsers.front().c_str());
00519 __pending_browsers.pop();
00520 }
00521 __pending_browsers.unlock();
00522 }
00523
00524
00525 void
00526 AvahiThread::remove_pending_browsers()
00527 {
00528 __pending_browser_removes.lock();
00529 while ( ! __pending_browser_removes.empty()) {
00530 std::string &s = __pending_browser_removes.front();
00531 avahi_service_browser_free(__browsers[s]);
00532 __browsers.erase_locked(s);
00533 __pending_browser_removes.pop();
00534 }
00535 __pending_browser_removes.unlock();
00536 }
00537
00538
00539
00540 void
00541 AvahiThread::erase_browsers()
00542 {
00543 std::map< std::string, AvahiServiceBrowser * >::iterator i;
00544 for (i = __browsers.begin(); i != __browsers.end(); ++i) {
00545 avahi_service_browser_free((*i).second);
00546 }
00547 __browsers.clear();
00548 }
00549
00550
00551
00552
00553
00554
00555
00556 void
00557 AvahiThread::call_handler_service_removed( const char *name,
00558 const char *type,
00559 const char *domain)
00560 {
00561 if ( __handlers.find(type) != __handlers.end() ) {
00562 std::list<ServiceBrowseHandler *>::iterator i;
00563 for ( i = __handlers[type].begin(); i != __handlers[type].end(); ++i) {
00564 (*i)->service_removed(name, type, domain);
00565 }
00566 }
00567 }
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580 void
00581 AvahiThread::call_handler_service_added( const char *name,
00582 const char *type,
00583 const char *domain,
00584 const char *host_name,
00585 const AvahiAddress *address,
00586 uint16_t port,
00587 std::list<std::string> &txt,
00588 AvahiLookupResultFlags flags)
00589 {
00590 struct sockaddr_in *s = NULL;
00591 socklen_t slen;
00592 if ( address->proto == AVAHI_PROTO_INET ) {
00593 slen = sizeof(struct sockaddr_in);
00594 s = (struct sockaddr_in *)malloc(slen);
00595 s->sin_addr.s_addr = address->data.ipv4.address;
00596 } else {
00597
00598 return;
00599 }
00600 if ( __handlers.find(type) != __handlers.end() ) {
00601 std::list<ServiceBrowseHandler *>::iterator i;
00602 for ( i = __handlers[type].begin(); i != __handlers[type].end(); ++i) {
00603 (*i)->service_added(name, type, domain, host_name,
00604 (struct sockaddr *)s, slen, port, txt, (int)flags);
00605 }
00606 }
00607 free(s);
00608 }
00609
00610
00611
00612
00613
00614
00615
00616 void
00617 AvahiThread::call_handler_failed( const char *name,
00618 const char *type,
00619 const char *domain)
00620 {
00621 if ( __handlers.find(type) != __handlers.end() ) {
00622 std::list<ServiceBrowseHandler *>::iterator i;
00623 for ( i = __handlers[type].begin(); i != __handlers[type].end(); ++i) {
00624 (*i)->browse_failed(name, type, domain);
00625 }
00626 }
00627 }
00628
00629
00630
00631
00632
00633 void
00634 AvahiThread::call_handler_all_for_now(const char *type)
00635 {
00636 if ( __handlers.find(type) != __handlers.end() ) {
00637 std::list<ServiceBrowseHandler *>::iterator i;
00638 for ( i = __handlers[type].begin(); i != __handlers[type].end(); ++i) {
00639 (*i)->all_for_now();
00640 }
00641 }
00642 }
00643
00644
00645
00646
00647
00648 void
00649 AvahiThread::call_handler_cache_exhausted(const char *type)
00650 {
00651 if ( __handlers.find(type) != __handlers.end() ) {
00652 std::list<ServiceBrowseHandler *>::iterator i;
00653 for ( i = __handlers[type].begin(); i != __handlers[type].end(); ++i) {
00654 (*i)->cache_exhausted();
00655 }
00656 }
00657 }
00658
00659
00660
00661
00662
00663
00664
00665
00666
00667
00668
00669
00670
00671
00672
00673 void
00674 AvahiThread::browse_callback( AvahiServiceBrowser *b,
00675 AvahiIfIndex interface,
00676 AvahiProtocol protocol,
00677 AvahiBrowserEvent event,
00678 const char *name,
00679 const char *type,
00680 const char *domain,
00681 AvahiLookupResultFlags flags,
00682 void *instance)
00683 {
00684 AvahiThread *at = static_cast<AvahiThread *>(instance);
00685
00686 switch (event) {
00687 case AVAHI_BROWSER_FAILURE:
00688
00689 return;
00690
00691 case AVAHI_BROWSER_NEW:
00692
00693
00694
00695
00696
00697 if (!(avahi_service_resolver_new(at->client, interface, protocol,
00698 name, type, domain, protocol, (AvahiLookupFlags)0,
00699 AvahiThread::resolve_callback, instance))) {
00700 throw NullPointerException("Could not instantiate resolver");
00701 }
00702 break;
00703
00704 case AVAHI_BROWSER_REMOVE:
00705
00706
00707 at->call_handler_service_removed(name, type, domain);
00708 break;
00709
00710 case AVAHI_BROWSER_ALL_FOR_NOW:
00711
00712
00713 at->call_handler_all_for_now(type);
00714 break;
00715
00716 case AVAHI_BROWSER_CACHE_EXHAUSTED:
00717
00718
00719 at->call_handler_cache_exhausted(type);
00720 break;
00721
00722 }
00723 }
00724
00725
00726
00727
00728
00729
00730
00731
00732
00733
00734
00735
00736
00737
00738
00739
00740
00741
00742
00743 void
00744 AvahiThread::resolve_callback( AvahiServiceResolver *r,
00745 AVAHI_GCC_UNUSED AvahiIfIndex interface,
00746 AVAHI_GCC_UNUSED AvahiProtocol protocol,
00747 AvahiResolverEvent event,
00748 const char *name,
00749 const char *type,
00750 const char *domain,
00751 const char *host_name,
00752 const AvahiAddress *address,
00753 uint16_t port,
00754 AvahiStringList *txt,
00755 AvahiLookupResultFlags flags,
00756 void *instance)
00757 {
00758 AvahiThread *at = static_cast<AvahiThread *>(instance);
00759
00760 switch (event) {
00761 case AVAHI_RESOLVER_FAILURE:
00762
00763 at->call_handler_failed(name, type, domain);
00764 break;
00765
00766 case AVAHI_RESOLVER_FOUND:
00767
00768 {
00769 std::list< std::string > txts;
00770 AvahiStringList *l = txt;
00771
00772 txts.clear();
00773 while ( l ) {
00774 txts.push_back((char *)avahi_string_list_get_text(l));
00775 l = avahi_string_list_get_next( l );
00776 }
00777
00778 at->call_handler_service_added(name, type, domain, host_name, address, port, txts, flags);
00779 }
00780 break;
00781 }
00782
00783 avahi_service_resolver_free(r);
00784 }
00785
00786
00787
00788
00789
00790
00791
00792
00793
00794
00795
00796
00797
00798 void
00799 AvahiThread::resolve_name(const char *name, AvahiResolverHandler *handler)
00800 {
00801 AvahiResolverCallbackData *data = new AvahiResolverCallbackData(this, handler);
00802
00803 if ( __pending_hostname_resolves.find(name) == __pending_hostname_resolves.end()) {
00804 __pending_hostname_resolves[name] = data;
00805 }
00806
00807 wake_poller();
00808 }
00809
00810
00811 void
00812 AvahiThread::start_hostname_resolver(const char *name, AvahiResolverCallbackData *data)
00813 {
00814 AvahiHostNameResolver *resolver;
00815 if ( (resolver = avahi_host_name_resolver_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
00816 name, AVAHI_PROTO_INET,
00817 AVAHI_LOOKUP_USE_MULTICAST,
00818 AvahiThread::host_name_resolver_callback,
00819 data) ) == NULL ) {
00820 throw Exception("Cannot create Avahi name resolver");
00821 } else {
00822 __running_hostname_resolvers.push_back(resolver);
00823 }
00824
00825 }
00826
00827
00828 void
00829 AvahiThread::start_hostname_resolvers()
00830 {
00831 for (__phrit = __pending_hostname_resolves.begin(); __phrit != __pending_hostname_resolves.end(); ++__phrit) {
00832 start_hostname_resolver((*__phrit).first.c_str(), (*__phrit).second);
00833 }
00834 __pending_hostname_resolves.clear();
00835 }
00836
00837
00838 void
00839 AvahiThread::start_address_resolvers()
00840 {
00841 for (__parit = __pending_address_resolves.begin(); __parit != __pending_address_resolves.end(); ++__parit) {
00842 start_address_resolver((*__parit).first, (*__parit).second);
00843 }
00844 __pending_address_resolves.clear();
00845 }
00846
00847
00848
00849
00850
00851
00852
00853
00854
00855 void
00856 AvahiThread::resolve_address(struct sockaddr *addr, socklen_t addrlen,
00857 AvahiResolverHandler *handler)
00858 {
00859 if ( addrlen != sizeof(struct sockaddr_in) ) {
00860 throw Exception("Only IPv4 is currently supported");
00861 }
00862
00863 struct sockaddr_in *in_addr = (struct sockaddr_in *)calloc(1, sizeof(struct sockaddr_in));
00864 memcpy(in_addr, addr, sizeof(struct sockaddr_in));
00865 AvahiResolverCallbackData *data = new AvahiResolverCallbackData(this, handler);
00866
00867 __pending_address_resolves[in_addr] = data;
00868 wake_poller();
00869 }
00870
00871
00872 void
00873 AvahiThread::start_address_resolver(struct sockaddr_in *in_addr, AvahiResolverCallbackData *data)
00874 {
00875 AvahiAddress a;
00876 a.proto = AVAHI_PROTO_INET;
00877 a.data.ipv4.address = in_addr->sin_addr.s_addr;
00878
00879 AvahiAddressResolver *resolver;
00880 if ( (resolver = avahi_address_resolver_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
00881 &a, AVAHI_LOOKUP_USE_MULTICAST,
00882 AvahiThread::address_resolver_callback,
00883 data) ) == NULL ) {
00884 Exception e("Cannot create Avahi address resolver");
00885 e.append("Avahi error: %s", avahi_strerror(avahi_client_errno(client)));
00886 throw e;
00887 } else {
00888 __running_address_resolvers.push_back_locked(resolver);
00889 }
00890 }
00891
00892
00893
00894
00895
00896
00897 void
00898 AvahiThread::remove_hostname_resolver(AvahiHostNameResolver *r)
00899 {
00900 __running_hostname_resolvers.remove_locked(r);
00901 }
00902
00903
00904
00905
00906
00907
00908 void
00909 AvahiThread::remove_address_resolver(AvahiAddressResolver *r)
00910 {
00911 __running_address_resolvers.remove_locked(r);
00912 }
00913
00914
00915
00916
00917
00918 void
00919 AvahiThread::host_name_resolver_callback(AvahiHostNameResolver *r,
00920 AvahiIfIndex interface,
00921 AvahiProtocol protocol,
00922 AvahiResolverEvent event,
00923 const char *name,
00924 const AvahiAddress *a,
00925 AvahiLookupResultFlags flags,
00926 void *userdata)
00927 {
00928 AvahiResolverCallbackData *cd = static_cast<AvahiResolverCallbackData *>(userdata);
00929
00930 cd->first->remove_hostname_resolver(r);
00931 avahi_host_name_resolver_free(r);
00932
00933 switch (event) {
00934 case AVAHI_RESOLVER_FOUND:
00935 {
00936 struct sockaddr_in *res = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
00937 res->sin_family = (unsigned short)avahi_proto_to_af(protocol);
00938 res->sin_addr.s_addr = a->data.ipv4.address;
00939
00940 cd->second->resolved_name(strdup(name), (struct sockaddr *)res, sizeof(struct sockaddr_in));
00941 }
00942 break;
00943
00944 case AVAHI_RESOLVER_FAILURE:
00945 default:
00946 cd->second->name_resolution_failed(strdup(name));
00947 break;
00948 }
00949
00950 delete cd;
00951 }
00952
00953
00954
00955
00956
00957 void
00958 AvahiThread::address_resolver_callback(AvahiAddressResolver *r,
00959 AvahiIfIndex interface,
00960 AvahiProtocol protocol,
00961 AvahiResolverEvent event,
00962 const AvahiAddress *a,
00963 const char *name,
00964 AvahiLookupResultFlags flags,
00965 void *userdata)
00966 {
00967 AvahiResolverCallbackData *cd = static_cast<AvahiResolverCallbackData *>(userdata);
00968
00969 cd->first->remove_address_resolver(r);
00970 avahi_address_resolver_free(r);
00971
00972 struct sockaddr_in *res = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in));
00973 res->sin_family = (unsigned short)avahi_proto_to_af(protocol);
00974 res->sin_addr.s_addr = a->data.ipv4.address;
00975
00976 switch (event) {
00977 case AVAHI_RESOLVER_FOUND:
00978 cd->second->resolved_address((struct sockaddr_in *)res, sizeof(struct sockaddr_in),
00979 strdup(name));
00980 break;
00981 case AVAHI_RESOLVER_FAILURE:
00982 default:
00983 cd->second->address_resolution_failed((struct sockaddr_in *)res,
00984 sizeof(struct sockaddr_in));
00985 break;
00986 }
00987
00988 delete cd;
00989 }
00990
00991
00992
00993
00994
00995 void
00996 AvahiThread::init_done()
00997 {
00998 wake_poller();
00999 init_wc->wake_all();
01000 }
01001
01002
01003
01004
01005
01006
01007
01008
01009
01010
01011 void
01012 AvahiThread::wait_initialized()
01013 {
01014 init_wc->wait();
01015 }
01016
01017 }