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 <netinet/in.h>
39 #include <dbus/dbus.h>
41 #include <avahi-common/dbus.h>
42 #include <avahi-common/llist.h>
43 #include <avahi-common/malloc.h>
44 #include <avahi-common/dbus.h>
45 #include <avahi-common/dbus-watch-glue.h>
46 #include <avahi-common/alternative.h>
47 #include <avahi-common/error.h>
49 #include <avahi-core/log.h>
50 #include <avahi-core/core.h>
51 #include <avahi-core/lookup.h>
52 #include <avahi-core/publish.h>
54 #include "dbus-protocol.h"
57 typedef struct Server Server;
58 typedef struct Client Client;
59 typedef struct EntryGroupInfo EntryGroupInfo;
60 typedef struct SyncHostNameResolverInfo SyncHostNameResolverInfo;
61 typedef struct AsyncHostNameResolverInfo AsyncHostNameResolverInfo;
62 typedef struct SyncAddressResolverInfo SyncAddressResolverInfo;
63 typedef struct AsyncAddressResolverInfo AsyncAddressResolverInfo;
64 typedef struct DomainBrowserInfo DomainBrowserInfo;
65 typedef struct ServiceTypeBrowserInfo ServiceTypeBrowserInfo;
66 typedef struct ServiceBrowserInfo ServiceBrowserInfo;
67 typedef struct SyncServiceResolverInfo SyncServiceResolverInfo;
68 typedef struct AsyncServiceResolverInfo AsyncServiceResolverInfo;
70 #define MAX_CLIENTS 20
71 #define MAX_OBJECTS_PER_CLIENT 50
72 #define MAX_ENTRIES_PER_ENTRY_GROUP 20
74 /* #define VALGRIND_WORKAROUND 1 */
76 struct EntryGroupInfo {
79 AvahiSEntryGroup *entry_group;
84 AVAHI_LLIST_FIELDS(EntryGroupInfo, entry_groups);
87 struct SyncHostNameResolverInfo {
89 AvahiSHostNameResolver *host_name_resolver;
92 AVAHI_LLIST_FIELDS(SyncHostNameResolverInfo, sync_host_name_resolvers);
95 struct AsyncHostNameResolverInfo {
98 AvahiSHostNameResolver *host_name_resolver;
101 AVAHI_LLIST_FIELDS(AsyncHostNameResolverInfo, async_host_name_resolvers);
104 struct SyncAddressResolverInfo {
106 AvahiSAddressResolver *address_resolver;
107 DBusMessage *message;
109 AVAHI_LLIST_FIELDS(SyncAddressResolverInfo, sync_address_resolvers);
112 struct AsyncAddressResolverInfo {
115 AvahiSAddressResolver *address_resolver;
118 AVAHI_LLIST_FIELDS(AsyncAddressResolverInfo, async_address_resolvers);
121 struct DomainBrowserInfo {
124 AvahiSDomainBrowser *domain_browser;
127 AVAHI_LLIST_FIELDS(DomainBrowserInfo, domain_browsers);
130 struct ServiceTypeBrowserInfo {
133 AvahiSServiceTypeBrowser *service_type_browser;
136 AVAHI_LLIST_FIELDS(ServiceTypeBrowserInfo, service_type_browsers);
139 struct ServiceBrowserInfo {
142 AvahiSServiceBrowser *service_browser;
145 AVAHI_LLIST_FIELDS(ServiceBrowserInfo, service_browsers);
148 struct SyncServiceResolverInfo {
150 AvahiSServiceResolver *service_resolver;
151 DBusMessage *message;
153 AVAHI_LLIST_FIELDS(SyncServiceResolverInfo, sync_service_resolvers);
156 struct AsyncServiceResolverInfo {
159 AvahiSServiceResolver *service_resolver;
162 AVAHI_LLIST_FIELDS(AsyncServiceResolverInfo, async_service_resolvers);
171 AVAHI_LLIST_FIELDS(Client, clients);
172 AVAHI_LLIST_HEAD(EntryGroupInfo, entry_groups);
173 AVAHI_LLIST_HEAD(SyncHostNameResolverInfo, sync_host_name_resolvers);
174 AVAHI_LLIST_HEAD(AsyncHostNameResolverInfo, async_host_name_resolvers);
175 AVAHI_LLIST_HEAD(SyncAddressResolverInfo, sync_address_resolvers);
176 AVAHI_LLIST_HEAD(AsyncAddressResolverInfo, async_address_resolvers);
177 AVAHI_LLIST_HEAD(DomainBrowserInfo, domain_browsers);
178 AVAHI_LLIST_HEAD(ServiceTypeBrowserInfo, service_type_browsers);
179 AVAHI_LLIST_HEAD(ServiceBrowserInfo, service_browsers);
180 AVAHI_LLIST_HEAD(SyncServiceResolverInfo, sync_service_resolvers);
181 AVAHI_LLIST_HEAD(AsyncServiceResolverInfo, async_service_resolvers);
186 AVAHI_LLIST_HEAD(Client, clients);
191 static Server *server = NULL;
193 static void entry_group_free(EntryGroupInfo *i) {
197 avahi_s_entry_group_free(i->entry_group);
198 dbus_connection_unregister_object_path(server->bus, i->path);
200 AVAHI_LLIST_REMOVE(EntryGroupInfo, entry_groups, i->client->entry_groups, i);
202 i->client->n_objects--;
203 assert(i->client->n_objects >= 0);
208 static void sync_host_name_resolver_free(SyncHostNameResolverInfo *i) {
211 if (i->host_name_resolver)
212 avahi_s_host_name_resolver_free(i->host_name_resolver);
213 dbus_message_unref(i->message);
214 AVAHI_LLIST_REMOVE(SyncHostNameResolverInfo, sync_host_name_resolvers, i->client->sync_host_name_resolvers, i);
216 i->client->n_objects--;
217 assert(i->client->n_objects >= 0);
222 static void async_host_name_resolver_free(AsyncHostNameResolverInfo *i) {
225 if (i->host_name_resolver)
226 avahi_s_host_name_resolver_free(i->host_name_resolver);
227 dbus_connection_unregister_object_path(server->bus, i->path);
228 AVAHI_LLIST_REMOVE(AsyncHostNameResolverInfo, async_host_name_resolvers, i->client->async_host_name_resolvers, i);
230 i->client->n_objects--;
231 assert(i->client->n_objects >= 0);
236 static void sync_address_resolver_free(SyncAddressResolverInfo *i) {
239 if (i->address_resolver)
240 avahi_s_address_resolver_free(i->address_resolver);
241 dbus_message_unref(i->message);
242 AVAHI_LLIST_REMOVE(SyncAddressResolverInfo, sync_address_resolvers, i->client->sync_address_resolvers, i);
244 i->client->n_objects--;
245 assert(i->client->n_objects >= 0);
250 static void async_address_resolver_free(AsyncAddressResolverInfo *i) {
253 if (i->address_resolver)
254 avahi_s_address_resolver_free(i->address_resolver);
255 dbus_connection_unregister_object_path(server->bus, i->path);
256 AVAHI_LLIST_REMOVE(AsyncAddressResolverInfo, async_address_resolvers, i->client->async_address_resolvers, i);
258 i->client->n_objects--;
259 assert(i->client->n_objects >= 0);
264 static void domain_browser_free(DomainBrowserInfo *i) {
267 if (i->domain_browser)
268 avahi_s_domain_browser_free(i->domain_browser);
269 dbus_connection_unregister_object_path(server->bus, i->path);
271 AVAHI_LLIST_REMOVE(DomainBrowserInfo, domain_browsers, i->client->domain_browsers, i);
273 i->client->n_objects--;
274 assert(i->client->n_objects >= 0);
279 static void service_type_browser_free(ServiceTypeBrowserInfo *i) {
282 if (i->service_type_browser)
283 avahi_s_service_type_browser_free(i->service_type_browser);
284 dbus_connection_unregister_object_path(server->bus, i->path);
286 AVAHI_LLIST_REMOVE(ServiceTypeBrowserInfo, service_type_browsers, i->client->service_type_browsers, i);
288 i->client->n_objects--;
289 assert(i->client->n_objects >= 0);
294 static void service_browser_free(ServiceBrowserInfo *i) {
297 if (i->service_browser)
298 avahi_s_service_browser_free(i->service_browser);
299 dbus_connection_unregister_object_path(server->bus, i->path);
301 AVAHI_LLIST_REMOVE(ServiceBrowserInfo, service_browsers, i->client->service_browsers, i);
303 i->client->n_objects--;
304 assert(i->client->n_objects >= 0);
309 static void sync_service_resolver_free(SyncServiceResolverInfo *i) {
312 if (i->service_resolver)
313 avahi_s_service_resolver_free(i->service_resolver);
314 dbus_message_unref(i->message);
315 AVAHI_LLIST_REMOVE(SyncServiceResolverInfo, sync_service_resolvers, i->client->sync_service_resolvers, i);
317 i->client->n_objects--;
318 assert(i->client->n_objects >= 0);
323 static void async_service_resolver_free(AsyncServiceResolverInfo *i) {
326 if (i->service_resolver)
327 avahi_s_service_resolver_free(i->service_resolver);
329 dbus_connection_unregister_object_path(server->bus, i->path);
330 AVAHI_LLIST_REMOVE(AsyncServiceResolverInfo, async_service_resolvers, i->client->async_service_resolvers, i);
332 i->client->n_objects--;
333 assert(i->client->n_objects >= 0);
338 static void client_free(Client *c) {
343 while (c->entry_groups)
344 entry_group_free(c->entry_groups);
346 while (c->sync_host_name_resolvers)
347 sync_host_name_resolver_free(c->sync_host_name_resolvers);
349 while (c->async_host_name_resolvers)
350 async_host_name_resolver_free(c->async_host_name_resolvers);
352 while (c->sync_address_resolvers)
353 sync_address_resolver_free(c->sync_address_resolvers);
355 while (c->async_address_resolvers)
356 async_address_resolver_free(c->async_address_resolvers);
358 while (c->domain_browsers)
359 domain_browser_free(c->domain_browsers);
361 while (c->service_type_browsers)
362 service_type_browser_free(c->service_type_browsers);
364 while (c->service_browsers)
365 service_browser_free(c->service_browsers);
367 while (c->sync_service_resolvers)
368 sync_service_resolver_free(c->sync_service_resolvers);
370 while (c->async_service_resolvers)
371 async_service_resolver_free(c->async_service_resolvers);
373 assert(c->n_objects == 0);
376 AVAHI_LLIST_REMOVE(Client, clients, server->clients, c);
379 server->n_clients --;
380 assert(server->n_clients >= 0);
383 static Client *client_get(const char *name, int create) {
389 for (client = server->clients; client; client = client->clients_next)
390 if (!strcmp(name, client->name))
396 if (server->n_clients >= MAX_CLIENTS)
399 /* If not existant yet, create a new entry */
400 client = avahi_new(Client, 1);
401 client->id = server->current_id++;
402 client->name = avahi_strdup(name);
403 client->current_id = 0;
404 client->n_objects = 0;
406 AVAHI_LLIST_HEAD_INIT(EntryGroupInfo, client->entry_groups);
407 AVAHI_LLIST_HEAD_INIT(SyncHostNameResolverInfo, client->sync_host_name_resolvers);
408 AVAHI_LLIST_HEAD_INIT(AsyncHostNameResolverInfo, client->async_host_name_resolvers);
409 AVAHI_LLIST_HEAD_INIT(SyncAddressResolverInfo, client->sync_address_resolvers);
410 AVAHI_LLIST_HEAD_INIT(AsyncAddressResolverInfo, client->async_address_resolvers);
411 AVAHI_LLIST_HEAD_INIT(DomainBrowserInfo, client->domain_browsers);
412 AVAHI_LLIST_HEAD_INIT(ServiceTypeBrowserInfo, client->service_type_browsers);
413 AVAHI_LLIST_HEAD_INIT(ServiceBrowserInfo, client->service_browsers);
414 AVAHI_LLIST_HEAD_INIT(SyncServiceResolverInfo, client->sync_service_resolvers);
415 AVAHI_LLIST_HEAD_INIT(AsyncServiceResolverInfo, client->async_service_resolvers);
417 AVAHI_LLIST_PREPEND(Client, clients, server->clients, client);
420 assert(server->n_clients > 0);
425 static DBusHandlerResult respond_error(DBusConnection *c, DBusMessage *m, int error, const char *text) {
428 assert(-error > -AVAHI_OK);
429 assert(-error < -AVAHI_ERR_MAX);
432 text = avahi_strerror(error);
434 reply = dbus_message_new_error(m, avahi_error_number_to_dbus(error), text);
435 dbus_connection_send(c, reply, NULL);
436 dbus_message_unref(reply);
438 avahi_log_debug(__FILE__": Responding error '%s' (%i)", text, error);
440 return DBUS_HANDLER_RESULT_HANDLED;
443 static DBusHandlerResult respond_string(DBusConnection *c, DBusMessage *m, const char *text) {
446 reply = dbus_message_new_method_return(m);
447 dbus_message_append_args(reply, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID);
448 dbus_connection_send(c, reply, NULL);
449 dbus_message_unref(reply);
451 return DBUS_HANDLER_RESULT_HANDLED;
454 static DBusHandlerResult respond_int32(DBusConnection *c, DBusMessage *m, int32_t i) {
457 reply = dbus_message_new_method_return(m);
458 dbus_message_append_args(reply, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID);
459 dbus_connection_send(c, reply, NULL);
460 dbus_message_unref(reply);
462 return DBUS_HANDLER_RESULT_HANDLED;
465 static DBusHandlerResult respond_uint32(DBusConnection *c, DBusMessage *m, uint32_t u) {
468 reply = dbus_message_new_method_return(m);
469 dbus_message_append_args(reply, DBUS_TYPE_UINT32, &u, DBUS_TYPE_INVALID);
470 dbus_connection_send(c, reply, NULL);
471 dbus_message_unref(reply);
473 return DBUS_HANDLER_RESULT_HANDLED;
476 static DBusHandlerResult respond_boolean(DBusConnection *c, DBusMessage *m, int b) {
479 reply = dbus_message_new_method_return(m);
480 dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
481 dbus_connection_send(c, reply, NULL);
482 dbus_message_unref(reply);
484 return DBUS_HANDLER_RESULT_HANDLED;
487 static DBusHandlerResult respond_ok(DBusConnection *c, DBusMessage *m) {
490 reply = dbus_message_new_method_return(m);
491 dbus_connection_send(c, reply, NULL);
492 dbus_message_unref(reply);
494 return DBUS_HANDLER_RESULT_HANDLED;
497 static DBusHandlerResult respond_path(DBusConnection *c, DBusMessage *m, const char *path) {
500 reply = dbus_message_new_method_return(m);
501 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
502 dbus_connection_send(c, reply, NULL);
503 dbus_message_unref(reply);
505 return DBUS_HANDLER_RESULT_HANDLED;
508 static void append_server_error(DBusMessage *reply) {
511 t = avahi_error_number_to_dbus(avahi_server_errno(avahi_server));
513 dbus_message_append_args(
515 DBUS_TYPE_STRING, &t,
519 static char *file_get_contents(char *fname) {
527 if (!(fd = open(fname, O_RDONLY))) {
528 avahi_log_error("Failed to open %s: %s", fname, strerror(errno));
532 if (fstat(fd, &st) < 0) {
533 avahi_log_error("stat(%s) failed: %s", fname, strerror(errno));
537 if (!(S_ISREG(st.st_mode))) {
538 avahi_log_error("Invalid file %s", fname);
542 if (st.st_size > 1024*1024) { /** 1MB */
543 avahi_log_error("File too large %s", fname);
547 buf = avahi_new(char, st.st_size+1);
549 if ((size = read(fd, buf, st.st_size)) < 0) {
550 avahi_log_error("read() failed: %s\n", strerror(errno));
570 static const char *map_browse_signal_name(AvahiBrowserEvent e) {
572 case AVAHI_BROWSER_NEW : return "ItemNew";
573 case AVAHI_BROWSER_REMOVE : return "ItemRemove";
574 case AVAHI_BROWSER_FAILURE : return "Failure";
575 case AVAHI_BROWSER_CACHE_EXHAUSTED : return "CacheExhausted";
576 case AVAHI_BROWSER_ALL_FOR_NOW : return "AllForNow";
582 static const char *map_resolve_signal_name(AvahiResolverEvent e) {
584 case AVAHI_RESOLVER_FOUND : return "Found";
585 case AVAHI_RESOLVER_FAILURE : return "Failure";
592 static DBusHandlerResult handle_introspect(DBusConnection *c, DBusMessage *m, const char *fname) {
593 char *path, *contents;
600 dbus_error_init(&error);
602 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
603 avahi_log_error("Error parsing Introspect message: %s", error.message);
607 path = avahi_strdup_printf("%s/%s", AVAHI_DBUS_INTROSPECTION_DIR, fname);
608 contents = file_get_contents(path);
612 avahi_log_error("Failed to load introspection data.");
616 respond_string(c, m, contents);
617 avahi_free(contents);
619 return DBUS_HANDLER_RESULT_HANDLED;
622 if (dbus_error_is_set(&error))
623 dbus_error_free(&error);
625 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
629 static DBusHandlerResult msg_signal_filter_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
632 dbus_error_init(&error);
634 /* avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s", */
635 /* dbus_message_get_interface(m), */
636 /* dbus_message_get_path(m), */
637 /* dbus_message_get_member(m)); */
639 if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
640 /* No, we shouldn't quit, but until we get somewhere
641 * usefull such that we can restore our state, we will */
642 avahi_log_warn("Disconnnected from D-BUS, terminating...");
644 raise(SIGQUIT); /* The signal handler will catch this and terminate the process cleanly*/
646 return DBUS_HANDLER_RESULT_HANDLED;
648 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) {
651 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
652 avahi_log_warn("Error parsing NameAcquired message");
656 /* avahi_log_info(__FILE__": name acquired (%s)", name); */
657 return DBUS_HANDLER_RESULT_HANDLED;
659 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
660 char *name, *old, *new;
662 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) {
663 avahi_log_warn("Error parsing NameOwnerChanged message");
670 if ((client = client_get(name, FALSE))) {
671 avahi_log_debug(__FILE__": client %s vanished.", name);
678 if (dbus_error_is_set(&error))
679 dbus_error_free(&error);
681 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
684 static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntryGroupState state, void* userdata) {
685 EntryGroupInfo *i = userdata;
693 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged");
695 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
696 dbus_message_set_destination(m, i->client->name);
697 dbus_connection_send(server->bus, m, NULL);
698 dbus_message_unref(m);
701 static int read_strlst(DBusMessage *m, int idx, AvahiStringList **l) {
702 DBusMessageIter iter, sub;
704 AvahiStringList *strlst = NULL;
709 dbus_message_iter_init(m, &iter);
711 for (j = 0; j < idx; j++)
712 dbus_message_iter_next(&iter);
714 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
715 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY)
718 dbus_message_iter_recurse(&iter, &sub);
721 DBusMessageIter sub2;
725 if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
728 assert(at == DBUS_TYPE_ARRAY);
730 if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE)
733 dbus_message_iter_recurse(&sub, &sub2);
734 dbus_message_iter_get_fixed_array(&sub2, &k, &n);
735 strlst = avahi_string_list_add_arbitrary(strlst, k, n);
737 dbus_message_iter_next(&sub);
745 avahi_log_warn("Error parsing TXT data");
747 avahi_string_list_free(strlst);
753 static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
755 EntryGroupInfo *i = userdata;
761 dbus_error_init(&error);
763 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
764 dbus_message_get_interface(m),
765 dbus_message_get_path(m),
766 dbus_message_get_member(m));
769 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
770 return handle_introspect(c, m, "EntryGroup.introspect");
773 if (strcmp(dbus_message_get_sender(m), i->client->name))
774 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
776 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) {
778 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
779 avahi_log_warn("Error parsing EntryGroup::Free message");
784 return respond_ok(c, m);
786 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Commit")) {
788 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
789 avahi_log_warn("Error parsing EntryGroup::Commit message");
793 avahi_s_entry_group_commit(i->entry_group);
794 return respond_ok(c, m);
797 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Reset")) {
799 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
800 avahi_log_warn("Error parsing EntryGroup::Reset message");
804 avahi_s_entry_group_reset(i->entry_group);
806 return respond_ok(c, m);
808 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) {
810 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
811 avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
815 return respond_boolean(c, m, !!avahi_s_entry_group_is_empty(i->entry_group));
817 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
818 AvahiEntryGroupState state;
820 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
821 avahi_log_warn("Error parsing EntryGroup::GetState message");
825 state = avahi_s_entry_group_get_state(i->entry_group);
826 return respond_int32(c, m, (int32_t) state);
828 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
829 int32_t interface, protocol;
831 char *type, *name, *domain, *host;
833 AvahiStringList *strlst = NULL;
835 if (!dbus_message_get_args(
837 DBUS_TYPE_INT32, &interface,
838 DBUS_TYPE_INT32, &protocol,
839 DBUS_TYPE_UINT32, &flags,
840 DBUS_TYPE_STRING, &name,
841 DBUS_TYPE_STRING, &type,
842 DBUS_TYPE_STRING, &domain,
843 DBUS_TYPE_STRING, &host,
844 DBUS_TYPE_UINT16, &port,
845 DBUS_TYPE_INVALID) ||
847 read_strlst(m, 8, &strlst) < 0) {
848 avahi_log_warn("Error parsing EntryGroup::AddService message");
852 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
853 avahi_string_list_free(strlst);
854 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
857 if (domain && !*domain)
863 if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, host, port, strlst) < 0) {
864 avahi_string_list_free(strlst);
865 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
868 if (!(flags & AVAHI_PUBLISH_UPDATE))
871 avahi_string_list_free(strlst);
873 return respond_ok(c, m);
875 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddServiceSubtype")) {
877 int32_t interface, protocol;
879 char *type, *name, *domain, *subtype;
881 if (!dbus_message_get_args(
883 DBUS_TYPE_INT32, &interface,
884 DBUS_TYPE_INT32, &protocol,
885 DBUS_TYPE_UINT32, &flags,
886 DBUS_TYPE_STRING, &name,
887 DBUS_TYPE_STRING, &type,
888 DBUS_TYPE_STRING, &domain,
889 DBUS_TYPE_STRING, &subtype,
890 DBUS_TYPE_INVALID) || !type || !name || !subtype) {
891 avahi_log_warn("Error parsing EntryGroup::AddServiceSubtype message");
895 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP)
896 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
898 if (domain && !*domain)
901 if (avahi_server_add_service_subtype(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, subtype) < 0)
902 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
904 if (!(flags & AVAHI_PUBLISH_UPDATE))
907 return respond_ok(c, m);
909 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "UpdateServiceTxt")) {
910 int32_t interface, protocol;
912 char *type, *name, *domain;
913 AvahiStringList *strlst;
915 if (!dbus_message_get_args(
917 DBUS_TYPE_INT32, &interface,
918 DBUS_TYPE_INT32, &protocol,
919 DBUS_TYPE_UINT32, &flags,
920 DBUS_TYPE_STRING, &name,
921 DBUS_TYPE_STRING, &type,
922 DBUS_TYPE_STRING, &domain,
923 DBUS_TYPE_INVALID) ||
925 read_strlst(m, 6, &strlst)) {
926 avahi_log_warn("Error parsing EntryGroup::UpdateServiceTxt message");
930 if (domain && !*domain)
933 if (avahi_server_update_service_txt_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, strlst) < 0) {
934 avahi_string_list_free(strlst);
935 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
938 avahi_string_list_free(strlst);
940 return respond_ok(c, m);
942 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
943 int32_t interface, protocol;
945 char *name, *address;
948 if (!dbus_message_get_args(
950 DBUS_TYPE_INT32, &interface,
951 DBUS_TYPE_INT32, &protocol,
952 DBUS_TYPE_UINT32, &flags,
953 DBUS_TYPE_STRING, &name,
954 DBUS_TYPE_STRING, &address,
955 DBUS_TYPE_INVALID) || !name || !address) {
956 avahi_log_warn("Error parsing EntryGroup::AddAddress message");
960 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP)
961 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
963 if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a)))
964 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
966 if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, &a) < 0)
967 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
969 if (!(flags & AVAHI_PUBLISH_UPDATE))
972 return respond_ok(c, m);
975 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
978 if (dbus_error_is_set(&error))
979 dbus_error_free(&error);
981 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
984 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) {
985 SyncHostNameResolverInfo *i = userdata;
991 if (event == AVAHI_RESOLVER_FOUND) {
992 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
993 int32_t i_interface, i_protocol, i_aprotocol;
998 avahi_address_snprint(t, sizeof(t), a);
1000 i_interface = (int32_t) interface;
1001 i_protocol = (int32_t) protocol;
1002 i_aprotocol = (int32_t) a->proto;
1003 u_flags = (uint32_t) flags;
1005 reply = dbus_message_new_method_return(i->message);
1006 dbus_message_append_args(
1008 DBUS_TYPE_INT32, &i_interface,
1009 DBUS_TYPE_INT32, &i_protocol,
1010 DBUS_TYPE_STRING, &host_name,
1011 DBUS_TYPE_INT32, &i_aprotocol,
1012 DBUS_TYPE_STRING, &pt,
1013 DBUS_TYPE_UINT32, &u_flags,
1016 dbus_connection_send(server->bus, reply, NULL);
1017 dbus_message_unref(reply);
1019 assert(event == AVAHI_RESOLVER_FAILURE);
1020 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1023 sync_host_name_resolver_free(i);
1026 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) {
1027 SyncAddressResolverInfo *i = userdata;
1033 if (event == AVAHI_RESOLVER_FOUND) {
1034 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1035 int32_t i_interface, i_protocol, i_aprotocol;
1040 avahi_address_snprint(t, sizeof(t), address);
1042 i_interface = (int32_t) interface;
1043 i_protocol = (int32_t) protocol;
1044 i_aprotocol = (int32_t) address->proto;
1045 u_flags = (uint32_t) flags;
1047 reply = dbus_message_new_method_return(i->message);
1048 dbus_message_append_args(
1050 DBUS_TYPE_INT32, &i_interface,
1051 DBUS_TYPE_INT32, &i_protocol,
1052 DBUS_TYPE_INT32, &i_aprotocol,
1053 DBUS_TYPE_STRING, &pt,
1054 DBUS_TYPE_STRING, &host_name,
1055 DBUS_TYPE_UINT32, &u_flags,
1058 dbus_connection_send(server->bus, reply, NULL);
1059 dbus_message_unref(reply);
1061 assert(event == AVAHI_RESOLVER_FAILURE);
1062 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1065 sync_address_resolver_free(i);
1068 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1070 DomainBrowserInfo *i = userdata;
1076 dbus_error_init(&error);
1078 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1079 dbus_message_get_interface(m),
1080 dbus_message_get_path(m),
1081 dbus_message_get_member(m));
1084 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1085 return handle_introspect(c, m, "DomainBrowser.introspect");
1087 /* Access control */
1088 if (strcmp(dbus_message_get_sender(m), i->client->name))
1089 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1091 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
1093 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1094 avahi_log_warn("Error parsing DomainBrowser::Free message");
1098 domain_browser_free(i);
1099 return respond_ok(c, m);
1103 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1106 if (dbus_error_is_set(&error))
1107 dbus_error_free(&error);
1109 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1112 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1113 DomainBrowserInfo *i = userdata;
1115 int32_t i_interface, i_protocol;
1121 i_interface = (int32_t) interface;
1122 i_protocol = (int32_t) protocol;
1123 u_flags = (uint32_t) flags;
1125 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, map_browse_signal_name(event));
1127 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1129 dbus_message_append_args(
1131 DBUS_TYPE_INT32, &i_interface,
1132 DBUS_TYPE_INT32, &i_protocol,
1133 DBUS_TYPE_STRING, &domain,
1134 DBUS_TYPE_UINT32, &u_flags,
1136 } else if (event == AVAHI_BROWSER_FAILURE)
1137 append_server_error(m);
1139 dbus_message_set_destination(m, i->client->name);
1140 dbus_connection_send(server->bus, m, NULL);
1141 dbus_message_unref(m);
1144 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1146 ServiceTypeBrowserInfo *i = userdata;
1152 dbus_error_init(&error);
1154 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1155 dbus_message_get_interface(m),
1156 dbus_message_get_path(m),
1157 dbus_message_get_member(m));
1160 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1161 return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
1163 /* Access control */
1164 if (strcmp(dbus_message_get_sender(m), i->client->name))
1165 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1167 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
1169 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1170 avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
1174 service_type_browser_free(i);
1175 return respond_ok(c, m);
1179 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1182 if (dbus_error_is_set(&error))
1183 dbus_error_free(&error);
1185 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1188 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1189 ServiceTypeBrowserInfo *i = userdata;
1191 int32_t i_interface, i_protocol;
1197 i_interface = (int32_t) interface;
1198 i_protocol = (int32_t) protocol;
1199 u_flags = (uint32_t) flags;
1201 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, map_browse_signal_name(event));
1203 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1206 dbus_message_append_args(
1208 DBUS_TYPE_INT32, &i_interface,
1209 DBUS_TYPE_INT32, &i_protocol,
1210 DBUS_TYPE_STRING, &type,
1211 DBUS_TYPE_STRING, &domain,
1212 DBUS_TYPE_UINT32, &u_flags,
1214 } else if (event == AVAHI_BROWSER_FAILURE)
1215 append_server_error(m);
1217 dbus_message_set_destination(m, i->client->name);
1218 dbus_connection_send(server->bus, m, NULL);
1219 dbus_message_unref(m);
1222 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1224 ServiceBrowserInfo *i = userdata;
1230 dbus_error_init(&error);
1232 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1233 dbus_message_get_interface(m),
1234 dbus_message_get_path(m),
1235 dbus_message_get_member(m));
1238 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1239 return handle_introspect(c, m, "ServiceBrowser.Introspect");
1241 /* Access control */
1242 if (strcmp(dbus_message_get_sender(m), i->client->name))
1243 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1245 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
1247 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1248 avahi_log_warn("Error parsing ServiceBrowser::Free message");
1252 service_browser_free(i);
1253 return respond_ok(c, m);
1257 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1260 if (dbus_error_is_set(&error))
1261 dbus_error_free(&error);
1263 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1266 static int is_our_own_service(Client *c, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain) {
1267 AvahiSEntryGroup *g;
1270 if (avahi_server_get_group_of_service(avahi_server, interface, protocol, name, type, domain, &g) == AVAHI_OK) {
1271 EntryGroupInfo *egi;
1273 for (egi = c->entry_groups; egi; egi = egi->entry_groups_next)
1274 if (egi->entry_group == g)
1281 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) {
1282 ServiceBrowserInfo *i = userdata;
1284 int32_t i_interface, i_protocol;
1290 i_interface = (int32_t) interface;
1291 i_protocol = (int32_t) protocol;
1292 u_flags = (uint32_t) flags;
1294 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, map_browse_signal_name(event));
1296 if (event == AVAHI_BROWSER_NEW) {
1297 /* Patch in AVAHI_LOOKUP_RESULT_OUR_OWN */
1299 if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1300 flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1303 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1308 dbus_message_append_args(
1310 DBUS_TYPE_INT32, &i_interface,
1311 DBUS_TYPE_INT32, &i_protocol,
1312 DBUS_TYPE_STRING, &name,
1313 DBUS_TYPE_STRING, &type,
1314 DBUS_TYPE_STRING, &domain,
1315 DBUS_TYPE_UINT32, &u_flags,
1317 } else if (event == AVAHI_BROWSER_FAILURE)
1318 append_server_error(m);
1320 dbus_message_set_destination(m, i->client->name);
1321 dbus_connection_send(server->bus, m, NULL);
1322 dbus_message_unref(m);
1325 static void append_string_list(DBusMessage *reply, AvahiStringList *txt) {
1327 DBusMessageIter iter, sub;
1331 dbus_message_iter_init_append(reply, &iter);
1332 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1334 for (p = txt; p; p = p->next) {
1335 DBusMessageIter sub2;
1336 const uint8_t *data = p->text;
1338 dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1339 dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
1340 dbus_message_iter_close_container(&sub, &sub2);
1343 dbus_message_iter_close_container(&iter, &sub);
1346 static void sync_service_resolver_callback(
1347 AvahiSServiceResolver *r,
1348 AvahiIfIndex interface,
1349 AvahiProtocol protocol,
1350 AvahiResolverEvent event,
1354 const char *host_name,
1355 const AvahiAddress *a,
1357 AvahiStringList *txt,
1358 AvahiLookupResultFlags flags,
1361 SyncServiceResolverInfo *i = userdata;
1366 if (event == AVAHI_RESOLVER_FOUND) {
1367 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1368 int32_t i_interface, i_protocol, i_aprotocol;
1378 avahi_address_snprint(t, sizeof(t), a);
1382 /* Patch in AVAHI_LOOKUP_RESULT_OUR_OWN */
1384 if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1385 flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1387 i_interface = (int32_t) interface;
1388 i_protocol = (int32_t) protocol;
1390 i_aprotocol = (int32_t) a->proto;
1392 i_aprotocol = AVAHI_PROTO_UNSPEC;
1393 u_flags = (uint32_t) flags;
1395 reply = dbus_message_new_method_return(i->message);
1396 dbus_message_append_args(
1398 DBUS_TYPE_INT32, &i_interface,
1399 DBUS_TYPE_INT32, &i_protocol,
1400 DBUS_TYPE_STRING, &name,
1401 DBUS_TYPE_STRING, &type,
1402 DBUS_TYPE_STRING, &domain,
1403 DBUS_TYPE_STRING, &host_name,
1404 DBUS_TYPE_INT32, &i_aprotocol,
1405 DBUS_TYPE_STRING, &pt,
1406 DBUS_TYPE_UINT16, &port,
1409 append_string_list(reply, txt);
1411 dbus_message_append_args(
1413 DBUS_TYPE_UINT32, &u_flags,
1416 dbus_connection_send(server->bus, reply, NULL);
1417 dbus_message_unref(reply);
1419 assert(event == AVAHI_RESOLVER_FAILURE);
1421 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1424 sync_service_resolver_free(i);
1427 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) {
1428 AsyncAddressResolverInfo *i = userdata;
1434 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, map_resolve_signal_name(event));
1436 if (event == AVAHI_RESOLVER_FOUND) {
1437 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1438 int32_t i_interface, i_protocol, i_aprotocol;
1443 avahi_address_snprint(t, sizeof(t), address);
1445 i_interface = (int32_t) interface;
1446 i_protocol = (int32_t) protocol;
1447 i_aprotocol = (int32_t) address->proto;
1448 u_flags = (uint32_t) flags;
1450 dbus_message_append_args(
1452 DBUS_TYPE_INT32, &i_interface,
1453 DBUS_TYPE_INT32, &i_protocol,
1454 DBUS_TYPE_INT32, &i_aprotocol,
1455 DBUS_TYPE_STRING, &pt,
1456 DBUS_TYPE_STRING, &host_name,
1457 DBUS_TYPE_UINT32, &u_flags,
1461 assert(event == AVAHI_RESOLVER_FAILURE);
1462 append_server_error(reply);
1465 dbus_message_set_destination(reply, i->client->name);
1466 dbus_connection_send(server->bus, reply, NULL);
1467 dbus_message_unref(reply);
1470 static DBusHandlerResult msg_async_address_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1472 AsyncAddressResolverInfo *i = userdata;
1478 dbus_error_init(&error);
1480 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1481 dbus_message_get_interface(m),
1482 dbus_message_get_path(m),
1483 dbus_message_get_member(m));
1486 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1487 return handle_introspect(c, m, "AddressResolver.Introspect");
1489 /* Access control */
1490 if (strcmp(dbus_message_get_sender(m), i->client->name))
1491 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1493 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Free")) {
1495 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1496 avahi_log_warn("Error parsing AddressResolver::Free message");
1500 async_address_resolver_free(i);
1501 return respond_ok(c, m);
1505 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1508 if (dbus_error_is_set(&error))
1509 dbus_error_free(&error);
1511 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1514 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) {
1515 AsyncHostNameResolverInfo *i = userdata;
1521 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, map_resolve_signal_name(event));
1523 if (event == AVAHI_RESOLVER_FOUND) {
1524 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1525 int32_t i_interface, i_protocol, i_aprotocol;
1530 avahi_address_snprint(t, sizeof(t), a);
1532 i_interface = (int32_t) interface;
1533 i_protocol = (int32_t) protocol;
1534 i_aprotocol = (int32_t) a->proto;
1535 u_flags = (uint32_t) flags;
1537 dbus_message_append_args(
1539 DBUS_TYPE_INT32, &i_interface,
1540 DBUS_TYPE_INT32, &i_protocol,
1541 DBUS_TYPE_STRING, &host_name,
1542 DBUS_TYPE_INT32, &i_aprotocol,
1543 DBUS_TYPE_STRING, &pt,
1544 DBUS_TYPE_UINT32, &u_flags,
1547 assert(event == AVAHI_RESOLVER_FAILURE);
1548 append_server_error(reply);
1551 dbus_message_set_destination(reply, i->client->name);
1552 dbus_connection_send(server->bus, reply, NULL);
1553 dbus_message_unref(reply);
1556 static DBusHandlerResult msg_async_host_name_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1558 AsyncHostNameResolverInfo *i = userdata;
1564 dbus_error_init(&error);
1566 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1567 dbus_message_get_interface(m),
1568 dbus_message_get_path(m),
1569 dbus_message_get_member(m));
1572 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1573 return handle_introspect(c, m, "HostNameResolver.Introspect");
1575 /* Access control */
1576 if (strcmp(dbus_message_get_sender(m), i->client->name))
1577 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1579 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, "Free")) {
1581 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1582 avahi_log_warn("Error parsing HostNameResolver::Free message");
1586 async_host_name_resolver_free(i);
1587 return respond_ok(c, m);
1590 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1593 if (dbus_error_is_set(&error))
1594 dbus_error_free(&error);
1596 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1599 static void async_service_resolver_callback(
1600 AvahiSServiceResolver *r,
1601 AvahiIfIndex interface,
1602 AvahiProtocol protocol,
1603 AvahiResolverEvent event,
1607 const char *host_name,
1608 const AvahiAddress *a,
1610 AvahiStringList *txt,
1611 AvahiLookupResultFlags flags,
1614 AsyncServiceResolverInfo *i = userdata;
1620 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, map_resolve_signal_name(event));
1622 if (event == AVAHI_RESOLVER_FOUND) {
1623 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1624 int32_t i_interface, i_protocol, i_aprotocol;
1629 /* avahi_log_debug(__FILE__": [%s] Successfully resolved service <%s.%s.%s>", i->path, name, type, domain); */
1632 avahi_address_snprint(t, sizeof(t), a);
1639 if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1640 flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1642 i_interface = (int32_t) interface;
1643 i_protocol = (int32_t) protocol;
1645 i_aprotocol = (int32_t) a->proto;
1647 i_aprotocol = AVAHI_PROTO_UNSPEC;
1648 u_flags = (uint32_t) flags;
1650 dbus_message_append_args(
1652 DBUS_TYPE_INT32, &i_interface,
1653 DBUS_TYPE_INT32, &i_protocol,
1654 DBUS_TYPE_STRING, &name,
1655 DBUS_TYPE_STRING, &type,
1656 DBUS_TYPE_STRING, &domain,
1657 DBUS_TYPE_STRING, &host_name,
1658 DBUS_TYPE_INT32, &i_aprotocol,
1659 DBUS_TYPE_STRING, &pt,
1660 DBUS_TYPE_UINT16, &port,
1663 append_string_list(reply, txt);
1665 dbus_message_append_args(
1667 DBUS_TYPE_UINT32, &u_flags,
1670 assert(event == AVAHI_RESOLVER_FAILURE);
1671 append_server_error(reply);
1674 dbus_message_set_destination(reply, i->client->name);
1675 dbus_connection_send(server->bus, reply, NULL);
1676 dbus_message_unref(reply);
1679 static DBusHandlerResult msg_async_service_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1681 AsyncServiceResolverInfo *i = userdata;
1687 dbus_error_init(&error);
1689 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1690 dbus_message_get_interface(m),
1691 dbus_message_get_path(m),
1692 dbus_message_get_member(m));
1695 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1696 return handle_introspect(c, m, "ServiceResolver.Introspect");
1698 /* Access control */
1699 if (strcmp(dbus_message_get_sender(m), i->client->name))
1700 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1702 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, "Free")) {
1704 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1705 avahi_log_warn("Error parsing ServiceResolver::Free message");
1709 async_service_resolver_free(i);
1710 return respond_ok(c, m);
1713 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1716 if (dbus_error_is_set(&error))
1717 dbus_error_free(&error);
1719 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1722 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1725 dbus_error_init(&error);
1727 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1728 dbus_message_get_interface(m),
1729 dbus_message_get_path(m),
1730 dbus_message_get_member(m));
1732 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1733 return handle_introspect(c, m, "Server.introspect");
1735 else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1737 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1738 avahi_log_warn("Error parsing Server::GetHostName message");
1742 return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1744 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1746 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1747 avahi_log_warn("Error parsing Server::GetDomainName message");
1751 return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1753 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1755 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1756 avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1760 return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1762 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1764 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1765 avahi_log_warn("Error parsing Server::GetVersionString message");
1769 return respond_string(c, m, PACKAGE_STRING);
1771 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1772 AvahiServerState state;
1774 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1775 avahi_log_warn("Error parsing Server::GetState message");
1779 state = avahi_server_get_state(avahi_server);
1780 return respond_int32(c, m, (int32_t) state);
1782 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetLocalServiceCookie")) {
1784 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1785 avahi_log_warn("Error parsing Server::GetLocalServiceCookie message");
1789 return respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server));
1791 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1794 char name[IF_NAMESIZE];
1797 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1798 avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1802 #ifdef VALGRIND_WORKAROUND
1803 return respond_string(c, m, "blah");
1806 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1807 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1809 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1810 return respond_error(c, m, AVAHI_ERR_OS, txt);
1813 if ((!if_indextoname(idx, name))) {
1815 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1817 return respond_error(c, m, AVAHI_ERR_OS, txt);
1822 return respond_string(c, m, name);
1825 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1830 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1831 avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1835 #ifdef VALGRIND_WORKAROUND
1836 return respond_int32(c, m, 1);
1838 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1839 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1841 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1842 return respond_error(c, m, AVAHI_ERR_OS, txt);
1845 if (!(idx = if_nametoindex(n))) {
1847 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1849 return respond_error(c, m, AVAHI_ERR_OS, txt);
1854 return respond_int32(c, m, idx);
1857 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1860 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1861 avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1865 t = avahi_alternative_host_name(n);
1866 respond_string(c, m, t);
1869 return DBUS_HANDLER_RESULT_HANDLED;
1871 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1874 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1875 avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1879 t = avahi_alternative_service_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, "EntryGroupNew")) {
1888 static const DBusObjectPathVTable vtable = {
1890 msg_entry_group_impl,
1897 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1898 avahi_log_warn("Error parsing Server::EntryGroupNew message");
1902 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1903 avahi_log_warn("Too many clients, client request failed.");
1904 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1907 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1908 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1909 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1912 i = avahi_new(EntryGroupInfo, 1);
1913 i->id = ++client->current_id;
1915 i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1917 AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1918 client->n_objects++;
1920 if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1921 entry_group_free(i);
1922 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1925 dbus_connection_register_object_path(c, i->path, &vtable, i);
1926 return respond_path(c, m, i->path);
1928 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1930 int32_t interface, protocol, aprotocol;
1933 SyncHostNameResolverInfo *i;
1935 if (!dbus_message_get_args(
1937 DBUS_TYPE_INT32, &interface,
1938 DBUS_TYPE_INT32, &protocol,
1939 DBUS_TYPE_STRING, &name,
1940 DBUS_TYPE_INT32, &aprotocol,
1941 DBUS_TYPE_UINT32, &flags,
1942 DBUS_TYPE_INVALID) || !name) {
1943 avahi_log_warn("Error parsing Server::ResolveHostName message");
1947 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1948 avahi_log_warn("Too many clients, client request failed.");
1949 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1952 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1953 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1954 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1957 i = avahi_new(SyncHostNameResolverInfo, 1);
1959 i->message = dbus_message_ref(m);
1960 AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i);
1961 client->n_objects++;
1963 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))) {
1964 sync_host_name_resolver_free(i);
1965 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1968 return DBUS_HANDLER_RESULT_HANDLED;
1970 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1972 int32_t interface, protocol;
1975 SyncAddressResolverInfo *i;
1978 if (!dbus_message_get_args(
1980 DBUS_TYPE_INT32, &interface,
1981 DBUS_TYPE_INT32, &protocol,
1982 DBUS_TYPE_STRING, &address,
1983 DBUS_TYPE_UINT32, &flags,
1984 DBUS_TYPE_INVALID) || !address) {
1985 avahi_log_warn("Error parsing Server::ResolveAddress message");
1989 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
1990 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
1992 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1993 avahi_log_warn("Too many clients, client request failed.");
1994 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1997 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1998 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1999 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2002 i = avahi_new(SyncAddressResolverInfo, 1);
2004 i->message = dbus_message_ref(m);
2005 AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i);
2006 client->n_objects++;
2008 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, sync_address_resolver_callback, i))) {
2009 sync_address_resolver_free(i);
2010 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2013 return DBUS_HANDLER_RESULT_HANDLED;
2015 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
2017 DomainBrowserInfo *i;
2018 static const DBusObjectPathVTable vtable = {
2020 msg_domain_browser_impl,
2026 int32_t interface, protocol, type;
2030 if (!dbus_message_get_args(
2032 DBUS_TYPE_INT32, &interface,
2033 DBUS_TYPE_INT32, &protocol,
2034 DBUS_TYPE_STRING, &domain,
2035 DBUS_TYPE_INT32, &type,
2036 DBUS_TYPE_UINT32, &flags,
2037 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
2038 avahi_log_warn("Error parsing Server::DomainBrowserNew message");
2042 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2043 avahi_log_warn("Too many clients, client request failed.");
2044 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2047 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2048 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2049 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2055 i = avahi_new(DomainBrowserInfo, 1);
2056 i->id = ++client->current_id;
2058 i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
2059 AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
2060 client->n_objects++;
2062 if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, (AvahiLookupFlags) flags, domain_browser_callback, i))) {
2063 domain_browser_free(i);
2064 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2067 dbus_connection_register_object_path(c, i->path, &vtable, i);
2068 return respond_path(c, m, i->path);
2070 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
2072 ServiceTypeBrowserInfo *i;
2073 static const DBusObjectPathVTable vtable = {
2075 msg_service_type_browser_impl,
2081 int32_t interface, protocol;
2085 if (!dbus_message_get_args(
2087 DBUS_TYPE_INT32, &interface,
2088 DBUS_TYPE_INT32, &protocol,
2089 DBUS_TYPE_STRING, &domain,
2090 DBUS_TYPE_UINT32, &flags,
2091 DBUS_TYPE_INVALID)) {
2092 avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
2096 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2097 avahi_log_warn("Too many clients, client request failed.");
2098 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2102 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2103 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2104 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2110 i = avahi_new(ServiceTypeBrowserInfo, 1);
2111 i->id = ++client->current_id;
2113 i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
2114 AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
2115 client->n_objects++;
2117 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))) {
2118 service_type_browser_free(i);
2119 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2122 dbus_connection_register_object_path(c, i->path, &vtable, i);
2123 return respond_path(c, m, i->path);
2125 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
2127 ServiceBrowserInfo *i;
2128 static const DBusObjectPathVTable vtable = {
2130 msg_service_browser_impl,
2136 int32_t interface, protocol;
2138 char *domain, *type;
2140 if (!dbus_message_get_args(
2142 DBUS_TYPE_INT32, &interface,
2143 DBUS_TYPE_INT32, &protocol,
2144 DBUS_TYPE_STRING, &type,
2145 DBUS_TYPE_STRING, &domain,
2146 DBUS_TYPE_UINT32, &flags,
2147 DBUS_TYPE_INVALID) || !type) {
2148 avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
2152 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2153 avahi_log_warn("Too many clients, client request failed.");
2154 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2158 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2159 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2160 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2166 i = avahi_new(ServiceBrowserInfo, 1);
2167 i->id = ++client->current_id;
2169 i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
2170 AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
2171 client->n_objects++;
2173 if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, (AvahiLookupFlags) flags, service_browser_callback, i))) {
2174 service_browser_free(i);
2175 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2178 dbus_connection_register_object_path(c, i->path, &vtable, i);
2179 return respond_path(c, m, i->path);
2181 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
2183 int32_t interface, protocol, aprotocol;
2185 char *name, *type, *domain;
2186 SyncServiceResolverInfo *i;
2188 if (!dbus_message_get_args(
2190 DBUS_TYPE_INT32, &interface,
2191 DBUS_TYPE_INT32, &protocol,
2192 DBUS_TYPE_STRING, &name,
2193 DBUS_TYPE_STRING, &type,
2194 DBUS_TYPE_STRING, &domain,
2195 DBUS_TYPE_INT32, &aprotocol,
2196 DBUS_TYPE_UINT32, &flags,
2197 DBUS_TYPE_INVALID) || !type) {
2198 avahi_log_warn("Error parsing Server::ResolveService message");
2202 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2203 avahi_log_warn("Too many clients, client request failed.");
2204 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2207 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2208 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2209 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2218 i = avahi_new(SyncServiceResolverInfo, 1);
2220 i->message = dbus_message_ref(m);
2221 AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i);
2222 client->n_objects++;
2224 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))) {
2225 sync_service_resolver_free(i);
2226 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2229 return DBUS_HANDLER_RESULT_HANDLED;
2231 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) {
2233 int32_t interface, protocol, aprotocol;
2235 char *name, *type, *domain;
2236 AsyncServiceResolverInfo *i;
2237 static const DBusObjectPathVTable vtable = {
2239 msg_async_service_resolver_impl,
2246 if (!dbus_message_get_args(
2248 DBUS_TYPE_INT32, &interface,
2249 DBUS_TYPE_INT32, &protocol,
2250 DBUS_TYPE_STRING, &name,
2251 DBUS_TYPE_STRING, &type,
2252 DBUS_TYPE_STRING, &domain,
2253 DBUS_TYPE_INT32, &aprotocol,
2254 DBUS_TYPE_UINT32, &flags,
2255 DBUS_TYPE_INVALID) || !type) {
2256 avahi_log_warn("Error parsing Server::ServiceResolverNew message");
2260 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2261 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2262 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2265 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2266 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2267 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2276 i = avahi_new(AsyncServiceResolverInfo, 1);
2277 i->id = ++client->current_id;
2279 i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
2280 AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i);
2281 client->n_objects++;
2283 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))) {
2284 async_service_resolver_free(i);
2285 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2288 /* avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */
2290 dbus_connection_register_object_path(c, i->path, &vtable, i);
2291 return respond_path(c, m, i->path);
2293 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew")) {
2295 int32_t interface, protocol, aprotocol;
2298 AsyncHostNameResolverInfo *i;
2299 static const DBusObjectPathVTable vtable = {
2301 msg_async_host_name_resolver_impl,
2308 if (!dbus_message_get_args(
2310 DBUS_TYPE_INT32, &interface,
2311 DBUS_TYPE_INT32, &protocol,
2312 DBUS_TYPE_STRING, &name,
2313 DBUS_TYPE_INT32, &aprotocol,
2314 DBUS_TYPE_UINT32, &flags,
2315 DBUS_TYPE_INVALID) || !name) {
2316 avahi_log_warn("Error parsing Server::HostNameResolverNew message");
2320 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2321 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2322 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2325 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2326 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2327 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2330 i = avahi_new(AsyncHostNameResolverInfo, 1);
2331 i->id = ++client->current_id;
2333 i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
2334 AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i);
2335 client->n_objects++;
2337 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))) {
2338 async_host_name_resolver_free(i);
2339 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2342 dbus_connection_register_object_path(c, i->path, &vtable, i);
2343 return respond_path(c, m, i->path);
2345 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew")) {
2347 int32_t interface, protocol;
2350 AsyncAddressResolverInfo *i;
2352 static const DBusObjectPathVTable vtable = {
2354 msg_async_address_resolver_impl,
2361 if (!dbus_message_get_args(
2363 DBUS_TYPE_INT32, &interface,
2364 DBUS_TYPE_INT32, &protocol,
2365 DBUS_TYPE_STRING, &address,
2366 DBUS_TYPE_UINT32, &flags,
2367 DBUS_TYPE_INVALID) || !address) {
2368 avahi_log_warn("Error parsing Server::AddressResolverNew message");
2372 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
2373 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
2375 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2376 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2377 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2380 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2381 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2382 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2385 i = avahi_new(AsyncAddressResolverInfo, 1);
2386 i->id = ++client->current_id;
2388 i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
2389 AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i);
2390 client->n_objects++;
2392 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, async_address_resolver_callback, i))) {
2393 async_address_resolver_free(i);
2394 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2397 dbus_connection_register_object_path(c, i->path, &vtable, i);
2398 return respond_path(c, m, i->path);
2401 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
2404 if (dbus_error_is_set(&error))
2405 dbus_error_free(&error);
2407 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2410 void dbus_protocol_server_state_changed(AvahiServerState state) {
2417 m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
2418 t = (int32_t) state;
2419 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
2420 dbus_connection_send(server->bus, m, NULL);
2421 dbus_message_unref(m);
2424 int dbus_protocol_setup(const AvahiPoll *poll_api) {
2427 static const DBusObjectPathVTable server_vtable = {
2436 dbus_error_init(&error);
2438 server = avahi_new(Server, 1);
2439 AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
2440 server->current_id = 0;
2441 server->n_clients = 0;
2443 if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
2444 assert(dbus_error_is_set(&error));
2445 avahi_log_error("dbus_bus_get(): %s", error.message);
2449 if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) {
2450 avahi_log_error("avahi_dbus_connection_glue() failed");
2454 if (dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
2455 if (dbus_error_is_set(&error)) {
2456 avahi_log_error("dbus_bus_request_name(): %s", error.message);
2460 avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'");
2464 if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) {
2465 avahi_log_error("dbus_connection_add_filter() failed");
2469 dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
2471 if (dbus_error_is_set(&error)) {
2472 avahi_log_error("dbus_bus_add_match(): %s", error.message);
2476 if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
2477 avahi_log_error("dbus_connection_register_object_path() failed");
2485 dbus_connection_disconnect(server->bus);
2486 dbus_connection_unref(server->bus);
2489 if (dbus_error_is_set(&error))
2490 dbus_error_free(&error);
2497 void dbus_protocol_shutdown(void) {
2501 while (server->clients)
2502 client_free(server->clients);
2504 assert(server->n_clients == 0);
2507 dbus_connection_disconnect(server->bus);
2508 dbus_connection_unref(server->bus);