diff options
| author | Lennart Poettering <lennart@poettering.net> | 2005-08-21 21:15:47 +0000 | 
|---|---|---|
| committer | Lennart Poettering <lennart@poettering.net> | 2005-08-21 21:15:47 +0000 | 
| commit | 15aaf28f0345ed6998ef6eae921c7750c4ce26f9 (patch) | |
| tree | 06515dc742be8eca223bf6f82d85528d3f6bb499 | |
| parent | 041302604374ae779d4d6a1e83b5f738c7be00d0 (diff) | |
* Beef up host name and address resolvers to notify about RR changes (Similar to what already is available for the service resolver)
git-svn-id: file:///home/lennart/svn/public/avahi/trunk@388 941a03a8-eaeb-0310-b9a0-b1bbd8fe43fe
| -rw-r--r-- | avahi-core/core.h | 4 | ||||
| -rw-r--r-- | avahi-core/resolve-address.c | 99 | ||||
| -rw-r--r-- | avahi-core/resolve-host-name.c | 120 | ||||
| -rw-r--r-- | avahi-core/resolve-service.c | 2 | 
4 files changed, 165 insertions, 60 deletions
| diff --git a/avahi-core/core.h b/avahi-core/core.h index 2f55d73..1cf35fc 100644 --- a/avahi-core/core.h +++ b/avahi-core/core.h @@ -506,7 +506,7 @@ typedef void (*AvahiSServiceResolverCallback)(      AvahiSServiceResolver *r,      AvahiIfIndex interface,      AvahiProtocol protocol, -    AvahiResolverEvent event, +    AvahiResolverEvent event,  /**< Is AVAHI_RESOLVER_FOUND when the service was resolved successfully, and everytime it changes. Is AVAHI_RESOLVER_TIMOUT when the service failed to resolve or disappeared. */      const char *name,       /**< Service name */      const char *type,       /**< Service Type */      const char *domain, @@ -516,7 +516,7 @@ typedef void (*AvahiSServiceResolverCallback)(      AvahiStringList *txt,    /**< TXT record data */      void* userdata); -/** Create a new AvahiSServiceResolver object */ +/** Create a new AvahiSServiceResolver object. The specified callback function will be called with the resolved service data. */  AvahiSServiceResolver *avahi_s_service_resolver_new(      AvahiServer *server,      AvahiIfIndex interface, diff --git a/avahi-core/resolve-address.c b/avahi-core/resolve-address.c index 07902e6..fbf50ff 100644 --- a/avahi-core/resolve-address.c +++ b/avahi-core/resolve-address.c @@ -29,6 +29,8 @@  #include "browse.h" +#define TIMEOUT_MSEC 1000 +  struct AvahiSAddressResolver {      AvahiServer *server;      AvahiAddress address; @@ -38,54 +40,102 @@ struct AvahiSAddressResolver {      AvahiSAddressResolverCallback callback;      void* userdata; +    AvahiRecord *ptr_record; +    AvahiIfIndex interface; +    AvahiProtocol protocol; +      AvahiTimeEvent *time_event;      AVAHI_LLIST_FIELDS(AvahiSAddressResolver, resolver);  }; -static void finish(AvahiSAddressResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, AvahiRecord *record) { +static void finish(AvahiSAddressResolver *r, AvahiResolverEvent event) {      assert(r); -    avahi_s_record_browser_free(r->record_browser); -    r->record_browser = NULL; -      if (r->time_event) {          avahi_time_event_free(r->time_event);          r->time_event = NULL;      } -    r->callback(r, interface, protocol, event, &r->address, record ? record->data.ptr.name : NULL, r->userdata); +    if (event == AVAHI_RESOLVER_TIMEOUT) +        r->callback(r, r->interface, r->protocol, AVAHI_RESOLVER_TIMEOUT, &r->address, NULL, r->userdata); +    else { + +        assert(event == AVAHI_RESOLVER_FOUND); +        assert(r->ptr_record); + +        r->callback(r, r->interface, r->protocol, AVAHI_RESOLVER_FOUND, &r->address, r->ptr_record->data.ptr.name, r->userdata); +    }  } -static void record_browser_callback(AvahiSRecordBrowser*rr, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, AvahiRecord *record, void* userdata) { +static void time_event_callback(AvahiTimeEvent *e, void *userdata) {      AvahiSAddressResolver *r = userdata; +     +    assert(e); +    assert(r); -    assert(rr); -    assert(record); +    finish(r, AVAHI_RESOLVER_TIMEOUT); +} + +static void start_timeout(AvahiSAddressResolver *r) { +    struct timeval tv;      assert(r); -    if (!(event == AVAHI_BROWSER_NEW)) +    if (r->time_event)          return; -    assert(record->key->type == AVAHI_DNS_TYPE_PTR); - -    finish(r, interface, protocol, AVAHI_RESOLVER_FOUND, record); +    avahi_elapse_time(&tv, TIMEOUT_MSEC, 0); +    r->time_event = avahi_time_event_new(r->server->time_event_queue, &tv, time_event_callback, r);  } -static void time_event_callback(AvahiTimeEvent *e, void *userdata) { +static void record_browser_callback(AvahiSRecordBrowser*rr, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, AvahiRecord *record, void* userdata) {      AvahiSAddressResolver *r = userdata; -     -    assert(e); + +    assert(rr); +    assert(record);      assert(r); -    finish(r, -1, AVAHI_PROTO_UNSPEC, AVAHI_RESOLVER_TIMEOUT, NULL); +    assert(record->key->type == AVAHI_DNS_TYPE_PTR); + +    if (event == AVAHI_BROWSER_NEW) { + +        if (r->interface > 0 && interface != r->interface) +            return; +         +        if (r->protocol != AVAHI_PROTO_UNSPEC && protocol != r->protocol) +            return; +         +        if (r->interface <= 0) +            r->interface = interface; +         +        if (r->protocol == AVAHI_PROTO_UNSPEC) +            r->protocol = protocol; +         +        if (!r->ptr_record) { +            r->ptr_record = avahi_record_ref(record); + +            finish(r, AVAHI_RESOLVER_FOUND); +        } + +    } else { +         +        assert(event == AVAHI_BROWSER_REMOVE); +         +        if (avahi_record_equal_no_ttl(record, r->ptr_record)) { +            avahi_record_unref(r->ptr_record); +            r->ptr_record = NULL; + +            /** Look for a replacement */ +            avahi_s_record_browser_restart(r->record_browser); +            start_timeout(r); +        } +    }  }  AvahiSAddressResolver *avahi_s_address_resolver_new(AvahiServer *server, AvahiIfIndex interface, AvahiProtocol protocol, const AvahiAddress *address, AvahiSAddressResolverCallback callback, void* userdata) {      AvahiSAddressResolver *r;      AvahiKey *k;      char *n; -    struct timeval tv;      assert(server);      assert(address); @@ -121,17 +171,15 @@ AvahiSAddressResolver *avahi_s_address_resolver_new(AvahiServer *server, AvahiIf      r->address = *address;      r->callback = callback;      r->userdata = userdata; +    r->ptr_record = NULL; +    r->interface = interface; +    r->protocol = protocol;      r->record_browser = NULL;      AVAHI_LLIST_PREPEND(AvahiSAddressResolver, resolver, server->address_resolvers, r); -    avahi_elapse_time(&tv, 1000, 0); -    if (!(r->time_event = avahi_time_event_new(server->time_event_queue, &tv, time_event_callback, r))) { -        avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY); -        avahi_s_address_resolver_free(r); -        avahi_key_unref(k); -        return NULL; -    } +    r->time_event = NULL; +    start_timeout(r);      r->record_browser = avahi_s_record_browser_new(server, interface, protocol, k, record_browser_callback, r);      avahi_key_unref(k); @@ -154,6 +202,9 @@ void avahi_s_address_resolver_free(AvahiSAddressResolver *r) {      if (r->time_event)          avahi_time_event_free(r->time_event); + +    if (r->ptr_record) +        avahi_record_unref(r->ptr_record);      avahi_free(r);  } diff --git a/avahi-core/resolve-host-name.c b/avahi-core/resolve-host-name.c index 82b0ab4..ae7ef78 100644 --- a/avahi-core/resolve-host-name.c +++ b/avahi-core/resolve-host-name.c @@ -23,6 +23,8 @@  #include <config.h>  #endif +#include <stdlib.h> +  #include <avahi-common/domain.h>  #include <avahi-common/timeval.h>  #include <avahi-common/malloc.h> @@ -31,6 +33,8 @@  #include "browse.h"  #include "log.h" +#define TIMEOUT_MSEC 1000 +  struct AvahiSHostNameResolver {      AvahiServer *server;      char *host_name; @@ -41,49 +45,68 @@ struct AvahiSHostNameResolver {      AvahiSHostNameResolverCallback callback;      void* userdata; +    AvahiRecord *address_record; +    AvahiIfIndex interface; +    AvahiProtocol protocol; +      AvahiTimeEvent *time_event;      AVAHI_LLIST_FIELDS(AvahiSHostNameResolver, resolver);  }; -static void finish(AvahiSHostNameResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, AvahiRecord *record) { -    AvahiAddress a; -     +static void finish(AvahiSHostNameResolver *r, AvahiResolverEvent event) {      assert(r); -    if (r->record_browser_a) { -        avahi_s_record_browser_free(r->record_browser_a); -        r->record_browser_a = NULL; -    } - -    if (r->record_browser_aaaa) { -        avahi_s_record_browser_free(r->record_browser_aaaa); -        r->record_browser_aaaa = NULL; -    } -      if (r->time_event) {          avahi_time_event_free(r->time_event);          r->time_event = NULL;      } -    if (record) { -        switch (record->key->type) { +    if (event == AVAHI_RESOLVER_TIMEOUT) +        r->callback(r, r->interface, r->protocol, AVAHI_RESOLVER_TIMEOUT, r->host_name, NULL, r->userdata); +    else { +        AvahiAddress a; +     +        assert(event == AVAHI_RESOLVER_FOUND); +        assert(r->address_record); +     +        switch (r->address_record->key->type) {              case AVAHI_DNS_TYPE_A:                  a.family = AVAHI_PROTO_INET; -                a.data.ipv4 = record->data.a.address; +                a.data.ipv4 = r->address_record->data.a.address;                  break;              case AVAHI_DNS_TYPE_AAAA:                  a.family = AVAHI_PROTO_INET6; -                a.data.ipv6 = record->data.aaaa.address; +                a.data.ipv6 = r->address_record->data.aaaa.address;                  break;              default: -                assert(0); +                abort();          } + +        r->callback(r, r->interface, r->protocol, AVAHI_RESOLVER_FOUND, r->address_record->key->name, &a, r->userdata);      } +} + +static void time_event_callback(AvahiTimeEvent *e, void *userdata) { +    AvahiSHostNameResolver *r = userdata; +     +    assert(e); +    assert(r); -    r->callback(r, interface, protocol, event, record ? record->key->name : r->host_name, record ? &a : NULL, r->userdata); +    finish(r, AVAHI_RESOLVER_TIMEOUT); +} + +static void start_timeout(AvahiSHostNameResolver *r) { +    struct timeval tv; +    assert(r); + +    if (r->time_event) +        return; + +    avahi_elapse_time(&tv, TIMEOUT_MSEC, 0); +    r->time_event = avahi_time_event_new(r->server->time_event_queue, &tv, time_event_callback, r);  }  static void record_browser_callback(AvahiSRecordBrowser*rr, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, AvahiRecord *record, void* userdata) { @@ -93,26 +116,49 @@ static void record_browser_callback(AvahiSRecordBrowser*rr, AvahiIfIndex interfa      assert(record);      assert(r); -    if (!(event == AVAHI_BROWSER_NEW)) -        return; -          assert(record->key->type == AVAHI_DNS_TYPE_A || record->key->type == AVAHI_DNS_TYPE_AAAA); -    finish(r, interface, protocol, AVAHI_RESOLVER_FOUND, record); -} - -static void time_event_callback(AvahiTimeEvent *e, void *userdata) { -    AvahiSHostNameResolver *r = userdata; -    assert(e); -    assert(r); +    if (event == AVAHI_BROWSER_NEW) { -    finish(r, -1, AVAHI_PROTO_UNSPEC, AVAHI_RESOLVER_TIMEOUT, NULL); +        if (r->interface > 0 && interface != r->interface) +            return; +         +        if (r->protocol != AVAHI_PROTO_UNSPEC && protocol != r->protocol) +            return; +         +        if (r->interface <= 0) +            r->interface = interface; +         +        if (r->protocol == AVAHI_PROTO_UNSPEC) +            r->protocol = protocol; +         +        if (!r->address_record) { +            r->address_record = avahi_record_ref(record); +             +            finish(r, AVAHI_RESOLVER_FOUND); +        } +    } else { + +        assert(event == AVAHI_BROWSER_REMOVE); + +        if (avahi_record_equal_no_ttl(record, r->address_record)) { +            avahi_record_unref(r->address_record); +            r->address_record = NULL; + +            /** Look for a replacement */ +            if (r->record_browser_aaaa) +                avahi_s_record_browser_restart(r->record_browser_aaaa); +            if (r->record_browser_a) +                avahi_s_record_browser_restart(r->record_browser_a); + +            start_timeout(r); +        } +    }  }  AvahiSHostNameResolver *avahi_s_host_name_resolver_new(AvahiServer *server, AvahiIfIndex interface, AvahiProtocol protocol, const char *host_name, AvahiProtocol aprotocol, AvahiSHostNameResolverCallback callback, void* userdata) {      AvahiSHostNameResolver *r;      AvahiKey *k; -    struct timeval tv;      assert(server);      assert(host_name); @@ -134,11 +180,14 @@ AvahiSHostNameResolver *avahi_s_host_name_resolver_new(AvahiServer *server, Avah      r->host_name = avahi_normalize_name(host_name);      r->callback = callback;      r->userdata = userdata; +    r->address_record = NULL; +    r->interface = interface; +    r->protocol = protocol;      r->record_browser_a = r->record_browser_aaaa = NULL; -         -    avahi_elapse_time(&tv, 1000, 0); -    r->time_event = avahi_time_event_new(server->time_event_queue, &tv, time_event_callback, r); + +    r->time_event = NULL; +    start_timeout(r);      AVAHI_LLIST_PREPEND(AvahiSHostNameResolver, resolver, server->host_name_resolvers, r); @@ -184,6 +233,9 @@ void avahi_s_host_name_resolver_free(AvahiSHostNameResolver *r) {      if (r->time_event)          avahi_time_event_free(r->time_event); + +    if (r->address_record) +        avahi_record_unref(r->address_record);      avahi_free(r->host_name);      avahi_free(r); diff --git a/avahi-core/resolve-service.c b/avahi-core/resolve-service.c index 347de77..333f257 100644 --- a/avahi-core/resolve-service.c +++ b/avahi-core/resolve-service.c @@ -75,6 +75,8 @@ static void finish(AvahiSServiceResolver *r, AvahiResolverEvent event) {          AvahiAddress a;          char sn[256], st[256];          size_t i; + +        assert(event == AVAHI_RESOLVER_FOUND);          assert(r->srv_record);          assert(r->txt_record); | 
