From b8c78f5c0da93d92aa28d3ef3757e78d03141f41 Mon Sep 17 00:00:00 2001 From: Lennart Poettering Date: Tue, 3 May 2005 21:22:52 +0000 Subject: [PATCH] * correctly build probe packets * fix conflict detection * correctly handle FLUSH bit in incoming packets * drop whole group when one record conflicts * remove wrong TRUE/FALSE usage in flx_server_add_service_va() * fix wrong pass-through in switch satetement in rr.c git-svn-id: file:///home/lennart/svn/public/avahi/trunk@37 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe --- announce.c | 5 ++-- dns.c | 8 +++--- main.c | 4 +-- psched.c | 2 +- rr.c | 4 ++- server.c | 78 +++++++++++++++++++++++++++++++++++++----------------- server.h | 2 +- 7 files changed, 66 insertions(+), 37 deletions(-) diff --git a/announce.c b/announce.c index 1dae473..613d10d 100644 --- a/announce.c +++ b/announce.c @@ -49,7 +49,7 @@ void flx_entry_group_check_probed(flxEntryGroup *g, gboolean immediately) { if (g->state != FLX_ENTRY_GROUP_REGISTERING || g->n_probing > 0) return; - flx_entry_group_run_callback(g, g->state = FLX_ENTRY_GROUP_ESTABLISHED); + flx_entry_group_change_state(g, FLX_ENTRY_GROUP_ESTABLISHED); if (g->dead) return; @@ -367,11 +367,10 @@ void flx_goodbye_interface(flxServer *s, flxInterface *i, gboolean goodbye) { void flx_goodbye_entry(flxServer *s, flxEntry *e, gboolean goodbye) { g_assert(s); g_assert(e); - g_assert(!e->dead); g_message("goodbye entry: %p", e); - if (goodbye) + if (goodbye && !e->dead) flx_interface_monitor_walk(s->monitor, 0, AF_UNSPEC, send_goodbye_callback, e); while (e->announcements) diff --git a/dns.c b/dns.c index a402e29..3f50827 100644 --- a/dns.c +++ b/dns.c @@ -482,9 +482,12 @@ flxRecord* flx_dns_packet_consume_record(flxDnsPacket *p, gboolean *ret_cache_fl goto fail; /* g_message("name = %s, rdlength = %u", name, rdlength); */ + + *ret_cache_flush = !!(class & FLX_DNS_CACHE_FLUSH); + class &= ~ FLX_DNS_CACHE_FLUSH; start = flx_dns_packet_get_rptr(p); - + r = flx_record_new_full(name, class, type); switch (type) { @@ -581,9 +584,6 @@ flxRecord* flx_dns_packet_consume_record(flxDnsPacket *p, gboolean *ret_cache_fl if ((guint8*) flx_dns_packet_get_rptr(p) - (guint8*) start != rdlength) goto fail; - *ret_cache_flush = !!(class & FLX_DNS_CACHE_FLUSH); - class &= ~ FLX_DNS_CACHE_FLUSH; - r->ttl = ttl; return r; diff --git a/main.c b/main.c index 82e7090..987df22 100644 --- a/main.c +++ b/main.c @@ -60,8 +60,8 @@ int main(int argc, char *argv[]) { loop = g_main_loop_new(NULL, FALSE); - g_timeout_add(1000*20, dump_timeout, flx); - g_timeout_add(1000*30, quit_timeout, loop); + /* g_timeout_add(1000*20, dump_timeout, flx); */ +/* g_timeout_add(1000*30, quit_timeout, loop); */ g_main_loop_run(loop); g_main_loop_unref(loop); diff --git a/psched.c b/psched.c index 22474f3..6f148ca 100644 --- a/psched.c +++ b/psched.c @@ -615,7 +615,7 @@ static guint8* packet_add_probe_query(flxPacketScheduler *s, flxDnsPacket *p, fl continue; /* Does the record match the probe? */ - if (k->class != pj->record->key->class || flx_domain_equal(k->name, pj->record->key->name)) + if (k->class != pj->record->key->class || !flx_domain_equal(k->name, pj->record->key->name)) continue; /* This job wouldn't fit in */ diff --git a/rr.c b/rr.c index 49a60b4..a71e2a0 100644 --- a/rr.c +++ b/rr.c @@ -477,7 +477,9 @@ gint flx_record_lexicographical_compare(flxRecord *a, flxRecord *b) { if ((r = uint16_cmp(a->data.srv.priority, b->data.srv.priority)) != 0 || (r = uint16_cmp(a->data.srv.weight, b->data.srv.weight)) != 0 || (r = uint16_cmp(a->data.srv.port, b->data.srv.port)) != 0) - return lexicographical_domain_cmp(a->data.srv.name, b->data.srv.name); + r = lexicographical_domain_cmp(a->data.srv.name, b->data.srv.name); + + return r; } case FLX_DNS_TYPE_HINFO: { diff --git a/server.c b/server.c index 55776a0..f43f414 100644 --- a/server.c +++ b/server.c @@ -112,13 +112,23 @@ static void withdraw_entry(flxServer *s, flxEntry *e) { g_assert(s); g_assert(e); - e->dead = TRUE; + + if (e->group) { + flxEntry *k; + + for (k = e->group->entries; k; k = k->by_group_next) { + flx_goodbye_entry(s, k, FALSE); + k->dead = TRUE; + } + + flx_entry_group_change_state(e->group, FLX_ENTRY_GROUP_COLLISION); + } else { + flx_goodbye_entry(s, e, FALSE); + e->dead = TRUE; + } + s->need_entry_cleanup = TRUE; - flx_goodbye_entry(s, e, FALSE); - - if (e->group) - flx_entry_group_run_callback(e->group, FLX_ENTRY_GROUP_COLLISION); } static void incoming_probe(flxServer *s, flxRecord *record, flxInterface *i) { @@ -131,6 +141,9 @@ static void incoming_probe(flxServer *s, flxRecord *record, flxInterface *i) { t = flx_record_to_string(record); + g_message("PROBE! PROBE! PROBE! [%s]", t); + + for (e = g_hash_table_lookup(s->entries_by_key, record->key); e; e = n) { n = e->by_key_next; @@ -138,11 +151,12 @@ static void incoming_probe(flxServer *s, flxRecord *record, flxInterface *i) { continue; if (flx_entry_registering(s, e, i)) { + gint cmp; - if (flx_record_lexicographical_compare(record, e->record) > 0) { + if ((cmp = flx_record_lexicographical_compare(record, e->record)) > 0) { withdraw_entry(s, e); g_message("Recieved conflicting probe [%s]. Local host lost. Withdrawing.", t); - } else + } else if (cmp < 0) g_message("Recieved conflicting probe [%s]. Local host won.", t); } } @@ -202,7 +216,7 @@ static void handle_query(flxServer *s, flxDnsPacket *p, flxInterface *i, const f } } -static gboolean handle_conflict(flxServer *s, flxInterface *i, flxRecord *record, const flxAddress *a) { +static gboolean handle_conflict(flxServer *s, flxInterface *i, flxRecord *record, gboolean unique, const flxAddress *a) { gboolean valid = TRUE; flxEntry *e, *n; gchar *t; @@ -213,6 +227,8 @@ static gboolean handle_conflict(flxServer *s, flxInterface *i, flxRecord *record t = flx_record_to_string(record); + g_message("CHECKING FOR CONFLICT: [%s]", t); + for (e = g_hash_table_lookup(s->entries_by_key, record->key); e; e = n) { n = e->by_key_next; @@ -224,17 +240,20 @@ static gboolean handle_conflict(flxServer *s, flxInterface *i, flxRecord *record gboolean equal = flx_record_equal_no_ttl(record, e->record); /* Check whether there is a unique record conflict */ - if (!equal && (e->flags & FLX_ENTRY_UNIQUE)) { + if (!equal && ((e->flags & FLX_ENTRY_UNIQUE) || unique)) { + gint cmp; /* The lexicographically later data wins. */ - if (flx_record_lexicographical_compare(record, e->record) > 0) { - withdraw_entry(s, e); + if ((cmp = flx_record_lexicographical_compare(record, e->record)) > 0) { g_message("Recieved conflicting record [%s]. Local host lost. Withdrawing.", t); - } else { + withdraw_entry(s, e); + } else if (cmp < 0) { /* Tell the other host that our entry is lexicographically later */ + + g_message("Recieved conflicting record [%s]. Local host won. Refreshing.", t); + valid = FALSE; flx_interface_post_response(i, a, e->record, e->flags & FLX_ENTRY_UNIQUE, TRUE); - g_message("Recieved conflicting record [%s]. Local host won. Refreshing.", t); } /* Check wheter there is a TTL conflict */ @@ -244,6 +263,18 @@ static gboolean handle_conflict(flxServer *s, flxInterface *i, flxRecord *record flx_interface_post_response(i, a, e->record, e->flags & FLX_ENTRY_UNIQUE, TRUE); g_message("Recieved record with bad TTL [%s]. Refreshing.", t); } + + } else if (flx_entry_registering(s, e, i)) { + + if (!flx_record_equal_no_ttl(record, e->record) && ((e->flags & FLX_ENTRY_UNIQUE) || unique)) { + + /* We are currently registering a matching record, but + * someone else already claimed it, so let's + * withdraw */ + + g_message("Recieved conflicting record [%s] with local record to be. Withdrawing.", t); + withdraw_entry(s, e); + } } } @@ -276,7 +307,7 @@ static void handle_response(flxServer *s, flxDnsPacket *p, flxInterface *i, cons g_message("Handling response: %s", txt = flx_record_to_string(record)); g_free(txt); - if (handle_conflict(s, i, record, a)) { + if (handle_conflict(s, i, record, cache_flush, a)) { flx_cache_update(i->cache, record, cache_flush, a); flx_packet_scheduler_incoming_response(i->scheduler, record); } @@ -779,20 +810,20 @@ void flx_server_add_service_va( snprintf(ptr_name, sizeof(ptr_name), "%s.%s", type, domain); snprintf(svc_name, sizeof(svc_name), "%s.%s.%s", ename, type, domain); - flx_server_add_ptr(s, g, interface, protocol, FALSE, ptr_name, svc_name); + flx_server_add_ptr(s, g, interface, protocol, FLX_ENTRY_NULL, ptr_name, svc_name); r = flx_record_new_full(svc_name, FLX_DNS_CLASS_IN, FLX_DNS_TYPE_SRV); r->data.srv.priority = 0; r->data.srv.weight = 0; r->data.srv.port = port; r->data.srv.name = flx_normalize_name(host); - flx_server_add(s, g, interface, protocol, TRUE, r); + flx_server_add(s, g, interface, protocol, FLX_ENTRY_UNIQUE, r); flx_record_unref(r); - flx_server_add_text_va(s, g, interface, protocol, FALSE, svc_name, va); + flx_server_add_text_va(s, g, interface, protocol, FLX_ENTRY_UNIQUE, svc_name, va); snprintf(enum_ptr, sizeof(enum_ptr), "_services._dns-sd._udp.%s", domain); - flx_server_add_ptr(s, g, interface, protocol, FALSE, enum_ptr, ptr_name); + flx_server_add_ptr(s, g, interface, protocol, FLX_ENTRY_NULL, enum_ptr, ptr_name); } void flx_server_add_service( @@ -862,18 +893,15 @@ void flx_server_post_response(flxServer *s, gint interface, guchar protocol, flx flx_interface_monitor_walk(s->monitor, interface, protocol, post_response_callback, &tmpdata); } -void flx_entry_group_run_callback(flxEntryGroup *g, flxEntryGroupState state) { +void flx_entry_group_change_state(flxEntryGroup *g, flxEntryGroupState state) { g_assert(g); + g->state = state; + if (g->callback) { g->callback(g->server, g, state, g->userdata); return; } - - if (state == FLX_ENTRY_GROUP_COLLISION) - flx_entry_group_free(g); - - /* Ignore the rest */ } flxEntryGroup *flx_entry_group_new(flxServer *s, flxEntryGroupCallback callback, gpointer userdata) { @@ -911,7 +939,7 @@ void flx_entry_group_commit(flxEntryGroup *g) { if (g->state != FLX_ENTRY_GROUP_UNCOMMITED) return; - flx_entry_group_run_callback(g, g->state = FLX_ENTRY_GROUP_REGISTERING); + flx_entry_group_change_state(g, FLX_ENTRY_GROUP_REGISTERING); flx_announce_group(g->server, g); flx_entry_group_check_probed(g, FALSE); } diff --git a/server.h b/server.h index 810fd53..3960ee5 100644 --- a/server.h +++ b/server.h @@ -72,7 +72,7 @@ gboolean flx_server_entry_match_interface(flxEntry *e, flxInterface *i); void flx_server_post_query(flxServer *s, gint interface, guchar protocol, flxKey *key); void flx_server_post_response(flxServer *s, gint interface, guchar protocol, flxRecord *record, gboolean flush_cache); -void flx_entry_group_run_callback(flxEntryGroup *g, flxEntryGroupState state); +void flx_entry_group_change_state(flxEntryGroup *g, flxEntryGroupState state); gboolean flx_entry_commited(flxEntry *e); -- 2.39.5