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);
755 return respond_ok(c, m);
757 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) {
761 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
762 avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
766 b = !!avahi_s_entry_group_is_empty(i->entry_group);
768 reply = dbus_message_new_method_return(m);
769 dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
770 dbus_connection_send(c, reply, NULL);
771 dbus_message_unref(reply);
773 return DBUS_HANDLER_RESULT_HANDLED;
775 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
776 AvahiEntryGroupState state;
778 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
779 avahi_log_warn("Error parsing EntryGroup::GetState message");
783 state = avahi_s_entry_group_get_state(i->entry_group);
784 return respond_int32(c, m, (int32_t) state);
786 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
787 int32_t interface, protocol;
788 char *type, *name, *domain, *host;
790 AvahiStringList *strlst;
791 DBusMessageIter iter, sub;
794 if (!dbus_message_get_args(
796 DBUS_TYPE_INT32, &interface,
797 DBUS_TYPE_INT32, &protocol,
798 DBUS_TYPE_STRING, &name,
799 DBUS_TYPE_STRING, &type,
800 DBUS_TYPE_STRING, &domain,
801 DBUS_TYPE_STRING, &host,
802 DBUS_TYPE_UINT16, &port,
803 DBUS_TYPE_INVALID) || !type || !name) {
804 avahi_log_warn("Error parsing EntryGroup::AddService message");
808 dbus_message_iter_init(m, &iter);
810 for (j = 0; j < 7; j++)
811 dbus_message_iter_next(&iter);
813 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
814 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY) {
815 avahi_log_warn("Error parsing EntryGroup::AddService message 2");
820 dbus_message_iter_recurse(&iter, &sub);
823 DBusMessageIter sub2;
827 if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
830 assert(at == DBUS_TYPE_ARRAY);
832 if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) {
833 avahi_log_warn("Error parsing EntryGroup::AddService message");
837 dbus_message_iter_recurse(&sub, &sub2);
838 dbus_message_iter_get_fixed_array(&sub2, &k, &n);
839 strlst = avahi_string_list_add_arbitrary(strlst, k, n);
841 dbus_message_iter_next(&sub);
844 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
845 avahi_string_list_free(strlst);
846 avahi_log_warn("Too many entries per entry group, client request failed.");
847 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
850 if (domain && !*domain)
856 if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, host, port, strlst) < 0) {
857 avahi_string_list_free(strlst);
858 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
862 avahi_string_list_free(strlst);
864 return respond_ok(c, m);
866 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
867 int32_t interface, protocol;
868 char *name, *address;
871 if (!dbus_message_get_args(
873 DBUS_TYPE_INT32, &interface,
874 DBUS_TYPE_INT32, &protocol,
875 DBUS_TYPE_STRING, &name,
876 DBUS_TYPE_STRING, &address,
877 DBUS_TYPE_INVALID) || !name || !address) {
878 avahi_log_warn("Error parsing EntryGroup::AddAddress message");
882 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
883 avahi_log_warn("Too many entries per entry group, client request failed.");
884 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
887 if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))) {
888 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
891 if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, 0, name, &a) < 0)
892 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
896 return respond_ok(c, m);
899 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
902 if (dbus_error_is_set(&error))
903 dbus_error_free(&error);
905 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
908 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) {
909 SyncHostNameResolverInfo *i = userdata;
915 if (event == AVAHI_RESOLVER_FOUND) {
916 char t[256], *pt = t;
917 int32_t i_interface, i_protocol, i_aprotocol, i_flags;
921 avahi_address_snprint(t, sizeof(t), a);
923 i_interface = (int32_t) interface;
924 i_protocol = (int32_t) protocol;
925 i_aprotocol = (int32_t) a->proto;
926 i_flags = (int32_t) flags;
928 reply = dbus_message_new_method_return(i->message);
929 dbus_message_append_args(
931 DBUS_TYPE_INT32, &i_interface,
932 DBUS_TYPE_INT32, &i_protocol,
933 DBUS_TYPE_STRING, &host_name,
934 DBUS_TYPE_INT32, &i_aprotocol,
935 DBUS_TYPE_STRING, &pt,
936 DBUS_TYPE_INT32, &i_flags,
939 dbus_connection_send(server->bus, reply, NULL);
940 dbus_message_unref(reply);
942 respond_error(server->bus, i->message, map_resolve_error(event), NULL);
944 sync_host_name_resolver_free(i);
947 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) {
948 SyncAddressResolverInfo *i = userdata;
954 if (event == AVAHI_RESOLVER_FOUND) {
955 char t[256], *pt = t;
956 int32_t i_interface, i_protocol, i_aprotocol, i_flags;
960 avahi_address_snprint(t, sizeof(t), address);
962 i_interface = (int32_t) interface;
963 i_protocol = (int32_t) protocol;
964 i_aprotocol = (int32_t) address->proto;
965 i_flags = (int32_t) flags;
967 reply = dbus_message_new_method_return(i->message);
968 dbus_message_append_args(
970 DBUS_TYPE_INT32, &i_interface,
971 DBUS_TYPE_INT32, &i_protocol,
972 DBUS_TYPE_INT32, &i_aprotocol,
973 DBUS_TYPE_STRING, &pt,
974 DBUS_TYPE_STRING, &host_name,
975 DBUS_TYPE_INT32, &i_flags,
978 dbus_connection_send(server->bus, reply, NULL);
979 dbus_message_unref(reply);
981 respond_error(server->bus, i->message, map_resolve_error(event), NULL);
983 sync_address_resolver_free(i);
986 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
988 DomainBrowserInfo *i = userdata;
994 dbus_error_init(&error);
996 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
997 dbus_message_get_interface(m),
998 dbus_message_get_path(m),
999 dbus_message_get_member(m));
1002 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1003 return handle_introspect(c, m, "DomainBrowser.introspect");
1005 /* Access control */
1006 if (strcmp(dbus_message_get_sender(m), i->client->name))
1007 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1009 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
1011 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1012 avahi_log_warn("Error parsing DomainBrowser::Free message");
1016 domain_browser_free(i);
1017 return respond_ok(c, m);
1021 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1024 if (dbus_error_is_set(&error))
1025 dbus_error_free(&error);
1027 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1030 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1031 DomainBrowserInfo *i = userdata;
1033 int32_t i_interface, i_protocol, i_flags;
1038 i_interface = (int32_t) interface;
1039 i_protocol = (int32_t) protocol;
1040 i_flags = (int32_t) flags;
1042 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, map_browse_signal_name(event));
1044 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1046 dbus_message_append_args(
1048 DBUS_TYPE_INT32, &i_interface,
1049 DBUS_TYPE_INT32, &i_protocol,
1050 DBUS_TYPE_STRING, &domain,
1051 DBUS_TYPE_INT32, &i_flags,
1055 dbus_message_set_destination(m, i->client->name);
1056 dbus_connection_send(server->bus, m, NULL);
1057 dbus_message_unref(m);
1060 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1062 ServiceTypeBrowserInfo *i = userdata;
1068 dbus_error_init(&error);
1070 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1071 dbus_message_get_interface(m),
1072 dbus_message_get_path(m),
1073 dbus_message_get_member(m));
1076 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1077 return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
1079 /* Access control */
1080 if (strcmp(dbus_message_get_sender(m), i->client->name))
1081 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1083 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
1085 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1086 avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
1090 service_type_browser_free(i);
1091 return respond_ok(c, m);
1095 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1098 if (dbus_error_is_set(&error))
1099 dbus_error_free(&error);
1101 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1104 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1105 ServiceTypeBrowserInfo *i = userdata;
1107 int32_t i_interface, i_protocol, i_flags;
1112 i_interface = (int32_t) interface;
1113 i_protocol = (int32_t) protocol;
1114 i_flags = (int32_t) flags;
1116 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, map_browse_signal_name(event));
1118 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1121 dbus_message_append_args(
1123 DBUS_TYPE_INT32, &i_interface,
1124 DBUS_TYPE_INT32, &i_protocol,
1125 DBUS_TYPE_STRING, &type,
1126 DBUS_TYPE_STRING, &domain,
1127 DBUS_TYPE_INT32, &i_flags,
1131 dbus_message_set_destination(m, i->client->name);
1132 dbus_connection_send(server->bus, m, NULL);
1133 dbus_message_unref(m);
1136 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1138 ServiceBrowserInfo *i = userdata;
1144 dbus_error_init(&error);
1146 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1147 dbus_message_get_interface(m),
1148 dbus_message_get_path(m),
1149 dbus_message_get_member(m));
1152 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1153 return handle_introspect(c, m, "ServiceBrowser.Introspect");
1155 /* Access control */
1156 if (strcmp(dbus_message_get_sender(m), i->client->name))
1157 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1159 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
1161 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1162 avahi_log_warn("Error parsing ServiceBrowser::Free message");
1166 service_browser_free(i);
1167 return respond_ok(c, m);
1171 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1174 if (dbus_error_is_set(&error))
1175 dbus_error_free(&error);
1177 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1180 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) {
1181 ServiceBrowserInfo *i = userdata;
1183 int32_t i_interface, i_protocol, i_flags;
1188 i_interface = (int32_t) interface;
1189 i_protocol = (int32_t) protocol;
1190 i_flags = (int32_t) flags;
1192 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, map_browse_signal_name(event));
1194 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1199 dbus_message_append_args(
1201 DBUS_TYPE_INT32, &i_interface,
1202 DBUS_TYPE_INT32, &i_protocol,
1203 DBUS_TYPE_STRING, &name,
1204 DBUS_TYPE_STRING, &type,
1205 DBUS_TYPE_STRING, &domain,
1206 DBUS_TYPE_INT32, &i_flags,
1210 dbus_message_set_destination(m, i->client->name);
1211 dbus_connection_send(server->bus, m, NULL);
1212 dbus_message_unref(m);
1215 static void append_string_list(DBusMessage *reply, AvahiStringList *txt) {
1217 DBusMessageIter iter, sub;
1221 dbus_message_iter_init_append(reply, &iter);
1222 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1224 for (p = txt; p; p = p->next) {
1225 DBusMessageIter sub2;
1226 const uint8_t *data = p->text;
1228 dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1229 dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
1230 dbus_message_iter_close_container(&sub, &sub2);
1233 dbus_message_iter_close_container(&iter, &sub);
1236 static void sync_service_resolver_callback(
1237 AvahiSServiceResolver *r,
1238 AvahiIfIndex interface,
1239 AvahiProtocol protocol,
1240 AvahiResolverEvent event,
1244 const char *host_name,
1245 const AvahiAddress *a,
1247 AvahiStringList *txt,
1248 AvahiLookupResultFlags flags,
1251 SyncServiceResolverInfo *i = userdata;
1256 if (event == AVAHI_RESOLVER_FOUND) {
1257 char t[256], *pt = t;
1258 int32_t i_interface, i_protocol, i_aprotocol, i_flags;
1267 avahi_address_snprint(t, sizeof(t), a);
1269 i_interface = (int32_t) interface;
1270 i_protocol = (int32_t) protocol;
1271 i_aprotocol = (int32_t) a->proto;
1272 i_flags = (int32_t) flags;
1274 reply = dbus_message_new_method_return(i->message);
1275 dbus_message_append_args(
1277 DBUS_TYPE_INT32, &i_interface,
1278 DBUS_TYPE_INT32, &i_protocol,
1279 DBUS_TYPE_STRING, &name,
1280 DBUS_TYPE_STRING, &type,
1281 DBUS_TYPE_STRING, &domain,
1282 DBUS_TYPE_STRING, &host_name,
1283 DBUS_TYPE_INT32, &i_aprotocol,
1284 DBUS_TYPE_STRING, &pt,
1285 DBUS_TYPE_UINT16, &port,
1288 append_string_list(reply, txt);
1290 dbus_message_append_args(
1292 DBUS_TYPE_INT32, &i_flags,
1295 dbus_connection_send(server->bus, reply, NULL);
1296 dbus_message_unref(reply);
1298 respond_error(server->bus, i->message, map_resolve_error(event), NULL);
1300 sync_service_resolver_free(i);
1303 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) {
1304 AsyncAddressResolverInfo *i = userdata;
1310 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, map_browse_signal_name(event));
1312 if (event == AVAHI_RESOLVER_FOUND) {
1313 char t[256], *pt = t;
1314 int32_t i_interface, i_protocol, i_aprotocol, i_flags;
1318 avahi_address_snprint(t, sizeof(t), address);
1320 i_interface = (int32_t) interface;
1321 i_protocol = (int32_t) protocol;
1322 i_aprotocol = (int32_t) address->proto;
1323 i_flags = (int32_t) flags;
1325 dbus_message_append_args(
1327 DBUS_TYPE_INT32, &i_interface,
1328 DBUS_TYPE_INT32, &i_protocol,
1329 DBUS_TYPE_INT32, &i_aprotocol,
1330 DBUS_TYPE_STRING, &pt,
1331 DBUS_TYPE_STRING, &host_name,
1332 DBUS_TYPE_INT32, &i_flags,
1337 dbus_message_set_destination(reply, i->client->name);
1338 dbus_connection_send(server->bus, reply, NULL);
1339 dbus_message_unref(reply);
1342 static DBusHandlerResult msg_async_address_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1344 AsyncAddressResolverInfo *i = userdata;
1350 dbus_error_init(&error);
1352 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1353 dbus_message_get_interface(m),
1354 dbus_message_get_path(m),
1355 dbus_message_get_member(m));
1358 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1359 return handle_introspect(c, m, "AddressResolver.Introspect");
1361 /* Access control */
1362 if (strcmp(dbus_message_get_sender(m), i->client->name))
1363 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1365 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Free")) {
1367 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1368 avahi_log_warn("Error parsing AddressResolver::Free message");
1372 async_address_resolver_free(i);
1373 return respond_ok(c, m);
1377 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1380 if (dbus_error_is_set(&error))
1381 dbus_error_free(&error);
1383 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1386 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) {
1387 AsyncHostNameResolverInfo *i = userdata;
1393 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, map_resolve_signal_name(event));
1395 if (event == AVAHI_RESOLVER_FOUND) {
1396 char t[256], *pt = t;
1397 int32_t i_interface, i_protocol, i_aprotocol, i_flags;
1401 avahi_address_snprint(t, sizeof(t), a);
1403 i_interface = (int32_t) interface;
1404 i_protocol = (int32_t) protocol;
1405 i_aprotocol = (int32_t) a->proto;
1406 i_flags = (int32_t) flags;
1408 dbus_message_append_args(
1410 DBUS_TYPE_INT32, &i_interface,
1411 DBUS_TYPE_INT32, &i_protocol,
1412 DBUS_TYPE_STRING, &host_name,
1413 DBUS_TYPE_INT32, &i_aprotocol,
1414 DBUS_TYPE_STRING, &pt,
1415 DBUS_TYPE_INT32, &i_flags,
1419 dbus_message_set_destination(reply, i->client->name);
1420 dbus_connection_send(server->bus, reply, NULL);
1421 dbus_message_unref(reply);
1424 static DBusHandlerResult msg_async_host_name_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1426 AsyncHostNameResolverInfo *i = userdata;
1432 dbus_error_init(&error);
1434 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1435 dbus_message_get_interface(m),
1436 dbus_message_get_path(m),
1437 dbus_message_get_member(m));
1440 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1441 return handle_introspect(c, m, "HostNameResolver.Introspect");
1443 /* Access control */
1444 if (strcmp(dbus_message_get_sender(m), i->client->name))
1445 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1447 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, "Free")) {
1449 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1450 avahi_log_warn("Error parsing HostNameResolver::Free message");
1454 async_host_name_resolver_free(i);
1455 return respond_ok(c, m);
1458 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1461 if (dbus_error_is_set(&error))
1462 dbus_error_free(&error);
1464 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1467 static void async_service_resolver_callback(
1468 AvahiSServiceResolver *r,
1469 AvahiIfIndex interface,
1470 AvahiProtocol protocol,
1471 AvahiResolverEvent event,
1475 const char *host_name,
1476 const AvahiAddress *a,
1478 AvahiStringList *txt,
1479 AvahiLookupResultFlags flags,
1482 AsyncServiceResolverInfo *i = userdata;
1488 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, map_resolve_signal_name(event));
1490 if (event == AVAHI_RESOLVER_FOUND) {
1491 char t[256], *pt = t;
1492 int32_t i_interface, i_protocol, i_aprotocol, i_flags;
1496 /* avahi_log_debug(__FILE__": [%s] Successfully resolved service <%s.%s.%s>", i->path, name, type, domain); */
1499 avahi_address_snprint(t, sizeof(t), a);
1504 i_interface = (int32_t) interface;
1505 i_protocol = (int32_t) protocol;
1506 i_aprotocol = (int32_t) a->proto;
1507 i_flags = (int32_t) flags;
1509 dbus_message_append_args(
1511 DBUS_TYPE_INT32, &i_interface,
1512 DBUS_TYPE_INT32, &i_protocol,
1513 DBUS_TYPE_STRING, &name,
1514 DBUS_TYPE_STRING, &type,
1515 DBUS_TYPE_STRING, &domain,
1516 DBUS_TYPE_STRING, &host_name,
1517 DBUS_TYPE_INT32, &i_aprotocol,
1518 DBUS_TYPE_STRING, &pt,
1519 DBUS_TYPE_UINT16, &port,
1522 append_string_list(reply, txt);
1524 dbus_message_append_args(
1526 DBUS_TYPE_INT32, &i_flags,
1530 dbus_message_set_destination(reply, i->client->name);
1531 dbus_connection_send(server->bus, reply, NULL);
1532 dbus_message_unref(reply);
1535 static DBusHandlerResult msg_async_service_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1537 AsyncServiceResolverInfo *i = userdata;
1543 dbus_error_init(&error);
1545 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1546 dbus_message_get_interface(m),
1547 dbus_message_get_path(m),
1548 dbus_message_get_member(m));
1551 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1552 return handle_introspect(c, m, "ServiceResolver.Introspect");
1554 /* Access control */
1555 if (strcmp(dbus_message_get_sender(m), i->client->name))
1556 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1558 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, "Free")) {
1560 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1561 avahi_log_warn("Error parsing ServiceResolver::Free message");
1565 async_service_resolver_free(i);
1566 return respond_ok(c, m);
1569 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1572 if (dbus_error_is_set(&error))
1573 dbus_error_free(&error);
1575 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1578 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1581 dbus_error_init(&error);
1583 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1584 dbus_message_get_interface(m),
1585 dbus_message_get_path(m),
1586 dbus_message_get_member(m));
1588 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1589 return handle_introspect(c, m, "Server.introspect");
1591 else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1593 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1594 avahi_log_warn("Error parsing Server::GetHostName message");
1598 return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1600 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1602 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1603 avahi_log_warn("Error parsing Server::GetDomainName message");
1607 return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1609 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1611 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1612 avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1616 return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1618 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1620 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1621 avahi_log_warn("Error parsing Server::GetVersionString message");
1625 return respond_string(c, m, PACKAGE_STRING);
1627 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1628 AvahiServerState state;
1630 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1631 avahi_log_warn("Error parsing Server::GetState message");
1635 state = avahi_server_get_state(avahi_server);
1636 return respond_int32(c, m, (int32_t) state);
1638 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetLocalServiceCookie")) {
1640 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1641 avahi_log_warn("Error parsing Server::GetLocalServiceCookie message");
1645 return respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server));
1647 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "IsServiceLocal")) {
1648 int32_t interface, protocol;
1649 char *name, *type, *domain;
1652 if (!dbus_message_get_args(
1654 DBUS_TYPE_INT32, &interface,
1655 DBUS_TYPE_INT32, &protocol,
1656 DBUS_TYPE_STRING, &name,
1657 DBUS_TYPE_STRING, &type,
1658 DBUS_TYPE_STRING, &domain,
1659 DBUS_TYPE_INVALID) || !name || !type || !domain) {
1660 avahi_log_warn("Error parsing Server::IsServiceLocal message");
1664 if ((b = avahi_server_is_service_local(avahi_server, interface, protocol, name, type, domain)) < 0)
1665 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1667 return respond_boolean(c, m, b);
1669 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1674 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1675 avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1679 #ifdef VALGRIND_WORKAROUND
1680 return respond_string(c, m, "blah");
1683 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1684 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1686 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1687 return respond_error(c, m, AVAHI_ERR_OS, txt);
1690 memset(&ifr, 0, sizeof(ifr));
1691 ifr.ifr_ifindex = idx;
1693 if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) {
1695 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1697 return respond_error(c, m, AVAHI_ERR_OS, txt);
1702 return respond_string(c, m, ifr.ifr_name);
1705 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1710 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1711 avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1715 #ifdef VALGRIND_WORKAROUND
1716 return respond_int32(c, m, 1);
1718 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1719 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1721 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1722 return respond_error(c, m, AVAHI_ERR_OS, txt);
1725 memset(&ifr, 0, sizeof(ifr));
1726 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", n);
1728 if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
1730 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1732 return respond_error(c, m, AVAHI_ERR_OS, txt);
1737 return respond_int32(c, m, ifr.ifr_ifindex);
1740 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1743 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1744 avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1748 t = avahi_alternative_host_name(n);
1749 respond_string(c, m, t);
1752 return DBUS_HANDLER_RESULT_HANDLED;
1754 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1757 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1758 avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1762 t = avahi_alternative_service_name(n);
1763 respond_string(c, m, t);
1766 return DBUS_HANDLER_RESULT_HANDLED;
1768 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1771 static const DBusObjectPathVTable vtable = {
1773 msg_entry_group_impl,
1780 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1781 avahi_log_warn("Error parsing Server::EntryGroupNew message");
1785 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1786 avahi_log_warn("Too many clients, client request failed.");
1787 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1790 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1791 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1792 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1795 i = avahi_new(EntryGroupInfo, 1);
1796 i->id = ++client->current_id;
1798 i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1800 AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1801 client->n_objects++;
1803 if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1804 entry_group_free(i);
1805 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1808 dbus_connection_register_object_path(c, i->path, &vtable, i);
1809 return respond_path(c, m, i->path);
1811 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1813 int32_t interface, protocol, aprotocol, flags;
1815 SyncHostNameResolverInfo *i;
1817 if (!dbus_message_get_args(
1819 DBUS_TYPE_INT32, &interface,
1820 DBUS_TYPE_INT32, &protocol,
1821 DBUS_TYPE_STRING, &name,
1822 DBUS_TYPE_INT32, &aprotocol,
1823 DBUS_TYPE_INT32, &flags,
1824 DBUS_TYPE_INVALID) || !name) {
1825 avahi_log_warn("Error parsing Server::ResolveHostName message");
1829 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1830 avahi_log_warn("Too many clients, client request failed.");
1831 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1834 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1835 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1836 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1839 i = avahi_new(SyncHostNameResolverInfo, 1);
1841 i->message = dbus_message_ref(m);
1842 AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i);
1843 client->n_objects++;
1845 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))) {
1846 sync_host_name_resolver_free(i);
1847 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1850 return DBUS_HANDLER_RESULT_HANDLED;
1852 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1854 int32_t interface, protocol, flags;
1856 SyncAddressResolverInfo *i;
1859 if (!dbus_message_get_args(
1861 DBUS_TYPE_INT32, &interface,
1862 DBUS_TYPE_INT32, &protocol,
1863 DBUS_TYPE_STRING, &address,
1864 DBUS_TYPE_INT32, &flags,
1865 DBUS_TYPE_INVALID) || !address) {
1866 avahi_log_warn("Error parsing Server::ResolveAddress message");
1870 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
1871 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
1873 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1874 avahi_log_warn("Too many clients, client request failed.");
1875 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1878 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1879 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1880 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1883 i = avahi_new(SyncAddressResolverInfo, 1);
1885 i->message = dbus_message_ref(m);
1886 AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i);
1887 client->n_objects++;
1889 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, sync_address_resolver_callback, i))) {
1890 sync_address_resolver_free(i);
1891 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1894 return DBUS_HANDLER_RESULT_HANDLED;
1896 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
1898 DomainBrowserInfo *i;
1899 static const DBusObjectPathVTable vtable = {
1901 msg_domain_browser_impl,
1907 int32_t interface, protocol, type, flags;
1910 if (!dbus_message_get_args(
1912 DBUS_TYPE_INT32, &interface,
1913 DBUS_TYPE_INT32, &protocol,
1914 DBUS_TYPE_STRING, &domain,
1915 DBUS_TYPE_INT32, &type,
1916 DBUS_TYPE_INT32, &flags,
1917 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
1918 avahi_log_warn("Error parsing Server::DomainBrowserNew message");
1922 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1923 avahi_log_warn("Too many clients, client request failed.");
1924 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1927 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1928 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1929 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1935 i = avahi_new(DomainBrowserInfo, 1);
1936 i->id = ++client->current_id;
1938 i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
1939 AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
1940 client->n_objects++;
1942 if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, (AvahiLookupFlags) flags, domain_browser_callback, i))) {
1943 domain_browser_free(i);
1944 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1947 dbus_connection_register_object_path(c, i->path, &vtable, i);
1948 return respond_path(c, m, i->path);
1950 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
1952 ServiceTypeBrowserInfo *i;
1953 static const DBusObjectPathVTable vtable = {
1955 msg_service_type_browser_impl,
1961 int32_t interface, protocol, flags;
1964 if (!dbus_message_get_args(
1966 DBUS_TYPE_INT32, &interface,
1967 DBUS_TYPE_INT32, &protocol,
1968 DBUS_TYPE_STRING, &domain,
1969 DBUS_TYPE_INT32, &flags,
1970 DBUS_TYPE_INVALID)) {
1971 avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
1975 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1976 avahi_log_warn("Too many clients, client request failed.");
1977 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1981 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1982 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1983 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1989 i = avahi_new(ServiceTypeBrowserInfo, 1);
1990 i->id = ++client->current_id;
1992 i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
1993 AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
1994 client->n_objects++;
1996 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))) {
1997 service_type_browser_free(i);
1998 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2001 dbus_connection_register_object_path(c, i->path, &vtable, i);
2002 return respond_path(c, m, i->path);
2004 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
2006 ServiceBrowserInfo *i;
2007 static const DBusObjectPathVTable vtable = {
2009 msg_service_browser_impl,
2015 int32_t interface, protocol, flags;
2016 char *domain, *type;
2018 if (!dbus_message_get_args(
2020 DBUS_TYPE_INT32, &interface,
2021 DBUS_TYPE_INT32, &protocol,
2022 DBUS_TYPE_STRING, &type,
2023 DBUS_TYPE_STRING, &domain,
2024 DBUS_TYPE_INT32, &flags,
2025 DBUS_TYPE_INVALID) || !type) {
2026 avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
2030 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2031 avahi_log_warn("Too many clients, client request failed.");
2032 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2036 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2037 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2038 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2044 i = avahi_new(ServiceBrowserInfo, 1);
2045 i->id = ++client->current_id;
2047 i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
2048 AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
2049 client->n_objects++;
2051 if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, (AvahiLookupFlags) flags, service_browser_callback, i))) {
2052 service_browser_free(i);
2053 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2056 dbus_connection_register_object_path(c, i->path, &vtable, i);
2057 return respond_path(c, m, i->path);
2059 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
2061 int32_t interface, protocol, aprotocol, flags;
2062 char *name, *type, *domain;
2063 SyncServiceResolverInfo *i;
2065 if (!dbus_message_get_args(
2067 DBUS_TYPE_INT32, &interface,
2068 DBUS_TYPE_INT32, &protocol,
2069 DBUS_TYPE_STRING, &name,
2070 DBUS_TYPE_STRING, &type,
2071 DBUS_TYPE_STRING, &domain,
2072 DBUS_TYPE_INT32, &aprotocol,
2073 DBUS_TYPE_INT32, &flags,
2074 DBUS_TYPE_INVALID) || !type) {
2075 avahi_log_warn("Error parsing Server::ResolveService message");
2079 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2080 avahi_log_warn("Too many clients, client request failed.");
2081 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2084 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2085 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2086 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2095 i = avahi_new(SyncServiceResolverInfo, 1);
2097 i->message = dbus_message_ref(m);
2098 AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i);
2099 client->n_objects++;
2101 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))) {
2102 sync_service_resolver_free(i);
2103 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2106 return DBUS_HANDLER_RESULT_HANDLED;
2108 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) {
2110 int32_t interface, protocol, aprotocol, flags;
2111 char *name, *type, *domain;
2112 AsyncServiceResolverInfo *i;
2113 static const DBusObjectPathVTable vtable = {
2115 msg_async_service_resolver_impl,
2122 if (!dbus_message_get_args(
2124 DBUS_TYPE_INT32, &interface,
2125 DBUS_TYPE_INT32, &protocol,
2126 DBUS_TYPE_STRING, &name,
2127 DBUS_TYPE_STRING, &type,
2128 DBUS_TYPE_STRING, &domain,
2129 DBUS_TYPE_INT32, &aprotocol,
2130 DBUS_TYPE_INT32, &flags,
2131 DBUS_TYPE_INVALID) || !type) {
2132 avahi_log_warn("Error parsing Server::ServiceResolverNew message");
2136 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2137 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2138 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2141 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2142 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2143 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2152 i = avahi_new(AsyncServiceResolverInfo, 1);
2153 i->id = ++client->current_id;
2155 i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
2156 AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i);
2157 client->n_objects++;
2159 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))) {
2160 async_service_resolver_free(i);
2161 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2164 /* avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */
2166 dbus_connection_register_object_path(c, i->path, &vtable, i);
2167 return respond_path(c, m, i->path);
2169 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew")) {
2171 int32_t interface, protocol, aprotocol, flags;
2173 AsyncHostNameResolverInfo *i;
2174 static const DBusObjectPathVTable vtable = {
2176 msg_async_host_name_resolver_impl,
2183 if (!dbus_message_get_args(
2185 DBUS_TYPE_INT32, &interface,
2186 DBUS_TYPE_INT32, &protocol,
2187 DBUS_TYPE_STRING, &name,
2188 DBUS_TYPE_INT32, &aprotocol,
2189 DBUS_TYPE_INT32, &flags,
2190 DBUS_TYPE_INVALID) || !name) {
2191 avahi_log_warn("Error parsing Server::HostNameResolverNew message");
2195 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2196 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2197 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2200 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2201 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2202 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2205 i = avahi_new(AsyncHostNameResolverInfo, 1);
2206 i->id = ++client->current_id;
2208 i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
2209 AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i);
2210 client->n_objects++;
2212 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))) {
2213 async_host_name_resolver_free(i);
2214 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2217 dbus_connection_register_object_path(c, i->path, &vtable, i);
2218 return respond_path(c, m, i->path);
2220 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew")) {
2222 int32_t interface, protocol, flags;
2224 AsyncAddressResolverInfo *i;
2226 static const DBusObjectPathVTable vtable = {
2228 msg_async_address_resolver_impl,
2235 if (!dbus_message_get_args(
2237 DBUS_TYPE_INT32, &interface,
2238 DBUS_TYPE_INT32, &protocol,
2239 DBUS_TYPE_STRING, &address,
2240 DBUS_TYPE_INT32, &flags,
2241 DBUS_TYPE_INVALID) || !address) {
2242 avahi_log_warn("Error parsing Server::AddressResolverNew message");
2246 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
2247 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
2249 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2250 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2251 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2254 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2255 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2256 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2259 i = avahi_new(AsyncAddressResolverInfo, 1);
2260 i->id = ++client->current_id;
2262 i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
2263 AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i);
2264 client->n_objects++;
2266 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, async_address_resolver_callback, i))) {
2267 async_address_resolver_free(i);
2268 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2271 dbus_connection_register_object_path(c, i->path, &vtable, i);
2272 return respond_path(c, m, i->path);
2275 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
2278 if (dbus_error_is_set(&error))
2279 dbus_error_free(&error);
2281 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2284 void dbus_protocol_server_state_changed(AvahiServerState state) {
2291 m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
2292 t = (int32_t) state;
2293 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
2294 dbus_connection_send(server->bus, m, NULL);
2295 dbus_message_unref(m);
2298 int dbus_protocol_setup(const AvahiPoll *poll_api) {
2301 static const DBusObjectPathVTable server_vtable = {
2310 dbus_error_init(&error);
2312 server = avahi_new(Server, 1);
2313 AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
2314 server->current_id = 0;
2315 server->n_clients = 0;
2317 if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
2318 assert(dbus_error_is_set(&error));
2319 avahi_log_error("dbus_bus_get(): %s", error.message);
2323 if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) {
2324 avahi_log_error("avahi_dbus_connection_glue() failed");
2328 if (dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
2329 if (dbus_error_is_set(&error)) {
2330 avahi_log_error("dbus_bus_request_name(): %s", error.message);
2334 avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'");
2338 if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) {
2339 avahi_log_error("dbus_connection_add_filter() failed");
2343 dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
2345 if (dbus_error_is_set(&error)) {
2346 avahi_log_error("dbus_bus_add_match(): %s", error.message);
2350 if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
2351 avahi_log_error("dbus_connection_register_object_path() failed");
2359 dbus_connection_disconnect(server->bus);
2360 dbus_connection_unref(server->bus);
2363 if (dbus_error_is_set(&error))
2364 dbus_error_free(&error);
2371 void dbus_protocol_shutdown(void) {
2375 while (server->clients)
2376 client_free(server->clients);
2378 assert(server->n_clients == 0);
2381 dbus_connection_disconnect(server->bus);
2382 dbus_connection_unref(server->bus);