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