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 256
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;
695 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged");
698 if (state == AVAHI_ENTRY_GROUP_FAILURE)
699 e = avahi_error_number_to_dbus(avahi_server_errno(s));
700 else if (state == AVAHI_ENTRY_GROUP_COLLISION)
701 e = AVAHI_DBUS_ERR_COLLISION;
703 e = AVAHI_DBUS_ERR_OK;
705 dbus_message_append_args(
708 DBUS_TYPE_STRING, &e,
710 dbus_message_set_destination(m, i->client->name);
711 dbus_connection_send(server->bus, m, NULL);
712 dbus_message_unref(m);
715 static int read_strlst(DBusMessage *m, int idx, AvahiStringList **l) {
716 DBusMessageIter iter, sub;
718 AvahiStringList *strlst = NULL;
723 dbus_message_iter_init(m, &iter);
725 for (j = 0; j < idx; j++)
726 dbus_message_iter_next(&iter);
728 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
729 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY)
732 dbus_message_iter_recurse(&iter, &sub);
735 DBusMessageIter sub2;
739 if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
742 assert(at == DBUS_TYPE_ARRAY);
744 if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE)
747 dbus_message_iter_recurse(&sub, &sub2);
748 dbus_message_iter_get_fixed_array(&sub2, &k, &n);
749 strlst = avahi_string_list_add_arbitrary(strlst, k, n);
751 dbus_message_iter_next(&sub);
759 avahi_log_warn("Error parsing TXT data");
761 avahi_string_list_free(strlst);
767 static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
769 EntryGroupInfo *i = userdata;
775 dbus_error_init(&error);
777 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
778 dbus_message_get_interface(m),
779 dbus_message_get_path(m),
780 dbus_message_get_member(m));
783 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
784 return handle_introspect(c, m, "EntryGroup.introspect");
787 if (strcmp(dbus_message_get_sender(m), i->client->name))
788 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
790 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) {
792 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
793 avahi_log_warn("Error parsing EntryGroup::Free message");
798 return respond_ok(c, m);
800 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Commit")) {
802 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
803 avahi_log_warn("Error parsing EntryGroup::Commit message");
807 avahi_s_entry_group_commit(i->entry_group);
808 return respond_ok(c, m);
811 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Reset")) {
813 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
814 avahi_log_warn("Error parsing EntryGroup::Reset message");
818 avahi_s_entry_group_reset(i->entry_group);
820 return respond_ok(c, m);
822 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) {
824 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
825 avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
829 return respond_boolean(c, m, !!avahi_s_entry_group_is_empty(i->entry_group));
831 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
832 AvahiEntryGroupState state;
834 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
835 avahi_log_warn("Error parsing EntryGroup::GetState message");
839 state = avahi_s_entry_group_get_state(i->entry_group);
840 return respond_int32(c, m, (int32_t) state);
842 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
843 int32_t interface, protocol;
845 char *type, *name, *domain, *host;
847 AvahiStringList *strlst = NULL;
849 if (!dbus_message_get_args(
851 DBUS_TYPE_INT32, &interface,
852 DBUS_TYPE_INT32, &protocol,
853 DBUS_TYPE_UINT32, &flags,
854 DBUS_TYPE_STRING, &name,
855 DBUS_TYPE_STRING, &type,
856 DBUS_TYPE_STRING, &domain,
857 DBUS_TYPE_STRING, &host,
858 DBUS_TYPE_UINT16, &port,
859 DBUS_TYPE_INVALID) ||
861 read_strlst(m, 8, &strlst) < 0) {
862 avahi_log_warn("Error parsing EntryGroup::AddService message");
866 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
867 avahi_string_list_free(strlst);
868 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
871 if (domain && !*domain)
877 if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, host, port, strlst) < 0) {
878 avahi_string_list_free(strlst);
879 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
882 if (!(flags & AVAHI_PUBLISH_UPDATE))
885 avahi_string_list_free(strlst);
887 return respond_ok(c, m);
889 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddServiceSubtype")) {
891 int32_t interface, protocol;
893 char *type, *name, *domain, *subtype;
895 if (!dbus_message_get_args(
897 DBUS_TYPE_INT32, &interface,
898 DBUS_TYPE_INT32, &protocol,
899 DBUS_TYPE_UINT32, &flags,
900 DBUS_TYPE_STRING, &name,
901 DBUS_TYPE_STRING, &type,
902 DBUS_TYPE_STRING, &domain,
903 DBUS_TYPE_STRING, &subtype,
904 DBUS_TYPE_INVALID) || !type || !name || !subtype) {
905 avahi_log_warn("Error parsing EntryGroup::AddServiceSubtype message");
909 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP)
910 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
912 if (domain && !*domain)
915 if (avahi_server_add_service_subtype(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, subtype) < 0)
916 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
918 if (!(flags & AVAHI_PUBLISH_UPDATE))
921 return respond_ok(c, m);
923 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "UpdateServiceTxt")) {
924 int32_t interface, protocol;
926 char *type, *name, *domain;
927 AvahiStringList *strlst;
929 if (!dbus_message_get_args(
931 DBUS_TYPE_INT32, &interface,
932 DBUS_TYPE_INT32, &protocol,
933 DBUS_TYPE_UINT32, &flags,
934 DBUS_TYPE_STRING, &name,
935 DBUS_TYPE_STRING, &type,
936 DBUS_TYPE_STRING, &domain,
937 DBUS_TYPE_INVALID) ||
939 read_strlst(m, 6, &strlst)) {
940 avahi_log_warn("Error parsing EntryGroup::UpdateServiceTxt message");
944 if (domain && !*domain)
947 if (avahi_server_update_service_txt_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, strlst) < 0) {
948 avahi_string_list_free(strlst);
949 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
952 avahi_string_list_free(strlst);
954 return respond_ok(c, m);
956 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
957 int32_t interface, protocol;
959 char *name, *address;
962 if (!dbus_message_get_args(
964 DBUS_TYPE_INT32, &interface,
965 DBUS_TYPE_INT32, &protocol,
966 DBUS_TYPE_UINT32, &flags,
967 DBUS_TYPE_STRING, &name,
968 DBUS_TYPE_STRING, &address,
969 DBUS_TYPE_INVALID) || !name || !address) {
970 avahi_log_warn("Error parsing EntryGroup::AddAddress message");
974 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP)
975 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
977 if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a)))
978 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
980 if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, &a) < 0)
981 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
983 if (!(flags & AVAHI_PUBLISH_UPDATE))
986 return respond_ok(c, m);
989 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
992 if (dbus_error_is_set(&error))
993 dbus_error_free(&error);
995 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
998 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) {
999 SyncHostNameResolverInfo *i = userdata;
1005 if (event == AVAHI_RESOLVER_FOUND) {
1006 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1007 int32_t i_interface, i_protocol, i_aprotocol;
1012 avahi_address_snprint(t, sizeof(t), a);
1014 i_interface = (int32_t) interface;
1015 i_protocol = (int32_t) protocol;
1016 i_aprotocol = (int32_t) a->proto;
1017 u_flags = (uint32_t) flags;
1019 reply = dbus_message_new_method_return(i->message);
1020 dbus_message_append_args(
1022 DBUS_TYPE_INT32, &i_interface,
1023 DBUS_TYPE_INT32, &i_protocol,
1024 DBUS_TYPE_STRING, &host_name,
1025 DBUS_TYPE_INT32, &i_aprotocol,
1026 DBUS_TYPE_STRING, &pt,
1027 DBUS_TYPE_UINT32, &u_flags,
1030 dbus_connection_send(server->bus, reply, NULL);
1031 dbus_message_unref(reply);
1033 assert(event == AVAHI_RESOLVER_FAILURE);
1034 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1037 sync_host_name_resolver_free(i);
1040 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) {
1041 SyncAddressResolverInfo *i = userdata;
1047 if (event == AVAHI_RESOLVER_FOUND) {
1048 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1049 int32_t i_interface, i_protocol, i_aprotocol;
1054 avahi_address_snprint(t, sizeof(t), address);
1056 i_interface = (int32_t) interface;
1057 i_protocol = (int32_t) protocol;
1058 i_aprotocol = (int32_t) address->proto;
1059 u_flags = (uint32_t) flags;
1061 reply = dbus_message_new_method_return(i->message);
1062 dbus_message_append_args(
1064 DBUS_TYPE_INT32, &i_interface,
1065 DBUS_TYPE_INT32, &i_protocol,
1066 DBUS_TYPE_INT32, &i_aprotocol,
1067 DBUS_TYPE_STRING, &pt,
1068 DBUS_TYPE_STRING, &host_name,
1069 DBUS_TYPE_UINT32, &u_flags,
1072 dbus_connection_send(server->bus, reply, NULL);
1073 dbus_message_unref(reply);
1075 assert(event == AVAHI_RESOLVER_FAILURE);
1076 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1079 sync_address_resolver_free(i);
1082 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1084 DomainBrowserInfo *i = userdata;
1090 dbus_error_init(&error);
1092 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1093 dbus_message_get_interface(m),
1094 dbus_message_get_path(m),
1095 dbus_message_get_member(m));
1098 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1099 return handle_introspect(c, m, "DomainBrowser.introspect");
1101 /* Access control */
1102 if (strcmp(dbus_message_get_sender(m), i->client->name))
1103 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1105 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
1107 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1108 avahi_log_warn("Error parsing DomainBrowser::Free message");
1112 domain_browser_free(i);
1113 return respond_ok(c, m);
1117 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1120 if (dbus_error_is_set(&error))
1121 dbus_error_free(&error);
1123 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1126 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1127 DomainBrowserInfo *i = userdata;
1129 int32_t i_interface, i_protocol;
1135 i_interface = (int32_t) interface;
1136 i_protocol = (int32_t) protocol;
1137 u_flags = (uint32_t) flags;
1139 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, map_browse_signal_name(event));
1141 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1143 dbus_message_append_args(
1145 DBUS_TYPE_INT32, &i_interface,
1146 DBUS_TYPE_INT32, &i_protocol,
1147 DBUS_TYPE_STRING, &domain,
1148 DBUS_TYPE_UINT32, &u_flags,
1150 } else if (event == AVAHI_BROWSER_FAILURE)
1151 append_server_error(m);
1153 dbus_message_set_destination(m, i->client->name);
1154 dbus_connection_send(server->bus, m, NULL);
1155 dbus_message_unref(m);
1158 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1160 ServiceTypeBrowserInfo *i = userdata;
1166 dbus_error_init(&error);
1168 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1169 dbus_message_get_interface(m),
1170 dbus_message_get_path(m),
1171 dbus_message_get_member(m));
1174 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1175 return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
1177 /* Access control */
1178 if (strcmp(dbus_message_get_sender(m), i->client->name))
1179 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1181 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
1183 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1184 avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
1188 service_type_browser_free(i);
1189 return respond_ok(c, m);
1193 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1196 if (dbus_error_is_set(&error))
1197 dbus_error_free(&error);
1199 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1202 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1203 ServiceTypeBrowserInfo *i = userdata;
1205 int32_t i_interface, i_protocol;
1211 i_interface = (int32_t) interface;
1212 i_protocol = (int32_t) protocol;
1213 u_flags = (uint32_t) flags;
1215 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, map_browse_signal_name(event));
1217 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1220 dbus_message_append_args(
1222 DBUS_TYPE_INT32, &i_interface,
1223 DBUS_TYPE_INT32, &i_protocol,
1224 DBUS_TYPE_STRING, &type,
1225 DBUS_TYPE_STRING, &domain,
1226 DBUS_TYPE_UINT32, &u_flags,
1228 } else if (event == AVAHI_BROWSER_FAILURE)
1229 append_server_error(m);
1231 dbus_message_set_destination(m, i->client->name);
1232 dbus_connection_send(server->bus, m, NULL);
1233 dbus_message_unref(m);
1236 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1238 ServiceBrowserInfo *i = userdata;
1244 dbus_error_init(&error);
1246 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1247 dbus_message_get_interface(m),
1248 dbus_message_get_path(m),
1249 dbus_message_get_member(m));
1252 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1253 return handle_introspect(c, m, "ServiceBrowser.Introspect");
1255 /* Access control */
1256 if (strcmp(dbus_message_get_sender(m), i->client->name))
1257 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1259 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
1261 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1262 avahi_log_warn("Error parsing ServiceBrowser::Free message");
1266 service_browser_free(i);
1267 return respond_ok(c, m);
1271 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1274 if (dbus_error_is_set(&error))
1275 dbus_error_free(&error);
1277 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1280 static int is_our_own_service(Client *c, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain) {
1281 AvahiSEntryGroup *g;
1284 if (avahi_server_get_group_of_service(avahi_server, interface, protocol, name, type, domain, &g) == AVAHI_OK) {
1285 EntryGroupInfo *egi;
1287 for (egi = c->entry_groups; egi; egi = egi->entry_groups_next)
1288 if (egi->entry_group == g)
1295 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) {
1296 ServiceBrowserInfo *i = userdata;
1298 int32_t i_interface, i_protocol;
1304 i_interface = (int32_t) interface;
1305 i_protocol = (int32_t) protocol;
1306 u_flags = (uint32_t) flags;
1308 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, map_browse_signal_name(event));
1310 if (event == AVAHI_BROWSER_NEW) {
1311 /* Patch in AVAHI_LOOKUP_RESULT_OUR_OWN */
1313 if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1314 flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1317 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1322 dbus_message_append_args(
1324 DBUS_TYPE_INT32, &i_interface,
1325 DBUS_TYPE_INT32, &i_protocol,
1326 DBUS_TYPE_STRING, &name,
1327 DBUS_TYPE_STRING, &type,
1328 DBUS_TYPE_STRING, &domain,
1329 DBUS_TYPE_UINT32, &u_flags,
1331 } else if (event == AVAHI_BROWSER_FAILURE)
1332 append_server_error(m);
1334 dbus_message_set_destination(m, i->client->name);
1335 dbus_connection_send(server->bus, m, NULL);
1336 dbus_message_unref(m);
1339 static void append_string_list(DBusMessage *reply, AvahiStringList *txt) {
1341 DBusMessageIter iter, sub;
1345 dbus_message_iter_init_append(reply, &iter);
1346 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1348 for (p = txt; p; p = p->next) {
1349 DBusMessageIter sub2;
1350 const uint8_t *data = p->text;
1352 dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1353 dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
1354 dbus_message_iter_close_container(&sub, &sub2);
1357 dbus_message_iter_close_container(&iter, &sub);
1360 static void sync_service_resolver_callback(
1361 AvahiSServiceResolver *r,
1362 AvahiIfIndex interface,
1363 AvahiProtocol protocol,
1364 AvahiResolverEvent event,
1368 const char *host_name,
1369 const AvahiAddress *a,
1371 AvahiStringList *txt,
1372 AvahiLookupResultFlags flags,
1375 SyncServiceResolverInfo *i = userdata;
1380 if (event == AVAHI_RESOLVER_FOUND) {
1381 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1382 int32_t i_interface, i_protocol, i_aprotocol;
1392 avahi_address_snprint(t, sizeof(t), a);
1396 /* Patch in AVAHI_LOOKUP_RESULT_OUR_OWN */
1398 if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1399 flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1401 i_interface = (int32_t) interface;
1402 i_protocol = (int32_t) protocol;
1404 i_aprotocol = (int32_t) a->proto;
1406 i_aprotocol = AVAHI_PROTO_UNSPEC;
1407 u_flags = (uint32_t) flags;
1409 reply = dbus_message_new_method_return(i->message);
1410 dbus_message_append_args(
1412 DBUS_TYPE_INT32, &i_interface,
1413 DBUS_TYPE_INT32, &i_protocol,
1414 DBUS_TYPE_STRING, &name,
1415 DBUS_TYPE_STRING, &type,
1416 DBUS_TYPE_STRING, &domain,
1417 DBUS_TYPE_STRING, &host_name,
1418 DBUS_TYPE_INT32, &i_aprotocol,
1419 DBUS_TYPE_STRING, &pt,
1420 DBUS_TYPE_UINT16, &port,
1423 append_string_list(reply, txt);
1425 dbus_message_append_args(
1427 DBUS_TYPE_UINT32, &u_flags,
1430 dbus_connection_send(server->bus, reply, NULL);
1431 dbus_message_unref(reply);
1433 assert(event == AVAHI_RESOLVER_FAILURE);
1435 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1438 sync_service_resolver_free(i);
1441 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) {
1442 AsyncAddressResolverInfo *i = userdata;
1448 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, map_resolve_signal_name(event));
1450 if (event == AVAHI_RESOLVER_FOUND) {
1451 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1452 int32_t i_interface, i_protocol, i_aprotocol;
1457 avahi_address_snprint(t, sizeof(t), address);
1459 i_interface = (int32_t) interface;
1460 i_protocol = (int32_t) protocol;
1461 i_aprotocol = (int32_t) address->proto;
1462 u_flags = (uint32_t) flags;
1464 dbus_message_append_args(
1466 DBUS_TYPE_INT32, &i_interface,
1467 DBUS_TYPE_INT32, &i_protocol,
1468 DBUS_TYPE_INT32, &i_aprotocol,
1469 DBUS_TYPE_STRING, &pt,
1470 DBUS_TYPE_STRING, &host_name,
1471 DBUS_TYPE_UINT32, &u_flags,
1475 assert(event == AVAHI_RESOLVER_FAILURE);
1476 append_server_error(reply);
1479 dbus_message_set_destination(reply, i->client->name);
1480 dbus_connection_send(server->bus, reply, NULL);
1481 dbus_message_unref(reply);
1484 static DBusHandlerResult msg_async_address_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1486 AsyncAddressResolverInfo *i = userdata;
1492 dbus_error_init(&error);
1494 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1495 dbus_message_get_interface(m),
1496 dbus_message_get_path(m),
1497 dbus_message_get_member(m));
1500 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1501 return handle_introspect(c, m, "AddressResolver.Introspect");
1503 /* Access control */
1504 if (strcmp(dbus_message_get_sender(m), i->client->name))
1505 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1507 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Free")) {
1509 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1510 avahi_log_warn("Error parsing AddressResolver::Free message");
1514 async_address_resolver_free(i);
1515 return respond_ok(c, m);
1519 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1522 if (dbus_error_is_set(&error))
1523 dbus_error_free(&error);
1525 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1528 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) {
1529 AsyncHostNameResolverInfo *i = userdata;
1535 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, map_resolve_signal_name(event));
1537 if (event == AVAHI_RESOLVER_FOUND) {
1538 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1539 int32_t i_interface, i_protocol, i_aprotocol;
1544 avahi_address_snprint(t, sizeof(t), a);
1546 i_interface = (int32_t) interface;
1547 i_protocol = (int32_t) protocol;
1548 i_aprotocol = (int32_t) a->proto;
1549 u_flags = (uint32_t) flags;
1551 dbus_message_append_args(
1553 DBUS_TYPE_INT32, &i_interface,
1554 DBUS_TYPE_INT32, &i_protocol,
1555 DBUS_TYPE_STRING, &host_name,
1556 DBUS_TYPE_INT32, &i_aprotocol,
1557 DBUS_TYPE_STRING, &pt,
1558 DBUS_TYPE_UINT32, &u_flags,
1561 assert(event == AVAHI_RESOLVER_FAILURE);
1562 append_server_error(reply);
1565 dbus_message_set_destination(reply, i->client->name);
1566 dbus_connection_send(server->bus, reply, NULL);
1567 dbus_message_unref(reply);
1570 static DBusHandlerResult msg_async_host_name_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1572 AsyncHostNameResolverInfo *i = userdata;
1578 dbus_error_init(&error);
1580 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1581 dbus_message_get_interface(m),
1582 dbus_message_get_path(m),
1583 dbus_message_get_member(m));
1586 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1587 return handle_introspect(c, m, "HostNameResolver.Introspect");
1589 /* Access control */
1590 if (strcmp(dbus_message_get_sender(m), i->client->name))
1591 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1593 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, "Free")) {
1595 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1596 avahi_log_warn("Error parsing HostNameResolver::Free message");
1600 async_host_name_resolver_free(i);
1601 return respond_ok(c, m);
1604 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1607 if (dbus_error_is_set(&error))
1608 dbus_error_free(&error);
1610 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1613 static void async_service_resolver_callback(
1614 AvahiSServiceResolver *r,
1615 AvahiIfIndex interface,
1616 AvahiProtocol protocol,
1617 AvahiResolverEvent event,
1621 const char *host_name,
1622 const AvahiAddress *a,
1624 AvahiStringList *txt,
1625 AvahiLookupResultFlags flags,
1628 AsyncServiceResolverInfo *i = userdata;
1634 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, map_resolve_signal_name(event));
1636 if (event == AVAHI_RESOLVER_FOUND) {
1637 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1638 int32_t i_interface, i_protocol, i_aprotocol;
1643 /* avahi_log_debug(__FILE__": [%s] Successfully resolved service <%s.%s.%s>", i->path, name, type, domain); */
1646 avahi_address_snprint(t, sizeof(t), a);
1653 if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1654 flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1656 i_interface = (int32_t) interface;
1657 i_protocol = (int32_t) protocol;
1659 i_aprotocol = (int32_t) a->proto;
1661 i_aprotocol = AVAHI_PROTO_UNSPEC;
1662 u_flags = (uint32_t) flags;
1664 dbus_message_append_args(
1666 DBUS_TYPE_INT32, &i_interface,
1667 DBUS_TYPE_INT32, &i_protocol,
1668 DBUS_TYPE_STRING, &name,
1669 DBUS_TYPE_STRING, &type,
1670 DBUS_TYPE_STRING, &domain,
1671 DBUS_TYPE_STRING, &host_name,
1672 DBUS_TYPE_INT32, &i_aprotocol,
1673 DBUS_TYPE_STRING, &pt,
1674 DBUS_TYPE_UINT16, &port,
1677 append_string_list(reply, txt);
1679 dbus_message_append_args(
1681 DBUS_TYPE_UINT32, &u_flags,
1684 assert(event == AVAHI_RESOLVER_FAILURE);
1685 append_server_error(reply);
1688 dbus_message_set_destination(reply, i->client->name);
1689 dbus_connection_send(server->bus, reply, NULL);
1690 dbus_message_unref(reply);
1693 static DBusHandlerResult msg_async_service_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1695 AsyncServiceResolverInfo *i = userdata;
1701 dbus_error_init(&error);
1703 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1704 dbus_message_get_interface(m),
1705 dbus_message_get_path(m),
1706 dbus_message_get_member(m));
1709 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1710 return handle_introspect(c, m, "ServiceResolver.Introspect");
1712 /* Access control */
1713 if (strcmp(dbus_message_get_sender(m), i->client->name))
1714 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1716 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, "Free")) {
1718 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1719 avahi_log_warn("Error parsing ServiceResolver::Free message");
1723 async_service_resolver_free(i);
1724 return respond_ok(c, m);
1727 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1730 if (dbus_error_is_set(&error))
1731 dbus_error_free(&error);
1733 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1736 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1739 dbus_error_init(&error);
1741 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1742 dbus_message_get_interface(m),
1743 dbus_message_get_path(m),
1744 dbus_message_get_member(m));
1746 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1747 return handle_introspect(c, m, "Server.introspect");
1749 else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1751 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1752 avahi_log_warn("Error parsing Server::GetHostName message");
1756 return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1758 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1760 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1761 avahi_log_warn("Error parsing Server::GetDomainName message");
1765 return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1767 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1769 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1770 avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1774 return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1776 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1778 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1779 avahi_log_warn("Error parsing Server::GetVersionString message");
1783 return respond_string(c, m, PACKAGE_STRING);
1785 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1786 AvahiServerState state;
1788 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1789 avahi_log_warn("Error parsing Server::GetState message");
1793 state = avahi_server_get_state(avahi_server);
1794 return respond_int32(c, m, (int32_t) state);
1796 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetLocalServiceCookie")) {
1798 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1799 avahi_log_warn("Error parsing Server::GetLocalServiceCookie message");
1803 return respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server));
1805 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1808 char name[IF_NAMESIZE];
1811 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1812 avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1816 #ifdef VALGRIND_WORKAROUND
1817 return respond_string(c, m, "blah");
1820 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1821 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1823 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1824 return respond_error(c, m, AVAHI_ERR_OS, txt);
1827 if ((!if_indextoname(idx, name))) {
1829 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1831 return respond_error(c, m, AVAHI_ERR_OS, txt);
1836 return respond_string(c, m, name);
1839 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1844 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1845 avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1849 #ifdef VALGRIND_WORKAROUND
1850 return respond_int32(c, m, 1);
1852 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1853 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1855 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1856 return respond_error(c, m, AVAHI_ERR_OS, txt);
1859 if (!(idx = if_nametoindex(n))) {
1861 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1863 return respond_error(c, m, AVAHI_ERR_OS, txt);
1868 return respond_int32(c, m, idx);
1871 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1874 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1875 avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1879 t = avahi_alternative_host_name(n);
1880 respond_string(c, m, t);
1883 return DBUS_HANDLER_RESULT_HANDLED;
1885 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1888 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1889 avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1893 t = avahi_alternative_service_name(n);
1894 respond_string(c, m, t);
1897 return DBUS_HANDLER_RESULT_HANDLED;
1899 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1902 static const DBusObjectPathVTable vtable = {
1904 msg_entry_group_impl,
1911 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1912 avahi_log_warn("Error parsing Server::EntryGroupNew message");
1916 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1917 avahi_log_warn("Too many clients, client request failed.");
1918 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1921 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1922 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1923 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1926 i = avahi_new(EntryGroupInfo, 1);
1927 i->id = ++client->current_id;
1929 i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1931 AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1932 client->n_objects++;
1934 if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1935 entry_group_free(i);
1936 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1939 dbus_connection_register_object_path(c, i->path, &vtable, i);
1940 return respond_path(c, m, i->path);
1942 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1944 int32_t interface, protocol, aprotocol;
1947 SyncHostNameResolverInfo *i;
1949 if (!dbus_message_get_args(
1951 DBUS_TYPE_INT32, &interface,
1952 DBUS_TYPE_INT32, &protocol,
1953 DBUS_TYPE_STRING, &name,
1954 DBUS_TYPE_INT32, &aprotocol,
1955 DBUS_TYPE_UINT32, &flags,
1956 DBUS_TYPE_INVALID) || !name) {
1957 avahi_log_warn("Error parsing Server::ResolveHostName message");
1961 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1962 avahi_log_warn("Too many clients, client request failed.");
1963 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1966 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1967 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1968 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1971 i = avahi_new(SyncHostNameResolverInfo, 1);
1973 i->message = dbus_message_ref(m);
1974 AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i);
1975 client->n_objects++;
1977 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))) {
1978 sync_host_name_resolver_free(i);
1979 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1982 return DBUS_HANDLER_RESULT_HANDLED;
1984 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1986 int32_t interface, protocol;
1989 SyncAddressResolverInfo *i;
1992 if (!dbus_message_get_args(
1994 DBUS_TYPE_INT32, &interface,
1995 DBUS_TYPE_INT32, &protocol,
1996 DBUS_TYPE_STRING, &address,
1997 DBUS_TYPE_UINT32, &flags,
1998 DBUS_TYPE_INVALID) || !address) {
1999 avahi_log_warn("Error parsing Server::ResolveAddress message");
2003 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
2004 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
2006 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2007 avahi_log_warn("Too many clients, client request failed.");
2008 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2011 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2012 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2013 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2016 i = avahi_new(SyncAddressResolverInfo, 1);
2018 i->message = dbus_message_ref(m);
2019 AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i);
2020 client->n_objects++;
2022 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, sync_address_resolver_callback, i))) {
2023 sync_address_resolver_free(i);
2024 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2027 return DBUS_HANDLER_RESULT_HANDLED;
2029 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
2031 DomainBrowserInfo *i;
2032 static const DBusObjectPathVTable vtable = {
2034 msg_domain_browser_impl,
2040 int32_t interface, protocol, type;
2044 if (!dbus_message_get_args(
2046 DBUS_TYPE_INT32, &interface,
2047 DBUS_TYPE_INT32, &protocol,
2048 DBUS_TYPE_STRING, &domain,
2049 DBUS_TYPE_INT32, &type,
2050 DBUS_TYPE_UINT32, &flags,
2051 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
2052 avahi_log_warn("Error parsing Server::DomainBrowserNew message");
2056 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2057 avahi_log_warn("Too many clients, client request failed.");
2058 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2061 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2062 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2063 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2069 i = avahi_new(DomainBrowserInfo, 1);
2070 i->id = ++client->current_id;
2072 i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
2073 AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
2074 client->n_objects++;
2076 if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, (AvahiLookupFlags) flags, domain_browser_callback, i))) {
2077 domain_browser_free(i);
2078 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2081 dbus_connection_register_object_path(c, i->path, &vtable, i);
2082 return respond_path(c, m, i->path);
2084 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
2086 ServiceTypeBrowserInfo *i;
2087 static const DBusObjectPathVTable vtable = {
2089 msg_service_type_browser_impl,
2095 int32_t interface, protocol;
2099 if (!dbus_message_get_args(
2101 DBUS_TYPE_INT32, &interface,
2102 DBUS_TYPE_INT32, &protocol,
2103 DBUS_TYPE_STRING, &domain,
2104 DBUS_TYPE_UINT32, &flags,
2105 DBUS_TYPE_INVALID)) {
2106 avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
2110 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2111 avahi_log_warn("Too many clients, client request failed.");
2112 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2116 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2117 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2118 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2124 i = avahi_new(ServiceTypeBrowserInfo, 1);
2125 i->id = ++client->current_id;
2127 i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
2128 AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
2129 client->n_objects++;
2131 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))) {
2132 service_type_browser_free(i);
2133 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2136 dbus_connection_register_object_path(c, i->path, &vtable, i);
2137 return respond_path(c, m, i->path);
2139 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
2141 ServiceBrowserInfo *i;
2142 static const DBusObjectPathVTable vtable = {
2144 msg_service_browser_impl,
2150 int32_t interface, protocol;
2152 char *domain, *type;
2154 if (!dbus_message_get_args(
2156 DBUS_TYPE_INT32, &interface,
2157 DBUS_TYPE_INT32, &protocol,
2158 DBUS_TYPE_STRING, &type,
2159 DBUS_TYPE_STRING, &domain,
2160 DBUS_TYPE_UINT32, &flags,
2161 DBUS_TYPE_INVALID) || !type) {
2162 avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
2166 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2167 avahi_log_warn("Too many clients, client request failed.");
2168 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2172 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2173 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2174 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2180 i = avahi_new(ServiceBrowserInfo, 1);
2181 i->id = ++client->current_id;
2183 i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
2184 AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
2185 client->n_objects++;
2187 if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, (AvahiLookupFlags) flags, service_browser_callback, i))) {
2188 service_browser_free(i);
2189 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2192 dbus_connection_register_object_path(c, i->path, &vtable, i);
2193 return respond_path(c, m, i->path);
2195 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
2197 int32_t interface, protocol, aprotocol;
2199 char *name, *type, *domain;
2200 SyncServiceResolverInfo *i;
2202 if (!dbus_message_get_args(
2204 DBUS_TYPE_INT32, &interface,
2205 DBUS_TYPE_INT32, &protocol,
2206 DBUS_TYPE_STRING, &name,
2207 DBUS_TYPE_STRING, &type,
2208 DBUS_TYPE_STRING, &domain,
2209 DBUS_TYPE_INT32, &aprotocol,
2210 DBUS_TYPE_UINT32, &flags,
2211 DBUS_TYPE_INVALID) || !type) {
2212 avahi_log_warn("Error parsing Server::ResolveService message");
2216 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2217 avahi_log_warn("Too many clients, client request failed.");
2218 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2221 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2222 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2223 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2232 i = avahi_new(SyncServiceResolverInfo, 1);
2234 i->message = dbus_message_ref(m);
2235 AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i);
2236 client->n_objects++;
2238 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))) {
2239 sync_service_resolver_free(i);
2240 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2243 return DBUS_HANDLER_RESULT_HANDLED;
2245 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) {
2247 int32_t interface, protocol, aprotocol;
2249 char *name, *type, *domain;
2250 AsyncServiceResolverInfo *i;
2251 static const DBusObjectPathVTable vtable = {
2253 msg_async_service_resolver_impl,
2260 if (!dbus_message_get_args(
2262 DBUS_TYPE_INT32, &interface,
2263 DBUS_TYPE_INT32, &protocol,
2264 DBUS_TYPE_STRING, &name,
2265 DBUS_TYPE_STRING, &type,
2266 DBUS_TYPE_STRING, &domain,
2267 DBUS_TYPE_INT32, &aprotocol,
2268 DBUS_TYPE_UINT32, &flags,
2269 DBUS_TYPE_INVALID) || !type) {
2270 avahi_log_warn("Error parsing Server::ServiceResolverNew message");
2274 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2275 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2276 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2279 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2280 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2281 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2290 i = avahi_new(AsyncServiceResolverInfo, 1);
2291 i->id = ++client->current_id;
2293 i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
2294 AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i);
2295 client->n_objects++;
2297 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))) {
2298 async_service_resolver_free(i);
2299 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2302 /* avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */
2304 dbus_connection_register_object_path(c, i->path, &vtable, i);
2305 return respond_path(c, m, i->path);
2307 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew")) {
2309 int32_t interface, protocol, aprotocol;
2312 AsyncHostNameResolverInfo *i;
2313 static const DBusObjectPathVTable vtable = {
2315 msg_async_host_name_resolver_impl,
2322 if (!dbus_message_get_args(
2324 DBUS_TYPE_INT32, &interface,
2325 DBUS_TYPE_INT32, &protocol,
2326 DBUS_TYPE_STRING, &name,
2327 DBUS_TYPE_INT32, &aprotocol,
2328 DBUS_TYPE_UINT32, &flags,
2329 DBUS_TYPE_INVALID) || !name) {
2330 avahi_log_warn("Error parsing Server::HostNameResolverNew message");
2334 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2335 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2336 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2339 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2340 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2341 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2344 i = avahi_new(AsyncHostNameResolverInfo, 1);
2345 i->id = ++client->current_id;
2347 i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
2348 AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i);
2349 client->n_objects++;
2351 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))) {
2352 async_host_name_resolver_free(i);
2353 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2356 dbus_connection_register_object_path(c, i->path, &vtable, i);
2357 return respond_path(c, m, i->path);
2359 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew")) {
2361 int32_t interface, protocol;
2364 AsyncAddressResolverInfo *i;
2366 static const DBusObjectPathVTable vtable = {
2368 msg_async_address_resolver_impl,
2375 if (!dbus_message_get_args(
2377 DBUS_TYPE_INT32, &interface,
2378 DBUS_TYPE_INT32, &protocol,
2379 DBUS_TYPE_STRING, &address,
2380 DBUS_TYPE_UINT32, &flags,
2381 DBUS_TYPE_INVALID) || !address) {
2382 avahi_log_warn("Error parsing Server::AddressResolverNew message");
2386 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
2387 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
2389 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2390 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2391 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2394 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2395 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2396 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2399 i = avahi_new(AsyncAddressResolverInfo, 1);
2400 i->id = ++client->current_id;
2402 i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
2403 AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i);
2404 client->n_objects++;
2406 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, async_address_resolver_callback, i))) {
2407 async_address_resolver_free(i);
2408 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2411 dbus_connection_register_object_path(c, i->path, &vtable, i);
2412 return respond_path(c, m, i->path);
2415 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
2418 if (dbus_error_is_set(&error))
2419 dbus_error_free(&error);
2421 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2424 void dbus_protocol_server_state_changed(AvahiServerState state) {
2432 m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
2433 t = (int32_t) state;
2435 if (state == AVAHI_SERVER_COLLISION)
2436 e = AVAHI_DBUS_ERR_COLLISION;
2437 else if (state == AVAHI_SERVER_FAILURE)
2438 e = avahi_error_number_to_dbus(avahi_server_errno(avahi_server));
2440 e = AVAHI_DBUS_ERR_OK;
2442 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
2443 dbus_connection_send(server->bus, m, NULL);
2444 dbus_message_unref(m);
2447 int dbus_protocol_setup(const AvahiPoll *poll_api) {
2450 static const DBusObjectPathVTable server_vtable = {
2459 dbus_error_init(&error);
2461 server = avahi_new(Server, 1);
2462 AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
2463 server->current_id = 0;
2464 server->n_clients = 0;
2466 if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
2467 assert(dbus_error_is_set(&error));
2468 avahi_log_error("dbus_bus_get(): %s", error.message);
2472 if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) {
2473 avahi_log_error("avahi_dbus_connection_glue() failed");
2477 if (dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
2478 if (dbus_error_is_set(&error)) {
2479 avahi_log_error("dbus_bus_request_name(): %s", error.message);
2483 avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'");
2487 if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) {
2488 avahi_log_error("dbus_connection_add_filter() failed");
2492 dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
2494 if (dbus_error_is_set(&error)) {
2495 avahi_log_error("dbus_bus_add_match(): %s", error.message);
2499 if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
2500 avahi_log_error("dbus_connection_register_object_path() failed");
2508 dbus_connection_disconnect(server->bus);
2509 dbus_connection_unref(server->bus);
2512 if (dbus_error_is_set(&error))
2513 dbus_error_free(&error);
2520 void dbus_protocol_shutdown(void) {
2524 while (server->clients)
2525 client_free(server->clients);
2527 assert(server->n_clients == 0);
2530 dbus_connection_disconnect(server->bus);
2531 dbus_connection_unref(server->bus);