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 DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
702 EntryGroupInfo *i = userdata;
708 dbus_error_init(&error);
710 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
711 dbus_message_get_interface(m),
712 dbus_message_get_path(m),
713 dbus_message_get_member(m));
716 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
717 return handle_introspect(c, m, "EntryGroup.introspect");
720 if (strcmp(dbus_message_get_sender(m), i->client->name))
721 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
723 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) {
725 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
726 avahi_log_warn("Error parsing EntryGroup::Free message");
731 return respond_ok(c, m);
733 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Commit")) {
735 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
736 avahi_log_warn("Error parsing EntryGroup::Commit message");
740 avahi_s_entry_group_commit(i->entry_group);
741 return respond_ok(c, m);
744 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Reset")) {
746 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
747 avahi_log_warn("Error parsing EntryGroup::Reset message");
751 avahi_s_entry_group_reset(i->entry_group);
753 return respond_ok(c, m);
755 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) {
759 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
760 avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
764 b = !!avahi_s_entry_group_is_empty(i->entry_group);
766 reply = dbus_message_new_method_return(m);
767 dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
768 dbus_connection_send(c, reply, NULL);
769 dbus_message_unref(reply);
771 return DBUS_HANDLER_RESULT_HANDLED;
773 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
774 AvahiEntryGroupState state;
776 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
777 avahi_log_warn("Error parsing EntryGroup::GetState message");
781 state = avahi_s_entry_group_get_state(i->entry_group);
782 return respond_int32(c, m, (int32_t) state);
784 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
785 int32_t interface, protocol;
787 char *type, *name, *domain, *host;
789 AvahiStringList *strlst;
790 DBusMessageIter iter, sub;
793 if (!dbus_message_get_args(
795 DBUS_TYPE_INT32, &interface,
796 DBUS_TYPE_INT32, &protocol,
797 DBUS_TYPE_UINT32, &flags,
798 DBUS_TYPE_STRING, &name,
799 DBUS_TYPE_STRING, &type,
800 DBUS_TYPE_STRING, &domain,
801 DBUS_TYPE_STRING, &host,
802 DBUS_TYPE_UINT16, &port,
803 DBUS_TYPE_INVALID) || !type || !name) {
804 avahi_log_warn("Error parsing EntryGroup::AddService message");
808 dbus_message_iter_init(m, &iter);
810 for (j = 0; j < 8; j++)
811 dbus_message_iter_next(&iter);
813 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
814 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY) {
815 avahi_log_warn("Error parsing EntryGroup::AddService message 2");
820 dbus_message_iter_recurse(&iter, &sub);
823 DBusMessageIter sub2;
827 if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
830 assert(at == DBUS_TYPE_ARRAY);
832 if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) {
833 avahi_log_warn("Error parsing EntryGroup::AddService message");
837 dbus_message_iter_recurse(&sub, &sub2);
838 dbus_message_iter_get_fixed_array(&sub2, &k, &n);
839 strlst = avahi_string_list_add_arbitrary(strlst, k, n);
841 dbus_message_iter_next(&sub);
844 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
845 avahi_string_list_free(strlst);
846 avahi_log_warn("Too many entries per entry group, client request failed.");
847 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
850 if (domain && !*domain)
856 if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, host, port, strlst) < 0) {
857 avahi_string_list_free(strlst);
858 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
862 avahi_string_list_free(strlst);
864 return respond_ok(c, m);
866 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddServiceSubtype")) {
868 int32_t interface, protocol;
870 char *type, *name, *domain, *subtype;
872 if (!dbus_message_get_args(
874 DBUS_TYPE_INT32, &interface,
875 DBUS_TYPE_INT32, &protocol,
876 DBUS_TYPE_UINT32, &flags,
877 DBUS_TYPE_STRING, &name,
878 DBUS_TYPE_STRING, &type,
879 DBUS_TYPE_STRING, &domain,
880 DBUS_TYPE_STRING, &subtype,
881 DBUS_TYPE_INVALID) || !type || !name || !subtype) {
882 avahi_log_warn("Error parsing EntryGroup::AddServiceSubtype message");
886 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
887 avahi_log_warn("Too many entries per entry group, client request failed.");
888 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
891 if (domain && !*domain)
894 if (avahi_server_add_service_subtype(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, subtype) < 0)
895 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
899 return respond_ok(c, m);
901 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
902 int32_t interface, protocol;
904 char *name, *address;
907 if (!dbus_message_get_args(
909 DBUS_TYPE_INT32, &interface,
910 DBUS_TYPE_INT32, &protocol,
911 DBUS_TYPE_UINT32, &flags,
912 DBUS_TYPE_STRING, &name,
913 DBUS_TYPE_STRING, &address,
914 DBUS_TYPE_INVALID) || !name || !address) {
915 avahi_log_warn("Error parsing EntryGroup::AddAddress message");
919 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
920 avahi_log_warn("Too many entries per entry group, client request failed.");
921 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
924 if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))) {
925 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
928 if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, &a) < 0)
929 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
933 return respond_ok(c, m);
936 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
939 if (dbus_error_is_set(&error))
940 dbus_error_free(&error);
942 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
945 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) {
946 SyncHostNameResolverInfo *i = userdata;
952 if (event == AVAHI_RESOLVER_FOUND) {
953 char t[256], *pt = t;
954 int32_t i_interface, i_protocol, i_aprotocol;
959 avahi_address_snprint(t, sizeof(t), a);
961 i_interface = (int32_t) interface;
962 i_protocol = (int32_t) protocol;
963 i_aprotocol = (int32_t) a->proto;
964 u_flags = (uint32_t) flags;
966 reply = dbus_message_new_method_return(i->message);
967 dbus_message_append_args(
969 DBUS_TYPE_INT32, &i_interface,
970 DBUS_TYPE_INT32, &i_protocol,
971 DBUS_TYPE_STRING, &host_name,
972 DBUS_TYPE_INT32, &i_aprotocol,
973 DBUS_TYPE_STRING, &pt,
974 DBUS_TYPE_UINT32, &u_flags,
977 dbus_connection_send(server->bus, reply, NULL);
978 dbus_message_unref(reply);
980 assert(event == AVAHI_RESOLVER_FAILURE);
981 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
984 sync_host_name_resolver_free(i);
987 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) {
988 SyncAddressResolverInfo *i = userdata;
994 if (event == AVAHI_RESOLVER_FOUND) {
995 char t[256], *pt = t;
996 int32_t i_interface, i_protocol, i_aprotocol;
1001 avahi_address_snprint(t, sizeof(t), address);
1003 i_interface = (int32_t) interface;
1004 i_protocol = (int32_t) protocol;
1005 i_aprotocol = (int32_t) address->proto;
1006 u_flags = (uint32_t) flags;
1008 reply = dbus_message_new_method_return(i->message);
1009 dbus_message_append_args(
1011 DBUS_TYPE_INT32, &i_interface,
1012 DBUS_TYPE_INT32, &i_protocol,
1013 DBUS_TYPE_INT32, &i_aprotocol,
1014 DBUS_TYPE_STRING, &pt,
1015 DBUS_TYPE_STRING, &host_name,
1016 DBUS_TYPE_UINT32, &u_flags,
1019 dbus_connection_send(server->bus, reply, NULL);
1020 dbus_message_unref(reply);
1022 assert(event == AVAHI_RESOLVER_FAILURE);
1023 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1026 sync_address_resolver_free(i);
1029 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1031 DomainBrowserInfo *i = userdata;
1037 dbus_error_init(&error);
1039 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1040 dbus_message_get_interface(m),
1041 dbus_message_get_path(m),
1042 dbus_message_get_member(m));
1045 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1046 return handle_introspect(c, m, "DomainBrowser.introspect");
1048 /* Access control */
1049 if (strcmp(dbus_message_get_sender(m), i->client->name))
1050 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1052 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
1054 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1055 avahi_log_warn("Error parsing DomainBrowser::Free message");
1059 domain_browser_free(i);
1060 return respond_ok(c, m);
1064 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1067 if (dbus_error_is_set(&error))
1068 dbus_error_free(&error);
1070 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1073 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1074 DomainBrowserInfo *i = userdata;
1076 int32_t i_interface, i_protocol;
1082 i_interface = (int32_t) interface;
1083 i_protocol = (int32_t) protocol;
1084 u_flags = (uint32_t) flags;
1086 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, map_browse_signal_name(event));
1088 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1090 dbus_message_append_args(
1092 DBUS_TYPE_INT32, &i_interface,
1093 DBUS_TYPE_INT32, &i_protocol,
1094 DBUS_TYPE_STRING, &domain,
1095 DBUS_TYPE_UINT32, &u_flags,
1097 } else if (event == AVAHI_BROWSER_FAILURE)
1098 append_server_error(m);
1100 dbus_message_set_destination(m, i->client->name);
1101 dbus_connection_send(server->bus, m, NULL);
1102 dbus_message_unref(m);
1105 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1107 ServiceTypeBrowserInfo *i = userdata;
1113 dbus_error_init(&error);
1115 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1116 dbus_message_get_interface(m),
1117 dbus_message_get_path(m),
1118 dbus_message_get_member(m));
1121 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1122 return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
1124 /* Access control */
1125 if (strcmp(dbus_message_get_sender(m), i->client->name))
1126 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1128 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
1130 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1131 avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
1135 service_type_browser_free(i);
1136 return respond_ok(c, m);
1140 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1143 if (dbus_error_is_set(&error))
1144 dbus_error_free(&error);
1146 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1149 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1150 ServiceTypeBrowserInfo *i = userdata;
1152 int32_t i_interface, i_protocol;
1158 i_interface = (int32_t) interface;
1159 i_protocol = (int32_t) protocol;
1160 u_flags = (uint32_t) flags;
1162 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, map_browse_signal_name(event));
1164 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1167 dbus_message_append_args(
1169 DBUS_TYPE_INT32, &i_interface,
1170 DBUS_TYPE_INT32, &i_protocol,
1171 DBUS_TYPE_STRING, &type,
1172 DBUS_TYPE_STRING, &domain,
1173 DBUS_TYPE_UINT32, &u_flags,
1175 } else if (event == AVAHI_BROWSER_FAILURE)
1176 append_server_error(m);
1178 dbus_message_set_destination(m, i->client->name);
1179 dbus_connection_send(server->bus, m, NULL);
1180 dbus_message_unref(m);
1183 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1185 ServiceBrowserInfo *i = userdata;
1191 dbus_error_init(&error);
1193 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1194 dbus_message_get_interface(m),
1195 dbus_message_get_path(m),
1196 dbus_message_get_member(m));
1199 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1200 return handle_introspect(c, m, "ServiceBrowser.Introspect");
1202 /* Access control */
1203 if (strcmp(dbus_message_get_sender(m), i->client->name))
1204 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1206 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
1208 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1209 avahi_log_warn("Error parsing ServiceBrowser::Free message");
1213 service_browser_free(i);
1214 return respond_ok(c, m);
1218 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1221 if (dbus_error_is_set(&error))
1222 dbus_error_free(&error);
1224 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1227 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) {
1228 ServiceBrowserInfo *i = userdata;
1230 int32_t i_interface, i_protocol;
1236 i_interface = (int32_t) interface;
1237 i_protocol = (int32_t) protocol;
1238 u_flags = (uint32_t) flags;
1240 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, map_browse_signal_name(event));
1242 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1247 dbus_message_append_args(
1249 DBUS_TYPE_INT32, &i_interface,
1250 DBUS_TYPE_INT32, &i_protocol,
1251 DBUS_TYPE_STRING, &name,
1252 DBUS_TYPE_STRING, &type,
1253 DBUS_TYPE_STRING, &domain,
1254 DBUS_TYPE_UINT32, &u_flags,
1256 } else if (event == AVAHI_BROWSER_FAILURE)
1257 append_server_error(m);
1259 dbus_message_set_destination(m, i->client->name);
1260 dbus_connection_send(server->bus, m, NULL);
1261 dbus_message_unref(m);
1264 static void append_string_list(DBusMessage *reply, AvahiStringList *txt) {
1266 DBusMessageIter iter, sub;
1270 dbus_message_iter_init_append(reply, &iter);
1271 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1273 for (p = txt; p; p = p->next) {
1274 DBusMessageIter sub2;
1275 const uint8_t *data = p->text;
1277 dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1278 dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
1279 dbus_message_iter_close_container(&sub, &sub2);
1282 dbus_message_iter_close_container(&iter, &sub);
1285 static void sync_service_resolver_callback(
1286 AvahiSServiceResolver *r,
1287 AvahiIfIndex interface,
1288 AvahiProtocol protocol,
1289 AvahiResolverEvent event,
1293 const char *host_name,
1294 const AvahiAddress *a,
1296 AvahiStringList *txt,
1297 AvahiLookupResultFlags flags,
1300 SyncServiceResolverInfo *i = userdata;
1305 if (event == AVAHI_RESOLVER_FOUND) {
1306 char t[256], *pt = t;
1307 int32_t i_interface, i_protocol, i_aprotocol;
1317 avahi_address_snprint(t, sizeof(t), a);
1319 i_interface = (int32_t) interface;
1320 i_protocol = (int32_t) protocol;
1321 i_aprotocol = (int32_t) a->proto;
1322 u_flags = (uint32_t) flags;
1324 reply = dbus_message_new_method_return(i->message);
1325 dbus_message_append_args(
1327 DBUS_TYPE_INT32, &i_interface,
1328 DBUS_TYPE_INT32, &i_protocol,
1329 DBUS_TYPE_STRING, &name,
1330 DBUS_TYPE_STRING, &type,
1331 DBUS_TYPE_STRING, &domain,
1332 DBUS_TYPE_STRING, &host_name,
1333 DBUS_TYPE_INT32, &i_aprotocol,
1334 DBUS_TYPE_STRING, &pt,
1335 DBUS_TYPE_UINT16, &port,
1338 append_string_list(reply, txt);
1340 dbus_message_append_args(
1342 DBUS_TYPE_UINT32, &u_flags,
1345 dbus_connection_send(server->bus, reply, NULL);
1346 dbus_message_unref(reply);
1349 assert(event == AVAHI_RESOLVER_FAILURE);
1351 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1354 sync_service_resolver_free(i);
1357 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) {
1358 AsyncAddressResolverInfo *i = userdata;
1364 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, map_resolve_signal_name(event));
1366 if (event == AVAHI_RESOLVER_FOUND) {
1367 char t[256], *pt = t;
1368 int32_t i_interface, i_protocol, i_aprotocol;
1373 avahi_address_snprint(t, sizeof(t), address);
1375 i_interface = (int32_t) interface;
1376 i_protocol = (int32_t) protocol;
1377 i_aprotocol = (int32_t) address->proto;
1378 u_flags = (uint32_t) flags;
1380 dbus_message_append_args(
1382 DBUS_TYPE_INT32, &i_interface,
1383 DBUS_TYPE_INT32, &i_protocol,
1384 DBUS_TYPE_INT32, &i_aprotocol,
1385 DBUS_TYPE_STRING, &pt,
1386 DBUS_TYPE_STRING, &host_name,
1387 DBUS_TYPE_UINT32, &u_flags,
1391 assert(event == AVAHI_RESOLVER_FAILURE);
1392 append_server_error(reply);
1395 dbus_message_set_destination(reply, i->client->name);
1396 dbus_connection_send(server->bus, reply, NULL);
1397 dbus_message_unref(reply);
1400 static DBusHandlerResult msg_async_address_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1402 AsyncAddressResolverInfo *i = userdata;
1408 dbus_error_init(&error);
1410 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1411 dbus_message_get_interface(m),
1412 dbus_message_get_path(m),
1413 dbus_message_get_member(m));
1416 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1417 return handle_introspect(c, m, "AddressResolver.Introspect");
1419 /* Access control */
1420 if (strcmp(dbus_message_get_sender(m), i->client->name))
1421 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1423 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Free")) {
1425 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1426 avahi_log_warn("Error parsing AddressResolver::Free message");
1430 async_address_resolver_free(i);
1431 return respond_ok(c, m);
1435 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1438 if (dbus_error_is_set(&error))
1439 dbus_error_free(&error);
1441 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1444 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) {
1445 AsyncHostNameResolverInfo *i = userdata;
1451 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, map_resolve_signal_name(event));
1453 if (event == AVAHI_RESOLVER_FOUND) {
1454 char t[256], *pt = t;
1455 int32_t i_interface, i_protocol, i_aprotocol;
1460 avahi_address_snprint(t, sizeof(t), a);
1462 i_interface = (int32_t) interface;
1463 i_protocol = (int32_t) protocol;
1464 i_aprotocol = (int32_t) a->proto;
1465 u_flags = (uint32_t) flags;
1467 dbus_message_append_args(
1469 DBUS_TYPE_INT32, &i_interface,
1470 DBUS_TYPE_INT32, &i_protocol,
1471 DBUS_TYPE_STRING, &host_name,
1472 DBUS_TYPE_INT32, &i_aprotocol,
1473 DBUS_TYPE_STRING, &pt,
1474 DBUS_TYPE_UINT32, &u_flags,
1477 assert(event == AVAHI_RESOLVER_FAILURE);
1478 append_server_error(reply);
1481 dbus_message_set_destination(reply, i->client->name);
1482 dbus_connection_send(server->bus, reply, NULL);
1483 dbus_message_unref(reply);
1486 static DBusHandlerResult msg_async_host_name_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1488 AsyncHostNameResolverInfo *i = userdata;
1494 dbus_error_init(&error);
1496 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1497 dbus_message_get_interface(m),
1498 dbus_message_get_path(m),
1499 dbus_message_get_member(m));
1502 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1503 return handle_introspect(c, m, "HostNameResolver.Introspect");
1505 /* Access control */
1506 if (strcmp(dbus_message_get_sender(m), i->client->name))
1507 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1509 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, "Free")) {
1511 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1512 avahi_log_warn("Error parsing HostNameResolver::Free message");
1516 async_host_name_resolver_free(i);
1517 return respond_ok(c, m);
1520 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1523 if (dbus_error_is_set(&error))
1524 dbus_error_free(&error);
1526 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1529 static void async_service_resolver_callback(
1530 AvahiSServiceResolver *r,
1531 AvahiIfIndex interface,
1532 AvahiProtocol protocol,
1533 AvahiResolverEvent event,
1537 const char *host_name,
1538 const AvahiAddress *a,
1540 AvahiStringList *txt,
1541 AvahiLookupResultFlags flags,
1544 AsyncServiceResolverInfo *i = userdata;
1550 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, map_resolve_signal_name(event));
1552 if (event == AVAHI_RESOLVER_FOUND) {
1553 char t[256], *pt = t;
1554 int32_t i_interface, i_protocol, i_aprotocol;
1559 /* avahi_log_debug(__FILE__": [%s] Successfully resolved service <%s.%s.%s>", i->path, name, type, domain); */
1562 avahi_address_snprint(t, sizeof(t), a);
1567 i_interface = (int32_t) interface;
1568 i_protocol = (int32_t) protocol;
1569 i_aprotocol = (int32_t) a->proto;
1570 u_flags = (uint32_t) flags;
1572 dbus_message_append_args(
1574 DBUS_TYPE_INT32, &i_interface,
1575 DBUS_TYPE_INT32, &i_protocol,
1576 DBUS_TYPE_STRING, &name,
1577 DBUS_TYPE_STRING, &type,
1578 DBUS_TYPE_STRING, &domain,
1579 DBUS_TYPE_STRING, &host_name,
1580 DBUS_TYPE_INT32, &i_aprotocol,
1581 DBUS_TYPE_STRING, &pt,
1582 DBUS_TYPE_UINT16, &port,
1585 append_string_list(reply, txt);
1587 dbus_message_append_args(
1589 DBUS_TYPE_UINT32, &u_flags,
1592 assert(event == AVAHI_RESOLVER_FAILURE);
1593 append_server_error(reply);
1596 dbus_message_set_destination(reply, i->client->name);
1597 dbus_connection_send(server->bus, reply, NULL);
1598 dbus_message_unref(reply);
1601 static DBusHandlerResult msg_async_service_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1603 AsyncServiceResolverInfo *i = userdata;
1609 dbus_error_init(&error);
1611 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1612 dbus_message_get_interface(m),
1613 dbus_message_get_path(m),
1614 dbus_message_get_member(m));
1617 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1618 return handle_introspect(c, m, "ServiceResolver.Introspect");
1620 /* Access control */
1621 if (strcmp(dbus_message_get_sender(m), i->client->name))
1622 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1624 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, "Free")) {
1626 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1627 avahi_log_warn("Error parsing ServiceResolver::Free message");
1631 async_service_resolver_free(i);
1632 return respond_ok(c, m);
1635 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1638 if (dbus_error_is_set(&error))
1639 dbus_error_free(&error);
1641 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1644 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1647 dbus_error_init(&error);
1649 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1650 dbus_message_get_interface(m),
1651 dbus_message_get_path(m),
1652 dbus_message_get_member(m));
1654 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1655 return handle_introspect(c, m, "Server.introspect");
1657 else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1659 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1660 avahi_log_warn("Error parsing Server::GetHostName message");
1664 return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1666 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1668 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1669 avahi_log_warn("Error parsing Server::GetDomainName message");
1673 return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1675 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1677 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1678 avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1682 return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1684 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1686 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1687 avahi_log_warn("Error parsing Server::GetVersionString message");
1691 return respond_string(c, m, PACKAGE_STRING);
1693 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1694 AvahiServerState state;
1696 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1697 avahi_log_warn("Error parsing Server::GetState message");
1701 state = avahi_server_get_state(avahi_server);
1702 return respond_int32(c, m, (int32_t) state);
1704 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetLocalServiceCookie")) {
1706 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1707 avahi_log_warn("Error parsing Server::GetLocalServiceCookie message");
1711 return respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server));
1713 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "IsServiceLocal")) {
1714 int32_t interface, protocol;
1715 char *name, *type, *domain;
1718 if (!dbus_message_get_args(
1720 DBUS_TYPE_INT32, &interface,
1721 DBUS_TYPE_INT32, &protocol,
1722 DBUS_TYPE_STRING, &name,
1723 DBUS_TYPE_STRING, &type,
1724 DBUS_TYPE_STRING, &domain,
1725 DBUS_TYPE_INVALID) || !name || !type || !domain) {
1726 avahi_log_warn("Error parsing Server::IsServiceLocal message");
1730 if ((b = avahi_server_is_service_local(avahi_server, interface, protocol, name, type, domain)) < 0)
1731 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1733 return respond_boolean(c, m, b);
1735 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1740 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1741 avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1745 #ifdef VALGRIND_WORKAROUND
1746 return respond_string(c, m, "blah");
1749 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1750 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1752 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1753 return respond_error(c, m, AVAHI_ERR_OS, txt);
1756 memset(&ifr, 0, sizeof(ifr));
1757 ifr.ifr_ifindex = idx;
1759 if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) {
1761 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1763 return respond_error(c, m, AVAHI_ERR_OS, txt);
1768 return respond_string(c, m, ifr.ifr_name);
1771 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1776 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1777 avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1781 #ifdef VALGRIND_WORKAROUND
1782 return respond_int32(c, m, 1);
1784 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1785 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1787 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1788 return respond_error(c, m, AVAHI_ERR_OS, txt);
1791 memset(&ifr, 0, sizeof(ifr));
1792 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", n);
1794 if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
1796 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1798 return respond_error(c, m, AVAHI_ERR_OS, txt);
1803 return respond_int32(c, m, ifr.ifr_ifindex);
1806 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1809 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1810 avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1814 t = avahi_alternative_host_name(n);
1815 respond_string(c, m, t);
1818 return DBUS_HANDLER_RESULT_HANDLED;
1820 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1823 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1824 avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1828 t = avahi_alternative_service_name(n);
1829 respond_string(c, m, t);
1832 return DBUS_HANDLER_RESULT_HANDLED;
1834 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1837 static const DBusObjectPathVTable vtable = {
1839 msg_entry_group_impl,
1846 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1847 avahi_log_warn("Error parsing Server::EntryGroupNew message");
1851 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1852 avahi_log_warn("Too many clients, client request failed.");
1853 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1856 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1857 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1858 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1861 i = avahi_new(EntryGroupInfo, 1);
1862 i->id = ++client->current_id;
1864 i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1866 AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1867 client->n_objects++;
1869 if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1870 entry_group_free(i);
1871 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1874 dbus_connection_register_object_path(c, i->path, &vtable, i);
1875 return respond_path(c, m, i->path);
1877 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1879 int32_t interface, protocol, aprotocol;
1882 SyncHostNameResolverInfo *i;
1884 if (!dbus_message_get_args(
1886 DBUS_TYPE_INT32, &interface,
1887 DBUS_TYPE_INT32, &protocol,
1888 DBUS_TYPE_STRING, &name,
1889 DBUS_TYPE_INT32, &aprotocol,
1890 DBUS_TYPE_UINT32, &flags,
1891 DBUS_TYPE_INVALID) || !name) {
1892 avahi_log_warn("Error parsing Server::ResolveHostName message");
1896 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1897 avahi_log_warn("Too many clients, client request failed.");
1898 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1901 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1902 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1903 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1906 i = avahi_new(SyncHostNameResolverInfo, 1);
1908 i->message = dbus_message_ref(m);
1909 AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i);
1910 client->n_objects++;
1912 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))) {
1913 sync_host_name_resolver_free(i);
1914 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1917 return DBUS_HANDLER_RESULT_HANDLED;
1919 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1921 int32_t interface, protocol;
1924 SyncAddressResolverInfo *i;
1927 if (!dbus_message_get_args(
1929 DBUS_TYPE_INT32, &interface,
1930 DBUS_TYPE_INT32, &protocol,
1931 DBUS_TYPE_STRING, &address,
1932 DBUS_TYPE_UINT32, &flags,
1933 DBUS_TYPE_INVALID) || !address) {
1934 avahi_log_warn("Error parsing Server::ResolveAddress message");
1938 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
1939 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
1941 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1942 avahi_log_warn("Too many clients, client request failed.");
1943 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1946 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1947 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1948 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1951 i = avahi_new(SyncAddressResolverInfo, 1);
1953 i->message = dbus_message_ref(m);
1954 AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i);
1955 client->n_objects++;
1957 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, sync_address_resolver_callback, i))) {
1958 sync_address_resolver_free(i);
1959 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1962 return DBUS_HANDLER_RESULT_HANDLED;
1964 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
1966 DomainBrowserInfo *i;
1967 static const DBusObjectPathVTable vtable = {
1969 msg_domain_browser_impl,
1975 int32_t interface, protocol, type;
1979 if (!dbus_message_get_args(
1981 DBUS_TYPE_INT32, &interface,
1982 DBUS_TYPE_INT32, &protocol,
1983 DBUS_TYPE_STRING, &domain,
1984 DBUS_TYPE_INT32, &type,
1985 DBUS_TYPE_UINT32, &flags,
1986 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
1987 avahi_log_warn("Error parsing Server::DomainBrowserNew message");
1991 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1992 avahi_log_warn("Too many clients, client request failed.");
1993 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1996 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1997 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1998 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2004 i = avahi_new(DomainBrowserInfo, 1);
2005 i->id = ++client->current_id;
2007 i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
2008 AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
2009 client->n_objects++;
2011 if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, (AvahiLookupFlags) flags, domain_browser_callback, i))) {
2012 domain_browser_free(i);
2013 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2016 dbus_connection_register_object_path(c, i->path, &vtable, i);
2017 return respond_path(c, m, i->path);
2019 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
2021 ServiceTypeBrowserInfo *i;
2022 static const DBusObjectPathVTable vtable = {
2024 msg_service_type_browser_impl,
2030 int32_t interface, protocol;
2034 if (!dbus_message_get_args(
2036 DBUS_TYPE_INT32, &interface,
2037 DBUS_TYPE_INT32, &protocol,
2038 DBUS_TYPE_STRING, &domain,
2039 DBUS_TYPE_UINT32, &flags,
2040 DBUS_TYPE_INVALID)) {
2041 avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
2045 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2046 avahi_log_warn("Too many clients, client request failed.");
2047 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(ServiceTypeBrowserInfo, 1);
2060 i->id = ++client->current_id;
2062 i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
2063 AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
2064 client->n_objects++;
2066 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))) {
2067 service_type_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, "ServiceBrowserNew")) {
2076 ServiceBrowserInfo *i;
2077 static const DBusObjectPathVTable vtable = {
2079 msg_service_browser_impl,
2085 int32_t interface, protocol;
2087 char *domain, *type;
2089 if (!dbus_message_get_args(
2091 DBUS_TYPE_INT32, &interface,
2092 DBUS_TYPE_INT32, &protocol,
2093 DBUS_TYPE_STRING, &type,
2094 DBUS_TYPE_STRING, &domain,
2095 DBUS_TYPE_UINT32, &flags,
2096 DBUS_TYPE_INVALID) || !type) {
2097 avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
2101 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2102 avahi_log_warn("Too many clients, client request failed.");
2103 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2107 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2108 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2109 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2115 i = avahi_new(ServiceBrowserInfo, 1);
2116 i->id = ++client->current_id;
2118 i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
2119 AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
2120 client->n_objects++;
2122 if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, (AvahiLookupFlags) flags, service_browser_callback, i))) {
2123 service_browser_free(i);
2124 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2127 dbus_connection_register_object_path(c, i->path, &vtable, i);
2128 return respond_path(c, m, i->path);
2130 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
2132 int32_t interface, protocol, aprotocol;
2134 char *name, *type, *domain;
2135 SyncServiceResolverInfo *i;
2137 if (!dbus_message_get_args(
2139 DBUS_TYPE_INT32, &interface,
2140 DBUS_TYPE_INT32, &protocol,
2141 DBUS_TYPE_STRING, &name,
2142 DBUS_TYPE_STRING, &type,
2143 DBUS_TYPE_STRING, &domain,
2144 DBUS_TYPE_INT32, &aprotocol,
2145 DBUS_TYPE_UINT32, &flags,
2146 DBUS_TYPE_INVALID) || !type) {
2147 avahi_log_warn("Error parsing Server::ResolveService message");
2151 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2152 avahi_log_warn("Too many clients, client request failed.");
2153 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2156 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2157 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2158 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2167 i = avahi_new(SyncServiceResolverInfo, 1);
2169 i->message = dbus_message_ref(m);
2170 AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i);
2171 client->n_objects++;
2173 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))) {
2174 sync_service_resolver_free(i);
2175 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2178 return DBUS_HANDLER_RESULT_HANDLED;
2180 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) {
2182 int32_t interface, protocol, aprotocol;
2184 char *name, *type, *domain;
2185 AsyncServiceResolverInfo *i;
2186 static const DBusObjectPathVTable vtable = {
2188 msg_async_service_resolver_impl,
2195 if (!dbus_message_get_args(
2197 DBUS_TYPE_INT32, &interface,
2198 DBUS_TYPE_INT32, &protocol,
2199 DBUS_TYPE_STRING, &name,
2200 DBUS_TYPE_STRING, &type,
2201 DBUS_TYPE_STRING, &domain,
2202 DBUS_TYPE_INT32, &aprotocol,
2203 DBUS_TYPE_UINT32, &flags,
2204 DBUS_TYPE_INVALID) || !type) {
2205 avahi_log_warn("Error parsing Server::ServiceResolverNew message");
2209 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2210 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2211 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2214 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2215 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2216 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2225 i = avahi_new(AsyncServiceResolverInfo, 1);
2226 i->id = ++client->current_id;
2228 i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
2229 AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i);
2230 client->n_objects++;
2232 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))) {
2233 async_service_resolver_free(i);
2234 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2237 /* avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */
2239 dbus_connection_register_object_path(c, i->path, &vtable, i);
2240 return respond_path(c, m, i->path);
2242 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew")) {
2244 int32_t interface, protocol, aprotocol;
2247 AsyncHostNameResolverInfo *i;
2248 static const DBusObjectPathVTable vtable = {
2250 msg_async_host_name_resolver_impl,
2257 if (!dbus_message_get_args(
2259 DBUS_TYPE_INT32, &interface,
2260 DBUS_TYPE_INT32, &protocol,
2261 DBUS_TYPE_STRING, &name,
2262 DBUS_TYPE_INT32, &aprotocol,
2263 DBUS_TYPE_UINT32, &flags,
2264 DBUS_TYPE_INVALID) || !name) {
2265 avahi_log_warn("Error parsing Server::HostNameResolverNew message");
2269 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2270 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2271 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2274 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
2275 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2276 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2279 i = avahi_new(AsyncHostNameResolverInfo, 1);
2280 i->id = ++client->current_id;
2282 i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
2283 AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i);
2284 client->n_objects++;
2286 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))) {
2287 async_host_name_resolver_free(i);
2288 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
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, "AddressResolverNew")) {
2296 int32_t interface, protocol;
2299 AsyncAddressResolverInfo *i;
2301 static const DBusObjectPathVTable vtable = {
2303 msg_async_address_resolver_impl,
2310 if (!dbus_message_get_args(
2312 DBUS_TYPE_INT32, &interface,
2313 DBUS_TYPE_INT32, &protocol,
2314 DBUS_TYPE_STRING, &address,
2315 DBUS_TYPE_UINT32, &flags,
2316 DBUS_TYPE_INVALID) || !address) {
2317 avahi_log_warn("Error parsing Server::AddressResolverNew message");
2321 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
2322 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
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(AsyncAddressResolverInfo, 1);
2335 i->id = ++client->current_id;
2337 i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
2338 AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i);
2339 client->n_objects++;
2341 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, async_address_resolver_callback, i))) {
2342 async_address_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);
2350 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
2353 if (dbus_error_is_set(&error))
2354 dbus_error_free(&error);
2356 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2359 void dbus_protocol_server_state_changed(AvahiServerState state) {
2366 m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
2367 t = (int32_t) state;
2368 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
2369 dbus_connection_send(server->bus, m, NULL);
2370 dbus_message_unref(m);
2373 int dbus_protocol_setup(const AvahiPoll *poll_api) {
2376 static const DBusObjectPathVTable server_vtable = {
2385 dbus_error_init(&error);
2387 server = avahi_new(Server, 1);
2388 AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
2389 server->current_id = 0;
2390 server->n_clients = 0;
2392 if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
2393 assert(dbus_error_is_set(&error));
2394 avahi_log_error("dbus_bus_get(): %s", error.message);
2398 if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) {
2399 avahi_log_error("avahi_dbus_connection_glue() failed");
2403 if (dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
2404 if (dbus_error_is_set(&error)) {
2405 avahi_log_error("dbus_bus_request_name(): %s", error.message);
2409 avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'");
2413 if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) {
2414 avahi_log_error("dbus_connection_add_filter() failed");
2418 dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
2420 if (dbus_error_is_set(&error)) {
2421 avahi_log_error("dbus_bus_add_match(): %s", error.message);
2425 if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
2426 avahi_log_error("dbus_connection_register_object_path() failed");
2434 dbus_connection_disconnect(server->bus);
2435 dbus_connection_unref(server->bus);
2438 if (dbus_error_is_set(&error))
2439 dbus_error_free(&error);
2446 void dbus_protocol_shutdown(void) {
2450 while (server->clients)
2451 client_free(server->clients);
2453 assert(server->n_clients == 0);
2456 dbus_connection_disconnect(server->bus);
2457 dbus_connection_unref(server->bus);