avahi is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
avahi is free software; you can redistribute it and/or modify it
under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 of the
License, or (at your option) any later version.
avahi is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
Public License for more details.
avahi is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with avahi; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
You should have received a copy of the GNU Lesser General Public
License along with avahi; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
AVAHI_LLIST_FIELDS(AvahiWideAreaCacheEntry, by_key);
AVAHI_LLIST_FIELDS(AvahiWideAreaCacheEntry, cache);
};
AVAHI_LLIST_FIELDS(AvahiWideAreaCacheEntry, by_key);
AVAHI_LLIST_FIELDS(AvahiWideAreaCacheEntry, cache);
};
uint32_t id; /* effectively just an uint16_t, but we need it as an index for a hash table */
AvahiTimeEvent *time_event;
AvahiKey *key, *cname_key;
uint32_t id; /* effectively just an uint16_t, but we need it as an index for a hash table */
AvahiTimeEvent *time_event;
AvahiKey *key, *cname_key;
/* Cache */
AVAHI_LLIST_HEAD(AvahiWideAreaCacheEntry, cache);
AvahiHashmap *cache_by_key;
/* Cache */
AVAHI_LLIST_HEAD(AvahiWideAreaCacheEntry, cache);
AvahiHashmap *cache_by_key;
return avahi_send_dns_packet_ipv4(l->engine->fd_ipv4, AVAHI_IF_UNSPEC, p, NULL, &a->data.ipv4, AVAHI_DNS_PORT);
return avahi_send_dns_packet_ipv4(l->engine->fd_ipv4, AVAHI_IF_UNSPEC, p, NULL, &a->data.ipv4, AVAHI_DNS_PORT);
return avahi_send_dns_packet_ipv6(l->engine->fd_ipv6, AVAHI_IF_UNSPEC, p, NULL, &a->data.ipv6, AVAHI_DNS_PORT);
}
}
return avahi_send_dns_packet_ipv6(l->engine->fd_ipv6, AVAHI_IF_UNSPEC, p, NULL, &a->data.ipv6, AVAHI_DNS_PORT);
}
}
if (l->n_send >= 6) {
avahi_log_warn(__FILE__": Query timed out.");
avahi_server_set_errno(l->engine->server, AVAHI_ERR_TIMEOUT);
if (l->n_send >= 6) {
avahi_log_warn(__FILE__": Query timed out.");
avahi_server_set_errno(l->engine->server, AVAHI_ERR_TIMEOUT);
/* We keep the packet around in case we need to repeat our query */
l->packet = avahi_dns_packet_new(0);
/* We keep the packet around in case we need to repeat our query */
l->packet = avahi_dns_packet_new(0);
avahi_dns_packet_set_field(l->packet, AVAHI_DNS_FIELD_QDCOUNT, 1);
if (send_to_dns_server(l, l->packet) < 0) {
avahi_dns_packet_set_field(l->packet, AVAHI_DNS_FIELD_QDCOUNT, 1);
if (send_to_dns_server(l, l->packet) < 0) {
l->time_event = avahi_time_event_new(e->server->time_event_queue, avahi_elapse_time(&tv, 500, 0), sender_timeout_callback, l);
avahi_hashmap_insert(e->lookups_by_id, &l->id, l);
l->time_event = avahi_time_event_new(e->server->time_event_queue, avahi_elapse_time(&tv, 500, 0), sender_timeout_callback, l);
avahi_hashmap_insert(e->lookups_by_id, &l->id, l);
avahi_hashmap_replace(e->lookups_by_key, avahi_key_ref(l->key), t);
AVAHI_LLIST_PREPEND(AvahiWideAreaLookup, lookups, e->lookups, l);
avahi_hashmap_replace(e->lookups_by_key, avahi_key_ref(l->key), t);
AVAHI_LLIST_PREPEND(AvahiWideAreaLookup, lookups, e->lookups, l);
avahi_hashmap_remove(l->engine->lookups_by_key, l->key);
AVAHI_LLIST_REMOVE(AvahiWideAreaLookup, lookups, l->engine->lookups, l);
avahi_hashmap_remove(l->engine->lookups_by_key, l->key);
AVAHI_LLIST_REMOVE(AvahiWideAreaLookup, lookups, l->engine->lookups, l);
avahi_hashmap_remove(l->engine->lookups_by_id, &l->id);
avahi_dns_packet_free(l->packet);
avahi_hashmap_remove(l->engine->lookups_by_id, &l->id);
avahi_dns_packet_free(l->packet);
static void expiry_event(AvahiTimeEvent *te, void *userdata) {
AvahiWideAreaCacheEntry *e = userdata;
static void expiry_event(AvahiTimeEvent *te, void *userdata) {
AvahiWideAreaCacheEntry *e = userdata;
static AvahiWideAreaCacheEntry* find_record_in_cache(AvahiWideAreaLookupEngine *e, AvahiRecord *r) {
AvahiWideAreaCacheEntry *c;
static AvahiWideAreaCacheEntry* find_record_in_cache(AvahiWideAreaLookupEngine *e, AvahiRecord *r) {
AvahiWideAreaCacheEntry *c;
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;
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);
}
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 */
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 */
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);
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);
static void add_to_cache(AvahiWideAreaLookupEngine *e, AvahiRecord *r) {
AvahiWideAreaCacheEntry *c;
int is_new;
static void add_to_cache(AvahiWideAreaLookupEngine *e, AvahiRecord *r) {
AvahiWideAreaCacheEntry *c;
int is_new;
if (e->cache_n_entries >= CACHE_ENTRIES_MAX)
/* Eventually we should improve the caching algorithm here */
goto finish;
if (e->cache_n_entries >= CACHE_ENTRIES_MAX)
/* Eventually we should improve the caching algorithm here */
goto finish;
gettimeofday(&c->timestamp, NULL);
c->expiry = c->timestamp;
avahi_timeval_add(&c->expiry, r->ttl * 1000000);
gettimeofday(&c->timestamp, NULL);
c->expiry = c->timestamp;
avahi_timeval_add(&c->expiry, r->ttl * 1000000);
c->time_event = avahi_time_event_new(e->server->time_event_queue, &c->expiry, expiry_event, c);
finish:
c->time_event = avahi_time_event_new(e->server->time_event_queue, &c->expiry, expiry_event, c);
finish:
/* Skip over the question */
for (i = (int) avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_QDCOUNT); i > 0; i--) {
AvahiKey *k;
/* Skip over the question */
for (i = (int) avahi_dns_packet_get_field(p, AVAHI_DNS_FIELD_QDCOUNT); i > 0; i--) {
AvahiKey *k;
avahi_server_set_errno(e->server, AVAHI_ERR_INVALID_PACKET);
final_event = AVAHI_BROWSER_FAILURE;
goto finish;
avahi_server_set_errno(e->server, AVAHI_ERR_INVALID_PACKET);
final_event = AVAHI_BROWSER_FAILURE;
goto finish;
avahi_server_set_errno(e->server, AVAHI_ERR_INVALID_PACKET);
final_event = AVAHI_BROWSER_FAILURE;
goto finish;
avahi_server_set_errno(e->server, AVAHI_ERR_INVALID_PACKET);
final_event = AVAHI_BROWSER_FAILURE;
goto finish;
if (l && !l->dead) {
if (l->callback)
l->callback(e, final_event, AVAHI_LOOKUP_RESULT_WIDE_AREA, NULL, l->userdata);
if (l && !l->dead) {
if (l->callback)
l->callback(e, final_event, AVAHI_LOOKUP_RESULT_WIDE_AREA, NULL, l->userdata);
static void socket_event(AVAHI_GCC_UNUSED AvahiWatch *w, int fd, AVAHI_GCC_UNUSED AvahiWatchEvent events, void *userdata) {
AvahiWideAreaLookupEngine *e = userdata;
AvahiDnsPacket *p = NULL;
static void socket_event(AVAHI_GCC_UNUSED AvahiWatch *w, int fd, AVAHI_GCC_UNUSED AvahiWatchEvent events, void *userdata) {
AvahiWideAreaLookupEngine *e = userdata;
AvahiDnsPacket *p = NULL;
if (fd == e->fd_ipv4)
p = avahi_recv_dns_packet_ipv4(e->fd_ipv4, NULL, NULL, NULL, NULL, NULL);
else {
if (fd == e->fd_ipv4)
p = avahi_recv_dns_packet_ipv4(e->fd_ipv4, NULL, NULL, NULL, NULL, NULL);
else {
AvahiWideAreaLookupEngine *avahi_wide_area_engine_new(AvahiServer *s) {
AvahiWideAreaLookupEngine *e;
AvahiWideAreaLookupEngine *avahi_wide_area_engine_new(AvahiServer *s) {
AvahiWideAreaLookupEngine *e;
if (e->fd_ipv4 >= 0)
e->watch_ipv4 = s->poll_api->watch_new(e->server->poll_api, e->fd_ipv4, AVAHI_WATCH_IN, socket_event, e);
if (e->fd_ipv6 >= 0)
if (e->fd_ipv4 >= 0)
e->watch_ipv4 = s->poll_api->watch_new(e->server->poll_api, e->fd_ipv4, AVAHI_WATCH_IN, socket_event, e);
if (e->fd_ipv6 >= 0)
avahi_hashmap_free(e->cache_by_key);
avahi_hashmap_free(e->lookups_by_id);
avahi_hashmap_free(e->lookups_by_key);
avahi_hashmap_free(e->cache_by_key);
avahi_hashmap_free(e->lookups_by_id);
avahi_hashmap_free(e->lookups_by_key);
if ((a->proto == AVAHI_PROTO_INET && e->fd_ipv4 >= 0) || (a->proto == AVAHI_PROTO_INET6 && e->fd_ipv6 >= 0))
e->dns_servers[e->n_dns_servers++] = *a;
} else {
assert(n == 0);
e->n_dns_servers = 0;
}
if ((a->proto == AVAHI_PROTO_INET && e->fd_ipv4 >= 0) || (a->proto == AVAHI_PROTO_INET6 && e->fd_ipv6 >= 0))
e->dns_servers[e->n_dns_servers++] = *a;
} else {
assert(n == 0);
e->n_dns_servers = 0;
}
void avahi_wide_area_cache_dump(AvahiWideAreaLookupEngine *e, AvahiDumpCallback callback, void* userdata) {
AvahiWideAreaCacheEntry *c;
void avahi_wide_area_cache_dump(AvahiWideAreaLookupEngine *e, AvahiDumpCallback callback, void* userdata) {
AvahiWideAreaCacheEntry *c;
callback(e, AVAHI_BROWSER_NEW, AVAHI_LOOKUP_RESULT_WIDE_AREA|AVAHI_LOOKUP_RESULT_CACHED, c->record, userdata);
n++;
}
callback(e, AVAHI_BROWSER_NEW, AVAHI_LOOKUP_RESULT_WIDE_AREA|AVAHI_LOOKUP_RESULT_CACHED, c->record, userdata);
n++;
}