+static AvahiSRBLookup* lookup_add(AvahiSRecordBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiLookupFlags flags, AvahiKey *key) {
+ AvahiSRBLookup *l;
+
+ assert(b);
+ assert(!b->dead);
+
+ if ((l = lookup_find(b, interface, protocol, flags, key)))
+ return lookup_ref(l);
+
+ if (!(l = lookup_new(b, interface, protocol, flags, key)))
+ return NULL;
+
+ return l;
+}
+
+static int lookup_go(AvahiSRBLookup *l) {
+ int n = 0;
+ assert(l);
+
+ if (l->record_browser->dead)
+ return 0;
+
+ lookup_ref(l);
+
+ /* Browse the cache for the root request */
+ n = lookup_scan_cache(l);
+
+ /* Start the lookup */
+ if (!l->record_browser->dead && l->ref > 1) {
+
+ if ((l->flags & AVAHI_LOOKUP_USE_MULTICAST) || n == 0)
+ /* We do no start a query if the cache contained entries and we're on wide area */
+
+ if (lookup_start(l) < 0)
+ n = -1;
+ }
+
+ lookup_unref(l);
+
+ return n;
+}
+
+static void lookup_handle_cname(AvahiSRBLookup *l, AvahiIfIndex interface, AvahiProtocol protocol, AvahiLookupFlags flags, AvahiRecord *r) {
+ AvahiKey *k;
+ AvahiSRBLookup *n;
+
+ assert(l);
+ assert(r);
+
+ assert(r->key->clazz == AVAHI_DNS_CLASS_IN);
+ assert(r->key->type == AVAHI_DNS_TYPE_CNAME);
+
+ k = avahi_key_new(r->data.ptr.name, l->record_browser->key->clazz, l->record_browser->key->type);
+ n = lookup_add(l->record_browser, interface, protocol, flags, k);
+ avahi_key_unref(k);
+
+ if (!n) {
+ avahi_log_debug(__FILE__": Failed to create SRBLookup.");
+ return;
+ }
+
+ l->cname_lookups = avahi_rlist_prepend(l->cname_lookups, lookup_ref(n));
+
+ lookup_go(n);
+ lookup_unref(n);
+}
+
+static void lookup_drop_cname(AvahiSRBLookup *l, AvahiIfIndex interface, AvahiProtocol protocol, AvahiLookupFlags flags, AvahiRecord *r) {
+ AvahiKey *k;
+ AvahiSRBLookup *n = NULL;
+ AvahiRList *rl;
+
+ assert(r->key->clazz == AVAHI_DNS_CLASS_IN);
+ assert(r->key->type == AVAHI_DNS_TYPE_CNAME);
+
+ k = avahi_key_new(r->data.ptr.name, l->record_browser->key->clazz, l->record_browser->key->type);
+
+ for (rl = l->cname_lookups; rl; rl = rl->rlist_next) {
+ n = rl->data;
+
+ assert(n);
+
+ if ((n->interface == AVAHI_IF_UNSPEC || n->interface == interface) &&
+ (n->interface == AVAHI_PROTO_UNSPEC || n->protocol == protocol) &&
+ n->flags == flags &&
+ avahi_key_equal(n->key, k))
+ break;
+ }
+
+ avahi_key_unref(k);
+
+ if (rl) {
+ l->cname_lookups = avahi_rlist_remove_by_link(l->cname_lookups, rl);
+ lookup_unref(n);
+ }
+}
+
+static void defer_callback(AVAHI_GCC_UNUSED AvahiTimeEvent *e, void *userdata) {
+ AvahiSRecordBrowser *b = userdata;
+ int n;
+
+ assert(b);
+ assert(!b->dead);
+
+ /* Remove the defer timeout */
+ if (b->defer_time_event) {
+ avahi_time_event_free(b->defer_time_event);
+ b->defer_time_event = NULL;
+ }