4 This file is part of avahi.
6 avahi is free software; you can redistribute it and/or modify it
7 under the terms of the GNU Lesser General Public License as
8 published by the Free Software Foundation; either version 2.1 of the
9 License, or (at your option) any later version.
11 avahi is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14 Public License for more details.
16 You should have received a copy of the GNU Lesser General Public
17 License along with avahi; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 #include <sys/ioctl.h>
38 #include <dbus/dbus.h>
40 #include <avahi-common/dbus.h>
41 #include <avahi-common/llist.h>
42 #include <avahi-common/malloc.h>
43 #include <avahi-common/dbus.h>
44 #include <avahi-common/dbus-watch-glue.h>
45 #include <avahi-common/alternative.h>
46 #include <avahi-common/error.h>
48 #include <avahi-core/log.h>
49 #include <avahi-core/core.h>
50 #include <avahi-core/lookup.h>
51 #include <avahi-core/publish.h>
53 #include "dbus-protocol.h"
56 typedef struct Server Server;
57 typedef struct Client Client;
58 typedef struct EntryGroupInfo EntryGroupInfo;
59 typedef struct SyncHostNameResolverInfo SyncHostNameResolverInfo;
60 typedef struct AsyncHostNameResolverInfo AsyncHostNameResolverInfo;
61 typedef struct SyncAddressResolverInfo SyncAddressResolverInfo;
62 typedef struct AsyncAddressResolverInfo AsyncAddressResolverInfo;
63 typedef struct DomainBrowserInfo DomainBrowserInfo;
64 typedef struct ServiceTypeBrowserInfo ServiceTypeBrowserInfo;
65 typedef struct ServiceBrowserInfo ServiceBrowserInfo;
66 typedef struct SyncServiceResolverInfo SyncServiceResolverInfo;
67 typedef struct AsyncServiceResolverInfo AsyncServiceResolverInfo;
69 #define MAX_CLIENTS 20
70 #define MAX_OBJECTS_PER_CLIENT 50
71 #define MAX_ENTRIES_PER_ENTRY_GROUP 20
73 /* #define VALGRIND_WORKAROUND 1 */
75 struct EntryGroupInfo {
78 AvahiSEntryGroup *entry_group;
83 AVAHI_LLIST_FIELDS(EntryGroupInfo, entry_groups);
86 struct SyncHostNameResolverInfo {
88 AvahiSHostNameResolver *host_name_resolver;
91 AVAHI_LLIST_FIELDS(SyncHostNameResolverInfo, sync_host_name_resolvers);
94 struct AsyncHostNameResolverInfo {
97 AvahiSHostNameResolver *host_name_resolver;
100 AVAHI_LLIST_FIELDS(AsyncHostNameResolverInfo, async_host_name_resolvers);
103 struct SyncAddressResolverInfo {
105 AvahiSAddressResolver *address_resolver;
106 DBusMessage *message;
108 AVAHI_LLIST_FIELDS(SyncAddressResolverInfo, sync_address_resolvers);
111 struct AsyncAddressResolverInfo {
114 AvahiSAddressResolver *address_resolver;
117 AVAHI_LLIST_FIELDS(AsyncAddressResolverInfo, async_address_resolvers);
120 struct DomainBrowserInfo {
123 AvahiSDomainBrowser *domain_browser;
126 AVAHI_LLIST_FIELDS(DomainBrowserInfo, domain_browsers);
129 struct ServiceTypeBrowserInfo {
132 AvahiSServiceTypeBrowser *service_type_browser;
135 AVAHI_LLIST_FIELDS(ServiceTypeBrowserInfo, service_type_browsers);
138 struct ServiceBrowserInfo {
141 AvahiSServiceBrowser *service_browser;
144 AVAHI_LLIST_FIELDS(ServiceBrowserInfo, service_browsers);
147 struct SyncServiceResolverInfo {
149 AvahiSServiceResolver *service_resolver;
150 DBusMessage *message;
152 AVAHI_LLIST_FIELDS(SyncServiceResolverInfo, sync_service_resolvers);
155 struct AsyncServiceResolverInfo {
158 AvahiSServiceResolver *service_resolver;
161 AVAHI_LLIST_FIELDS(AsyncServiceResolverInfo, async_service_resolvers);
170 AVAHI_LLIST_FIELDS(Client, clients);
171 AVAHI_LLIST_HEAD(EntryGroupInfo, entry_groups);
172 AVAHI_LLIST_HEAD(SyncHostNameResolverInfo, sync_host_name_resolvers);
173 AVAHI_LLIST_HEAD(AsyncHostNameResolverInfo, async_host_name_resolvers);
174 AVAHI_LLIST_HEAD(SyncAddressResolverInfo, sync_address_resolvers);
175 AVAHI_LLIST_HEAD(AsyncAddressResolverInfo, async_address_resolvers);
176 AVAHI_LLIST_HEAD(DomainBrowserInfo, domain_browsers);
177 AVAHI_LLIST_HEAD(ServiceTypeBrowserInfo, service_type_browsers);
178 AVAHI_LLIST_HEAD(ServiceBrowserInfo, service_browsers);
179 AVAHI_LLIST_HEAD(SyncServiceResolverInfo, sync_service_resolvers);
180 AVAHI_LLIST_HEAD(AsyncServiceResolverInfo, async_service_resolvers);
185 AVAHI_LLIST_HEAD(Client, clients);
190 static Server *server = NULL;
192 static void entry_group_free(EntryGroupInfo *i) {
196 avahi_s_entry_group_free(i->entry_group);
197 dbus_connection_unregister_object_path(server->bus, i->path);
199 AVAHI_LLIST_REMOVE(EntryGroupInfo, entry_groups, i->client->entry_groups, i);
201 i->client->n_objects--;
202 assert(i->client->n_objects >= 0);
207 static void sync_host_name_resolver_free(SyncHostNameResolverInfo *i) {
210 if (i->host_name_resolver)
211 avahi_s_host_name_resolver_free(i->host_name_resolver);
212 dbus_message_unref(i->message);
213 AVAHI_LLIST_REMOVE(SyncHostNameResolverInfo, sync_host_name_resolvers, i->client->sync_host_name_resolvers, i);
215 i->client->n_objects--;
216 assert(i->client->n_objects >= 0);
221 static void async_host_name_resolver_free(AsyncHostNameResolverInfo *i) {
224 if (i->host_name_resolver)
225 avahi_s_host_name_resolver_free(i->host_name_resolver);
226 dbus_connection_unregister_object_path(server->bus, i->path);
227 AVAHI_LLIST_REMOVE(AsyncHostNameResolverInfo, async_host_name_resolvers, i->client->async_host_name_resolvers, i);
229 i->client->n_objects--;
230 assert(i->client->n_objects >= 0);
235 static void sync_address_resolver_free(SyncAddressResolverInfo *i) {
238 if (i->address_resolver)
239 avahi_s_address_resolver_free(i->address_resolver);
240 dbus_message_unref(i->message);
241 AVAHI_LLIST_REMOVE(SyncAddressResolverInfo, sync_address_resolvers, i->client->sync_address_resolvers, i);
243 i->client->n_objects--;
244 assert(i->client->n_objects >= 0);
249 static void async_address_resolver_free(AsyncAddressResolverInfo *i) {
252 if (i->address_resolver)
253 avahi_s_address_resolver_free(i->address_resolver);
254 dbus_connection_unregister_object_path(server->bus, i->path);
255 AVAHI_LLIST_REMOVE(AsyncAddressResolverInfo, async_address_resolvers, i->client->async_address_resolvers, i);
257 i->client->n_objects--;
258 assert(i->client->n_objects >= 0);
263 static void domain_browser_free(DomainBrowserInfo *i) {
266 if (i->domain_browser)
267 avahi_s_domain_browser_free(i->domain_browser);
268 dbus_connection_unregister_object_path(server->bus, i->path);
270 AVAHI_LLIST_REMOVE(DomainBrowserInfo, domain_browsers, i->client->domain_browsers, i);
272 i->client->n_objects--;
273 assert(i->client->n_objects >= 0);
278 static void service_type_browser_free(ServiceTypeBrowserInfo *i) {
281 if (i->service_type_browser)
282 avahi_s_service_type_browser_free(i->service_type_browser);
283 dbus_connection_unregister_object_path(server->bus, i->path);
285 AVAHI_LLIST_REMOVE(ServiceTypeBrowserInfo, service_type_browsers, i->client->service_type_browsers, i);
287 i->client->n_objects--;
288 assert(i->client->n_objects >= 0);
293 static void service_browser_free(ServiceBrowserInfo *i) {
296 if (i->service_browser)
297 avahi_s_service_browser_free(i->service_browser);
298 dbus_connection_unregister_object_path(server->bus, i->path);
300 AVAHI_LLIST_REMOVE(ServiceBrowserInfo, service_browsers, i->client->service_browsers, i);
302 i->client->n_objects--;
303 assert(i->client->n_objects >= 0);
308 static void sync_service_resolver_free(SyncServiceResolverInfo *i) {
311 if (i->service_resolver)
312 avahi_s_service_resolver_free(i->service_resolver);
313 dbus_message_unref(i->message);
314 AVAHI_LLIST_REMOVE(SyncServiceResolverInfo, sync_service_resolvers, i->client->sync_service_resolvers, i);
316 i->client->n_objects--;
317 assert(i->client->n_objects >= 0);
322 static void async_service_resolver_free(AsyncServiceResolverInfo *i) {
325 if (i->service_resolver)
326 avahi_s_service_resolver_free(i->service_resolver);
328 dbus_connection_unregister_object_path(server->bus, i->path);
329 AVAHI_LLIST_REMOVE(AsyncServiceResolverInfo, async_service_resolvers, i->client->async_service_resolvers, i);
331 i->client->n_objects--;
332 assert(i->client->n_objects >= 0);
337 static void client_free(Client *c) {
342 while (c->entry_groups)
343 entry_group_free(c->entry_groups);
345 while (c->sync_host_name_resolvers)
346 sync_host_name_resolver_free(c->sync_host_name_resolvers);
348 while (c->async_host_name_resolvers)
349 async_host_name_resolver_free(c->async_host_name_resolvers);
351 while (c->sync_address_resolvers)
352 sync_address_resolver_free(c->sync_address_resolvers);
354 while (c->async_address_resolvers)
355 async_address_resolver_free(c->async_address_resolvers);
357 while (c->domain_browsers)
358 domain_browser_free(c->domain_browsers);
360 while (c->service_type_browsers)
361 service_type_browser_free(c->service_type_browsers);
363 while (c->service_browsers)
364 service_browser_free(c->service_browsers);
366 while (c->sync_service_resolvers)
367 sync_service_resolver_free(c->sync_service_resolvers);
369 while (c->async_service_resolvers)
370 async_service_resolver_free(c->async_service_resolvers);
372 assert(c->n_objects == 0);
375 AVAHI_LLIST_REMOVE(Client, clients, server->clients, c);
378 server->n_clients --;
379 assert(server->n_clients >= 0);
382 static Client *client_get(const char *name, int create) {
388 for (client = server->clients; client; client = client->clients_next)
389 if (!strcmp(name, client->name))
395 if (server->n_clients >= MAX_CLIENTS)
398 /* If not existant yet, create a new entry */
399 client = avahi_new(Client, 1);
400 client->id = server->current_id++;
401 client->name = avahi_strdup(name);
402 client->current_id = 0;
403 client->n_objects = 0;
405 AVAHI_LLIST_HEAD_INIT(EntryGroupInfo, client->entry_groups);
406 AVAHI_LLIST_HEAD_INIT(SyncHostNameResolverInfo, client->sync_host_name_resolvers);
407 AVAHI_LLIST_HEAD_INIT(AsyncHostNameResolverInfo, client->async_host_name_resolvers);
408 AVAHI_LLIST_HEAD_INIT(SyncAddressResolverInfo, client->sync_address_resolvers);
409 AVAHI_LLIST_HEAD_INIT(AsyncAddressResolverInfo, client->async_address_resolvers);
410 AVAHI_LLIST_HEAD_INIT(DomainBrowserInfo, client->domain_browsers);
411 AVAHI_LLIST_HEAD_INIT(ServiceTypeBrowserInfo, client->service_type_browsers);
412 AVAHI_LLIST_HEAD_INIT(ServiceBrowserInfo, client->service_browsers);
413 AVAHI_LLIST_HEAD_INIT(SyncServiceResolverInfo, client->sync_service_resolvers);
414 AVAHI_LLIST_HEAD_INIT(AsyncServiceResolverInfo, client->async_service_resolvers);
416 AVAHI_LLIST_PREPEND(Client, clients, server->clients, client);
419 assert(server->n_clients > 0);
424 static DBusHandlerResult respond_error(DBusConnection *c, DBusMessage *m, int error, const char *text) {
427 assert(-error > -AVAHI_OK);
428 assert(-error < -AVAHI_ERR_MAX);
431 text = avahi_strerror(error);
433 reply = dbus_message_new_error(m, avahi_error_number_to_dbus (error), text);
434 dbus_connection_send(c, reply, NULL);
435 dbus_message_unref(reply);
437 avahi_log_debug(__FILE__": Responding error '%s' (%i)", text, error);
439 return DBUS_HANDLER_RESULT_HANDLED;
442 static DBusHandlerResult respond_string(DBusConnection *c, DBusMessage *m, const char *text) {
445 reply = dbus_message_new_method_return(m);
446 dbus_message_append_args(reply, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID);
447 dbus_connection_send(c, reply, NULL);
448 dbus_message_unref(reply);
450 return DBUS_HANDLER_RESULT_HANDLED;
453 static DBusHandlerResult respond_int32(DBusConnection *c, DBusMessage *m, int32_t i) {
456 reply = dbus_message_new_method_return(m);
457 dbus_message_append_args(reply, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID);
458 dbus_connection_send(c, reply, NULL);
459 dbus_message_unref(reply);
461 return DBUS_HANDLER_RESULT_HANDLED;
464 static DBusHandlerResult respond_uint32(DBusConnection *c, DBusMessage *m, uint32_t u) {
467 reply = dbus_message_new_method_return(m);
468 dbus_message_append_args(reply, DBUS_TYPE_UINT32, &u, DBUS_TYPE_INVALID);
469 dbus_connection_send(c, reply, NULL);
470 dbus_message_unref(reply);
472 return DBUS_HANDLER_RESULT_HANDLED;
475 static DBusHandlerResult respond_boolean(DBusConnection *c, DBusMessage *m, int b) {
478 reply = dbus_message_new_method_return(m);
479 dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
480 dbus_connection_send(c, reply, NULL);
481 dbus_message_unref(reply);
483 return DBUS_HANDLER_RESULT_HANDLED;
486 static DBusHandlerResult respond_ok(DBusConnection *c, DBusMessage *m) {
489 reply = dbus_message_new_method_return(m);
490 dbus_connection_send(c, reply, NULL);
491 dbus_message_unref(reply);
493 return DBUS_HANDLER_RESULT_HANDLED;
496 static DBusHandlerResult respond_path(DBusConnection *c, DBusMessage *m, const char *path) {
499 reply = dbus_message_new_method_return(m);
500 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
501 dbus_connection_send(c, reply, NULL);
502 dbus_message_unref(reply);
504 return DBUS_HANDLER_RESULT_HANDLED;
507 static char *file_get_contents(char *fname) {
515 if (!(fd = open(fname, O_RDONLY))) {
516 avahi_log_error("Failed to open %s: %s", fname, strerror(errno));
520 if (fstat(fd, &st) < 0) {
521 avahi_log_error("stat(%s) failed: %s", fname, strerror(errno));
525 if (!(S_ISREG(st.st_mode))) {
526 avahi_log_error("Invalid file %s", fname);
530 if (st.st_size > 1024*1024) { /** 1MB */
531 avahi_log_error("File too large %s", fname);
535 buf = avahi_new(char, st.st_size+1);
537 if ((size = read(fd, buf, st.st_size)) < 0) {
538 avahi_log_error("read() failed: %s\n", strerror(errno));
558 static const char *map_browse_signal_name(AvahiBrowserEvent e) {
560 case AVAHI_BROWSER_NEW : return "ItemNew";
561 case AVAHI_BROWSER_REMOVE : return "ItemRemove";
562 case AVAHI_BROWSER_FAILURE : return "Failure";
563 case AVAHI_BROWSER_NOT_FOUND : return "NotFound";
564 case AVAHI_BROWSER_CACHE_EXHAUSTED : return "CacheExhausted";
565 case AVAHI_BROWSER_ALL_FOR_NOW : return "AllForNow";
571 static const char *map_resolve_signal_name(AvahiResolverEvent e) {
573 case AVAHI_RESOLVER_FOUND : return "Found";
574 case AVAHI_RESOLVER_TIMEOUT : return "Timeout";
575 case AVAHI_RESOLVER_FAILURE : return "Failure";
576 case AVAHI_RESOLVER_NOT_FOUND : return "NotFound";
582 static int map_resolve_error(AvahiResolverEvent e) {
585 case AVAHI_RESOLVER_FOUND : abort();
586 case AVAHI_RESOLVER_TIMEOUT : return AVAHI_ERR_TIMEOUT;
587 case AVAHI_RESOLVER_FAILURE : return AVAHI_ERR_FAILURE;
588 case AVAHI_RESOLVER_NOT_FOUND : return AVAHI_ERR_NOT_FOUND;
594 static DBusHandlerResult handle_introspect(DBusConnection *c, DBusMessage *m, const char *fname) {
595 char *path, *contents;
602 dbus_error_init(&error);
604 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
605 avahi_log_error("Error parsing Introspect message: %s", error.message);
609 path = avahi_strdup_printf("%s/%s", AVAHI_DBUS_INTROSPECTION_DIR, fname);
610 contents = file_get_contents(path);
614 avahi_log_error("Failed to load introspection data.");
618 respond_string(c, m, contents);
619 avahi_free(contents);
621 return DBUS_HANDLER_RESULT_HANDLED;
624 if (dbus_error_is_set(&error))
625 dbus_error_free(&error);
627 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
631 static DBusHandlerResult msg_signal_filter_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
634 dbus_error_init(&error);
636 /* avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s", */
637 /* dbus_message_get_interface(m), */
638 /* dbus_message_get_path(m), */
639 /* dbus_message_get_member(m)); */
641 if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
642 /* No, we shouldn't quit, but until we get somewhere
643 * usefull such that we can restore our state, we will */
644 avahi_log_warn("Disconnnected from D-BUS, terminating...");
646 raise(SIGQUIT); /* The signal handler will catch this and terminate the process cleanly*/
648 return DBUS_HANDLER_RESULT_HANDLED;
650 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) {
653 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
654 avahi_log_warn("Error parsing NameAcquired message");
658 /* avahi_log_info(__FILE__": name acquired (%s)", name); */
659 return DBUS_HANDLER_RESULT_HANDLED;
661 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
662 char *name, *old, *new;
664 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) {
665 avahi_log_warn("Error parsing NameOwnerChanged message");
672 if ((client = client_get(name, FALSE))) {
673 avahi_log_debug(__FILE__": client %s vanished.", name);
680 if (dbus_error_is_set(&error))
681 dbus_error_free(&error);
683 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
686 static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntryGroupState state, void* userdata) {
687 EntryGroupInfo *i = userdata;
695 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged");
697 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
698 dbus_message_set_destination(m, i->client->name);
699 dbus_connection_send(server->bus, m, NULL);
700 dbus_message_unref(m);
703 static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
705 EntryGroupInfo *i = userdata;
711 dbus_error_init(&error);
713 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
714 dbus_message_get_interface(m),
715 dbus_message_get_path(m),
716 dbus_message_get_member(m));
719 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
720 return handle_introspect(c, m, "EntryGroup.introspect");
723 if (strcmp(dbus_message_get_sender(m), i->client->name))
724 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
726 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) {
728 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
729 avahi_log_warn("Error parsing EntryGroup::Free message");
734 return respond_ok(c, m);
736 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Commit")) {
738 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
739 avahi_log_warn("Error parsing EntryGroup::Commit message");
743 avahi_s_entry_group_commit(i->entry_group);
744 return respond_ok(c, m);
747 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Reset")) {
749 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
750 avahi_log_warn("Error parsing EntryGroup::Reset message");
754 avahi_s_entry_group_reset(i->entry_group);
756 return respond_ok(c, m);
758 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) {
762 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
763 avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
767 b = !!avahi_s_entry_group_is_empty(i->entry_group);
769 reply = dbus_message_new_method_return(m);
770 dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
771 dbus_connection_send(c, reply, NULL);
772 dbus_message_unref(reply);
774 return DBUS_HANDLER_RESULT_HANDLED;
776 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
777 AvahiEntryGroupState state;
779 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
780 avahi_log_warn("Error parsing EntryGroup::GetState message");
784 state = avahi_s_entry_group_get_state(i->entry_group);
785 return respond_int32(c, m, (int32_t) state);
787 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
788 int32_t interface, protocol;
789 char *type, *name, *domain, *host;
791 AvahiStringList *strlst;
792 DBusMessageIter iter, sub;
795 if (!dbus_message_get_args(
797 DBUS_TYPE_INT32, &interface,
798 DBUS_TYPE_INT32, &protocol,
799 DBUS_TYPE_STRING, &name,
800 DBUS_TYPE_STRING, &type,
801 DBUS_TYPE_STRING, &domain,
802 DBUS_TYPE_STRING, &host,
803 DBUS_TYPE_UINT16, &port,
804 DBUS_TYPE_INVALID) || !type || !name) {
805 avahi_log_warn("Error parsing EntryGroup::AddService message");
809 dbus_message_iter_init(m, &iter);
811 for (j = 0; j < 7; j++)
812 dbus_message_iter_next(&iter);
814 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
815 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY) {
816 avahi_log_warn("Error parsing EntryGroup::AddService message 2");
821 dbus_message_iter_recurse(&iter, &sub);
824 DBusMessageIter sub2;
828 if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
831 assert(at == DBUS_TYPE_ARRAY);
833 if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) {
834 avahi_log_warn("Error parsing EntryGroup::AddService message");
838 dbus_message_iter_recurse(&sub, &sub2);
839 dbus_message_iter_get_fixed_array(&sub2, &k, &n);
840 strlst = avahi_string_list_add_arbitrary(strlst, k, n);
842 dbus_message_iter_next(&sub);
845 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
846 avahi_string_list_free(strlst);
847 avahi_log_warn("Too many entries per entry group, client request failed.");
848 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
851 if (domain && !*domain)
857 if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, host, port, strlst) < 0) {
858 avahi_string_list_free(strlst);
859 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
863 avahi_string_list_free(strlst);
865 return respond_ok(c, m);
867 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
868 int32_t interface, protocol;
869 char *name, *address;
872 if (!dbus_message_get_args(
874 DBUS_TYPE_INT32, &interface,
875 DBUS_TYPE_INT32, &protocol,
876 DBUS_TYPE_STRING, &name,
877 DBUS_TYPE_STRING, &address,
878 DBUS_TYPE_INVALID) || !name || !address) {
879 avahi_log_warn("Error parsing EntryGroup::AddAddress message");
883 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
884 avahi_log_warn("Too many entries per entry group, client request failed.");
885 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
888 if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))) {
889 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
892 if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, 0, name, &a) < 0)
893 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
897 return respond_ok(c, m);
900 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
903 if (dbus_error_is_set(&error))
904 dbus_error_free(&error);
906 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
909 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) {
910 SyncHostNameResolverInfo *i = userdata;
916 if (event == AVAHI_RESOLVER_FOUND) {
917 char t[256], *pt = t;
918 int32_t i_interface, i_protocol, i_aprotocol, i_flags;
922 avahi_address_snprint(t, sizeof(t), a);
924 i_interface = (int32_t) interface;
925 i_protocol = (int32_t) protocol;
926 i_aprotocol = (int32_t) a->proto;
927 i_flags = (int32_t) flags;
929 reply = dbus_message_new_method_return(i->message);
930 dbus_message_append_args(
932 DBUS_TYPE_INT32, &i_interface,
933 DBUS_TYPE_INT32, &i_protocol,
934 DBUS_TYPE_STRING, &host_name,
935 DBUS_TYPE_INT32, &i_aprotocol,
936 DBUS_TYPE_STRING, &pt,
937 DBUS_TYPE_INT32, &i_flags,
940 dbus_connection_send(server->bus, reply, NULL);
941 dbus_message_unref(reply);
943 respond_error(server->bus, i->message, map_resolve_error(event), NULL);
945 sync_host_name_resolver_free(i);
948 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) {
949 SyncAddressResolverInfo *i = userdata;
955 if (event == AVAHI_RESOLVER_FOUND) {
956 char t[256], *pt = t;
957 int32_t i_interface, i_protocol, i_aprotocol, i_flags;
961 avahi_address_snprint(t, sizeof(t), address);
963 i_interface = (int32_t) interface;
964 i_protocol = (int32_t) protocol;
965 i_aprotocol = (int32_t) address->proto;
966 i_flags = (int32_t) flags;
968 reply = dbus_message_new_method_return(i->message);
969 dbus_message_append_args(
971 DBUS_TYPE_INT32, &i_interface,
972 DBUS_TYPE_INT32, &i_protocol,
973 DBUS_TYPE_INT32, &i_aprotocol,
974 DBUS_TYPE_STRING, &pt,
975 DBUS_TYPE_STRING, &host_name,
976 DBUS_TYPE_INT32, &i_flags,
979 dbus_connection_send(server->bus, reply, NULL);
980 dbus_message_unref(reply);
982 respond_error(server->bus, i->message, map_resolve_error(event), NULL);
984 sync_address_resolver_free(i);
987 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
989 DomainBrowserInfo *i = userdata;
995 dbus_error_init(&error);
997 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
998 dbus_message_get_interface(m),
999 dbus_message_get_path(m),
1000 dbus_message_get_member(m));
1003 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1004 return handle_introspect(c, m, "DomainBrowser.introspect");
1006 /* Access control */
1007 if (strcmp(dbus_message_get_sender(m), i->client->name))
1008 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1010 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
1012 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1013 avahi_log_warn("Error parsing DomainBrowser::Free message");
1017 domain_browser_free(i);
1018 return respond_ok(c, m);
1022 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1025 if (dbus_error_is_set(&error))
1026 dbus_error_free(&error);
1028 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1031 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1032 DomainBrowserInfo *i = userdata;
1034 int32_t i_interface, i_protocol, i_flags;
1039 i_interface = (int32_t) interface;
1040 i_protocol = (int32_t) protocol;
1041 i_flags = (int32_t) flags;
1043 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, map_browse_signal_name(event));
1045 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1047 dbus_message_append_args(
1049 DBUS_TYPE_INT32, &i_interface,
1050 DBUS_TYPE_INT32, &i_protocol,
1051 DBUS_TYPE_STRING, &domain,
1052 DBUS_TYPE_INT32, &i_flags,
1056 dbus_message_set_destination(m, i->client->name);
1057 dbus_connection_send(server->bus, m, NULL);
1058 dbus_message_unref(m);
1061 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1063 ServiceTypeBrowserInfo *i = userdata;
1069 dbus_error_init(&error);
1071 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1072 dbus_message_get_interface(m),
1073 dbus_message_get_path(m),
1074 dbus_message_get_member(m));
1077 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1078 return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
1080 /* Access control */
1081 if (strcmp(dbus_message_get_sender(m), i->client->name))
1082 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1084 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
1086 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1087 avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
1091 service_type_browser_free(i);
1092 return respond_ok(c, m);
1096 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1099 if (dbus_error_is_set(&error))
1100 dbus_error_free(&error);
1102 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1105 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1106 ServiceTypeBrowserInfo *i = userdata;
1108 int32_t i_interface, i_protocol, i_flags;
1113 i_interface = (int32_t) interface;
1114 i_protocol = (int32_t) protocol;
1115 i_flags = (int32_t) flags;
1117 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, map_browse_signal_name(event));
1119 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1122 dbus_message_append_args(
1124 DBUS_TYPE_INT32, &i_interface,
1125 DBUS_TYPE_INT32, &i_protocol,
1126 DBUS_TYPE_STRING, &type,
1127 DBUS_TYPE_STRING, &domain,
1128 DBUS_TYPE_INT32, &i_flags,
1132 dbus_message_set_destination(m, i->client->name);
1133 dbus_connection_send(server->bus, m, NULL);
1134 dbus_message_unref(m);
1137 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1139 ServiceBrowserInfo *i = userdata;
1145 dbus_error_init(&error);
1147 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1148 dbus_message_get_interface(m),
1149 dbus_message_get_path(m),
1150 dbus_message_get_member(m));
1153 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1154 return handle_introspect(c, m, "ServiceBrowser.Introspect");
1156 /* Access control */
1157 if (strcmp(dbus_message_get_sender(m), i->client->name))
1158 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1160 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
1162 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1163 avahi_log_warn("Error parsing ServiceBrowser::Free message");
1167 service_browser_free(i);
1168 return respond_ok(c, m);
1172 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1175 if (dbus_error_is_set(&error))
1176 dbus_error_free(&error);
1178 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1181 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) {
1182 ServiceBrowserInfo *i = userdata;
1184 int32_t i_interface, i_protocol, i_flags;
1189 i_interface = (int32_t) interface;
1190 i_protocol = (int32_t) protocol;
1191 i_flags = (int32_t) flags;
1193 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, map_browse_signal_name(event));
1195 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1200 dbus_message_append_args(
1202 DBUS_TYPE_INT32, &i_interface,
1203 DBUS_TYPE_INT32, &i_protocol,
1204 DBUS_TYPE_STRING, &name,
1205 DBUS_TYPE_STRING, &type,
1206 DBUS_TYPE_STRING, &domain,
1207 DBUS_TYPE_INT32, &i_flags,
1211 dbus_message_set_destination(m, i->client->name);
1212 dbus_connection_send(server->bus, m, NULL);
1213 dbus_message_unref(m);
1216 static void append_string_list(DBusMessage *reply, AvahiStringList *txt) {
1218 DBusMessageIter iter, sub;
1222 dbus_message_iter_init_append(reply, &iter);
1223 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1225 for (p = txt; p; p = p->next) {
1226 DBusMessageIter sub2;
1227 const uint8_t *data = p->text;
1229 dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1230 dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
1231 dbus_message_iter_close_container(&sub, &sub2);
1234 dbus_message_iter_close_container(&iter, &sub);
1237 static void sync_service_resolver_callback(
1238 AvahiSServiceResolver *r,
1239 AvahiIfIndex interface,
1240 AvahiProtocol protocol,
1241 AvahiResolverEvent event,
1245 const char *host_name,
1246 const AvahiAddress *a,
1248 AvahiStringList *txt,
1249 AvahiLookupResultFlags flags,
1252 SyncServiceResolverInfo *i = userdata;
1257 if (event == AVAHI_RESOLVER_FOUND) {
1258 char t[256], *pt = t;
1259 int32_t i_interface, i_protocol, i_aprotocol, i_flags;
1268 avahi_address_snprint(t, sizeof(t), a);
1270 i_interface = (int32_t) interface;
1271 i_protocol = (int32_t) protocol;
1272 i_aprotocol = (int32_t) a->proto;
1273 i_flags = (int32_t) flags;
1275 reply = dbus_message_new_method_return(i->message);
1276 dbus_message_append_args(
1278 DBUS_TYPE_INT32, &i_interface,
1279 DBUS_TYPE_INT32, &i_protocol,
1280 DBUS_TYPE_STRING, &name,
1281 DBUS_TYPE_STRING, &type,
1282 DBUS_TYPE_STRING, &domain,
1283 DBUS_TYPE_STRING, &host_name,
1284 DBUS_TYPE_INT32, &i_aprotocol,
1285 DBUS_TYPE_STRING, &pt,
1286 DBUS_TYPE_UINT16, &port,
1289 append_string_list(reply, txt);
1291 dbus_message_append_args(
1293 DBUS_TYPE_INT32, &i_flags,
1296 dbus_connection_send(server->bus, reply, NULL);
1297 dbus_message_unref(reply);
1299 respond_error(server->bus, i->message, map_resolve_error(event), NULL);
1301 sync_service_resolver_free(i);
1304 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) {
1305 AsyncAddressResolverInfo *i = userdata;
1311 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, map_browse_signal_name(event));
1313 if (event == AVAHI_RESOLVER_FOUND) {
1314 char t[256], *pt = t;
1315 int32_t i_interface, i_protocol, i_aprotocol, i_flags;
1319 avahi_address_snprint(t, sizeof(t), address);
1321 i_interface = (int32_t) interface;
1322 i_protocol = (int32_t) protocol;
1323 i_aprotocol = (int32_t) address->proto;
1324 i_flags = (int32_t) flags;
1326 dbus_message_append_args(
1328 DBUS_TYPE_INT32, &i_interface,
1329 DBUS_TYPE_INT32, &i_protocol,
1330 DBUS_TYPE_INT32, &i_aprotocol,
1331 DBUS_TYPE_STRING, &pt,
1332 DBUS_TYPE_STRING, &host_name,
1333 DBUS_TYPE_INT32, &i_flags,
1338 dbus_message_set_destination(reply, i->client->name);
1339 dbus_connection_send(server->bus, reply, NULL);
1340 dbus_message_unref(reply);
1343 static DBusHandlerResult msg_async_address_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1345 AsyncAddressResolverInfo *i = userdata;
1351 dbus_error_init(&error);
1353 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1354 dbus_message_get_interface(m),
1355 dbus_message_get_path(m),
1356 dbus_message_get_member(m));
1359 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1360 return handle_introspect(c, m, "AddressResolver.Introspect");
1362 /* Access control */
1363 if (strcmp(dbus_message_get_sender(m), i->client->name))
1364 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1366 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Free")) {
1368 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1369 avahi_log_warn("Error parsing AddressResolver::Free message");
1373 async_address_resolver_free(i);
1374 return respond_ok(c, m);
1378 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1381 if (dbus_error_is_set(&error))
1382 dbus_error_free(&error);
1384 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1387 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) {
1388 AsyncHostNameResolverInfo *i = userdata;
1394 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, map_resolve_signal_name(event));
1396 if (event == AVAHI_RESOLVER_FOUND) {
1397 char t[256], *pt = t;
1398 int32_t i_interface, i_protocol, i_aprotocol, i_flags;
1402 avahi_address_snprint(t, sizeof(t), a);
1404 i_interface = (int32_t) interface;
1405 i_protocol = (int32_t) protocol;
1406 i_aprotocol = (int32_t) a->proto;
1407 i_flags = (int32_t) flags;
1409 dbus_message_append_args(
1411 DBUS_TYPE_INT32, &i_interface,
1412 DBUS_TYPE_INT32, &i_protocol,
1413 DBUS_TYPE_STRING, &host_name,
1414 DBUS_TYPE_INT32, &i_aprotocol,
1415 DBUS_TYPE_STRING, &pt,
1416 DBUS_TYPE_INT32, &i_flags,
1420 dbus_message_set_destination(reply, i->client->name);
1421 dbus_connection_send(server->bus, reply, NULL);
1422 dbus_message_unref(reply);
1425 static DBusHandlerResult msg_async_host_name_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1427 AsyncHostNameResolverInfo *i = userdata;
1433 dbus_error_init(&error);
1435 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1436 dbus_message_get_interface(m),
1437 dbus_message_get_path(m),
1438 dbus_message_get_member(m));
1441 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1442 return handle_introspect(c, m, "HostNameResolver.Introspect");
1444 /* Access control */
1445 if (strcmp(dbus_message_get_sender(m), i->client->name))
1446 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1448 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, "Free")) {
1450 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1451 avahi_log_warn("Error parsing HostNameResolver::Free message");
1455 async_host_name_resolver_free(i);
1456 return respond_ok(c, m);
1459 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1462 if (dbus_error_is_set(&error))
1463 dbus_error_free(&error);
1465 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1468 static void async_service_resolver_callback(
1469 AvahiSServiceResolver *r,
1470 AvahiIfIndex interface,
1471 AvahiProtocol protocol,
1472 AvahiResolverEvent event,
1476 const char *host_name,
1477 const AvahiAddress *a,
1479 AvahiStringList *txt,
1480 AvahiLookupResultFlags flags,
1483 AsyncServiceResolverInfo *i = userdata;
1489 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, map_resolve_signal_name(event));
1491 if (event == AVAHI_RESOLVER_FOUND) {
1492 char t[256], *pt = t;
1493 int32_t i_interface, i_protocol, i_aprotocol, i_flags;
1497 /* avahi_log_debug(__FILE__": [%s] Successfully resolved service <%s.%s.%s>", i->path, name, type, domain); */
1500 avahi_address_snprint(t, sizeof(t), a);
1505 i_interface = (int32_t) interface;
1506 i_protocol = (int32_t) protocol;
1507 i_aprotocol = (int32_t) a->proto;
1508 i_flags = (int32_t) flags;
1510 dbus_message_append_args(
1512 DBUS_TYPE_INT32, &i_interface,
1513 DBUS_TYPE_INT32, &i_protocol,
1514 DBUS_TYPE_STRING, &name,
1515 DBUS_TYPE_STRING, &type,
1516 DBUS_TYPE_STRING, &domain,
1517 DBUS_TYPE_STRING, &host_name,
1518 DBUS_TYPE_INT32, &i_aprotocol,
1519 DBUS_TYPE_STRING, &pt,
1520 DBUS_TYPE_UINT16, &port,
1523 append_string_list(reply, txt);
1525 dbus_message_append_args(
1527 DBUS_TYPE_INT32, &i_flags,
1531 dbus_message_set_destination(reply, i->client->name);
1532 dbus_connection_send(server->bus, reply, NULL);
1533 dbus_message_unref(reply);
1536 static DBusHandlerResult msg_async_service_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1538 AsyncServiceResolverInfo *i = userdata;
1544 dbus_error_init(&error);
1546 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1547 dbus_message_get_interface(m),
1548 dbus_message_get_path(m),
1549 dbus_message_get_member(m));
1552 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1553 return handle_introspect(c, m, "ServiceResolver.Introspect");
1555 /* Access control */
1556 if (strcmp(dbus_message_get_sender(m), i->client->name))
1557 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1559 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, "Free")) {
1561 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1562 avahi_log_warn("Error parsing ServiceResolver::Free message");
1566 async_service_resolver_free(i);
1567 return respond_ok(c, m);
1570 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1573 if (dbus_error_is_set(&error))
1574 dbus_error_free(&error);
1576 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1579 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1582 dbus_error_init(&error);
1584 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1585 dbus_message_get_interface(m),
1586 dbus_message_get_path(m),
1587 dbus_message_get_member(m));
1589 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1590 return handle_introspect(c, m, "Server.introspect");
1592 else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1594 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1595 avahi_log_warn("Error parsing Server::GetHostName message");
1599 return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1601 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1603 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1604 avahi_log_warn("Error parsing Server::GetDomainName message");
1608 return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1610 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1612 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1613 avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1617 return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1619 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1621 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1622 avahi_log_warn("Error parsing Server::GetVersionString message");
1626 return respond_string(c, m, PACKAGE_STRING);
1628 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1629 AvahiServerState state;
1631 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1632 avahi_log_warn("Error parsing Server::GetState message");
1636 state = avahi_server_get_state(avahi_server);
1637 return respond_int32(c, m, (int32_t) state);
1639 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetLocalServiceCookie")) {
1641 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1642 avahi_log_warn("Error parsing Server::GetLocalServiceCookie message");
1646 return respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server));
1648 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "IsServiceLocal")) {
1649 int32_t interface, protocol;
1650 char *name, *type, *domain;
1653 if (!dbus_message_get_args(
1655 DBUS_TYPE_INT32, &interface,
1656 DBUS_TYPE_INT32, &protocol,
1657 DBUS_TYPE_STRING, &name,
1658 DBUS_TYPE_STRING, &type,
1659 DBUS_TYPE_STRING, &domain,
1660 DBUS_TYPE_INVALID) || !name || !type || !domain) {
1661 avahi_log_warn("Error parsing Server::IsServiceLocal message");
1665 if ((b = avahi_server_is_service_local(avahi_server, interface, protocol, name, type, domain)) < 0)
1666 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1668 return respond_boolean(c, m, b);
1670 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1675 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1676 avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1680 #ifdef VALGRIND_WORKAROUND
1681 return respond_string(c, m, "blah");
1684 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1685 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1687 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1688 return respond_error(c, m, AVAHI_ERR_OS, txt);
1691 memset(&ifr, 0, sizeof(ifr));
1692 ifr.ifr_ifindex = idx;
1694 if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) {
1696 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1698 return respond_error(c, m, AVAHI_ERR_OS, txt);
1703 return respond_string(c, m, ifr.ifr_name);
1706 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1711 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1712 avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1716 #ifdef VALGRIND_WORKAROUND
1717 return respond_int32(c, m, 1);
1719 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1720 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1722 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1723 return respond_error(c, m, AVAHI_ERR_OS, txt);
1726 memset(&ifr, 0, sizeof(ifr));
1727 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", n);
1729 if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
1731 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1733 return respond_error(c, m, AVAHI_ERR_OS, txt);
1738 return respond_int32(c, m, ifr.ifr_ifindex);
1741 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1744 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1745 avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1749 t = avahi_alternative_host_name(n);
1750 respond_string(c, m, t);
1753 return DBUS_HANDLER_RESULT_HANDLED;
1755 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1758 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1759 avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1763 t = avahi_alternative_service_name(n);
1764 respond_string(c, m, t);
1767 return DBUS_HANDLER_RESULT_HANDLED;
1769 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1772 static const DBusObjectPathVTable vtable = {
1774 msg_entry_group_impl,
1781 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1782 avahi_log_warn("Error parsing Server::EntryGroupNew message");
1786 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1787 avahi_log_warn("Too many clients, client request failed.");
1788 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1791 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1792 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1793 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1796 i = avahi_new(EntryGroupInfo, 1);
1797 i->id = ++client->current_id;
1799 i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1801 AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1802 client->n_objects++;
1804 if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1805 entry_group_free(i);
1806 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1809 dbus_connection_register_object_path(c, i->path, &vtable, i);
1810 return respond_path(c, m, i->path);
1812 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1814 int32_t interface, protocol, aprotocol, flags;
1816 SyncHostNameResolverInfo *i;
1818 if (!dbus_message_get_args(
1820 DBUS_TYPE_INT32, &interface,
1821 DBUS_TYPE_INT32, &protocol,
1822 DBUS_TYPE_STRING, &name,
1823 DBUS_TYPE_INT32, &aprotocol,
1824 DBUS_TYPE_INT32, &flags,
1825 DBUS_TYPE_INVALID) || !name) {
1826 avahi_log_warn("Error parsing Server::ResolveHostName message");
1830 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1831 avahi_log_warn("Too many clients, client request failed.");
1832 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1835 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1836 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1837 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1840 i = avahi_new(SyncHostNameResolverInfo, 1);
1842 i->message = dbus_message_ref(m);
1843 AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i);
1844 client->n_objects++;
1846 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))) {
1847 sync_host_name_resolver_free(i);
1848 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1851 return DBUS_HANDLER_RESULT_HANDLED;
1853 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1855 int32_t interface, protocol, flags;
1857 SyncAddressResolverInfo *i;
1860 if (!dbus_message_get_args(
1862 DBUS_TYPE_INT32, &interface,
1863 DBUS_TYPE_INT32, &protocol,
1864 DBUS_TYPE_STRING, &address,
1865 DBUS_TYPE_INT32, &flags,
1866 DBUS_TYPE_INVALID) || !address) {
1867 avahi_log_warn("Error parsing Server::ResolveAddress message");
1871 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
1872 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
1874 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1875 avahi_log_warn("Too many clients, client request failed.");
1876 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1879 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1880 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1881 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1884 i = avahi_new(SyncAddressResolverInfo, 1);
1886 i->message = dbus_message_ref(m);
1887 AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i);
1888 client->n_objects++;
1890 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, sync_address_resolver_callback, i))) {
1891 sync_address_resolver_free(i);
1892 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1895 return DBUS_HANDLER_RESULT_HANDLED;
1897 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
1899 DomainBrowserInfo *i;
1900 static const DBusObjectPathVTable vtable = {
1902 msg_domain_browser_impl,
1908 int32_t interface, protocol, type, flags;
1911 if (!dbus_message_get_args(
1913 DBUS_TYPE_INT32, &interface,
1914 DBUS_TYPE_INT32, &protocol,
1915 DBUS_TYPE_STRING, &domain,
1916 DBUS_TYPE_INT32, &type,
1917 DBUS_TYPE_INT32, &flags,
1918 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
1919 avahi_log_warn("Error parsing Server::DomainBrowserNew message");
1923 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1924 avahi_log_warn("Too many clients, client request failed.");
1925 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1928 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1929 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1930 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1936 i = avahi_new(DomainBrowserInfo, 1);
1937 i->id = ++client->current_id;
1939 i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
1940 AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
1941 client->n_objects++;
1943 if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, (AvahiLookupFlags) flags, domain_browser_callback, i))) {
1944 domain_browser_free(i);
1945 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1948 dbus_connection_register_object_path(c, i->path, &vtable, i);
1949 return respond_path(c, m, i->path);
1951 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
1953 ServiceTypeBrowserInfo *i;
1954 static const DBusObjectPathVTable vtable = {
1956 msg_service_type_browser_impl,
1962 int32_t interface, protocol, flags;
1965 if (!dbus_message_get_args(
1967 DBUS_TYPE_INT32, &interface,
1968 DBUS_TYPE_INT32, &protocol,
1969 DBUS_TYPE_STRING, &domain,
1970 DBUS_TYPE_INT32, &flags,
1971 DBUS_TYPE_INVALID)) {
1972 avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
1976 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1977 avahi_log_warn("Too many clients, client request failed.");
1978 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1982 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1983 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1984 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1990 i = avahi_new(ServiceTypeBrowserInfo, 1);
1991 i->id = ++client->current_id;
1993 i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
1994 AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
1995 client->n_objects++;
1997 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))) {
1998 service_type_browser_free(i);
1999 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2002 dbus_connection_register_object_path(c, i->path, &vtable, i);
2003 return respond_path(c, m, i->path);
2005 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
2007 ServiceBrowserInfo *i;
2008 static const DBusObjectPathVTable vtable = {
2010 msg_service_browser_impl,
2016 int32_t interface, protocol, flags;
2017 char *domain, *type;
2019 if (!dbus_message_get_args(
2021 DBUS_TYPE_INT32, &interface,
2022 DBUS_TYPE_INT32, &protocol,
2023 DBUS_TYPE_STRING, &type,
2024 DBUS_TYPE_STRING, &domain,
2025 DBUS_TYPE_INT32, &flags,
2026 DBUS_TYPE_INVALID) || !type) {
2027 avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
2031 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2032 avahi_log_warn("Too many clients, client request failed.");
2033 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2037 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2038 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2039 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2045 i = avahi_new(ServiceBrowserInfo, 1);
2046 i->id = ++client->current_id;
2048 i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
2049 AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
2050 client->n_objects++;
2052 if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, (AvahiLookupFlags) flags, service_browser_callback, i))) {
2053 service_browser_free(i);
2054 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2057 dbus_connection_register_object_path(c, i->path, &vtable, i);
2058 return respond_path(c, m, i->path);
2060 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
2062 int32_t interface, protocol, aprotocol, flags;
2063 char *name, *type, *domain;
2064 SyncServiceResolverInfo *i;
2066 if (!dbus_message_get_args(
2068 DBUS_TYPE_INT32, &interface,
2069 DBUS_TYPE_INT32, &protocol,
2070 DBUS_TYPE_STRING, &name,
2071 DBUS_TYPE_STRING, &type,
2072 DBUS_TYPE_STRING, &domain,
2073 DBUS_TYPE_INT32, &aprotocol,
2074 DBUS_TYPE_INT32, &flags,
2075 DBUS_TYPE_INVALID) || !type) {
2076 avahi_log_warn("Error parsing Server::ResolveService message");
2080 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2081 avahi_log_warn("Too many clients, client request failed.");
2082 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2085 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2086 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2087 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2096 i = avahi_new(SyncServiceResolverInfo, 1);
2098 i->message = dbus_message_ref(m);
2099 AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i);
2100 client->n_objects++;
2102 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))) {
2103 sync_service_resolver_free(i);
2104 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2107 return DBUS_HANDLER_RESULT_HANDLED;
2109 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) {
2111 int32_t interface, protocol, aprotocol, flags;
2112 char *name, *type, *domain;
2113 AsyncServiceResolverInfo *i;
2114 static const DBusObjectPathVTable vtable = {
2116 msg_async_service_resolver_impl,
2123 if (!dbus_message_get_args(
2125 DBUS_TYPE_INT32, &interface,
2126 DBUS_TYPE_INT32, &protocol,
2127 DBUS_TYPE_STRING, &name,
2128 DBUS_TYPE_STRING, &type,
2129 DBUS_TYPE_STRING, &domain,
2130 DBUS_TYPE_INT32, &aprotocol,
2131 DBUS_TYPE_INT32, &flags,
2132 DBUS_TYPE_INVALID) || !type) {
2133 avahi_log_warn("Error parsing Server::ServiceResolverNew message");
2137 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2138 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2139 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2142 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2143 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2144 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2153 i = avahi_new(AsyncServiceResolverInfo, 1);
2154 i->id = ++client->current_id;
2156 i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
2157 AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i);
2158 client->n_objects++;
2160 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))) {
2161 async_service_resolver_free(i);
2162 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2165 /* avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */
2167 dbus_connection_register_object_path(c, i->path, &vtable, i);
2168 return respond_path(c, m, i->path);
2170 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew")) {
2172 int32_t interface, protocol, aprotocol, flags;
2174 AsyncHostNameResolverInfo *i;
2175 static const DBusObjectPathVTable vtable = {
2177 msg_async_host_name_resolver_impl,
2184 if (!dbus_message_get_args(
2186 DBUS_TYPE_INT32, &interface,
2187 DBUS_TYPE_INT32, &protocol,
2188 DBUS_TYPE_STRING, &name,
2189 DBUS_TYPE_INT32, &aprotocol,
2190 DBUS_TYPE_INT32, &flags,
2191 DBUS_TYPE_INVALID) || !name) {
2192 avahi_log_warn("Error parsing Server::HostNameResolverNew message");
2196 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2197 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2198 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2201 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2202 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2203 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2206 i = avahi_new(AsyncHostNameResolverInfo, 1);
2207 i->id = ++client->current_id;
2209 i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
2210 AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i);
2211 client->n_objects++;
2213 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))) {
2214 async_host_name_resolver_free(i);
2215 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2218 dbus_connection_register_object_path(c, i->path, &vtable, i);
2219 return respond_path(c, m, i->path);
2221 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew")) {
2223 int32_t interface, protocol, flags;
2225 AsyncAddressResolverInfo *i;
2227 static const DBusObjectPathVTable vtable = {
2229 msg_async_address_resolver_impl,
2236 if (!dbus_message_get_args(
2238 DBUS_TYPE_INT32, &interface,
2239 DBUS_TYPE_INT32, &protocol,
2240 DBUS_TYPE_STRING, &address,
2241 DBUS_TYPE_INT32, &flags,
2242 DBUS_TYPE_INVALID) || !address) {
2243 avahi_log_warn("Error parsing Server::AddressResolverNew message");
2247 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
2248 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
2250 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2251 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2252 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2255 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2256 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2257 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2260 i = avahi_new(AsyncAddressResolverInfo, 1);
2261 i->id = ++client->current_id;
2263 i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
2264 AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i);
2265 client->n_objects++;
2267 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, async_address_resolver_callback, i))) {
2268 async_address_resolver_free(i);
2269 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2272 dbus_connection_register_object_path(c, i->path, &vtable, i);
2273 return respond_path(c, m, i->path);
2276 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
2279 if (dbus_error_is_set(&error))
2280 dbus_error_free(&error);
2282 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2285 void dbus_protocol_server_state_changed(AvahiServerState state) {
2292 m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
2293 t = (int32_t) state;
2294 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
2295 dbus_connection_send(server->bus, m, NULL);
2296 dbus_message_unref(m);
2299 int dbus_protocol_setup(const AvahiPoll *poll_api) {
2302 static const DBusObjectPathVTable server_vtable = {
2311 dbus_error_init(&error);
2313 server = avahi_new(Server, 1);
2314 AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
2315 server->current_id = 0;
2316 server->n_clients = 0;
2318 if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
2319 assert(dbus_error_is_set(&error));
2320 avahi_log_error("dbus_bus_get(): %s", error.message);
2324 if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) {
2325 avahi_log_error("avahi_dbus_connection_glue() failed");
2329 if (dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
2330 if (dbus_error_is_set(&error)) {
2331 avahi_log_error("dbus_bus_request_name(): %s", error.message);
2335 avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'");
2339 if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) {
2340 avahi_log_error("dbus_connection_add_filter() failed");
2344 dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
2346 if (dbus_error_is_set(&error)) {
2347 avahi_log_error("dbus_bus_add_match(): %s", error.message);
2351 if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
2352 avahi_log_error("dbus_connection_register_object_path() failed");
2360 dbus_connection_disconnect(server->bus);
2361 dbus_connection_unref(server->bus);
2364 if (dbus_error_is_set(&error))
2365 dbus_error_free(&error);
2372 void dbus_protocol_shutdown(void) {
2376 while (server->clients)
2377 client_free(server->clients);
2379 assert(server->n_clients == 0);
2382 dbus_connection_disconnect(server->bus);
2383 dbus_connection_unref(server->bus);