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