]> git.meshlink.io Git - catta/blobdiff - avahi-core/resolve-service.c
Fix ./configure: line 23192: xyes: command not found
[catta] / avahi-core / resolve-service.c
index 194c245b9159bc3cde2154be87dc78f9199b888a..6dbca40ee2726df25f5a78bc982973b383b6563a 100644 (file)
 
 #include <string.h>
 #include <stdio.h>
+#include <stdlib.h>
 
 #include <avahi-common/domain.h>
 #include <avahi-common/timeval.h>
 #include <avahi-common/malloc.h>
+#include <avahi-common/error.h>
 
 #include "browse.h"
 
-struct AvahiServiceResolver {
+#define TIMEOUT_MSEC 1000
+
+struct AvahiSServiceResolver {
     AvahiServer *server;
     char *service_name;
     char *service_type;
@@ -42,44 +46,24 @@ struct AvahiServiceResolver {
     AvahiIfIndex interface;
     AvahiProtocol protocol;
 
-    AvahiRecordBrowser *record_browser_srv;
-    AvahiRecordBrowser *record_browser_txt;
-    AvahiRecordBrowser *record_browser_a;
-    AvahiRecordBrowser *record_browser_aaaa;
+    AvahiSRecordBrowser *record_browser_srv;
+    AvahiSRecordBrowser *record_browser_txt;
+    AvahiSRecordBrowser *record_browser_a;
+    AvahiSRecordBrowser *record_browser_aaaa;
 
     AvahiRecord *srv_record, *txt_record, *address_record;
     
-    AvahiServiceResolverCallback callback;
+    AvahiSServiceResolverCallback callback;
     void* userdata;
 
     AvahiTimeEvent *time_event;
 
-    AVAHI_LLIST_FIELDS(AvahiServiceResolver, resolver);
+    AVAHI_LLIST_FIELDS(AvahiSServiceResolver, resolver);
 };
 
-static void finish(AvahiServiceResolver *r, AvahiResolverEvent event) {
+static void finish(AvahiSServiceResolver *r, AvahiResolverEvent event) {
     assert(r);
 
-    if (r->record_browser_a) {
-        avahi_record_browser_free(r->record_browser_a);
-        r->record_browser_a = NULL;
-    }
-
-    if (r->record_browser_aaaa) {
-        avahi_record_browser_free(r->record_browser_aaaa);
-        r->record_browser_aaaa = NULL;
-    }
-
-    if (r->record_browser_srv) {
-        avahi_record_browser_free(r->record_browser_srv);
-        r->record_browser_srv = NULL;
-    }
-
-    if (r->record_browser_txt) {
-        avahi_record_browser_free(r->record_browser_txt);
-        r->record_browser_txt = NULL;
-    }
-
     if (r->time_event) {
         avahi_time_event_free(r->time_event);
         r->time_event = NULL;
@@ -91,6 +75,8 @@ static void finish(AvahiServiceResolver *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);
@@ -121,85 +107,159 @@ static void finish(AvahiServiceResolver *r, AvahiResolverEvent event) {
             st[i-1] = 0;
 
         r->callback(r, r->interface, r->protocol, event, sn, st, r->domain_name, r->srv_record->data.srv.name, &a, r->srv_record->data.srv.port, r->txt_record->data.txt.string_list, r->userdata);
-
     }
 }
 
-static void record_browser_callback(AvahiRecordBrowser*rr, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, AvahiRecord *record, void* userdata) {
-    AvahiServiceResolver *r = userdata;
-
-    assert(rr);
-    assert(record);
+static void time_event_callback(AvahiTimeEvent *e, void *userdata) {
+    AvahiSServiceResolver *r = userdata;
+    
+    assert(e);
     assert(r);
 
-    if (!(event == AVAHI_BROWSER_NEW))
-        return;
+    finish(r, AVAHI_RESOLVER_TIMEOUT);
+}
 
-    if (r->interface > 0 && interface != r->interface)
-        return;
+static void start_timeout(AvahiSServiceResolver *r) {
+    struct timeval tv;
+    assert(r);
 
-    if (r->protocol != AVAHI_PROTO_UNSPEC && protocol != r->protocol)
+    if (r->time_event)
         return;
     
-    if (r->interface <= 0)
-        r->interface = interface;
+    avahi_elapse_time(&tv, TIMEOUT_MSEC, 0);
+    r->time_event = avahi_time_event_new(r->server->time_event_queue, &tv, time_event_callback, r);
+}
 
-    if (r->protocol == AVAHI_PROTO_UNSPEC)
-        r->protocol = protocol;
-    
-    switch (record->key->type) {
-        case AVAHI_DNS_TYPE_SRV:
-            if (!r->srv_record) {
-                r->srv_record = avahi_record_ref(record);
+static void record_browser_callback(AvahiSRecordBrowser*rr, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, AvahiRecord *record, void* userdata) {
+    AvahiSServiceResolver *r = userdata;
 
-                assert(!r->record_browser_a && !r->record_browser_aaaa);
+    assert(rr);
+    assert(record);
+    assert(r);
+
+    if (event == AVAHI_BROWSER_NEW) {
+        int changed = 0;
+
+        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;
+        
+        switch (record->key->type) {
+            case AVAHI_DNS_TYPE_SRV:
+                if (!r->srv_record) {
+                    r->srv_record = avahi_record_ref(record);
+                    changed = 1;
+
+                    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->address_protocol == AVAHI_PROTO_INET || r->address_protocol == AVAHI_PROTO_UNSPEC) {
+                        AvahiKey *k = avahi_key_new(r->srv_record->data.srv.name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_A);
+                        r->record_browser_a = avahi_s_record_browser_new(r->server, r->interface, r->protocol, k, record_browser_callback, r);
+                        avahi_key_unref(k);
+                    } 
+                    
+                    if (r->address_protocol == AVAHI_PROTO_INET6 || r->address_protocol == AVAHI_PROTO_UNSPEC) {
+                        AvahiKey *k = avahi_key_new(r->srv_record->data.srv.name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_AAAA);
+                        r->record_browser_aaaa = avahi_s_record_browser_new(r->server, r->interface, r->protocol, k, record_browser_callback, r);
+                        avahi_key_unref(k);
+                    }
+                }
+                break;
+                
+            case AVAHI_DNS_TYPE_TXT:
+                if (!r->txt_record) {
+                    r->txt_record = avahi_record_ref(record);
+                    changed = 1;
+                }
+                break;
                 
-                if (r->address_protocol == AVAHI_PROTO_INET || r->address_protocol == AVAHI_PROTO_UNSPEC) {
-                    AvahiKey *k = avahi_key_new(r->srv_record->data.srv.name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_A);
-                    r->record_browser_a = avahi_record_browser_new(r->server, r->interface, r->protocol, k, record_browser_callback, r);
-                    avahi_key_unref(k);
-                } 
+            case AVAHI_DNS_TYPE_A:
+            case AVAHI_DNS_TYPE_AAAA:
+                if (!r->address_record) {
+                    r->address_record = avahi_record_ref(record);
+                    changed = 1;
+                }
+                break;
                 
-                if (r->address_protocol == AVAHI_PROTO_INET6 || r->address_protocol == AVAHI_PROTO_UNSPEC) {
-                    AvahiKey *k = avahi_key_new(r->srv_record->data.srv.name, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_AAAA);
-                    r->record_browser_aaaa = avahi_record_browser_new(r->server, r->interface, r->protocol, k, record_browser_callback, r);
-                    avahi_key_unref(k);
+            default:
+                abort();
+        }
+
+
+        if (changed && r->txt_record && r->srv_record && r->address_record)
+            finish(r, AVAHI_RESOLVER_FOUND);
+
+    } else {
+        assert(event == AVAHI_BROWSER_REMOVE);
+
+        
+        switch (record->key->type) {
+            case AVAHI_DNS_TYPE_SRV:
+
+                if (r->srv_record && avahi_record_equal_no_ttl(record, r->srv_record)) {
+                    avahi_record_unref(r->srv_record);
+                    r->srv_record = NULL;
+
+                    /** Look for a replacement */
+                    avahi_s_record_browser_restart(r->record_browser_srv);
+                    start_timeout(r);
                 }
-            }
-            break;
-            
-        case AVAHI_DNS_TYPE_TXT:
-            if (!r->txt_record)
-                r->txt_record = avahi_record_ref(record);
-            break;
-
-        case AVAHI_DNS_TYPE_A:
-        case AVAHI_DNS_TYPE_AAAA:
-            if (!r->address_record)
-                r->address_record = avahi_record_ref(record);
-            break;
-            
-        default:
-            assert(0);
-    }
+                
+                break;
 
-    if (r->txt_record && r->srv_record && r->address_record)
-        finish(r, AVAHI_RESOLVER_FOUND);
-}
+            case AVAHI_DNS_TYPE_TXT:
 
-static void time_event_callback(AvahiTimeEvent *e, void *userdata) {
-    AvahiServiceResolver *r = userdata;
-    
-    assert(e);
-    assert(r);
+                if (r->txt_record && avahi_record_equal_no_ttl(record, r->txt_record)) {
+                    avahi_record_unref(r->txt_record);
+                    r->txt_record = NULL;
 
-    finish(r, AVAHI_RESOLVER_TIMEOUT);
+                    /** Look for a replacement */
+                    avahi_s_record_browser_restart(r->record_browser_txt);
+                    start_timeout(r);
+                }
+                break;
+
+            case AVAHI_DNS_TYPE_A:
+            case AVAHI_DNS_TYPE_AAAA:
+
+                if (r->address_record && 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);
+                }
+                break;
+
+            default:
+                abort();
+        }
+    }
 }
 
-AvahiServiceResolver *avahi_service_resolver_new(AvahiServer *server, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain, AvahiProtocol aprotocol, AvahiServiceResolverCallback callback, void* userdata) {
-    AvahiServiceResolver *r;
+AvahiSServiceResolver *avahi_s_service_resolver_new(AvahiServer *server, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain, AvahiProtocol aprotocol, AvahiSServiceResolverCallback callback, void* userdata) {
+    AvahiSServiceResolver *r;
     AvahiKey *k;
-    struct timeval tv;
     char t[256], *n;
     size_t l;
     
@@ -225,7 +285,7 @@ AvahiServiceResolver *avahi_service_resolver_new(AvahiServer *server, AvahiIfInd
         return NULL;
     }
     
-    if (!(r = avahi_new(AvahiServiceResolver, 1))) {
+    if (!(r = avahi_new(AvahiSServiceResolver, 1))) {
         avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
         return NULL;
     }
@@ -246,50 +306,50 @@ AvahiServiceResolver *avahi_service_resolver_new(AvahiServer *server, AvahiIfInd
     avahi_escape_label((const uint8_t*) name, strlen(name), &n, &l);
     snprintf(n, l, ".%s.%s", r->service_type, r->domain_name);
 
-    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(AvahiServiceResolver, resolver, server->service_resolvers, r);
+    AVAHI_LLIST_PREPEND(AvahiSServiceResolver, resolver, server->service_resolvers, r);
 
     r->record_browser_a = r->record_browser_aaaa = r->record_browser_srv = r->record_browser_txt = NULL;
     
     k = avahi_key_new(t, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_SRV);
-    r->record_browser_srv = avahi_record_browser_new(server, interface, protocol, k, record_browser_callback, r);
+    r->record_browser_srv = avahi_s_record_browser_new(server, interface, protocol, k, record_browser_callback, r);
     avahi_key_unref(k);
 
     if (!r->record_browser_srv) {
-        avahi_service_resolver_free(r);
+        avahi_s_service_resolver_free(r);
         return NULL;
     }
     
     k = avahi_key_new(t, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_TXT);
-    r->record_browser_txt = avahi_record_browser_new(server, interface, protocol, k, record_browser_callback, r);
+    r->record_browser_txt = avahi_s_record_browser_new(server, interface, protocol, k, record_browser_callback, r);
     avahi_key_unref(k);
 
     if (!r->record_browser_txt) {
-        avahi_service_resolver_free(r);
+        avahi_s_service_resolver_free(r);
         return NULL;
     }
 
     return r;
 }
 
-void avahi_service_resolver_free(AvahiServiceResolver *r) {
+void avahi_s_service_resolver_free(AvahiSServiceResolver *r) {
     assert(r);
 
-    AVAHI_LLIST_REMOVE(AvahiServiceResolver, resolver, r->server->service_resolvers, r);
+    AVAHI_LLIST_REMOVE(AvahiSServiceResolver, resolver, r->server->service_resolvers, r);
 
     if (r->time_event)
         avahi_time_event_free(r->time_event);
     
     if (r->record_browser_srv)
-        avahi_record_browser_free(r->record_browser_srv);
+        avahi_s_record_browser_free(r->record_browser_srv);
     if (r->record_browser_txt)
-        avahi_record_browser_free(r->record_browser_txt);
+        avahi_s_record_browser_free(r->record_browser_txt);
     if (r->record_browser_a)
-        avahi_record_browser_free(r->record_browser_a);
+        avahi_s_record_browser_free(r->record_browser_a);
     if (r->record_browser_aaaa)
-        avahi_record_browser_free(r->record_browser_aaaa);
+        avahi_s_record_browser_free(r->record_browser_aaaa);
 
     if (r->srv_record)
         avahi_record_unref(r->srv_record);