]> git.meshlink.io Git - catta/blobdiff - avahi-daemon/dbus-protocol.c
autoconf love:
[catta] / avahi-daemon / dbus-protocol.c
index c6c4a676c50c2041ecf05cbbe33d197b13af88ca..e74caa328ec7213c056b76de994d168351550dd2 100644 (file)
 #include <avahi-common/dbus.h>
 #include <avahi-common/llist.h>
 #include <avahi-common/malloc.h>
-#include <avahi-common/dbus.h>
 #include <avahi-common/dbus-watch-glue.h>
 #include <avahi-common/alternative.h>
 #include <avahi-common/error.h>
 #include <avahi-common/domain.h>
+#include <avahi-common/timeval.h>
 
 #include <avahi-core/log.h>
 #include <avahi-core/core.h>
 
 /* #define VALGRIND_WORKAROUND 1 */
 
+#define RECONNECT_MSEC 3000
+
 Server *server = NULL;
 
 static int disable_user_service_publishing = 0;
 
+static int dbus_connect(void);
+static void dbus_disconnect(void);
+
 static void client_free(Client *c) {
     
     assert(server);
@@ -100,6 +105,9 @@ static void client_free(Client *c) {
     while (c->async_service_resolvers)
         avahi_dbus_async_service_resolver_free(c->async_service_resolvers);
 
+    while (c->record_browsers)
+        avahi_dbus_record_browser_free(c->record_browsers);
+
     assert(c->n_objects == 0);
     
     avahi_free(c->name);
@@ -143,6 +151,7 @@ static Client *client_get(const char *name, int create) {
     AVAHI_LLIST_HEAD_INIT(ServiceBrowserInfo, client->service_browsers);
     AVAHI_LLIST_HEAD_INIT(SyncServiceResolverInfo, client->sync_service_resolvers);
     AVAHI_LLIST_HEAD_INIT(AsyncServiceResolverInfo, client->async_service_resolvers);
+    AVAHI_LLIST_HEAD_INIT(RecordBrowserInfo, client->record_browsers);
 
     AVAHI_LLIST_PREPEND(Client, clients, server->clients, client);
 
@@ -152,6 +161,19 @@ static Client *client_get(const char *name, int create) {
     return client;
 }
 
+static void reconnect_callback(AvahiTimeout *t, AVAHI_GCC_UNUSED void *userdata) {
+    assert(!server->bus);
+
+    if (dbus_connect() < 0) {
+        struct timeval tv;
+        avahi_log_debug(__FILE__": Connection failed, retrying in %ims...", RECONNECT_MSEC);
+        avahi_elapse_time(&tv, RECONNECT_MSEC, 0);
+        server->poll_api->timeout_update(t, &tv);
+    } else {
+        avahi_log_debug(__FILE__": Successfully reconnected.");
+        server->poll_api->timeout_update(t, NULL);
+    }
+}
 
 static DBusHandlerResult msg_signal_filter_impl(AVAHI_GCC_UNUSED DBusConnection *c, DBusMessage *m, AVAHI_GCC_UNUSED void *userdata) {
     DBusError error;
@@ -164,12 +186,24 @@ static DBusHandlerResult msg_signal_filter_impl(AVAHI_GCC_UNUSED DBusConnection
 /*                     dbus_message_get_member(m)); */
 
     if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
-        /* No, we shouldn't quit, but until we get somewhere
-         * usefull such that we can restore our state, we will */
-        avahi_log_warn("Disconnnected from D-BUS, terminating...");
-        
-        raise(SIGQUIT); /* The signal handler will catch this and terminate the process cleanly*/
-        
+        struct timeval tv;
+
+        if (server->reconnect) {
+            avahi_log_warn("Disconnnected from D-BUS, trying to reconnect in %ims...", RECONNECT_MSEC);
+            
+            dbus_disconnect();
+            
+            avahi_elapse_time(&tv, RECONNECT_MSEC, 0);
+            
+            if (server->reconnect_timeout)
+                server->poll_api->timeout_update(server->reconnect_timeout, &tv);
+            else
+                server->reconnect_timeout = server->poll_api->timeout_new(server->poll_api, &tv, reconnect_callback, NULL);
+        } else {
+            avahi_log_warn("Disconnnected from D-BUS, exiting.");
+            raise(SIGQUIT);
+        }
+            
         return DBUS_HANDLER_RESULT_HANDLED;
         
     } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) {
@@ -230,6 +264,22 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
 
         return avahi_dbus_respond_string(c, m, avahi_server_get_host_name(avahi_server));
         
+    } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "SetHostName")) {
+
+        char *name;
+        
+        if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
+            avahi_log_warn("Error parsing Server::SetHostName message");
+            goto fail;
+        }
+        
+        if (avahi_server_set_host_name(avahi_server, name) < 0) 
+            return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
+
+        avahi_log_info("Changing host name to '%s'.", name);
+        
+        return avahi_dbus_respond_ok(c, m);
+        
     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
 
         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
@@ -248,6 +298,14 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
     
         return avahi_dbus_respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
         
+    } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "IsNSSSupportAvailable")) {
+        if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
+            avahi_log_warn("Error parsing Server::IsNSSSupportAvailable message");
+            goto fail;
+        }
+
+        return avahi_dbus_respond_boolean(c, m, nss_support);
+        
     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
 
         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
@@ -257,6 +315,15 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
     
         return avahi_dbus_respond_string(c, m, PACKAGE_STRING);
 
+    } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAPIVersion")) {
+
+        if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
+            avahi_log_warn("Error parsing Server::GetAPIVersion message");
+            goto fail;
+        }
+    
+        return avahi_dbus_respond_uint32(c, m, AVAHI_DBUS_API_VERSION);
+
     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
         AvahiServerState state;
         
@@ -404,7 +471,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
         i = avahi_new(EntryGroupInfo, 1);
         i->id = ++client->current_id;
         i->client = client;
-        i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
+        i->path = NULL;
         i->n_entries = 0;
         AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
         client->n_objects++;
@@ -414,6 +481,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
         }
 
+        i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
         dbus_connection_register_object_path(c, i->path, &vtable, i);
         return avahi_dbus_respond_path(c, m, i->path);
         
@@ -547,7 +615,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
         i = avahi_new(DomainBrowserInfo, 1);
         i->id = ++client->current_id;
         i->client = client;
-        i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
+        i->path = NULL;
         AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
         client->n_objects++;
 
@@ -555,7 +623,8 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
             avahi_dbus_domain_browser_free(i);
             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
         }
-        
+
+        i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
         dbus_connection_register_object_path(c, i->path, &vtable, i);
         return avahi_dbus_respond_path(c, m, i->path);
 
@@ -590,7 +659,6 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
         }
 
-
         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
@@ -602,7 +670,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
         i = avahi_new(ServiceTypeBrowserInfo, 1);
         i->id = ++client->current_id;
         i->client = client;
-        i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
+        i->path = NULL;
         AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
         client->n_objects++;
 
@@ -611,6 +679,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
         }
         
+        i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
         dbus_connection_register_object_path(c, i->path, &vtable, i);
         return avahi_dbus_respond_path(c, m, i->path);
         
@@ -646,7 +715,6 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
         }
 
-
         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
@@ -658,7 +726,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
         i = avahi_new(ServiceBrowserInfo, 1);
         i->id = ++client->current_id;
         i->client = client;
-        i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
+        i->path = NULL;
         AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
         client->n_objects++;
 
@@ -666,7 +734,8 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
             avahi_dbus_service_browser_free(i);
             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
         }
-        
+
+        i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
         dbus_connection_register_object_path(c, i->path, &vtable, i);
         return avahi_dbus_respond_path(c, m, i->path);
         
@@ -768,7 +837,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
         i = avahi_new(AsyncServiceResolverInfo, 1);
         i->id = ++client->current_id;
         i->client = client;
-        i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
+        i->path = NULL;
         AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i);
         client->n_objects++;
 
@@ -779,6 +848,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
 
 /*         avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */
         
+        i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
         dbus_connection_register_object_path(c, i->path, &vtable, i);
         return avahi_dbus_respond_path(c, m, i->path);
 
@@ -822,7 +892,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
         i = avahi_new(AsyncHostNameResolverInfo, 1);
         i->id = ++client->current_id;
         i->client = client;
-        i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
+        i->path = NULL;
         AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i);
         client->n_objects++;
 
@@ -830,7 +900,8 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
             avahi_dbus_async_host_name_resolver_free(i);
             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
         }
-        
+
+        i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
         dbus_connection_register_object_path(c, i->path, &vtable, i);
         return avahi_dbus_respond_path(c, m, i->path);
 
@@ -877,7 +948,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
         i = avahi_new(AsyncAddressResolverInfo, 1);
         i->id = ++client->current_id;
         i->client = client;
-        i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
+        i->path = NULL;
         AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i);
         client->n_objects++;
 
@@ -885,7 +956,73 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH
             avahi_dbus_async_address_resolver_free(i);
             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
         }
+
+        i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
+        dbus_connection_register_object_path(c, i->path, &vtable, i);
+        return avahi_dbus_respond_path(c, m, i->path);
+        
+    } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "RecordBrowserNew")) {
+        Client *client;
+        RecordBrowserInfo *i;
+        static const DBusObjectPathVTable vtable = {
+            NULL,
+            avahi_dbus_msg_record_browser_impl,
+            NULL,
+            NULL,
+            NULL,
+            NULL
+        };
+        int32_t interface, protocol;
+        uint32_t flags;
+        char *name;
+        uint16_t type, clazz;
+        AvahiKey *key;
+        
+        if (!dbus_message_get_args(
+                m, &error,
+                DBUS_TYPE_INT32, &interface,
+                DBUS_TYPE_INT32, &protocol,
+                DBUS_TYPE_STRING, &name,
+                DBUS_TYPE_UINT16, &clazz,
+                DBUS_TYPE_UINT16, &type,
+                DBUS_TYPE_UINT32, &flags,
+                DBUS_TYPE_INVALID) || !name) {
+            avahi_log_warn("Error parsing Server::RecordBrowserNew message");
+            goto fail;
+        }
+
+        if (!avahi_is_valid_domain_name(name)) 
+            return avahi_dbus_respond_error(c, m, AVAHI_ERR_INVALID_DOMAIN_NAME, NULL);
+
+        if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
+            avahi_log_warn("Too many clients, client request failed.");
+            return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
+        }
+
+        if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
+            avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
+            return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
+        }
+
+        i = avahi_new(RecordBrowserInfo, 1);
+        i->id = ++client->current_id;
+        i->client = client;
+        i->path = NULL;
+        AVAHI_LLIST_PREPEND(RecordBrowserInfo, record_browsers, client->record_browsers, i);
+        client->n_objects++;
+
+        key = avahi_key_new(name, clazz, type);
+        assert(key);
+
+        if (!(i->record_browser = avahi_s_record_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, key, (AvahiLookupFlags) flags, avahi_dbus_record_browser_callback, i))) {
+            avahi_key_unref(key);
+            avahi_dbus_record_browser_free(i);
+            return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
+        }
+
+        avahi_key_unref(key);
         
+        i->path = avahi_strdup_printf("/Client%u/RecordBrowser%u", client->id, i->id);
         dbus_connection_register_object_path(c, i->path, &vtable, i);
         return avahi_dbus_respond_path(c, m, i->path);
     }
@@ -904,7 +1041,7 @@ void dbus_protocol_server_state_changed(AvahiServerState state) {
     int32_t t;
     const char *e;
     
-    if (!server)
+    if (!server || !server->bus)
         return;
 
     m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
@@ -922,7 +1059,7 @@ void dbus_protocol_server_state_changed(AvahiServerState state) {
     dbus_message_unref(m);
 }
 
-int dbus_protocol_setup(const AvahiPoll *poll_api, int _disable_user_service_publishing) {
+static int dbus_connect(void) {
     DBusError error;
 
     static const DBusObjectPathVTable server_vtable = {
@@ -934,27 +1071,32 @@ int dbus_protocol_setup(const AvahiPoll *poll_api, int _disable_user_service_pub
         NULL
     };
 
-    dbus_error_init(&error);
-
-    disable_user_service_publishing = _disable_user_service_publishing;
-
-    server = avahi_new(Server, 1);
-    AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
-    server->current_id = 0;
-    server->n_clients = 0;
+    assert(server);
+    assert(!server->bus);
 
+    dbus_error_init(&error);
+    
     if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
         assert(dbus_error_is_set(&error));
         avahi_log_error("dbus_bus_get(): %s", error.message);
         goto fail;
     }
-
-    if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) {
+    if (avahi_dbus_connection_glue(server->bus, server->poll_api) < 0) {
         avahi_log_error("avahi_dbus_connection_glue() failed");
         goto fail;
     }
 
-    if (dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+    dbus_connection_set_exit_on_disconnect(server->bus, FALSE);
+    
+    if (dbus_bus_request_name(
+            server->bus,
+            AVAHI_DBUS_NAME,
+#if (DBUS_VERSION_MAJOR == 0) && (DBUS_VERSION_MINOR >= 60)
+            DBUS_NAME_FLAG_DO_NOT_QUEUE,
+#else
+            DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT,
+#endif
+            &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
         if (dbus_error_is_set(&error)) {
             avahi_log_error("dbus_bus_request_name(): %s", error.message);
             goto fail;
@@ -964,7 +1106,7 @@ int dbus_protocol_setup(const AvahiPoll *poll_api, int _disable_user_service_pub
         goto fail;
     }
 
-    if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) {
+    if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) server->poll_api, NULL))) {
         avahi_log_error("dbus_connection_add_filter() failed");
         goto fail;
     }
@@ -982,16 +1124,80 @@ int dbus_protocol_setup(const AvahiPoll *poll_api, int _disable_user_service_pub
     }
 
     return 0;
-
 fail:
+
+    if (dbus_error_is_set(&error))
+        dbus_error_free(&error);
+
     if (server->bus) {
+#ifdef HAVE_DBUS_CONNECTION_CLOSE
+        dbus_connection_close(server->bus);
+#else
         dbus_connection_disconnect(server->bus);
+#endif
         dbus_connection_unref(server->bus);
+        server->bus = NULL;
     }
 
-    if (dbus_error_is_set(&error))
-        dbus_error_free(&error);
+    return -1;
+}
+
+static void dbus_disconnect(void) {
+    assert(server);
+
+    while (server->clients)
+        client_free(server->clients);
+    
+    assert(server->n_clients == 0);
+
+    if (server->bus) {
+#ifdef HAVE_DBUS_CONNECTION_CLOSE
+        dbus_connection_close(server->bus);
+#else
+        dbus_connection_disconnect(server->bus);
+#endif
+        dbus_connection_unref(server->bus);
+        server->bus = NULL;
+    }
+}
+
+int dbus_protocol_setup(const AvahiPoll *poll_api, int _disable_user_service_publishing, int force) {
+
+    disable_user_service_publishing = _disable_user_service_publishing;
+
+    server = avahi_new(Server, 1);
+    AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
+    server->current_id = 0;
+    server->n_clients = 0;
+    server->bus = NULL;
+    server->poll_api = poll_api;
+    server->reconnect_timeout = NULL;
+    server->reconnect = force;
+
+    if (dbus_connect() < 0) {
+        struct timeval tv;
+
+        if (!force)
+            goto fail;
+
+        avahi_log_warn("WARNING: Failed to contact D-Bus daemon, retrying in %ims.", RECONNECT_MSEC);
+        
+        avahi_elapse_time(&tv, RECONNECT_MSEC, 0);
+        server->reconnect_timeout = server->poll_api->timeout_new(server->poll_api, &tv, reconnect_callback, NULL);
+    }
         
+    return 0;
+
+fail:
+    if (server->bus) {
+#ifdef HAVE_DBUS_CONNECTION_CLOSE
+        dbus_connection_close(server->bus);
+#else
+        dbus_connection_disconnect(server->bus);
+#endif
+        dbus_connection_unref(server->bus);
+    }
+
     avahi_free(server);
     server = NULL;
     return -1;
@@ -1000,17 +1206,11 @@ fail:
 void dbus_protocol_shutdown(void) {
 
     if (server) {
-    
-        while (server->clients)
-            client_free(server->clients);
-
-        assert(server->n_clients == 0);
-
-        if (server->bus) {
-            dbus_connection_disconnect(server->bus);
-            dbus_connection_unref(server->bus);
-        }
+        dbus_disconnect();
 
+        if (server->reconnect_timeout)
+            server->poll_api->timeout_free(server->reconnect_timeout);
+        
         avahi_free(server);
         server = NULL;
     }