]> git.meshlink.io Git - catta/blob - avahi-daemon/dbus-protocol.c
fix a few more s/DBUS/D-Bus/
[catta] / avahi-daemon / dbus-protocol.c
1 /* $Id$ */
2
3 /***
4   This file is part of avahi.
5  
6   avahi is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as
8   published by the Free Software Foundation; either version 2.1 of the
9   License, or (at your option) any later version.
10  
11   avahi is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14   Public License for more details.
15  
16   You should have received a copy of the GNU Lesser General Public
17   License along with avahi; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <string.h>
27 #include <sys/ioctl.h>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <net/if.h>
32 #include <errno.h>
33 #include <unistd.h>
34 #include <assert.h>
35 #include <sys/stat.h>
36 #include <fcntl.h>
37 #include <stdio.h>
38 #include <signal.h>
39 #include <stdlib.h>
40
41 #include <dbus/dbus.h>
42
43 #include <avahi-common/dbus.h>
44 #include <avahi-common/llist.h>
45 #include <avahi-common/malloc.h>
46 #include <avahi-common/dbus-watch-glue.h>
47 #include <avahi-common/alternative.h>
48 #include <avahi-common/error.h>
49 #include <avahi-common/domain.h>
50 #include <avahi-common/timeval.h>
51
52 #include <avahi-core/log.h>
53 #include <avahi-core/core.h>
54 #include <avahi-core/lookup.h>
55 #include <avahi-core/publish.h>
56
57 #include "dbus-protocol.h"
58 #include "dbus-util.h"
59 #include "dbus-internal.h"
60 #include "main.h"
61
62 /* #define VALGRIND_WORKAROUND 1 */
63
64 #define RECONNECT_MSEC 3000
65
66 Server *server = NULL;
67
68 static int disable_user_service_publishing = 0;
69
70 static int dbus_connect(void);
71 static void dbus_disconnect(void);
72
73 static void client_free(Client *c) {
74     
75     assert(server);
76     assert(c);
77
78     while (c->entry_groups)
79         avahi_dbus_entry_group_free(c->entry_groups);
80
81     while (c->sync_host_name_resolvers)
82         avahi_dbus_sync_host_name_resolver_free(c->sync_host_name_resolvers);
83
84     while (c->async_host_name_resolvers)
85         avahi_dbus_async_host_name_resolver_free(c->async_host_name_resolvers);
86     
87     while (c->sync_address_resolvers)
88         avahi_dbus_sync_address_resolver_free(c->sync_address_resolvers);
89
90     while (c->async_address_resolvers)
91         avahi_dbus_async_address_resolver_free(c->async_address_resolvers);
92
93     while (c->domain_browsers)
94         avahi_dbus_domain_browser_free(c->domain_browsers);
95
96     while (c->service_type_browsers)
97         avahi_dbus_service_type_browser_free(c->service_type_browsers);
98
99     while (c->service_browsers)
100         avahi_dbus_service_browser_free(c->service_browsers);
101
102     while (c->sync_service_resolvers)
103         avahi_dbus_sync_service_resolver_free(c->sync_service_resolvers);
104
105     while (c->async_service_resolvers)
106         avahi_dbus_async_service_resolver_free(c->async_service_resolvers);
107
108     while (c->record_browsers)
109         avahi_dbus_record_browser_free(c->record_browsers);
110
111     assert(c->n_objects == 0);
112     
113     avahi_free(c->name);
114     AVAHI_LLIST_REMOVE(Client, clients, server->clients, c);
115     avahi_free(c);
116
117     server->n_clients --;
118     assert(server->n_clients >= 0);
119 }
120
121 static Client *client_get(const char *name, int create) {
122     Client *client;
123
124     assert(server);
125     assert(name);
126
127     for (client = server->clients; client; client = client->clients_next)
128         if (!strcmp(name, client->name))
129             return client;
130
131     if (!create)
132         return NULL;
133
134     if (server->n_clients >= CLIENTS_MAX)
135         return NULL;
136     
137     /* If not existant yet, create a new entry */
138     client = avahi_new(Client, 1);
139     client->id = server->current_id++;
140     client->name = avahi_strdup(name);
141     client->current_id = 0;
142     client->n_objects = 0;
143     
144     AVAHI_LLIST_HEAD_INIT(EntryGroupInfo, client->entry_groups);
145     AVAHI_LLIST_HEAD_INIT(SyncHostNameResolverInfo, client->sync_host_name_resolvers);
146     AVAHI_LLIST_HEAD_INIT(AsyncHostNameResolverInfo, client->async_host_name_resolvers);
147     AVAHI_LLIST_HEAD_INIT(SyncAddressResolverInfo, client->sync_address_resolvers);
148     AVAHI_LLIST_HEAD_INIT(AsyncAddressResolverInfo, client->async_address_resolvers);
149     AVAHI_LLIST_HEAD_INIT(DomainBrowserInfo, client->domain_browsers);
150     AVAHI_LLIST_HEAD_INIT(ServiceTypeBrowserInfo, client->service_type_browsers);
151     AVAHI_LLIST_HEAD_INIT(ServiceBrowserInfo, client->service_browsers);
152     AVAHI_LLIST_HEAD_INIT(SyncServiceResolverInfo, client->sync_service_resolvers);
153     AVAHI_LLIST_HEAD_INIT(AsyncServiceResolverInfo, client->async_service_resolvers);
154     AVAHI_LLIST_HEAD_INIT(RecordBrowserInfo, client->record_browsers);
155
156     AVAHI_LLIST_PREPEND(Client, clients, server->clients, client);
157
158     server->n_clients++;
159     assert(server->n_clients > 0);
160     
161     return client;
162 }
163
164 static void reconnect_callback(AvahiTimeout *t, AVAHI_GCC_UNUSED void *userdata) {
165     assert(!server->bus);
166
167     if (dbus_connect() < 0) {
168         struct timeval tv;
169         avahi_log_debug(__FILE__": Connection failed, retrying in %ims...", RECONNECT_MSEC);
170         avahi_elapse_time(&tv, RECONNECT_MSEC, 0);
171         server->poll_api->timeout_update(t, &tv);
172     } else {
173         avahi_log_debug(__FILE__": Successfully reconnected.");
174         server->poll_api->timeout_update(t, NULL);
175     }
176 }
177
178 static DBusHandlerResult msg_signal_filter_impl(AVAHI_GCC_UNUSED DBusConnection *c, DBusMessage *m, AVAHI_GCC_UNUSED void *userdata) {
179     DBusError error;
180
181     dbus_error_init(&error);
182
183 /*     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s", */
184 /*                     dbus_message_get_interface(m), */
185 /*                     dbus_message_get_path(m), */
186 /*                     dbus_message_get_member(m)); */
187
188     if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
189         struct timeval tv;
190
191         if (server->reconnect) {
192             avahi_log_warn("Disconnnected from D-Bus, trying to reconnect in %ims...", RECONNECT_MSEC);
193             
194             dbus_disconnect();
195             
196             avahi_elapse_time(&tv, RECONNECT_MSEC, 0);
197             
198             if (server->reconnect_timeout)
199                 server->poll_api->timeout_update(server->reconnect_timeout, &tv);
200             else
201                 server->reconnect_timeout = server->poll_api->timeout_new(server->poll_api, &tv, reconnect_callback, NULL);
202         } else {
203             avahi_log_warn("Disconnnected from D-Bus, exiting.");
204             raise(SIGQUIT);
205         }
206             
207         return DBUS_HANDLER_RESULT_HANDLED;
208         
209     } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) {
210         char *name;
211
212         if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
213             avahi_log_warn("Error parsing NameAcquired message");
214             goto fail;
215         }
216
217 /*         avahi_log_info(__FILE__": name acquired (%s)", name); */
218         return DBUS_HANDLER_RESULT_HANDLED;
219         
220     } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
221         char *name, *old, *new;
222
223         if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) {
224             avahi_log_warn("Error parsing NameOwnerChanged message");
225             goto fail;
226         }
227
228         if (!*new) {
229             Client *client;
230
231             if ((client = client_get(name, FALSE))) {
232                 avahi_log_debug(__FILE__": client %s vanished.", name); 
233                 client_free(client);
234             }
235         }
236     }
237
238 fail:
239     if (dbus_error_is_set(&error))
240         dbus_error_free(&error);
241     
242     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
243 }
244
245 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAHI_GCC_UNUSED void *userdata) {
246     DBusError error;
247
248     dbus_error_init(&error);
249
250     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
251                     dbus_message_get_interface(m),
252                     dbus_message_get_path(m),
253                     dbus_message_get_member(m));
254
255     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
256         return avahi_dbus_handle_introspect(c, m, "Server.introspect");
257         
258     else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
259
260         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
261             avahi_log_warn("Error parsing Server::GetHostName message");
262             goto fail;
263         }
264
265         return avahi_dbus_respond_string(c, m, avahi_server_get_host_name(avahi_server));
266         
267     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "SetHostName")) {
268
269         char *name;
270         
271         if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
272             avahi_log_warn("Error parsing Server::SetHostName message");
273             goto fail;
274         }
275         
276         if (avahi_server_set_host_name(avahi_server, name) < 0) 
277             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
278
279         avahi_log_info("Changing host name to '%s'.", name);
280         
281         return avahi_dbus_respond_ok(c, m);
282         
283     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
284
285         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
286             avahi_log_warn("Error parsing Server::GetDomainName message");
287             goto fail;
288         }
289
290         return avahi_dbus_respond_string(c, m, avahi_server_get_domain_name(avahi_server));
291
292     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
293
294         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
295             avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
296             goto fail;
297         }
298     
299         return avahi_dbus_respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
300         
301     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "IsNSSSupportAvailable")) {
302         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
303             avahi_log_warn("Error parsing Server::IsNSSSupportAvailable message");
304             goto fail;
305         }
306
307         return avahi_dbus_respond_boolean(c, m, nss_support);
308         
309     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
310
311         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
312             avahi_log_warn("Error parsing Server::GetVersionString message");
313             goto fail;
314         }
315     
316         return avahi_dbus_respond_string(c, m, PACKAGE_STRING);
317
318     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAPIVersion")) {
319
320         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
321             avahi_log_warn("Error parsing Server::GetAPIVersion message");
322             goto fail;
323         }
324     
325         return avahi_dbus_respond_uint32(c, m, AVAHI_DBUS_API_VERSION);
326
327     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
328         AvahiServerState state;
329         
330         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
331             avahi_log_warn("Error parsing Server::GetState message");
332             goto fail;
333         }
334         
335         state = avahi_server_get_state(avahi_server);
336         return avahi_dbus_respond_int32(c, m, (int32_t) state);
337
338     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetLocalServiceCookie")) {
339
340         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
341             avahi_log_warn("Error parsing Server::GetLocalServiceCookie message");
342             goto fail;
343         }
344         
345         return avahi_dbus_respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server));
346
347     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
348         int32_t idx;
349         int fd;
350         char name[IF_NAMESIZE];
351
352         
353         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
354             avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
355             goto fail;
356         }
357
358 #ifdef VALGRIND_WORKAROUND
359         return respond_string(c, m, "blah");
360 #else
361         
362         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
363             if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
364                 char txt[256];
365                 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
366                 return avahi_dbus_respond_error(c, m, AVAHI_ERR_OS, txt);
367             }
368
369         if ((!if_indextoname(idx, name))) {
370             char txt[256];
371             snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
372             close(fd);
373             return avahi_dbus_respond_error(c, m, AVAHI_ERR_OS, txt);
374         }
375
376         close(fd);
377         
378         return avahi_dbus_respond_string(c, m, name);
379 #endif
380         
381     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
382         char *n;
383         int fd;
384         int32_t idx;
385         
386         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
387             avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
388             goto fail;
389         }
390
391 #ifdef VALGRIND_WORKAROUND
392         return respond_int32(c, m, 1);
393 #else
394         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
395             if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
396                 char txt[256];
397                 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
398                 return avahi_dbus_respond_error(c, m, AVAHI_ERR_OS, txt);
399             }
400
401         if (!(idx = if_nametoindex(n))) {
402             char txt[256];
403             snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
404             close(fd);
405             return avahi_dbus_respond_error(c, m, AVAHI_ERR_OS, txt);
406         }
407
408         close(fd);
409         
410         return avahi_dbus_respond_int32(c, m, idx);
411 #endif
412
413     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
414         char *n, * t;
415         
416         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
417             avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
418             goto fail;
419         }
420
421         t = avahi_alternative_host_name(n);
422         avahi_dbus_respond_string(c, m, t);
423         avahi_free(t);
424
425         return DBUS_HANDLER_RESULT_HANDLED;
426
427     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
428         char *n, *t;
429         
430         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
431             avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
432             goto fail;
433         }
434
435         t = avahi_alternative_service_name(n);
436         avahi_dbus_respond_string(c, m, t);
437         avahi_free(t);
438
439         return DBUS_HANDLER_RESULT_HANDLED;
440         
441     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
442         Client *client;
443         EntryGroupInfo *i;
444         static const DBusObjectPathVTable vtable = {
445             NULL,
446             avahi_dbus_msg_entry_group_impl,
447             NULL,
448             NULL,
449             NULL,
450             NULL
451         };
452
453         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
454             avahi_log_warn("Error parsing Server::EntryGroupNew message");
455             goto fail;
456         }
457
458         if (disable_user_service_publishing)
459             return avahi_dbus_respond_error(c, m, AVAHI_ERR_NOT_PERMITTED, NULL);
460         
461         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
462             avahi_log_warn("Too many clients, client request failed.");
463             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
464         }
465
466         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
467             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
468             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
469         }
470
471         i = avahi_new(EntryGroupInfo, 1);
472         i->id = ++client->current_id;
473         i->client = client;
474         i->path = NULL;
475         i->n_entries = 0;
476         AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
477         client->n_objects++;
478         
479         if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, avahi_dbus_entry_group_callback, i))) {
480             avahi_dbus_entry_group_free(i);
481             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
482         }
483
484         i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
485         dbus_connection_register_object_path(c, i->path, &vtable, i);
486         return avahi_dbus_respond_path(c, m, i->path);
487         
488     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
489         Client *client;
490         int32_t interface, protocol, aprotocol;
491         uint32_t flags;
492         char *name;
493         SyncHostNameResolverInfo *i;
494             
495         if (!dbus_message_get_args(
496                 m, &error,
497                 DBUS_TYPE_INT32, &interface,
498                 DBUS_TYPE_INT32, &protocol,
499                 DBUS_TYPE_STRING, &name,
500                 DBUS_TYPE_INT32, &aprotocol,
501                 DBUS_TYPE_UINT32, &flags,
502                 DBUS_TYPE_INVALID) || !name) {
503             avahi_log_warn("Error parsing Server::ResolveHostName message");
504             goto fail;
505         }
506
507         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
508             avahi_log_warn("Too many clients, client request failed.");
509             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
510         }
511
512         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
513             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
514             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
515         }
516
517         i = avahi_new(SyncHostNameResolverInfo, 1);
518         i->client = client;
519         i->message = dbus_message_ref(m);
520         AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i);
521         client->n_objects++;
522
523         if (!(i->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, avahi_dbus_sync_host_name_resolver_callback, i))) {
524             avahi_dbus_sync_host_name_resolver_free(i);
525             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
526         }
527         
528         return DBUS_HANDLER_RESULT_HANDLED;
529         
530     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
531         Client *client;
532         int32_t interface, protocol;
533         uint32_t flags;
534         char *address;
535         SyncAddressResolverInfo *i;
536         AvahiAddress a;
537             
538         if (!dbus_message_get_args(
539                 m, &error,
540                 DBUS_TYPE_INT32, &interface,
541                 DBUS_TYPE_INT32, &protocol,
542                 DBUS_TYPE_STRING, &address,
543                 DBUS_TYPE_UINT32, &flags, 
544                 DBUS_TYPE_INVALID) || !address) {
545             avahi_log_warn("Error parsing Server::ResolveAddress message");
546             goto fail;
547         }
548
549         if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
550             return avahi_dbus_respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
551
552         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
553             avahi_log_warn("Too many clients, client request failed.");
554             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
555         }
556
557         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
558             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
559             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
560         }
561
562         i = avahi_new(SyncAddressResolverInfo, 1);
563         i->client = client;
564         i->message = dbus_message_ref(m);
565         AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i);
566         client->n_objects++;
567
568         if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, avahi_dbus_sync_address_resolver_callback, i))) {
569             avahi_dbus_sync_address_resolver_free(i);
570             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
571         }
572         
573         return DBUS_HANDLER_RESULT_HANDLED;
574         
575     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
576         Client *client;
577         DomainBrowserInfo *i;
578         static const DBusObjectPathVTable vtable = {
579             NULL,
580             avahi_dbus_msg_domain_browser_impl,
581             NULL,
582             NULL,
583             NULL,
584             NULL
585         };
586         int32_t interface, protocol, type;
587         uint32_t flags;
588         char *domain;
589         
590         if (!dbus_message_get_args(
591                 m, &error,
592                 DBUS_TYPE_INT32, &interface,
593                 DBUS_TYPE_INT32, &protocol,
594                 DBUS_TYPE_STRING, &domain,
595                 DBUS_TYPE_INT32, &type,
596                 DBUS_TYPE_UINT32, &flags,
597                 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
598             avahi_log_warn("Error parsing Server::DomainBrowserNew message");
599             goto fail;
600         }
601
602         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
603             avahi_log_warn("Too many clients, client request failed.");
604             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
605         }
606
607         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
608             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
609             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
610         }
611
612         if (!*domain)
613             domain = NULL;
614
615         i = avahi_new(DomainBrowserInfo, 1);
616         i->id = ++client->current_id;
617         i->client = client;
618         i->path = NULL;
619         AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
620         client->n_objects++;
621
622         if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, (AvahiLookupFlags) flags, avahi_dbus_domain_browser_callback, i))) {
623             avahi_dbus_domain_browser_free(i);
624             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
625         }
626
627         i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
628         dbus_connection_register_object_path(c, i->path, &vtable, i);
629         return avahi_dbus_respond_path(c, m, i->path);
630
631     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
632         Client *client;
633         ServiceTypeBrowserInfo *i;
634         static const DBusObjectPathVTable vtable = {
635             NULL,
636             avahi_dbus_msg_service_type_browser_impl,
637             NULL,
638             NULL,
639             NULL,
640             NULL
641         };
642         int32_t interface, protocol;
643         uint32_t flags;
644         char *domain;
645         
646         if (!dbus_message_get_args(
647                 m, &error,
648                 DBUS_TYPE_INT32, &interface,
649                 DBUS_TYPE_INT32, &protocol,
650                 DBUS_TYPE_STRING, &domain,
651                 DBUS_TYPE_UINT32, &flags,
652                 DBUS_TYPE_INVALID)) {
653             avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
654             goto fail;
655         }
656
657         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
658             avahi_log_warn("Too many clients, client request failed.");
659             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
660         }
661
662         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
663             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
664             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
665         }
666
667         if (!*domain)
668             domain = NULL;
669
670         i = avahi_new(ServiceTypeBrowserInfo, 1);
671         i->id = ++client->current_id;
672         i->client = client;
673         i->path = NULL;
674         AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
675         client->n_objects++;
676
677         if (!(i->service_type_browser = avahi_s_service_type_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiLookupFlags) flags, avahi_dbus_service_type_browser_callback, i))) {
678             avahi_dbus_service_type_browser_free(i);
679             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
680         }
681         
682         i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
683         dbus_connection_register_object_path(c, i->path, &vtable, i);
684         return avahi_dbus_respond_path(c, m, i->path);
685         
686     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
687         Client *client;
688         ServiceBrowserInfo *i;
689         static const DBusObjectPathVTable vtable = {
690             NULL,
691             avahi_dbus_msg_service_browser_impl,
692             NULL,
693             NULL,
694             NULL,
695             NULL
696         };
697         int32_t interface, protocol;
698         uint32_t flags;
699         char *domain, *type;
700         
701         if (!dbus_message_get_args(
702                 m, &error,
703                 DBUS_TYPE_INT32, &interface,
704                 DBUS_TYPE_INT32, &protocol,
705                 DBUS_TYPE_STRING, &type,
706                 DBUS_TYPE_STRING, &domain,
707                 DBUS_TYPE_UINT32, &flags,
708                 DBUS_TYPE_INVALID) || !type) {
709             avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
710             goto fail;
711         }
712
713         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
714             avahi_log_warn("Too many clients, client request failed.");
715             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
716         }
717
718         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
719             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
720             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
721         }
722
723         if (!*domain)
724             domain = NULL;
725
726         i = avahi_new(ServiceBrowserInfo, 1);
727         i->id = ++client->current_id;
728         i->client = client;
729         i->path = NULL;
730         AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
731         client->n_objects++;
732
733         if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, (AvahiLookupFlags) flags, avahi_dbus_service_browser_callback, i))) {
734             avahi_dbus_service_browser_free(i);
735             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
736         }
737
738         i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
739         dbus_connection_register_object_path(c, i->path, &vtable, i);
740         return avahi_dbus_respond_path(c, m, i->path);
741         
742     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
743         Client *client;
744         int32_t interface, protocol, aprotocol;
745         uint32_t flags;
746         char *name, *type, *domain;
747         SyncServiceResolverInfo *i;
748             
749         if (!dbus_message_get_args(
750                 m, &error,
751                 DBUS_TYPE_INT32, &interface,
752                 DBUS_TYPE_INT32, &protocol,
753                 DBUS_TYPE_STRING, &name,
754                 DBUS_TYPE_STRING, &type,
755                 DBUS_TYPE_STRING, &domain,
756                 DBUS_TYPE_INT32, &aprotocol,
757                 DBUS_TYPE_UINT32, &flags,
758                 DBUS_TYPE_INVALID) || !type) {
759             avahi_log_warn("Error parsing Server::ResolveService message");
760             goto fail;
761         }
762
763         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
764             avahi_log_warn("Too many clients, client request failed.");
765             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
766         }
767         
768         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
769             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
770             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
771         }
772
773         if (!*domain)
774             domain = NULL;
775
776         if (!*name)
777             name = NULL;
778         
779         i = avahi_new(SyncServiceResolverInfo, 1);
780         i->client = client;
781         i->message = dbus_message_ref(m);
782         AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i);
783         client->n_objects++;
784
785         if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, avahi_dbus_sync_service_resolver_callback, i))) {
786             avahi_dbus_sync_service_resolver_free(i);
787             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
788         }
789         
790         return DBUS_HANDLER_RESULT_HANDLED;
791         
792     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) {
793         Client *client;
794         int32_t interface, protocol, aprotocol;
795         uint32_t flags;
796         char *name, *type, *domain;
797         AsyncServiceResolverInfo *i;
798         static const DBusObjectPathVTable vtable = {
799             NULL,
800             avahi_dbus_msg_async_service_resolver_impl,
801             NULL,
802             NULL,
803             NULL,
804             NULL
805         };
806
807         if (!dbus_message_get_args(
808                 m, &error,
809                 DBUS_TYPE_INT32, &interface,
810                 DBUS_TYPE_INT32, &protocol,
811                 DBUS_TYPE_STRING, &name,
812                 DBUS_TYPE_STRING, &type,
813                 DBUS_TYPE_STRING, &domain,
814                 DBUS_TYPE_INT32, &aprotocol,
815                 DBUS_TYPE_UINT32, &flags,
816                 DBUS_TYPE_INVALID) || !type) {
817             avahi_log_warn("Error parsing Server::ServiceResolverNew message");
818             goto fail;
819         }
820             
821         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
822             avahi_log_warn(__FILE__": Too many clients, client request failed.");
823             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
824         }
825
826         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
827             avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
828             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
829         }
830
831         if (!*domain)
832             domain = NULL;
833
834         if (!*name)
835             name = NULL;
836         
837         i = avahi_new(AsyncServiceResolverInfo, 1);
838         i->id = ++client->current_id;
839         i->client = client;
840         i->path = NULL;
841         AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i);
842         client->n_objects++;
843
844         if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, avahi_dbus_async_service_resolver_callback, i))) {
845             avahi_dbus_async_service_resolver_free(i);
846             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
847         }
848
849 /*         avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */
850         
851         i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
852         dbus_connection_register_object_path(c, i->path, &vtable, i);
853         return avahi_dbus_respond_path(c, m, i->path);
854
855     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew")) {
856         Client *client;
857         int32_t interface, protocol, aprotocol;
858         uint32_t flags;
859         char *name;
860         AsyncHostNameResolverInfo *i;
861         static const DBusObjectPathVTable vtable = {
862             NULL,
863             avahi_dbus_msg_async_host_name_resolver_impl,
864             NULL,
865             NULL,
866             NULL,
867             NULL
868         };
869             
870         if (!dbus_message_get_args(
871                 m, &error,
872                 DBUS_TYPE_INT32, &interface,
873                 DBUS_TYPE_INT32, &protocol,
874                 DBUS_TYPE_STRING, &name,
875                 DBUS_TYPE_INT32, &aprotocol,
876                 DBUS_TYPE_UINT32, &flags,
877                 DBUS_TYPE_INVALID) || !name) {
878             avahi_log_warn("Error parsing Server::HostNameResolverNew message");
879             goto fail;
880         }
881             
882         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
883             avahi_log_warn(__FILE__": Too many clients, client request failed.");
884             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
885         }
886
887         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
888             avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
889             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
890         }
891
892         i = avahi_new(AsyncHostNameResolverInfo, 1);
893         i->id = ++client->current_id;
894         i->client = client;
895         i->path = NULL;
896         AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i);
897         client->n_objects++;
898
899         if (!(i->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, aprotocol, (AvahiLookupFlags) flags, avahi_dbus_async_host_name_resolver_callback, i))) {
900             avahi_dbus_async_host_name_resolver_free(i);
901             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
902         }
903
904         i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
905         dbus_connection_register_object_path(c, i->path, &vtable, i);
906         return avahi_dbus_respond_path(c, m, i->path);
907
908     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew")) {
909         Client *client;
910         int32_t interface, protocol;
911         uint32_t flags;
912         char *address;
913         AsyncAddressResolverInfo *i;
914         AvahiAddress a;
915         static const DBusObjectPathVTable vtable = {
916             NULL,
917             avahi_dbus_msg_async_address_resolver_impl,
918             NULL,
919             NULL,
920             NULL,
921             NULL
922         };
923             
924         if (!dbus_message_get_args(
925                 m, &error,
926                 DBUS_TYPE_INT32, &interface,
927                 DBUS_TYPE_INT32, &protocol,
928                 DBUS_TYPE_STRING, &address,
929                 DBUS_TYPE_UINT32, &flags,
930                 DBUS_TYPE_INVALID) || !address) {
931             avahi_log_warn("Error parsing Server::AddressResolverNew message");
932             goto fail;
933         }
934
935         if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
936             return avahi_dbus_respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
937
938         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
939             avahi_log_warn(__FILE__": Too many clients, client request failed.");
940             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
941         }
942
943         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
944             avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
945             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
946         }
947
948         i = avahi_new(AsyncAddressResolverInfo, 1);
949         i->id = ++client->current_id;
950         i->client = client;
951         i->path = NULL;
952         AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i);
953         client->n_objects++;
954
955         if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, avahi_dbus_async_address_resolver_callback, i))) {
956             avahi_dbus_async_address_resolver_free(i);
957             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
958         }
959
960         i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
961         dbus_connection_register_object_path(c, i->path, &vtable, i);
962         return avahi_dbus_respond_path(c, m, i->path);
963         
964     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "RecordBrowserNew")) {
965         Client *client;
966         RecordBrowserInfo *i;
967         static const DBusObjectPathVTable vtable = {
968             NULL,
969             avahi_dbus_msg_record_browser_impl,
970             NULL,
971             NULL,
972             NULL,
973             NULL
974         };
975         int32_t interface, protocol;
976         uint32_t flags;
977         char *name;
978         uint16_t type, clazz;
979         AvahiKey *key;
980         
981         if (!dbus_message_get_args(
982                 m, &error,
983                 DBUS_TYPE_INT32, &interface,
984                 DBUS_TYPE_INT32, &protocol,
985                 DBUS_TYPE_STRING, &name,
986                 DBUS_TYPE_UINT16, &clazz,
987                 DBUS_TYPE_UINT16, &type,
988                 DBUS_TYPE_UINT32, &flags,
989                 DBUS_TYPE_INVALID) || !name) {
990             avahi_log_warn("Error parsing Server::RecordBrowserNew message");
991             goto fail;
992         }
993
994         if (!avahi_is_valid_domain_name(name)) 
995             return avahi_dbus_respond_error(c, m, AVAHI_ERR_INVALID_DOMAIN_NAME, NULL);
996
997         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
998             avahi_log_warn("Too many clients, client request failed.");
999             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1000         }
1001
1002         if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
1003             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1004             return avahi_dbus_respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1005         }
1006
1007         i = avahi_new(RecordBrowserInfo, 1);
1008         i->id = ++client->current_id;
1009         i->client = client;
1010         i->path = NULL;
1011         AVAHI_LLIST_PREPEND(RecordBrowserInfo, record_browsers, client->record_browsers, i);
1012         client->n_objects++;
1013
1014         key = avahi_key_new(name, clazz, type);
1015         assert(key);
1016
1017         if (!(i->record_browser = avahi_s_record_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, key, (AvahiLookupFlags) flags, avahi_dbus_record_browser_callback, i))) {
1018             avahi_key_unref(key);
1019             avahi_dbus_record_browser_free(i);
1020             return avahi_dbus_respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1021         }
1022
1023         avahi_key_unref(key);
1024         
1025         i->path = avahi_strdup_printf("/Client%u/RecordBrowser%u", client->id, i->id);
1026         dbus_connection_register_object_path(c, i->path, &vtable, i);
1027         return avahi_dbus_respond_path(c, m, i->path);
1028     }
1029
1030     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1031
1032 fail:
1033     if (dbus_error_is_set(&error))
1034         dbus_error_free(&error);
1035     
1036     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1037 }
1038
1039 void dbus_protocol_server_state_changed(AvahiServerState state) {
1040     DBusMessage *m;
1041     int32_t t;
1042     const char *e;
1043     
1044     if (!server || !server->bus)
1045         return;
1046
1047     m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
1048     t = (int32_t) state;
1049
1050     if (state == AVAHI_SERVER_COLLISION)
1051         e = AVAHI_DBUS_ERR_COLLISION;
1052     else if (state == AVAHI_SERVER_FAILURE)
1053         e = avahi_error_number_to_dbus(avahi_server_errno(avahi_server));
1054     else
1055         e = AVAHI_DBUS_ERR_OK;
1056     
1057     dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_STRING, &e, DBUS_TYPE_INVALID);
1058     dbus_connection_send(server->bus, m, NULL);
1059     dbus_message_unref(m);
1060 }
1061
1062 static int dbus_connect(void) {
1063     DBusError error;
1064
1065     static const DBusObjectPathVTable server_vtable = {
1066         NULL,
1067         msg_server_impl,
1068         NULL,
1069         NULL,
1070         NULL,
1071         NULL
1072     };
1073
1074     assert(server);
1075     assert(!server->bus);
1076
1077     dbus_error_init(&error);
1078     
1079     if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
1080         assert(dbus_error_is_set(&error));
1081         avahi_log_error("dbus_bus_get(): %s", error.message);
1082         goto fail;
1083     }
1084     if (avahi_dbus_connection_glue(server->bus, server->poll_api) < 0) {
1085         avahi_log_error("avahi_dbus_connection_glue() failed");
1086         goto fail;
1087     }
1088
1089     dbus_connection_set_exit_on_disconnect(server->bus, FALSE);
1090     
1091     if (dbus_bus_request_name(
1092             server->bus,
1093             AVAHI_DBUS_NAME,
1094 #if (DBUS_VERSION_MAJOR == 0) && (DBUS_VERSION_MINOR >= 60)
1095             DBUS_NAME_FLAG_DO_NOT_QUEUE,
1096 #else
1097             DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT,
1098 #endif
1099             &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1100         if (dbus_error_is_set(&error)) {
1101             avahi_log_error("dbus_bus_request_name(): %s", error.message);
1102             goto fail;
1103         }
1104
1105         avahi_log_error("Failed to acquire D-Bus name '"AVAHI_DBUS_NAME"'");
1106         goto fail;
1107     }
1108
1109     if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) server->poll_api, NULL))) {
1110         avahi_log_error("dbus_connection_add_filter() failed");
1111         goto fail;
1112     }
1113     
1114     dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS  "'", &error);
1115
1116     if (dbus_error_is_set(&error)) {
1117         avahi_log_error("dbus_bus_add_match(): %s", error.message);
1118         goto fail;
1119     }
1120     
1121     if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
1122         avahi_log_error("dbus_connection_register_object_path() failed");
1123         goto fail;
1124     }
1125
1126     return 0;
1127 fail:
1128
1129     if (dbus_error_is_set(&error))
1130         dbus_error_free(&error);
1131
1132     if (server->bus) {
1133 #ifdef HAVE_DBUS_CONNECTION_CLOSE
1134         dbus_connection_close(server->bus);
1135 #else
1136         dbus_connection_disconnect(server->bus);
1137 #endif
1138         dbus_connection_unref(server->bus);
1139         server->bus = NULL;
1140     }
1141
1142     return -1;
1143 }
1144
1145 static void dbus_disconnect(void) {
1146     assert(server);
1147
1148     while (server->clients)
1149         client_free(server->clients);
1150     
1151     assert(server->n_clients == 0);
1152
1153     if (server->bus) {
1154 #ifdef HAVE_DBUS_CONNECTION_CLOSE
1155         dbus_connection_close(server->bus);
1156 #else
1157         dbus_connection_disconnect(server->bus);
1158 #endif
1159         dbus_connection_unref(server->bus);
1160         server->bus = NULL;
1161     }
1162 }
1163
1164 int dbus_protocol_setup(const AvahiPoll *poll_api, int _disable_user_service_publishing, int force) {
1165
1166     disable_user_service_publishing = _disable_user_service_publishing;
1167
1168     server = avahi_new(Server, 1);
1169     AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
1170     server->current_id = 0;
1171     server->n_clients = 0;
1172     server->bus = NULL;
1173     server->poll_api = poll_api;
1174     server->reconnect_timeout = NULL;
1175     server->reconnect = force;
1176
1177     if (dbus_connect() < 0) {
1178         struct timeval tv;
1179
1180         if (!force)
1181             goto fail;
1182
1183         avahi_log_warn("WARNING: Failed to contact D-Bus daemon, retrying in %ims.", RECONNECT_MSEC);
1184         
1185         avahi_elapse_time(&tv, RECONNECT_MSEC, 0);
1186         server->reconnect_timeout = server->poll_api->timeout_new(server->poll_api, &tv, reconnect_callback, NULL);
1187     }
1188         
1189     return 0;
1190
1191 fail:
1192     if (server->bus) {
1193 #ifdef HAVE_DBUS_CONNECTION_CLOSE
1194         dbus_connection_close(server->bus);
1195 #else
1196         dbus_connection_disconnect(server->bus);
1197 #endif
1198         dbus_connection_unref(server->bus);
1199     }
1200
1201     avahi_free(server);
1202     server = NULL;
1203     return -1;
1204 }
1205
1206 void dbus_protocol_shutdown(void) {
1207
1208     if (server) {
1209         dbus_disconnect();
1210
1211         if (server->reconnect_timeout)
1212             server->poll_api->timeout_free(server->reconnect_timeout);
1213         
1214         avahi_free(server);
1215         server = NULL;
1216     }
1217 }