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 void append_server_error(DBusMessage *reply) {
510 t = avahi_error_number_to_dbus(avahi_server_errno(avahi_server));
512 dbus_message_append_args(
514 DBUS_TYPE_STRING, &t,
518 static char *file_get_contents(char *fname) {
526 if (!(fd = open(fname, O_RDONLY))) {
527 avahi_log_error("Failed to open %s: %s", fname, strerror(errno));
531 if (fstat(fd, &st) < 0) {
532 avahi_log_error("stat(%s) failed: %s", fname, strerror(errno));
536 if (!(S_ISREG(st.st_mode))) {
537 avahi_log_error("Invalid file %s", fname);
541 if (st.st_size > 1024*1024) { /** 1MB */
542 avahi_log_error("File too large %s", fname);
546 buf = avahi_new(char, st.st_size+1);
548 if ((size = read(fd, buf, st.st_size)) < 0) {
549 avahi_log_error("read() failed: %s\n", strerror(errno));
569 static const char *map_browse_signal_name(AvahiBrowserEvent e) {
571 case AVAHI_BROWSER_NEW : return "ItemNew";
572 case AVAHI_BROWSER_REMOVE : return "ItemRemove";
573 case AVAHI_BROWSER_FAILURE : return "Failure";
574 case AVAHI_BROWSER_CACHE_EXHAUSTED : return "CacheExhausted";
575 case AVAHI_BROWSER_ALL_FOR_NOW : return "AllForNow";
581 static const char *map_resolve_signal_name(AvahiResolverEvent e) {
583 case AVAHI_RESOLVER_FOUND : return "Found";
584 case AVAHI_RESOLVER_FAILURE : return "Failure";
591 static DBusHandlerResult handle_introspect(DBusConnection *c, DBusMessage *m, const char *fname) {
592 char *path, *contents;
599 dbus_error_init(&error);
601 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
602 avahi_log_error("Error parsing Introspect message: %s", error.message);
606 path = avahi_strdup_printf("%s/%s", AVAHI_DBUS_INTROSPECTION_DIR, fname);
607 contents = file_get_contents(path);
611 avahi_log_error("Failed to load introspection data.");
615 respond_string(c, m, contents);
616 avahi_free(contents);
618 return DBUS_HANDLER_RESULT_HANDLED;
621 if (dbus_error_is_set(&error))
622 dbus_error_free(&error);
624 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
628 static DBusHandlerResult msg_signal_filter_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
631 dbus_error_init(&error);
633 /* avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s", */
634 /* dbus_message_get_interface(m), */
635 /* dbus_message_get_path(m), */
636 /* dbus_message_get_member(m)); */
638 if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
639 /* No, we shouldn't quit, but until we get somewhere
640 * usefull such that we can restore our state, we will */
641 avahi_log_warn("Disconnnected from D-BUS, terminating...");
643 raise(SIGQUIT); /* The signal handler will catch this and terminate the process cleanly*/
645 return DBUS_HANDLER_RESULT_HANDLED;
647 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) {
650 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
651 avahi_log_warn("Error parsing NameAcquired message");
655 /* avahi_log_info(__FILE__": name acquired (%s)", name); */
656 return DBUS_HANDLER_RESULT_HANDLED;
658 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
659 char *name, *old, *new;
661 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) {
662 avahi_log_warn("Error parsing NameOwnerChanged message");
669 if ((client = client_get(name, FALSE))) {
670 avahi_log_debug(__FILE__": client %s vanished.", name);
677 if (dbus_error_is_set(&error))
678 dbus_error_free(&error);
680 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
683 static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntryGroupState state, void* userdata) {
684 EntryGroupInfo *i = userdata;
692 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged");
694 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
695 dbus_message_set_destination(m, i->client->name);
696 dbus_connection_send(server->bus, m, NULL);
697 dbus_message_unref(m);
700 static int read_strlst(DBusMessage *m, int idx, AvahiStringList **l) {
701 DBusMessageIter iter, sub;
703 AvahiStringList *strlst = NULL;
708 dbus_message_iter_init(m, &iter);
710 for (j = 0; j < idx; j++)
711 dbus_message_iter_next(&iter);
713 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
714 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY)
717 dbus_message_iter_recurse(&iter, &sub);
720 DBusMessageIter sub2;
724 if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
727 assert(at == DBUS_TYPE_ARRAY);
729 if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE)
732 dbus_message_iter_recurse(&sub, &sub2);
733 dbus_message_iter_get_fixed_array(&sub2, &k, &n);
734 strlst = avahi_string_list_add_arbitrary(strlst, k, n);
736 dbus_message_iter_next(&sub);
744 avahi_log_warn("Error parsing TXT data");
746 avahi_string_list_free(strlst);
752 static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
754 EntryGroupInfo *i = userdata;
760 dbus_error_init(&error);
762 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
763 dbus_message_get_interface(m),
764 dbus_message_get_path(m),
765 dbus_message_get_member(m));
768 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
769 return handle_introspect(c, m, "EntryGroup.introspect");
772 if (strcmp(dbus_message_get_sender(m), i->client->name))
773 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
775 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) {
777 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
778 avahi_log_warn("Error parsing EntryGroup::Free message");
783 return respond_ok(c, m);
785 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Commit")) {
787 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
788 avahi_log_warn("Error parsing EntryGroup::Commit message");
792 avahi_s_entry_group_commit(i->entry_group);
793 return respond_ok(c, m);
796 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Reset")) {
798 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
799 avahi_log_warn("Error parsing EntryGroup::Reset message");
803 avahi_s_entry_group_reset(i->entry_group);
805 return respond_ok(c, m);
807 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) {
811 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
812 avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
816 b = !!avahi_s_entry_group_is_empty(i->entry_group);
818 reply = dbus_message_new_method_return(m);
819 dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
820 dbus_connection_send(c, reply, NULL);
821 dbus_message_unref(reply);
823 return DBUS_HANDLER_RESULT_HANDLED;
825 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
826 AvahiEntryGroupState state;
828 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
829 avahi_log_warn("Error parsing EntryGroup::GetState message");
833 state = avahi_s_entry_group_get_state(i->entry_group);
834 return respond_int32(c, m, (int32_t) state);
836 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
837 int32_t interface, protocol;
839 char *type, *name, *domain, *host;
841 AvahiStringList *strlst = NULL;
843 if (!dbus_message_get_args(
845 DBUS_TYPE_INT32, &interface,
846 DBUS_TYPE_INT32, &protocol,
847 DBUS_TYPE_UINT32, &flags,
848 DBUS_TYPE_STRING, &name,
849 DBUS_TYPE_STRING, &type,
850 DBUS_TYPE_STRING, &domain,
851 DBUS_TYPE_STRING, &host,
852 DBUS_TYPE_UINT16, &port,
853 DBUS_TYPE_INVALID) ||
855 read_strlst(m, 8, &strlst) < 0) {
856 avahi_log_warn("Error parsing EntryGroup::AddService message");
860 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
861 avahi_string_list_free(strlst);
862 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
865 if (domain && !*domain)
871 if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, host, port, strlst) < 0) {
872 avahi_string_list_free(strlst);
873 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
876 if (!(flags & AVAHI_PUBLISH_UPDATE))
879 avahi_string_list_free(strlst);
881 return respond_ok(c, m);
883 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddServiceSubtype")) {
885 int32_t interface, protocol;
887 char *type, *name, *domain, *subtype;
889 if (!dbus_message_get_args(
891 DBUS_TYPE_INT32, &interface,
892 DBUS_TYPE_INT32, &protocol,
893 DBUS_TYPE_UINT32, &flags,
894 DBUS_TYPE_STRING, &name,
895 DBUS_TYPE_STRING, &type,
896 DBUS_TYPE_STRING, &domain,
897 DBUS_TYPE_STRING, &subtype,
898 DBUS_TYPE_INVALID) || !type || !name || !subtype) {
899 avahi_log_warn("Error parsing EntryGroup::AddServiceSubtype message");
903 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP)
904 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
906 if (domain && !*domain)
909 if (avahi_server_add_service_subtype(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, subtype) < 0)
910 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
912 if (!(flags & AVAHI_PUBLISH_UPDATE))
915 return respond_ok(c, m);
917 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "UpdateServiceTxt")) {
918 int32_t interface, protocol;
920 char *type, *name, *domain;
921 AvahiStringList *strlst;
923 if (!dbus_message_get_args(
925 DBUS_TYPE_INT32, &interface,
926 DBUS_TYPE_INT32, &protocol,
927 DBUS_TYPE_UINT32, &flags,
928 DBUS_TYPE_STRING, &name,
929 DBUS_TYPE_STRING, &type,
930 DBUS_TYPE_STRING, &domain,
931 DBUS_TYPE_INVALID) ||
933 read_strlst(m, 6, &strlst)) {
934 avahi_log_warn("Error parsing EntryGroup::UpdateServiceTxt message");
938 if (domain && !*domain)
941 if (avahi_server_update_service_txt_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, strlst) < 0) {
942 avahi_string_list_free(strlst);
943 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
946 avahi_string_list_free(strlst);
948 return respond_ok(c, m);
950 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
951 int32_t interface, protocol;
953 char *name, *address;
956 if (!dbus_message_get_args(
958 DBUS_TYPE_INT32, &interface,
959 DBUS_TYPE_INT32, &protocol,
960 DBUS_TYPE_UINT32, &flags,
961 DBUS_TYPE_STRING, &name,
962 DBUS_TYPE_STRING, &address,
963 DBUS_TYPE_INVALID) || !name || !address) {
964 avahi_log_warn("Error parsing EntryGroup::AddAddress message");
968 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP)
969 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
971 if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a)))
972 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
974 if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, &a) < 0)
975 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
977 if (!(flags & AVAHI_PUBLISH_UPDATE))
980 return respond_ok(c, m);
983 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
986 if (dbus_error_is_set(&error))
987 dbus_error_free(&error);
989 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
992 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) {
993 SyncHostNameResolverInfo *i = userdata;
999 if (event == AVAHI_RESOLVER_FOUND) {
1000 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1001 int32_t i_interface, i_protocol, i_aprotocol;
1006 avahi_address_snprint(t, sizeof(t), a);
1008 i_interface = (int32_t) interface;
1009 i_protocol = (int32_t) protocol;
1010 i_aprotocol = (int32_t) a->proto;
1011 u_flags = (uint32_t) flags;
1013 reply = dbus_message_new_method_return(i->message);
1014 dbus_message_append_args(
1016 DBUS_TYPE_INT32, &i_interface,
1017 DBUS_TYPE_INT32, &i_protocol,
1018 DBUS_TYPE_STRING, &host_name,
1019 DBUS_TYPE_INT32, &i_aprotocol,
1020 DBUS_TYPE_STRING, &pt,
1021 DBUS_TYPE_UINT32, &u_flags,
1024 dbus_connection_send(server->bus, reply, NULL);
1025 dbus_message_unref(reply);
1027 assert(event == AVAHI_RESOLVER_FAILURE);
1028 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1031 sync_host_name_resolver_free(i);
1034 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) {
1035 SyncAddressResolverInfo *i = userdata;
1041 if (event == AVAHI_RESOLVER_FOUND) {
1042 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1043 int32_t i_interface, i_protocol, i_aprotocol;
1048 avahi_address_snprint(t, sizeof(t), address);
1050 i_interface = (int32_t) interface;
1051 i_protocol = (int32_t) protocol;
1052 i_aprotocol = (int32_t) address->proto;
1053 u_flags = (uint32_t) flags;
1055 reply = dbus_message_new_method_return(i->message);
1056 dbus_message_append_args(
1058 DBUS_TYPE_INT32, &i_interface,
1059 DBUS_TYPE_INT32, &i_protocol,
1060 DBUS_TYPE_INT32, &i_aprotocol,
1061 DBUS_TYPE_STRING, &pt,
1062 DBUS_TYPE_STRING, &host_name,
1063 DBUS_TYPE_UINT32, &u_flags,
1066 dbus_connection_send(server->bus, reply, NULL);
1067 dbus_message_unref(reply);
1069 assert(event == AVAHI_RESOLVER_FAILURE);
1070 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1073 sync_address_resolver_free(i);
1076 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1078 DomainBrowserInfo *i = userdata;
1084 dbus_error_init(&error);
1086 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1087 dbus_message_get_interface(m),
1088 dbus_message_get_path(m),
1089 dbus_message_get_member(m));
1092 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1093 return handle_introspect(c, m, "DomainBrowser.introspect");
1095 /* Access control */
1096 if (strcmp(dbus_message_get_sender(m), i->client->name))
1097 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1099 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
1101 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1102 avahi_log_warn("Error parsing DomainBrowser::Free message");
1106 domain_browser_free(i);
1107 return respond_ok(c, m);
1111 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1114 if (dbus_error_is_set(&error))
1115 dbus_error_free(&error);
1117 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1120 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1121 DomainBrowserInfo *i = userdata;
1123 int32_t i_interface, i_protocol;
1129 i_interface = (int32_t) interface;
1130 i_protocol = (int32_t) protocol;
1131 u_flags = (uint32_t) flags;
1133 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, map_browse_signal_name(event));
1135 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1137 dbus_message_append_args(
1139 DBUS_TYPE_INT32, &i_interface,
1140 DBUS_TYPE_INT32, &i_protocol,
1141 DBUS_TYPE_STRING, &domain,
1142 DBUS_TYPE_UINT32, &u_flags,
1144 } else if (event == AVAHI_BROWSER_FAILURE)
1145 append_server_error(m);
1147 dbus_message_set_destination(m, i->client->name);
1148 dbus_connection_send(server->bus, m, NULL);
1149 dbus_message_unref(m);
1152 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1154 ServiceTypeBrowserInfo *i = userdata;
1160 dbus_error_init(&error);
1162 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1163 dbus_message_get_interface(m),
1164 dbus_message_get_path(m),
1165 dbus_message_get_member(m));
1168 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1169 return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
1171 /* Access control */
1172 if (strcmp(dbus_message_get_sender(m), i->client->name))
1173 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1175 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
1177 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1178 avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
1182 service_type_browser_free(i);
1183 return respond_ok(c, m);
1187 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1190 if (dbus_error_is_set(&error))
1191 dbus_error_free(&error);
1193 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1196 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1197 ServiceTypeBrowserInfo *i = userdata;
1199 int32_t i_interface, i_protocol;
1205 i_interface = (int32_t) interface;
1206 i_protocol = (int32_t) protocol;
1207 u_flags = (uint32_t) flags;
1209 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, map_browse_signal_name(event));
1211 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1214 dbus_message_append_args(
1216 DBUS_TYPE_INT32, &i_interface,
1217 DBUS_TYPE_INT32, &i_protocol,
1218 DBUS_TYPE_STRING, &type,
1219 DBUS_TYPE_STRING, &domain,
1220 DBUS_TYPE_UINT32, &u_flags,
1222 } else if (event == AVAHI_BROWSER_FAILURE)
1223 append_server_error(m);
1225 dbus_message_set_destination(m, i->client->name);
1226 dbus_connection_send(server->bus, m, NULL);
1227 dbus_message_unref(m);
1230 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1232 ServiceBrowserInfo *i = userdata;
1238 dbus_error_init(&error);
1240 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1241 dbus_message_get_interface(m),
1242 dbus_message_get_path(m),
1243 dbus_message_get_member(m));
1246 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1247 return handle_introspect(c, m, "ServiceBrowser.Introspect");
1249 /* Access control */
1250 if (strcmp(dbus_message_get_sender(m), i->client->name))
1251 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1253 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
1255 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1256 avahi_log_warn("Error parsing ServiceBrowser::Free message");
1260 service_browser_free(i);
1261 return respond_ok(c, m);
1265 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1268 if (dbus_error_is_set(&error))
1269 dbus_error_free(&error);
1271 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1274 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) {
1275 ServiceBrowserInfo *i = userdata;
1277 int32_t i_interface, i_protocol;
1283 i_interface = (int32_t) interface;
1284 i_protocol = (int32_t) protocol;
1285 u_flags = (uint32_t) flags;
1287 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, map_browse_signal_name(event));
1289 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1294 dbus_message_append_args(
1296 DBUS_TYPE_INT32, &i_interface,
1297 DBUS_TYPE_INT32, &i_protocol,
1298 DBUS_TYPE_STRING, &name,
1299 DBUS_TYPE_STRING, &type,
1300 DBUS_TYPE_STRING, &domain,
1301 DBUS_TYPE_UINT32, &u_flags,
1303 } else if (event == AVAHI_BROWSER_FAILURE)
1304 append_server_error(m);
1306 dbus_message_set_destination(m, i->client->name);
1307 dbus_connection_send(server->bus, m, NULL);
1308 dbus_message_unref(m);
1311 static void append_string_list(DBusMessage *reply, AvahiStringList *txt) {
1313 DBusMessageIter iter, sub;
1317 dbus_message_iter_init_append(reply, &iter);
1318 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1320 for (p = txt; p; p = p->next) {
1321 DBusMessageIter sub2;
1322 const uint8_t *data = p->text;
1324 dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1325 dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
1326 dbus_message_iter_close_container(&sub, &sub2);
1329 dbus_message_iter_close_container(&iter, &sub);
1332 static void sync_service_resolver_callback(
1333 AvahiSServiceResolver *r,
1334 AvahiIfIndex interface,
1335 AvahiProtocol protocol,
1336 AvahiResolverEvent event,
1340 const char *host_name,
1341 const AvahiAddress *a,
1343 AvahiStringList *txt,
1344 AvahiLookupResultFlags flags,
1347 SyncServiceResolverInfo *i = userdata;
1352 if (event == AVAHI_RESOLVER_FOUND) {
1353 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1354 int32_t i_interface, i_protocol, i_aprotocol;
1364 avahi_address_snprint(t, sizeof(t), a);
1366 i_interface = (int32_t) interface;
1367 i_protocol = (int32_t) protocol;
1368 i_aprotocol = (int32_t) a->proto;
1369 u_flags = (uint32_t) flags;
1371 reply = dbus_message_new_method_return(i->message);
1372 dbus_message_append_args(
1374 DBUS_TYPE_INT32, &i_interface,
1375 DBUS_TYPE_INT32, &i_protocol,
1376 DBUS_TYPE_STRING, &name,
1377 DBUS_TYPE_STRING, &type,
1378 DBUS_TYPE_STRING, &domain,
1379 DBUS_TYPE_STRING, &host_name,
1380 DBUS_TYPE_INT32, &i_aprotocol,
1381 DBUS_TYPE_STRING, &pt,
1382 DBUS_TYPE_UINT16, &port,
1385 append_string_list(reply, txt);
1387 dbus_message_append_args(
1389 DBUS_TYPE_UINT32, &u_flags,
1392 dbus_connection_send(server->bus, reply, NULL);
1393 dbus_message_unref(reply);
1396 assert(event == AVAHI_RESOLVER_FAILURE);
1398 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1401 sync_service_resolver_free(i);
1404 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) {
1405 AsyncAddressResolverInfo *i = userdata;
1411 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, map_resolve_signal_name(event));
1413 if (event == AVAHI_RESOLVER_FOUND) {
1414 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1415 int32_t i_interface, i_protocol, i_aprotocol;
1420 avahi_address_snprint(t, sizeof(t), address);
1422 i_interface = (int32_t) interface;
1423 i_protocol = (int32_t) protocol;
1424 i_aprotocol = (int32_t) address->proto;
1425 u_flags = (uint32_t) flags;
1427 dbus_message_append_args(
1429 DBUS_TYPE_INT32, &i_interface,
1430 DBUS_TYPE_INT32, &i_protocol,
1431 DBUS_TYPE_INT32, &i_aprotocol,
1432 DBUS_TYPE_STRING, &pt,
1433 DBUS_TYPE_STRING, &host_name,
1434 DBUS_TYPE_UINT32, &u_flags,
1438 assert(event == AVAHI_RESOLVER_FAILURE);
1439 append_server_error(reply);
1442 dbus_message_set_destination(reply, i->client->name);
1443 dbus_connection_send(server->bus, reply, NULL);
1444 dbus_message_unref(reply);
1447 static DBusHandlerResult msg_async_address_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1449 AsyncAddressResolverInfo *i = userdata;
1455 dbus_error_init(&error);
1457 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1458 dbus_message_get_interface(m),
1459 dbus_message_get_path(m),
1460 dbus_message_get_member(m));
1463 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1464 return handle_introspect(c, m, "AddressResolver.Introspect");
1466 /* Access control */
1467 if (strcmp(dbus_message_get_sender(m), i->client->name))
1468 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1470 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Free")) {
1472 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1473 avahi_log_warn("Error parsing AddressResolver::Free message");
1477 async_address_resolver_free(i);
1478 return respond_ok(c, m);
1482 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1485 if (dbus_error_is_set(&error))
1486 dbus_error_free(&error);
1488 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1491 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) {
1492 AsyncHostNameResolverInfo *i = userdata;
1498 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, map_resolve_signal_name(event));
1500 if (event == AVAHI_RESOLVER_FOUND) {
1501 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1502 int32_t i_interface, i_protocol, i_aprotocol;
1507 avahi_address_snprint(t, sizeof(t), a);
1509 i_interface = (int32_t) interface;
1510 i_protocol = (int32_t) protocol;
1511 i_aprotocol = (int32_t) a->proto;
1512 u_flags = (uint32_t) flags;
1514 dbus_message_append_args(
1516 DBUS_TYPE_INT32, &i_interface,
1517 DBUS_TYPE_INT32, &i_protocol,
1518 DBUS_TYPE_STRING, &host_name,
1519 DBUS_TYPE_INT32, &i_aprotocol,
1520 DBUS_TYPE_STRING, &pt,
1521 DBUS_TYPE_UINT32, &u_flags,
1524 assert(event == AVAHI_RESOLVER_FAILURE);
1525 append_server_error(reply);
1528 dbus_message_set_destination(reply, i->client->name);
1529 dbus_connection_send(server->bus, reply, NULL);
1530 dbus_message_unref(reply);
1533 static DBusHandlerResult msg_async_host_name_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1535 AsyncHostNameResolverInfo *i = userdata;
1541 dbus_error_init(&error);
1543 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1544 dbus_message_get_interface(m),
1545 dbus_message_get_path(m),
1546 dbus_message_get_member(m));
1549 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1550 return handle_introspect(c, m, "HostNameResolver.Introspect");
1552 /* Access control */
1553 if (strcmp(dbus_message_get_sender(m), i->client->name))
1554 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1556 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, "Free")) {
1558 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1559 avahi_log_warn("Error parsing HostNameResolver::Free message");
1563 async_host_name_resolver_free(i);
1564 return respond_ok(c, m);
1567 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1570 if (dbus_error_is_set(&error))
1571 dbus_error_free(&error);
1573 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1576 static void async_service_resolver_callback(
1577 AvahiSServiceResolver *r,
1578 AvahiIfIndex interface,
1579 AvahiProtocol protocol,
1580 AvahiResolverEvent event,
1584 const char *host_name,
1585 const AvahiAddress *a,
1587 AvahiStringList *txt,
1588 AvahiLookupResultFlags flags,
1591 AsyncServiceResolverInfo *i = userdata;
1597 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, map_resolve_signal_name(event));
1599 if (event == AVAHI_RESOLVER_FOUND) {
1600 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1601 int32_t i_interface, i_protocol, i_aprotocol;
1606 /* avahi_log_debug(__FILE__": [%s] Successfully resolved service <%s.%s.%s>", i->path, name, type, domain); */
1609 avahi_address_snprint(t, sizeof(t), a);
1616 i_interface = (int32_t) interface;
1617 i_protocol = (int32_t) protocol;
1619 i_aprotocol = (int32_t) a->proto;
1621 i_aprotocol = AVAHI_PROTO_UNSPEC;
1622 u_flags = (uint32_t) flags;
1624 dbus_message_append_args(
1626 DBUS_TYPE_INT32, &i_interface,
1627 DBUS_TYPE_INT32, &i_protocol,
1628 DBUS_TYPE_STRING, &name,
1629 DBUS_TYPE_STRING, &type,
1630 DBUS_TYPE_STRING, &domain,
1631 DBUS_TYPE_STRING, &host_name,
1632 DBUS_TYPE_INT32, &i_aprotocol,
1633 DBUS_TYPE_STRING, &pt,
1634 DBUS_TYPE_UINT16, &port,
1637 append_string_list(reply, txt);
1639 dbus_message_append_args(
1641 DBUS_TYPE_UINT32, &u_flags,
1644 assert(event == AVAHI_RESOLVER_FAILURE);
1645 append_server_error(reply);
1648 dbus_message_set_destination(reply, i->client->name);
1649 dbus_connection_send(server->bus, reply, NULL);
1650 dbus_message_unref(reply);
1653 static DBusHandlerResult msg_async_service_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1655 AsyncServiceResolverInfo *i = userdata;
1661 dbus_error_init(&error);
1663 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1664 dbus_message_get_interface(m),
1665 dbus_message_get_path(m),
1666 dbus_message_get_member(m));
1669 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1670 return handle_introspect(c, m, "ServiceResolver.Introspect");
1672 /* Access control */
1673 if (strcmp(dbus_message_get_sender(m), i->client->name))
1674 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1676 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, "Free")) {
1678 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1679 avahi_log_warn("Error parsing ServiceResolver::Free message");
1683 async_service_resolver_free(i);
1684 return respond_ok(c, m);
1687 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1690 if (dbus_error_is_set(&error))
1691 dbus_error_free(&error);
1693 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1696 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1699 dbus_error_init(&error);
1701 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1702 dbus_message_get_interface(m),
1703 dbus_message_get_path(m),
1704 dbus_message_get_member(m));
1706 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1707 return handle_introspect(c, m, "Server.introspect");
1709 else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1711 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1712 avahi_log_warn("Error parsing Server::GetHostName message");
1716 return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1718 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1720 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1721 avahi_log_warn("Error parsing Server::GetDomainName message");
1725 return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1727 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1729 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1730 avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1734 return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1736 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1738 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1739 avahi_log_warn("Error parsing Server::GetVersionString message");
1743 return respond_string(c, m, PACKAGE_STRING);
1745 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1746 AvahiServerState state;
1748 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1749 avahi_log_warn("Error parsing Server::GetState message");
1753 state = avahi_server_get_state(avahi_server);
1754 return respond_int32(c, m, (int32_t) state);
1756 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetLocalServiceCookie")) {
1758 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1759 avahi_log_warn("Error parsing Server::GetLocalServiceCookie message");
1763 return respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server));
1765 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "IsServiceLocal")) {
1766 int32_t interface, protocol;
1767 char *name, *type, *domain;
1770 if (!dbus_message_get_args(
1772 DBUS_TYPE_INT32, &interface,
1773 DBUS_TYPE_INT32, &protocol,
1774 DBUS_TYPE_STRING, &name,
1775 DBUS_TYPE_STRING, &type,
1776 DBUS_TYPE_STRING, &domain,
1777 DBUS_TYPE_INVALID) || !name || !type || !domain) {
1778 avahi_log_warn("Error parsing Server::IsServiceLocal message");
1782 if ((b = avahi_server_is_service_local(avahi_server, interface, protocol, name, type, domain)) < 0)
1783 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1785 return respond_boolean(c, m, b);
1787 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1792 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1793 avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1797 #ifdef VALGRIND_WORKAROUND
1798 return respond_string(c, m, "blah");
1801 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1802 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1804 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1805 return respond_error(c, m, AVAHI_ERR_OS, txt);
1808 memset(&ifr, 0, sizeof(ifr));
1809 ifr.ifr_ifindex = idx;
1811 if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) {
1813 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1815 return respond_error(c, m, AVAHI_ERR_OS, txt);
1820 return respond_string(c, m, ifr.ifr_name);
1823 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1828 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1829 avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1833 #ifdef VALGRIND_WORKAROUND
1834 return respond_int32(c, m, 1);
1836 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1837 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1839 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1840 return respond_error(c, m, AVAHI_ERR_OS, txt);
1843 memset(&ifr, 0, sizeof(ifr));
1844 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", n);
1846 if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
1848 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1850 return respond_error(c, m, AVAHI_ERR_OS, txt);
1855 return respond_int32(c, m, ifr.ifr_ifindex);
1858 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1861 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1862 avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1866 t = avahi_alternative_host_name(n);
1867 respond_string(c, m, t);
1870 return DBUS_HANDLER_RESULT_HANDLED;
1872 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1875 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1876 avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1880 t = avahi_alternative_service_name(n);
1881 respond_string(c, m, t);
1884 return DBUS_HANDLER_RESULT_HANDLED;
1886 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1889 static const DBusObjectPathVTable vtable = {
1891 msg_entry_group_impl,
1898 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1899 avahi_log_warn("Error parsing Server::EntryGroupNew message");
1903 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1904 avahi_log_warn("Too many clients, client request failed.");
1905 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1908 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1909 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1910 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1913 i = avahi_new(EntryGroupInfo, 1);
1914 i->id = ++client->current_id;
1916 i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1918 AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1919 client->n_objects++;
1921 if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1922 entry_group_free(i);
1923 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1926 dbus_connection_register_object_path(c, i->path, &vtable, i);
1927 return respond_path(c, m, i->path);
1929 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1931 int32_t interface, protocol, aprotocol;
1934 SyncHostNameResolverInfo *i;
1936 if (!dbus_message_get_args(
1938 DBUS_TYPE_INT32, &interface,
1939 DBUS_TYPE_INT32, &protocol,
1940 DBUS_TYPE_STRING, &name,
1941 DBUS_TYPE_INT32, &aprotocol,
1942 DBUS_TYPE_UINT32, &flags,
1943 DBUS_TYPE_INVALID) || !name) {
1944 avahi_log_warn("Error parsing Server::ResolveHostName message");
1948 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1949 avahi_log_warn("Too many clients, client request failed.");
1950 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1953 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1954 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1955 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1958 i = avahi_new(SyncHostNameResolverInfo, 1);
1960 i->message = dbus_message_ref(m);
1961 AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i);
1962 client->n_objects++;
1964 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))) {
1965 sync_host_name_resolver_free(i);
1966 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1969 return DBUS_HANDLER_RESULT_HANDLED;
1971 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1973 int32_t interface, protocol;
1976 SyncAddressResolverInfo *i;
1979 if (!dbus_message_get_args(
1981 DBUS_TYPE_INT32, &interface,
1982 DBUS_TYPE_INT32, &protocol,
1983 DBUS_TYPE_STRING, &address,
1984 DBUS_TYPE_UINT32, &flags,
1985 DBUS_TYPE_INVALID) || !address) {
1986 avahi_log_warn("Error parsing Server::ResolveAddress message");
1990 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
1991 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
1993 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1994 avahi_log_warn("Too many clients, client request failed.");
1995 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1998 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1999 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2000 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2003 i = avahi_new(SyncAddressResolverInfo, 1);
2005 i->message = dbus_message_ref(m);
2006 AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i);
2007 client->n_objects++;
2009 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, sync_address_resolver_callback, i))) {
2010 sync_address_resolver_free(i);
2011 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2014 return DBUS_HANDLER_RESULT_HANDLED;
2016 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
2018 DomainBrowserInfo *i;
2019 static const DBusObjectPathVTable vtable = {
2021 msg_domain_browser_impl,
2027 int32_t interface, protocol, type;
2031 if (!dbus_message_get_args(
2033 DBUS_TYPE_INT32, &interface,
2034 DBUS_TYPE_INT32, &protocol,
2035 DBUS_TYPE_STRING, &domain,
2036 DBUS_TYPE_INT32, &type,
2037 DBUS_TYPE_UINT32, &flags,
2038 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
2039 avahi_log_warn("Error parsing Server::DomainBrowserNew message");
2043 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2044 avahi_log_warn("Too many clients, client request failed.");
2045 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2048 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2049 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2050 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2056 i = avahi_new(DomainBrowserInfo, 1);
2057 i->id = ++client->current_id;
2059 i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
2060 AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
2061 client->n_objects++;
2063 if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, (AvahiLookupFlags) flags, domain_browser_callback, i))) {
2064 domain_browser_free(i);
2065 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2068 dbus_connection_register_object_path(c, i->path, &vtable, i);
2069 return respond_path(c, m, i->path);
2071 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
2073 ServiceTypeBrowserInfo *i;
2074 static const DBusObjectPathVTable vtable = {
2076 msg_service_type_browser_impl,
2082 int32_t interface, protocol;
2086 if (!dbus_message_get_args(
2088 DBUS_TYPE_INT32, &interface,
2089 DBUS_TYPE_INT32, &protocol,
2090 DBUS_TYPE_STRING, &domain,
2091 DBUS_TYPE_UINT32, &flags,
2092 DBUS_TYPE_INVALID)) {
2093 avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
2097 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2098 avahi_log_warn("Too many clients, client request failed.");
2099 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2103 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2104 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2105 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2111 i = avahi_new(ServiceTypeBrowserInfo, 1);
2112 i->id = ++client->current_id;
2114 i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
2115 AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
2116 client->n_objects++;
2118 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))) {
2119 service_type_browser_free(i);
2120 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2123 dbus_connection_register_object_path(c, i->path, &vtable, i);
2124 return respond_path(c, m, i->path);
2126 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
2128 ServiceBrowserInfo *i;
2129 static const DBusObjectPathVTable vtable = {
2131 msg_service_browser_impl,
2137 int32_t interface, protocol;
2139 char *domain, *type;
2141 if (!dbus_message_get_args(
2143 DBUS_TYPE_INT32, &interface,
2144 DBUS_TYPE_INT32, &protocol,
2145 DBUS_TYPE_STRING, &type,
2146 DBUS_TYPE_STRING, &domain,
2147 DBUS_TYPE_UINT32, &flags,
2148 DBUS_TYPE_INVALID) || !type) {
2149 avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
2153 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2154 avahi_log_warn("Too many clients, client request failed.");
2155 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2159 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2160 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2161 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2167 i = avahi_new(ServiceBrowserInfo, 1);
2168 i->id = ++client->current_id;
2170 i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
2171 AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
2172 client->n_objects++;
2174 if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, (AvahiLookupFlags) flags, service_browser_callback, i))) {
2175 service_browser_free(i);
2176 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2179 dbus_connection_register_object_path(c, i->path, &vtable, i);
2180 return respond_path(c, m, i->path);
2182 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
2184 int32_t interface, protocol, aprotocol;
2186 char *name, *type, *domain;
2187 SyncServiceResolverInfo *i;
2189 if (!dbus_message_get_args(
2191 DBUS_TYPE_INT32, &interface,
2192 DBUS_TYPE_INT32, &protocol,
2193 DBUS_TYPE_STRING, &name,
2194 DBUS_TYPE_STRING, &type,
2195 DBUS_TYPE_STRING, &domain,
2196 DBUS_TYPE_INT32, &aprotocol,
2197 DBUS_TYPE_UINT32, &flags,
2198 DBUS_TYPE_INVALID) || !type) {
2199 avahi_log_warn("Error parsing Server::ResolveService message");
2203 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2204 avahi_log_warn("Too many clients, client request failed.");
2205 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2208 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2209 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2210 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2219 i = avahi_new(SyncServiceResolverInfo, 1);
2221 i->message = dbus_message_ref(m);
2222 AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i);
2223 client->n_objects++;
2225 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))) {
2226 sync_service_resolver_free(i);
2227 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2230 return DBUS_HANDLER_RESULT_HANDLED;
2232 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) {
2234 int32_t interface, protocol, aprotocol;
2236 char *name, *type, *domain;
2237 AsyncServiceResolverInfo *i;
2238 static const DBusObjectPathVTable vtable = {
2240 msg_async_service_resolver_impl,
2247 if (!dbus_message_get_args(
2249 DBUS_TYPE_INT32, &interface,
2250 DBUS_TYPE_INT32, &protocol,
2251 DBUS_TYPE_STRING, &name,
2252 DBUS_TYPE_STRING, &type,
2253 DBUS_TYPE_STRING, &domain,
2254 DBUS_TYPE_INT32, &aprotocol,
2255 DBUS_TYPE_UINT32, &flags,
2256 DBUS_TYPE_INVALID) || !type) {
2257 avahi_log_warn("Error parsing Server::ServiceResolverNew message");
2261 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2262 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2263 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2266 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2267 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2268 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2277 i = avahi_new(AsyncServiceResolverInfo, 1);
2278 i->id = ++client->current_id;
2280 i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
2281 AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i);
2282 client->n_objects++;
2284 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))) {
2285 async_service_resolver_free(i);
2286 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2289 /* avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */
2291 dbus_connection_register_object_path(c, i->path, &vtable, i);
2292 return respond_path(c, m, i->path);
2294 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew")) {
2296 int32_t interface, protocol, aprotocol;
2299 AsyncHostNameResolverInfo *i;
2300 static const DBusObjectPathVTable vtable = {
2302 msg_async_host_name_resolver_impl,
2309 if (!dbus_message_get_args(
2311 DBUS_TYPE_INT32, &interface,
2312 DBUS_TYPE_INT32, &protocol,
2313 DBUS_TYPE_STRING, &name,
2314 DBUS_TYPE_INT32, &aprotocol,
2315 DBUS_TYPE_UINT32, &flags,
2316 DBUS_TYPE_INVALID) || !name) {
2317 avahi_log_warn("Error parsing Server::HostNameResolverNew message");
2321 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2322 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2323 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2326 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2327 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2328 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2331 i = avahi_new(AsyncHostNameResolverInfo, 1);
2332 i->id = ++client->current_id;
2334 i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
2335 AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i);
2336 client->n_objects++;
2338 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))) {
2339 async_host_name_resolver_free(i);
2340 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2343 dbus_connection_register_object_path(c, i->path, &vtable, i);
2344 return respond_path(c, m, i->path);
2346 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew")) {
2348 int32_t interface, protocol;
2351 AsyncAddressResolverInfo *i;
2353 static const DBusObjectPathVTable vtable = {
2355 msg_async_address_resolver_impl,
2362 if (!dbus_message_get_args(
2364 DBUS_TYPE_INT32, &interface,
2365 DBUS_TYPE_INT32, &protocol,
2366 DBUS_TYPE_STRING, &address,
2367 DBUS_TYPE_UINT32, &flags,
2368 DBUS_TYPE_INVALID) || !address) {
2369 avahi_log_warn("Error parsing Server::AddressResolverNew message");
2373 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
2374 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
2376 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2377 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2378 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2381 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2382 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2383 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2386 i = avahi_new(AsyncAddressResolverInfo, 1);
2387 i->id = ++client->current_id;
2389 i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
2390 AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i);
2391 client->n_objects++;
2393 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, async_address_resolver_callback, i))) {
2394 async_address_resolver_free(i);
2395 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2398 dbus_connection_register_object_path(c, i->path, &vtable, i);
2399 return respond_path(c, m, i->path);
2402 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
2405 if (dbus_error_is_set(&error))
2406 dbus_error_free(&error);
2408 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2411 void dbus_protocol_server_state_changed(AvahiServerState state) {
2418 m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
2419 t = (int32_t) state;
2420 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
2421 dbus_connection_send(server->bus, m, NULL);
2422 dbus_message_unref(m);
2425 int dbus_protocol_setup(const AvahiPoll *poll_api) {
2428 static const DBusObjectPathVTable server_vtable = {
2437 dbus_error_init(&error);
2439 server = avahi_new(Server, 1);
2440 AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
2441 server->current_id = 0;
2442 server->n_clients = 0;
2444 if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
2445 assert(dbus_error_is_set(&error));
2446 avahi_log_error("dbus_bus_get(): %s", error.message);
2450 if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) {
2451 avahi_log_error("avahi_dbus_connection_glue() failed");
2455 if (dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
2456 if (dbus_error_is_set(&error)) {
2457 avahi_log_error("dbus_bus_request_name(): %s", error.message);
2461 avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'");
2465 if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) {
2466 avahi_log_error("dbus_connection_add_filter() failed");
2470 dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
2472 if (dbus_error_is_set(&error)) {
2473 avahi_log_error("dbus_bus_add_match(): %s", error.message);
2477 if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
2478 avahi_log_error("dbus_connection_register_object_path() failed");
2486 dbus_connection_disconnect(server->bus);
2487 dbus_connection_unref(server->bus);
2490 if (dbus_error_is_set(&error))
2491 dbus_error_free(&error);
2498 void dbus_protocol_shutdown(void) {
2502 while (server->clients)
2503 client_free(server->clients);
2505 assert(server->n_clients == 0);
2508 dbus_connection_disconnect(server->bus);
2509 dbus_connection_unref(server->bus);