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")) {
809 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
810 avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
814 return respond_boolean(c, m, !!avahi_s_entry_group_is_empty(i->entry_group));
816 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
817 AvahiEntryGroupState state;
819 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
820 avahi_log_warn("Error parsing EntryGroup::GetState message");
824 state = avahi_s_entry_group_get_state(i->entry_group);
825 return respond_int32(c, m, (int32_t) state);
827 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
828 int32_t interface, protocol;
830 char *type, *name, *domain, *host;
832 AvahiStringList *strlst = NULL;
834 if (!dbus_message_get_args(
836 DBUS_TYPE_INT32, &interface,
837 DBUS_TYPE_INT32, &protocol,
838 DBUS_TYPE_UINT32, &flags,
839 DBUS_TYPE_STRING, &name,
840 DBUS_TYPE_STRING, &type,
841 DBUS_TYPE_STRING, &domain,
842 DBUS_TYPE_STRING, &host,
843 DBUS_TYPE_UINT16, &port,
844 DBUS_TYPE_INVALID) ||
846 read_strlst(m, 8, &strlst) < 0) {
847 avahi_log_warn("Error parsing EntryGroup::AddService message");
851 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
852 avahi_string_list_free(strlst);
853 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
856 if (domain && !*domain)
862 if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, host, port, strlst) < 0) {
863 avahi_string_list_free(strlst);
864 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
867 if (!(flags & AVAHI_PUBLISH_UPDATE))
870 avahi_string_list_free(strlst);
872 return respond_ok(c, m);
874 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddServiceSubtype")) {
876 int32_t interface, protocol;
878 char *type, *name, *domain, *subtype;
880 if (!dbus_message_get_args(
882 DBUS_TYPE_INT32, &interface,
883 DBUS_TYPE_INT32, &protocol,
884 DBUS_TYPE_UINT32, &flags,
885 DBUS_TYPE_STRING, &name,
886 DBUS_TYPE_STRING, &type,
887 DBUS_TYPE_STRING, &domain,
888 DBUS_TYPE_STRING, &subtype,
889 DBUS_TYPE_INVALID) || !type || !name || !subtype) {
890 avahi_log_warn("Error parsing EntryGroup::AddServiceSubtype message");
894 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP)
895 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
897 if (domain && !*domain)
900 if (avahi_server_add_service_subtype(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, subtype) < 0)
901 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
903 if (!(flags & AVAHI_PUBLISH_UPDATE))
906 return respond_ok(c, m);
908 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "UpdateServiceTxt")) {
909 int32_t interface, protocol;
911 char *type, *name, *domain;
912 AvahiStringList *strlst;
914 if (!dbus_message_get_args(
916 DBUS_TYPE_INT32, &interface,
917 DBUS_TYPE_INT32, &protocol,
918 DBUS_TYPE_UINT32, &flags,
919 DBUS_TYPE_STRING, &name,
920 DBUS_TYPE_STRING, &type,
921 DBUS_TYPE_STRING, &domain,
922 DBUS_TYPE_INVALID) ||
924 read_strlst(m, 6, &strlst)) {
925 avahi_log_warn("Error parsing EntryGroup::UpdateServiceTxt message");
929 if (domain && !*domain)
932 if (avahi_server_update_service_txt_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, strlst) < 0) {
933 avahi_string_list_free(strlst);
934 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
937 avahi_string_list_free(strlst);
939 return respond_ok(c, m);
941 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
942 int32_t interface, protocol;
944 char *name, *address;
947 if (!dbus_message_get_args(
949 DBUS_TYPE_INT32, &interface,
950 DBUS_TYPE_INT32, &protocol,
951 DBUS_TYPE_UINT32, &flags,
952 DBUS_TYPE_STRING, &name,
953 DBUS_TYPE_STRING, &address,
954 DBUS_TYPE_INVALID) || !name || !address) {
955 avahi_log_warn("Error parsing EntryGroup::AddAddress message");
959 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP)
960 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
962 if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a)))
963 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
965 if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, &a) < 0)
966 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
968 if (!(flags & AVAHI_PUBLISH_UPDATE))
971 return respond_ok(c, m);
974 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
977 if (dbus_error_is_set(&error))
978 dbus_error_free(&error);
980 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
983 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) {
984 SyncHostNameResolverInfo *i = userdata;
990 if (event == AVAHI_RESOLVER_FOUND) {
991 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
992 int32_t i_interface, i_protocol, i_aprotocol;
997 avahi_address_snprint(t, sizeof(t), a);
999 i_interface = (int32_t) interface;
1000 i_protocol = (int32_t) protocol;
1001 i_aprotocol = (int32_t) a->proto;
1002 u_flags = (uint32_t) flags;
1004 reply = dbus_message_new_method_return(i->message);
1005 dbus_message_append_args(
1007 DBUS_TYPE_INT32, &i_interface,
1008 DBUS_TYPE_INT32, &i_protocol,
1009 DBUS_TYPE_STRING, &host_name,
1010 DBUS_TYPE_INT32, &i_aprotocol,
1011 DBUS_TYPE_STRING, &pt,
1012 DBUS_TYPE_UINT32, &u_flags,
1015 dbus_connection_send(server->bus, reply, NULL);
1016 dbus_message_unref(reply);
1018 assert(event == AVAHI_RESOLVER_FAILURE);
1019 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1022 sync_host_name_resolver_free(i);
1025 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) {
1026 SyncAddressResolverInfo *i = userdata;
1032 if (event == AVAHI_RESOLVER_FOUND) {
1033 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1034 int32_t i_interface, i_protocol, i_aprotocol;
1039 avahi_address_snprint(t, sizeof(t), address);
1041 i_interface = (int32_t) interface;
1042 i_protocol = (int32_t) protocol;
1043 i_aprotocol = (int32_t) address->proto;
1044 u_flags = (uint32_t) flags;
1046 reply = dbus_message_new_method_return(i->message);
1047 dbus_message_append_args(
1049 DBUS_TYPE_INT32, &i_interface,
1050 DBUS_TYPE_INT32, &i_protocol,
1051 DBUS_TYPE_INT32, &i_aprotocol,
1052 DBUS_TYPE_STRING, &pt,
1053 DBUS_TYPE_STRING, &host_name,
1054 DBUS_TYPE_UINT32, &u_flags,
1057 dbus_connection_send(server->bus, reply, NULL);
1058 dbus_message_unref(reply);
1060 assert(event == AVAHI_RESOLVER_FAILURE);
1061 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1064 sync_address_resolver_free(i);
1067 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1069 DomainBrowserInfo *i = userdata;
1075 dbus_error_init(&error);
1077 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1078 dbus_message_get_interface(m),
1079 dbus_message_get_path(m),
1080 dbus_message_get_member(m));
1083 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1084 return handle_introspect(c, m, "DomainBrowser.introspect");
1086 /* Access control */
1087 if (strcmp(dbus_message_get_sender(m), i->client->name))
1088 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1090 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
1092 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1093 avahi_log_warn("Error parsing DomainBrowser::Free message");
1097 domain_browser_free(i);
1098 return respond_ok(c, m);
1102 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1105 if (dbus_error_is_set(&error))
1106 dbus_error_free(&error);
1108 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1111 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1112 DomainBrowserInfo *i = userdata;
1114 int32_t i_interface, i_protocol;
1120 i_interface = (int32_t) interface;
1121 i_protocol = (int32_t) protocol;
1122 u_flags = (uint32_t) flags;
1124 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, map_browse_signal_name(event));
1126 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1128 dbus_message_append_args(
1130 DBUS_TYPE_INT32, &i_interface,
1131 DBUS_TYPE_INT32, &i_protocol,
1132 DBUS_TYPE_STRING, &domain,
1133 DBUS_TYPE_UINT32, &u_flags,
1135 } else if (event == AVAHI_BROWSER_FAILURE)
1136 append_server_error(m);
1138 dbus_message_set_destination(m, i->client->name);
1139 dbus_connection_send(server->bus, m, NULL);
1140 dbus_message_unref(m);
1143 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1145 ServiceTypeBrowserInfo *i = userdata;
1151 dbus_error_init(&error);
1153 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1154 dbus_message_get_interface(m),
1155 dbus_message_get_path(m),
1156 dbus_message_get_member(m));
1159 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1160 return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
1162 /* Access control */
1163 if (strcmp(dbus_message_get_sender(m), i->client->name))
1164 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1166 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
1168 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1169 avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
1173 service_type_browser_free(i);
1174 return respond_ok(c, m);
1178 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1181 if (dbus_error_is_set(&error))
1182 dbus_error_free(&error);
1184 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1187 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1188 ServiceTypeBrowserInfo *i = userdata;
1190 int32_t i_interface, i_protocol;
1196 i_interface = (int32_t) interface;
1197 i_protocol = (int32_t) protocol;
1198 u_flags = (uint32_t) flags;
1200 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, map_browse_signal_name(event));
1202 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1205 dbus_message_append_args(
1207 DBUS_TYPE_INT32, &i_interface,
1208 DBUS_TYPE_INT32, &i_protocol,
1209 DBUS_TYPE_STRING, &type,
1210 DBUS_TYPE_STRING, &domain,
1211 DBUS_TYPE_UINT32, &u_flags,
1213 } else if (event == AVAHI_BROWSER_FAILURE)
1214 append_server_error(m);
1216 dbus_message_set_destination(m, i->client->name);
1217 dbus_connection_send(server->bus, m, NULL);
1218 dbus_message_unref(m);
1221 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1223 ServiceBrowserInfo *i = userdata;
1229 dbus_error_init(&error);
1231 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1232 dbus_message_get_interface(m),
1233 dbus_message_get_path(m),
1234 dbus_message_get_member(m));
1237 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1238 return handle_introspect(c, m, "ServiceBrowser.Introspect");
1240 /* Access control */
1241 if (strcmp(dbus_message_get_sender(m), i->client->name))
1242 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1244 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
1246 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1247 avahi_log_warn("Error parsing ServiceBrowser::Free message");
1251 service_browser_free(i);
1252 return respond_ok(c, m);
1256 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1259 if (dbus_error_is_set(&error))
1260 dbus_error_free(&error);
1262 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1265 static int is_our_own_service(Client *c, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain) {
1266 AvahiSEntryGroup *g;
1269 if (avahi_server_get_group_of_service(avahi_server, interface, protocol, name, type, domain, &g) == AVAHI_OK) {
1270 EntryGroupInfo *egi;
1272 for (egi = c->entry_groups; egi; egi = egi->entry_groups_next)
1273 if (egi->entry_group == g)
1280 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) {
1281 ServiceBrowserInfo *i = userdata;
1283 int32_t i_interface, i_protocol;
1289 i_interface = (int32_t) interface;
1290 i_protocol = (int32_t) protocol;
1291 u_flags = (uint32_t) flags;
1293 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, map_browse_signal_name(event));
1295 if (event == AVAHI_BROWSER_NEW) {
1296 /* Patch in AVAHI_LOOKUP_RESULT_OUR_OWN */
1298 if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1299 flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1302 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1307 dbus_message_append_args(
1309 DBUS_TYPE_INT32, &i_interface,
1310 DBUS_TYPE_INT32, &i_protocol,
1311 DBUS_TYPE_STRING, &name,
1312 DBUS_TYPE_STRING, &type,
1313 DBUS_TYPE_STRING, &domain,
1314 DBUS_TYPE_UINT32, &u_flags,
1316 } else if (event == AVAHI_BROWSER_FAILURE)
1317 append_server_error(m);
1319 dbus_message_set_destination(m, i->client->name);
1320 dbus_connection_send(server->bus, m, NULL);
1321 dbus_message_unref(m);
1324 static void append_string_list(DBusMessage *reply, AvahiStringList *txt) {
1326 DBusMessageIter iter, sub;
1330 dbus_message_iter_init_append(reply, &iter);
1331 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1333 for (p = txt; p; p = p->next) {
1334 DBusMessageIter sub2;
1335 const uint8_t *data = p->text;
1337 dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1338 dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
1339 dbus_message_iter_close_container(&sub, &sub2);
1342 dbus_message_iter_close_container(&iter, &sub);
1345 static void sync_service_resolver_callback(
1346 AvahiSServiceResolver *r,
1347 AvahiIfIndex interface,
1348 AvahiProtocol protocol,
1349 AvahiResolverEvent event,
1353 const char *host_name,
1354 const AvahiAddress *a,
1356 AvahiStringList *txt,
1357 AvahiLookupResultFlags flags,
1360 SyncServiceResolverInfo *i = userdata;
1365 if (event == AVAHI_RESOLVER_FOUND) {
1366 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1367 int32_t i_interface, i_protocol, i_aprotocol;
1377 avahi_address_snprint(t, sizeof(t), a);
1381 /* Patch in AVAHI_LOOKUP_RESULT_OUR_OWN */
1383 if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1384 flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1386 i_interface = (int32_t) interface;
1387 i_protocol = (int32_t) protocol;
1389 i_aprotocol = (int32_t) a->proto;
1391 i_aprotocol = AVAHI_PROTO_UNSPEC;
1392 u_flags = (uint32_t) flags;
1394 reply = dbus_message_new_method_return(i->message);
1395 dbus_message_append_args(
1397 DBUS_TYPE_INT32, &i_interface,
1398 DBUS_TYPE_INT32, &i_protocol,
1399 DBUS_TYPE_STRING, &name,
1400 DBUS_TYPE_STRING, &type,
1401 DBUS_TYPE_STRING, &domain,
1402 DBUS_TYPE_STRING, &host_name,
1403 DBUS_TYPE_INT32, &i_aprotocol,
1404 DBUS_TYPE_STRING, &pt,
1405 DBUS_TYPE_UINT16, &port,
1408 append_string_list(reply, txt);
1410 dbus_message_append_args(
1412 DBUS_TYPE_UINT32, &u_flags,
1415 dbus_connection_send(server->bus, reply, NULL);
1416 dbus_message_unref(reply);
1418 assert(event == AVAHI_RESOLVER_FAILURE);
1420 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1423 sync_service_resolver_free(i);
1426 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) {
1427 AsyncAddressResolverInfo *i = userdata;
1433 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, map_resolve_signal_name(event));
1435 if (event == AVAHI_RESOLVER_FOUND) {
1436 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1437 int32_t i_interface, i_protocol, i_aprotocol;
1442 avahi_address_snprint(t, sizeof(t), address);
1444 i_interface = (int32_t) interface;
1445 i_protocol = (int32_t) protocol;
1446 i_aprotocol = (int32_t) address->proto;
1447 u_flags = (uint32_t) flags;
1449 dbus_message_append_args(
1451 DBUS_TYPE_INT32, &i_interface,
1452 DBUS_TYPE_INT32, &i_protocol,
1453 DBUS_TYPE_INT32, &i_aprotocol,
1454 DBUS_TYPE_STRING, &pt,
1455 DBUS_TYPE_STRING, &host_name,
1456 DBUS_TYPE_UINT32, &u_flags,
1460 assert(event == AVAHI_RESOLVER_FAILURE);
1461 append_server_error(reply);
1464 dbus_message_set_destination(reply, i->client->name);
1465 dbus_connection_send(server->bus, reply, NULL);
1466 dbus_message_unref(reply);
1469 static DBusHandlerResult msg_async_address_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1471 AsyncAddressResolverInfo *i = userdata;
1477 dbus_error_init(&error);
1479 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1480 dbus_message_get_interface(m),
1481 dbus_message_get_path(m),
1482 dbus_message_get_member(m));
1485 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1486 return handle_introspect(c, m, "AddressResolver.Introspect");
1488 /* Access control */
1489 if (strcmp(dbus_message_get_sender(m), i->client->name))
1490 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1492 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Free")) {
1494 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1495 avahi_log_warn("Error parsing AddressResolver::Free message");
1499 async_address_resolver_free(i);
1500 return respond_ok(c, m);
1504 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1507 if (dbus_error_is_set(&error))
1508 dbus_error_free(&error);
1510 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1513 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) {
1514 AsyncHostNameResolverInfo *i = userdata;
1520 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, map_resolve_signal_name(event));
1522 if (event == AVAHI_RESOLVER_FOUND) {
1523 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1524 int32_t i_interface, i_protocol, i_aprotocol;
1529 avahi_address_snprint(t, sizeof(t), a);
1531 i_interface = (int32_t) interface;
1532 i_protocol = (int32_t) protocol;
1533 i_aprotocol = (int32_t) a->proto;
1534 u_flags = (uint32_t) flags;
1536 dbus_message_append_args(
1538 DBUS_TYPE_INT32, &i_interface,
1539 DBUS_TYPE_INT32, &i_protocol,
1540 DBUS_TYPE_STRING, &host_name,
1541 DBUS_TYPE_INT32, &i_aprotocol,
1542 DBUS_TYPE_STRING, &pt,
1543 DBUS_TYPE_UINT32, &u_flags,
1546 assert(event == AVAHI_RESOLVER_FAILURE);
1547 append_server_error(reply);
1550 dbus_message_set_destination(reply, i->client->name);
1551 dbus_connection_send(server->bus, reply, NULL);
1552 dbus_message_unref(reply);
1555 static DBusHandlerResult msg_async_host_name_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1557 AsyncHostNameResolverInfo *i = userdata;
1563 dbus_error_init(&error);
1565 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1566 dbus_message_get_interface(m),
1567 dbus_message_get_path(m),
1568 dbus_message_get_member(m));
1571 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1572 return handle_introspect(c, m, "HostNameResolver.Introspect");
1574 /* Access control */
1575 if (strcmp(dbus_message_get_sender(m), i->client->name))
1576 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1578 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, "Free")) {
1580 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1581 avahi_log_warn("Error parsing HostNameResolver::Free message");
1585 async_host_name_resolver_free(i);
1586 return respond_ok(c, m);
1589 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1592 if (dbus_error_is_set(&error))
1593 dbus_error_free(&error);
1595 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1598 static void async_service_resolver_callback(
1599 AvahiSServiceResolver *r,
1600 AvahiIfIndex interface,
1601 AvahiProtocol protocol,
1602 AvahiResolverEvent event,
1606 const char *host_name,
1607 const AvahiAddress *a,
1609 AvahiStringList *txt,
1610 AvahiLookupResultFlags flags,
1613 AsyncServiceResolverInfo *i = userdata;
1619 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, map_resolve_signal_name(event));
1621 if (event == AVAHI_RESOLVER_FOUND) {
1622 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1623 int32_t i_interface, i_protocol, i_aprotocol;
1628 /* avahi_log_debug(__FILE__": [%s] Successfully resolved service <%s.%s.%s>", i->path, name, type, domain); */
1631 avahi_address_snprint(t, sizeof(t), a);
1638 if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1639 flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1641 i_interface = (int32_t) interface;
1642 i_protocol = (int32_t) protocol;
1644 i_aprotocol = (int32_t) a->proto;
1646 i_aprotocol = AVAHI_PROTO_UNSPEC;
1647 u_flags = (uint32_t) flags;
1649 dbus_message_append_args(
1651 DBUS_TYPE_INT32, &i_interface,
1652 DBUS_TYPE_INT32, &i_protocol,
1653 DBUS_TYPE_STRING, &name,
1654 DBUS_TYPE_STRING, &type,
1655 DBUS_TYPE_STRING, &domain,
1656 DBUS_TYPE_STRING, &host_name,
1657 DBUS_TYPE_INT32, &i_aprotocol,
1658 DBUS_TYPE_STRING, &pt,
1659 DBUS_TYPE_UINT16, &port,
1662 append_string_list(reply, txt);
1664 dbus_message_append_args(
1666 DBUS_TYPE_UINT32, &u_flags,
1669 assert(event == AVAHI_RESOLVER_FAILURE);
1670 append_server_error(reply);
1673 dbus_message_set_destination(reply, i->client->name);
1674 dbus_connection_send(server->bus, reply, NULL);
1675 dbus_message_unref(reply);
1678 static DBusHandlerResult msg_async_service_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1680 AsyncServiceResolverInfo *i = userdata;
1686 dbus_error_init(&error);
1688 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1689 dbus_message_get_interface(m),
1690 dbus_message_get_path(m),
1691 dbus_message_get_member(m));
1694 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1695 return handle_introspect(c, m, "ServiceResolver.Introspect");
1697 /* Access control */
1698 if (strcmp(dbus_message_get_sender(m), i->client->name))
1699 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1701 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, "Free")) {
1703 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1704 avahi_log_warn("Error parsing ServiceResolver::Free message");
1708 async_service_resolver_free(i);
1709 return respond_ok(c, m);
1712 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1715 if (dbus_error_is_set(&error))
1716 dbus_error_free(&error);
1718 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1721 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1724 dbus_error_init(&error);
1726 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1727 dbus_message_get_interface(m),
1728 dbus_message_get_path(m),
1729 dbus_message_get_member(m));
1731 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1732 return handle_introspect(c, m, "Server.introspect");
1734 else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1736 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1737 avahi_log_warn("Error parsing Server::GetHostName message");
1741 return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1743 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1745 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1746 avahi_log_warn("Error parsing Server::GetDomainName message");
1750 return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1752 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1754 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1755 avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1759 return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1761 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1763 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1764 avahi_log_warn("Error parsing Server::GetVersionString message");
1768 return respond_string(c, m, PACKAGE_STRING);
1770 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1771 AvahiServerState state;
1773 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1774 avahi_log_warn("Error parsing Server::GetState message");
1778 state = avahi_server_get_state(avahi_server);
1779 return respond_int32(c, m, (int32_t) state);
1781 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetLocalServiceCookie")) {
1783 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1784 avahi_log_warn("Error parsing Server::GetLocalServiceCookie message");
1788 return respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server));
1790 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1795 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1796 avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1800 #ifdef VALGRIND_WORKAROUND
1801 return respond_string(c, m, "blah");
1804 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1805 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1807 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1808 return respond_error(c, m, AVAHI_ERR_OS, txt);
1811 memset(&ifr, 0, sizeof(ifr));
1812 ifr.ifr_ifindex = idx;
1814 if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) {
1816 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1818 return respond_error(c, m, AVAHI_ERR_OS, txt);
1823 return respond_string(c, m, ifr.ifr_name);
1826 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1831 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1832 avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1836 #ifdef VALGRIND_WORKAROUND
1837 return respond_int32(c, m, 1);
1839 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1840 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1842 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1843 return respond_error(c, m, AVAHI_ERR_OS, txt);
1846 memset(&ifr, 0, sizeof(ifr));
1847 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", n);
1849 if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
1851 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1853 return respond_error(c, m, AVAHI_ERR_OS, txt);
1858 return respond_int32(c, m, ifr.ifr_ifindex);
1861 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1864 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1865 avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1869 t = avahi_alternative_host_name(n);
1870 respond_string(c, m, t);
1873 return DBUS_HANDLER_RESULT_HANDLED;
1875 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1878 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1879 avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1883 t = avahi_alternative_service_name(n);
1884 respond_string(c, m, t);
1887 return DBUS_HANDLER_RESULT_HANDLED;
1889 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1892 static const DBusObjectPathVTable vtable = {
1894 msg_entry_group_impl,
1901 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1902 avahi_log_warn("Error parsing Server::EntryGroupNew message");
1906 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1907 avahi_log_warn("Too many clients, client request failed.");
1908 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1911 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1912 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1913 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1916 i = avahi_new(EntryGroupInfo, 1);
1917 i->id = ++client->current_id;
1919 i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1921 AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1922 client->n_objects++;
1924 if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1925 entry_group_free(i);
1926 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1929 dbus_connection_register_object_path(c, i->path, &vtable, i);
1930 return respond_path(c, m, i->path);
1932 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1934 int32_t interface, protocol, aprotocol;
1937 SyncHostNameResolverInfo *i;
1939 if (!dbus_message_get_args(
1941 DBUS_TYPE_INT32, &interface,
1942 DBUS_TYPE_INT32, &protocol,
1943 DBUS_TYPE_STRING, &name,
1944 DBUS_TYPE_INT32, &aprotocol,
1945 DBUS_TYPE_UINT32, &flags,
1946 DBUS_TYPE_INVALID) || !name) {
1947 avahi_log_warn("Error parsing Server::ResolveHostName message");
1951 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1952 avahi_log_warn("Too many clients, client request failed.");
1953 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1956 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1957 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1958 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1961 i = avahi_new(SyncHostNameResolverInfo, 1);
1963 i->message = dbus_message_ref(m);
1964 AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i);
1965 client->n_objects++;
1967 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))) {
1968 sync_host_name_resolver_free(i);
1969 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1972 return DBUS_HANDLER_RESULT_HANDLED;
1974 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1976 int32_t interface, protocol;
1979 SyncAddressResolverInfo *i;
1982 if (!dbus_message_get_args(
1984 DBUS_TYPE_INT32, &interface,
1985 DBUS_TYPE_INT32, &protocol,
1986 DBUS_TYPE_STRING, &address,
1987 DBUS_TYPE_UINT32, &flags,
1988 DBUS_TYPE_INVALID) || !address) {
1989 avahi_log_warn("Error parsing Server::ResolveAddress message");
1993 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
1994 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
1996 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1997 avahi_log_warn("Too many clients, client request failed.");
1998 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2001 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2002 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2003 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2006 i = avahi_new(SyncAddressResolverInfo, 1);
2008 i->message = dbus_message_ref(m);
2009 AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i);
2010 client->n_objects++;
2012 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, sync_address_resolver_callback, i))) {
2013 sync_address_resolver_free(i);
2014 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2017 return DBUS_HANDLER_RESULT_HANDLED;
2019 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
2021 DomainBrowserInfo *i;
2022 static const DBusObjectPathVTable vtable = {
2024 msg_domain_browser_impl,
2030 int32_t interface, protocol, type;
2034 if (!dbus_message_get_args(
2036 DBUS_TYPE_INT32, &interface,
2037 DBUS_TYPE_INT32, &protocol,
2038 DBUS_TYPE_STRING, &domain,
2039 DBUS_TYPE_INT32, &type,
2040 DBUS_TYPE_UINT32, &flags,
2041 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
2042 avahi_log_warn("Error parsing Server::DomainBrowserNew message");
2046 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2047 avahi_log_warn("Too many clients, client request failed.");
2048 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2051 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2052 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2053 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2059 i = avahi_new(DomainBrowserInfo, 1);
2060 i->id = ++client->current_id;
2062 i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
2063 AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
2064 client->n_objects++;
2066 if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, (AvahiLookupFlags) flags, domain_browser_callback, i))) {
2067 domain_browser_free(i);
2068 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2071 dbus_connection_register_object_path(c, i->path, &vtable, i);
2072 return respond_path(c, m, i->path);
2074 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
2076 ServiceTypeBrowserInfo *i;
2077 static const DBusObjectPathVTable vtable = {
2079 msg_service_type_browser_impl,
2085 int32_t interface, protocol;
2089 if (!dbus_message_get_args(
2091 DBUS_TYPE_INT32, &interface,
2092 DBUS_TYPE_INT32, &protocol,
2093 DBUS_TYPE_STRING, &domain,
2094 DBUS_TYPE_UINT32, &flags,
2095 DBUS_TYPE_INVALID)) {
2096 avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
2100 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2101 avahi_log_warn("Too many clients, client request failed.");
2102 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2106 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2107 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2108 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2114 i = avahi_new(ServiceTypeBrowserInfo, 1);
2115 i->id = ++client->current_id;
2117 i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
2118 AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
2119 client->n_objects++;
2121 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))) {
2122 service_type_browser_free(i);
2123 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2126 dbus_connection_register_object_path(c, i->path, &vtable, i);
2127 return respond_path(c, m, i->path);
2129 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
2131 ServiceBrowserInfo *i;
2132 static const DBusObjectPathVTable vtable = {
2134 msg_service_browser_impl,
2140 int32_t interface, protocol;
2142 char *domain, *type;
2144 if (!dbus_message_get_args(
2146 DBUS_TYPE_INT32, &interface,
2147 DBUS_TYPE_INT32, &protocol,
2148 DBUS_TYPE_STRING, &type,
2149 DBUS_TYPE_STRING, &domain,
2150 DBUS_TYPE_UINT32, &flags,
2151 DBUS_TYPE_INVALID) || !type) {
2152 avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
2156 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2157 avahi_log_warn("Too many clients, client request failed.");
2158 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2162 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2163 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2164 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2170 i = avahi_new(ServiceBrowserInfo, 1);
2171 i->id = ++client->current_id;
2173 i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
2174 AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
2175 client->n_objects++;
2177 if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, (AvahiLookupFlags) flags, service_browser_callback, i))) {
2178 service_browser_free(i);
2179 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2182 dbus_connection_register_object_path(c, i->path, &vtable, i);
2183 return respond_path(c, m, i->path);
2185 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
2187 int32_t interface, protocol, aprotocol;
2189 char *name, *type, *domain;
2190 SyncServiceResolverInfo *i;
2192 if (!dbus_message_get_args(
2194 DBUS_TYPE_INT32, &interface,
2195 DBUS_TYPE_INT32, &protocol,
2196 DBUS_TYPE_STRING, &name,
2197 DBUS_TYPE_STRING, &type,
2198 DBUS_TYPE_STRING, &domain,
2199 DBUS_TYPE_INT32, &aprotocol,
2200 DBUS_TYPE_UINT32, &flags,
2201 DBUS_TYPE_INVALID) || !type) {
2202 avahi_log_warn("Error parsing Server::ResolveService message");
2206 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2207 avahi_log_warn("Too many clients, client request failed.");
2208 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2211 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2212 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2213 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2222 i = avahi_new(SyncServiceResolverInfo, 1);
2224 i->message = dbus_message_ref(m);
2225 AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i);
2226 client->n_objects++;
2228 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))) {
2229 sync_service_resolver_free(i);
2230 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2233 return DBUS_HANDLER_RESULT_HANDLED;
2235 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) {
2237 int32_t interface, protocol, aprotocol;
2239 char *name, *type, *domain;
2240 AsyncServiceResolverInfo *i;
2241 static const DBusObjectPathVTable vtable = {
2243 msg_async_service_resolver_impl,
2250 if (!dbus_message_get_args(
2252 DBUS_TYPE_INT32, &interface,
2253 DBUS_TYPE_INT32, &protocol,
2254 DBUS_TYPE_STRING, &name,
2255 DBUS_TYPE_STRING, &type,
2256 DBUS_TYPE_STRING, &domain,
2257 DBUS_TYPE_INT32, &aprotocol,
2258 DBUS_TYPE_UINT32, &flags,
2259 DBUS_TYPE_INVALID) || !type) {
2260 avahi_log_warn("Error parsing Server::ServiceResolverNew message");
2264 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2265 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2266 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2269 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2270 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2271 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2280 i = avahi_new(AsyncServiceResolverInfo, 1);
2281 i->id = ++client->current_id;
2283 i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
2284 AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i);
2285 client->n_objects++;
2287 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))) {
2288 async_service_resolver_free(i);
2289 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2292 /* avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */
2294 dbus_connection_register_object_path(c, i->path, &vtable, i);
2295 return respond_path(c, m, i->path);
2297 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew")) {
2299 int32_t interface, protocol, aprotocol;
2302 AsyncHostNameResolverInfo *i;
2303 static const DBusObjectPathVTable vtable = {
2305 msg_async_host_name_resolver_impl,
2312 if (!dbus_message_get_args(
2314 DBUS_TYPE_INT32, &interface,
2315 DBUS_TYPE_INT32, &protocol,
2316 DBUS_TYPE_STRING, &name,
2317 DBUS_TYPE_INT32, &aprotocol,
2318 DBUS_TYPE_UINT32, &flags,
2319 DBUS_TYPE_INVALID) || !name) {
2320 avahi_log_warn("Error parsing Server::HostNameResolverNew message");
2324 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2325 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2326 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2329 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2330 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2331 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2334 i = avahi_new(AsyncHostNameResolverInfo, 1);
2335 i->id = ++client->current_id;
2337 i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
2338 AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i);
2339 client->n_objects++;
2341 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))) {
2342 async_host_name_resolver_free(i);
2343 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2346 dbus_connection_register_object_path(c, i->path, &vtable, i);
2347 return respond_path(c, m, i->path);
2349 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew")) {
2351 int32_t interface, protocol;
2354 AsyncAddressResolverInfo *i;
2356 static const DBusObjectPathVTable vtable = {
2358 msg_async_address_resolver_impl,
2365 if (!dbus_message_get_args(
2367 DBUS_TYPE_INT32, &interface,
2368 DBUS_TYPE_INT32, &protocol,
2369 DBUS_TYPE_STRING, &address,
2370 DBUS_TYPE_UINT32, &flags,
2371 DBUS_TYPE_INVALID) || !address) {
2372 avahi_log_warn("Error parsing Server::AddressResolverNew message");
2376 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
2377 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
2379 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2380 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2381 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2384 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2385 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2386 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2389 i = avahi_new(AsyncAddressResolverInfo, 1);
2390 i->id = ++client->current_id;
2392 i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
2393 AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i);
2394 client->n_objects++;
2396 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, async_address_resolver_callback, i))) {
2397 async_address_resolver_free(i);
2398 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2401 dbus_connection_register_object_path(c, i->path, &vtable, i);
2402 return respond_path(c, m, i->path);
2405 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
2408 if (dbus_error_is_set(&error))
2409 dbus_error_free(&error);
2411 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2414 void dbus_protocol_server_state_changed(AvahiServerState state) {
2421 m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
2422 t = (int32_t) state;
2423 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
2424 dbus_connection_send(server->bus, m, NULL);
2425 dbus_message_unref(m);
2428 int dbus_protocol_setup(const AvahiPoll *poll_api) {
2431 static const DBusObjectPathVTable server_vtable = {
2440 dbus_error_init(&error);
2442 server = avahi_new(Server, 1);
2443 AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
2444 server->current_id = 0;
2445 server->n_clients = 0;
2447 if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
2448 assert(dbus_error_is_set(&error));
2449 avahi_log_error("dbus_bus_get(): %s", error.message);
2453 if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) {
2454 avahi_log_error("avahi_dbus_connection_glue() failed");
2458 if (dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
2459 if (dbus_error_is_set(&error)) {
2460 avahi_log_error("dbus_bus_request_name(): %s", error.message);
2464 avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'");
2468 if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) {
2469 avahi_log_error("dbus_connection_add_filter() failed");
2473 dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
2475 if (dbus_error_is_set(&error)) {
2476 avahi_log_error("dbus_bus_add_match(): %s", error.message);
2480 if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
2481 avahi_log_error("dbus_connection_register_object_path() failed");
2489 dbus_connection_disconnect(server->bus);
2490 dbus_connection_unref(server->bus);
2493 if (dbus_error_is_set(&error))
2494 dbus_error_free(&error);
2501 void dbus_protocol_shutdown(void) {
2505 while (server->clients)
2506 client_free(server->clients);
2508 assert(server->n_clients == 0);
2511 dbus_connection_disconnect(server->bus);
2512 dbus_connection_unref(server->bus);