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;
790 char *type, *name, *domain, *host;
792 AvahiStringList *strlst;
793 DBusMessageIter iter, sub;
796 if (!dbus_message_get_args(
798 DBUS_TYPE_INT32, &interface,
799 DBUS_TYPE_INT32, &protocol,
800 DBUS_TYPE_UINT32, &flags,
801 DBUS_TYPE_STRING, &name,
802 DBUS_TYPE_STRING, &type,
803 DBUS_TYPE_STRING, &domain,
804 DBUS_TYPE_STRING, &host,
805 DBUS_TYPE_UINT16, &port,
806 DBUS_TYPE_INVALID) || !type || !name) {
807 avahi_log_warn("Error parsing EntryGroup::AddService message");
811 dbus_message_iter_init(m, &iter);
813 for (j = 0; j < 8; j++)
814 dbus_message_iter_next(&iter);
816 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
817 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY) {
818 avahi_log_warn("Error parsing EntryGroup::AddService message 2");
823 dbus_message_iter_recurse(&iter, &sub);
826 DBusMessageIter sub2;
830 if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
833 assert(at == DBUS_TYPE_ARRAY);
835 if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) {
836 avahi_log_warn("Error parsing EntryGroup::AddService message");
840 dbus_message_iter_recurse(&sub, &sub2);
841 dbus_message_iter_get_fixed_array(&sub2, &k, &n);
842 strlst = avahi_string_list_add_arbitrary(strlst, k, n);
844 dbus_message_iter_next(&sub);
847 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
848 avahi_string_list_free(strlst);
849 avahi_log_warn("Too many entries per entry group, client request failed.");
850 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
853 if (domain && !*domain)
859 if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, host, port, strlst) < 0) {
860 avahi_string_list_free(strlst);
861 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
865 avahi_string_list_free(strlst);
867 return respond_ok(c, m);
869 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddServiceSubtype")) {
871 int32_t interface, protocol;
873 char *type, *name, *domain, *subtype;
875 if (!dbus_message_get_args(
877 DBUS_TYPE_INT32, &interface,
878 DBUS_TYPE_INT32, &protocol,
879 DBUS_TYPE_UINT32, &flags,
880 DBUS_TYPE_STRING, &name,
881 DBUS_TYPE_STRING, &type,
882 DBUS_TYPE_STRING, &domain,
883 DBUS_TYPE_STRING, &subtype,
884 DBUS_TYPE_INVALID) || !type || !name || !subtype) {
885 avahi_log_warn("Error parsing EntryGroup::AddServiceSubtype message");
889 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
890 avahi_log_warn("Too many entries per entry group, client request failed.");
891 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
894 if (domain && !*domain)
897 if (avahi_server_add_service_subtype(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, subtype) < 0)
898 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
902 return respond_ok(c, m);
904 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
905 int32_t interface, protocol;
907 char *name, *address;
910 if (!dbus_message_get_args(
912 DBUS_TYPE_INT32, &interface,
913 DBUS_TYPE_INT32, &protocol,
914 DBUS_TYPE_UINT32, &flags,
915 DBUS_TYPE_STRING, &name,
916 DBUS_TYPE_STRING, &address,
917 DBUS_TYPE_INVALID) || !name || !address) {
918 avahi_log_warn("Error parsing EntryGroup::AddAddress message");
922 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
923 avahi_log_warn("Too many entries per entry group, client request failed.");
924 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
927 if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))) {
928 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
931 if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, &a) < 0)
932 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
936 return respond_ok(c, m);
939 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
942 if (dbus_error_is_set(&error))
943 dbus_error_free(&error);
945 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
948 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) {
949 SyncHostNameResolverInfo *i = userdata;
955 if (event == AVAHI_RESOLVER_FOUND) {
956 char t[256], *pt = t;
957 int32_t i_interface, i_protocol, i_aprotocol;
962 avahi_address_snprint(t, sizeof(t), a);
964 i_interface = (int32_t) interface;
965 i_protocol = (int32_t) protocol;
966 i_aprotocol = (int32_t) a->proto;
967 u_flags = (uint32_t) flags;
969 reply = dbus_message_new_method_return(i->message);
970 dbus_message_append_args(
972 DBUS_TYPE_INT32, &i_interface,
973 DBUS_TYPE_INT32, &i_protocol,
974 DBUS_TYPE_STRING, &host_name,
975 DBUS_TYPE_INT32, &i_aprotocol,
976 DBUS_TYPE_STRING, &pt,
977 DBUS_TYPE_UINT32, &u_flags,
980 dbus_connection_send(server->bus, reply, NULL);
981 dbus_message_unref(reply);
983 respond_error(server->bus, i->message, map_resolve_error(event), NULL);
985 sync_host_name_resolver_free(i);
988 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) {
989 SyncAddressResolverInfo *i = userdata;
995 if (event == AVAHI_RESOLVER_FOUND) {
996 char t[256], *pt = t;
997 int32_t i_interface, i_protocol, i_aprotocol;
1002 avahi_address_snprint(t, sizeof(t), address);
1004 i_interface = (int32_t) interface;
1005 i_protocol = (int32_t) protocol;
1006 i_aprotocol = (int32_t) address->proto;
1007 u_flags = (uint32_t) flags;
1009 reply = dbus_message_new_method_return(i->message);
1010 dbus_message_append_args(
1012 DBUS_TYPE_INT32, &i_interface,
1013 DBUS_TYPE_INT32, &i_protocol,
1014 DBUS_TYPE_INT32, &i_aprotocol,
1015 DBUS_TYPE_STRING, &pt,
1016 DBUS_TYPE_STRING, &host_name,
1017 DBUS_TYPE_UINT32, &u_flags,
1020 dbus_connection_send(server->bus, reply, NULL);
1021 dbus_message_unref(reply);
1023 respond_error(server->bus, i->message, map_resolve_error(event), NULL);
1025 sync_address_resolver_free(i);
1028 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1030 DomainBrowserInfo *i = userdata;
1036 dbus_error_init(&error);
1038 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1039 dbus_message_get_interface(m),
1040 dbus_message_get_path(m),
1041 dbus_message_get_member(m));
1044 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1045 return handle_introspect(c, m, "DomainBrowser.introspect");
1047 /* Access control */
1048 if (strcmp(dbus_message_get_sender(m), i->client->name))
1049 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1051 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
1053 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1054 avahi_log_warn("Error parsing DomainBrowser::Free message");
1058 domain_browser_free(i);
1059 return respond_ok(c, m);
1063 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1066 if (dbus_error_is_set(&error))
1067 dbus_error_free(&error);
1069 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1072 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1073 DomainBrowserInfo *i = userdata;
1075 int32_t i_interface, i_protocol;
1081 i_interface = (int32_t) interface;
1082 i_protocol = (int32_t) protocol;
1083 u_flags = (uint32_t) flags;
1085 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, map_browse_signal_name(event));
1087 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1089 dbus_message_append_args(
1091 DBUS_TYPE_INT32, &i_interface,
1092 DBUS_TYPE_INT32, &i_protocol,
1093 DBUS_TYPE_STRING, &domain,
1094 DBUS_TYPE_UINT32, &u_flags,
1098 dbus_message_set_destination(m, i->client->name);
1099 dbus_connection_send(server->bus, m, NULL);
1100 dbus_message_unref(m);
1103 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1105 ServiceTypeBrowserInfo *i = userdata;
1111 dbus_error_init(&error);
1113 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1114 dbus_message_get_interface(m),
1115 dbus_message_get_path(m),
1116 dbus_message_get_member(m));
1119 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1120 return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
1122 /* Access control */
1123 if (strcmp(dbus_message_get_sender(m), i->client->name))
1124 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1126 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
1128 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1129 avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
1133 service_type_browser_free(i);
1134 return respond_ok(c, m);
1138 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1141 if (dbus_error_is_set(&error))
1142 dbus_error_free(&error);
1144 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1147 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1148 ServiceTypeBrowserInfo *i = userdata;
1150 int32_t i_interface, i_protocol;
1156 i_interface = (int32_t) interface;
1157 i_protocol = (int32_t) protocol;
1158 u_flags = (uint32_t) flags;
1160 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, map_browse_signal_name(event));
1162 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1165 dbus_message_append_args(
1167 DBUS_TYPE_INT32, &i_interface,
1168 DBUS_TYPE_INT32, &i_protocol,
1169 DBUS_TYPE_STRING, &type,
1170 DBUS_TYPE_STRING, &domain,
1171 DBUS_TYPE_UINT32, &u_flags,
1175 dbus_message_set_destination(m, i->client->name);
1176 dbus_connection_send(server->bus, m, NULL);
1177 dbus_message_unref(m);
1180 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1182 ServiceBrowserInfo *i = userdata;
1188 dbus_error_init(&error);
1190 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1191 dbus_message_get_interface(m),
1192 dbus_message_get_path(m),
1193 dbus_message_get_member(m));
1196 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1197 return handle_introspect(c, m, "ServiceBrowser.Introspect");
1199 /* Access control */
1200 if (strcmp(dbus_message_get_sender(m), i->client->name))
1201 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1203 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
1205 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1206 avahi_log_warn("Error parsing ServiceBrowser::Free message");
1210 service_browser_free(i);
1211 return respond_ok(c, m);
1215 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1218 if (dbus_error_is_set(&error))
1219 dbus_error_free(&error);
1221 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1224 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) {
1225 ServiceBrowserInfo *i = userdata;
1227 int32_t i_interface, i_protocol;
1233 i_interface = (int32_t) interface;
1234 i_protocol = (int32_t) protocol;
1235 u_flags = (uint32_t) flags;
1237 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, map_browse_signal_name(event));
1239 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1244 dbus_message_append_args(
1246 DBUS_TYPE_INT32, &i_interface,
1247 DBUS_TYPE_INT32, &i_protocol,
1248 DBUS_TYPE_STRING, &name,
1249 DBUS_TYPE_STRING, &type,
1250 DBUS_TYPE_STRING, &domain,
1251 DBUS_TYPE_UINT32, &u_flags,
1255 dbus_message_set_destination(m, i->client->name);
1256 dbus_connection_send(server->bus, m, NULL);
1257 dbus_message_unref(m);
1260 static void append_string_list(DBusMessage *reply, AvahiStringList *txt) {
1262 DBusMessageIter iter, sub;
1266 dbus_message_iter_init_append(reply, &iter);
1267 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1269 for (p = txt; p; p = p->next) {
1270 DBusMessageIter sub2;
1271 const uint8_t *data = p->text;
1273 dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1274 dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
1275 dbus_message_iter_close_container(&sub, &sub2);
1278 dbus_message_iter_close_container(&iter, &sub);
1281 static void sync_service_resolver_callback(
1282 AvahiSServiceResolver *r,
1283 AvahiIfIndex interface,
1284 AvahiProtocol protocol,
1285 AvahiResolverEvent event,
1289 const char *host_name,
1290 const AvahiAddress *a,
1292 AvahiStringList *txt,
1293 AvahiLookupResultFlags flags,
1296 SyncServiceResolverInfo *i = userdata;
1301 if (event == AVAHI_RESOLVER_FOUND) {
1302 char t[256], *pt = t;
1303 int32_t i_interface, i_protocol, i_aprotocol;
1313 avahi_address_snprint(t, sizeof(t), a);
1315 i_interface = (int32_t) interface;
1316 i_protocol = (int32_t) protocol;
1317 i_aprotocol = (int32_t) a->proto;
1318 u_flags = (uint32_t) flags;
1320 reply = dbus_message_new_method_return(i->message);
1321 dbus_message_append_args(
1323 DBUS_TYPE_INT32, &i_interface,
1324 DBUS_TYPE_INT32, &i_protocol,
1325 DBUS_TYPE_STRING, &name,
1326 DBUS_TYPE_STRING, &type,
1327 DBUS_TYPE_STRING, &domain,
1328 DBUS_TYPE_STRING, &host_name,
1329 DBUS_TYPE_INT32, &i_aprotocol,
1330 DBUS_TYPE_STRING, &pt,
1331 DBUS_TYPE_UINT16, &port,
1334 append_string_list(reply, txt);
1336 dbus_message_append_args(
1338 DBUS_TYPE_UINT32, &u_flags,
1341 dbus_connection_send(server->bus, reply, NULL);
1342 dbus_message_unref(reply);
1344 respond_error(server->bus, i->message, map_resolve_error(event), NULL);
1346 sync_service_resolver_free(i);
1349 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) {
1350 AsyncAddressResolverInfo *i = userdata;
1356 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, map_browse_signal_name(event));
1358 if (event == AVAHI_RESOLVER_FOUND) {
1359 char t[256], *pt = t;
1360 int32_t i_interface, i_protocol, i_aprotocol;
1365 avahi_address_snprint(t, sizeof(t), address);
1367 i_interface = (int32_t) interface;
1368 i_protocol = (int32_t) protocol;
1369 i_aprotocol = (int32_t) address->proto;
1370 u_flags = (uint32_t) flags;
1372 dbus_message_append_args(
1374 DBUS_TYPE_INT32, &i_interface,
1375 DBUS_TYPE_INT32, &i_protocol,
1376 DBUS_TYPE_INT32, &i_aprotocol,
1377 DBUS_TYPE_STRING, &pt,
1378 DBUS_TYPE_STRING, &host_name,
1379 DBUS_TYPE_UINT32, &u_flags,
1384 dbus_message_set_destination(reply, i->client->name);
1385 dbus_connection_send(server->bus, reply, NULL);
1386 dbus_message_unref(reply);
1389 static DBusHandlerResult msg_async_address_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1391 AsyncAddressResolverInfo *i = userdata;
1397 dbus_error_init(&error);
1399 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1400 dbus_message_get_interface(m),
1401 dbus_message_get_path(m),
1402 dbus_message_get_member(m));
1405 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1406 return handle_introspect(c, m, "AddressResolver.Introspect");
1408 /* Access control */
1409 if (strcmp(dbus_message_get_sender(m), i->client->name))
1410 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1412 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Free")) {
1414 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1415 avahi_log_warn("Error parsing AddressResolver::Free message");
1419 async_address_resolver_free(i);
1420 return respond_ok(c, m);
1424 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1427 if (dbus_error_is_set(&error))
1428 dbus_error_free(&error);
1430 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1433 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) {
1434 AsyncHostNameResolverInfo *i = userdata;
1440 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, map_resolve_signal_name(event));
1442 if (event == AVAHI_RESOLVER_FOUND) {
1443 char t[256], *pt = t;
1444 int32_t i_interface, i_protocol, i_aprotocol;
1449 avahi_address_snprint(t, sizeof(t), a);
1451 i_interface = (int32_t) interface;
1452 i_protocol = (int32_t) protocol;
1453 i_aprotocol = (int32_t) a->proto;
1454 u_flags = (uint32_t) flags;
1456 dbus_message_append_args(
1458 DBUS_TYPE_INT32, &i_interface,
1459 DBUS_TYPE_INT32, &i_protocol,
1460 DBUS_TYPE_STRING, &host_name,
1461 DBUS_TYPE_INT32, &i_aprotocol,
1462 DBUS_TYPE_STRING, &pt,
1463 DBUS_TYPE_UINT32, &u_flags,
1467 dbus_message_set_destination(reply, i->client->name);
1468 dbus_connection_send(server->bus, reply, NULL);
1469 dbus_message_unref(reply);
1472 static DBusHandlerResult msg_async_host_name_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1474 AsyncHostNameResolverInfo *i = userdata;
1480 dbus_error_init(&error);
1482 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1483 dbus_message_get_interface(m),
1484 dbus_message_get_path(m),
1485 dbus_message_get_member(m));
1488 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1489 return handle_introspect(c, m, "HostNameResolver.Introspect");
1491 /* Access control */
1492 if (strcmp(dbus_message_get_sender(m), i->client->name))
1493 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1495 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, "Free")) {
1497 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1498 avahi_log_warn("Error parsing HostNameResolver::Free message");
1502 async_host_name_resolver_free(i);
1503 return respond_ok(c, m);
1506 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1509 if (dbus_error_is_set(&error))
1510 dbus_error_free(&error);
1512 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1515 static void async_service_resolver_callback(
1516 AvahiSServiceResolver *r,
1517 AvahiIfIndex interface,
1518 AvahiProtocol protocol,
1519 AvahiResolverEvent event,
1523 const char *host_name,
1524 const AvahiAddress *a,
1526 AvahiStringList *txt,
1527 AvahiLookupResultFlags flags,
1530 AsyncServiceResolverInfo *i = userdata;
1536 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, map_resolve_signal_name(event));
1538 if (event == AVAHI_RESOLVER_FOUND) {
1539 char t[256], *pt = t;
1540 int32_t i_interface, i_protocol, i_aprotocol;
1545 /* avahi_log_debug(__FILE__": [%s] Successfully resolved service <%s.%s.%s>", i->path, name, type, domain); */
1548 avahi_address_snprint(t, sizeof(t), a);
1553 i_interface = (int32_t) interface;
1554 i_protocol = (int32_t) protocol;
1555 i_aprotocol = (int32_t) a->proto;
1556 u_flags = (uint32_t) flags;
1558 dbus_message_append_args(
1560 DBUS_TYPE_INT32, &i_interface,
1561 DBUS_TYPE_INT32, &i_protocol,
1562 DBUS_TYPE_STRING, &name,
1563 DBUS_TYPE_STRING, &type,
1564 DBUS_TYPE_STRING, &domain,
1565 DBUS_TYPE_STRING, &host_name,
1566 DBUS_TYPE_INT32, &i_aprotocol,
1567 DBUS_TYPE_STRING, &pt,
1568 DBUS_TYPE_UINT16, &port,
1571 append_string_list(reply, txt);
1573 dbus_message_append_args(
1575 DBUS_TYPE_UINT32, &u_flags,
1579 dbus_message_set_destination(reply, i->client->name);
1580 dbus_connection_send(server->bus, reply, NULL);
1581 dbus_message_unref(reply);
1584 static DBusHandlerResult msg_async_service_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1586 AsyncServiceResolverInfo *i = userdata;
1592 dbus_error_init(&error);
1594 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1595 dbus_message_get_interface(m),
1596 dbus_message_get_path(m),
1597 dbus_message_get_member(m));
1600 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1601 return handle_introspect(c, m, "ServiceResolver.Introspect");
1603 /* Access control */
1604 if (strcmp(dbus_message_get_sender(m), i->client->name))
1605 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1607 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, "Free")) {
1609 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1610 avahi_log_warn("Error parsing ServiceResolver::Free message");
1614 async_service_resolver_free(i);
1615 return respond_ok(c, m);
1618 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1621 if (dbus_error_is_set(&error))
1622 dbus_error_free(&error);
1624 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1627 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1630 dbus_error_init(&error);
1632 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1633 dbus_message_get_interface(m),
1634 dbus_message_get_path(m),
1635 dbus_message_get_member(m));
1637 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1638 return handle_introspect(c, m, "Server.introspect");
1640 else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1642 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1643 avahi_log_warn("Error parsing Server::GetHostName message");
1647 return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1649 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1651 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1652 avahi_log_warn("Error parsing Server::GetDomainName message");
1656 return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1658 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1660 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1661 avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1665 return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1667 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1669 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1670 avahi_log_warn("Error parsing Server::GetVersionString message");
1674 return respond_string(c, m, PACKAGE_STRING);
1676 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1677 AvahiServerState state;
1679 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1680 avahi_log_warn("Error parsing Server::GetState message");
1684 state = avahi_server_get_state(avahi_server);
1685 return respond_int32(c, m, (int32_t) state);
1687 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetLocalServiceCookie")) {
1689 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1690 avahi_log_warn("Error parsing Server::GetLocalServiceCookie message");
1694 return respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server));
1696 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "IsServiceLocal")) {
1697 int32_t interface, protocol;
1698 char *name, *type, *domain;
1701 if (!dbus_message_get_args(
1703 DBUS_TYPE_INT32, &interface,
1704 DBUS_TYPE_INT32, &protocol,
1705 DBUS_TYPE_STRING, &name,
1706 DBUS_TYPE_STRING, &type,
1707 DBUS_TYPE_STRING, &domain,
1708 DBUS_TYPE_INVALID) || !name || !type || !domain) {
1709 avahi_log_warn("Error parsing Server::IsServiceLocal message");
1713 if ((b = avahi_server_is_service_local(avahi_server, interface, protocol, name, type, domain)) < 0)
1714 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1716 return respond_boolean(c, m, b);
1718 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1723 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1724 avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1728 #ifdef VALGRIND_WORKAROUND
1729 return respond_string(c, m, "blah");
1732 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1733 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1735 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1736 return respond_error(c, m, AVAHI_ERR_OS, txt);
1739 memset(&ifr, 0, sizeof(ifr));
1740 ifr.ifr_ifindex = idx;
1742 if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) {
1744 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1746 return respond_error(c, m, AVAHI_ERR_OS, txt);
1751 return respond_string(c, m, ifr.ifr_name);
1754 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1759 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1760 avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1764 #ifdef VALGRIND_WORKAROUND
1765 return respond_int32(c, m, 1);
1767 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1768 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1770 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1771 return respond_error(c, m, AVAHI_ERR_OS, txt);
1774 memset(&ifr, 0, sizeof(ifr));
1775 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", n);
1777 if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
1779 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1781 return respond_error(c, m, AVAHI_ERR_OS, txt);
1786 return respond_int32(c, m, ifr.ifr_ifindex);
1789 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1792 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1793 avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1797 t = avahi_alternative_host_name(n);
1798 respond_string(c, m, t);
1801 return DBUS_HANDLER_RESULT_HANDLED;
1803 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1806 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1807 avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1811 t = avahi_alternative_service_name(n);
1812 respond_string(c, m, t);
1815 return DBUS_HANDLER_RESULT_HANDLED;
1817 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1820 static const DBusObjectPathVTable vtable = {
1822 msg_entry_group_impl,
1829 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1830 avahi_log_warn("Error parsing Server::EntryGroupNew message");
1834 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1835 avahi_log_warn("Too many clients, client request failed.");
1836 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1839 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1840 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1841 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1844 i = avahi_new(EntryGroupInfo, 1);
1845 i->id = ++client->current_id;
1847 i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1849 AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1850 client->n_objects++;
1852 if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1853 entry_group_free(i);
1854 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1857 dbus_connection_register_object_path(c, i->path, &vtable, i);
1858 return respond_path(c, m, i->path);
1860 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1862 int32_t interface, protocol, aprotocol;
1865 SyncHostNameResolverInfo *i;
1867 if (!dbus_message_get_args(
1869 DBUS_TYPE_INT32, &interface,
1870 DBUS_TYPE_INT32, &protocol,
1871 DBUS_TYPE_STRING, &name,
1872 DBUS_TYPE_INT32, &aprotocol,
1873 DBUS_TYPE_UINT32, &flags,
1874 DBUS_TYPE_INVALID) || !name) {
1875 avahi_log_warn("Error parsing Server::ResolveHostName message");
1879 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1880 avahi_log_warn("Too many clients, client request failed.");
1881 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1884 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1885 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1886 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1889 i = avahi_new(SyncHostNameResolverInfo, 1);
1891 i->message = dbus_message_ref(m);
1892 AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i);
1893 client->n_objects++;
1895 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))) {
1896 sync_host_name_resolver_free(i);
1897 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1900 return DBUS_HANDLER_RESULT_HANDLED;
1902 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1904 int32_t interface, protocol;
1907 SyncAddressResolverInfo *i;
1910 if (!dbus_message_get_args(
1912 DBUS_TYPE_INT32, &interface,
1913 DBUS_TYPE_INT32, &protocol,
1914 DBUS_TYPE_STRING, &address,
1915 DBUS_TYPE_UINT32, &flags,
1916 DBUS_TYPE_INVALID) || !address) {
1917 avahi_log_warn("Error parsing Server::ResolveAddress message");
1921 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
1922 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
1924 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1925 avahi_log_warn("Too many clients, client request failed.");
1926 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1929 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1930 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1931 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1934 i = avahi_new(SyncAddressResolverInfo, 1);
1936 i->message = dbus_message_ref(m);
1937 AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i);
1938 client->n_objects++;
1940 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, sync_address_resolver_callback, i))) {
1941 sync_address_resolver_free(i);
1942 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1945 return DBUS_HANDLER_RESULT_HANDLED;
1947 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
1949 DomainBrowserInfo *i;
1950 static const DBusObjectPathVTable vtable = {
1952 msg_domain_browser_impl,
1958 int32_t interface, protocol, type;
1962 if (!dbus_message_get_args(
1964 DBUS_TYPE_INT32, &interface,
1965 DBUS_TYPE_INT32, &protocol,
1966 DBUS_TYPE_STRING, &domain,
1967 DBUS_TYPE_INT32, &type,
1968 DBUS_TYPE_UINT32, &flags,
1969 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
1970 avahi_log_warn("Error parsing Server::DomainBrowserNew message");
1974 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1975 avahi_log_warn("Too many clients, client request failed.");
1976 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1979 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1980 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1981 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1987 i = avahi_new(DomainBrowserInfo, 1);
1988 i->id = ++client->current_id;
1990 i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
1991 AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
1992 client->n_objects++;
1994 if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, (AvahiLookupFlags) flags, domain_browser_callback, i))) {
1995 domain_browser_free(i);
1996 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1999 dbus_connection_register_object_path(c, i->path, &vtable, i);
2000 return respond_path(c, m, i->path);
2002 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
2004 ServiceTypeBrowserInfo *i;
2005 static const DBusObjectPathVTable vtable = {
2007 msg_service_type_browser_impl,
2013 int32_t interface, protocol;
2017 if (!dbus_message_get_args(
2019 DBUS_TYPE_INT32, &interface,
2020 DBUS_TYPE_INT32, &protocol,
2021 DBUS_TYPE_STRING, &domain,
2022 DBUS_TYPE_UINT32, &flags,
2023 DBUS_TYPE_INVALID)) {
2024 avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
2028 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2029 avahi_log_warn("Too many clients, client request failed.");
2030 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2034 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2035 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2036 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2042 i = avahi_new(ServiceTypeBrowserInfo, 1);
2043 i->id = ++client->current_id;
2045 i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
2046 AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
2047 client->n_objects++;
2049 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))) {
2050 service_type_browser_free(i);
2051 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2054 dbus_connection_register_object_path(c, i->path, &vtable, i);
2055 return respond_path(c, m, i->path);
2057 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
2059 ServiceBrowserInfo *i;
2060 static const DBusObjectPathVTable vtable = {
2062 msg_service_browser_impl,
2068 int32_t interface, protocol;
2070 char *domain, *type;
2072 if (!dbus_message_get_args(
2074 DBUS_TYPE_INT32, &interface,
2075 DBUS_TYPE_INT32, &protocol,
2076 DBUS_TYPE_STRING, &type,
2077 DBUS_TYPE_STRING, &domain,
2078 DBUS_TYPE_UINT32, &flags,
2079 DBUS_TYPE_INVALID) || !type) {
2080 avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
2084 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2085 avahi_log_warn("Too many clients, client request failed.");
2086 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2090 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2091 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2092 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2098 i = avahi_new(ServiceBrowserInfo, 1);
2099 i->id = ++client->current_id;
2101 i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
2102 AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
2103 client->n_objects++;
2105 if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, (AvahiLookupFlags) flags, service_browser_callback, i))) {
2106 service_browser_free(i);
2107 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2110 dbus_connection_register_object_path(c, i->path, &vtable, i);
2111 return respond_path(c, m, i->path);
2113 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
2115 int32_t interface, protocol, aprotocol;
2117 char *name, *type, *domain;
2118 SyncServiceResolverInfo *i;
2120 if (!dbus_message_get_args(
2122 DBUS_TYPE_INT32, &interface,
2123 DBUS_TYPE_INT32, &protocol,
2124 DBUS_TYPE_STRING, &name,
2125 DBUS_TYPE_STRING, &type,
2126 DBUS_TYPE_STRING, &domain,
2127 DBUS_TYPE_INT32, &aprotocol,
2128 DBUS_TYPE_UINT32, &flags,
2129 DBUS_TYPE_INVALID) || !type) {
2130 avahi_log_warn("Error parsing Server::ResolveService message");
2134 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2135 avahi_log_warn("Too many clients, client request failed.");
2136 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2139 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2140 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2141 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2150 i = avahi_new(SyncServiceResolverInfo, 1);
2152 i->message = dbus_message_ref(m);
2153 AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i);
2154 client->n_objects++;
2156 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))) {
2157 sync_service_resolver_free(i);
2158 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2161 return DBUS_HANDLER_RESULT_HANDLED;
2163 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) {
2165 int32_t interface, protocol, aprotocol;
2167 char *name, *type, *domain;
2168 AsyncServiceResolverInfo *i;
2169 static const DBusObjectPathVTable vtable = {
2171 msg_async_service_resolver_impl,
2178 if (!dbus_message_get_args(
2180 DBUS_TYPE_INT32, &interface,
2181 DBUS_TYPE_INT32, &protocol,
2182 DBUS_TYPE_STRING, &name,
2183 DBUS_TYPE_STRING, &type,
2184 DBUS_TYPE_STRING, &domain,
2185 DBUS_TYPE_INT32, &aprotocol,
2186 DBUS_TYPE_UINT32, &flags,
2187 DBUS_TYPE_INVALID) || !type) {
2188 avahi_log_warn("Error parsing Server::ServiceResolverNew message");
2192 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2193 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2194 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2197 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2198 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2199 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2208 i = avahi_new(AsyncServiceResolverInfo, 1);
2209 i->id = ++client->current_id;
2211 i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
2212 AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i);
2213 client->n_objects++;
2215 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))) {
2216 async_service_resolver_free(i);
2217 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2220 /* avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */
2222 dbus_connection_register_object_path(c, i->path, &vtable, i);
2223 return respond_path(c, m, i->path);
2225 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew")) {
2227 int32_t interface, protocol, aprotocol;
2230 AsyncHostNameResolverInfo *i;
2231 static const DBusObjectPathVTable vtable = {
2233 msg_async_host_name_resolver_impl,
2240 if (!dbus_message_get_args(
2242 DBUS_TYPE_INT32, &interface,
2243 DBUS_TYPE_INT32, &protocol,
2244 DBUS_TYPE_STRING, &name,
2245 DBUS_TYPE_INT32, &aprotocol,
2246 DBUS_TYPE_UINT32, &flags,
2247 DBUS_TYPE_INVALID) || !name) {
2248 avahi_log_warn("Error parsing Server::HostNameResolverNew message");
2252 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2253 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2254 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2257 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2258 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2259 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2262 i = avahi_new(AsyncHostNameResolverInfo, 1);
2263 i->id = ++client->current_id;
2265 i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
2266 AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i);
2267 client->n_objects++;
2269 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))) {
2270 async_host_name_resolver_free(i);
2271 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2274 dbus_connection_register_object_path(c, i->path, &vtable, i);
2275 return respond_path(c, m, i->path);
2277 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew")) {
2279 int32_t interface, protocol;
2282 AsyncAddressResolverInfo *i;
2284 static const DBusObjectPathVTable vtable = {
2286 msg_async_address_resolver_impl,
2293 if (!dbus_message_get_args(
2295 DBUS_TYPE_INT32, &interface,
2296 DBUS_TYPE_INT32, &protocol,
2297 DBUS_TYPE_STRING, &address,
2298 DBUS_TYPE_UINT32, &flags,
2299 DBUS_TYPE_INVALID) || !address) {
2300 avahi_log_warn("Error parsing Server::AddressResolverNew message");
2304 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
2305 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
2307 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2308 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2309 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2312 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2313 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2314 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2317 i = avahi_new(AsyncAddressResolverInfo, 1);
2318 i->id = ++client->current_id;
2320 i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
2321 AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i);
2322 client->n_objects++;
2324 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, async_address_resolver_callback, i))) {
2325 async_address_resolver_free(i);
2326 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2329 dbus_connection_register_object_path(c, i->path, &vtable, i);
2330 return respond_path(c, m, i->path);
2333 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
2336 if (dbus_error_is_set(&error))
2337 dbus_error_free(&error);
2339 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2342 void dbus_protocol_server_state_changed(AvahiServerState state) {
2349 m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
2350 t = (int32_t) state;
2351 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
2352 dbus_connection_send(server->bus, m, NULL);
2353 dbus_message_unref(m);
2356 int dbus_protocol_setup(const AvahiPoll *poll_api) {
2359 static const DBusObjectPathVTable server_vtable = {
2368 dbus_error_init(&error);
2370 server = avahi_new(Server, 1);
2371 AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
2372 server->current_id = 0;
2373 server->n_clients = 0;
2375 if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
2376 assert(dbus_error_is_set(&error));
2377 avahi_log_error("dbus_bus_get(): %s", error.message);
2381 if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) {
2382 avahi_log_error("avahi_dbus_connection_glue() failed");
2386 if (dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
2387 if (dbus_error_is_set(&error)) {
2388 avahi_log_error("dbus_bus_request_name(): %s", error.message);
2392 avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'");
2396 if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) {
2397 avahi_log_error("dbus_connection_add_filter() failed");
2401 dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
2403 if (dbus_error_is_set(&error)) {
2404 avahi_log_error("dbus_bus_add_match(): %s", error.message);
2408 if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
2409 avahi_log_error("dbus_connection_register_object_path() failed");
2417 dbus_connection_disconnect(server->bus);
2418 dbus_connection_unref(server->bus);
2421 if (dbus_error_is_set(&error))
2422 dbus_error_free(&error);
2429 void dbus_protocol_shutdown(void) {
2433 while (server->clients)
2434 client_free(server->clients);
2436 assert(server->n_clients == 0);
2439 dbus_connection_disconnect(server->bus);
2440 dbus_connection_unref(server->bus);