]> git.meshlink.io Git - catta/blob - avahi-daemon/dbus-protocol.c
* adapt to recent avahi-core API changes
[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 <net/if.h>
29 #include <errno.h>
30 #include <unistd.h>
31 #include <assert.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <stdio.h>
35 #include <signal.h>
36 #include <stdlib.h>
37
38 #include <dbus/dbus.h>
39
40 #include <avahi-common/dbus.h>
41 #include <avahi-common/llist.h>
42 #include <avahi-common/malloc.h>
43 #include <avahi-common/dbus.h>
44 #include <avahi-common/dbus-watch-glue.h>
45 #include <avahi-common/alternative.h>
46 #include <avahi-common/error.h>
47
48 #include <avahi-core/log.h>
49 #include <avahi-core/core.h>
50 #include <avahi-core/lookup.h>
51 #include <avahi-core/publish.h>
52
53 #include "dbus-protocol.h"
54 #include "main.h"
55
56 typedef struct Server Server;
57 typedef struct Client Client;
58 typedef struct EntryGroupInfo EntryGroupInfo;
59 typedef struct SyncHostNameResolverInfo SyncHostNameResolverInfo;
60 typedef struct AsyncHostNameResolverInfo AsyncHostNameResolverInfo;
61 typedef struct SyncAddressResolverInfo SyncAddressResolverInfo;
62 typedef struct AsyncAddressResolverInfo AsyncAddressResolverInfo;
63 typedef struct DomainBrowserInfo DomainBrowserInfo;
64 typedef struct ServiceTypeBrowserInfo ServiceTypeBrowserInfo;
65 typedef struct ServiceBrowserInfo ServiceBrowserInfo;
66 typedef struct SyncServiceResolverInfo SyncServiceResolverInfo;
67 typedef struct AsyncServiceResolverInfo AsyncServiceResolverInfo;
68
69 #define MAX_CLIENTS 20
70 #define MAX_OBJECTS_PER_CLIENT 50
71 #define MAX_ENTRIES_PER_ENTRY_GROUP 20
72
73 /* #define VALGRIND_WORKAROUND 1 */
74
75 struct EntryGroupInfo {
76     unsigned id;
77     Client *client;
78     AvahiSEntryGroup *entry_group;
79     char *path;
80
81     int n_entries;
82     
83     AVAHI_LLIST_FIELDS(EntryGroupInfo, entry_groups);
84 };
85
86 struct SyncHostNameResolverInfo {
87     Client *client;
88     AvahiSHostNameResolver *host_name_resolver;
89     DBusMessage *message;
90
91     AVAHI_LLIST_FIELDS(SyncHostNameResolverInfo, sync_host_name_resolvers);
92 };
93
94 struct AsyncHostNameResolverInfo {
95     unsigned id;
96     Client *client;
97     AvahiSHostNameResolver *host_name_resolver;
98     char *path;
99
100     AVAHI_LLIST_FIELDS(AsyncHostNameResolverInfo, async_host_name_resolvers);
101 };
102
103 struct SyncAddressResolverInfo {
104     Client *client;
105     AvahiSAddressResolver *address_resolver;
106     DBusMessage *message;
107
108     AVAHI_LLIST_FIELDS(SyncAddressResolverInfo, sync_address_resolvers);
109 };
110
111 struct AsyncAddressResolverInfo {
112     unsigned id;
113     Client *client;
114     AvahiSAddressResolver *address_resolver;
115     char *path;
116
117     AVAHI_LLIST_FIELDS(AsyncAddressResolverInfo, async_address_resolvers);
118 };
119
120 struct DomainBrowserInfo {
121     unsigned id;
122     Client *client;
123     AvahiSDomainBrowser *domain_browser;
124     char *path;
125
126     AVAHI_LLIST_FIELDS(DomainBrowserInfo, domain_browsers);
127 };
128
129 struct ServiceTypeBrowserInfo {
130     unsigned id;
131     Client *client;
132     AvahiSServiceTypeBrowser *service_type_browser;
133     char *path;
134
135     AVAHI_LLIST_FIELDS(ServiceTypeBrowserInfo, service_type_browsers);
136 };
137
138 struct ServiceBrowserInfo {
139     unsigned id;
140     Client *client;
141     AvahiSServiceBrowser *service_browser;
142     char *path;
143
144     AVAHI_LLIST_FIELDS(ServiceBrowserInfo, service_browsers);
145 };
146
147 struct SyncServiceResolverInfo {
148     Client *client;
149     AvahiSServiceResolver *service_resolver;
150     DBusMessage *message;
151
152     AVAHI_LLIST_FIELDS(SyncServiceResolverInfo, sync_service_resolvers);
153 };
154
155 struct AsyncServiceResolverInfo {
156     unsigned id;
157     Client *client;
158     AvahiSServiceResolver *service_resolver;
159     char *path;
160
161     AVAHI_LLIST_FIELDS(AsyncServiceResolverInfo, async_service_resolvers);
162 };
163
164 struct Client {
165     unsigned id;
166     char *name;
167     unsigned current_id;
168     int n_objects;
169     
170     AVAHI_LLIST_FIELDS(Client, clients);
171     AVAHI_LLIST_HEAD(EntryGroupInfo, entry_groups);
172     AVAHI_LLIST_HEAD(SyncHostNameResolverInfo, sync_host_name_resolvers);
173     AVAHI_LLIST_HEAD(AsyncHostNameResolverInfo, async_host_name_resolvers);
174     AVAHI_LLIST_HEAD(SyncAddressResolverInfo, sync_address_resolvers);
175     AVAHI_LLIST_HEAD(AsyncAddressResolverInfo, async_address_resolvers);
176     AVAHI_LLIST_HEAD(DomainBrowserInfo, domain_browsers);
177     AVAHI_LLIST_HEAD(ServiceTypeBrowserInfo, service_type_browsers);
178     AVAHI_LLIST_HEAD(ServiceBrowserInfo, service_browsers);
179     AVAHI_LLIST_HEAD(SyncServiceResolverInfo, sync_service_resolvers);
180     AVAHI_LLIST_HEAD(AsyncServiceResolverInfo, async_service_resolvers);
181 };
182
183 struct Server {
184     DBusConnection *bus;
185     AVAHI_LLIST_HEAD(Client, clients);
186     int n_clients;
187     unsigned current_id;
188 };
189
190 static Server *server = NULL;
191
192 static void entry_group_free(EntryGroupInfo *i) {
193     assert(i);
194
195     if (i->entry_group)
196         avahi_s_entry_group_free(i->entry_group);
197     dbus_connection_unregister_object_path(server->bus, i->path);
198     avahi_free(i->path);
199     AVAHI_LLIST_REMOVE(EntryGroupInfo, entry_groups, i->client->entry_groups, i);
200
201     i->client->n_objects--;
202     assert(i->client->n_objects >= 0);
203     
204     avahi_free(i);
205 }
206
207 static void sync_host_name_resolver_free(SyncHostNameResolverInfo *i) {
208     assert(i);
209
210     if (i->host_name_resolver)
211         avahi_s_host_name_resolver_free(i->host_name_resolver);
212     dbus_message_unref(i->message);
213     AVAHI_LLIST_REMOVE(SyncHostNameResolverInfo, sync_host_name_resolvers, i->client->sync_host_name_resolvers, i);
214
215     i->client->n_objects--;
216     assert(i->client->n_objects >= 0);
217
218     avahi_free(i);
219 }
220
221 static void async_host_name_resolver_free(AsyncHostNameResolverInfo *i) {
222     assert(i);
223
224     if (i->host_name_resolver)
225         avahi_s_host_name_resolver_free(i->host_name_resolver);
226     dbus_connection_unregister_object_path(server->bus, i->path);
227     AVAHI_LLIST_REMOVE(AsyncHostNameResolverInfo, async_host_name_resolvers, i->client->async_host_name_resolvers, i);
228
229     i->client->n_objects--;
230     assert(i->client->n_objects >= 0);
231
232     avahi_free(i);
233 }
234
235 static void sync_address_resolver_free(SyncAddressResolverInfo *i) {
236     assert(i);
237
238     if (i->address_resolver)
239         avahi_s_address_resolver_free(i->address_resolver);
240     dbus_message_unref(i->message);
241     AVAHI_LLIST_REMOVE(SyncAddressResolverInfo, sync_address_resolvers, i->client->sync_address_resolvers, i);
242
243     i->client->n_objects--;
244     assert(i->client->n_objects >= 0);
245
246     avahi_free(i);
247 }
248
249 static void async_address_resolver_free(AsyncAddressResolverInfo *i) {
250     assert(i);
251
252     if (i->address_resolver)
253         avahi_s_address_resolver_free(i->address_resolver);
254     dbus_connection_unregister_object_path(server->bus, i->path);
255     AVAHI_LLIST_REMOVE(AsyncAddressResolverInfo, async_address_resolvers, i->client->async_address_resolvers, i);
256
257     i->client->n_objects--;
258     assert(i->client->n_objects >= 0);
259
260     avahi_free(i);
261 }
262
263 static void domain_browser_free(DomainBrowserInfo *i) {
264     assert(i);
265
266     if (i->domain_browser)
267         avahi_s_domain_browser_free(i->domain_browser);
268     dbus_connection_unregister_object_path(server->bus, i->path);
269     avahi_free(i->path);
270     AVAHI_LLIST_REMOVE(DomainBrowserInfo, domain_browsers, i->client->domain_browsers, i);
271
272     i->client->n_objects--;
273     assert(i->client->n_objects >= 0);
274
275     avahi_free(i);
276 }
277
278 static void service_type_browser_free(ServiceTypeBrowserInfo *i) {
279     assert(i);
280
281     if (i->service_type_browser)
282         avahi_s_service_type_browser_free(i->service_type_browser);
283     dbus_connection_unregister_object_path(server->bus, i->path);
284     avahi_free(i->path);
285     AVAHI_LLIST_REMOVE(ServiceTypeBrowserInfo, service_type_browsers, i->client->service_type_browsers, i);
286
287     i->client->n_objects--;
288     assert(i->client->n_objects >= 0);
289
290     avahi_free(i);
291 }
292
293 static void service_browser_free(ServiceBrowserInfo *i) {
294     assert(i);
295
296     if (i->service_browser)
297         avahi_s_service_browser_free(i->service_browser);
298     dbus_connection_unregister_object_path(server->bus, i->path);
299     avahi_free(i->path);
300     AVAHI_LLIST_REMOVE(ServiceBrowserInfo, service_browsers, i->client->service_browsers, i);
301
302     i->client->n_objects--;
303     assert(i->client->n_objects >= 0);
304
305     avahi_free(i);
306 }
307
308 static void sync_service_resolver_free(SyncServiceResolverInfo *i) {
309     assert(i);
310
311     if (i->service_resolver)
312         avahi_s_service_resolver_free(i->service_resolver);
313     dbus_message_unref(i->message);
314     AVAHI_LLIST_REMOVE(SyncServiceResolverInfo, sync_service_resolvers, i->client->sync_service_resolvers, i);
315
316     i->client->n_objects--;
317     assert(i->client->n_objects >= 0);
318
319     avahi_free(i);
320 }
321
322 static void async_service_resolver_free(AsyncServiceResolverInfo *i) {
323     assert(i);
324
325     if (i->service_resolver)
326         avahi_s_service_resolver_free(i->service_resolver);
327
328     dbus_connection_unregister_object_path(server->bus, i->path);
329     AVAHI_LLIST_REMOVE(AsyncServiceResolverInfo, async_service_resolvers, i->client->async_service_resolvers, i);
330
331     i->client->n_objects--;
332     assert(i->client->n_objects >= 0);
333
334     avahi_free(i);
335 }
336
337 static void client_free(Client *c) {
338     
339     assert(server);
340     assert(c);
341
342     while (c->entry_groups)
343         entry_group_free(c->entry_groups);
344
345     while (c->sync_host_name_resolvers)
346         sync_host_name_resolver_free(c->sync_host_name_resolvers);
347
348     while (c->async_host_name_resolvers)
349         async_host_name_resolver_free(c->async_host_name_resolvers);
350     
351     while (c->sync_address_resolvers)
352         sync_address_resolver_free(c->sync_address_resolvers);
353
354     while (c->async_address_resolvers)
355         async_address_resolver_free(c->async_address_resolvers);
356
357     while (c->domain_browsers)
358         domain_browser_free(c->domain_browsers);
359
360     while (c->service_type_browsers)
361         service_type_browser_free(c->service_type_browsers);
362
363     while (c->service_browsers)
364         service_browser_free(c->service_browsers);
365
366     while (c->sync_service_resolvers)
367         sync_service_resolver_free(c->sync_service_resolvers);
368
369     while (c->async_service_resolvers)
370         async_service_resolver_free(c->async_service_resolvers);
371
372     assert(c->n_objects == 0);
373     
374     avahi_free(c->name);
375     AVAHI_LLIST_REMOVE(Client, clients, server->clients, c);
376     avahi_free(c);
377
378     server->n_clients --;
379     assert(server->n_clients >= 0);
380 }
381
382 static Client *client_get(const char *name, int create) {
383     Client *client;
384
385     assert(server);
386     assert(name);
387
388     for (client = server->clients; client; client = client->clients_next)
389         if (!strcmp(name, client->name))
390             return client;
391
392     if (!create)
393         return NULL;
394
395     if (server->n_clients >= MAX_CLIENTS)
396         return NULL;
397     
398     /* If not existant yet, create a new entry */
399     client = avahi_new(Client, 1);
400     client->id = server->current_id++;
401     client->name = avahi_strdup(name);
402     client->current_id = 0;
403     client->n_objects = 0;
404     
405     AVAHI_LLIST_HEAD_INIT(EntryGroupInfo, client->entry_groups);
406     AVAHI_LLIST_HEAD_INIT(SyncHostNameResolverInfo, client->sync_host_name_resolvers);
407     AVAHI_LLIST_HEAD_INIT(AsyncHostNameResolverInfo, client->async_host_name_resolvers);
408     AVAHI_LLIST_HEAD_INIT(SyncAddressResolverInfo, client->sync_address_resolvers);
409     AVAHI_LLIST_HEAD_INIT(AsyncAddressResolverInfo, client->async_address_resolvers);
410     AVAHI_LLIST_HEAD_INIT(DomainBrowserInfo, client->domain_browsers);
411     AVAHI_LLIST_HEAD_INIT(ServiceTypeBrowserInfo, client->service_type_browsers);
412     AVAHI_LLIST_HEAD_INIT(ServiceBrowserInfo, client->service_browsers);
413     AVAHI_LLIST_HEAD_INIT(SyncServiceResolverInfo, client->sync_service_resolvers);
414     AVAHI_LLIST_HEAD_INIT(AsyncServiceResolverInfo, client->async_service_resolvers);
415
416     AVAHI_LLIST_PREPEND(Client, clients, server->clients, client);
417
418     server->n_clients++;
419     assert(server->n_clients > 0);
420     
421     return client;
422 }
423
424 static DBusHandlerResult respond_error(DBusConnection *c, DBusMessage *m, int error, const char *text) {
425     DBusMessage *reply;
426
427     assert(-error > -AVAHI_OK);
428     assert(-error < -AVAHI_ERR_MAX);
429
430     if (!text)
431         text = avahi_strerror(error);
432     
433     reply = dbus_message_new_error(m, avahi_error_number_to_dbus (error), text);
434     dbus_connection_send(c, reply, NULL);
435     dbus_message_unref(reply);
436
437     avahi_log_debug(__FILE__": Responding error '%s' (%i)", text, error);
438     
439     return DBUS_HANDLER_RESULT_HANDLED;
440 }
441
442 static DBusHandlerResult respond_string(DBusConnection *c, DBusMessage *m, const char *text) {
443     DBusMessage *reply;
444
445     reply = dbus_message_new_method_return(m);
446     dbus_message_append_args(reply, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID);
447     dbus_connection_send(c, reply, NULL);
448     dbus_message_unref(reply);
449     
450     return DBUS_HANDLER_RESULT_HANDLED;
451 }
452
453 static DBusHandlerResult respond_int32(DBusConnection *c, DBusMessage *m, int32_t i) {
454     DBusMessage *reply;
455
456     reply = dbus_message_new_method_return(m);
457     dbus_message_append_args(reply, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID);
458     dbus_connection_send(c, reply, NULL);
459     dbus_message_unref(reply);
460     
461     return DBUS_HANDLER_RESULT_HANDLED;
462 }
463
464 static DBusHandlerResult respond_uint32(DBusConnection *c, DBusMessage *m, uint32_t u) {
465     DBusMessage *reply;
466
467     reply = dbus_message_new_method_return(m);
468     dbus_message_append_args(reply, DBUS_TYPE_UINT32, &u, DBUS_TYPE_INVALID);
469     dbus_connection_send(c, reply, NULL);
470     dbus_message_unref(reply);
471     
472     return DBUS_HANDLER_RESULT_HANDLED;
473 }
474
475 static DBusHandlerResult respond_boolean(DBusConnection *c, DBusMessage *m, int b) {
476     DBusMessage *reply;
477
478     reply = dbus_message_new_method_return(m);
479     dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
480     dbus_connection_send(c, reply, NULL);
481     dbus_message_unref(reply);
482     
483     return DBUS_HANDLER_RESULT_HANDLED;
484 }
485
486 static DBusHandlerResult respond_ok(DBusConnection *c, DBusMessage *m) {
487     DBusMessage *reply;
488
489     reply = dbus_message_new_method_return(m);
490     dbus_connection_send(c, reply, NULL);
491     dbus_message_unref(reply);
492     
493     return DBUS_HANDLER_RESULT_HANDLED;
494 }
495
496 static DBusHandlerResult respond_path(DBusConnection *c, DBusMessage *m, const char *path) {
497     DBusMessage *reply;
498
499     reply = dbus_message_new_method_return(m);
500     dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
501     dbus_connection_send(c, reply, NULL);
502     dbus_message_unref(reply);
503     
504     return DBUS_HANDLER_RESULT_HANDLED;
505 }
506
507 static char *file_get_contents(char *fname) {
508     int fd = -1;
509     struct stat st;
510     ssize_t size;
511     char *buf = NULL;
512     
513     assert(fname);
514
515     if (!(fd = open(fname, O_RDONLY))) {
516         avahi_log_error("Failed to open %s: %s", fname, strerror(errno));
517         goto fail;
518     }
519
520     if (fstat(fd, &st) < 0) {
521         avahi_log_error("stat(%s) failed: %s", fname, strerror(errno));
522         goto fail;
523     }
524
525     if (!(S_ISREG(st.st_mode))) {
526         avahi_log_error("Invalid file %s", fname);
527         goto fail;
528     }
529
530     if (st.st_size > 1024*1024) { /** 1MB */
531         avahi_log_error("File too large %s", fname);
532         goto fail;
533     }
534
535     buf = avahi_new(char, st.st_size+1);
536
537     if ((size = read(fd, buf, st.st_size)) < 0) {
538         avahi_log_error("read() failed: %s\n", strerror(errno));
539         goto fail;
540     }
541
542     buf[size] = 0;
543
544     close(fd);
545     return buf;
546     
547 fail:
548     if (fd >= 0)
549         close(fd);
550
551     if (buf)
552         avahi_free(buf);
553
554     return NULL;
555         
556 }
557
558 static const char *map_browse_signal_name(AvahiBrowserEvent e) {
559     switch (e) {
560         case AVAHI_BROWSER_NEW : return "ItemNew";
561         case AVAHI_BROWSER_REMOVE : return "ItemRemove";
562         case AVAHI_BROWSER_FAILURE : return "Failure";
563         case AVAHI_BROWSER_NOT_FOUND : return "NotFound";
564         case AVAHI_BROWSER_CACHE_EXHAUSTED : return "CacheExhausted";
565         case AVAHI_BROWSER_ALL_FOR_NOW : return "AllForNow";
566     }
567
568     abort();
569 }
570
571 static const char *map_resolve_signal_name(AvahiResolverEvent e) {
572     switch (e) {
573         case AVAHI_RESOLVER_FOUND : return "Found";
574         case AVAHI_RESOLVER_TIMEOUT : return "Timeout";
575         case AVAHI_RESOLVER_FAILURE : return "Failure";
576         case AVAHI_RESOLVER_NOT_FOUND : return "NotFound";
577     }
578
579     abort();
580 }
581
582 static int map_resolve_error(AvahiResolverEvent e) {
583
584     switch(e) {
585         case AVAHI_RESOLVER_FOUND : abort();
586         case AVAHI_RESOLVER_TIMEOUT : return AVAHI_ERR_TIMEOUT;
587         case AVAHI_RESOLVER_FAILURE : return AVAHI_ERR_FAILURE;
588         case AVAHI_RESOLVER_NOT_FOUND : return AVAHI_ERR_NOT_FOUND;
589     }
590
591     abort();
592 }
593
594 static DBusHandlerResult handle_introspect(DBusConnection *c, DBusMessage *m, const char *fname) {
595     char *path, *contents;
596     DBusError error;
597     
598     assert(c);
599     assert(m);
600     assert(fname);
601
602     dbus_error_init(&error);
603
604     if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
605         avahi_log_error("Error parsing Introspect message: %s", error.message);
606         goto fail;
607     }
608     
609     path = avahi_strdup_printf("%s/%s", AVAHI_DBUS_INTROSPECTION_DIR, fname);
610     contents = file_get_contents(path);
611     avahi_free(path);
612     
613     if (!contents) {
614         avahi_log_error("Failed to load introspection data.");
615         goto fail;
616     }
617     
618     respond_string(c, m, contents);
619     avahi_free(contents);
620     
621     return DBUS_HANDLER_RESULT_HANDLED;
622
623 fail:
624     if (dbus_error_is_set(&error))
625         dbus_error_free(&error);
626     
627     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
628
629 }
630
631 static DBusHandlerResult msg_signal_filter_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
632     DBusError error;
633
634     dbus_error_init(&error);
635
636 /*     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s", */
637 /*                     dbus_message_get_interface(m), */
638 /*                     dbus_message_get_path(m), */
639 /*                     dbus_message_get_member(m)); */
640
641     if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
642         /* No, we shouldn't quit, but until we get somewhere
643          * usefull such that we can restore our state, we will */
644         avahi_log_warn("Disconnnected from D-BUS, terminating...");
645         
646         raise(SIGQUIT); /* The signal handler will catch this and terminate the process cleanly*/
647         
648         return DBUS_HANDLER_RESULT_HANDLED;
649         
650     } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) {
651         char *name;
652
653         if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
654             avahi_log_warn("Error parsing NameAcquired message");
655             goto fail;
656         }
657
658 /*         avahi_log_info(__FILE__": name acquired (%s)", name); */
659         return DBUS_HANDLER_RESULT_HANDLED;
660         
661     } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
662         char *name, *old, *new;
663
664         if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) {
665             avahi_log_warn("Error parsing NameOwnerChanged message");
666             goto fail;
667         }
668
669         if (!*new) {
670             Client *client;
671
672             if ((client = client_get(name, FALSE))) {
673                 avahi_log_debug(__FILE__": client %s vanished.", name); 
674                 client_free(client);
675             }
676         }
677     }
678
679 fail:
680     if (dbus_error_is_set(&error))
681         dbus_error_free(&error);
682     
683     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
684 }
685
686 static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntryGroupState state, void* userdata) {
687     EntryGroupInfo *i = userdata;
688     DBusMessage *m;
689     int32_t t;
690     
691     assert(s);
692     assert(g);
693     assert(i);
694
695     m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged");
696     t = (int32_t) state;
697     dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
698     dbus_message_set_destination(m, i->client->name);  
699     dbus_connection_send(server->bus, m, NULL);
700     dbus_message_unref(m);
701 }
702
703 static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
704     DBusError error;
705     EntryGroupInfo *i = userdata;
706
707     assert(c);
708     assert(m);
709     assert(i);
710     
711     dbus_error_init(&error);
712
713     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
714                     dbus_message_get_interface(m),
715                     dbus_message_get_path(m),
716                     dbus_message_get_member(m));
717
718     /* Introspection */
719     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
720         return handle_introspect(c, m, "EntryGroup.introspect");
721     
722     /* Access control */
723     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
724         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
725     
726     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) {
727
728         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
729             avahi_log_warn("Error parsing EntryGroup::Free message");
730             goto fail;
731         }
732
733         entry_group_free(i);
734         return respond_ok(c, m);
735         
736     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Commit")) {
737
738         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
739             avahi_log_warn("Error parsing EntryGroup::Commit message");
740             goto fail;
741         }
742
743         avahi_s_entry_group_commit(i->entry_group);
744         return respond_ok(c, m);
745         
746         
747     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Reset")) {
748         
749         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
750             avahi_log_warn("Error parsing EntryGroup::Reset message");
751             goto fail;
752         }
753
754         avahi_s_entry_group_reset(i->entry_group);
755         return respond_ok(c, m);
756         
757     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) {
758         DBusMessage *reply;
759         int b;
760         
761         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
762             avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
763             goto fail;
764         }
765
766         b = !!avahi_s_entry_group_is_empty(i->entry_group);
767
768         reply = dbus_message_new_method_return(m);
769         dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
770         dbus_connection_send(c, reply, NULL);
771         dbus_message_unref(reply);
772         
773         return DBUS_HANDLER_RESULT_HANDLED;
774         
775     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
776         AvahiEntryGroupState state;
777         
778         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
779             avahi_log_warn("Error parsing EntryGroup::GetState message");
780             goto fail;
781         }
782
783         state = avahi_s_entry_group_get_state(i->entry_group);
784         return respond_int32(c, m, (int32_t) state);
785         
786     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
787         int32_t interface, protocol;
788         char *type, *name, *domain, *host;
789         uint16_t port;
790         AvahiStringList *strlst;
791         DBusMessageIter iter, sub;
792         int j;
793         
794         if (!dbus_message_get_args(
795                 m, &error,
796                 DBUS_TYPE_INT32, &interface,
797                 DBUS_TYPE_INT32, &protocol,
798                 DBUS_TYPE_STRING, &name,
799                 DBUS_TYPE_STRING, &type,
800                 DBUS_TYPE_STRING, &domain,
801                 DBUS_TYPE_STRING, &host,
802                 DBUS_TYPE_UINT16, &port, 
803                 DBUS_TYPE_INVALID) || !type || !name) {
804             avahi_log_warn("Error parsing EntryGroup::AddService message");
805             goto fail;
806         }
807
808         dbus_message_iter_init(m, &iter);
809
810         for (j = 0; j < 7; j++)
811             dbus_message_iter_next(&iter);
812         
813         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
814             dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY) {
815             avahi_log_warn("Error parsing EntryGroup::AddService message 2");
816             goto fail;
817         }
818
819         strlst = NULL;
820         dbus_message_iter_recurse(&iter, &sub);
821         
822         for (;;) {
823             DBusMessageIter sub2;
824             int at, n;
825             uint8_t *k;
826
827             if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
828                 break;
829
830             assert(at == DBUS_TYPE_ARRAY);
831             
832             if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) {
833                 avahi_log_warn("Error parsing EntryGroup::AddService message");
834                 goto fail;
835             }
836
837             dbus_message_iter_recurse(&sub, &sub2);
838             dbus_message_iter_get_fixed_array(&sub2, &k, &n);
839             strlst = avahi_string_list_add_arbitrary(strlst, k, n);
840             
841             dbus_message_iter_next(&sub);
842         }
843
844         if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
845             avahi_string_list_free(strlst);
846             avahi_log_warn("Too many entries per entry group, client request failed.");
847             return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
848         }
849
850         if (domain && !*domain)
851             domain = NULL;
852
853         if (host && !*host)
854             host = NULL;
855
856         if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, host, port, strlst) < 0) {
857             avahi_string_list_free(strlst);
858             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
859         } else
860             i->n_entries ++;
861         
862         avahi_string_list_free(strlst);
863         
864         return respond_ok(c, m);
865         
866     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
867         int32_t interface, protocol;
868         char *name, *address;
869         AvahiAddress a;
870         
871         if (!dbus_message_get_args(
872                 m, &error,
873                 DBUS_TYPE_INT32, &interface,
874                 DBUS_TYPE_INT32, &protocol,
875                 DBUS_TYPE_STRING, &name,
876                 DBUS_TYPE_STRING, &address,
877                 DBUS_TYPE_INVALID) || !name || !address) {
878             avahi_log_warn("Error parsing EntryGroup::AddAddress message");
879             goto fail;
880         }
881
882         if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
883             avahi_log_warn("Too many entries per entry group, client request failed.");
884             return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
885         }
886         
887         if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))) {
888             return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
889         }
890
891         if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, 0, name, &a) < 0)
892             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
893         else
894             i->n_entries ++;
895         
896         return respond_ok(c, m);
897     }
898     
899     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
900
901 fail:
902     if (dbus_error_is_set(&error))
903         dbus_error_free(&error);
904     
905     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
906 }
907
908 static void sync_host_name_resolver_callback(AvahiSHostNameResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *host_name, const AvahiAddress *a, AvahiLookupResultFlags flags, void* userdata) {
909     SyncHostNameResolverInfo *i = userdata;
910     
911     assert(r);
912     assert(host_name);
913     assert(i);
914
915     if (event == AVAHI_RESOLVER_FOUND) {
916         char t[256], *pt = t;
917         int32_t i_interface, i_protocol, i_aprotocol, i_flags;
918         DBusMessage *reply;
919
920         assert(a);
921         avahi_address_snprint(t, sizeof(t), a);
922
923         i_interface = (int32_t) interface;
924         i_protocol = (int32_t) protocol;
925         i_aprotocol = (int32_t) a->proto;
926         i_flags = (int32_t) flags;
927         
928         reply = dbus_message_new_method_return(i->message);
929         dbus_message_append_args(
930             reply,
931             DBUS_TYPE_INT32, &i_interface,
932             DBUS_TYPE_INT32, &i_protocol,
933             DBUS_TYPE_STRING, &host_name,
934             DBUS_TYPE_INT32, &i_aprotocol,
935             DBUS_TYPE_STRING, &pt,
936             DBUS_TYPE_INT32, &i_flags,
937             DBUS_TYPE_INVALID);
938
939         dbus_connection_send(server->bus, reply, NULL);
940         dbus_message_unref(reply);
941     } else
942         respond_error(server->bus, i->message, map_resolve_error(event), NULL);
943
944     sync_host_name_resolver_free(i);
945 }
946
947 static void sync_address_resolver_callback(AvahiSAddressResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const AvahiAddress *address, const char *host_name, AvahiLookupResultFlags flags, void* userdata) {
948     SyncAddressResolverInfo *i = userdata;
949     
950     assert(r);
951     assert(address);
952     assert(i);
953
954     if (event == AVAHI_RESOLVER_FOUND) {
955         char t[256], *pt = t;
956         int32_t i_interface, i_protocol, i_aprotocol, i_flags;
957         DBusMessage *reply;
958
959         assert(host_name);
960         avahi_address_snprint(t, sizeof(t), address);
961
962         i_interface = (int32_t) interface;
963         i_protocol = (int32_t) protocol;
964         i_aprotocol = (int32_t) address->proto;
965         i_flags = (int32_t) flags;
966         
967         reply = dbus_message_new_method_return(i->message);
968         dbus_message_append_args(
969             reply,
970             DBUS_TYPE_INT32, &i_interface,
971             DBUS_TYPE_INT32, &i_protocol,
972             DBUS_TYPE_INT32, &i_aprotocol,
973             DBUS_TYPE_STRING, &pt,
974             DBUS_TYPE_STRING, &host_name,
975             DBUS_TYPE_INT32, &i_flags,
976             DBUS_TYPE_INVALID);
977
978         dbus_connection_send(server->bus, reply, NULL);
979         dbus_message_unref(reply);
980     } else
981         respond_error(server->bus, i->message, map_resolve_error(event), NULL);
982
983     sync_address_resolver_free(i);
984 }
985
986 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
987     DBusError error;
988     DomainBrowserInfo *i = userdata;
989
990     assert(c);
991     assert(m);
992     assert(i);
993     
994     dbus_error_init(&error);
995
996     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
997                     dbus_message_get_interface(m),
998                     dbus_message_get_path(m),
999                     dbus_message_get_member(m));
1000
1001     /* Introspection */
1002     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1003         return handle_introspect(c, m, "DomainBrowser.introspect");
1004     
1005     /* Access control */
1006     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
1007         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1008     
1009     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
1010
1011         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1012             avahi_log_warn("Error parsing DomainBrowser::Free message");
1013             goto fail;
1014         }
1015
1016         domain_browser_free(i);
1017         return respond_ok(c, m);
1018         
1019     }
1020     
1021     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1022
1023 fail:
1024     if (dbus_error_is_set(&error))
1025         dbus_error_free(&error);
1026     
1027     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1028 }
1029
1030 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, AvahiLookupResultFlags flags,  void* userdata) {
1031     DomainBrowserInfo *i = userdata;
1032     DBusMessage *m;
1033     int32_t i_interface, i_protocol, i_flags;
1034     
1035     assert(b);
1036     assert(i);
1037
1038     i_interface = (int32_t) interface;
1039     i_protocol = (int32_t) protocol;
1040     i_flags = (int32_t) flags;
1041
1042     m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, map_browse_signal_name(event));
1043
1044     if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1045         assert(domain);
1046         dbus_message_append_args(
1047             m,
1048             DBUS_TYPE_INT32, &i_interface,
1049             DBUS_TYPE_INT32, &i_protocol,
1050             DBUS_TYPE_STRING, &domain,
1051             DBUS_TYPE_INT32, &i_flags,
1052             DBUS_TYPE_INVALID);
1053     }
1054     
1055     dbus_message_set_destination(m, i->client->name);   
1056     dbus_connection_send(server->bus, m, NULL);
1057     dbus_message_unref(m);
1058 }
1059
1060 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1061     DBusError error;
1062     ServiceTypeBrowserInfo *i = userdata;
1063
1064     assert(c);
1065     assert(m);
1066     assert(i);
1067     
1068     dbus_error_init(&error);
1069
1070     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1071                     dbus_message_get_interface(m),
1072                     dbus_message_get_path(m),
1073                     dbus_message_get_member(m));
1074
1075     /* Introspection */
1076     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1077         return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
1078     
1079     /* Access control */
1080     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
1081         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1082     
1083     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
1084
1085         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1086             avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
1087             goto fail;
1088         }
1089
1090         service_type_browser_free(i);
1091         return respond_ok(c, m);
1092         
1093     }
1094     
1095     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1096
1097 fail:
1098     if (dbus_error_is_set(&error))
1099         dbus_error_free(&error);
1100     
1101     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1102 }
1103
1104 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1105     ServiceTypeBrowserInfo *i = userdata;
1106     DBusMessage *m;
1107     int32_t i_interface, i_protocol, i_flags;
1108     
1109     assert(b);
1110     assert(i);
1111
1112     i_interface = (int32_t) interface;
1113     i_protocol = (int32_t) protocol;
1114     i_flags = (int32_t) flags;
1115
1116     m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, map_browse_signal_name(event));
1117
1118     if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1119         assert(type);
1120         assert(domain);
1121         dbus_message_append_args(
1122             m,
1123             DBUS_TYPE_INT32, &i_interface,
1124             DBUS_TYPE_INT32, &i_protocol,
1125             DBUS_TYPE_STRING, &type,
1126             DBUS_TYPE_STRING, &domain,
1127             DBUS_TYPE_INT32, &i_flags,
1128             DBUS_TYPE_INVALID);
1129     }
1130         
1131     dbus_message_set_destination(m, i->client->name);   
1132     dbus_connection_send(server->bus, m, NULL);
1133     dbus_message_unref(m);
1134 }
1135
1136 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1137     DBusError error;
1138     ServiceBrowserInfo *i = userdata;
1139
1140     assert(c);
1141     assert(m);
1142     assert(i);
1143     
1144     dbus_error_init(&error);
1145
1146     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1147                     dbus_message_get_interface(m),
1148                     dbus_message_get_path(m),
1149                     dbus_message_get_member(m));
1150
1151     /* Introspection */
1152     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1153         return handle_introspect(c, m, "ServiceBrowser.Introspect");
1154     
1155     /* Access control */
1156     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
1157         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1158     
1159     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
1160
1161         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1162             avahi_log_warn("Error parsing ServiceBrowser::Free message");
1163             goto fail;
1164         }
1165
1166         service_browser_free(i);
1167         return respond_ok(c, m);
1168         
1169     }
1170     
1171     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1172
1173 fail:
1174     if (dbus_error_is_set(&error))
1175         dbus_error_free(&error);
1176     
1177     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1178 }
1179
1180 static void service_browser_callback(AvahiSServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1181     ServiceBrowserInfo *i = userdata;
1182     DBusMessage *m;
1183     int32_t i_interface, i_protocol, i_flags;
1184     
1185     assert(b);
1186     assert(i);
1187
1188     i_interface = (int32_t) interface;
1189     i_protocol = (int32_t) protocol;
1190     i_flags = (int32_t) flags;
1191
1192     m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, map_browse_signal_name(event));
1193
1194     if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1195         assert(name);
1196         assert(type);
1197         assert(domain);
1198         
1199         dbus_message_append_args(
1200             m,
1201             DBUS_TYPE_INT32, &i_interface,
1202             DBUS_TYPE_INT32, &i_protocol,
1203             DBUS_TYPE_STRING, &name,
1204             DBUS_TYPE_STRING, &type,
1205             DBUS_TYPE_STRING, &domain,
1206             DBUS_TYPE_INT32, &i_flags,
1207             DBUS_TYPE_INVALID);
1208     }
1209     
1210     dbus_message_set_destination(m, i->client->name);   
1211     dbus_connection_send(server->bus, m, NULL);
1212     dbus_message_unref(m);
1213 }
1214
1215 static void append_string_list(DBusMessage *reply, AvahiStringList *txt) {
1216     AvahiStringList *p;
1217     DBusMessageIter iter, sub;
1218     
1219     assert(reply);
1220
1221     dbus_message_iter_init_append(reply, &iter);
1222     dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1223     
1224     for (p = txt; p; p = p->next) {
1225         DBusMessageIter sub2;
1226         const uint8_t *data = p->text;
1227         
1228         dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1229         dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size); 
1230         dbus_message_iter_close_container(&sub, &sub2);
1231         
1232     }
1233     dbus_message_iter_close_container(&iter, &sub);
1234 }
1235
1236 static void sync_service_resolver_callback(
1237     AvahiSServiceResolver *r,
1238     AvahiIfIndex interface,
1239     AvahiProtocol protocol,
1240     AvahiResolverEvent event,
1241     const char *name,
1242     const char *type,
1243     const char *domain,
1244     const char *host_name,
1245     const AvahiAddress *a,
1246     uint16_t port,
1247     AvahiStringList *txt,
1248     AvahiLookupResultFlags flags, 
1249     void* userdata) {
1250     
1251     SyncServiceResolverInfo *i = userdata;
1252     
1253     assert(r);
1254     assert(i);
1255
1256     if (event == AVAHI_RESOLVER_FOUND) {
1257         char t[256], *pt = t;
1258         int32_t i_interface, i_protocol, i_aprotocol, i_flags;
1259         DBusMessage *reply;
1260     
1261         assert(host_name);
1262
1263         if (!name)
1264             name = "";
1265         
1266         assert(a);
1267         avahi_address_snprint(t, sizeof(t), a);
1268
1269         i_interface = (int32_t) interface;
1270         i_protocol = (int32_t) protocol;
1271         i_aprotocol = (int32_t) a->proto;
1272         i_flags = (int32_t) flags;
1273
1274         reply = dbus_message_new_method_return(i->message);
1275         dbus_message_append_args(
1276             reply,
1277             DBUS_TYPE_INT32, &i_interface,
1278             DBUS_TYPE_INT32, &i_protocol,
1279             DBUS_TYPE_STRING, &name,
1280             DBUS_TYPE_STRING, &type,
1281             DBUS_TYPE_STRING, &domain,
1282             DBUS_TYPE_STRING, &host_name,
1283             DBUS_TYPE_INT32, &i_aprotocol,
1284             DBUS_TYPE_STRING, &pt,
1285             DBUS_TYPE_UINT16, &port,
1286             DBUS_TYPE_INVALID);
1287
1288         append_string_list(reply, txt);
1289                 
1290         dbus_message_append_args(
1291             reply,
1292             DBUS_TYPE_INT32, &i_flags,
1293             DBUS_TYPE_INVALID);
1294
1295         dbus_connection_send(server->bus, reply, NULL);
1296         dbus_message_unref(reply);
1297     } else
1298         respond_error(server->bus, i->message, map_resolve_error(event), NULL);
1299
1300     sync_service_resolver_free(i);
1301 }
1302
1303 static void async_address_resolver_callback(AvahiSAddressResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const AvahiAddress *address, const char *host_name, AvahiLookupResultFlags flags, void* userdata) {
1304     AsyncAddressResolverInfo *i = userdata;
1305     DBusMessage *reply;
1306     
1307     assert(r);
1308     assert(i);
1309
1310     reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, map_browse_signal_name(event));
1311     
1312     if (event == AVAHI_RESOLVER_FOUND) {
1313         char t[256], *pt = t;
1314         int32_t i_interface, i_protocol, i_aprotocol, i_flags;
1315
1316         assert(address);
1317         assert(host_name);
1318         avahi_address_snprint(t, sizeof(t), address);
1319
1320         i_interface = (int32_t) interface;
1321         i_protocol = (int32_t) protocol;
1322         i_aprotocol = (int32_t) address->proto;
1323         i_flags = (int32_t) flags;
1324         
1325         dbus_message_append_args(
1326             reply,
1327             DBUS_TYPE_INT32, &i_interface,
1328             DBUS_TYPE_INT32, &i_protocol,
1329             DBUS_TYPE_INT32, &i_aprotocol,
1330             DBUS_TYPE_STRING, &pt,
1331             DBUS_TYPE_STRING, &host_name,
1332             DBUS_TYPE_INT32, &i_flags,
1333             DBUS_TYPE_INVALID);
1334
1335     }
1336
1337     dbus_message_set_destination(reply, i->client->name);  
1338     dbus_connection_send(server->bus, reply, NULL);
1339     dbus_message_unref(reply);
1340 }
1341
1342 static DBusHandlerResult msg_async_address_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1343     DBusError error;
1344     AsyncAddressResolverInfo *i = userdata;
1345
1346     assert(c);
1347     assert(m);
1348     assert(i);
1349     
1350     dbus_error_init(&error);
1351
1352     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1353                     dbus_message_get_interface(m),
1354                     dbus_message_get_path(m),
1355                     dbus_message_get_member(m));
1356
1357     /* Introspection */
1358     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1359         return handle_introspect(c, m, "AddressResolver.Introspect");
1360     
1361     /* Access control */
1362     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
1363         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1364     
1365     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Free")) {
1366
1367         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1368             avahi_log_warn("Error parsing AddressResolver::Free message");
1369             goto fail;
1370         }
1371
1372         async_address_resolver_free(i);
1373         return respond_ok(c, m);
1374         
1375     }
1376     
1377     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1378
1379 fail:
1380     if (dbus_error_is_set(&error))
1381         dbus_error_free(&error);
1382     
1383     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1384 }
1385
1386 static void async_host_name_resolver_callback(AvahiSHostNameResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *host_name, const AvahiAddress *a, AvahiLookupResultFlags flags, void* userdata) {
1387     AsyncHostNameResolverInfo *i = userdata;
1388     DBusMessage *reply;
1389     
1390     assert(r);
1391     assert(i);
1392
1393     reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, map_resolve_signal_name(event));
1394     
1395     if (event == AVAHI_RESOLVER_FOUND) {
1396         char t[256], *pt = t;
1397         int32_t i_interface, i_protocol, i_aprotocol, i_flags;
1398
1399         assert(a);
1400         assert(host_name);
1401         avahi_address_snprint(t, sizeof(t), a);
1402
1403         i_interface = (int32_t) interface;
1404         i_protocol = (int32_t) protocol;
1405         i_aprotocol = (int32_t) a->proto;
1406         i_flags = (int32_t) flags;
1407         
1408         dbus_message_append_args(
1409             reply,
1410             DBUS_TYPE_INT32, &i_interface,
1411             DBUS_TYPE_INT32, &i_protocol,
1412             DBUS_TYPE_STRING, &host_name,
1413             DBUS_TYPE_INT32, &i_aprotocol,
1414             DBUS_TYPE_STRING, &pt,
1415             DBUS_TYPE_INT32, &i_flags,
1416             DBUS_TYPE_INVALID);
1417     }
1418
1419     dbus_message_set_destination(reply, i->client->name);  
1420     dbus_connection_send(server->bus, reply, NULL);
1421     dbus_message_unref(reply);
1422 }
1423
1424 static DBusHandlerResult msg_async_host_name_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1425     DBusError error;
1426     AsyncHostNameResolverInfo *i = userdata;
1427
1428     assert(c);
1429     assert(m);
1430     assert(i);
1431     
1432     dbus_error_init(&error);
1433
1434     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1435                     dbus_message_get_interface(m),
1436                     dbus_message_get_path(m),
1437                     dbus_message_get_member(m));
1438
1439     /* Introspection */
1440     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1441         return handle_introspect(c, m, "HostNameResolver.Introspect");
1442     
1443     /* Access control */
1444     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
1445         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1446     
1447     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, "Free")) {
1448
1449         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1450             avahi_log_warn("Error parsing HostNameResolver::Free message");
1451             goto fail;
1452         }
1453
1454         async_host_name_resolver_free(i);
1455         return respond_ok(c, m);
1456     }
1457     
1458     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1459
1460 fail:
1461     if (dbus_error_is_set(&error))
1462         dbus_error_free(&error);
1463     
1464     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1465 }
1466
1467 static void async_service_resolver_callback(
1468     AvahiSServiceResolver *r,
1469     AvahiIfIndex interface,
1470     AvahiProtocol protocol,
1471     AvahiResolverEvent event,
1472     const char *name,
1473     const char *type,
1474     const char *domain,
1475     const char *host_name,
1476     const AvahiAddress *a,
1477     uint16_t port,
1478     AvahiStringList *txt,
1479     AvahiLookupResultFlags flags, 
1480     void* userdata) {
1481
1482     AsyncServiceResolverInfo *i = userdata;
1483     DBusMessage *reply;
1484     
1485     assert(r);
1486     assert(i);
1487
1488     reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, map_resolve_signal_name(event));
1489     
1490     if (event == AVAHI_RESOLVER_FOUND) {
1491         char t[256], *pt = t;
1492         int32_t i_interface, i_protocol, i_aprotocol, i_flags;
1493     
1494         assert(host_name);
1495
1496 /*         avahi_log_debug(__FILE__": [%s] Successfully resolved service <%s.%s.%s>", i->path, name, type, domain); */
1497         
1498         assert(a);
1499         avahi_address_snprint(t, sizeof(t), a);
1500
1501         if (!name)
1502             name = "";
1503
1504         i_interface = (int32_t) interface;
1505         i_protocol = (int32_t) protocol;
1506         i_aprotocol = (int32_t) a->proto;
1507         i_flags = (int32_t) flags;
1508
1509         dbus_message_append_args(
1510             reply,
1511             DBUS_TYPE_INT32, &i_interface,
1512             DBUS_TYPE_INT32, &i_protocol,
1513             DBUS_TYPE_STRING, &name,
1514             DBUS_TYPE_STRING, &type,
1515             DBUS_TYPE_STRING, &domain,
1516             DBUS_TYPE_STRING, &host_name,
1517             DBUS_TYPE_INT32, &i_aprotocol,
1518             DBUS_TYPE_STRING, &pt,
1519             DBUS_TYPE_UINT16, &port,
1520             DBUS_TYPE_INVALID);
1521
1522         append_string_list(reply, txt);
1523
1524         dbus_message_append_args(
1525             reply,
1526             DBUS_TYPE_INT32, &i_flags,
1527             DBUS_TYPE_INVALID);
1528     }
1529
1530     dbus_message_set_destination(reply, i->client->name);  
1531     dbus_connection_send(server->bus, reply, NULL);
1532     dbus_message_unref(reply);
1533 }
1534
1535 static DBusHandlerResult msg_async_service_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1536     DBusError error;
1537     AsyncServiceResolverInfo *i = userdata;
1538
1539     assert(c);
1540     assert(m);
1541     assert(i);
1542     
1543     dbus_error_init(&error);
1544
1545     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1546                     dbus_message_get_interface(m),
1547                     dbus_message_get_path(m),
1548                     dbus_message_get_member(m));
1549
1550     /* Introspection */
1551     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1552         return handle_introspect(c, m, "ServiceResolver.Introspect");
1553     
1554     /* Access control */
1555     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
1556         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1557     
1558     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, "Free")) {
1559
1560         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1561             avahi_log_warn("Error parsing ServiceResolver::Free message");
1562             goto fail;
1563         }
1564
1565         async_service_resolver_free(i);
1566         return respond_ok(c, m);
1567     }
1568     
1569     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1570
1571 fail:
1572     if (dbus_error_is_set(&error))
1573         dbus_error_free(&error);
1574     
1575     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1576 }
1577
1578 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1579     DBusError error;
1580
1581     dbus_error_init(&error);
1582
1583     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1584                     dbus_message_get_interface(m),
1585                     dbus_message_get_path(m),
1586                     dbus_message_get_member(m));
1587
1588     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1589         return handle_introspect(c, m, "Server.introspect");
1590         
1591     else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1592
1593         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1594             avahi_log_warn("Error parsing Server::GetHostName message");
1595             goto fail;
1596         }
1597
1598         return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1599         
1600     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1601
1602         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1603             avahi_log_warn("Error parsing Server::GetDomainName message");
1604             goto fail;
1605         }
1606
1607         return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1608
1609     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1610
1611         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1612             avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1613             goto fail;
1614         }
1615     
1616         return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1617         
1618     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1619
1620         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1621             avahi_log_warn("Error parsing Server::GetVersionString message");
1622             goto fail;
1623         }
1624     
1625         return respond_string(c, m, PACKAGE_STRING);
1626
1627     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1628         AvahiServerState state;
1629         
1630         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1631             avahi_log_warn("Error parsing Server::GetState message");
1632             goto fail;
1633         }
1634         
1635         state = avahi_server_get_state(avahi_server);
1636         return respond_int32(c, m, (int32_t) state);
1637
1638     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetLocalServiceCookie")) {
1639
1640         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1641             avahi_log_warn("Error parsing Server::GetLocalServiceCookie message");
1642             goto fail;
1643         }
1644         
1645         return respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server));
1646
1647     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "IsServiceLocal")) {
1648         int32_t interface, protocol;
1649         char *name, *type, *domain;
1650         int b;
1651         
1652         if (!dbus_message_get_args(
1653                 m, &error,
1654                 DBUS_TYPE_INT32, &interface,
1655                 DBUS_TYPE_INT32, &protocol,
1656                 DBUS_TYPE_STRING, &name,
1657                 DBUS_TYPE_STRING, &type,
1658                 DBUS_TYPE_STRING, &domain,
1659                 DBUS_TYPE_INVALID) || !name || !type || !domain) {
1660             avahi_log_warn("Error parsing Server::IsServiceLocal message");
1661             goto fail;
1662         }
1663
1664         if ((b = avahi_server_is_service_local(avahi_server, interface, protocol, name, type, domain)) < 0)
1665             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);            
1666         
1667         return respond_boolean(c, m, b);
1668
1669     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1670         int32_t idx;
1671         int fd;
1672         struct ifreq ifr;
1673         
1674         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1675             avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1676             goto fail;
1677         }
1678
1679 #ifdef VALGRIND_WORKAROUND
1680         return respond_string(c, m, "blah");
1681 #else
1682         
1683         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
1684             if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1685                 char txt[256];
1686                 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1687                 return respond_error(c, m, AVAHI_ERR_OS, txt);
1688             }
1689
1690         memset(&ifr, 0, sizeof(ifr));
1691         ifr.ifr_ifindex = idx;
1692
1693         if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) {
1694             char txt[256];
1695             snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1696             close(fd);
1697             return respond_error(c, m, AVAHI_ERR_OS, txt);
1698         }
1699
1700         close(fd);
1701         
1702         return respond_string(c, m, ifr.ifr_name);
1703 #endif
1704         
1705     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1706         char *n;
1707         int fd;
1708         struct ifreq ifr;
1709         
1710         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1711             avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1712             goto fail;
1713         }
1714
1715 #ifdef VALGRIND_WORKAROUND
1716         return respond_int32(c, m, 1);
1717 #else
1718         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
1719             if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1720                 char txt[256];
1721                 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1722                 return respond_error(c, m, AVAHI_ERR_OS, txt);
1723             }
1724
1725         memset(&ifr, 0, sizeof(ifr));
1726         snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", n);
1727
1728         if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
1729             char txt[256];
1730             snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1731             close(fd);
1732             return respond_error(c, m, AVAHI_ERR_OS, txt);
1733         }
1734
1735         close(fd);
1736         
1737         return respond_int32(c, m, ifr.ifr_ifindex);
1738 #endif
1739
1740     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1741         char *n, * t;
1742         
1743         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1744             avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1745             goto fail;
1746         }
1747
1748         t = avahi_alternative_host_name(n);
1749         respond_string(c, m, t);
1750         avahi_free(t);
1751
1752         return DBUS_HANDLER_RESULT_HANDLED;
1753
1754     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1755         char *n, *t;
1756         
1757         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1758             avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1759             goto fail;
1760         }
1761
1762         t = avahi_alternative_service_name(n);
1763         respond_string(c, m, t);
1764         avahi_free(t);
1765
1766         return DBUS_HANDLER_RESULT_HANDLED;
1767         
1768     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1769         Client *client;
1770         EntryGroupInfo *i;
1771         static const DBusObjectPathVTable vtable = {
1772             NULL,
1773             msg_entry_group_impl,
1774             NULL,
1775             NULL,
1776             NULL,
1777             NULL
1778         };
1779
1780         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1781             avahi_log_warn("Error parsing Server::EntryGroupNew message");
1782             goto fail;
1783         }
1784
1785         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1786             avahi_log_warn("Too many clients, client request failed.");
1787             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1788         }
1789
1790         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1791             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1792             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1793         }
1794
1795         i = avahi_new(EntryGroupInfo, 1);
1796         i->id = ++client->current_id;
1797         i->client = client;
1798         i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1799         i->n_entries = 0;
1800         AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1801         client->n_objects++;
1802         
1803         if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1804             entry_group_free(i);
1805             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1806         }
1807
1808         dbus_connection_register_object_path(c, i->path, &vtable, i);
1809         return respond_path(c, m, i->path);
1810         
1811     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1812         Client *client;
1813         int32_t interface, protocol, aprotocol, flags;
1814         char *name;
1815         SyncHostNameResolverInfo *i;
1816             
1817         if (!dbus_message_get_args(
1818                 m, &error,
1819                 DBUS_TYPE_INT32, &interface,
1820                 DBUS_TYPE_INT32, &protocol,
1821                 DBUS_TYPE_STRING, &name,
1822                 DBUS_TYPE_INT32, &aprotocol,
1823                 DBUS_TYPE_INT32, &flags,
1824                 DBUS_TYPE_INVALID) || !name) {
1825             avahi_log_warn("Error parsing Server::ResolveHostName message");
1826             goto fail;
1827         }
1828
1829         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1830             avahi_log_warn("Too many clients, client request failed.");
1831             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1832         }
1833
1834         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1835             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1836             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1837         }
1838
1839         i = avahi_new(SyncHostNameResolverInfo, 1);
1840         i->client = client;
1841         i->message = dbus_message_ref(m);
1842         AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i);
1843         client->n_objects++;
1844
1845         if (!(i->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, sync_host_name_resolver_callback, i))) {
1846             sync_host_name_resolver_free(i);
1847             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1848         }
1849         
1850         return DBUS_HANDLER_RESULT_HANDLED;
1851         
1852     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1853         Client *client;
1854         int32_t interface, protocol, flags;
1855         char *address;
1856         SyncAddressResolverInfo *i;
1857         AvahiAddress a;
1858             
1859         if (!dbus_message_get_args(
1860                 m, &error,
1861                 DBUS_TYPE_INT32, &interface,
1862                 DBUS_TYPE_INT32, &protocol,
1863                 DBUS_TYPE_STRING, &address,
1864                 DBUS_TYPE_INT32, &flags, 
1865                 DBUS_TYPE_INVALID) || !address) {
1866             avahi_log_warn("Error parsing Server::ResolveAddress message");
1867             goto fail;
1868         }
1869
1870         if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
1871             return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
1872
1873         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1874             avahi_log_warn("Too many clients, client request failed.");
1875             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1876         }
1877
1878         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1879             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1880             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1881         }
1882
1883         i = avahi_new(SyncAddressResolverInfo, 1);
1884         i->client = client;
1885         i->message = dbus_message_ref(m);
1886         AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i);
1887         client->n_objects++;
1888
1889         if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, sync_address_resolver_callback, i))) {
1890             sync_address_resolver_free(i);
1891             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1892         }
1893         
1894         return DBUS_HANDLER_RESULT_HANDLED;
1895         
1896     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
1897         Client *client;
1898         DomainBrowserInfo *i;
1899         static const DBusObjectPathVTable vtable = {
1900             NULL,
1901             msg_domain_browser_impl,
1902             NULL,
1903             NULL,
1904             NULL,
1905             NULL
1906         };
1907         int32_t interface, protocol, type, flags;
1908         char *domain;
1909         
1910         if (!dbus_message_get_args(
1911                 m, &error,
1912                 DBUS_TYPE_INT32, &interface,
1913                 DBUS_TYPE_INT32, &protocol,
1914                 DBUS_TYPE_STRING, &domain,
1915                 DBUS_TYPE_INT32, &type,
1916                 DBUS_TYPE_INT32, &flags,
1917                 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
1918             avahi_log_warn("Error parsing Server::DomainBrowserNew message");
1919             goto fail;
1920         }
1921
1922         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1923             avahi_log_warn("Too many clients, client request failed.");
1924             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1925         }
1926
1927         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1928             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1929             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1930         }
1931
1932         if (!*domain)
1933             domain = NULL;
1934
1935         i = avahi_new(DomainBrowserInfo, 1);
1936         i->id = ++client->current_id;
1937         i->client = client;
1938         i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
1939         AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
1940         client->n_objects++;
1941
1942         if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, (AvahiLookupFlags) flags, domain_browser_callback, i))) {
1943             domain_browser_free(i);
1944             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1945         }
1946         
1947         dbus_connection_register_object_path(c, i->path, &vtable, i);
1948         return respond_path(c, m, i->path);
1949
1950     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
1951         Client *client;
1952         ServiceTypeBrowserInfo *i;
1953         static const DBusObjectPathVTable vtable = {
1954             NULL,
1955             msg_service_type_browser_impl,
1956             NULL,
1957             NULL,
1958             NULL,
1959             NULL
1960         };
1961         int32_t interface, protocol, flags;
1962         char *domain;
1963         
1964         if (!dbus_message_get_args(
1965                 m, &error,
1966                 DBUS_TYPE_INT32, &interface,
1967                 DBUS_TYPE_INT32, &protocol,
1968                 DBUS_TYPE_STRING, &domain,
1969                 DBUS_TYPE_INT32, &flags,
1970                 DBUS_TYPE_INVALID)) {
1971             avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
1972             goto fail;
1973         }
1974
1975         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1976             avahi_log_warn("Too many clients, client request failed.");
1977             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1978         }
1979
1980
1981         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1982             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1983             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1984         }
1985
1986         if (!*domain)
1987             domain = NULL;
1988
1989         i = avahi_new(ServiceTypeBrowserInfo, 1);
1990         i->id = ++client->current_id;
1991         i->client = client;
1992         i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
1993         AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
1994         client->n_objects++;
1995
1996         if (!(i->service_type_browser = avahi_s_service_type_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiLookupFlags) flags, service_type_browser_callback, i))) {
1997             service_type_browser_free(i);
1998             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1999         }
2000         
2001         dbus_connection_register_object_path(c, i->path, &vtable, i);
2002         return respond_path(c, m, i->path);
2003         
2004     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
2005         Client *client;
2006         ServiceBrowserInfo *i;
2007         static const DBusObjectPathVTable vtable = {
2008             NULL,
2009             msg_service_browser_impl,
2010             NULL,
2011             NULL,
2012             NULL,
2013             NULL
2014         };
2015         int32_t interface, protocol, flags;
2016         char *domain, *type;
2017         
2018         if (!dbus_message_get_args(
2019                 m, &error,
2020                 DBUS_TYPE_INT32, &interface,
2021                 DBUS_TYPE_INT32, &protocol,
2022                 DBUS_TYPE_STRING, &type,
2023                 DBUS_TYPE_STRING, &domain,
2024                 DBUS_TYPE_INT32, &flags,
2025                 DBUS_TYPE_INVALID) || !type) {
2026             avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
2027             goto fail;
2028         }
2029
2030         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2031             avahi_log_warn("Too many clients, client request failed.");
2032             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2033         }
2034
2035
2036         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2037             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2038             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2039         }
2040
2041         if (!*domain)
2042             domain = NULL;
2043
2044         i = avahi_new(ServiceBrowserInfo, 1);
2045         i->id = ++client->current_id;
2046         i->client = client;
2047         i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
2048         AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
2049         client->n_objects++;
2050
2051         if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, (AvahiLookupFlags) flags, service_browser_callback, i))) {
2052             service_browser_free(i);
2053             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2054         }
2055         
2056         dbus_connection_register_object_path(c, i->path, &vtable, i);
2057         return respond_path(c, m, i->path);
2058         
2059     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
2060         Client *client;
2061         int32_t interface, protocol, aprotocol, flags;
2062         char *name, *type, *domain;
2063         SyncServiceResolverInfo *i;
2064             
2065         if (!dbus_message_get_args(
2066                 m, &error,
2067                 DBUS_TYPE_INT32, &interface,
2068                 DBUS_TYPE_INT32, &protocol,
2069                 DBUS_TYPE_STRING, &name,
2070                 DBUS_TYPE_STRING, &type,
2071                 DBUS_TYPE_STRING, &domain,
2072                 DBUS_TYPE_INT32, &aprotocol,
2073                 DBUS_TYPE_INT32, &flags,
2074                 DBUS_TYPE_INVALID) || !type) {
2075             avahi_log_warn("Error parsing Server::ResolveService message");
2076             goto fail;
2077         }
2078
2079         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2080             avahi_log_warn("Too many clients, client request failed.");
2081             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2082         }
2083         
2084         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2085             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2086             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2087         }
2088
2089         if (!*domain)
2090             domain = NULL;
2091
2092         if (!*name)
2093             name = NULL;
2094         
2095         i = avahi_new(SyncServiceResolverInfo, 1);
2096         i->client = client;
2097         i->message = dbus_message_ref(m);
2098         AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i);
2099         client->n_objects++;
2100
2101         if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, sync_service_resolver_callback, i))) {
2102             sync_service_resolver_free(i);
2103             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2104         }
2105         
2106         return DBUS_HANDLER_RESULT_HANDLED;
2107         
2108     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) {
2109         Client *client;
2110         int32_t interface, protocol, aprotocol, flags;
2111         char *name, *type, *domain;
2112         AsyncServiceResolverInfo *i;
2113         static const DBusObjectPathVTable vtable = {
2114             NULL,
2115             msg_async_service_resolver_impl,
2116             NULL,
2117             NULL,
2118             NULL,
2119             NULL
2120         };
2121
2122         if (!dbus_message_get_args(
2123                 m, &error,
2124                 DBUS_TYPE_INT32, &interface,
2125                 DBUS_TYPE_INT32, &protocol,
2126                 DBUS_TYPE_STRING, &name,
2127                 DBUS_TYPE_STRING, &type,
2128                 DBUS_TYPE_STRING, &domain,
2129                 DBUS_TYPE_INT32, &aprotocol,
2130                 DBUS_TYPE_INT32, &flags,
2131                 DBUS_TYPE_INVALID) || !type) {
2132             avahi_log_warn("Error parsing Server::ServiceResolverNew message");
2133             goto fail;
2134         }
2135             
2136         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2137             avahi_log_warn(__FILE__": Too many clients, client request failed.");
2138             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2139         }
2140
2141         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2142             avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2143             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2144         }
2145
2146         if (!*domain)
2147             domain = NULL;
2148
2149         if (!*name)
2150             name = NULL;
2151         
2152         i = avahi_new(AsyncServiceResolverInfo, 1);
2153         i->id = ++client->current_id;
2154         i->client = client;
2155         i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
2156         AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i);
2157         client->n_objects++;
2158
2159         if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, async_service_resolver_callback, i))) {
2160             async_service_resolver_free(i);
2161             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2162         }
2163
2164 /*         avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */
2165         
2166         dbus_connection_register_object_path(c, i->path, &vtable, i);
2167         return respond_path(c, m, i->path);
2168
2169     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew")) {
2170         Client *client;
2171         int32_t interface, protocol, aprotocol, flags;
2172         char *name;
2173         AsyncHostNameResolverInfo *i;
2174         static const DBusObjectPathVTable vtable = {
2175             NULL,
2176             msg_async_host_name_resolver_impl,
2177             NULL,
2178             NULL,
2179             NULL,
2180             NULL
2181         };
2182             
2183         if (!dbus_message_get_args(
2184                 m, &error,
2185                 DBUS_TYPE_INT32, &interface,
2186                 DBUS_TYPE_INT32, &protocol,
2187                 DBUS_TYPE_STRING, &name,
2188                 DBUS_TYPE_INT32, &aprotocol,
2189                 DBUS_TYPE_INT32, &flags,
2190                 DBUS_TYPE_INVALID) || !name) {
2191             avahi_log_warn("Error parsing Server::HostNameResolverNew message");
2192             goto fail;
2193         }
2194             
2195         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2196             avahi_log_warn(__FILE__": Too many clients, client request failed.");
2197             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2198         }
2199
2200         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2201             avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2202             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2203         }
2204
2205         i = avahi_new(AsyncHostNameResolverInfo, 1);
2206         i->id = ++client->current_id;
2207         i->client = client;
2208         i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
2209         AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i);
2210         client->n_objects++;
2211
2212         if (!(i->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, aprotocol, (AvahiLookupFlags) flags, async_host_name_resolver_callback, i))) {
2213             async_host_name_resolver_free(i);
2214             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2215         }
2216         
2217         dbus_connection_register_object_path(c, i->path, &vtable, i);
2218         return respond_path(c, m, i->path);
2219
2220     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew")) {
2221         Client *client;
2222         int32_t interface, protocol, flags;
2223         char *address;
2224         AsyncAddressResolverInfo *i;
2225         AvahiAddress a;
2226         static const DBusObjectPathVTable vtable = {
2227             NULL,
2228             msg_async_address_resolver_impl,
2229             NULL,
2230             NULL,
2231             NULL,
2232             NULL
2233         };
2234             
2235         if (!dbus_message_get_args(
2236                 m, &error,
2237                 DBUS_TYPE_INT32, &interface,
2238                 DBUS_TYPE_INT32, &protocol,
2239                 DBUS_TYPE_STRING, &address,
2240                 DBUS_TYPE_INT32, &flags,
2241                 DBUS_TYPE_INVALID) || !address) {
2242             avahi_log_warn("Error parsing Server::AddressResolverNew message");
2243             goto fail;
2244         }
2245
2246         if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
2247             return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
2248
2249         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2250             avahi_log_warn(__FILE__": Too many clients, client request failed.");
2251             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2252         }
2253
2254         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2255             avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2256             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2257         }
2258
2259         i = avahi_new(AsyncAddressResolverInfo, 1);
2260         i->id = ++client->current_id;
2261         i->client = client;
2262         i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
2263         AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i);
2264         client->n_objects++;
2265
2266         if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, async_address_resolver_callback, i))) {
2267             async_address_resolver_free(i);
2268             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2269         }
2270         
2271         dbus_connection_register_object_path(c, i->path, &vtable, i);
2272         return respond_path(c, m, i->path);
2273     }
2274
2275     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
2276
2277 fail:
2278     if (dbus_error_is_set(&error))
2279         dbus_error_free(&error);
2280     
2281     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2282 }
2283
2284 void dbus_protocol_server_state_changed(AvahiServerState state) {
2285     DBusMessage *m;
2286     int32_t t;
2287     
2288     if (!server)
2289         return;
2290
2291     m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
2292     t = (int32_t) state;
2293     dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
2294     dbus_connection_send(server->bus, m, NULL);
2295     dbus_message_unref(m);
2296 }
2297
2298 int dbus_protocol_setup(const AvahiPoll *poll_api) {
2299     DBusError error;
2300
2301     static const DBusObjectPathVTable server_vtable = {
2302         NULL,
2303         msg_server_impl,
2304         NULL,
2305         NULL,
2306         NULL,
2307         NULL
2308     };
2309
2310     dbus_error_init(&error);
2311
2312     server = avahi_new(Server, 1);
2313     AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
2314     server->current_id = 0;
2315     server->n_clients = 0;
2316
2317     if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
2318         assert(dbus_error_is_set(&error));
2319         avahi_log_error("dbus_bus_get(): %s", error.message);
2320         goto fail;
2321     }
2322
2323     if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) {
2324         avahi_log_error("avahi_dbus_connection_glue() failed");
2325         goto fail;
2326     }
2327
2328     if (dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
2329         if (dbus_error_is_set(&error)) {
2330             avahi_log_error("dbus_bus_request_name(): %s", error.message);
2331             goto fail;
2332         }
2333
2334         avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'");
2335         goto fail;
2336     }
2337
2338     if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) {
2339         avahi_log_error("dbus_connection_add_filter() failed");
2340         goto fail;
2341     }
2342     
2343     dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS  "'", &error);
2344
2345     if (dbus_error_is_set(&error)) {
2346         avahi_log_error("dbus_bus_add_match(): %s", error.message);
2347         goto fail;
2348     }
2349     
2350     if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
2351         avahi_log_error("dbus_connection_register_object_path() failed");
2352         goto fail;
2353     }
2354
2355     return 0;
2356
2357 fail:
2358     if (server->bus) {
2359         dbus_connection_disconnect(server->bus);
2360         dbus_connection_unref(server->bus);
2361     }
2362
2363     if (dbus_error_is_set(&error))
2364         dbus_error_free(&error);
2365         
2366     avahi_free(server);
2367     server = NULL;
2368     return -1;
2369 }
2370
2371 void dbus_protocol_shutdown(void) {
2372
2373     if (server) {
2374     
2375         while (server->clients)
2376             client_free(server->clients);
2377
2378         assert(server->n_clients == 0);
2379
2380         if (server->bus) {
2381             dbus_connection_disconnect(server->bus);
2382             dbus_connection_unref(server->bus);
2383         }
2384
2385         avahi_free(server);
2386         server = NULL;
2387     }
2388 }