X-Git-Url: http://git.meshlink.io/?a=blobdiff_plain;f=avahi-daemon%2Fdbus-protocol.c;h=eb8a6629a4c2541ee0ae34044b808ce8a041af54;hb=7a5b2f69af7d36d6cd4153142f125fa011784e03;hp=2e3fd2f2d594d8cf8a93fd1d7f6b5330912c36f9;hpb=e614891d38cae63957d0bfc00d34ecdbad4f8322;p=catta diff --git a/avahi-daemon/dbus-protocol.c b/avahi-daemon/dbus-protocol.c index 2e3fd2f..eb8a662 100644 --- a/avahi-daemon/dbus-protocol.c +++ b/avahi-daemon/dbus-protocol.c @@ -1,18 +1,16 @@ -/* $Id$ */ - /*** This file is part of avahi. - + avahi is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. - + avahi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. - + You should have received a copy of the GNU Lesser General Public License along with avahi; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 @@ -43,11 +41,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include @@ -61,12 +59,15 @@ /* #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); assert(c); @@ -78,7 +79,7 @@ static void client_free(Client *c) { while (c->async_host_name_resolvers) avahi_dbus_async_host_name_resolver_free(c->async_host_name_resolvers); - + while (c->sync_address_resolvers) avahi_dbus_sync_address_resolver_free(c->sync_address_resolvers); @@ -104,13 +105,13 @@ static void client_free(Client *c) { avahi_dbus_record_browser_free(c->record_browsers); assert(c->n_objects == 0); - + avahi_free(c->name); AVAHI_LLIST_REMOVE(Client, clients, server->clients, c); avahi_free(c); + assert(server->n_clients >= 1); server->n_clients --; - assert(server->n_clients >= 0); } static Client *client_get(const char *name, int create) { @@ -126,16 +127,16 @@ static Client *client_get(const char *name, int create) { if (!create) return NULL; - if (server->n_clients >= CLIENTS_MAX) + if (server->n_clients >= server->n_clients_max) return NULL; - - /* If not existant yet, create a new entry */ + + /* If not existent yet, create a new entry */ client = avahi_new(Client, 1); client->id = server->current_id++; client->name = avahi_strdup(name); client->current_id = 0; client->n_objects = 0; - + AVAHI_LLIST_HEAD_INIT(EntryGroupInfo, client->entry_groups); AVAHI_LLIST_HEAD_INIT(SyncHostNameResolverInfo, client->sync_host_name_resolvers); AVAHI_LLIST_HEAD_INIT(AsyncHostNameResolverInfo, client->async_host_name_resolvers); @@ -152,10 +153,24 @@ static Client *client_get(const char *name, int create) { server->n_clients++; assert(server->n_clients > 0); - + 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; @@ -167,14 +182,26 @@ 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("Disconnected 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("Disconnected from D-Bus, exiting."); + raise(SIGTERM); + } + return DBUS_HANDLER_RESULT_HANDLED; - + } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) { char *name; @@ -185,7 +212,7 @@ static DBusHandlerResult msg_signal_filter_impl(AVAHI_GCC_UNUSED DBusConnection /* avahi_log_info(__FILE__": name acquired (%s)", name); */ return DBUS_HANDLER_RESULT_HANDLED; - + } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) { char *name, *old, *new; @@ -198,7 +225,7 @@ static DBusHandlerResult msg_signal_filter_impl(AVAHI_GCC_UNUSED DBusConnection Client *client; if ((client = client_get(name, FALSE))) { - avahi_log_debug(__FILE__": client %s vanished.", name); + avahi_log_debug(__FILE__": client %s vanished.", name); client_free(client); } } @@ -207,7 +234,7 @@ static DBusHandlerResult msg_signal_filter_impl(AVAHI_GCC_UNUSED DBusConnection fail: if (dbus_error_is_set(&error)) dbus_error_free(&error); - + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } @@ -222,8 +249,8 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH dbus_message_get_member(m)); if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect")) - return avahi_dbus_handle_introspect(c, m, "Server.introspect"); - + return avahi_dbus_handle_introspect(c, m, "org.freedesktop.Avahi.Server.xml"); + else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) { if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) { @@ -232,7 +259,23 @@ 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,9 +291,9 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH avahi_log_warn("Error parsing Server::GetHostNameFqdn message"); goto fail; } - + 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"); @@ -258,14 +301,14 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH } 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))) { avahi_log_warn("Error parsing Server::GetVersionString message"); goto fail; } - + return avahi_dbus_respond_string(c, m, PACKAGE_STRING); } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAPIVersion")) { @@ -274,17 +317,17 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH 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; - + if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) { avahi_log_warn("Error parsing Server::GetState message"); goto fail; } - + state = avahi_server_get_state(avahi_server); return avahi_dbus_respond_int32(c, m, (int32_t) state); @@ -294,15 +337,13 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH avahi_log_warn("Error parsing Server::GetLocalServiceCookie message"); goto fail; } - + return avahi_dbus_respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server)); } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) { int32_t idx; - int fd; - char name[IF_NAMESIZE]; + char name[IF_NAMESIZE]; - if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) { avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message"); goto fail; @@ -311,31 +352,19 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH #ifdef VALGRIND_WORKAROUND return respond_string(c, m, "blah"); #else - - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { - char txt[256]; - snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno)); - return avahi_dbus_respond_error(c, m, AVAHI_ERR_OS, txt); - } - if ((!if_indextoname(idx, name))) { char txt[256]; snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno)); - close(fd); return avahi_dbus_respond_error(c, m, AVAHI_ERR_OS, txt); } - close(fd); - return avahi_dbus_respond_string(c, m, name); #endif - + } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) { char *n; - int fd; int32_t idx; - + if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) { avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message"); goto fail; @@ -344,28 +373,18 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH #ifdef VALGRIND_WORKAROUND return respond_int32(c, m, 1); #else - if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) - if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) { - char txt[256]; - snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno)); - return avahi_dbus_respond_error(c, m, AVAHI_ERR_OS, txt); - } - if (!(idx = if_nametoindex(n))) { char txt[256]; snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno)); - close(fd); return avahi_dbus_respond_error(c, m, AVAHI_ERR_OS, txt); } - close(fd); - return avahi_dbus_respond_int32(c, m, idx); #endif } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) { char *n, * t; - + if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) { avahi_log_warn("Error parsing Server::GetAlternativeHostName message"); goto fail; @@ -379,7 +398,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) { char *n, *t; - + if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) { avahi_log_warn("Error parsing Server::GetAlternativeServiceName message"); goto fail; @@ -390,7 +409,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH avahi_free(t); return DBUS_HANDLER_RESULT_HANDLED; - + } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) { Client *client; EntryGroupInfo *i; @@ -408,15 +427,15 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH goto fail; } - if (disable_user_service_publishing) + if (server->disable_user_service_publishing) return avahi_dbus_respond_error(c, m, AVAHI_ERR_NOT_PERMITTED, 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) { + if (client->n_objects >= server->n_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); } @@ -424,26 +443,27 @@ 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++; - + if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, avahi_dbus_entry_group_callback, i))) { avahi_dbus_entry_group_free(i); 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); - + } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) { Client *client; int32_t interface, protocol, aprotocol; uint32_t flags; char *name; SyncHostNameResolverInfo *i; - + if (!dbus_message_get_args( m, &error, DBUS_TYPE_INT32, &interface, @@ -461,7 +481,7 @@ 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) { + if (client->n_objects >= server->n_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); } @@ -476,9 +496,9 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH avahi_dbus_sync_host_name_resolver_free(i); return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); } - + return DBUS_HANDLER_RESULT_HANDLED; - + } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) { Client *client; int32_t interface, protocol; @@ -486,13 +506,13 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH char *address; SyncAddressResolverInfo *i; AvahiAddress a; - + if (!dbus_message_get_args( m, &error, DBUS_TYPE_INT32, &interface, DBUS_TYPE_INT32, &protocol, DBUS_TYPE_STRING, &address, - DBUS_TYPE_UINT32, &flags, + DBUS_TYPE_UINT32, &flags, DBUS_TYPE_INVALID) || !address) { avahi_log_warn("Error parsing Server::ResolveAddress message"); goto fail; @@ -506,7 +526,7 @@ 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) { + if (client->n_objects >= server->n_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); } @@ -521,9 +541,9 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH avahi_dbus_sync_address_resolver_free(i); return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); } - + return DBUS_HANDLER_RESULT_HANDLED; - + } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) { Client *client; DomainBrowserInfo *i; @@ -538,7 +558,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH int32_t interface, protocol, type; uint32_t flags; char *domain; - + if (!dbus_message_get_args( m, &error, DBUS_TYPE_INT32, &interface, @@ -556,7 +576,7 @@ 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) { + if (client->n_objects >= server->n_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); } @@ -567,7 +587,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++; @@ -575,7 +595,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); @@ -593,7 +614,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH int32_t interface, protocol; uint32_t flags; char *domain; - + if (!dbus_message_get_args( m, &error, DBUS_TYPE_INT32, &interface, @@ -610,7 +631,7 @@ 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) { + if (client->n_objects >= server->n_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); } @@ -621,7 +642,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++; @@ -629,10 +650,11 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH avahi_dbus_service_type_browser_free(i); 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); - + } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) { Client *client; ServiceBrowserInfo *i; @@ -647,7 +669,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH int32_t interface, protocol; uint32_t flags; char *domain, *type; - + if (!dbus_message_get_args( m, &error, DBUS_TYPE_INT32, &interface, @@ -665,7 +687,7 @@ 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) { + if (client->n_objects >= server->n_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); } @@ -676,7 +698,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++; @@ -684,17 +706,18 @@ 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); - + } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) { Client *client; int32_t interface, protocol, aprotocol; uint32_t flags; char *name, *type, *domain; SyncServiceResolverInfo *i; - + if (!dbus_message_get_args( m, &error, DBUS_TYPE_INT32, &interface, @@ -713,8 +736,8 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH 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) { + + if (client->n_objects >= server->n_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); } @@ -724,7 +747,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH if (!*name) name = NULL; - + i = avahi_new(SyncServiceResolverInfo, 1); i->client = client; i->message = dbus_message_ref(m); @@ -735,9 +758,9 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH avahi_dbus_sync_service_resolver_free(i); return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL); } - + return DBUS_HANDLER_RESULT_HANDLED; - + } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) { Client *client; int32_t interface, protocol, aprotocol; @@ -766,13 +789,13 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH avahi_log_warn("Error parsing Server::ServiceResolverNew message"); goto fail; } - + if (!(client = client_get(dbus_message_get_sender(m), TRUE))) { avahi_log_warn(__FILE__": 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) { + if (client->n_objects >= server->n_objects_per_client_max) { avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name); return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL); } @@ -782,11 +805,11 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH if (!*name) name = NULL; - + 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++; @@ -796,7 +819,8 @@ 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); @@ -814,7 +838,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH NULL, NULL }; - + if (!dbus_message_get_args( m, &error, DBUS_TYPE_INT32, &interface, @@ -826,13 +850,13 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH avahi_log_warn("Error parsing Server::HostNameResolverNew message"); goto fail; } - + if (!(client = client_get(dbus_message_get_sender(m), TRUE))) { avahi_log_warn(__FILE__": 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) { + if (client->n_objects >= server->n_objects_per_client_max) { avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name); return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL); } @@ -840,7 +864,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++; @@ -848,7 +872,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); @@ -867,7 +892,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH NULL, NULL }; - + if (!dbus_message_get_args( m, &error, DBUS_TYPE_INT32, &interface, @@ -887,7 +912,7 @@ 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) { + if (client->n_objects >= server->n_objects_per_client_max) { avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name); return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL); } @@ -895,7 +920,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++; @@ -903,10 +928,11 @@ 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; @@ -923,7 +949,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH char *name; uint16_t type, clazz; AvahiKey *key; - + if (!dbus_message_get_args( m, &error, DBUS_TYPE_INT32, &interface, @@ -937,7 +963,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH goto fail; } - if (!avahi_is_valid_domain_name(name)) + 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))) { @@ -945,7 +971,7 @@ 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) { + if (client->n_objects >= server->n_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); } @@ -953,7 +979,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH i = avahi_new(RecordBrowserInfo, 1); i->id = ++client->current_id; i->client = client; - i->path = avahi_strdup_printf("/Client%u/RecordBrowser%u", client->id, i->id); + i->path = NULL; AVAHI_LLIST_PREPEND(RecordBrowserInfo, record_browsers, client->record_browsers, i); client->n_objects++; @@ -967,7 +993,8 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH } 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); } @@ -977,7 +1004,7 @@ static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAH fail: if (dbus_error_is_set(&error)) dbus_error_free(&error); - + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; } @@ -985,11 +1012,17 @@ void dbus_protocol_server_state_changed(AvahiServerState state) { DBusMessage *m; 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"); + + if (!m) { + avahi_log_error("Failed allocate message"); + return; + } + t = (int32_t) state; if (state == AVAHI_SERVER_COLLISION) @@ -998,13 +1031,13 @@ void dbus_protocol_server_state_changed(AvahiServerState state) { e = avahi_error_number_to_dbus(avahi_server_errno(avahi_server)); else e = AVAHI_DBUS_ERR_OK; - + dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_STRING, &e, DBUS_TYPE_INVALID); dbus_connection_send(server->bus, m, NULL); 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 = { @@ -1016,33 +1049,52 @@ 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; + assert(server); + assert(!server->bus); - server = avahi_new(Server, 1); - AVAHI_LLIST_HEAD_INIT(Clients, server->clients); - server->current_id = 0; - server->n_clients = 0; + dbus_error_init(&error); - if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) { +#ifdef HAVE_DBUS_BUS_GET_PRIVATE + if (!(server->bus = dbus_bus_get_private(DBUS_BUS_SYSTEM, &error))) { assert(dbus_error_is_set(&error)); - avahi_log_error("dbus_bus_get(): %s", error.message); + avahi_log_error("dbus_bus_get_private(): %s", error.message); goto fail; } +#else + { + const char *a; - if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) { + if (!(a = getenv("DBUS_SYSTEM_BUS_ADDRESS")) || !*a) + a = DBUS_SYSTEM_BUS_DEFAULT_ADDRESS; + + if (!(server->bus = dbus_connection_open_private(a, &error))) { + assert(dbus_error_is_set(&error)); + avahi_log_error("dbus_bus_open_private(): %s", error.message); + goto fail; + } + + if (!dbus_bus_register(server->bus, &error)) { + assert(dbus_error_is_set(&error)); + avahi_log_error("dbus_bus_register(): %s", error.message); + goto fail; + } + } +#endif + + if (avahi_dbus_connection_glue(server->bus, server->poll_api) < 0) { avahi_log_error("avahi_dbus_connection_glue() failed"); goto fail; } + 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 +#if (DBUS_VERSION_MAJOR == 0) && (DBUS_VERSION_MINOR < 60) DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, +#else + DBUS_NAME_FLAG_DO_NOT_QUEUE, #endif &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { if (dbus_error_is_set(&error)) { @@ -1050,38 +1102,111 @@ int dbus_protocol_setup(const AvahiPoll *poll_api, int _disable_user_service_pub goto fail; } - avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'"); + avahi_log_error("Failed to acquire D-Bus name '"AVAHI_DBUS_NAME"'"); 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; } - + dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error); if (dbus_error_is_set(&error)) { avahi_log_error("dbus_bus_add_match(): %s", error.message); goto fail; } - + if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) { avahi_log_error("dbus_connection_register_object_path() failed"); goto fail; } + 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; + } + + 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 _n_clients_max, + int _n_objects_per_client_max, + int _n_entries_per_entry_group_max, + int force) { + + + 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; + server->disable_user_service_publishing = _disable_user_service_publishing; + server->n_clients_max = _n_clients_max > 0 ? _n_clients_max : DEFAULT_CLIENTS_MAX; + server->n_objects_per_client_max = _n_objects_per_client_max > 0 ? _n_objects_per_client_max : DEFAULT_OBJECTS_PER_CLIENT_MAX; + server->n_entries_per_entry_group_max = _n_entries_per_entry_group_max > 0 ? _n_entries_per_entry_group_max : DEFAULT_ENTRIES_PER_ENTRY_GROUP_MAX; + + 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); } - if (dbus_error_is_set(&error)) - dbus_error_free(&error); - avahi_free(server); server = NULL; return -1; @@ -1090,16 +1215,10 @@ fail: void dbus_protocol_shutdown(void) { if (server) { - - while (server->clients) - client_free(server->clients); + dbus_disconnect(); - assert(server->n_clients == 0); - - if (server->bus) { - dbus_connection_disconnect(server->bus); - dbus_connection_unref(server->bus); - } + if (server->reconnect_timeout) + server->poll_api->timeout_free(server->reconnect_timeout); avahi_free(server); server = NULL;