static void run_callbacks(AvahiWideAreaLookupEngine *e, AvahiRecord *r) { AvahiWideAreaLookup *l; assert(e); assert(r); for (l = avahi_hashmap_lookup(e->lookups_by_key, r->key); l; l = l->by_key_next) { if (l->dead || !l->callback) continue; l->callback(e, AVAHI_BROWSER_NEW, AVAHI_LOOKUP_RESULT_WIDE_AREA, r, l->userdata); } if (r->key->clazz == AVAHI_DNS_CLASS_IN && r->key->type == AVAHI_DNS_TYPE_CNAME) { /* It's a CNAME record, so we have to scan the all lookups to see if one matches */ for (l = e->lookups; l; l = l->lookups_next) { AvahiKey *key; if (l->dead || !l->callback) continue; if ((key = avahi_key_new_cname(l->key))) { if (avahi_key_equal(r->key, key)) l->callback(e, AVAHI_BROWSER_NEW, AVAHI_LOOKUP_RESULT_WIDE_AREA, r, l->userdata); avahi_key_unref(key); } } } }
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 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 AvahiQueryJob* find_scheduled_job(AvahiQueryScheduler *s, AvahiKey *key) { AvahiQueryJob *qj; assert(s); assert(key); for (qj = s->jobs; qj; qj = qj->jobs_next) { assert(!qj->done); if (avahi_key_equal(qj->key, key)) return qj; } return NULL; }
static AvahiSRBLookup *lookup_find( AvahiSRecordBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiLookupFlags flags, AvahiKey *key) { AvahiSRBLookup *l; assert(b); for (l = b->lookups; l; l = l->lookups_next) { if ((l->interface == AVAHI_IF_UNSPEC || l->interface == interface) && (l->interface == AVAHI_PROTO_UNSPEC || l->protocol == protocol) && l->flags == flags && avahi_key_equal(l->key, key)) return l; } return NULL; }
static AvahiQueryJob* find_history_job(AvahiQueryScheduler *s, AvahiKey *key) { AvahiQueryJob *qj; assert(s); assert(key); for (qj = s->history; qj; qj = qj->jobs_next) { assert(qj->done); if (avahi_key_equal(qj->key, key)) { /* Check whether this entry is outdated */ if (avahi_age(&qj->delivery) > AVAHI_QUERY_HISTORY_MSEC*1000) { /* it is outdated, so let's remove it */ job_free(s, qj); return NULL; } return qj; } } return NULL; }
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); }