--- avahi-0.6.28/avahi-core/browse-service.c.orig 2010-08-26 01:51:38.983153000 +0100 +++ avahi-0.6.28/avahi-core/browse-service.c 2011-01-20 09:22:41.808471289 +0000 @@ -21,10 +21,14 @@ #include #endif +#include #include #include #include +#ifdef HAVE_BONJOUR +#include +#endif #include #include "browse.h" @@ -40,9 +44,131 @@ AvahiSServiceBrowserCallback callback; void* userdata; +#ifdef HAVE_BONJOUR + AvahiProtocol protocol; + AvahiIfIndex interface; + AvahiTimeEvent *browse_error_event; + AvahiTimeEvent *all_for_now_event; + AvahiLookupFlags flags; + AvahiWatch *watch; + DNSServiceRef client; +#endif + AVAHI_LLIST_FIELDS(AvahiSServiceBrowser, browser); }; +#ifdef HAVE_BONJOUR +static void browse_reply(DNSServiceRef client, const DNSServiceFlags flags, uint32_t IfIndex, DNSServiceErrorType errorCode, + const char *name, const char *type, const char *domain, void *context) { + AvahiSServiceBrowser *b = context; + char *op = (flags &kDNSServiceFlagsAdd) ? "Add" : "Rmv"; + AvahiBrowserEvent event; + AvahiIfIndex interface; + + interface = (IfIndex == kDNSServiceInterfaceIndexAny) ? AVAHI_IF_UNSPEC : IfIndex; + + event = (flags &kDNSServiceFlagsAdd) ? AVAHI_BROWSER_NEW : AVAHI_BROWSER_REMOVE; + + b->callback(b, interface, AVAHI_PROTO_UNSPEC, event, name, type, domain, 0, b->userdata); + +} + +static void browse_socket_event(AvahiWatch *w, int fd, AvahiWatchEvent events, void *userdata) { + AvahiSServiceBrowser *b = userdata; + DNSServiceErrorType ret; + + assert(w); + assert(fd >= 0); + assert(events & AVAHI_WATCH_IN); + + assert (fd == DNSServiceRefSockFD(b->client)); + ret = DNSServiceProcessResult(b->client); + if (ret != kDNSServiceErr_NoError) { + if (b->watch) { + b->server->poll_api->watch_free(b->watch); + b->watch = NULL; + } + DNSServiceRefDeallocate(b->client); + b->client = NULL; + avahi_server_set_errno(b->server, AVAHI_ERR_DISCONNECTED); + b->callback(b, + b->interface, + b->protocol, + AVAHI_BROWSER_FAILURE, + NULL, + b->service_type, + b->domain_name, + 0, + b->userdata); + } +} + +static void all_for_now_callback(AvahiTimeEvent *e, void* userdata) { + AvahiSServiceBrowser *b = userdata; + + assert(e); + assert(b); + + avahi_time_event_free(b->all_for_now_event); + b->all_for_now_event = NULL; + + b->callback(b, + b->interface, + b->protocol, + AVAHI_BROWSER_ALL_FOR_NOW, + NULL, + b->service_type, + NULL, + 0, + b->userdata); +} + +static void browse_error_callback(AvahiTimeEvent *e, void *userdata) { + AvahiSServiceBrowser *b = userdata; + + if (b->browse_error_event) { + avahi_time_event_free(b->browse_error_event); + b->browse_error_event = NULL; + } + avahi_server_set_errno(b->server, AVAHI_ERR_FAILURE); + b->callback(b, + b->interface, + b->protocol, + AVAHI_BROWSER_FAILURE, + NULL, + b->service_type, + b->domain_name, + 0, + b->userdata); +} + +static void avahi_browse_service_start(AvahiSServiceBrowser *b) { + DNSServiceErrorType ret; + struct timeval tv; + + ret = DNSServiceBrowse(&b->client, + 0, + b->interface == AVAHI_IF_UNSPEC ? + kDNSServiceInterfaceIndexAny : + b->interface, + b->service_type, + b->domain_name, + browse_reply, + b); + if (ret != kDNSServiceErr_NoError || !b->client) { + b->browse_error_event = avahi_time_event_new(b->server->time_event_queue, +NULL, browse_error_callback, b); + } else { + b->watch = b->server->poll_api->watch_new(b->server->poll_api, DNSServiceRefSockFD(b->client), AVAHI_WATCH_IN, browse_socket_event, b); + + /* Add a second */ + gettimeofday(&tv, NULL); + avahi_timeval_add(&tv, 1000000); + b->all_for_now_event = avahi_time_event_new(b->server->time_event_queue, &tv, all_for_now_callback, b); + } +} +#endif + static void record_browser_callback( AvahiSRecordBrowser*rr, AvahiIfIndex interface, @@ -102,7 +228,11 @@ AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_IF_VALID(interface), AVAHI_ERR_INVALID_INTERFACE); AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_PROTO_VALID(protocol), AVAHI_ERR_INVALID_PROTOCOL); AVAHI_CHECK_VALIDITY_RETURN_NULL(server, !domain || avahi_is_valid_domain_name(domain), AVAHI_ERR_INVALID_DOMAIN_NAME); +#ifdef HAVE_BONJOUR + AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS); +#else AVAHI_CHECK_VALIDITY_RETURN_NULL(server, AVAHI_FLAGS_VALID(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST), AVAHI_ERR_INVALID_FLAGS); +#endif AVAHI_CHECK_VALIDITY_RETURN_NULL(server, avahi_is_valid_service_type_generic(service_type), AVAHI_ERR_INVALID_SERVICE_TYPE); if (!domain) @@ -132,6 +262,16 @@ goto fail; } +#ifdef HAVE_BONJOUR + b->protocol = protocol; + b->interface = interface; + b->flags = flags; + b->browse_error_event = NULL; + b->all_for_now_event = NULL; + b->client = NULL; + b->watch = NULL; + avahi_browse_service_start(b); +#else if (!(k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR))) { avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY); goto fail; @@ -141,6 +281,7 @@ goto fail; avahi_key_unref(k); +#endif return b; @@ -163,5 +304,21 @@ avahi_free(b->domain_name); avahi_free(b->service_type); +#ifdef HAVE_BONJOUR + if (b->browse_error_event) { + avahi_time_event_free(b->browse_error_event); + b->browse_error_event = NULL; + } + if (b->all_for_now_event) { + avahi_time_event_free(b->all_for_now_event); + b->all_for_now_event = NULL; + } + + if (b->watch) + b->server->poll_api->watch_free(b->watch); + + if (b->client) + DNSServiceRefDeallocate (b->client); +#endif avahi_free(b); }