summaryrefslogtreecommitdiffstats
path: root/avahi-core/server.c
diff options
context:
space:
mode:
Diffstat (limited to 'avahi-core/server.c')
-rw-r--r--avahi-core/server.c114
1 files changed, 83 insertions, 31 deletions
diff --git a/avahi-core/server.c b/avahi-core/server.c
index 6366dd8..31cbecc 100644
--- a/avahi-core/server.c
+++ b/avahi-core/server.c
@@ -102,38 +102,51 @@ static void cleanup_dead(AvahiServer *s) {
}
}
-static void add_aux_records(AvahiServer *s, AvahiInterface *i, const gchar *name, guint16 type, gboolean unicast_response) {
+static void enum_aux_records(AvahiServer *s, AvahiInterface *i, const gchar *name, guint16 type, void (*callback)(AvahiServer *s, AvahiRecord *r, gboolean flush_cache, gpointer userdata), gpointer userdata) {
AvahiKey *k;
+ AvahiEntry *e;
g_assert(s);
g_assert(i);
g_assert(name);
+ g_assert(callback);
+
+ g_assert(type != AVAHI_DNS_TYPE_ANY);
k = avahi_key_new(name, AVAHI_DNS_CLASS_IN, type);
- avahi_server_prepare_matching_responses(s, i, k, unicast_response);
+
+ for (e = g_hash_table_lookup(s->entries_by_key, k); e; e = e->by_key_next)
+ if (!e->dead && avahi_entry_registered(s, e, i))
+ callback(s, e->record, e->flags & AVAHI_ENTRY_UNIQUE, userdata);
+
avahi_key_unref(k);
}
-void avahi_server_prepare_response(AvahiServer *s, AvahiInterface *i, AvahiEntry *e, gboolean unicast_response) {
+void avahi_server_enumerate_aux_records(AvahiServer *s, AvahiInterface *i, AvahiRecord *r, void (*callback)(AvahiServer *s, AvahiRecord *r, gboolean flush_cache, gpointer userdata), gpointer userdata) {
g_assert(s);
g_assert(i);
- g_assert(e);
-
- /* Append a record to a packet and all the records referred by it */
-
- avahi_record_list_push(s->record_list, e->record, e->flags & AVAHI_ENTRY_UNIQUE, unicast_response);
+ g_assert(r);
+ g_assert(callback);
- if (e->record->key->class == AVAHI_DNS_CLASS_IN) {
- if (e->record->key->type == AVAHI_DNS_TYPE_PTR) {
- add_aux_records(s, i, e->record->data.ptr.name, AVAHI_DNS_TYPE_SRV, unicast_response);
- add_aux_records(s, i, e->record->data.ptr.name, AVAHI_DNS_TYPE_TXT, unicast_response);
- } else if (e->record->key->type == AVAHI_DNS_TYPE_SRV) {
- add_aux_records(s, i, e->record->data.srv.name, AVAHI_DNS_TYPE_A, unicast_response);
- add_aux_records(s, i, e->record->data.srv.name, AVAHI_DNS_TYPE_AAAA, unicast_response);
+ if (r->key->class == AVAHI_DNS_CLASS_IN) {
+ if (r->key->type == AVAHI_DNS_TYPE_PTR) {
+ enum_aux_records(s, i, r->data.ptr.name, AVAHI_DNS_TYPE_SRV, callback, userdata);
+ enum_aux_records(s, i, r->data.ptr.name, AVAHI_DNS_TYPE_TXT, callback, userdata);
+ } else if (r->key->type == AVAHI_DNS_TYPE_SRV) {
+ enum_aux_records(s, i, r->data.srv.name, AVAHI_DNS_TYPE_A, callback, userdata);
+ enum_aux_records(s, i, r->data.srv.name, AVAHI_DNS_TYPE_AAAA, callback, userdata);
}
}
}
+void avahi_server_prepare_response(AvahiServer *s, AvahiInterface *i, AvahiEntry *e, gboolean unicast_response, gboolean auxiliary) {
+ g_assert(s);
+ g_assert(i);
+ g_assert(e);
+
+ avahi_record_list_push(s->record_list, e->record, e->flags & AVAHI_ENTRY_UNIQUE, unicast_response, auxiliary);
+}
+
void avahi_server_prepare_matching_responses(AvahiServer *s, AvahiInterface *i, AvahiKey *k, gboolean unicast_response) {
AvahiEntry *e;
gchar *txt;
@@ -151,7 +164,7 @@ void avahi_server_prepare_matching_responses(AvahiServer *s, AvahiInterface *i,
for (e = s->entries; e; e = e->entries_next)
if (!e->dead && avahi_key_pattern_match(k, e->record->key) && avahi_entry_registered(s, e, i))
- avahi_server_prepare_response(s, i, e, unicast_response);
+ avahi_server_prepare_response(s, i, e, unicast_response, FALSE);
} else {
@@ -159,7 +172,7 @@ void avahi_server_prepare_matching_responses(AvahiServer *s, AvahiInterface *i,
for (e = g_hash_table_lookup(s->entries_by_key, k); e; e = e->by_key_next)
if (!e->dead && avahi_entry_registered(s, e, i))
- avahi_server_prepare_response(s, i, e, unicast_response);
+ avahi_server_prepare_response(s, i, e, unicast_response, FALSE);
}
}
@@ -264,7 +277,7 @@ static gboolean handle_conflict(AvahiServer *s, AvahiInterface *i, AvahiRecord *
if (record->ttl <= e->record->ttl/2) {
/* Refresh */
g_message("Recieved record with bad TTL [%s]. Refreshing.", t);
- avahi_interface_post_response(i, e->record, FALSE, TRUE, NULL);
+ avahi_interface_post_response(i, e->record, FALSE, NULL, TRUE);
valid = FALSE;
}
@@ -312,6 +325,23 @@ static gboolean handle_conflict(AvahiServer *s, AvahiInterface *i, AvahiRecord *
return valid;
}
+static void append_aux_callback(AvahiServer *s, AvahiRecord *r, gboolean flush_cache, gpointer userdata) {
+ gboolean *unicast_response = userdata;
+
+ g_assert(s);
+ g_assert(r);
+ g_assert(unicast_response);
+
+ avahi_record_list_push(s->record_list, r, flush_cache, *unicast_response, TRUE);
+}
+
+static void append_aux_records_to_list(AvahiServer *s, AvahiInterface *i, AvahiRecord *r, gboolean unicast_response) {
+ g_assert(s);
+ g_assert(r);
+
+ avahi_server_enumerate_aux_records(s, i, r, append_aux_callback, &unicast_response);
+}
+
void avahi_server_generate_response(AvahiServer *s, AvahiInterface *i, AvahiDnsPacket *p, const AvahiAddress *a, guint16 port, gboolean legacy_unicast) {
g_assert(s);
@@ -324,7 +354,9 @@ void avahi_server_generate_response(AvahiServer *s, AvahiInterface *i, AvahiDnsP
reply = avahi_dns_packet_new_reply(p, 512 /* unicast DNS maximum packet size is 512 */ , TRUE, TRUE);
- while ((r = avahi_record_list_pop(s->record_list, NULL, NULL))) {
+ while ((r = avahi_record_list_next(s->record_list, NULL, NULL, NULL))) {
+
+ append_aux_records_to_list(s, i, r, FALSE);
if (avahi_dns_packet_append_record(reply, r, FALSE, 10))
avahi_dns_packet_inc_field(reply, AVAHI_DNS_FIELD_ANCOUNT);
@@ -343,14 +375,17 @@ void avahi_server_generate_response(AvahiServer *s, AvahiInterface *i, AvahiDnsP
avahi_dns_packet_free(reply);
} else {
- gboolean unicast_response, flush_cache;
+ gboolean unicast_response, flush_cache, auxiliary;
AvahiDnsPacket *reply = NULL;
AvahiRecord *r;
- while ((r = avahi_record_list_pop(s->record_list, &flush_cache, &unicast_response))) {
+ while ((r = avahi_record_list_next(s->record_list, &flush_cache, &unicast_response, &auxiliary))) {
- if (!avahi_interface_post_response(i, r, flush_cache, FALSE, a) && unicast_response) {
-
+
+ if (!avahi_interface_post_response(i, r, flush_cache, a, flush_cache && !auxiliary) && unicast_response) {
+
+ append_aux_records_to_list(s, i, r, unicast_response);
+
/* Due to some reasons the record has not been scheduled.
* The client requested an unicast response in that
* case. Therefore we prepare such a response */
@@ -373,10 +408,25 @@ void avahi_server_generate_response(AvahiServer *s, AvahiInterface *i, AvahiDnsP
}
if (avahi_dns_packet_get_field(reply, AVAHI_DNS_FIELD_ANCOUNT) == 0) {
- gchar *t = avahi_record_to_string(r);
- g_warning("Record [%s] too large, doesn't fit in any packet!", t);
- g_free(t);
- break;
+ guint size;
+
+ /* The record is too large for one packet, so create a larger packet */
+
+ avahi_dns_packet_free(reply);
+ size = avahi_record_get_estimate_size(r) + AVAHI_DNS_PACKET_HEADER_SIZE;
+ if (size > AVAHI_DNS_PACKET_MAX_SIZE)
+ size = AVAHI_DNS_PACKET_MAX_SIZE;
+ reply = avahi_dns_packet_new_reply(p, size, FALSE, TRUE);
+
+ if (!avahi_dns_packet_append_record(reply, r, flush_cache, 0)) {
+ avahi_dns_packet_free(reply);
+
+ gchar *t = avahi_record_to_string(r);
+ g_warning("Record [%s] too large, doesn't fit in any packet!", t);
+ g_free(t);
+ break;
+ } else
+ avahi_dns_packet_inc_field(reply, AVAHI_DNS_FIELD_ANCOUNT);
}
/* Appending the record didn't succeeed, so let's send this packet, and create a new one */
@@ -395,6 +445,8 @@ void avahi_server_generate_response(AvahiServer *s, AvahiInterface *i, AvahiDnsP
avahi_dns_packet_free(reply);
}
}
+
+ avahi_record_list_flush(s->record_list);
}
static void handle_query(AvahiServer *s, AvahiDnsPacket *p, AvahiInterface *i, const AvahiAddress *a, guint16 port, gboolean legacy_unicast) {
@@ -417,9 +469,9 @@ static void handle_query(AvahiServer *s, AvahiDnsPacket *p, AvahiInterface *i, c
if (!(key = avahi_dns_packet_consume_key(p, &unicast_response))) {
g_warning("Packet too short (1)");
goto fail;
- }
+ }
- avahi_packet_scheduler_incoming_query(i->scheduler, key);
+ avahi_query_scheduler_incoming(i->query_scheduler, key);
avahi_server_prepare_matching_responses(s, i, key, unicast_response);
avahi_key_unref(key);
}
@@ -435,7 +487,7 @@ static void handle_query(AvahiServer *s, AvahiDnsPacket *p, AvahiInterface *i, c
}
if (handle_conflict(s, i, record, unique, a)) {
- avahi_packet_scheduler_incoming_known_answer(i->scheduler, record, a);
+ avahi_response_scheduler_suppress(i->response_scheduler, record, a);
avahi_record_list_drop(s->record_list, record);
}
@@ -496,7 +548,7 @@ static void handle_response(AvahiServer *s, AvahiDnsPacket *p, AvahiInterface *i
if (handle_conflict(s, i, record, cache_flush, a)) {
avahi_cache_update(i->cache, record, cache_flush, a);
- avahi_packet_scheduler_incoming_response(i->scheduler, record, cache_flush);
+ avahi_response_scheduler_incoming(i->response_scheduler, record, cache_flush);
}
}