4 This file is part of avahi.
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.
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.
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
27 #include <sys/ioctl.h>
38 #include <dbus/dbus.h>
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>
48 #include <avahi-core/log.h>
49 #include <avahi-core/core.h>
50 #include <avahi-core/lookup.h>
51 #include <avahi-core/publish.h>
53 #include "dbus-protocol.h"
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;
69 #define MAX_CLIENTS 20
70 #define MAX_OBJECTS_PER_CLIENT 50
71 #define MAX_ENTRIES_PER_ENTRY_GROUP 20
73 /* #define VALGRIND_WORKAROUND 1 */
75 struct EntryGroupInfo {
78 AvahiSEntryGroup *entry_group;
83 AVAHI_LLIST_FIELDS(EntryGroupInfo, entry_groups);
86 struct SyncHostNameResolverInfo {
88 AvahiSHostNameResolver *host_name_resolver;
91 AVAHI_LLIST_FIELDS(SyncHostNameResolverInfo, sync_host_name_resolvers);
94 struct AsyncHostNameResolverInfo {
97 AvahiSHostNameResolver *host_name_resolver;
100 AVAHI_LLIST_FIELDS(AsyncHostNameResolverInfo, async_host_name_resolvers);
103 struct SyncAddressResolverInfo {
105 AvahiSAddressResolver *address_resolver;
106 DBusMessage *message;
108 AVAHI_LLIST_FIELDS(SyncAddressResolverInfo, sync_address_resolvers);
111 struct AsyncAddressResolverInfo {
114 AvahiSAddressResolver *address_resolver;
117 AVAHI_LLIST_FIELDS(AsyncAddressResolverInfo, async_address_resolvers);
120 struct DomainBrowserInfo {
123 AvahiSDomainBrowser *domain_browser;
126 AVAHI_LLIST_FIELDS(DomainBrowserInfo, domain_browsers);
129 struct ServiceTypeBrowserInfo {
132 AvahiSServiceTypeBrowser *service_type_browser;
135 AVAHI_LLIST_FIELDS(ServiceTypeBrowserInfo, service_type_browsers);
138 struct ServiceBrowserInfo {
141 AvahiSServiceBrowser *service_browser;
144 AVAHI_LLIST_FIELDS(ServiceBrowserInfo, service_browsers);
147 struct SyncServiceResolverInfo {
149 AvahiSServiceResolver *service_resolver;
150 DBusMessage *message;
152 AVAHI_LLIST_FIELDS(SyncServiceResolverInfo, sync_service_resolvers);
155 struct AsyncServiceResolverInfo {
158 AvahiSServiceResolver *service_resolver;
161 AVAHI_LLIST_FIELDS(AsyncServiceResolverInfo, async_service_resolvers);
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);
185 AVAHI_LLIST_HEAD(Client, clients);
190 static Server *server = NULL;
192 static void entry_group_free(EntryGroupInfo *i) {
196 avahi_s_entry_group_free(i->entry_group);
197 dbus_connection_unregister_object_path(server->bus, i->path);
199 AVAHI_LLIST_REMOVE(EntryGroupInfo, entry_groups, i->client->entry_groups, i);
201 i->client->n_objects--;
202 assert(i->client->n_objects >= 0);
207 static void sync_host_name_resolver_free(SyncHostNameResolverInfo *i) {
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);
215 i->client->n_objects--;
216 assert(i->client->n_objects >= 0);
221 static void async_host_name_resolver_free(AsyncHostNameResolverInfo *i) {
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);
229 i->client->n_objects--;
230 assert(i->client->n_objects >= 0);
235 static void sync_address_resolver_free(SyncAddressResolverInfo *i) {
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);
243 i->client->n_objects--;
244 assert(i->client->n_objects >= 0);
249 static void async_address_resolver_free(AsyncAddressResolverInfo *i) {
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);
257 i->client->n_objects--;
258 assert(i->client->n_objects >= 0);
263 static void domain_browser_free(DomainBrowserInfo *i) {
266 if (i->domain_browser)
267 avahi_s_domain_browser_free(i->domain_browser);
268 dbus_connection_unregister_object_path(server->bus, i->path);
270 AVAHI_LLIST_REMOVE(DomainBrowserInfo, domain_browsers, i->client->domain_browsers, i);
272 i->client->n_objects--;
273 assert(i->client->n_objects >= 0);
278 static void service_type_browser_free(ServiceTypeBrowserInfo *i) {
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);
285 AVAHI_LLIST_REMOVE(ServiceTypeBrowserInfo, service_type_browsers, i->client->service_type_browsers, i);
287 i->client->n_objects--;
288 assert(i->client->n_objects >= 0);
293 static void service_browser_free(ServiceBrowserInfo *i) {
296 if (i->service_browser)
297 avahi_s_service_browser_free(i->service_browser);
298 dbus_connection_unregister_object_path(server->bus, i->path);
300 AVAHI_LLIST_REMOVE(ServiceBrowserInfo, service_browsers, i->client->service_browsers, i);
302 i->client->n_objects--;
303 assert(i->client->n_objects >= 0);
308 static void sync_service_resolver_free(SyncServiceResolverInfo *i) {
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);
316 i->client->n_objects--;
317 assert(i->client->n_objects >= 0);
322 static void async_service_resolver_free(AsyncServiceResolverInfo *i) {
325 if (i->service_resolver)
326 avahi_s_service_resolver_free(i->service_resolver);
328 dbus_connection_unregister_object_path(server->bus, i->path);
329 AVAHI_LLIST_REMOVE(AsyncServiceResolverInfo, async_service_resolvers, i->client->async_service_resolvers, i);
331 i->client->n_objects--;
332 assert(i->client->n_objects >= 0);
337 static void client_free(Client *c) {
342 while (c->entry_groups)
343 entry_group_free(c->entry_groups);
345 while (c->sync_host_name_resolvers)
346 sync_host_name_resolver_free(c->sync_host_name_resolvers);
348 while (c->async_host_name_resolvers)
349 async_host_name_resolver_free(c->async_host_name_resolvers);
351 while (c->sync_address_resolvers)
352 sync_address_resolver_free(c->sync_address_resolvers);
354 while (c->async_address_resolvers)
355 async_address_resolver_free(c->async_address_resolvers);
357 while (c->domain_browsers)
358 domain_browser_free(c->domain_browsers);
360 while (c->service_type_browsers)
361 service_type_browser_free(c->service_type_browsers);
363 while (c->service_browsers)
364 service_browser_free(c->service_browsers);
366 while (c->sync_service_resolvers)
367 sync_service_resolver_free(c->sync_service_resolvers);
369 while (c->async_service_resolvers)
370 async_service_resolver_free(c->async_service_resolvers);
372 assert(c->n_objects == 0);
375 AVAHI_LLIST_REMOVE(Client, clients, server->clients, c);
378 server->n_clients --;
379 assert(server->n_clients >= 0);
382 static Client *client_get(const char *name, int create) {
388 for (client = server->clients; client; client = client->clients_next)
389 if (!strcmp(name, client->name))
395 if (server->n_clients >= MAX_CLIENTS)
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;
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);
416 AVAHI_LLIST_PREPEND(Client, clients, server->clients, client);
419 assert(server->n_clients > 0);
424 static DBusHandlerResult respond_error(DBusConnection *c, DBusMessage *m, int error, const char *text) {
427 assert(-error > -AVAHI_OK);
428 assert(-error < -AVAHI_ERR_MAX);
431 text = avahi_strerror(error);
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);
437 avahi_log_debug(__FILE__": Responding error '%s' (%i)", text, error);
439 return DBUS_HANDLER_RESULT_HANDLED;
442 static DBusHandlerResult respond_string(DBusConnection *c, DBusMessage *m, const char *text) {
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);
450 return DBUS_HANDLER_RESULT_HANDLED;
453 static DBusHandlerResult respond_int32(DBusConnection *c, DBusMessage *m, int32_t i) {
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);
461 return DBUS_HANDLER_RESULT_HANDLED;
464 static DBusHandlerResult respond_uint32(DBusConnection *c, DBusMessage *m, uint32_t u) {
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);
472 return DBUS_HANDLER_RESULT_HANDLED;
475 static DBusHandlerResult respond_boolean(DBusConnection *c, DBusMessage *m, int b) {
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);
483 return DBUS_HANDLER_RESULT_HANDLED;
486 static DBusHandlerResult respond_ok(DBusConnection *c, DBusMessage *m) {
489 reply = dbus_message_new_method_return(m);
490 dbus_connection_send(c, reply, NULL);
491 dbus_message_unref(reply);
493 return DBUS_HANDLER_RESULT_HANDLED;
496 static DBusHandlerResult respond_path(DBusConnection *c, DBusMessage *m, const char *path) {
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);
504 return DBUS_HANDLER_RESULT_HANDLED;
507 static char *file_get_contents(char *fname) {
515 if (!(fd = open(fname, O_RDONLY))) {
516 avahi_log_error("Failed to open %s: %s", fname, strerror(errno));
520 if (fstat(fd, &st) < 0) {
521 avahi_log_error("stat(%s) failed: %s", fname, strerror(errno));
525 if (!(S_ISREG(st.st_mode))) {
526 avahi_log_error("Invalid file %s", fname);
530 if (st.st_size > 1024*1024) { /** 1MB */
531 avahi_log_error("File too large %s", fname);
535 buf = avahi_new(char, st.st_size+1);
537 if ((size = read(fd, buf, st.st_size)) < 0) {
538 avahi_log_error("read() failed: %s\n", strerror(errno));
558 static const char *map_browse_signal_name(AvahiBrowserEvent 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";
571 static const char *map_resolve_signal_name(AvahiResolverEvent 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";
582 static int map_resolve_error(AvahiResolverEvent 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;
594 static DBusHandlerResult handle_introspect(DBusConnection *c, DBusMessage *m, const char *fname) {
595 char *path, *contents;
602 dbus_error_init(&error);
604 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
605 avahi_log_error("Error parsing Introspect message: %s", error.message);
609 path = avahi_strdup_printf("%s/%s", AVAHI_DBUS_INTROSPECTION_DIR, fname);
610 contents = file_get_contents(path);
614 avahi_log_error("Failed to load introspection data.");
618 respond_string(c, m, contents);
619 avahi_free(contents);
621 return DBUS_HANDLER_RESULT_HANDLED;
624 if (dbus_error_is_set(&error))
625 dbus_error_free(&error);
627 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
631 static DBusHandlerResult msg_signal_filter_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
634 dbus_error_init(&error);
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)); */
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...");
646 raise(SIGQUIT); /* The signal handler will catch this and terminate the process cleanly*/
648 return DBUS_HANDLER_RESULT_HANDLED;
650 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) {
653 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
654 avahi_log_warn("Error parsing NameAcquired message");
658 /* avahi_log_info(__FILE__": name acquired (%s)", name); */
659 return DBUS_HANDLER_RESULT_HANDLED;
661 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
662 char *name, *old, *new;
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");
672 if ((client = client_get(name, FALSE))) {
673 avahi_log_debug(__FILE__": client %s vanished.", name);
680 if (dbus_error_is_set(&error))
681 dbus_error_free(&error);
683 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
686 static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntryGroupState state, void* userdata) {
687 EntryGroupInfo *i = userdata;
695 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged");
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);
703 static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
705 EntryGroupInfo *i = userdata;
711 dbus_error_init(&error);
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));
719 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
720 return handle_introspect(c, m, "EntryGroup.introspect");
723 if (strcmp(dbus_message_get_sender(m), i->client->name))
724 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
726 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) {
728 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
729 avahi_log_warn("Error parsing EntryGroup::Free message");
734 return respond_ok(c, m);
736 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Commit")) {
738 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
739 avahi_log_warn("Error parsing EntryGroup::Commit message");
743 avahi_s_entry_group_commit(i->entry_group);
744 return respond_ok(c, m);
747 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Reset")) {
749 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
750 avahi_log_warn("Error parsing EntryGroup::Reset message");
754 avahi_s_entry_group_reset(i->entry_group);
756 return respond_ok(c, m);
758 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) {
762 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
763 avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
767 b = !!avahi_s_entry_group_is_empty(i->entry_group);
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);
774 return DBUS_HANDLER_RESULT_HANDLED;
776 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
777 AvahiEntryGroupState state;
779 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
780 avahi_log_warn("Error parsing EntryGroup::GetState message");
784 state = avahi_s_entry_group_get_state(i->entry_group);
785 return respond_int32(c, m, (int32_t) state);
787 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
788 int32_t interface, protocol;
790 char *type, *name, *domain, *host;
792 AvahiStringList *strlst;
793 DBusMessageIter iter, sub;
796 if (!dbus_message_get_args(
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");
811 dbus_message_iter_init(m, &iter);
813 for (j = 0; j < 8; j++)
814 dbus_message_iter_next(&iter);
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");
823 dbus_message_iter_recurse(&iter, &sub);
826 DBusMessageIter sub2;
830 if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
833 assert(at == DBUS_TYPE_ARRAY);
835 if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) {
836 avahi_log_warn("Error parsing EntryGroup::AddService message");
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);
844 dbus_message_iter_next(&sub);
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);
853 if (domain && !*domain)
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);
865 avahi_string_list_free(strlst);
867 return respond_ok(c, m);
869 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
870 int32_t interface, protocol;
872 char *name, *address;
875 if (!dbus_message_get_args(
877 DBUS_TYPE_INT32, &interface,
878 DBUS_TYPE_INT32, &protocol,
879 DBUS_TYPE_UINT32, &flags,
880 DBUS_TYPE_STRING, &name,
881 DBUS_TYPE_STRING, &address,
882 DBUS_TYPE_INVALID) || !name || !address) {
883 avahi_log_warn("Error parsing EntryGroup::AddAddress message");
887 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
888 avahi_log_warn("Too many entries per entry group, client request failed.");
889 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
892 if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))) {
893 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
896 if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, &a) < 0)
897 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
901 return respond_ok(c, m);
904 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
907 if (dbus_error_is_set(&error))
908 dbus_error_free(&error);
910 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
913 static void sync_host_name_resolver_callback(AvahiSHostNameResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *host_name, const AvahiAddress *a, AvahiLookupResultFlags flags, void* userdata) {
914 SyncHostNameResolverInfo *i = userdata;
920 if (event == AVAHI_RESOLVER_FOUND) {
921 char t[256], *pt = t;
922 int32_t i_interface, i_protocol, i_aprotocol;
927 avahi_address_snprint(t, sizeof(t), a);
929 i_interface = (int32_t) interface;
930 i_protocol = (int32_t) protocol;
931 i_aprotocol = (int32_t) a->proto;
932 u_flags = (uint32_t) flags;
934 reply = dbus_message_new_method_return(i->message);
935 dbus_message_append_args(
937 DBUS_TYPE_INT32, &i_interface,
938 DBUS_TYPE_INT32, &i_protocol,
939 DBUS_TYPE_STRING, &host_name,
940 DBUS_TYPE_INT32, &i_aprotocol,
941 DBUS_TYPE_STRING, &pt,
942 DBUS_TYPE_UINT32, &u_flags,
945 dbus_connection_send(server->bus, reply, NULL);
946 dbus_message_unref(reply);
948 respond_error(server->bus, i->message, map_resolve_error(event), NULL);
950 sync_host_name_resolver_free(i);
953 static void sync_address_resolver_callback(AvahiSAddressResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const AvahiAddress *address, const char *host_name, AvahiLookupResultFlags flags, void* userdata) {
954 SyncAddressResolverInfo *i = userdata;
960 if (event == AVAHI_RESOLVER_FOUND) {
961 char t[256], *pt = t;
962 int32_t i_interface, i_protocol, i_aprotocol;
967 avahi_address_snprint(t, sizeof(t), address);
969 i_interface = (int32_t) interface;
970 i_protocol = (int32_t) protocol;
971 i_aprotocol = (int32_t) address->proto;
972 u_flags = (uint32_t) flags;
974 reply = dbus_message_new_method_return(i->message);
975 dbus_message_append_args(
977 DBUS_TYPE_INT32, &i_interface,
978 DBUS_TYPE_INT32, &i_protocol,
979 DBUS_TYPE_INT32, &i_aprotocol,
980 DBUS_TYPE_STRING, &pt,
981 DBUS_TYPE_STRING, &host_name,
982 DBUS_TYPE_UINT32, &u_flags,
985 dbus_connection_send(server->bus, reply, NULL);
986 dbus_message_unref(reply);
988 respond_error(server->bus, i->message, map_resolve_error(event), NULL);
990 sync_address_resolver_free(i);
993 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
995 DomainBrowserInfo *i = userdata;
1001 dbus_error_init(&error);
1003 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1004 dbus_message_get_interface(m),
1005 dbus_message_get_path(m),
1006 dbus_message_get_member(m));
1009 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1010 return handle_introspect(c, m, "DomainBrowser.introspect");
1012 /* Access control */
1013 if (strcmp(dbus_message_get_sender(m), i->client->name))
1014 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1016 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
1018 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1019 avahi_log_warn("Error parsing DomainBrowser::Free message");
1023 domain_browser_free(i);
1024 return respond_ok(c, m);
1028 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1031 if (dbus_error_is_set(&error))
1032 dbus_error_free(&error);
1034 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1037 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1038 DomainBrowserInfo *i = userdata;
1040 int32_t i_interface, i_protocol;
1046 i_interface = (int32_t) interface;
1047 i_protocol = (int32_t) protocol;
1048 u_flags = (uint32_t) flags;
1050 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, map_browse_signal_name(event));
1052 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1054 dbus_message_append_args(
1056 DBUS_TYPE_INT32, &i_interface,
1057 DBUS_TYPE_INT32, &i_protocol,
1058 DBUS_TYPE_STRING, &domain,
1059 DBUS_TYPE_UINT32, &u_flags,
1063 dbus_message_set_destination(m, i->client->name);
1064 dbus_connection_send(server->bus, m, NULL);
1065 dbus_message_unref(m);
1068 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1070 ServiceTypeBrowserInfo *i = userdata;
1076 dbus_error_init(&error);
1078 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1079 dbus_message_get_interface(m),
1080 dbus_message_get_path(m),
1081 dbus_message_get_member(m));
1084 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1085 return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
1087 /* Access control */
1088 if (strcmp(dbus_message_get_sender(m), i->client->name))
1089 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1091 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
1093 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1094 avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
1098 service_type_browser_free(i);
1099 return respond_ok(c, m);
1103 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1106 if (dbus_error_is_set(&error))
1107 dbus_error_free(&error);
1109 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1112 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1113 ServiceTypeBrowserInfo *i = userdata;
1115 int32_t i_interface, i_protocol;
1121 i_interface = (int32_t) interface;
1122 i_protocol = (int32_t) protocol;
1123 u_flags = (uint32_t) flags;
1125 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, map_browse_signal_name(event));
1127 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1130 dbus_message_append_args(
1132 DBUS_TYPE_INT32, &i_interface,
1133 DBUS_TYPE_INT32, &i_protocol,
1134 DBUS_TYPE_STRING, &type,
1135 DBUS_TYPE_STRING, &domain,
1136 DBUS_TYPE_UINT32, &u_flags,
1140 dbus_message_set_destination(m, i->client->name);
1141 dbus_connection_send(server->bus, m, NULL);
1142 dbus_message_unref(m);
1145 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1147 ServiceBrowserInfo *i = userdata;
1153 dbus_error_init(&error);
1155 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1156 dbus_message_get_interface(m),
1157 dbus_message_get_path(m),
1158 dbus_message_get_member(m));
1161 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1162 return handle_introspect(c, m, "ServiceBrowser.Introspect");
1164 /* Access control */
1165 if (strcmp(dbus_message_get_sender(m), i->client->name))
1166 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1168 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
1170 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1171 avahi_log_warn("Error parsing ServiceBrowser::Free message");
1175 service_browser_free(i);
1176 return respond_ok(c, m);
1180 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1183 if (dbus_error_is_set(&error))
1184 dbus_error_free(&error);
1186 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1189 static void service_browser_callback(AvahiSServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1190 ServiceBrowserInfo *i = userdata;
1192 int32_t i_interface, i_protocol;
1198 i_interface = (int32_t) interface;
1199 i_protocol = (int32_t) protocol;
1200 u_flags = (uint32_t) flags;
1202 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, map_browse_signal_name(event));
1204 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1209 dbus_message_append_args(
1211 DBUS_TYPE_INT32, &i_interface,
1212 DBUS_TYPE_INT32, &i_protocol,
1213 DBUS_TYPE_STRING, &name,
1214 DBUS_TYPE_STRING, &type,
1215 DBUS_TYPE_STRING, &domain,
1216 DBUS_TYPE_UINT32, &u_flags,
1220 dbus_message_set_destination(m, i->client->name);
1221 dbus_connection_send(server->bus, m, NULL);
1222 dbus_message_unref(m);
1225 static void append_string_list(DBusMessage *reply, AvahiStringList *txt) {
1227 DBusMessageIter iter, sub;
1231 dbus_message_iter_init_append(reply, &iter);
1232 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1234 for (p = txt; p; p = p->next) {
1235 DBusMessageIter sub2;
1236 const uint8_t *data = p->text;
1238 dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1239 dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
1240 dbus_message_iter_close_container(&sub, &sub2);
1243 dbus_message_iter_close_container(&iter, &sub);
1246 static void sync_service_resolver_callback(
1247 AvahiSServiceResolver *r,
1248 AvahiIfIndex interface,
1249 AvahiProtocol protocol,
1250 AvahiResolverEvent event,
1254 const char *host_name,
1255 const AvahiAddress *a,
1257 AvahiStringList *txt,
1258 AvahiLookupResultFlags flags,
1261 SyncServiceResolverInfo *i = userdata;
1266 if (event == AVAHI_RESOLVER_FOUND) {
1267 char t[256], *pt = t;
1268 int32_t i_interface, i_protocol, i_aprotocol;
1278 avahi_address_snprint(t, sizeof(t), a);
1280 i_interface = (int32_t) interface;
1281 i_protocol = (int32_t) protocol;
1282 i_aprotocol = (int32_t) a->proto;
1283 u_flags = (uint32_t) flags;
1285 reply = dbus_message_new_method_return(i->message);
1286 dbus_message_append_args(
1288 DBUS_TYPE_INT32, &i_interface,
1289 DBUS_TYPE_INT32, &i_protocol,
1290 DBUS_TYPE_STRING, &name,
1291 DBUS_TYPE_STRING, &type,
1292 DBUS_TYPE_STRING, &domain,
1293 DBUS_TYPE_STRING, &host_name,
1294 DBUS_TYPE_INT32, &i_aprotocol,
1295 DBUS_TYPE_STRING, &pt,
1296 DBUS_TYPE_UINT16, &port,
1299 append_string_list(reply, txt);
1301 dbus_message_append_args(
1303 DBUS_TYPE_UINT32, &u_flags,
1306 dbus_connection_send(server->bus, reply, NULL);
1307 dbus_message_unref(reply);
1309 respond_error(server->bus, i->message, map_resolve_error(event), NULL);
1311 sync_service_resolver_free(i);
1314 static void async_address_resolver_callback(AvahiSAddressResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const AvahiAddress *address, const char *host_name, AvahiLookupResultFlags flags, void* userdata) {
1315 AsyncAddressResolverInfo *i = userdata;
1321 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, map_browse_signal_name(event));
1323 if (event == AVAHI_RESOLVER_FOUND) {
1324 char t[256], *pt = t;
1325 int32_t i_interface, i_protocol, i_aprotocol;
1330 avahi_address_snprint(t, sizeof(t), address);
1332 i_interface = (int32_t) interface;
1333 i_protocol = (int32_t) protocol;
1334 i_aprotocol = (int32_t) address->proto;
1335 u_flags = (uint32_t) flags;
1337 dbus_message_append_args(
1339 DBUS_TYPE_INT32, &i_interface,
1340 DBUS_TYPE_INT32, &i_protocol,
1341 DBUS_TYPE_INT32, &i_aprotocol,
1342 DBUS_TYPE_STRING, &pt,
1343 DBUS_TYPE_STRING, &host_name,
1344 DBUS_TYPE_UINT32, &u_flags,
1349 dbus_message_set_destination(reply, i->client->name);
1350 dbus_connection_send(server->bus, reply, NULL);
1351 dbus_message_unref(reply);
1354 static DBusHandlerResult msg_async_address_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1356 AsyncAddressResolverInfo *i = userdata;
1362 dbus_error_init(&error);
1364 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1365 dbus_message_get_interface(m),
1366 dbus_message_get_path(m),
1367 dbus_message_get_member(m));
1370 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1371 return handle_introspect(c, m, "AddressResolver.Introspect");
1373 /* Access control */
1374 if (strcmp(dbus_message_get_sender(m), i->client->name))
1375 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1377 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Free")) {
1379 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1380 avahi_log_warn("Error parsing AddressResolver::Free message");
1384 async_address_resolver_free(i);
1385 return respond_ok(c, m);
1389 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1392 if (dbus_error_is_set(&error))
1393 dbus_error_free(&error);
1395 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1398 static void async_host_name_resolver_callback(AvahiSHostNameResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *host_name, const AvahiAddress *a, AvahiLookupResultFlags flags, void* userdata) {
1399 AsyncHostNameResolverInfo *i = userdata;
1405 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, map_resolve_signal_name(event));
1407 if (event == AVAHI_RESOLVER_FOUND) {
1408 char t[256], *pt = t;
1409 int32_t i_interface, i_protocol, i_aprotocol;
1414 avahi_address_snprint(t, sizeof(t), a);
1416 i_interface = (int32_t) interface;
1417 i_protocol = (int32_t) protocol;
1418 i_aprotocol = (int32_t) a->proto;
1419 u_flags = (uint32_t) flags;
1421 dbus_message_append_args(
1423 DBUS_TYPE_INT32, &i_interface,
1424 DBUS_TYPE_INT32, &i_protocol,
1425 DBUS_TYPE_STRING, &host_name,
1426 DBUS_TYPE_INT32, &i_aprotocol,
1427 DBUS_TYPE_STRING, &pt,
1428 DBUS_TYPE_UINT32, &u_flags,
1432 dbus_message_set_destination(reply, i->client->name);
1433 dbus_connection_send(server->bus, reply, NULL);
1434 dbus_message_unref(reply);
1437 static DBusHandlerResult msg_async_host_name_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1439 AsyncHostNameResolverInfo *i = userdata;
1445 dbus_error_init(&error);
1447 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1448 dbus_message_get_interface(m),
1449 dbus_message_get_path(m),
1450 dbus_message_get_member(m));
1453 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1454 return handle_introspect(c, m, "HostNameResolver.Introspect");
1456 /* Access control */
1457 if (strcmp(dbus_message_get_sender(m), i->client->name))
1458 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1460 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, "Free")) {
1462 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1463 avahi_log_warn("Error parsing HostNameResolver::Free message");
1467 async_host_name_resolver_free(i);
1468 return respond_ok(c, m);
1471 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1474 if (dbus_error_is_set(&error))
1475 dbus_error_free(&error);
1477 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1480 static void async_service_resolver_callback(
1481 AvahiSServiceResolver *r,
1482 AvahiIfIndex interface,
1483 AvahiProtocol protocol,
1484 AvahiResolverEvent event,
1488 const char *host_name,
1489 const AvahiAddress *a,
1491 AvahiStringList *txt,
1492 AvahiLookupResultFlags flags,
1495 AsyncServiceResolverInfo *i = userdata;
1501 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, map_resolve_signal_name(event));
1503 if (event == AVAHI_RESOLVER_FOUND) {
1504 char t[256], *pt = t;
1505 int32_t i_interface, i_protocol, i_aprotocol;
1510 /* avahi_log_debug(__FILE__": [%s] Successfully resolved service <%s.%s.%s>", i->path, name, type, domain); */
1513 avahi_address_snprint(t, sizeof(t), a);
1518 i_interface = (int32_t) interface;
1519 i_protocol = (int32_t) protocol;
1520 i_aprotocol = (int32_t) a->proto;
1521 u_flags = (uint32_t) flags;
1523 dbus_message_append_args(
1525 DBUS_TYPE_INT32, &i_interface,
1526 DBUS_TYPE_INT32, &i_protocol,
1527 DBUS_TYPE_STRING, &name,
1528 DBUS_TYPE_STRING, &type,
1529 DBUS_TYPE_STRING, &domain,
1530 DBUS_TYPE_STRING, &host_name,
1531 DBUS_TYPE_INT32, &i_aprotocol,
1532 DBUS_TYPE_STRING, &pt,
1533 DBUS_TYPE_UINT16, &port,
1536 append_string_list(reply, txt);
1538 dbus_message_append_args(
1540 DBUS_TYPE_UINT32, &u_flags,
1544 dbus_message_set_destination(reply, i->client->name);
1545 dbus_connection_send(server->bus, reply, NULL);
1546 dbus_message_unref(reply);
1549 static DBusHandlerResult msg_async_service_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1551 AsyncServiceResolverInfo *i = userdata;
1557 dbus_error_init(&error);
1559 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1560 dbus_message_get_interface(m),
1561 dbus_message_get_path(m),
1562 dbus_message_get_member(m));
1565 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1566 return handle_introspect(c, m, "ServiceResolver.Introspect");
1568 /* Access control */
1569 if (strcmp(dbus_message_get_sender(m), i->client->name))
1570 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1572 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, "Free")) {
1574 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1575 avahi_log_warn("Error parsing ServiceResolver::Free message");
1579 async_service_resolver_free(i);
1580 return respond_ok(c, m);
1583 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1586 if (dbus_error_is_set(&error))
1587 dbus_error_free(&error);
1589 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1592 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1595 dbus_error_init(&error);
1597 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1598 dbus_message_get_interface(m),
1599 dbus_message_get_path(m),
1600 dbus_message_get_member(m));
1602 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1603 return handle_introspect(c, m, "Server.introspect");
1605 else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1607 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1608 avahi_log_warn("Error parsing Server::GetHostName message");
1612 return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1614 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1616 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1617 avahi_log_warn("Error parsing Server::GetDomainName message");
1621 return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1623 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1625 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1626 avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1630 return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1632 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1634 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1635 avahi_log_warn("Error parsing Server::GetVersionString message");
1639 return respond_string(c, m, PACKAGE_STRING);
1641 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1642 AvahiServerState state;
1644 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1645 avahi_log_warn("Error parsing Server::GetState message");
1649 state = avahi_server_get_state(avahi_server);
1650 return respond_int32(c, m, (int32_t) state);
1652 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetLocalServiceCookie")) {
1654 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1655 avahi_log_warn("Error parsing Server::GetLocalServiceCookie message");
1659 return respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server));
1661 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "IsServiceLocal")) {
1662 int32_t interface, protocol;
1663 char *name, *type, *domain;
1666 if (!dbus_message_get_args(
1668 DBUS_TYPE_INT32, &interface,
1669 DBUS_TYPE_INT32, &protocol,
1670 DBUS_TYPE_STRING, &name,
1671 DBUS_TYPE_STRING, &type,
1672 DBUS_TYPE_STRING, &domain,
1673 DBUS_TYPE_INVALID) || !name || !type || !domain) {
1674 avahi_log_warn("Error parsing Server::IsServiceLocal message");
1678 if ((b = avahi_server_is_service_local(avahi_server, interface, protocol, name, type, domain)) < 0)
1679 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1681 return respond_boolean(c, m, b);
1683 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1688 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1689 avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1693 #ifdef VALGRIND_WORKAROUND
1694 return respond_string(c, m, "blah");
1697 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1698 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1700 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1701 return respond_error(c, m, AVAHI_ERR_OS, txt);
1704 memset(&ifr, 0, sizeof(ifr));
1705 ifr.ifr_ifindex = idx;
1707 if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) {
1709 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1711 return respond_error(c, m, AVAHI_ERR_OS, txt);
1716 return respond_string(c, m, ifr.ifr_name);
1719 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1724 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1725 avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1729 #ifdef VALGRIND_WORKAROUND
1730 return respond_int32(c, m, 1);
1732 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1733 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1735 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1736 return respond_error(c, m, AVAHI_ERR_OS, txt);
1739 memset(&ifr, 0, sizeof(ifr));
1740 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", n);
1742 if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
1744 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1746 return respond_error(c, m, AVAHI_ERR_OS, txt);
1751 return respond_int32(c, m, ifr.ifr_ifindex);
1754 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1757 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1758 avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1762 t = avahi_alternative_host_name(n);
1763 respond_string(c, m, t);
1766 return DBUS_HANDLER_RESULT_HANDLED;
1768 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1771 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1772 avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1776 t = avahi_alternative_service_name(n);
1777 respond_string(c, m, t);
1780 return DBUS_HANDLER_RESULT_HANDLED;
1782 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1785 static const DBusObjectPathVTable vtable = {
1787 msg_entry_group_impl,
1794 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1795 avahi_log_warn("Error parsing Server::EntryGroupNew message");
1799 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1800 avahi_log_warn("Too many clients, client request failed.");
1801 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1804 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1805 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1806 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1809 i = avahi_new(EntryGroupInfo, 1);
1810 i->id = ++client->current_id;
1812 i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1814 AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1815 client->n_objects++;
1817 if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1818 entry_group_free(i);
1819 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1822 dbus_connection_register_object_path(c, i->path, &vtable, i);
1823 return respond_path(c, m, i->path);
1825 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1827 int32_t interface, protocol, aprotocol;
1830 SyncHostNameResolverInfo *i;
1832 if (!dbus_message_get_args(
1834 DBUS_TYPE_INT32, &interface,
1835 DBUS_TYPE_INT32, &protocol,
1836 DBUS_TYPE_STRING, &name,
1837 DBUS_TYPE_INT32, &aprotocol,
1838 DBUS_TYPE_UINT32, &flags,
1839 DBUS_TYPE_INVALID) || !name) {
1840 avahi_log_warn("Error parsing Server::ResolveHostName message");
1844 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1845 avahi_log_warn("Too many clients, client request failed.");
1846 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1849 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1850 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1851 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1854 i = avahi_new(SyncHostNameResolverInfo, 1);
1856 i->message = dbus_message_ref(m);
1857 AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i);
1858 client->n_objects++;
1860 if (!(i->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, sync_host_name_resolver_callback, i))) {
1861 sync_host_name_resolver_free(i);
1862 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1865 return DBUS_HANDLER_RESULT_HANDLED;
1867 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1869 int32_t interface, protocol;
1872 SyncAddressResolverInfo *i;
1875 if (!dbus_message_get_args(
1877 DBUS_TYPE_INT32, &interface,
1878 DBUS_TYPE_INT32, &protocol,
1879 DBUS_TYPE_STRING, &address,
1880 DBUS_TYPE_UINT32, &flags,
1881 DBUS_TYPE_INVALID) || !address) {
1882 avahi_log_warn("Error parsing Server::ResolveAddress message");
1886 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
1887 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
1889 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1890 avahi_log_warn("Too many clients, client request failed.");
1891 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1894 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1895 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1896 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1899 i = avahi_new(SyncAddressResolverInfo, 1);
1901 i->message = dbus_message_ref(m);
1902 AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i);
1903 client->n_objects++;
1905 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, sync_address_resolver_callback, i))) {
1906 sync_address_resolver_free(i);
1907 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1910 return DBUS_HANDLER_RESULT_HANDLED;
1912 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
1914 DomainBrowserInfo *i;
1915 static const DBusObjectPathVTable vtable = {
1917 msg_domain_browser_impl,
1923 int32_t interface, protocol, type;
1927 if (!dbus_message_get_args(
1929 DBUS_TYPE_INT32, &interface,
1930 DBUS_TYPE_INT32, &protocol,
1931 DBUS_TYPE_STRING, &domain,
1932 DBUS_TYPE_INT32, &type,
1933 DBUS_TYPE_UINT32, &flags,
1934 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
1935 avahi_log_warn("Error parsing Server::DomainBrowserNew message");
1939 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1940 avahi_log_warn("Too many clients, client request failed.");
1941 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1944 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1945 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1946 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1952 i = avahi_new(DomainBrowserInfo, 1);
1953 i->id = ++client->current_id;
1955 i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
1956 AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
1957 client->n_objects++;
1959 if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, (AvahiLookupFlags) flags, domain_browser_callback, i))) {
1960 domain_browser_free(i);
1961 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1964 dbus_connection_register_object_path(c, i->path, &vtable, i);
1965 return respond_path(c, m, i->path);
1967 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
1969 ServiceTypeBrowserInfo *i;
1970 static const DBusObjectPathVTable vtable = {
1972 msg_service_type_browser_impl,
1978 int32_t interface, protocol;
1982 if (!dbus_message_get_args(
1984 DBUS_TYPE_INT32, &interface,
1985 DBUS_TYPE_INT32, &protocol,
1986 DBUS_TYPE_STRING, &domain,
1987 DBUS_TYPE_UINT32, &flags,
1988 DBUS_TYPE_INVALID)) {
1989 avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
1993 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1994 avahi_log_warn("Too many clients, client request failed.");
1995 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1999 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2000 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2001 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2007 i = avahi_new(ServiceTypeBrowserInfo, 1);
2008 i->id = ++client->current_id;
2010 i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
2011 AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
2012 client->n_objects++;
2014 if (!(i->service_type_browser = avahi_s_service_type_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiLookupFlags) flags, service_type_browser_callback, i))) {
2015 service_type_browser_free(i);
2016 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2019 dbus_connection_register_object_path(c, i->path, &vtable, i);
2020 return respond_path(c, m, i->path);
2022 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
2024 ServiceBrowserInfo *i;
2025 static const DBusObjectPathVTable vtable = {
2027 msg_service_browser_impl,
2033 int32_t interface, protocol;
2035 char *domain, *type;
2037 if (!dbus_message_get_args(
2039 DBUS_TYPE_INT32, &interface,
2040 DBUS_TYPE_INT32, &protocol,
2041 DBUS_TYPE_STRING, &type,
2042 DBUS_TYPE_STRING, &domain,
2043 DBUS_TYPE_UINT32, &flags,
2044 DBUS_TYPE_INVALID) || !type) {
2045 avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
2049 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2050 avahi_log_warn("Too many clients, client request failed.");
2051 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2055 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2056 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2057 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2063 i = avahi_new(ServiceBrowserInfo, 1);
2064 i->id = ++client->current_id;
2066 i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
2067 AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
2068 client->n_objects++;
2070 if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, (AvahiLookupFlags) flags, service_browser_callback, i))) {
2071 service_browser_free(i);
2072 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2075 dbus_connection_register_object_path(c, i->path, &vtable, i);
2076 return respond_path(c, m, i->path);
2078 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
2080 int32_t interface, protocol, aprotocol;
2082 char *name, *type, *domain;
2083 SyncServiceResolverInfo *i;
2085 if (!dbus_message_get_args(
2087 DBUS_TYPE_INT32, &interface,
2088 DBUS_TYPE_INT32, &protocol,
2089 DBUS_TYPE_STRING, &name,
2090 DBUS_TYPE_STRING, &type,
2091 DBUS_TYPE_STRING, &domain,
2092 DBUS_TYPE_INT32, &aprotocol,
2093 DBUS_TYPE_UINT32, &flags,
2094 DBUS_TYPE_INVALID) || !type) {
2095 avahi_log_warn("Error parsing Server::ResolveService message");
2099 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2100 avahi_log_warn("Too many clients, client request failed.");
2101 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2104 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2105 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2106 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2115 i = avahi_new(SyncServiceResolverInfo, 1);
2117 i->message = dbus_message_ref(m);
2118 AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i);
2119 client->n_objects++;
2121 if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, sync_service_resolver_callback, i))) {
2122 sync_service_resolver_free(i);
2123 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2126 return DBUS_HANDLER_RESULT_HANDLED;
2128 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) {
2130 int32_t interface, protocol, aprotocol;
2132 char *name, *type, *domain;
2133 AsyncServiceResolverInfo *i;
2134 static const DBusObjectPathVTable vtable = {
2136 msg_async_service_resolver_impl,
2143 if (!dbus_message_get_args(
2145 DBUS_TYPE_INT32, &interface,
2146 DBUS_TYPE_INT32, &protocol,
2147 DBUS_TYPE_STRING, &name,
2148 DBUS_TYPE_STRING, &type,
2149 DBUS_TYPE_STRING, &domain,
2150 DBUS_TYPE_INT32, &aprotocol,
2151 DBUS_TYPE_UINT32, &flags,
2152 DBUS_TYPE_INVALID) || !type) {
2153 avahi_log_warn("Error parsing Server::ServiceResolverNew message");
2157 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2158 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2159 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2162 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2163 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2164 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2173 i = avahi_new(AsyncServiceResolverInfo, 1);
2174 i->id = ++client->current_id;
2176 i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
2177 AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i);
2178 client->n_objects++;
2180 if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, (AvahiLookupFlags) flags, async_service_resolver_callback, i))) {
2181 async_service_resolver_free(i);
2182 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2185 /* avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */
2187 dbus_connection_register_object_path(c, i->path, &vtable, i);
2188 return respond_path(c, m, i->path);
2190 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew")) {
2192 int32_t interface, protocol, aprotocol;
2195 AsyncHostNameResolverInfo *i;
2196 static const DBusObjectPathVTable vtable = {
2198 msg_async_host_name_resolver_impl,
2205 if (!dbus_message_get_args(
2207 DBUS_TYPE_INT32, &interface,
2208 DBUS_TYPE_INT32, &protocol,
2209 DBUS_TYPE_STRING, &name,
2210 DBUS_TYPE_INT32, &aprotocol,
2211 DBUS_TYPE_UINT32, &flags,
2212 DBUS_TYPE_INVALID) || !name) {
2213 avahi_log_warn("Error parsing Server::HostNameResolverNew message");
2217 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2218 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2219 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2222 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2223 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2224 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2227 i = avahi_new(AsyncHostNameResolverInfo, 1);
2228 i->id = ++client->current_id;
2230 i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
2231 AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i);
2232 client->n_objects++;
2234 if (!(i->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, aprotocol, (AvahiLookupFlags) flags, async_host_name_resolver_callback, i))) {
2235 async_host_name_resolver_free(i);
2236 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2239 dbus_connection_register_object_path(c, i->path, &vtable, i);
2240 return respond_path(c, m, i->path);
2242 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew")) {
2244 int32_t interface, protocol;
2247 AsyncAddressResolverInfo *i;
2249 static const DBusObjectPathVTable vtable = {
2251 msg_async_address_resolver_impl,
2258 if (!dbus_message_get_args(
2260 DBUS_TYPE_INT32, &interface,
2261 DBUS_TYPE_INT32, &protocol,
2262 DBUS_TYPE_STRING, &address,
2263 DBUS_TYPE_UINT32, &flags,
2264 DBUS_TYPE_INVALID) || !address) {
2265 avahi_log_warn("Error parsing Server::AddressResolverNew message");
2269 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
2270 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
2272 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2273 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2274 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2277 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2278 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2279 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2282 i = avahi_new(AsyncAddressResolverInfo, 1);
2283 i->id = ++client->current_id;
2285 i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
2286 AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i);
2287 client->n_objects++;
2289 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, async_address_resolver_callback, i))) {
2290 async_address_resolver_free(i);
2291 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2294 dbus_connection_register_object_path(c, i->path, &vtable, i);
2295 return respond_path(c, m, i->path);
2298 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
2301 if (dbus_error_is_set(&error))
2302 dbus_error_free(&error);
2304 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2307 void dbus_protocol_server_state_changed(AvahiServerState state) {
2314 m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
2315 t = (int32_t) state;
2316 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
2317 dbus_connection_send(server->bus, m, NULL);
2318 dbus_message_unref(m);
2321 int dbus_protocol_setup(const AvahiPoll *poll_api) {
2324 static const DBusObjectPathVTable server_vtable = {
2333 dbus_error_init(&error);
2335 server = avahi_new(Server, 1);
2336 AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
2337 server->current_id = 0;
2338 server->n_clients = 0;
2340 if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
2341 assert(dbus_error_is_set(&error));
2342 avahi_log_error("dbus_bus_get(): %s", error.message);
2346 if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) {
2347 avahi_log_error("avahi_dbus_connection_glue() failed");
2351 if (dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
2352 if (dbus_error_is_set(&error)) {
2353 avahi_log_error("dbus_bus_request_name(): %s", error.message);
2357 avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'");
2361 if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) {
2362 avahi_log_error("dbus_connection_add_filter() failed");
2366 dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
2368 if (dbus_error_is_set(&error)) {
2369 avahi_log_error("dbus_bus_add_match(): %s", error.message);
2373 if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
2374 avahi_log_error("dbus_connection_register_object_path() failed");
2382 dbus_connection_disconnect(server->bus);
2383 dbus_connection_unref(server->bus);
2386 if (dbus_error_is_set(&error))
2387 dbus_error_free(&error);
2394 void dbus_protocol_shutdown(void) {
2398 while (server->clients)
2399 client_free(server->clients);
2401 assert(server->n_clients == 0);
2404 dbus_connection_disconnect(server->bus);
2405 dbus_connection_unref(server->bus);