]> git.meshlink.io Git - catta/blob - avahi-daemon/dbus-protocol.c
e5b099883474bac19573ccab28f7d86ba7cbc22a
[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         i->n_entries = 0;
756         return respond_ok(c, m);
757         
758     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) {
759         DBusMessage *reply;
760         int b;
761         
762         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
763             avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
764             goto fail;
765         }
766
767         b = !!avahi_s_entry_group_is_empty(i->entry_group);
768
769         reply = dbus_message_new_method_return(m);
770         dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
771         dbus_connection_send(c, reply, NULL);
772         dbus_message_unref(reply);
773         
774         return DBUS_HANDLER_RESULT_HANDLED;
775         
776     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
777         AvahiEntryGroupState state;
778         
779         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
780             avahi_log_warn("Error parsing EntryGroup::GetState message");
781             goto fail;
782         }
783
784         state = avahi_s_entry_group_get_state(i->entry_group);
785         return respond_int32(c, m, (int32_t) state);
786         
787     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
788         int32_t interface, protocol;
789         char *type, *name, *domain, *host;
790         uint16_t port;
791         AvahiStringList *strlst;
792         DBusMessageIter iter, sub;
793         int j;
794         
795         if (!dbus_message_get_args(
796                 m, &error,
797                 DBUS_TYPE_INT32, &interface,
798                 DBUS_TYPE_INT32, &protocol,
799                 DBUS_TYPE_STRING, &name,
800                 DBUS_TYPE_STRING, &type,
801                 DBUS_TYPE_STRING, &domain,
802                 DBUS_TYPE_STRING, &host,
803                 DBUS_TYPE_UINT16, &port, 
804                 DBUS_TYPE_INVALID) || !type || !name) {
805             avahi_log_warn("Error parsing EntryGroup::AddService message");
806             goto fail;
807         }
808
809         dbus_message_iter_init(m, &iter);
810
811         for (j = 0; j < 7; j++)
812             dbus_message_iter_next(&iter);
813         
814         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
815             dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY) {
816             avahi_log_warn("Error parsing EntryGroup::AddService message 2");
817             goto fail;
818         }
819
820         strlst = NULL;
821         dbus_message_iter_recurse(&iter, &sub);
822         
823         for (;;) {
824             DBusMessageIter sub2;
825             int at, n;
826             uint8_t *k;
827
828             if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
829                 break;
830
831             assert(at == DBUS_TYPE_ARRAY);
832             
833             if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) {
834                 avahi_log_warn("Error parsing EntryGroup::AddService message");
835                 goto fail;
836             }
837
838             dbus_message_iter_recurse(&sub, &sub2);
839             dbus_message_iter_get_fixed_array(&sub2, &k, &n);
840             strlst = avahi_string_list_add_arbitrary(strlst, k, n);
841             
842             dbus_message_iter_next(&sub);
843         }
844
845         if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
846             avahi_string_list_free(strlst);
847             avahi_log_warn("Too many entries per entry group, client request failed.");
848             return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
849         }
850
851         if (domain && !*domain)
852             domain = NULL;
853
854         if (host && !*host)
855             host = NULL;
856
857         if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, host, port, strlst) < 0) {
858             avahi_string_list_free(strlst);
859             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
860         } else
861             i->n_entries ++;
862         
863         avahi_string_list_free(strlst);
864         
865         return respond_ok(c, m);
866         
867     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
868         int32_t interface, protocol;
869         char *name, *address;
870         AvahiAddress a;
871         
872         if (!dbus_message_get_args(
873                 m, &error,
874                 DBUS_TYPE_INT32, &interface,
875                 DBUS_TYPE_INT32, &protocol,
876                 DBUS_TYPE_STRING, &name,
877                 DBUS_TYPE_STRING, &address,
878                 DBUS_TYPE_INVALID) || !name || !address) {
879             avahi_log_warn("Error parsing EntryGroup::AddAddress message");
880             goto fail;
881         }
882
883         if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
884             avahi_log_warn("Too many entries per entry group, client request failed.");
885             return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
886         }
887         
888         if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))) {
889             return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
890         }
891
892         if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, 0, name, &a) < 0)
893             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
894         else
895             i->n_entries ++;
896         
897         return respond_ok(c, m);
898     }
899     
900     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
901
902 fail:
903     if (dbus_error_is_set(&error))
904         dbus_error_free(&error);
905     
906     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
907 }
908
909 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) {
910     SyncHostNameResolverInfo *i = userdata;
911     
912     assert(r);
913     assert(host_name);
914     assert(i);
915
916     if (event == AVAHI_RESOLVER_FOUND) {
917         char t[256], *pt = t;
918         int32_t i_interface, i_protocol, i_aprotocol, i_flags;
919         DBusMessage *reply;
920
921         assert(a);
922         avahi_address_snprint(t, sizeof(t), a);
923
924         i_interface = (int32_t) interface;
925         i_protocol = (int32_t) protocol;
926         i_aprotocol = (int32_t) a->proto;
927         i_flags = (int32_t) flags;
928         
929         reply = dbus_message_new_method_return(i->message);
930         dbus_message_append_args(
931             reply,
932             DBUS_TYPE_INT32, &i_interface,
933             DBUS_TYPE_INT32, &i_protocol,
934             DBUS_TYPE_STRING, &host_name,
935             DBUS_TYPE_INT32, &i_aprotocol,
936             DBUS_TYPE_STRING, &pt,
937             DBUS_TYPE_INT32, &i_flags,
938             DBUS_TYPE_INVALID);
939
940         dbus_connection_send(server->bus, reply, NULL);
941         dbus_message_unref(reply);
942     } else
943         respond_error(server->bus, i->message, map_resolve_error(event), NULL);
944
945     sync_host_name_resolver_free(i);
946 }
947
948 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) {
949     SyncAddressResolverInfo *i = userdata;
950     
951     assert(r);
952     assert(address);
953     assert(i);
954
955     if (event == AVAHI_RESOLVER_FOUND) {
956         char t[256], *pt = t;
957         int32_t i_interface, i_protocol, i_aprotocol, i_flags;
958         DBusMessage *reply;
959
960         assert(host_name);
961         avahi_address_snprint(t, sizeof(t), address);
962
963         i_interface = (int32_t) interface;
964         i_protocol = (int32_t) protocol;
965         i_aprotocol = (int32_t) address->proto;
966         i_flags = (int32_t) flags;
967         
968         reply = dbus_message_new_method_return(i->message);
969         dbus_message_append_args(
970             reply,
971             DBUS_TYPE_INT32, &i_interface,
972             DBUS_TYPE_INT32, &i_protocol,
973             DBUS_TYPE_INT32, &i_aprotocol,
974             DBUS_TYPE_STRING, &pt,
975             DBUS_TYPE_STRING, &host_name,
976             DBUS_TYPE_INT32, &i_flags,
977             DBUS_TYPE_INVALID);
978
979         dbus_connection_send(server->bus, reply, NULL);
980         dbus_message_unref(reply);
981     } else
982         respond_error(server->bus, i->message, map_resolve_error(event), NULL);
983
984     sync_address_resolver_free(i);
985 }
986
987 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
988     DBusError error;
989     DomainBrowserInfo *i = userdata;
990
991     assert(c);
992     assert(m);
993     assert(i);
994     
995     dbus_error_init(&error);
996
997     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
998                     dbus_message_get_interface(m),
999                     dbus_message_get_path(m),
1000                     dbus_message_get_member(m));
1001
1002     /* Introspection */
1003     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1004         return handle_introspect(c, m, "DomainBrowser.introspect");
1005     
1006     /* Access control */
1007     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
1008         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1009     
1010     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
1011
1012         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1013             avahi_log_warn("Error parsing DomainBrowser::Free message");
1014             goto fail;
1015         }
1016
1017         domain_browser_free(i);
1018         return respond_ok(c, m);
1019         
1020     }
1021     
1022     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1023
1024 fail:
1025     if (dbus_error_is_set(&error))
1026         dbus_error_free(&error);
1027     
1028     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1029 }
1030
1031 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, AvahiLookupResultFlags flags,  void* userdata) {
1032     DomainBrowserInfo *i = userdata;
1033     DBusMessage *m;
1034     int32_t i_interface, i_protocol, i_flags;
1035     
1036     assert(b);
1037     assert(i);
1038
1039     i_interface = (int32_t) interface;
1040     i_protocol = (int32_t) protocol;
1041     i_flags = (int32_t) flags;
1042
1043     m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, map_browse_signal_name(event));
1044
1045     if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1046         assert(domain);
1047         dbus_message_append_args(
1048             m,
1049             DBUS_TYPE_INT32, &i_interface,
1050             DBUS_TYPE_INT32, &i_protocol,
1051             DBUS_TYPE_STRING, &domain,
1052             DBUS_TYPE_INT32, &i_flags,
1053             DBUS_TYPE_INVALID);
1054     }
1055     
1056     dbus_message_set_destination(m, i->client->name);   
1057     dbus_connection_send(server->bus, m, NULL);
1058     dbus_message_unref(m);
1059 }
1060
1061 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1062     DBusError error;
1063     ServiceTypeBrowserInfo *i = userdata;
1064
1065     assert(c);
1066     assert(m);
1067     assert(i);
1068     
1069     dbus_error_init(&error);
1070
1071     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1072                     dbus_message_get_interface(m),
1073                     dbus_message_get_path(m),
1074                     dbus_message_get_member(m));
1075
1076     /* Introspection */
1077     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1078         return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
1079     
1080     /* Access control */
1081     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
1082         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1083     
1084     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
1085
1086         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1087             avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
1088             goto fail;
1089         }
1090
1091         service_type_browser_free(i);
1092         return respond_ok(c, m);
1093         
1094     }
1095     
1096     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1097
1098 fail:
1099     if (dbus_error_is_set(&error))
1100         dbus_error_free(&error);
1101     
1102     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1103 }
1104
1105 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1106     ServiceTypeBrowserInfo *i = userdata;
1107     DBusMessage *m;
1108     int32_t i_interface, i_protocol, i_flags;
1109     
1110     assert(b);
1111     assert(i);
1112
1113     i_interface = (int32_t) interface;
1114     i_protocol = (int32_t) protocol;
1115     i_flags = (int32_t) flags;
1116
1117     m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, map_browse_signal_name(event));
1118
1119     if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1120         assert(type);
1121         assert(domain);
1122         dbus_message_append_args(
1123             m,
1124             DBUS_TYPE_INT32, &i_interface,
1125             DBUS_TYPE_INT32, &i_protocol,
1126             DBUS_TYPE_STRING, &type,
1127             DBUS_TYPE_STRING, &domain,
1128             DBUS_TYPE_INT32, &i_flags,
1129             DBUS_TYPE_INVALID);
1130     }
1131         
1132     dbus_message_set_destination(m, i->client->name);   
1133     dbus_connection_send(server->bus, m, NULL);
1134     dbus_message_unref(m);
1135 }
1136
1137 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1138     DBusError error;
1139     ServiceBrowserInfo *i = userdata;
1140
1141     assert(c);
1142     assert(m);
1143     assert(i);
1144     
1145     dbus_error_init(&error);
1146
1147     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1148                     dbus_message_get_interface(m),
1149                     dbus_message_get_path(m),
1150                     dbus_message_get_member(m));
1151
1152     /* Introspection */
1153     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1154         return handle_introspect(c, m, "ServiceBrowser.Introspect");
1155     
1156     /* Access control */
1157     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
1158         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1159     
1160     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
1161
1162         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1163             avahi_log_warn("Error parsing ServiceBrowser::Free message");
1164             goto fail;
1165         }
1166
1167         service_browser_free(i);
1168         return respond_ok(c, m);
1169         
1170     }
1171     
1172     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1173
1174 fail:
1175     if (dbus_error_is_set(&error))
1176         dbus_error_free(&error);
1177     
1178     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1179 }
1180
1181 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) {
1182     ServiceBrowserInfo *i = userdata;
1183     DBusMessage *m;
1184     int32_t i_interface, i_protocol, i_flags;
1185     
1186     assert(b);
1187     assert(i);
1188
1189     i_interface = (int32_t) interface;
1190     i_protocol = (int32_t) protocol;
1191     i_flags = (int32_t) flags;
1192
1193     m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, map_browse_signal_name(event));
1194
1195     if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1196         assert(name);
1197         assert(type);
1198         assert(domain);
1199         
1200         dbus_message_append_args(
1201             m,
1202             DBUS_TYPE_INT32, &i_interface,
1203             DBUS_TYPE_INT32, &i_protocol,
1204             DBUS_TYPE_STRING, &name,
1205             DBUS_TYPE_STRING, &type,
1206             DBUS_TYPE_STRING, &domain,
1207             DBUS_TYPE_INT32, &i_flags,
1208             DBUS_TYPE_INVALID);
1209     }
1210     
1211     dbus_message_set_destination(m, i->client->name);   
1212     dbus_connection_send(server->bus, m, NULL);
1213     dbus_message_unref(m);
1214 }
1215
1216 static void append_string_list(DBusMessage *reply, AvahiStringList *txt) {
1217     AvahiStringList *p;
1218     DBusMessageIter iter, sub;
1219     
1220     assert(reply);
1221
1222     dbus_message_iter_init_append(reply, &iter);
1223     dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1224     
1225     for (p = txt; p; p = p->next) {
1226         DBusMessageIter sub2;
1227         const uint8_t *data = p->text;
1228         
1229         dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1230         dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size); 
1231         dbus_message_iter_close_container(&sub, &sub2);
1232         
1233     }
1234     dbus_message_iter_close_container(&iter, &sub);
1235 }
1236
1237 static void sync_service_resolver_callback(
1238     AvahiSServiceResolver *r,
1239     AvahiIfIndex interface,
1240     AvahiProtocol protocol,
1241     AvahiResolverEvent event,
1242     const char *name,
1243     const char *type,
1244     const char *domain,
1245     const char *host_name,
1246     const AvahiAddress *a,
1247     uint16_t port,
1248     AvahiStringList *txt,
1249     AvahiLookupResultFlags flags, 
1250     void* userdata) {
1251     
1252     SyncServiceResolverInfo *i = userdata;
1253     
1254     assert(r);
1255     assert(i);
1256
1257     if (event == AVAHI_RESOLVER_FOUND) {
1258         char t[256], *pt = t;
1259         int32_t i_interface, i_protocol, i_aprotocol, i_flags;
1260         DBusMessage *reply;
1261     
1262         assert(host_name);
1263
1264         if (!name)
1265             name = "";
1266         
1267         assert(a);
1268         avahi_address_snprint(t, sizeof(t), a);
1269
1270         i_interface = (int32_t) interface;
1271         i_protocol = (int32_t) protocol;
1272         i_aprotocol = (int32_t) a->proto;
1273         i_flags = (int32_t) flags;
1274
1275         reply = dbus_message_new_method_return(i->message);
1276         dbus_message_append_args(
1277             reply,
1278             DBUS_TYPE_INT32, &i_interface,
1279             DBUS_TYPE_INT32, &i_protocol,
1280             DBUS_TYPE_STRING, &name,
1281             DBUS_TYPE_STRING, &type,
1282             DBUS_TYPE_STRING, &domain,
1283             DBUS_TYPE_STRING, &host_name,
1284             DBUS_TYPE_INT32, &i_aprotocol,
1285             DBUS_TYPE_STRING, &pt,
1286             DBUS_TYPE_UINT16, &port,
1287             DBUS_TYPE_INVALID);
1288
1289         append_string_list(reply, txt);
1290                 
1291         dbus_message_append_args(
1292             reply,
1293             DBUS_TYPE_INT32, &i_flags,
1294             DBUS_TYPE_INVALID);
1295
1296         dbus_connection_send(server->bus, reply, NULL);
1297         dbus_message_unref(reply);
1298     } else
1299         respond_error(server->bus, i->message, map_resolve_error(event), NULL);
1300
1301     sync_service_resolver_free(i);
1302 }
1303
1304 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) {
1305     AsyncAddressResolverInfo *i = userdata;
1306     DBusMessage *reply;
1307     
1308     assert(r);
1309     assert(i);
1310
1311     reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, map_browse_signal_name(event));
1312     
1313     if (event == AVAHI_RESOLVER_FOUND) {
1314         char t[256], *pt = t;
1315         int32_t i_interface, i_protocol, i_aprotocol, i_flags;
1316
1317         assert(address);
1318         assert(host_name);
1319         avahi_address_snprint(t, sizeof(t), address);
1320
1321         i_interface = (int32_t) interface;
1322         i_protocol = (int32_t) protocol;
1323         i_aprotocol = (int32_t) address->proto;
1324         i_flags = (int32_t) flags;
1325         
1326         dbus_message_append_args(
1327             reply,
1328             DBUS_TYPE_INT32, &i_interface,
1329             DBUS_TYPE_INT32, &i_protocol,
1330             DBUS_TYPE_INT32, &i_aprotocol,
1331             DBUS_TYPE_STRING, &pt,
1332             DBUS_TYPE_STRING, &host_name,
1333             DBUS_TYPE_INT32, &i_flags,
1334             DBUS_TYPE_INVALID);
1335
1336     }
1337
1338     dbus_message_set_destination(reply, i->client->name);  
1339     dbus_connection_send(server->bus, reply, NULL);
1340     dbus_message_unref(reply);
1341 }
1342
1343 static DBusHandlerResult msg_async_address_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1344     DBusError error;
1345     AsyncAddressResolverInfo *i = userdata;
1346
1347     assert(c);
1348     assert(m);
1349     assert(i);
1350     
1351     dbus_error_init(&error);
1352
1353     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1354                     dbus_message_get_interface(m),
1355                     dbus_message_get_path(m),
1356                     dbus_message_get_member(m));
1357
1358     /* Introspection */
1359     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1360         return handle_introspect(c, m, "AddressResolver.Introspect");
1361     
1362     /* Access control */
1363     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
1364         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1365     
1366     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Free")) {
1367
1368         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1369             avahi_log_warn("Error parsing AddressResolver::Free message");
1370             goto fail;
1371         }
1372
1373         async_address_resolver_free(i);
1374         return respond_ok(c, m);
1375         
1376     }
1377     
1378     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1379
1380 fail:
1381     if (dbus_error_is_set(&error))
1382         dbus_error_free(&error);
1383     
1384     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1385 }
1386
1387 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) {
1388     AsyncHostNameResolverInfo *i = userdata;
1389     DBusMessage *reply;
1390     
1391     assert(r);
1392     assert(i);
1393
1394     reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, map_resolve_signal_name(event));
1395     
1396     if (event == AVAHI_RESOLVER_FOUND) {
1397         char t[256], *pt = t;
1398         int32_t i_interface, i_protocol, i_aprotocol, i_flags;
1399
1400         assert(a);
1401         assert(host_name);
1402         avahi_address_snprint(t, sizeof(t), a);
1403
1404         i_interface = (int32_t) interface;
1405         i_protocol = (int32_t) protocol;
1406         i_aprotocol = (int32_t) a->proto;
1407         i_flags = (int32_t) flags;
1408         
1409         dbus_message_append_args(
1410             reply,
1411             DBUS_TYPE_INT32, &i_interface,
1412             DBUS_TYPE_INT32, &i_protocol,
1413             DBUS_TYPE_STRING, &host_name,
1414             DBUS_TYPE_INT32, &i_aprotocol,
1415             DBUS_TYPE_STRING, &pt,
1416             DBUS_TYPE_INT32, &i_flags,
1417             DBUS_TYPE_INVALID);
1418     }
1419
1420     dbus_message_set_destination(reply, i->client->name);  
1421     dbus_connection_send(server->bus, reply, NULL);
1422     dbus_message_unref(reply);
1423 }
1424
1425 static DBusHandlerResult msg_async_host_name_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1426     DBusError error;
1427     AsyncHostNameResolverInfo *i = userdata;
1428
1429     assert(c);
1430     assert(m);
1431     assert(i);
1432     
1433     dbus_error_init(&error);
1434
1435     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1436                     dbus_message_get_interface(m),
1437                     dbus_message_get_path(m),
1438                     dbus_message_get_member(m));
1439
1440     /* Introspection */
1441     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1442         return handle_introspect(c, m, "HostNameResolver.Introspect");
1443     
1444     /* Access control */
1445     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
1446         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1447     
1448     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, "Free")) {
1449
1450         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1451             avahi_log_warn("Error parsing HostNameResolver::Free message");
1452             goto fail;
1453         }
1454
1455         async_host_name_resolver_free(i);
1456         return respond_ok(c, m);
1457     }
1458     
1459     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1460
1461 fail:
1462     if (dbus_error_is_set(&error))
1463         dbus_error_free(&error);
1464     
1465     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1466 }
1467
1468 static void async_service_resolver_callback(
1469     AvahiSServiceResolver *r,
1470     AvahiIfIndex interface,
1471     AvahiProtocol protocol,
1472     AvahiResolverEvent event,
1473     const char *name,
1474     const char *type,
1475     const char *domain,
1476     const char *host_name,
1477     const AvahiAddress *a,
1478     uint16_t port,
1479     AvahiStringList *txt,
1480     AvahiLookupResultFlags flags, 
1481     void* userdata) {
1482
1483     AsyncServiceResolverInfo *i = userdata;
1484     DBusMessage *reply;
1485     
1486     assert(r);
1487     assert(i);
1488
1489     reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, map_resolve_signal_name(event));
1490     
1491     if (event == AVAHI_RESOLVER_FOUND) {
1492         char t[256], *pt = t;
1493         int32_t i_interface, i_protocol, i_aprotocol, i_flags;
1494     
1495         assert(host_name);
1496
1497 /*         avahi_log_debug(__FILE__": [%s] Successfully resolved service <%s.%s.%s>", i->path, name, type, domain); */
1498         
1499         assert(a);
1500         avahi_address_snprint(t, sizeof(t), a);
1501
1502         if (!name)
1503             name = "";
1504
1505         i_interface = (int32_t) interface;
1506         i_protocol = (int32_t) protocol;
1507         i_aprotocol = (int32_t) a->proto;
1508         i_flags = (int32_t) flags;
1509
1510         dbus_message_append_args(
1511             reply,
1512             DBUS_TYPE_INT32, &i_interface,
1513             DBUS_TYPE_INT32, &i_protocol,
1514             DBUS_TYPE_STRING, &name,
1515             DBUS_TYPE_STRING, &type,
1516             DBUS_TYPE_STRING, &domain,
1517             DBUS_TYPE_STRING, &host_name,
1518             DBUS_TYPE_INT32, &i_aprotocol,
1519             DBUS_TYPE_STRING, &pt,
1520             DBUS_TYPE_UINT16, &port,
1521             DBUS_TYPE_INVALID);
1522
1523         append_string_list(reply, txt);
1524
1525         dbus_message_append_args(
1526             reply,
1527             DBUS_TYPE_INT32, &i_flags,
1528             DBUS_TYPE_INVALID);
1529     }
1530
1531     dbus_message_set_destination(reply, i->client->name);  
1532     dbus_connection_send(server->bus, reply, NULL);
1533     dbus_message_unref(reply);
1534 }
1535
1536 static DBusHandlerResult msg_async_service_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1537     DBusError error;
1538     AsyncServiceResolverInfo *i = userdata;
1539
1540     assert(c);
1541     assert(m);
1542     assert(i);
1543     
1544     dbus_error_init(&error);
1545
1546     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1547                     dbus_message_get_interface(m),
1548                     dbus_message_get_path(m),
1549                     dbus_message_get_member(m));
1550
1551     /* Introspection */
1552     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1553         return handle_introspect(c, m, "ServiceResolver.Introspect");
1554     
1555     /* Access control */
1556     if (strcmp(dbus_message_get_sender(m), i->client->name)) 
1557         return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1558     
1559     if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, "Free")) {
1560
1561         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1562             avahi_log_warn("Error parsing ServiceResolver::Free message");
1563             goto fail;
1564         }
1565
1566         async_service_resolver_free(i);
1567         return respond_ok(c, m);
1568     }
1569     
1570     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1571
1572 fail:
1573     if (dbus_error_is_set(&error))
1574         dbus_error_free(&error);
1575     
1576     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1577 }
1578
1579 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1580     DBusError error;
1581
1582     dbus_error_init(&error);
1583
1584     avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1585                     dbus_message_get_interface(m),
1586                     dbus_message_get_path(m),
1587                     dbus_message_get_member(m));
1588
1589     if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1590         return handle_introspect(c, m, "Server.introspect");
1591         
1592     else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1593
1594         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1595             avahi_log_warn("Error parsing Server::GetHostName message");
1596             goto fail;
1597         }
1598
1599         return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1600         
1601     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1602
1603         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1604             avahi_log_warn("Error parsing Server::GetDomainName message");
1605             goto fail;
1606         }
1607
1608         return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1609
1610     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1611
1612         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1613             avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1614             goto fail;
1615         }
1616     
1617         return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1618         
1619     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1620
1621         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1622             avahi_log_warn("Error parsing Server::GetVersionString message");
1623             goto fail;
1624         }
1625     
1626         return respond_string(c, m, PACKAGE_STRING);
1627
1628     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1629         AvahiServerState state;
1630         
1631         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1632             avahi_log_warn("Error parsing Server::GetState message");
1633             goto fail;
1634         }
1635         
1636         state = avahi_server_get_state(avahi_server);
1637         return respond_int32(c, m, (int32_t) state);
1638
1639     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetLocalServiceCookie")) {
1640
1641         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1642             avahi_log_warn("Error parsing Server::GetLocalServiceCookie message");
1643             goto fail;
1644         }
1645         
1646         return respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server));
1647
1648     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "IsServiceLocal")) {
1649         int32_t interface, protocol;
1650         char *name, *type, *domain;
1651         int b;
1652         
1653         if (!dbus_message_get_args(
1654                 m, &error,
1655                 DBUS_TYPE_INT32, &interface,
1656                 DBUS_TYPE_INT32, &protocol,
1657                 DBUS_TYPE_STRING, &name,
1658                 DBUS_TYPE_STRING, &type,
1659                 DBUS_TYPE_STRING, &domain,
1660                 DBUS_TYPE_INVALID) || !name || !type || !domain) {
1661             avahi_log_warn("Error parsing Server::IsServiceLocal message");
1662             goto fail;
1663         }
1664
1665         if ((b = avahi_server_is_service_local(avahi_server, interface, protocol, name, type, domain)) < 0)
1666             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);            
1667         
1668         return respond_boolean(c, m, b);
1669
1670     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1671         int32_t idx;
1672         int fd;
1673         struct ifreq ifr;
1674         
1675         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1676             avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1677             goto fail;
1678         }
1679
1680 #ifdef VALGRIND_WORKAROUND
1681         return respond_string(c, m, "blah");
1682 #else
1683         
1684         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
1685             if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1686                 char txt[256];
1687                 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1688                 return respond_error(c, m, AVAHI_ERR_OS, txt);
1689             }
1690
1691         memset(&ifr, 0, sizeof(ifr));
1692         ifr.ifr_ifindex = idx;
1693
1694         if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) {
1695             char txt[256];
1696             snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1697             close(fd);
1698             return respond_error(c, m, AVAHI_ERR_OS, txt);
1699         }
1700
1701         close(fd);
1702         
1703         return respond_string(c, m, ifr.ifr_name);
1704 #endif
1705         
1706     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1707         char *n;
1708         int fd;
1709         struct ifreq ifr;
1710         
1711         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1712             avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1713             goto fail;
1714         }
1715
1716 #ifdef VALGRIND_WORKAROUND
1717         return respond_int32(c, m, 1);
1718 #else
1719         if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
1720             if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1721                 char txt[256];
1722                 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1723                 return respond_error(c, m, AVAHI_ERR_OS, txt);
1724             }
1725
1726         memset(&ifr, 0, sizeof(ifr));
1727         snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", n);
1728
1729         if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
1730             char txt[256];
1731             snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1732             close(fd);
1733             return respond_error(c, m, AVAHI_ERR_OS, txt);
1734         }
1735
1736         close(fd);
1737         
1738         return respond_int32(c, m, ifr.ifr_ifindex);
1739 #endif
1740
1741     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1742         char *n, * t;
1743         
1744         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1745             avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1746             goto fail;
1747         }
1748
1749         t = avahi_alternative_host_name(n);
1750         respond_string(c, m, t);
1751         avahi_free(t);
1752
1753         return DBUS_HANDLER_RESULT_HANDLED;
1754
1755     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1756         char *n, *t;
1757         
1758         if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1759             avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1760             goto fail;
1761         }
1762
1763         t = avahi_alternative_service_name(n);
1764         respond_string(c, m, t);
1765         avahi_free(t);
1766
1767         return DBUS_HANDLER_RESULT_HANDLED;
1768         
1769     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1770         Client *client;
1771         EntryGroupInfo *i;
1772         static const DBusObjectPathVTable vtable = {
1773             NULL,
1774             msg_entry_group_impl,
1775             NULL,
1776             NULL,
1777             NULL,
1778             NULL
1779         };
1780
1781         if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1782             avahi_log_warn("Error parsing Server::EntryGroupNew message");
1783             goto fail;
1784         }
1785
1786         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1787             avahi_log_warn("Too many clients, client request failed.");
1788             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1789         }
1790
1791         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1792             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1793             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1794         }
1795
1796         i = avahi_new(EntryGroupInfo, 1);
1797         i->id = ++client->current_id;
1798         i->client = client;
1799         i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1800         i->n_entries = 0;
1801         AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1802         client->n_objects++;
1803         
1804         if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1805             entry_group_free(i);
1806             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1807         }
1808
1809         dbus_connection_register_object_path(c, i->path, &vtable, i);
1810         return respond_path(c, m, i->path);
1811         
1812     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1813         Client *client;
1814         int32_t interface, protocol, aprotocol, flags;
1815         char *name;
1816         SyncHostNameResolverInfo *i;
1817             
1818         if (!dbus_message_get_args(
1819                 m, &error,
1820                 DBUS_TYPE_INT32, &interface,
1821                 DBUS_TYPE_INT32, &protocol,
1822                 DBUS_TYPE_STRING, &name,
1823                 DBUS_TYPE_INT32, &aprotocol,
1824                 DBUS_TYPE_INT32, &flags,
1825                 DBUS_TYPE_INVALID) || !name) {
1826             avahi_log_warn("Error parsing Server::ResolveHostName message");
1827             goto fail;
1828         }
1829
1830         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1831             avahi_log_warn("Too many clients, client request failed.");
1832             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1833         }
1834
1835         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1836             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1837             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1838         }
1839
1840         i = avahi_new(SyncHostNameResolverInfo, 1);
1841         i->client = client;
1842         i->message = dbus_message_ref(m);
1843         AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i);
1844         client->n_objects++;
1845
1846         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))) {
1847             sync_host_name_resolver_free(i);
1848             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1849         }
1850         
1851         return DBUS_HANDLER_RESULT_HANDLED;
1852         
1853     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1854         Client *client;
1855         int32_t interface, protocol, flags;
1856         char *address;
1857         SyncAddressResolverInfo *i;
1858         AvahiAddress a;
1859             
1860         if (!dbus_message_get_args(
1861                 m, &error,
1862                 DBUS_TYPE_INT32, &interface,
1863                 DBUS_TYPE_INT32, &protocol,
1864                 DBUS_TYPE_STRING, &address,
1865                 DBUS_TYPE_INT32, &flags, 
1866                 DBUS_TYPE_INVALID) || !address) {
1867             avahi_log_warn("Error parsing Server::ResolveAddress message");
1868             goto fail;
1869         }
1870
1871         if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
1872             return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
1873
1874         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1875             avahi_log_warn("Too many clients, client request failed.");
1876             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1877         }
1878
1879         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1880             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1881             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1882         }
1883
1884         i = avahi_new(SyncAddressResolverInfo, 1);
1885         i->client = client;
1886         i->message = dbus_message_ref(m);
1887         AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i);
1888         client->n_objects++;
1889
1890         if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, sync_address_resolver_callback, i))) {
1891             sync_address_resolver_free(i);
1892             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1893         }
1894         
1895         return DBUS_HANDLER_RESULT_HANDLED;
1896         
1897     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
1898         Client *client;
1899         DomainBrowserInfo *i;
1900         static const DBusObjectPathVTable vtable = {
1901             NULL,
1902             msg_domain_browser_impl,
1903             NULL,
1904             NULL,
1905             NULL,
1906             NULL
1907         };
1908         int32_t interface, protocol, type, flags;
1909         char *domain;
1910         
1911         if (!dbus_message_get_args(
1912                 m, &error,
1913                 DBUS_TYPE_INT32, &interface,
1914                 DBUS_TYPE_INT32, &protocol,
1915                 DBUS_TYPE_STRING, &domain,
1916                 DBUS_TYPE_INT32, &type,
1917                 DBUS_TYPE_INT32, &flags,
1918                 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
1919             avahi_log_warn("Error parsing Server::DomainBrowserNew message");
1920             goto fail;
1921         }
1922
1923         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1924             avahi_log_warn("Too many clients, client request failed.");
1925             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1926         }
1927
1928         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1929             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1930             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1931         }
1932
1933         if (!*domain)
1934             domain = NULL;
1935
1936         i = avahi_new(DomainBrowserInfo, 1);
1937         i->id = ++client->current_id;
1938         i->client = client;
1939         i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
1940         AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
1941         client->n_objects++;
1942
1943         if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, (AvahiLookupFlags) flags, domain_browser_callback, i))) {
1944             domain_browser_free(i);
1945             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1946         }
1947         
1948         dbus_connection_register_object_path(c, i->path, &vtable, i);
1949         return respond_path(c, m, i->path);
1950
1951     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
1952         Client *client;
1953         ServiceTypeBrowserInfo *i;
1954         static const DBusObjectPathVTable vtable = {
1955             NULL,
1956             msg_service_type_browser_impl,
1957             NULL,
1958             NULL,
1959             NULL,
1960             NULL
1961         };
1962         int32_t interface, protocol, flags;
1963         char *domain;
1964         
1965         if (!dbus_message_get_args(
1966                 m, &error,
1967                 DBUS_TYPE_INT32, &interface,
1968                 DBUS_TYPE_INT32, &protocol,
1969                 DBUS_TYPE_STRING, &domain,
1970                 DBUS_TYPE_INT32, &flags,
1971                 DBUS_TYPE_INVALID)) {
1972             avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
1973             goto fail;
1974         }
1975
1976         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1977             avahi_log_warn("Too many clients, client request failed.");
1978             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1979         }
1980
1981
1982         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1983             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1984             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1985         }
1986
1987         if (!*domain)
1988             domain = NULL;
1989
1990         i = avahi_new(ServiceTypeBrowserInfo, 1);
1991         i->id = ++client->current_id;
1992         i->client = client;
1993         i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
1994         AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
1995         client->n_objects++;
1996
1997         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))) {
1998             service_type_browser_free(i);
1999             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2000         }
2001         
2002         dbus_connection_register_object_path(c, i->path, &vtable, i);
2003         return respond_path(c, m, i->path);
2004         
2005     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
2006         Client *client;
2007         ServiceBrowserInfo *i;
2008         static const DBusObjectPathVTable vtable = {
2009             NULL,
2010             msg_service_browser_impl,
2011             NULL,
2012             NULL,
2013             NULL,
2014             NULL
2015         };
2016         int32_t interface, protocol, flags;
2017         char *domain, *type;
2018         
2019         if (!dbus_message_get_args(
2020                 m, &error,
2021                 DBUS_TYPE_INT32, &interface,
2022                 DBUS_TYPE_INT32, &protocol,
2023                 DBUS_TYPE_STRING, &type,
2024                 DBUS_TYPE_STRING, &domain,
2025                 DBUS_TYPE_INT32, &flags,
2026                 DBUS_TYPE_INVALID) || !type) {
2027             avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
2028             goto fail;
2029         }
2030
2031         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2032             avahi_log_warn("Too many clients, client request failed.");
2033             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2034         }
2035
2036
2037         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2038             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2039             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2040         }
2041
2042         if (!*domain)
2043             domain = NULL;
2044
2045         i = avahi_new(ServiceBrowserInfo, 1);
2046         i->id = ++client->current_id;
2047         i->client = client;
2048         i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
2049         AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
2050         client->n_objects++;
2051
2052         if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, (AvahiLookupFlags) flags, service_browser_callback, i))) {
2053             service_browser_free(i);
2054             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2055         }
2056         
2057         dbus_connection_register_object_path(c, i->path, &vtable, i);
2058         return respond_path(c, m, i->path);
2059         
2060     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
2061         Client *client;
2062         int32_t interface, protocol, aprotocol, flags;
2063         char *name, *type, *domain;
2064         SyncServiceResolverInfo *i;
2065             
2066         if (!dbus_message_get_args(
2067                 m, &error,
2068                 DBUS_TYPE_INT32, &interface,
2069                 DBUS_TYPE_INT32, &protocol,
2070                 DBUS_TYPE_STRING, &name,
2071                 DBUS_TYPE_STRING, &type,
2072                 DBUS_TYPE_STRING, &domain,
2073                 DBUS_TYPE_INT32, &aprotocol,
2074                 DBUS_TYPE_INT32, &flags,
2075                 DBUS_TYPE_INVALID) || !type) {
2076             avahi_log_warn("Error parsing Server::ResolveService message");
2077             goto fail;
2078         }
2079
2080         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2081             avahi_log_warn("Too many clients, client request failed.");
2082             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2083         }
2084         
2085         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2086             avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2087             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2088         }
2089
2090         if (!*domain)
2091             domain = NULL;
2092
2093         if (!*name)
2094             name = NULL;
2095         
2096         i = avahi_new(SyncServiceResolverInfo, 1);
2097         i->client = client;
2098         i->message = dbus_message_ref(m);
2099         AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i);
2100         client->n_objects++;
2101
2102         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))) {
2103             sync_service_resolver_free(i);
2104             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2105         }
2106         
2107         return DBUS_HANDLER_RESULT_HANDLED;
2108         
2109     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) {
2110         Client *client;
2111         int32_t interface, protocol, aprotocol, flags;
2112         char *name, *type, *domain;
2113         AsyncServiceResolverInfo *i;
2114         static const DBusObjectPathVTable vtable = {
2115             NULL,
2116             msg_async_service_resolver_impl,
2117             NULL,
2118             NULL,
2119             NULL,
2120             NULL
2121         };
2122
2123         if (!dbus_message_get_args(
2124                 m, &error,
2125                 DBUS_TYPE_INT32, &interface,
2126                 DBUS_TYPE_INT32, &protocol,
2127                 DBUS_TYPE_STRING, &name,
2128                 DBUS_TYPE_STRING, &type,
2129                 DBUS_TYPE_STRING, &domain,
2130                 DBUS_TYPE_INT32, &aprotocol,
2131                 DBUS_TYPE_INT32, &flags,
2132                 DBUS_TYPE_INVALID) || !type) {
2133             avahi_log_warn("Error parsing Server::ServiceResolverNew message");
2134             goto fail;
2135         }
2136             
2137         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2138             avahi_log_warn(__FILE__": Too many clients, client request failed.");
2139             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2140         }
2141
2142         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2143             avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2144             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2145         }
2146
2147         if (!*domain)
2148             domain = NULL;
2149
2150         if (!*name)
2151             name = NULL;
2152         
2153         i = avahi_new(AsyncServiceResolverInfo, 1);
2154         i->id = ++client->current_id;
2155         i->client = client;
2156         i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
2157         AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i);
2158         client->n_objects++;
2159
2160         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))) {
2161             async_service_resolver_free(i);
2162             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2163         }
2164
2165 /*         avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */
2166         
2167         dbus_connection_register_object_path(c, i->path, &vtable, i);
2168         return respond_path(c, m, i->path);
2169
2170     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew")) {
2171         Client *client;
2172         int32_t interface, protocol, aprotocol, flags;
2173         char *name;
2174         AsyncHostNameResolverInfo *i;
2175         static const DBusObjectPathVTable vtable = {
2176             NULL,
2177             msg_async_host_name_resolver_impl,
2178             NULL,
2179             NULL,
2180             NULL,
2181             NULL
2182         };
2183             
2184         if (!dbus_message_get_args(
2185                 m, &error,
2186                 DBUS_TYPE_INT32, &interface,
2187                 DBUS_TYPE_INT32, &protocol,
2188                 DBUS_TYPE_STRING, &name,
2189                 DBUS_TYPE_INT32, &aprotocol,
2190                 DBUS_TYPE_INT32, &flags,
2191                 DBUS_TYPE_INVALID) || !name) {
2192             avahi_log_warn("Error parsing Server::HostNameResolverNew message");
2193             goto fail;
2194         }
2195             
2196         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2197             avahi_log_warn(__FILE__": Too many clients, client request failed.");
2198             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2199         }
2200
2201         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2202             avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2203             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2204         }
2205
2206         i = avahi_new(AsyncHostNameResolverInfo, 1);
2207         i->id = ++client->current_id;
2208         i->client = client;
2209         i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
2210         AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i);
2211         client->n_objects++;
2212
2213         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))) {
2214             async_host_name_resolver_free(i);
2215             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2216         }
2217         
2218         dbus_connection_register_object_path(c, i->path, &vtable, i);
2219         return respond_path(c, m, i->path);
2220
2221     } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew")) {
2222         Client *client;
2223         int32_t interface, protocol, flags;
2224         char *address;
2225         AsyncAddressResolverInfo *i;
2226         AvahiAddress a;
2227         static const DBusObjectPathVTable vtable = {
2228             NULL,
2229             msg_async_address_resolver_impl,
2230             NULL,
2231             NULL,
2232             NULL,
2233             NULL
2234         };
2235             
2236         if (!dbus_message_get_args(
2237                 m, &error,
2238                 DBUS_TYPE_INT32, &interface,
2239                 DBUS_TYPE_INT32, &protocol,
2240                 DBUS_TYPE_STRING, &address,
2241                 DBUS_TYPE_INT32, &flags,
2242                 DBUS_TYPE_INVALID) || !address) {
2243             avahi_log_warn("Error parsing Server::AddressResolverNew message");
2244             goto fail;
2245         }
2246
2247         if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
2248             return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
2249
2250         if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2251             avahi_log_warn(__FILE__": Too many clients, client request failed.");
2252             return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2253         }
2254
2255         if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2256             avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2257             return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2258         }
2259
2260         i = avahi_new(AsyncAddressResolverInfo, 1);
2261         i->id = ++client->current_id;
2262         i->client = client;
2263         i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
2264         AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i);
2265         client->n_objects++;
2266
2267         if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, async_address_resolver_callback, i))) {
2268             async_address_resolver_free(i);
2269             return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2270         }
2271         
2272         dbus_connection_register_object_path(c, i->path, &vtable, i);
2273         return respond_path(c, m, i->path);
2274     }
2275
2276     avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
2277
2278 fail:
2279     if (dbus_error_is_set(&error))
2280         dbus_error_free(&error);
2281     
2282     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2283 }
2284
2285 void dbus_protocol_server_state_changed(AvahiServerState state) {
2286     DBusMessage *m;
2287     int32_t t;
2288     
2289     if (!server)
2290         return;
2291
2292     m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
2293     t = (int32_t) state;
2294     dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
2295     dbus_connection_send(server->bus, m, NULL);
2296     dbus_message_unref(m);
2297 }
2298
2299 int dbus_protocol_setup(const AvahiPoll *poll_api) {
2300     DBusError error;
2301
2302     static const DBusObjectPathVTable server_vtable = {
2303         NULL,
2304         msg_server_impl,
2305         NULL,
2306         NULL,
2307         NULL,
2308         NULL
2309     };
2310
2311     dbus_error_init(&error);
2312
2313     server = avahi_new(Server, 1);
2314     AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
2315     server->current_id = 0;
2316     server->n_clients = 0;
2317
2318     if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
2319         assert(dbus_error_is_set(&error));
2320         avahi_log_error("dbus_bus_get(): %s", error.message);
2321         goto fail;
2322     }
2323
2324     if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) {
2325         avahi_log_error("avahi_dbus_connection_glue() failed");
2326         goto fail;
2327     }
2328
2329     if (dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
2330         if (dbus_error_is_set(&error)) {
2331             avahi_log_error("dbus_bus_request_name(): %s", error.message);
2332             goto fail;
2333         }
2334
2335         avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'");
2336         goto fail;
2337     }
2338
2339     if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) {
2340         avahi_log_error("dbus_connection_add_filter() failed");
2341         goto fail;
2342     }
2343     
2344     dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS  "'", &error);
2345
2346     if (dbus_error_is_set(&error)) {
2347         avahi_log_error("dbus_bus_add_match(): %s", error.message);
2348         goto fail;
2349     }
2350     
2351     if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
2352         avahi_log_error("dbus_connection_register_object_path() failed");
2353         goto fail;
2354     }
2355
2356     return 0;
2357
2358 fail:
2359     if (server->bus) {
2360         dbus_connection_disconnect(server->bus);
2361         dbus_connection_unref(server->bus);
2362     }
2363
2364     if (dbus_error_is_set(&error))
2365         dbus_error_free(&error);
2366         
2367     avahi_free(server);
2368     server = NULL;
2369     return -1;
2370 }
2371
2372 void dbus_protocol_shutdown(void) {
2373
2374     if (server) {
2375     
2376         while (server->clients)
2377             client_free(server->clients);
2378
2379         assert(server->n_clients == 0);
2380
2381         if (server->bus) {
2382             dbus_connection_disconnect(server->bus);
2383             dbus_connection_unref(server->bus);
2384         }
2385
2386         avahi_free(server);
2387         server = NULL;
2388     }
2389 }