+static void browser_cancel(AvahiSRecordBrowser *b) {
+ assert(b);
+
+ if (b->root_lookup) {
+ lookup_unref(b->root_lookup);
+ b->root_lookup = NULL;
+ }
+
+ if (b->defer_time_event) {
+ avahi_time_event_free(b->defer_time_event);
+ b->defer_time_event = NULL;
+ }
+}
+
+static void lookup_wide_area_callback(
+ AvahiWideAreaLookupEngine *e,
+ AvahiBrowserEvent event,
+ AvahiLookupResultFlags flags,
+ AvahiRecord *r,
+ void *userdata) {
+
+ AvahiSRBLookup *l = userdata;
+ AvahiSRecordBrowser *b;
+
+ assert(e);
+ assert(l);
+ assert(l->ref >= 1);
+
+ b = l->record_browser;
+
+ if (b->dead)
+ return;
+
+ lookup_ref(l);
+
+ switch (event) {
+ case AVAHI_BROWSER_NEW:
+ assert(r);
+
+ if (r->key->clazz == AVAHI_DNS_CLASS_IN &&
+ r->key->type == AVAHI_DNS_TYPE_CNAME)
+ /* It's a CNAME record, so let's follow it. We only follow it on wide area DNS! */
+ lookup_handle_cname(l, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AVAHI_LOOKUP_USE_WIDE_AREA, r);
+ else {
+ /* It's a normal record, so let's call the user callback */
+ assert(avahi_key_equal(r->key, l->key));
+
+ b->callback(b, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, event, r, flags, b->userdata);
+ }
+ break;
+
+ case AVAHI_BROWSER_REMOVE:
+ case AVAHI_BROWSER_CACHE_EXHAUSTED:
+ /* Not defined for wide area DNS */
+ abort();
+
+ case AVAHI_BROWSER_ALL_FOR_NOW:
+ case AVAHI_BROWSER_FAILURE:
+
+ b->callback(b, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, event, NULL, flags, b->userdata);
+ break;
+ }
+
+ lookup_unref(l);
+
+}
+
+static void lookup_multicast_callback(
+ AvahiMulticastLookupEngine *e,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ AvahiLookupResultFlags flags,
+ AvahiRecord *r,
+ void *userdata) {
+
+ AvahiSRBLookup *l = userdata;
+ AvahiSRecordBrowser *b;
+
+ assert(e);
+ assert(l);
+
+ b = l->record_browser;
+
+ if (b->dead)
+ return;
+
+ lookup_ref(l);
+
+ switch (event) {
+ case AVAHI_BROWSER_NEW:
+ assert(r);
+
+ if (r->key->clazz == AVAHI_DNS_CLASS_IN &&
+ r->key->type == AVAHI_DNS_TYPE_CNAME)
+ /* It's a CNAME record, so let's follow it. We allow browsing on both multicast and wide area. */
+ lookup_handle_cname(l, interface, protocol, b->flags, r);
+ else {
+ /* It's a normal record, so let's call the user callback */
+
+ if (avahi_server_is_record_local(b->server, interface, protocol, r))
+ flags |= AVAHI_LOOKUP_RESULT_LOCAL;
+
+ b->callback(b, interface, protocol, event, r, flags, b->userdata);
+ }
+ break;
+
+ case AVAHI_BROWSER_REMOVE:
+ assert(r);
+
+ if (r->key->clazz == AVAHI_DNS_CLASS_IN &&
+ r->key->type == AVAHI_DNS_TYPE_CNAME)
+ /* It's a CNAME record, so let's drop that query! */
+ lookup_drop_cname(l, interface, protocol, 0, r);
+ else {
+ /* It's a normal record, so let's call the user callback */
+ assert(avahi_key_equal(b->key, l->key));
+
+ b->callback(b, interface, protocol, event, r, flags, b->userdata);
+ }
+ break;
+
+ case AVAHI_BROWSER_ALL_FOR_NOW:
+
+ b->callback(b, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, event, NULL, flags, b->userdata);
+ break;
+
+ case AVAHI_BROWSER_CACHE_EXHAUSTED:
+ case AVAHI_BROWSER_FAILURE:
+ /* Not defined for multicast DNS */
+ abort();
+
+ }
+
+ lookup_unref(l);
+}
+
+static int lookup_start(AvahiSRBLookup *l) {
+ assert(l);
+
+ assert(!(l->flags & AVAHI_LOOKUP_USE_WIDE_AREA) != !(l->flags & AVAHI_LOOKUP_USE_MULTICAST));
+ assert(!l->wide_area && !l->multicast);