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>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
40 #include <dbus/dbus.h>
42 #include <avahi-common/dbus.h>
43 #include <avahi-common/llist.h>
44 #include <avahi-common/malloc.h>
45 #include <avahi-common/dbus.h>
46 #include <avahi-common/dbus-watch-glue.h>
47 #include <avahi-common/alternative.h>
48 #include <avahi-common/error.h>
50 #include <avahi-core/log.h>
51 #include <avahi-core/core.h>
52 #include <avahi-core/lookup.h>
53 #include <avahi-core/publish.h>
55 #include "dbus-protocol.h"
58 typedef struct Server Server;
59 typedef struct Client Client;
60 typedef struct EntryGroupInfo EntryGroupInfo;
61 typedef struct SyncHostNameResolverInfo SyncHostNameResolverInfo;
62 typedef struct AsyncHostNameResolverInfo AsyncHostNameResolverInfo;
63 typedef struct SyncAddressResolverInfo SyncAddressResolverInfo;
64 typedef struct AsyncAddressResolverInfo AsyncAddressResolverInfo;
65 typedef struct DomainBrowserInfo DomainBrowserInfo;
66 typedef struct ServiceTypeBrowserInfo ServiceTypeBrowserInfo;
67 typedef struct ServiceBrowserInfo ServiceBrowserInfo;
68 typedef struct SyncServiceResolverInfo SyncServiceResolverInfo;
69 typedef struct AsyncServiceResolverInfo AsyncServiceResolverInfo;
71 #define MAX_CLIENTS 20
72 #define MAX_OBJECTS_PER_CLIENT 50
73 #define MAX_ENTRIES_PER_ENTRY_GROUP 20
75 /* #define VALGRIND_WORKAROUND 1 */
77 struct EntryGroupInfo {
80 AvahiSEntryGroup *entry_group;
85 AVAHI_LLIST_FIELDS(EntryGroupInfo, entry_groups);
88 struct SyncHostNameResolverInfo {
90 AvahiSHostNameResolver *host_name_resolver;
93 AVAHI_LLIST_FIELDS(SyncHostNameResolverInfo, sync_host_name_resolvers);
96 struct AsyncHostNameResolverInfo {
99 AvahiSHostNameResolver *host_name_resolver;
102 AVAHI_LLIST_FIELDS(AsyncHostNameResolverInfo, async_host_name_resolvers);
105 struct SyncAddressResolverInfo {
107 AvahiSAddressResolver *address_resolver;
108 DBusMessage *message;
110 AVAHI_LLIST_FIELDS(SyncAddressResolverInfo, sync_address_resolvers);
113 struct AsyncAddressResolverInfo {
116 AvahiSAddressResolver *address_resolver;
119 AVAHI_LLIST_FIELDS(AsyncAddressResolverInfo, async_address_resolvers);
122 struct DomainBrowserInfo {
125 AvahiSDomainBrowser *domain_browser;
128 AVAHI_LLIST_FIELDS(DomainBrowserInfo, domain_browsers);
131 struct ServiceTypeBrowserInfo {
134 AvahiSServiceTypeBrowser *service_type_browser;
137 AVAHI_LLIST_FIELDS(ServiceTypeBrowserInfo, service_type_browsers);
140 struct ServiceBrowserInfo {
143 AvahiSServiceBrowser *service_browser;
146 AVAHI_LLIST_FIELDS(ServiceBrowserInfo, service_browsers);
149 struct SyncServiceResolverInfo {
151 AvahiSServiceResolver *service_resolver;
152 DBusMessage *message;
154 AVAHI_LLIST_FIELDS(SyncServiceResolverInfo, sync_service_resolvers);
157 struct AsyncServiceResolverInfo {
160 AvahiSServiceResolver *service_resolver;
163 AVAHI_LLIST_FIELDS(AsyncServiceResolverInfo, async_service_resolvers);
172 AVAHI_LLIST_FIELDS(Client, clients);
173 AVAHI_LLIST_HEAD(EntryGroupInfo, entry_groups);
174 AVAHI_LLIST_HEAD(SyncHostNameResolverInfo, sync_host_name_resolvers);
175 AVAHI_LLIST_HEAD(AsyncHostNameResolverInfo, async_host_name_resolvers);
176 AVAHI_LLIST_HEAD(SyncAddressResolverInfo, sync_address_resolvers);
177 AVAHI_LLIST_HEAD(AsyncAddressResolverInfo, async_address_resolvers);
178 AVAHI_LLIST_HEAD(DomainBrowserInfo, domain_browsers);
179 AVAHI_LLIST_HEAD(ServiceTypeBrowserInfo, service_type_browsers);
180 AVAHI_LLIST_HEAD(ServiceBrowserInfo, service_browsers);
181 AVAHI_LLIST_HEAD(SyncServiceResolverInfo, sync_service_resolvers);
182 AVAHI_LLIST_HEAD(AsyncServiceResolverInfo, async_service_resolvers);
187 AVAHI_LLIST_HEAD(Client, clients);
192 static Server *server = NULL;
194 static void entry_group_free(EntryGroupInfo *i) {
198 avahi_s_entry_group_free(i->entry_group);
199 dbus_connection_unregister_object_path(server->bus, i->path);
201 AVAHI_LLIST_REMOVE(EntryGroupInfo, entry_groups, i->client->entry_groups, i);
203 i->client->n_objects--;
204 assert(i->client->n_objects >= 0);
209 static void sync_host_name_resolver_free(SyncHostNameResolverInfo *i) {
212 if (i->host_name_resolver)
213 avahi_s_host_name_resolver_free(i->host_name_resolver);
214 dbus_message_unref(i->message);
215 AVAHI_LLIST_REMOVE(SyncHostNameResolverInfo, sync_host_name_resolvers, i->client->sync_host_name_resolvers, i);
217 i->client->n_objects--;
218 assert(i->client->n_objects >= 0);
223 static void async_host_name_resolver_free(AsyncHostNameResolverInfo *i) {
226 if (i->host_name_resolver)
227 avahi_s_host_name_resolver_free(i->host_name_resolver);
228 dbus_connection_unregister_object_path(server->bus, i->path);
229 AVAHI_LLIST_REMOVE(AsyncHostNameResolverInfo, async_host_name_resolvers, i->client->async_host_name_resolvers, i);
231 i->client->n_objects--;
232 assert(i->client->n_objects >= 0);
237 static void sync_address_resolver_free(SyncAddressResolverInfo *i) {
240 if (i->address_resolver)
241 avahi_s_address_resolver_free(i->address_resolver);
242 dbus_message_unref(i->message);
243 AVAHI_LLIST_REMOVE(SyncAddressResolverInfo, sync_address_resolvers, i->client->sync_address_resolvers, i);
245 i->client->n_objects--;
246 assert(i->client->n_objects >= 0);
251 static void async_address_resolver_free(AsyncAddressResolverInfo *i) {
254 if (i->address_resolver)
255 avahi_s_address_resolver_free(i->address_resolver);
256 dbus_connection_unregister_object_path(server->bus, i->path);
257 AVAHI_LLIST_REMOVE(AsyncAddressResolverInfo, async_address_resolvers, i->client->async_address_resolvers, i);
259 i->client->n_objects--;
260 assert(i->client->n_objects >= 0);
265 static void domain_browser_free(DomainBrowserInfo *i) {
268 if (i->domain_browser)
269 avahi_s_domain_browser_free(i->domain_browser);
270 dbus_connection_unregister_object_path(server->bus, i->path);
272 AVAHI_LLIST_REMOVE(DomainBrowserInfo, domain_browsers, i->client->domain_browsers, i);
274 i->client->n_objects--;
275 assert(i->client->n_objects >= 0);
280 static void service_type_browser_free(ServiceTypeBrowserInfo *i) {
283 if (i->service_type_browser)
284 avahi_s_service_type_browser_free(i->service_type_browser);
285 dbus_connection_unregister_object_path(server->bus, i->path);
287 AVAHI_LLIST_REMOVE(ServiceTypeBrowserInfo, service_type_browsers, i->client->service_type_browsers, i);
289 i->client->n_objects--;
290 assert(i->client->n_objects >= 0);
295 static void service_browser_free(ServiceBrowserInfo *i) {
298 if (i->service_browser)
299 avahi_s_service_browser_free(i->service_browser);
300 dbus_connection_unregister_object_path(server->bus, i->path);
302 AVAHI_LLIST_REMOVE(ServiceBrowserInfo, service_browsers, i->client->service_browsers, i);
304 i->client->n_objects--;
305 assert(i->client->n_objects >= 0);
310 static void sync_service_resolver_free(SyncServiceResolverInfo *i) {
313 if (i->service_resolver)
314 avahi_s_service_resolver_free(i->service_resolver);
315 dbus_message_unref(i->message);
316 AVAHI_LLIST_REMOVE(SyncServiceResolverInfo, sync_service_resolvers, i->client->sync_service_resolvers, i);
318 i->client->n_objects--;
319 assert(i->client->n_objects >= 0);
324 static void async_service_resolver_free(AsyncServiceResolverInfo *i) {
327 if (i->service_resolver)
328 avahi_s_service_resolver_free(i->service_resolver);
330 dbus_connection_unregister_object_path(server->bus, i->path);
331 AVAHI_LLIST_REMOVE(AsyncServiceResolverInfo, async_service_resolvers, i->client->async_service_resolvers, i);
333 i->client->n_objects--;
334 assert(i->client->n_objects >= 0);
339 static void client_free(Client *c) {
344 while (c->entry_groups)
345 entry_group_free(c->entry_groups);
347 while (c->sync_host_name_resolvers)
348 sync_host_name_resolver_free(c->sync_host_name_resolvers);
350 while (c->async_host_name_resolvers)
351 async_host_name_resolver_free(c->async_host_name_resolvers);
353 while (c->sync_address_resolvers)
354 sync_address_resolver_free(c->sync_address_resolvers);
356 while (c->async_address_resolvers)
357 async_address_resolver_free(c->async_address_resolvers);
359 while (c->domain_browsers)
360 domain_browser_free(c->domain_browsers);
362 while (c->service_type_browsers)
363 service_type_browser_free(c->service_type_browsers);
365 while (c->service_browsers)
366 service_browser_free(c->service_browsers);
368 while (c->sync_service_resolvers)
369 sync_service_resolver_free(c->sync_service_resolvers);
371 while (c->async_service_resolvers)
372 async_service_resolver_free(c->async_service_resolvers);
374 assert(c->n_objects == 0);
377 AVAHI_LLIST_REMOVE(Client, clients, server->clients, c);
380 server->n_clients --;
381 assert(server->n_clients >= 0);
384 static Client *client_get(const char *name, int create) {
390 for (client = server->clients; client; client = client->clients_next)
391 if (!strcmp(name, client->name))
397 if (server->n_clients >= MAX_CLIENTS)
400 /* If not existant yet, create a new entry */
401 client = avahi_new(Client, 1);
402 client->id = server->current_id++;
403 client->name = avahi_strdup(name);
404 client->current_id = 0;
405 client->n_objects = 0;
407 AVAHI_LLIST_HEAD_INIT(EntryGroupInfo, client->entry_groups);
408 AVAHI_LLIST_HEAD_INIT(SyncHostNameResolverInfo, client->sync_host_name_resolvers);
409 AVAHI_LLIST_HEAD_INIT(AsyncHostNameResolverInfo, client->async_host_name_resolvers);
410 AVAHI_LLIST_HEAD_INIT(SyncAddressResolverInfo, client->sync_address_resolvers);
411 AVAHI_LLIST_HEAD_INIT(AsyncAddressResolverInfo, client->async_address_resolvers);
412 AVAHI_LLIST_HEAD_INIT(DomainBrowserInfo, client->domain_browsers);
413 AVAHI_LLIST_HEAD_INIT(ServiceTypeBrowserInfo, client->service_type_browsers);
414 AVAHI_LLIST_HEAD_INIT(ServiceBrowserInfo, client->service_browsers);
415 AVAHI_LLIST_HEAD_INIT(SyncServiceResolverInfo, client->sync_service_resolvers);
416 AVAHI_LLIST_HEAD_INIT(AsyncServiceResolverInfo, client->async_service_resolvers);
418 AVAHI_LLIST_PREPEND(Client, clients, server->clients, client);
421 assert(server->n_clients > 0);
426 static DBusHandlerResult respond_error(DBusConnection *c, DBusMessage *m, int error, const char *text) {
429 assert(-error > -AVAHI_OK);
430 assert(-error < -AVAHI_ERR_MAX);
433 text = avahi_strerror(error);
435 reply = dbus_message_new_error(m, avahi_error_number_to_dbus(error), text);
436 dbus_connection_send(c, reply, NULL);
437 dbus_message_unref(reply);
439 avahi_log_debug(__FILE__": Responding error '%s' (%i)", text, error);
441 return DBUS_HANDLER_RESULT_HANDLED;
444 static DBusHandlerResult respond_string(DBusConnection *c, DBusMessage *m, const char *text) {
447 reply = dbus_message_new_method_return(m);
448 dbus_message_append_args(reply, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID);
449 dbus_connection_send(c, reply, NULL);
450 dbus_message_unref(reply);
452 return DBUS_HANDLER_RESULT_HANDLED;
455 static DBusHandlerResult respond_int32(DBusConnection *c, DBusMessage *m, int32_t i) {
458 reply = dbus_message_new_method_return(m);
459 dbus_message_append_args(reply, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID);
460 dbus_connection_send(c, reply, NULL);
461 dbus_message_unref(reply);
463 return DBUS_HANDLER_RESULT_HANDLED;
466 static DBusHandlerResult respond_uint32(DBusConnection *c, DBusMessage *m, uint32_t u) {
469 reply = dbus_message_new_method_return(m);
470 dbus_message_append_args(reply, DBUS_TYPE_UINT32, &u, DBUS_TYPE_INVALID);
471 dbus_connection_send(c, reply, NULL);
472 dbus_message_unref(reply);
474 return DBUS_HANDLER_RESULT_HANDLED;
477 static DBusHandlerResult respond_boolean(DBusConnection *c, DBusMessage *m, int b) {
480 reply = dbus_message_new_method_return(m);
481 dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
482 dbus_connection_send(c, reply, NULL);
483 dbus_message_unref(reply);
485 return DBUS_HANDLER_RESULT_HANDLED;
488 static DBusHandlerResult respond_ok(DBusConnection *c, DBusMessage *m) {
491 reply = dbus_message_new_method_return(m);
492 dbus_connection_send(c, reply, NULL);
493 dbus_message_unref(reply);
495 return DBUS_HANDLER_RESULT_HANDLED;
498 static DBusHandlerResult respond_path(DBusConnection *c, DBusMessage *m, const char *path) {
501 reply = dbus_message_new_method_return(m);
502 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
503 dbus_connection_send(c, reply, NULL);
504 dbus_message_unref(reply);
506 return DBUS_HANDLER_RESULT_HANDLED;
509 static void append_server_error(DBusMessage *reply) {
512 t = avahi_error_number_to_dbus(avahi_server_errno(avahi_server));
514 dbus_message_append_args(
516 DBUS_TYPE_STRING, &t,
520 static char *file_get_contents(char *fname) {
528 if (!(fd = open(fname, O_RDONLY))) {
529 avahi_log_error("Failed to open %s: %s", fname, strerror(errno));
533 if (fstat(fd, &st) < 0) {
534 avahi_log_error("stat(%s) failed: %s", fname, strerror(errno));
538 if (!(S_ISREG(st.st_mode))) {
539 avahi_log_error("Invalid file %s", fname);
543 if (st.st_size > 1024*1024) { /** 1MB */
544 avahi_log_error("File too large %s", fname);
548 buf = avahi_new(char, st.st_size+1);
550 if ((size = read(fd, buf, st.st_size)) < 0) {
551 avahi_log_error("read() failed: %s\n", strerror(errno));
571 static const char *map_browse_signal_name(AvahiBrowserEvent e) {
573 case AVAHI_BROWSER_NEW : return "ItemNew";
574 case AVAHI_BROWSER_REMOVE : return "ItemRemove";
575 case AVAHI_BROWSER_FAILURE : return "Failure";
576 case AVAHI_BROWSER_CACHE_EXHAUSTED : return "CacheExhausted";
577 case AVAHI_BROWSER_ALL_FOR_NOW : return "AllForNow";
583 static const char *map_resolve_signal_name(AvahiResolverEvent e) {
585 case AVAHI_RESOLVER_FOUND : return "Found";
586 case AVAHI_RESOLVER_FAILURE : return "Failure";
593 static DBusHandlerResult handle_introspect(DBusConnection *c, DBusMessage *m, const char *fname) {
594 char *path, *contents;
601 dbus_error_init(&error);
603 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
604 avahi_log_error("Error parsing Introspect message: %s", error.message);
608 path = avahi_strdup_printf("%s/%s", AVAHI_DBUS_INTROSPECTION_DIR, fname);
609 contents = file_get_contents(path);
613 avahi_log_error("Failed to load introspection data.");
617 respond_string(c, m, contents);
618 avahi_free(contents);
620 return DBUS_HANDLER_RESULT_HANDLED;
623 if (dbus_error_is_set(&error))
624 dbus_error_free(&error);
626 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
630 static DBusHandlerResult msg_signal_filter_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
633 dbus_error_init(&error);
635 /* avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s", */
636 /* dbus_message_get_interface(m), */
637 /* dbus_message_get_path(m), */
638 /* dbus_message_get_member(m)); */
640 if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
641 /* No, we shouldn't quit, but until we get somewhere
642 * usefull such that we can restore our state, we will */
643 avahi_log_warn("Disconnnected from D-BUS, terminating...");
645 raise(SIGQUIT); /* The signal handler will catch this and terminate the process cleanly*/
647 return DBUS_HANDLER_RESULT_HANDLED;
649 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) {
652 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
653 avahi_log_warn("Error parsing NameAcquired message");
657 /* avahi_log_info(__FILE__": name acquired (%s)", name); */
658 return DBUS_HANDLER_RESULT_HANDLED;
660 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
661 char *name, *old, *new;
663 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) {
664 avahi_log_warn("Error parsing NameOwnerChanged message");
671 if ((client = client_get(name, FALSE))) {
672 avahi_log_debug(__FILE__": client %s vanished.", name);
679 if (dbus_error_is_set(&error))
680 dbus_error_free(&error);
682 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
685 static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntryGroupState state, void* userdata) {
686 EntryGroupInfo *i = userdata;
694 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged");
696 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
697 dbus_message_set_destination(m, i->client->name);
698 dbus_connection_send(server->bus, m, NULL);
699 dbus_message_unref(m);
702 static int read_strlst(DBusMessage *m, int idx, AvahiStringList **l) {
703 DBusMessageIter iter, sub;
705 AvahiStringList *strlst = NULL;
710 dbus_message_iter_init(m, &iter);
712 for (j = 0; j < idx; j++)
713 dbus_message_iter_next(&iter);
715 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
716 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY)
719 dbus_message_iter_recurse(&iter, &sub);
722 DBusMessageIter sub2;
726 if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
729 assert(at == DBUS_TYPE_ARRAY);
731 if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE)
734 dbus_message_iter_recurse(&sub, &sub2);
735 dbus_message_iter_get_fixed_array(&sub2, &k, &n);
736 strlst = avahi_string_list_add_arbitrary(strlst, k, n);
738 dbus_message_iter_next(&sub);
746 avahi_log_warn("Error parsing TXT data");
748 avahi_string_list_free(strlst);
754 static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
756 EntryGroupInfo *i = userdata;
762 dbus_error_init(&error);
764 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
765 dbus_message_get_interface(m),
766 dbus_message_get_path(m),
767 dbus_message_get_member(m));
770 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
771 return handle_introspect(c, m, "EntryGroup.introspect");
774 if (strcmp(dbus_message_get_sender(m), i->client->name))
775 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
777 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) {
779 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
780 avahi_log_warn("Error parsing EntryGroup::Free message");
785 return respond_ok(c, m);
787 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Commit")) {
789 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
790 avahi_log_warn("Error parsing EntryGroup::Commit message");
794 avahi_s_entry_group_commit(i->entry_group);
795 return respond_ok(c, m);
798 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Reset")) {
800 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
801 avahi_log_warn("Error parsing EntryGroup::Reset message");
805 avahi_s_entry_group_reset(i->entry_group);
807 return respond_ok(c, m);
809 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) {
811 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
812 avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
816 return respond_boolean(c, m, !!avahi_s_entry_group_is_empty(i->entry_group));
818 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
819 AvahiEntryGroupState state;
821 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
822 avahi_log_warn("Error parsing EntryGroup::GetState message");
826 state = avahi_s_entry_group_get_state(i->entry_group);
827 return respond_int32(c, m, (int32_t) state);
829 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
830 int32_t interface, protocol;
832 char *type, *name, *domain, *host;
834 AvahiStringList *strlst = NULL;
836 if (!dbus_message_get_args(
838 DBUS_TYPE_INT32, &interface,
839 DBUS_TYPE_INT32, &protocol,
840 DBUS_TYPE_UINT32, &flags,
841 DBUS_TYPE_STRING, &name,
842 DBUS_TYPE_STRING, &type,
843 DBUS_TYPE_STRING, &domain,
844 DBUS_TYPE_STRING, &host,
845 DBUS_TYPE_UINT16, &port,
846 DBUS_TYPE_INVALID) ||
848 read_strlst(m, 8, &strlst) < 0) {
849 avahi_log_warn("Error parsing EntryGroup::AddService message");
853 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
854 avahi_string_list_free(strlst);
855 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
858 if (domain && !*domain)
864 if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, host, port, strlst) < 0) {
865 avahi_string_list_free(strlst);
866 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
869 if (!(flags & AVAHI_PUBLISH_UPDATE))
872 avahi_string_list_free(strlst);
874 return respond_ok(c, m);
876 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddServiceSubtype")) {
878 int32_t interface, protocol;
880 char *type, *name, *domain, *subtype;
882 if (!dbus_message_get_args(
884 DBUS_TYPE_INT32, &interface,
885 DBUS_TYPE_INT32, &protocol,
886 DBUS_TYPE_UINT32, &flags,
887 DBUS_TYPE_STRING, &name,
888 DBUS_TYPE_STRING, &type,
889 DBUS_TYPE_STRING, &domain,
890 DBUS_TYPE_STRING, &subtype,
891 DBUS_TYPE_INVALID) || !type || !name || !subtype) {
892 avahi_log_warn("Error parsing EntryGroup::AddServiceSubtype message");
896 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP)
897 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
899 if (domain && !*domain)
902 if (avahi_server_add_service_subtype(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, subtype) < 0)
903 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
905 if (!(flags & AVAHI_PUBLISH_UPDATE))
908 return respond_ok(c, m);
910 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "UpdateServiceTxt")) {
911 int32_t interface, protocol;
913 char *type, *name, *domain;
914 AvahiStringList *strlst;
916 if (!dbus_message_get_args(
918 DBUS_TYPE_INT32, &interface,
919 DBUS_TYPE_INT32, &protocol,
920 DBUS_TYPE_UINT32, &flags,
921 DBUS_TYPE_STRING, &name,
922 DBUS_TYPE_STRING, &type,
923 DBUS_TYPE_STRING, &domain,
924 DBUS_TYPE_INVALID) ||
926 read_strlst(m, 6, &strlst)) {
927 avahi_log_warn("Error parsing EntryGroup::UpdateServiceTxt message");
931 if (domain && !*domain)
934 if (avahi_server_update_service_txt_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, strlst) < 0) {
935 avahi_string_list_free(strlst);
936 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
939 avahi_string_list_free(strlst);
941 return respond_ok(c, m);
943 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
944 int32_t interface, protocol;
946 char *name, *address;
949 if (!dbus_message_get_args(
951 DBUS_TYPE_INT32, &interface,
952 DBUS_TYPE_INT32, &protocol,
953 DBUS_TYPE_UINT32, &flags,
954 DBUS_TYPE_STRING, &name,
955 DBUS_TYPE_STRING, &address,
956 DBUS_TYPE_INVALID) || !name || !address) {
957 avahi_log_warn("Error parsing EntryGroup::AddAddress message");
961 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP)
962 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
964 if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a)))
965 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
967 if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, &a) < 0)
968 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
970 if (!(flags & AVAHI_PUBLISH_UPDATE))
973 return respond_ok(c, m);
976 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
979 if (dbus_error_is_set(&error))
980 dbus_error_free(&error);
982 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
985 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) {
986 SyncHostNameResolverInfo *i = userdata;
992 if (event == AVAHI_RESOLVER_FOUND) {
993 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
994 int32_t i_interface, i_protocol, i_aprotocol;
999 avahi_address_snprint(t, sizeof(t), a);
1001 i_interface = (int32_t) interface;
1002 i_protocol = (int32_t) protocol;
1003 i_aprotocol = (int32_t) a->proto;
1004 u_flags = (uint32_t) flags;
1006 reply = dbus_message_new_method_return(i->message);
1007 dbus_message_append_args(
1009 DBUS_TYPE_INT32, &i_interface,
1010 DBUS_TYPE_INT32, &i_protocol,
1011 DBUS_TYPE_STRING, &host_name,
1012 DBUS_TYPE_INT32, &i_aprotocol,
1013 DBUS_TYPE_STRING, &pt,
1014 DBUS_TYPE_UINT32, &u_flags,
1017 dbus_connection_send(server->bus, reply, NULL);
1018 dbus_message_unref(reply);
1020 assert(event == AVAHI_RESOLVER_FAILURE);
1021 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1024 sync_host_name_resolver_free(i);
1027 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) {
1028 SyncAddressResolverInfo *i = userdata;
1034 if (event == AVAHI_RESOLVER_FOUND) {
1035 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1036 int32_t i_interface, i_protocol, i_aprotocol;
1041 avahi_address_snprint(t, sizeof(t), address);
1043 i_interface = (int32_t) interface;
1044 i_protocol = (int32_t) protocol;
1045 i_aprotocol = (int32_t) address->proto;
1046 u_flags = (uint32_t) flags;
1048 reply = dbus_message_new_method_return(i->message);
1049 dbus_message_append_args(
1051 DBUS_TYPE_INT32, &i_interface,
1052 DBUS_TYPE_INT32, &i_protocol,
1053 DBUS_TYPE_INT32, &i_aprotocol,
1054 DBUS_TYPE_STRING, &pt,
1055 DBUS_TYPE_STRING, &host_name,
1056 DBUS_TYPE_UINT32, &u_flags,
1059 dbus_connection_send(server->bus, reply, NULL);
1060 dbus_message_unref(reply);
1062 assert(event == AVAHI_RESOLVER_FAILURE);
1063 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1066 sync_address_resolver_free(i);
1069 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1071 DomainBrowserInfo *i = userdata;
1077 dbus_error_init(&error);
1079 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1080 dbus_message_get_interface(m),
1081 dbus_message_get_path(m),
1082 dbus_message_get_member(m));
1085 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1086 return handle_introspect(c, m, "DomainBrowser.introspect");
1088 /* Access control */
1089 if (strcmp(dbus_message_get_sender(m), i->client->name))
1090 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1092 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
1094 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1095 avahi_log_warn("Error parsing DomainBrowser::Free message");
1099 domain_browser_free(i);
1100 return respond_ok(c, m);
1104 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1107 if (dbus_error_is_set(&error))
1108 dbus_error_free(&error);
1110 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1113 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1114 DomainBrowserInfo *i = userdata;
1116 int32_t i_interface, i_protocol;
1122 i_interface = (int32_t) interface;
1123 i_protocol = (int32_t) protocol;
1124 u_flags = (uint32_t) flags;
1126 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, map_browse_signal_name(event));
1128 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, &domain,
1135 DBUS_TYPE_UINT32, &u_flags,
1137 } else if (event == AVAHI_BROWSER_FAILURE)
1138 append_server_error(m);
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_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1147 ServiceTypeBrowserInfo *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, "ServiceTypeBrowser.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_TYPE_BROWSER, "Free")) {
1170 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1171 avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
1175 service_type_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_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1190 ServiceTypeBrowserInfo *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_TYPE_BROWSER, map_browse_signal_name(event));
1204 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1207 dbus_message_append_args(
1209 DBUS_TYPE_INT32, &i_interface,
1210 DBUS_TYPE_INT32, &i_protocol,
1211 DBUS_TYPE_STRING, &type,
1212 DBUS_TYPE_STRING, &domain,
1213 DBUS_TYPE_UINT32, &u_flags,
1215 } else if (event == AVAHI_BROWSER_FAILURE)
1216 append_server_error(m);
1218 dbus_message_set_destination(m, i->client->name);
1219 dbus_connection_send(server->bus, m, NULL);
1220 dbus_message_unref(m);
1223 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1225 ServiceBrowserInfo *i = userdata;
1231 dbus_error_init(&error);
1233 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1234 dbus_message_get_interface(m),
1235 dbus_message_get_path(m),
1236 dbus_message_get_member(m));
1239 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1240 return handle_introspect(c, m, "ServiceBrowser.Introspect");
1242 /* Access control */
1243 if (strcmp(dbus_message_get_sender(m), i->client->name))
1244 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1246 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
1248 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1249 avahi_log_warn("Error parsing ServiceBrowser::Free message");
1253 service_browser_free(i);
1254 return respond_ok(c, m);
1258 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1261 if (dbus_error_is_set(&error))
1262 dbus_error_free(&error);
1264 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1267 static int is_our_own_service(Client *c, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain) {
1268 AvahiSEntryGroup *g;
1271 if (avahi_server_get_group_of_service(avahi_server, interface, protocol, name, type, domain, &g) == AVAHI_OK) {
1272 EntryGroupInfo *egi;
1274 for (egi = c->entry_groups; egi; egi = egi->entry_groups_next)
1275 if (egi->entry_group == g)
1282 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) {
1283 ServiceBrowserInfo *i = userdata;
1285 int32_t i_interface, i_protocol;
1291 i_interface = (int32_t) interface;
1292 i_protocol = (int32_t) protocol;
1293 u_flags = (uint32_t) flags;
1295 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, map_browse_signal_name(event));
1297 if (event == AVAHI_BROWSER_NEW) {
1298 /* Patch in AVAHI_LOOKUP_RESULT_OUR_OWN */
1300 if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1301 flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1304 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1309 dbus_message_append_args(
1311 DBUS_TYPE_INT32, &i_interface,
1312 DBUS_TYPE_INT32, &i_protocol,
1313 DBUS_TYPE_STRING, &name,
1314 DBUS_TYPE_STRING, &type,
1315 DBUS_TYPE_STRING, &domain,
1316 DBUS_TYPE_UINT32, &u_flags,
1318 } else if (event == AVAHI_BROWSER_FAILURE)
1319 append_server_error(m);
1321 dbus_message_set_destination(m, i->client->name);
1322 dbus_connection_send(server->bus, m, NULL);
1323 dbus_message_unref(m);
1326 static void append_string_list(DBusMessage *reply, AvahiStringList *txt) {
1328 DBusMessageIter iter, sub;
1332 dbus_message_iter_init_append(reply, &iter);
1333 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1335 for (p = txt; p; p = p->next) {
1336 DBusMessageIter sub2;
1337 const uint8_t *data = p->text;
1339 dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1340 dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
1341 dbus_message_iter_close_container(&sub, &sub2);
1344 dbus_message_iter_close_container(&iter, &sub);
1347 static void sync_service_resolver_callback(
1348 AvahiSServiceResolver *r,
1349 AvahiIfIndex interface,
1350 AvahiProtocol protocol,
1351 AvahiResolverEvent event,
1355 const char *host_name,
1356 const AvahiAddress *a,
1358 AvahiStringList *txt,
1359 AvahiLookupResultFlags flags,
1362 SyncServiceResolverInfo *i = userdata;
1367 if (event == AVAHI_RESOLVER_FOUND) {
1368 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1369 int32_t i_interface, i_protocol, i_aprotocol;
1379 avahi_address_snprint(t, sizeof(t), a);
1383 /* Patch in AVAHI_LOOKUP_RESULT_OUR_OWN */
1385 if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1386 flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1388 i_interface = (int32_t) interface;
1389 i_protocol = (int32_t) protocol;
1391 i_aprotocol = (int32_t) a->proto;
1393 i_aprotocol = AVAHI_PROTO_UNSPEC;
1394 u_flags = (uint32_t) flags;
1396 reply = dbus_message_new_method_return(i->message);
1397 dbus_message_append_args(
1399 DBUS_TYPE_INT32, &i_interface,
1400 DBUS_TYPE_INT32, &i_protocol,
1401 DBUS_TYPE_STRING, &name,
1402 DBUS_TYPE_STRING, &type,
1403 DBUS_TYPE_STRING, &domain,
1404 DBUS_TYPE_STRING, &host_name,
1405 DBUS_TYPE_INT32, &i_aprotocol,
1406 DBUS_TYPE_STRING, &pt,
1407 DBUS_TYPE_UINT16, &port,
1410 append_string_list(reply, txt);
1412 dbus_message_append_args(
1414 DBUS_TYPE_UINT32, &u_flags,
1417 dbus_connection_send(server->bus, reply, NULL);
1418 dbus_message_unref(reply);
1420 assert(event == AVAHI_RESOLVER_FAILURE);
1422 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1425 sync_service_resolver_free(i);
1428 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) {
1429 AsyncAddressResolverInfo *i = userdata;
1435 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, map_resolve_signal_name(event));
1437 if (event == AVAHI_RESOLVER_FOUND) {
1438 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1439 int32_t i_interface, i_protocol, i_aprotocol;
1444 avahi_address_snprint(t, sizeof(t), address);
1446 i_interface = (int32_t) interface;
1447 i_protocol = (int32_t) protocol;
1448 i_aprotocol = (int32_t) address->proto;
1449 u_flags = (uint32_t) flags;
1451 dbus_message_append_args(
1453 DBUS_TYPE_INT32, &i_interface,
1454 DBUS_TYPE_INT32, &i_protocol,
1455 DBUS_TYPE_INT32, &i_aprotocol,
1456 DBUS_TYPE_STRING, &pt,
1457 DBUS_TYPE_STRING, &host_name,
1458 DBUS_TYPE_UINT32, &u_flags,
1462 assert(event == AVAHI_RESOLVER_FAILURE);
1463 append_server_error(reply);
1466 dbus_message_set_destination(reply, i->client->name);
1467 dbus_connection_send(server->bus, reply, NULL);
1468 dbus_message_unref(reply);
1471 static DBusHandlerResult msg_async_address_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1473 AsyncAddressResolverInfo *i = userdata;
1479 dbus_error_init(&error);
1481 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1482 dbus_message_get_interface(m),
1483 dbus_message_get_path(m),
1484 dbus_message_get_member(m));
1487 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1488 return handle_introspect(c, m, "AddressResolver.Introspect");
1490 /* Access control */
1491 if (strcmp(dbus_message_get_sender(m), i->client->name))
1492 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1494 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Free")) {
1496 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1497 avahi_log_warn("Error parsing AddressResolver::Free message");
1501 async_address_resolver_free(i);
1502 return respond_ok(c, m);
1506 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1509 if (dbus_error_is_set(&error))
1510 dbus_error_free(&error);
1512 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1515 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) {
1516 AsyncHostNameResolverInfo *i = userdata;
1522 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, map_resolve_signal_name(event));
1524 if (event == AVAHI_RESOLVER_FOUND) {
1525 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1526 int32_t i_interface, i_protocol, i_aprotocol;
1531 avahi_address_snprint(t, sizeof(t), a);
1533 i_interface = (int32_t) interface;
1534 i_protocol = (int32_t) protocol;
1535 i_aprotocol = (int32_t) a->proto;
1536 u_flags = (uint32_t) flags;
1538 dbus_message_append_args(
1540 DBUS_TYPE_INT32, &i_interface,
1541 DBUS_TYPE_INT32, &i_protocol,
1542 DBUS_TYPE_STRING, &host_name,
1543 DBUS_TYPE_INT32, &i_aprotocol,
1544 DBUS_TYPE_STRING, &pt,
1545 DBUS_TYPE_UINT32, &u_flags,
1548 assert(event == AVAHI_RESOLVER_FAILURE);
1549 append_server_error(reply);
1552 dbus_message_set_destination(reply, i->client->name);
1553 dbus_connection_send(server->bus, reply, NULL);
1554 dbus_message_unref(reply);
1557 static DBusHandlerResult msg_async_host_name_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1559 AsyncHostNameResolverInfo *i = userdata;
1565 dbus_error_init(&error);
1567 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1568 dbus_message_get_interface(m),
1569 dbus_message_get_path(m),
1570 dbus_message_get_member(m));
1573 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1574 return handle_introspect(c, m, "HostNameResolver.Introspect");
1576 /* Access control */
1577 if (strcmp(dbus_message_get_sender(m), i->client->name))
1578 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1580 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, "Free")) {
1582 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1583 avahi_log_warn("Error parsing HostNameResolver::Free message");
1587 async_host_name_resolver_free(i);
1588 return respond_ok(c, m);
1591 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1594 if (dbus_error_is_set(&error))
1595 dbus_error_free(&error);
1597 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1600 static void async_service_resolver_callback(
1601 AvahiSServiceResolver *r,
1602 AvahiIfIndex interface,
1603 AvahiProtocol protocol,
1604 AvahiResolverEvent event,
1608 const char *host_name,
1609 const AvahiAddress *a,
1611 AvahiStringList *txt,
1612 AvahiLookupResultFlags flags,
1615 AsyncServiceResolverInfo *i = userdata;
1621 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, map_resolve_signal_name(event));
1623 if (event == AVAHI_RESOLVER_FOUND) {
1624 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1625 int32_t i_interface, i_protocol, i_aprotocol;
1630 /* avahi_log_debug(__FILE__": [%s] Successfully resolved service <%s.%s.%s>", i->path, name, type, domain); */
1633 avahi_address_snprint(t, sizeof(t), a);
1640 if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1641 flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1643 i_interface = (int32_t) interface;
1644 i_protocol = (int32_t) protocol;
1646 i_aprotocol = (int32_t) a->proto;
1648 i_aprotocol = AVAHI_PROTO_UNSPEC;
1649 u_flags = (uint32_t) flags;
1651 dbus_message_append_args(
1653 DBUS_TYPE_INT32, &i_interface,
1654 DBUS_TYPE_INT32, &i_protocol,
1655 DBUS_TYPE_STRING, &name,
1656 DBUS_TYPE_STRING, &type,
1657 DBUS_TYPE_STRING, &domain,
1658 DBUS_TYPE_STRING, &host_name,
1659 DBUS_TYPE_INT32, &i_aprotocol,
1660 DBUS_TYPE_STRING, &pt,
1661 DBUS_TYPE_UINT16, &port,
1664 append_string_list(reply, txt);
1666 dbus_message_append_args(
1668 DBUS_TYPE_UINT32, &u_flags,
1671 assert(event == AVAHI_RESOLVER_FAILURE);
1672 append_server_error(reply);
1675 dbus_message_set_destination(reply, i->client->name);
1676 dbus_connection_send(server->bus, reply, NULL);
1677 dbus_message_unref(reply);
1680 static DBusHandlerResult msg_async_service_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1682 AsyncServiceResolverInfo *i = userdata;
1688 dbus_error_init(&error);
1690 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1691 dbus_message_get_interface(m),
1692 dbus_message_get_path(m),
1693 dbus_message_get_member(m));
1696 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1697 return handle_introspect(c, m, "ServiceResolver.Introspect");
1699 /* Access control */
1700 if (strcmp(dbus_message_get_sender(m), i->client->name))
1701 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1703 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, "Free")) {
1705 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1706 avahi_log_warn("Error parsing ServiceResolver::Free message");
1710 async_service_resolver_free(i);
1711 return respond_ok(c, m);
1714 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1717 if (dbus_error_is_set(&error))
1718 dbus_error_free(&error);
1720 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1723 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1726 dbus_error_init(&error);
1728 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1729 dbus_message_get_interface(m),
1730 dbus_message_get_path(m),
1731 dbus_message_get_member(m));
1733 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1734 return handle_introspect(c, m, "Server.introspect");
1736 else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1738 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1739 avahi_log_warn("Error parsing Server::GetHostName message");
1743 return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1745 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1747 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1748 avahi_log_warn("Error parsing Server::GetDomainName message");
1752 return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1754 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1756 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1757 avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1761 return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1763 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1765 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1766 avahi_log_warn("Error parsing Server::GetVersionString message");
1770 return respond_string(c, m, PACKAGE_STRING);
1772 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1773 AvahiServerState state;
1775 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1776 avahi_log_warn("Error parsing Server::GetState message");
1780 state = avahi_server_get_state(avahi_server);
1781 return respond_int32(c, m, (int32_t) state);
1783 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetLocalServiceCookie")) {
1785 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1786 avahi_log_warn("Error parsing Server::GetLocalServiceCookie message");
1790 return respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server));
1792 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1795 char name[IF_NAMESIZE];
1798 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1799 avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1803 #ifdef VALGRIND_WORKAROUND
1804 return respond_string(c, m, "blah");
1807 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1808 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1810 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1811 return respond_error(c, m, AVAHI_ERR_OS, txt);
1814 if ((!if_indextoname(idx, name))) {
1816 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1818 return respond_error(c, m, AVAHI_ERR_OS, txt);
1823 return respond_string(c, m, name);
1826 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1831 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1832 avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1836 #ifdef VALGRIND_WORKAROUND
1837 return respond_int32(c, m, 1);
1839 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1840 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1842 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1843 return respond_error(c, m, AVAHI_ERR_OS, txt);
1846 if (!(idx = if_nametoindex(n))) {
1848 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1850 return respond_error(c, m, AVAHI_ERR_OS, txt);
1855 return respond_int32(c, m, idx);
1858 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1861 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1862 avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1866 t = avahi_alternative_host_name(n);
1867 respond_string(c, m, t);
1870 return DBUS_HANDLER_RESULT_HANDLED;
1872 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1875 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1876 avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1880 t = avahi_alternative_service_name(n);
1881 respond_string(c, m, t);
1884 return DBUS_HANDLER_RESULT_HANDLED;
1886 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1889 static const DBusObjectPathVTable vtable = {
1891 msg_entry_group_impl,
1898 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1899 avahi_log_warn("Error parsing Server::EntryGroupNew message");
1903 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1904 avahi_log_warn("Too many clients, client request failed.");
1905 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1908 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1909 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1910 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1913 i = avahi_new(EntryGroupInfo, 1);
1914 i->id = ++client->current_id;
1916 i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1918 AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1919 client->n_objects++;
1921 if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1922 entry_group_free(i);
1923 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1926 dbus_connection_register_object_path(c, i->path, &vtable, i);
1927 return respond_path(c, m, i->path);
1929 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1931 int32_t interface, protocol, aprotocol;
1934 SyncHostNameResolverInfo *i;
1936 if (!dbus_message_get_args(
1938 DBUS_TYPE_INT32, &interface,
1939 DBUS_TYPE_INT32, &protocol,
1940 DBUS_TYPE_STRING, &name,
1941 DBUS_TYPE_INT32, &aprotocol,
1942 DBUS_TYPE_UINT32, &flags,
1943 DBUS_TYPE_INVALID) || !name) {
1944 avahi_log_warn("Error parsing Server::ResolveHostName message");
1948 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1949 avahi_log_warn("Too many clients, client request failed.");
1950 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1953 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1954 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1955 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1958 i = avahi_new(SyncHostNameResolverInfo, 1);
1960 i->message = dbus_message_ref(m);
1961 AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i);
1962 client->n_objects++;
1964 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))) {
1965 sync_host_name_resolver_free(i);
1966 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1969 return DBUS_HANDLER_RESULT_HANDLED;
1971 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1973 int32_t interface, protocol;
1976 SyncAddressResolverInfo *i;
1979 if (!dbus_message_get_args(
1981 DBUS_TYPE_INT32, &interface,
1982 DBUS_TYPE_INT32, &protocol,
1983 DBUS_TYPE_STRING, &address,
1984 DBUS_TYPE_UINT32, &flags,
1985 DBUS_TYPE_INVALID) || !address) {
1986 avahi_log_warn("Error parsing Server::ResolveAddress message");
1990 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
1991 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
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);
1998 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1999 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2000 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2003 i = avahi_new(SyncAddressResolverInfo, 1);
2005 i->message = dbus_message_ref(m);
2006 AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i);
2007 client->n_objects++;
2009 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, sync_address_resolver_callback, i))) {
2010 sync_address_resolver_free(i);
2011 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2014 return DBUS_HANDLER_RESULT_HANDLED;
2016 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
2018 DomainBrowserInfo *i;
2019 static const DBusObjectPathVTable vtable = {
2021 msg_domain_browser_impl,
2027 int32_t interface, protocol, type;
2031 if (!dbus_message_get_args(
2033 DBUS_TYPE_INT32, &interface,
2034 DBUS_TYPE_INT32, &protocol,
2035 DBUS_TYPE_STRING, &domain,
2036 DBUS_TYPE_INT32, &type,
2037 DBUS_TYPE_UINT32, &flags,
2038 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
2039 avahi_log_warn("Error parsing Server::DomainBrowserNew message");
2043 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2044 avahi_log_warn("Too many clients, client request failed.");
2045 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2048 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2049 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2050 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2056 i = avahi_new(DomainBrowserInfo, 1);
2057 i->id = ++client->current_id;
2059 i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
2060 AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
2061 client->n_objects++;
2063 if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, (AvahiLookupFlags) flags, domain_browser_callback, i))) {
2064 domain_browser_free(i);
2065 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2068 dbus_connection_register_object_path(c, i->path, &vtable, i);
2069 return respond_path(c, m, i->path);
2071 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
2073 ServiceTypeBrowserInfo *i;
2074 static const DBusObjectPathVTable vtable = {
2076 msg_service_type_browser_impl,
2082 int32_t interface, protocol;
2086 if (!dbus_message_get_args(
2088 DBUS_TYPE_INT32, &interface,
2089 DBUS_TYPE_INT32, &protocol,
2090 DBUS_TYPE_STRING, &domain,
2091 DBUS_TYPE_UINT32, &flags,
2092 DBUS_TYPE_INVALID)) {
2093 avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
2097 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2098 avahi_log_warn("Too many clients, client request failed.");
2099 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2103 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2104 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2105 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2111 i = avahi_new(ServiceTypeBrowserInfo, 1);
2112 i->id = ++client->current_id;
2114 i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
2115 AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
2116 client->n_objects++;
2118 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))) {
2119 service_type_browser_free(i);
2120 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2123 dbus_connection_register_object_path(c, i->path, &vtable, i);
2124 return respond_path(c, m, i->path);
2126 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
2128 ServiceBrowserInfo *i;
2129 static const DBusObjectPathVTable vtable = {
2131 msg_service_browser_impl,
2137 int32_t interface, protocol;
2139 char *domain, *type;
2141 if (!dbus_message_get_args(
2143 DBUS_TYPE_INT32, &interface,
2144 DBUS_TYPE_INT32, &protocol,
2145 DBUS_TYPE_STRING, &type,
2146 DBUS_TYPE_STRING, &domain,
2147 DBUS_TYPE_UINT32, &flags,
2148 DBUS_TYPE_INVALID) || !type) {
2149 avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
2153 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2154 avahi_log_warn("Too many clients, client request failed.");
2155 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2159 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2160 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2161 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2167 i = avahi_new(ServiceBrowserInfo, 1);
2168 i->id = ++client->current_id;
2170 i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
2171 AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
2172 client->n_objects++;
2174 if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, (AvahiLookupFlags) flags, service_browser_callback, i))) {
2175 service_browser_free(i);
2176 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2179 dbus_connection_register_object_path(c, i->path, &vtable, i);
2180 return respond_path(c, m, i->path);
2182 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
2184 int32_t interface, protocol, aprotocol;
2186 char *name, *type, *domain;
2187 SyncServiceResolverInfo *i;
2189 if (!dbus_message_get_args(
2191 DBUS_TYPE_INT32, &interface,
2192 DBUS_TYPE_INT32, &protocol,
2193 DBUS_TYPE_STRING, &name,
2194 DBUS_TYPE_STRING, &type,
2195 DBUS_TYPE_STRING, &domain,
2196 DBUS_TYPE_INT32, &aprotocol,
2197 DBUS_TYPE_UINT32, &flags,
2198 DBUS_TYPE_INVALID) || !type) {
2199 avahi_log_warn("Error parsing Server::ResolveService message");
2203 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2204 avahi_log_warn("Too many clients, client request failed.");
2205 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2208 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2209 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2210 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2219 i = avahi_new(SyncServiceResolverInfo, 1);
2221 i->message = dbus_message_ref(m);
2222 AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i);
2223 client->n_objects++;
2225 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))) {
2226 sync_service_resolver_free(i);
2227 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2230 return DBUS_HANDLER_RESULT_HANDLED;
2232 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) {
2234 int32_t interface, protocol, aprotocol;
2236 char *name, *type, *domain;
2237 AsyncServiceResolverInfo *i;
2238 static const DBusObjectPathVTable vtable = {
2240 msg_async_service_resolver_impl,
2247 if (!dbus_message_get_args(
2249 DBUS_TYPE_INT32, &interface,
2250 DBUS_TYPE_INT32, &protocol,
2251 DBUS_TYPE_STRING, &name,
2252 DBUS_TYPE_STRING, &type,
2253 DBUS_TYPE_STRING, &domain,
2254 DBUS_TYPE_INT32, &aprotocol,
2255 DBUS_TYPE_UINT32, &flags,
2256 DBUS_TYPE_INVALID) || !type) {
2257 avahi_log_warn("Error parsing Server::ServiceResolverNew message");
2261 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2262 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2263 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2266 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2267 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2268 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2277 i = avahi_new(AsyncServiceResolverInfo, 1);
2278 i->id = ++client->current_id;
2280 i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
2281 AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i);
2282 client->n_objects++;
2284 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))) {
2285 async_service_resolver_free(i);
2286 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2289 /* avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */
2291 dbus_connection_register_object_path(c, i->path, &vtable, i);
2292 return respond_path(c, m, i->path);
2294 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew")) {
2296 int32_t interface, protocol, aprotocol;
2299 AsyncHostNameResolverInfo *i;
2300 static const DBusObjectPathVTable vtable = {
2302 msg_async_host_name_resolver_impl,
2309 if (!dbus_message_get_args(
2311 DBUS_TYPE_INT32, &interface,
2312 DBUS_TYPE_INT32, &protocol,
2313 DBUS_TYPE_STRING, &name,
2314 DBUS_TYPE_INT32, &aprotocol,
2315 DBUS_TYPE_UINT32, &flags,
2316 DBUS_TYPE_INVALID) || !name) {
2317 avahi_log_warn("Error parsing Server::HostNameResolverNew message");
2321 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2322 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2323 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2326 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2327 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2328 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2331 i = avahi_new(AsyncHostNameResolverInfo, 1);
2332 i->id = ++client->current_id;
2334 i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
2335 AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i);
2336 client->n_objects++;
2338 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))) {
2339 async_host_name_resolver_free(i);
2340 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2343 dbus_connection_register_object_path(c, i->path, &vtable, i);
2344 return respond_path(c, m, i->path);
2346 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew")) {
2348 int32_t interface, protocol;
2351 AsyncAddressResolverInfo *i;
2353 static const DBusObjectPathVTable vtable = {
2355 msg_async_address_resolver_impl,
2362 if (!dbus_message_get_args(
2364 DBUS_TYPE_INT32, &interface,
2365 DBUS_TYPE_INT32, &protocol,
2366 DBUS_TYPE_STRING, &address,
2367 DBUS_TYPE_UINT32, &flags,
2368 DBUS_TYPE_INVALID) || !address) {
2369 avahi_log_warn("Error parsing Server::AddressResolverNew message");
2373 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
2374 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
2376 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2377 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2378 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2381 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2382 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2383 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2386 i = avahi_new(AsyncAddressResolverInfo, 1);
2387 i->id = ++client->current_id;
2389 i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
2390 AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i);
2391 client->n_objects++;
2393 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, async_address_resolver_callback, i))) {
2394 async_address_resolver_free(i);
2395 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2398 dbus_connection_register_object_path(c, i->path, &vtable, i);
2399 return respond_path(c, m, i->path);
2402 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
2405 if (dbus_error_is_set(&error))
2406 dbus_error_free(&error);
2408 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2411 void dbus_protocol_server_state_changed(AvahiServerState state) {
2418 m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
2419 t = (int32_t) state;
2420 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
2421 dbus_connection_send(server->bus, m, NULL);
2422 dbus_message_unref(m);
2425 int dbus_protocol_setup(const AvahiPoll *poll_api) {
2428 static const DBusObjectPathVTable server_vtable = {
2437 dbus_error_init(&error);
2439 server = avahi_new(Server, 1);
2440 AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
2441 server->current_id = 0;
2442 server->n_clients = 0;
2444 if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
2445 assert(dbus_error_is_set(&error));
2446 avahi_log_error("dbus_bus_get(): %s", error.message);
2450 if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) {
2451 avahi_log_error("avahi_dbus_connection_glue() failed");
2455 if (dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
2456 if (dbus_error_is_set(&error)) {
2457 avahi_log_error("dbus_bus_request_name(): %s", error.message);
2461 avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'");
2465 if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) {
2466 avahi_log_error("dbus_connection_add_filter() failed");
2470 dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
2472 if (dbus_error_is_set(&error)) {
2473 avahi_log_error("dbus_bus_add_match(): %s", error.message);
2477 if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
2478 avahi_log_error("dbus_connection_register_object_path() failed");
2486 dbus_connection_disconnect(server->bus);
2487 dbus_connection_unref(server->bus);
2490 if (dbus_error_is_set(&error))
2491 dbus_error_free(&error);
2498 void dbus_protocol_shutdown(void) {
2502 while (server->clients)
2503 client_free(server->clients);
2505 assert(server->n_clients == 0);
2508 dbus_connection_disconnect(server->bus);
2509 dbus_connection_unref(server->bus);