]> git.meshlink.io Git - catta/blobdiff - avahi-client/browser.c
* Rename AVAHI_ERR_NOT_CONNECTED to AVAHI_ERR_DISCONNECTED
[catta] / avahi-client / browser.c
index 122d6f2f74b02676f0b4573dcdcb3f0ee431b4fd..bf9c15f00652877966e03440dbba51faa142cb12 100644 (file)
 #include <avahi-common/llist.h>
 #include <avahi-common/error.h>
 #include <avahi-common/malloc.h>
+#include <avahi-common/domain.h>
 
 #include "client.h"
 #include "internal.h"
+#include "xdg-config.h"
+
+static void parse_environment(AvahiDomainBrowser *b) {
+    char buf[AVAHI_DOMAIN_NAME_MAX*3], *e, *t, *p;
+
+    assert(b);
+    
+    if (!(e = getenv("AVAHI_BROWSE_DOMAINS")))
+        return;
+
+    snprintf(buf, sizeof(buf), "%s", e);
+
+    for (t = strtok_r(buf, ":", &p); t; t = strtok_r(NULL, ":", &p)) {
+        char domain[AVAHI_DOMAIN_NAME_MAX];
+        if (avahi_normalize_name(t, domain, sizeof(domain)))
+            b->static_browse_domains = avahi_string_list_add(b->static_browse_domains, domain);
+    }
+}
+
+static void parse_domain_file(AvahiDomainBrowser *b) {
+    FILE *f;
+    char buf[AVAHI_DOMAIN_NAME_MAX];
+    
+    assert(b);
+
+    if (!(f = avahi_xdg_config_open("avahi/browse-domains")))
+        return;
+    
+    
+    while (fgets(buf, sizeof(buf)-1, f)) {
+        char domain[AVAHI_DOMAIN_NAME_MAX];
+        buf[strcspn(buf, "\n\r")] = 0;
+        
+        if (avahi_normalize_name(buf, domain, sizeof(domain)))
+            b->static_browse_domains = avahi_string_list_add(b->static_browse_domains, domain);
+    }
+}
+
+static void domain_browser_ref(AvahiDomainBrowser *db) {
+    assert(db);
+    assert(db->ref >= 1);
+    db->ref++;
+}
+
+static void defer_timeout_callback(AvahiTimeout *t, void *userdata) {
+    AvahiDomainBrowser *db = userdata;
+    AvahiStringList *l;
+    assert(t);
+
+    db->client->poll_api->timeout_free(db->defer_timeout);
+    db->defer_timeout = NULL;
+
+    domain_browser_ref(db);
+
+    for (l = db->static_browse_domains; l; l = l->next) {
+
+        if (db->ref <= 1)
+            break;
+
+        db->callback(db, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, AVAHI_BROWSER_NEW, (char*) l->text, AVAHI_LOOKUP_RESULT_STATIC, db->userdata);
+    }
+
+    avahi_domain_browser_free(db);
+}
 
 AvahiDomainBrowser* avahi_domain_browser_new(
     AvahiClient *client,
@@ -60,7 +125,7 @@ AvahiDomainBrowser* avahi_domain_browser_new(
 
     dbus_error_init (&error);
 
-    if (client->state == AVAHI_CLIENT_DISCONNECTED) {
+    if (client->state == AVAHI_CLIENT_FAILURE) {
         avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
         goto fail;
     }
@@ -73,15 +138,23 @@ AvahiDomainBrowser* avahi_domain_browser_new(
         goto fail;
     }
 
+    db->ref = 1;
     db->client = client;
     db->callback = callback;
     db->userdata = userdata;
     db->path = NULL;
     db->interface = interface;
     db->protocol = protocol;
+    db->static_browse_domains = NULL;
+    db->defer_timeout = NULL;
 
     AVAHI_LLIST_PREPEND(AvahiDomainBrowser, domain_browsers, client->domain_browsers, db);
 
+    parse_environment(db);
+    parse_domain_file(db);
+
+    db->static_browse_domains = avahi_string_list_reverse(db->static_browse_domains);
+    
     if (!(message = dbus_message_new_method_call (AVAHI_DBUS_NAME, AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew"))) {
         avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
         goto fail;
@@ -125,6 +198,15 @@ AvahiDomainBrowser* avahi_domain_browser_new(
         goto fail;
     }
 
+    if (db->static_browse_domains) {
+        struct timeval tv = { 0, 0 };
+
+        if (!(db->defer_timeout = client->poll_api->timeout_new(client->poll_api, &tv, defer_timeout_callback, db))) {
+            avahi_client_set_errno(client, AVAHI_ERR_NO_MEMORY);
+            goto fail;
+        }
+    }
+    
     dbus_message_unref(message);
     dbus_message_unref(reply);
     
@@ -157,15 +239,24 @@ AvahiClient* avahi_domain_browser_get_client (AvahiDomainBrowser *b) {
 int avahi_domain_browser_free (AvahiDomainBrowser *b) {
     AvahiClient *client;
     int r = AVAHI_OK;
-
+    
     assert(b);
+    assert(b->ref >= 1);
+
+    if (--(b->ref) >= 1)
+        return AVAHI_OK;
+    
     client = b->client;
 
-    if (b->path && client->state != AVAHI_CLIENT_DISCONNECTED)
+    if (b->path && client->state != AVAHI_CLIENT_FAILURE)
         r = avahi_client_simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free");
 
     AVAHI_LLIST_REMOVE(AvahiDomainBrowser, domain_browsers, client->domain_browsers, b);
 
+    if (b->defer_timeout)
+        b->client->poll_api->timeout_free(b->defer_timeout);
+    
+    avahi_string_list_free(b->static_browse_domains);
     avahi_free(b->path);
     avahi_free(b);
 
@@ -179,6 +270,7 @@ DBusHandlerResult avahi_domain_browser_event (AvahiClient *client, AvahiBrowserE
     char *domain = NULL;
     int32_t interface, protocol;
     uint32_t flags = 0;
+    AvahiStringList *l;
 
     assert(client);
     assert(message);
@@ -237,6 +329,13 @@ DBusHandlerResult avahi_domain_browser_event (AvahiClient *client, AvahiBrowserE
         }
     }
 
+    if (domain)
+        for (l = db->static_browse_domains; l; l = l->next)
+            if (avahi_domain_equal((char*) l->text, domain)) {
+                /* We had this entry already in the static entries */
+                return DBUS_HANDLER_RESULT_HANDLED;
+            }
+    
     db->callback(db, (AvahiIfIndex) interface, (AvahiProtocol) protocol, event, domain, (AvahiLookupResultFlags) flags, db->userdata);
 
     return DBUS_HANDLER_RESULT_HANDLED;
@@ -268,7 +367,7 @@ AvahiServiceTypeBrowser* avahi_service_type_browser_new(
 
     dbus_error_init(&error);
 
-    if (client->state == AVAHI_CLIENT_DISCONNECTED) {
+    if (client->state == AVAHI_CLIENT_FAILURE) {
         avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
         goto fail;
     }
@@ -374,7 +473,7 @@ int avahi_service_type_browser_free (AvahiServiceTypeBrowser *b) {
     assert(b);
     client = b->client;
 
-    if (b->path && client->state != AVAHI_CLIENT_DISCONNECTED)
+    if (b->path && client->state != AVAHI_CLIENT_FAILURE)
         r = avahi_client_simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free");
 
     AVAHI_LLIST_REMOVE(AvahiServiceTypeBrowser, service_type_browsers, b->client->service_type_browsers, b);
@@ -484,7 +583,7 @@ AvahiServiceBrowser* avahi_service_browser_new(
 
     dbus_error_init(&error);
 
-    if (client->state == AVAHI_CLIENT_DISCONNECTED) {
+    if (client->state == AVAHI_CLIENT_FAILURE) {
         avahi_client_set_errno(client, AVAHI_ERR_BAD_STATE);
         goto fail;
     }
@@ -595,7 +694,7 @@ int avahi_service_browser_free (AvahiServiceBrowser *b) {
     assert(b);
     client = b->client;
 
-    if (b->path && client->state != AVAHI_CLIENT_DISCONNECTED)
+    if (b->path && client->state != AVAHI_CLIENT_FAILURE)
         r = avahi_client_simple_method_call(client, b->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free");
 
     AVAHI_LLIST_REMOVE(AvahiServiceBrowser, service_browsers, b->client->service_browsers, b);