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>
28 #include <sys/socket.h>
29 #include <netinet/in.h>
40 #include <dbus/dbus.h>
42 #include <avahi-common/dbus.h>
43 #include <avahi-common/llist.h>
44 #include <avahi-common/malloc.h>
45 #include <avahi-common/dbus.h>
46 #include <avahi-common/dbus-watch-glue.h>
47 #include <avahi-common/alternative.h>
48 #include <avahi-common/error.h>
49 #include <avahi-common/domain.h>
51 #include <avahi-core/log.h>
52 #include <avahi-core/core.h>
53 #include <avahi-core/lookup.h>
54 #include <avahi-core/publish.h>
56 #include "dbus-protocol.h"
59 typedef struct Server Server;
60 typedef struct Client Client;
61 typedef struct EntryGroupInfo EntryGroupInfo;
62 typedef struct SyncHostNameResolverInfo SyncHostNameResolverInfo;
63 typedef struct AsyncHostNameResolverInfo AsyncHostNameResolverInfo;
64 typedef struct SyncAddressResolverInfo SyncAddressResolverInfo;
65 typedef struct AsyncAddressResolverInfo AsyncAddressResolverInfo;
66 typedef struct DomainBrowserInfo DomainBrowserInfo;
67 typedef struct ServiceTypeBrowserInfo ServiceTypeBrowserInfo;
68 typedef struct ServiceBrowserInfo ServiceBrowserInfo;
69 typedef struct SyncServiceResolverInfo SyncServiceResolverInfo;
70 typedef struct AsyncServiceResolverInfo AsyncServiceResolverInfo;
72 #define CLIENTS_MAX 256
73 #define OBJECTS_PER_CLIENT_MAX 50
74 #define ENTRIES_PER_ENTRY_GROUP_MAX 20
76 /* #define VALGRIND_WORKAROUND 1 */
78 struct EntryGroupInfo {
81 AvahiSEntryGroup *entry_group;
86 AVAHI_LLIST_FIELDS(EntryGroupInfo, entry_groups);
89 struct SyncHostNameResolverInfo {
91 AvahiSHostNameResolver *host_name_resolver;
94 AVAHI_LLIST_FIELDS(SyncHostNameResolverInfo, sync_host_name_resolvers);
97 struct AsyncHostNameResolverInfo {
100 AvahiSHostNameResolver *host_name_resolver;
103 AVAHI_LLIST_FIELDS(AsyncHostNameResolverInfo, async_host_name_resolvers);
106 struct SyncAddressResolverInfo {
108 AvahiSAddressResolver *address_resolver;
109 DBusMessage *message;
111 AVAHI_LLIST_FIELDS(SyncAddressResolverInfo, sync_address_resolvers);
114 struct AsyncAddressResolverInfo {
117 AvahiSAddressResolver *address_resolver;
120 AVAHI_LLIST_FIELDS(AsyncAddressResolverInfo, async_address_resolvers);
123 struct DomainBrowserInfo {
126 AvahiSDomainBrowser *domain_browser;
129 AVAHI_LLIST_FIELDS(DomainBrowserInfo, domain_browsers);
132 struct ServiceTypeBrowserInfo {
135 AvahiSServiceTypeBrowser *service_type_browser;
138 AVAHI_LLIST_FIELDS(ServiceTypeBrowserInfo, service_type_browsers);
141 struct ServiceBrowserInfo {
144 AvahiSServiceBrowser *service_browser;
147 AVAHI_LLIST_FIELDS(ServiceBrowserInfo, service_browsers);
150 struct SyncServiceResolverInfo {
152 AvahiSServiceResolver *service_resolver;
153 DBusMessage *message;
155 AVAHI_LLIST_FIELDS(SyncServiceResolverInfo, sync_service_resolvers);
158 struct AsyncServiceResolverInfo {
161 AvahiSServiceResolver *service_resolver;
164 AVAHI_LLIST_FIELDS(AsyncServiceResolverInfo, async_service_resolvers);
173 AVAHI_LLIST_FIELDS(Client, clients);
174 AVAHI_LLIST_HEAD(EntryGroupInfo, entry_groups);
175 AVAHI_LLIST_HEAD(SyncHostNameResolverInfo, sync_host_name_resolvers);
176 AVAHI_LLIST_HEAD(AsyncHostNameResolverInfo, async_host_name_resolvers);
177 AVAHI_LLIST_HEAD(SyncAddressResolverInfo, sync_address_resolvers);
178 AVAHI_LLIST_HEAD(AsyncAddressResolverInfo, async_address_resolvers);
179 AVAHI_LLIST_HEAD(DomainBrowserInfo, domain_browsers);
180 AVAHI_LLIST_HEAD(ServiceTypeBrowserInfo, service_type_browsers);
181 AVAHI_LLIST_HEAD(ServiceBrowserInfo, service_browsers);
182 AVAHI_LLIST_HEAD(SyncServiceResolverInfo, sync_service_resolvers);
183 AVAHI_LLIST_HEAD(AsyncServiceResolverInfo, async_service_resolvers);
188 AVAHI_LLIST_HEAD(Client, clients);
193 static Server *server = NULL;
195 static void entry_group_free(EntryGroupInfo *i) {
199 avahi_s_entry_group_free(i->entry_group);
200 dbus_connection_unregister_object_path(server->bus, i->path);
202 AVAHI_LLIST_REMOVE(EntryGroupInfo, entry_groups, i->client->entry_groups, i);
204 i->client->n_objects--;
205 assert(i->client->n_objects >= 0);
210 static void sync_host_name_resolver_free(SyncHostNameResolverInfo *i) {
213 if (i->host_name_resolver)
214 avahi_s_host_name_resolver_free(i->host_name_resolver);
215 dbus_message_unref(i->message);
216 AVAHI_LLIST_REMOVE(SyncHostNameResolverInfo, sync_host_name_resolvers, i->client->sync_host_name_resolvers, i);
218 i->client->n_objects--;
219 assert(i->client->n_objects >= 0);
224 static void async_host_name_resolver_free(AsyncHostNameResolverInfo *i) {
227 if (i->host_name_resolver)
228 avahi_s_host_name_resolver_free(i->host_name_resolver);
229 dbus_connection_unregister_object_path(server->bus, i->path);
230 AVAHI_LLIST_REMOVE(AsyncHostNameResolverInfo, async_host_name_resolvers, i->client->async_host_name_resolvers, i);
232 i->client->n_objects--;
233 assert(i->client->n_objects >= 0);
238 static void sync_address_resolver_free(SyncAddressResolverInfo *i) {
241 if (i->address_resolver)
242 avahi_s_address_resolver_free(i->address_resolver);
243 dbus_message_unref(i->message);
244 AVAHI_LLIST_REMOVE(SyncAddressResolverInfo, sync_address_resolvers, i->client->sync_address_resolvers, i);
246 i->client->n_objects--;
247 assert(i->client->n_objects >= 0);
252 static void async_address_resolver_free(AsyncAddressResolverInfo *i) {
255 if (i->address_resolver)
256 avahi_s_address_resolver_free(i->address_resolver);
257 dbus_connection_unregister_object_path(server->bus, i->path);
258 AVAHI_LLIST_REMOVE(AsyncAddressResolverInfo, async_address_resolvers, i->client->async_address_resolvers, i);
260 i->client->n_objects--;
261 assert(i->client->n_objects >= 0);
266 static void domain_browser_free(DomainBrowserInfo *i) {
269 if (i->domain_browser)
270 avahi_s_domain_browser_free(i->domain_browser);
271 dbus_connection_unregister_object_path(server->bus, i->path);
273 AVAHI_LLIST_REMOVE(DomainBrowserInfo, domain_browsers, i->client->domain_browsers, i);
275 i->client->n_objects--;
276 assert(i->client->n_objects >= 0);
281 static void service_type_browser_free(ServiceTypeBrowserInfo *i) {
284 if (i->service_type_browser)
285 avahi_s_service_type_browser_free(i->service_type_browser);
286 dbus_connection_unregister_object_path(server->bus, i->path);
288 AVAHI_LLIST_REMOVE(ServiceTypeBrowserInfo, service_type_browsers, i->client->service_type_browsers, i);
290 i->client->n_objects--;
291 assert(i->client->n_objects >= 0);
296 static void service_browser_free(ServiceBrowserInfo *i) {
299 if (i->service_browser)
300 avahi_s_service_browser_free(i->service_browser);
301 dbus_connection_unregister_object_path(server->bus, i->path);
303 AVAHI_LLIST_REMOVE(ServiceBrowserInfo, service_browsers, i->client->service_browsers, i);
305 i->client->n_objects--;
306 assert(i->client->n_objects >= 0);
311 static void sync_service_resolver_free(SyncServiceResolverInfo *i) {
314 if (i->service_resolver)
315 avahi_s_service_resolver_free(i->service_resolver);
316 dbus_message_unref(i->message);
317 AVAHI_LLIST_REMOVE(SyncServiceResolverInfo, sync_service_resolvers, i->client->sync_service_resolvers, i);
319 i->client->n_objects--;
320 assert(i->client->n_objects >= 0);
325 static void async_service_resolver_free(AsyncServiceResolverInfo *i) {
328 if (i->service_resolver)
329 avahi_s_service_resolver_free(i->service_resolver);
331 dbus_connection_unregister_object_path(server->bus, i->path);
332 AVAHI_LLIST_REMOVE(AsyncServiceResolverInfo, async_service_resolvers, i->client->async_service_resolvers, i);
334 i->client->n_objects--;
335 assert(i->client->n_objects >= 0);
340 static void client_free(Client *c) {
345 while (c->entry_groups)
346 entry_group_free(c->entry_groups);
348 while (c->sync_host_name_resolvers)
349 sync_host_name_resolver_free(c->sync_host_name_resolvers);
351 while (c->async_host_name_resolvers)
352 async_host_name_resolver_free(c->async_host_name_resolvers);
354 while (c->sync_address_resolvers)
355 sync_address_resolver_free(c->sync_address_resolvers);
357 while (c->async_address_resolvers)
358 async_address_resolver_free(c->async_address_resolvers);
360 while (c->domain_browsers)
361 domain_browser_free(c->domain_browsers);
363 while (c->service_type_browsers)
364 service_type_browser_free(c->service_type_browsers);
366 while (c->service_browsers)
367 service_browser_free(c->service_browsers);
369 while (c->sync_service_resolvers)
370 sync_service_resolver_free(c->sync_service_resolvers);
372 while (c->async_service_resolvers)
373 async_service_resolver_free(c->async_service_resolvers);
375 assert(c->n_objects == 0);
378 AVAHI_LLIST_REMOVE(Client, clients, server->clients, c);
381 server->n_clients --;
382 assert(server->n_clients >= 0);
385 static Client *client_get(const char *name, int create) {
391 for (client = server->clients; client; client = client->clients_next)
392 if (!strcmp(name, client->name))
398 if (server->n_clients >= CLIENTS_MAX)
401 /* If not existant yet, create a new entry */
402 client = avahi_new(Client, 1);
403 client->id = server->current_id++;
404 client->name = avahi_strdup(name);
405 client->current_id = 0;
406 client->n_objects = 0;
408 AVAHI_LLIST_HEAD_INIT(EntryGroupInfo, client->entry_groups);
409 AVAHI_LLIST_HEAD_INIT(SyncHostNameResolverInfo, client->sync_host_name_resolvers);
410 AVAHI_LLIST_HEAD_INIT(AsyncHostNameResolverInfo, client->async_host_name_resolvers);
411 AVAHI_LLIST_HEAD_INIT(SyncAddressResolverInfo, client->sync_address_resolvers);
412 AVAHI_LLIST_HEAD_INIT(AsyncAddressResolverInfo, client->async_address_resolvers);
413 AVAHI_LLIST_HEAD_INIT(DomainBrowserInfo, client->domain_browsers);
414 AVAHI_LLIST_HEAD_INIT(ServiceTypeBrowserInfo, client->service_type_browsers);
415 AVAHI_LLIST_HEAD_INIT(ServiceBrowserInfo, client->service_browsers);
416 AVAHI_LLIST_HEAD_INIT(SyncServiceResolverInfo, client->sync_service_resolvers);
417 AVAHI_LLIST_HEAD_INIT(AsyncServiceResolverInfo, client->async_service_resolvers);
419 AVAHI_LLIST_PREPEND(Client, clients, server->clients, client);
422 assert(server->n_clients > 0);
427 static DBusHandlerResult respond_error(DBusConnection *c, DBusMessage *m, int error, const char *text) {
430 assert(-error > -AVAHI_OK);
431 assert(-error < -AVAHI_ERR_MAX);
434 text = avahi_strerror(error);
436 reply = dbus_message_new_error(m, avahi_error_number_to_dbus(error), text);
437 dbus_connection_send(c, reply, NULL);
438 dbus_message_unref(reply);
440 avahi_log_debug(__FILE__": Responding error '%s' (%i)", text, error);
442 return DBUS_HANDLER_RESULT_HANDLED;
445 static DBusHandlerResult respond_string(DBusConnection *c, DBusMessage *m, const char *text) {
448 reply = dbus_message_new_method_return(m);
449 dbus_message_append_args(reply, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID);
450 dbus_connection_send(c, reply, NULL);
451 dbus_message_unref(reply);
453 return DBUS_HANDLER_RESULT_HANDLED;
456 static DBusHandlerResult respond_int32(DBusConnection *c, DBusMessage *m, int32_t i) {
459 reply = dbus_message_new_method_return(m);
460 dbus_message_append_args(reply, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID);
461 dbus_connection_send(c, reply, NULL);
462 dbus_message_unref(reply);
464 return DBUS_HANDLER_RESULT_HANDLED;
467 static DBusHandlerResult respond_uint32(DBusConnection *c, DBusMessage *m, uint32_t u) {
470 reply = dbus_message_new_method_return(m);
471 dbus_message_append_args(reply, DBUS_TYPE_UINT32, &u, DBUS_TYPE_INVALID);
472 dbus_connection_send(c, reply, NULL);
473 dbus_message_unref(reply);
475 return DBUS_HANDLER_RESULT_HANDLED;
478 static DBusHandlerResult respond_boolean(DBusConnection *c, DBusMessage *m, int b) {
481 reply = dbus_message_new_method_return(m);
482 dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
483 dbus_connection_send(c, reply, NULL);
484 dbus_message_unref(reply);
486 return DBUS_HANDLER_RESULT_HANDLED;
489 static DBusHandlerResult respond_ok(DBusConnection *c, DBusMessage *m) {
492 reply = dbus_message_new_method_return(m);
493 dbus_connection_send(c, reply, NULL);
494 dbus_message_unref(reply);
496 return DBUS_HANDLER_RESULT_HANDLED;
499 static DBusHandlerResult respond_path(DBusConnection *c, DBusMessage *m, const char *path) {
502 reply = dbus_message_new_method_return(m);
503 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
504 dbus_connection_send(c, reply, NULL);
505 dbus_message_unref(reply);
507 return DBUS_HANDLER_RESULT_HANDLED;
510 static void append_server_error(DBusMessage *reply) {
513 t = avahi_error_number_to_dbus(avahi_server_errno(avahi_server));
515 dbus_message_append_args(
517 DBUS_TYPE_STRING, &t,
521 static char *file_get_contents(char *fname) {
529 if (!(fd = open(fname, O_RDONLY))) {
530 avahi_log_error("Failed to open %s: %s", fname, strerror(errno));
534 if (fstat(fd, &st) < 0) {
535 avahi_log_error("stat(%s) failed: %s", fname, strerror(errno));
539 if (!(S_ISREG(st.st_mode))) {
540 avahi_log_error("Invalid file %s", fname);
544 if (st.st_size > 1024*1024) { /** 1MB */
545 avahi_log_error("File too large %s", fname);
549 buf = avahi_new(char, st.st_size+1);
551 if ((size = read(fd, buf, st.st_size)) < 0) {
552 avahi_log_error("read() failed: %s\n", strerror(errno));
572 static const char *map_browse_signal_name(AvahiBrowserEvent e) {
574 case AVAHI_BROWSER_NEW : return "ItemNew";
575 case AVAHI_BROWSER_REMOVE : return "ItemRemove";
576 case AVAHI_BROWSER_FAILURE : return "Failure";
577 case AVAHI_BROWSER_CACHE_EXHAUSTED : return "CacheExhausted";
578 case AVAHI_BROWSER_ALL_FOR_NOW : return "AllForNow";
584 static const char *map_resolve_signal_name(AvahiResolverEvent e) {
586 case AVAHI_RESOLVER_FOUND : return "Found";
587 case AVAHI_RESOLVER_FAILURE : return "Failure";
594 static DBusHandlerResult handle_introspect(DBusConnection *c, DBusMessage *m, const char *fname) {
595 char *path, *contents;
602 dbus_error_init(&error);
604 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
605 avahi_log_error("Error parsing Introspect message: %s", error.message);
609 path = avahi_strdup_printf("%s/%s", AVAHI_DBUS_INTROSPECTION_DIR, fname);
610 contents = file_get_contents(path);
614 avahi_log_error("Failed to load introspection data.");
618 respond_string(c, m, contents);
619 avahi_free(contents);
621 return DBUS_HANDLER_RESULT_HANDLED;
624 if (dbus_error_is_set(&error))
625 dbus_error_free(&error);
627 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
631 static DBusHandlerResult msg_signal_filter_impl(AVAHI_GCC_UNUSED DBusConnection *c, DBusMessage *m, AVAHI_GCC_UNUSED void *userdata) {
634 dbus_error_init(&error);
636 /* avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s", */
637 /* dbus_message_get_interface(m), */
638 /* dbus_message_get_path(m), */
639 /* dbus_message_get_member(m)); */
641 if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
642 /* No, we shouldn't quit, but until we get somewhere
643 * usefull such that we can restore our state, we will */
644 avahi_log_warn("Disconnnected from D-BUS, terminating...");
646 raise(SIGQUIT); /* The signal handler will catch this and terminate the process cleanly*/
648 return DBUS_HANDLER_RESULT_HANDLED;
650 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) {
653 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
654 avahi_log_warn("Error parsing NameAcquired message");
658 /* avahi_log_info(__FILE__": name acquired (%s)", name); */
659 return DBUS_HANDLER_RESULT_HANDLED;
661 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
662 char *name, *old, *new;
664 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) {
665 avahi_log_warn("Error parsing NameOwnerChanged message");
672 if ((client = client_get(name, FALSE))) {
673 avahi_log_debug(__FILE__": client %s vanished.", name);
680 if (dbus_error_is_set(&error))
681 dbus_error_free(&error);
683 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
686 static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntryGroupState state, void* userdata) {
687 EntryGroupInfo *i = userdata;
696 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged");
699 if (state == AVAHI_ENTRY_GROUP_FAILURE)
700 e = avahi_error_number_to_dbus(avahi_server_errno(s));
701 else if (state == AVAHI_ENTRY_GROUP_COLLISION)
702 e = AVAHI_DBUS_ERR_COLLISION;
704 e = AVAHI_DBUS_ERR_OK;
706 dbus_message_append_args(
709 DBUS_TYPE_STRING, &e,
711 dbus_message_set_destination(m, i->client->name);
712 dbus_connection_send(server->bus, m, NULL);
713 dbus_message_unref(m);
716 static int read_rdata(DBusMessage *m, int idx, void **rdata, uint32_t *size) {
717 DBusMessageIter iter, sub;
723 dbus_message_iter_init(m, &iter);
725 for (j = 0; j < idx; j++)
726 dbus_message_iter_next(&iter);
728 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
729 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE)
732 dbus_message_iter_recurse(&iter, &sub);
733 dbus_message_iter_get_fixed_array(&sub, &k, &n);
741 avahi_log_warn("Error parsing data");
748 static int read_strlst(DBusMessage *m, int idx, AvahiStringList **l) {
749 DBusMessageIter iter, sub;
751 AvahiStringList *strlst = NULL;
756 dbus_message_iter_init(m, &iter);
758 for (j = 0; j < idx; j++)
759 dbus_message_iter_next(&iter);
761 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
762 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY)
765 dbus_message_iter_recurse(&iter, &sub);
768 DBusMessageIter sub2;
772 if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
775 assert(at == DBUS_TYPE_ARRAY);
777 if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE)
780 dbus_message_iter_recurse(&sub, &sub2);
781 dbus_message_iter_get_fixed_array(&sub2, &k, &n);
782 strlst = avahi_string_list_add_arbitrary(strlst, k, n);
784 dbus_message_iter_next(&sub);
792 avahi_log_warn("Error parsing TXT data");
794 avahi_string_list_free(strlst);
800 static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
802 EntryGroupInfo *i = userdata;
808 dbus_error_init(&error);
810 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
811 dbus_message_get_interface(m),
812 dbus_message_get_path(m),
813 dbus_message_get_member(m));
816 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
817 return handle_introspect(c, m, "EntryGroup.introspect");
820 if (strcmp(dbus_message_get_sender(m), i->client->name))
821 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
823 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) {
825 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
826 avahi_log_warn("Error parsing EntryGroup::Free message");
831 return respond_ok(c, m);
833 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Commit")) {
835 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
836 avahi_log_warn("Error parsing EntryGroup::Commit message");
840 avahi_s_entry_group_commit(i->entry_group);
841 return respond_ok(c, m);
844 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Reset")) {
846 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
847 avahi_log_warn("Error parsing EntryGroup::Reset message");
851 avahi_s_entry_group_reset(i->entry_group);
853 return respond_ok(c, m);
855 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) {
857 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
858 avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
862 return respond_boolean(c, m, !!avahi_s_entry_group_is_empty(i->entry_group));
864 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
865 AvahiEntryGroupState state;
867 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
868 avahi_log_warn("Error parsing EntryGroup::GetState message");
872 state = avahi_s_entry_group_get_state(i->entry_group);
873 return respond_int32(c, m, (int32_t) state);
875 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
876 int32_t interface, protocol;
878 char *type, *name, *domain, *host;
880 AvahiStringList *strlst = NULL;
882 if (!dbus_message_get_args(
884 DBUS_TYPE_INT32, &interface,
885 DBUS_TYPE_INT32, &protocol,
886 DBUS_TYPE_UINT32, &flags,
887 DBUS_TYPE_STRING, &name,
888 DBUS_TYPE_STRING, &type,
889 DBUS_TYPE_STRING, &domain,
890 DBUS_TYPE_STRING, &host,
891 DBUS_TYPE_UINT16, &port,
892 DBUS_TYPE_INVALID) ||
894 read_strlst(m, 8, &strlst) < 0) {
895 avahi_log_warn("Error parsing EntryGroup::AddService message");
899 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= ENTRIES_PER_ENTRY_GROUP_MAX) {
900 avahi_string_list_free(strlst);
901 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
904 if (domain && !*domain)
910 if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, host, port, strlst) < 0) {
911 avahi_string_list_free(strlst);
912 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
915 if (!(flags & AVAHI_PUBLISH_UPDATE))
918 avahi_string_list_free(strlst);
920 return respond_ok(c, m);
922 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddServiceSubtype")) {
924 int32_t interface, protocol;
926 char *type, *name, *domain, *subtype;
928 if (!dbus_message_get_args(
930 DBUS_TYPE_INT32, &interface,
931 DBUS_TYPE_INT32, &protocol,
932 DBUS_TYPE_UINT32, &flags,
933 DBUS_TYPE_STRING, &name,
934 DBUS_TYPE_STRING, &type,
935 DBUS_TYPE_STRING, &domain,
936 DBUS_TYPE_STRING, &subtype,
937 DBUS_TYPE_INVALID) || !type || !name || !subtype) {
938 avahi_log_warn("Error parsing EntryGroup::AddServiceSubtype message");
942 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= ENTRIES_PER_ENTRY_GROUP_MAX)
943 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
945 if (domain && !*domain)
948 if (avahi_server_add_service_subtype(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, subtype) < 0)
949 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
951 if (!(flags & AVAHI_PUBLISH_UPDATE))
954 return respond_ok(c, m);
956 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "UpdateServiceTxt")) {
957 int32_t interface, protocol;
959 char *type, *name, *domain;
960 AvahiStringList *strlst;
962 if (!dbus_message_get_args(
964 DBUS_TYPE_INT32, &interface,
965 DBUS_TYPE_INT32, &protocol,
966 DBUS_TYPE_UINT32, &flags,
967 DBUS_TYPE_STRING, &name,
968 DBUS_TYPE_STRING, &type,
969 DBUS_TYPE_STRING, &domain,
970 DBUS_TYPE_INVALID) ||
972 read_strlst(m, 6, &strlst)) {
973 avahi_log_warn("Error parsing EntryGroup::UpdateServiceTxt message");
977 if (domain && !*domain)
980 if (avahi_server_update_service_txt_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, type, domain, strlst) < 0) {
981 avahi_string_list_free(strlst);
982 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
985 avahi_string_list_free(strlst);
987 return respond_ok(c, m);
989 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
990 int32_t interface, protocol;
992 char *name, *address;
995 if (!dbus_message_get_args(
997 DBUS_TYPE_INT32, &interface,
998 DBUS_TYPE_INT32, &protocol,
999 DBUS_TYPE_UINT32, &flags,
1000 DBUS_TYPE_STRING, &name,
1001 DBUS_TYPE_STRING, &address,
1002 DBUS_TYPE_INVALID) || !name || !address) {
1003 avahi_log_warn("Error parsing EntryGroup::AddAddress message");
1007 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= ENTRIES_PER_ENTRY_GROUP_MAX)
1008 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
1010 if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a)))
1011 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
1013 if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, name, &a) < 0)
1014 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1016 if (!(flags & AVAHI_PUBLISH_UPDATE))
1019 return respond_ok(c, m);
1020 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddRecord")) {
1021 int32_t interface, protocol;
1022 uint32_t flags, ttl, size;
1023 uint16_t clazz, type;
1028 if (!dbus_message_get_args(
1030 DBUS_TYPE_INT32, &interface,
1031 DBUS_TYPE_INT32, &protocol,
1032 DBUS_TYPE_UINT32, &flags,
1033 DBUS_TYPE_STRING, &name,
1034 DBUS_TYPE_UINT16, &clazz,
1035 DBUS_TYPE_UINT16, &type,
1036 DBUS_TYPE_UINT32, &ttl,
1037 DBUS_TYPE_INVALID) || !name ||
1038 read_rdata (m, 7, &rdata, &size)) {
1039 avahi_log_warn("Error parsing EntryGroup::AddRecord message");
1043 if (!(flags & AVAHI_PUBLISH_UPDATE) && i->n_entries >= ENTRIES_PER_ENTRY_GROUP_MAX)
1044 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
1046 if (!avahi_is_valid_domain_name (name))
1047 return respond_error(c, m, AVAHI_ERR_INVALID_DOMAIN_NAME, NULL);
1049 if (!(r = avahi_record_new_full (name, clazz, type, ttl)))
1050 return respond_error(c, m, AVAHI_ERR_NO_MEMORY, NULL);
1052 if (avahi_rdata_parse (r, rdata, size) < 0) {
1053 avahi_record_unref (r);
1054 return respond_error(c, m, AVAHI_ERR_INVALID_RDATA, NULL);
1057 if (avahi_server_add(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, (AvahiPublishFlags) flags, r) < 0) {
1058 avahi_record_unref (r);
1059 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1062 if (!(flags & AVAHI_PUBLISH_UPDATE))
1065 avahi_record_unref (r);
1067 return respond_ok(c, m);
1071 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1074 if (dbus_error_is_set(&error))
1075 dbus_error_free(&error);
1077 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1080 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) {
1081 SyncHostNameResolverInfo *i = userdata;
1087 if (event == AVAHI_RESOLVER_FOUND) {
1088 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1089 int32_t i_interface, i_protocol, i_aprotocol;
1094 avahi_address_snprint(t, sizeof(t), a);
1096 i_interface = (int32_t) interface;
1097 i_protocol = (int32_t) protocol;
1098 i_aprotocol = (int32_t) a->proto;
1099 u_flags = (uint32_t) flags;
1101 reply = dbus_message_new_method_return(i->message);
1102 dbus_message_append_args(
1104 DBUS_TYPE_INT32, &i_interface,
1105 DBUS_TYPE_INT32, &i_protocol,
1106 DBUS_TYPE_STRING, &host_name,
1107 DBUS_TYPE_INT32, &i_aprotocol,
1108 DBUS_TYPE_STRING, &pt,
1109 DBUS_TYPE_UINT32, &u_flags,
1112 dbus_connection_send(server->bus, reply, NULL);
1113 dbus_message_unref(reply);
1115 assert(event == AVAHI_RESOLVER_FAILURE);
1116 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1119 sync_host_name_resolver_free(i);
1122 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) {
1123 SyncAddressResolverInfo *i = userdata;
1129 if (event == AVAHI_RESOLVER_FOUND) {
1130 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1131 int32_t i_interface, i_protocol, i_aprotocol;
1136 avahi_address_snprint(t, sizeof(t), address);
1138 i_interface = (int32_t) interface;
1139 i_protocol = (int32_t) protocol;
1140 i_aprotocol = (int32_t) address->proto;
1141 u_flags = (uint32_t) flags;
1143 reply = dbus_message_new_method_return(i->message);
1144 dbus_message_append_args(
1146 DBUS_TYPE_INT32, &i_interface,
1147 DBUS_TYPE_INT32, &i_protocol,
1148 DBUS_TYPE_INT32, &i_aprotocol,
1149 DBUS_TYPE_STRING, &pt,
1150 DBUS_TYPE_STRING, &host_name,
1151 DBUS_TYPE_UINT32, &u_flags,
1154 dbus_connection_send(server->bus, reply, NULL);
1155 dbus_message_unref(reply);
1157 assert(event == AVAHI_RESOLVER_FAILURE);
1158 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1161 sync_address_resolver_free(i);
1164 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1166 DomainBrowserInfo *i = userdata;
1172 dbus_error_init(&error);
1174 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1175 dbus_message_get_interface(m),
1176 dbus_message_get_path(m),
1177 dbus_message_get_member(m));
1180 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1181 return handle_introspect(c, m, "DomainBrowser.introspect");
1183 /* Access control */
1184 if (strcmp(dbus_message_get_sender(m), i->client->name))
1185 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1187 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
1189 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1190 avahi_log_warn("Error parsing DomainBrowser::Free message");
1194 domain_browser_free(i);
1195 return respond_ok(c, m);
1199 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1202 if (dbus_error_is_set(&error))
1203 dbus_error_free(&error);
1205 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1208 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1209 DomainBrowserInfo *i = userdata;
1211 int32_t i_interface, i_protocol;
1217 i_interface = (int32_t) interface;
1218 i_protocol = (int32_t) protocol;
1219 u_flags = (uint32_t) flags;
1221 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, map_browse_signal_name(event));
1223 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1225 dbus_message_append_args(
1227 DBUS_TYPE_INT32, &i_interface,
1228 DBUS_TYPE_INT32, &i_protocol,
1229 DBUS_TYPE_STRING, &domain,
1230 DBUS_TYPE_UINT32, &u_flags,
1232 } else if (event == AVAHI_BROWSER_FAILURE)
1233 append_server_error(m);
1235 dbus_message_set_destination(m, i->client->name);
1236 dbus_connection_send(server->bus, m, NULL);
1237 dbus_message_unref(m);
1240 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1242 ServiceTypeBrowserInfo *i = userdata;
1248 dbus_error_init(&error);
1250 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1251 dbus_message_get_interface(m),
1252 dbus_message_get_path(m),
1253 dbus_message_get_member(m));
1256 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1257 return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
1259 /* Access control */
1260 if (strcmp(dbus_message_get_sender(m), i->client->name))
1261 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1263 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
1265 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1266 avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
1270 service_type_browser_free(i);
1271 return respond_ok(c, m);
1275 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1278 if (dbus_error_is_set(&error))
1279 dbus_error_free(&error);
1281 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1284 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, AvahiLookupResultFlags flags, void* userdata) {
1285 ServiceTypeBrowserInfo *i = userdata;
1287 int32_t i_interface, i_protocol;
1293 i_interface = (int32_t) interface;
1294 i_protocol = (int32_t) protocol;
1295 u_flags = (uint32_t) flags;
1297 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, map_browse_signal_name(event));
1299 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1302 dbus_message_append_args(
1304 DBUS_TYPE_INT32, &i_interface,
1305 DBUS_TYPE_INT32, &i_protocol,
1306 DBUS_TYPE_STRING, &type,
1307 DBUS_TYPE_STRING, &domain,
1308 DBUS_TYPE_UINT32, &u_flags,
1310 } else if (event == AVAHI_BROWSER_FAILURE)
1311 append_server_error(m);
1313 dbus_message_set_destination(m, i->client->name);
1314 dbus_connection_send(server->bus, m, NULL);
1315 dbus_message_unref(m);
1318 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1320 ServiceBrowserInfo *i = userdata;
1326 dbus_error_init(&error);
1328 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1329 dbus_message_get_interface(m),
1330 dbus_message_get_path(m),
1331 dbus_message_get_member(m));
1334 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1335 return handle_introspect(c, m, "ServiceBrowser.Introspect");
1337 /* Access control */
1338 if (strcmp(dbus_message_get_sender(m), i->client->name))
1339 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1341 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
1343 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1344 avahi_log_warn("Error parsing ServiceBrowser::Free message");
1348 service_browser_free(i);
1349 return respond_ok(c, m);
1353 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1356 if (dbus_error_is_set(&error))
1357 dbus_error_free(&error);
1359 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1362 static int is_our_own_service(Client *c, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain) {
1363 AvahiSEntryGroup *g;
1366 if (avahi_server_get_group_of_service(avahi_server, interface, protocol, name, type, domain, &g) == AVAHI_OK) {
1367 EntryGroupInfo *egi;
1369 for (egi = c->entry_groups; egi; egi = egi->entry_groups_next)
1370 if (egi->entry_group == g)
1377 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) {
1378 ServiceBrowserInfo *i = userdata;
1380 int32_t i_interface, i_protocol;
1386 i_interface = (int32_t) interface;
1387 i_protocol = (int32_t) protocol;
1388 u_flags = (uint32_t) flags;
1390 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, map_browse_signal_name(event));
1392 if (event == AVAHI_BROWSER_NEW) {
1393 /* Patch in AVAHI_LOOKUP_RESULT_OUR_OWN */
1395 if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1396 flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1399 if (event == AVAHI_BROWSER_NEW || event == AVAHI_BROWSER_REMOVE) {
1404 dbus_message_append_args(
1406 DBUS_TYPE_INT32, &i_interface,
1407 DBUS_TYPE_INT32, &i_protocol,
1408 DBUS_TYPE_STRING, &name,
1409 DBUS_TYPE_STRING, &type,
1410 DBUS_TYPE_STRING, &domain,
1411 DBUS_TYPE_UINT32, &u_flags,
1413 } else if (event == AVAHI_BROWSER_FAILURE)
1414 append_server_error(m);
1416 dbus_message_set_destination(m, i->client->name);
1417 dbus_connection_send(server->bus, m, NULL);
1418 dbus_message_unref(m);
1421 static void append_string_list(DBusMessage *reply, AvahiStringList *txt) {
1423 DBusMessageIter iter, sub;
1427 dbus_message_iter_init_append(reply, &iter);
1428 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1430 for (p = txt; p; p = p->next) {
1431 DBusMessageIter sub2;
1432 const uint8_t *data = p->text;
1434 dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1435 dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
1436 dbus_message_iter_close_container(&sub, &sub2);
1439 dbus_message_iter_close_container(&iter, &sub);
1442 static void sync_service_resolver_callback(
1443 AvahiSServiceResolver *r,
1444 AvahiIfIndex interface,
1445 AvahiProtocol protocol,
1446 AvahiResolverEvent event,
1450 const char *host_name,
1451 const AvahiAddress *a,
1453 AvahiStringList *txt,
1454 AvahiLookupResultFlags flags,
1457 SyncServiceResolverInfo *i = userdata;
1462 if (event == AVAHI_RESOLVER_FOUND) {
1463 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1464 int32_t i_interface, i_protocol, i_aprotocol;
1474 avahi_address_snprint(t, sizeof(t), a);
1478 /* Patch in AVAHI_LOOKUP_RESULT_OUR_OWN */
1480 if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1481 flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1483 i_interface = (int32_t) interface;
1484 i_protocol = (int32_t) protocol;
1486 i_aprotocol = (int32_t) a->proto;
1488 i_aprotocol = AVAHI_PROTO_UNSPEC;
1489 u_flags = (uint32_t) flags;
1491 reply = dbus_message_new_method_return(i->message);
1492 dbus_message_append_args(
1494 DBUS_TYPE_INT32, &i_interface,
1495 DBUS_TYPE_INT32, &i_protocol,
1496 DBUS_TYPE_STRING, &name,
1497 DBUS_TYPE_STRING, &type,
1498 DBUS_TYPE_STRING, &domain,
1499 DBUS_TYPE_STRING, &host_name,
1500 DBUS_TYPE_INT32, &i_aprotocol,
1501 DBUS_TYPE_STRING, &pt,
1502 DBUS_TYPE_UINT16, &port,
1505 append_string_list(reply, txt);
1507 dbus_message_append_args(
1509 DBUS_TYPE_UINT32, &u_flags,
1512 dbus_connection_send(server->bus, reply, NULL);
1513 dbus_message_unref(reply);
1515 assert(event == AVAHI_RESOLVER_FAILURE);
1517 respond_error(server->bus, i->message, avahi_server_errno(avahi_server), NULL);
1520 sync_service_resolver_free(i);
1523 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) {
1524 AsyncAddressResolverInfo *i = userdata;
1530 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, map_resolve_signal_name(event));
1532 if (event == AVAHI_RESOLVER_FOUND) {
1533 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1534 int32_t i_interface, i_protocol, i_aprotocol;
1539 avahi_address_snprint(t, sizeof(t), address);
1541 i_interface = (int32_t) interface;
1542 i_protocol = (int32_t) protocol;
1543 i_aprotocol = (int32_t) address->proto;
1544 u_flags = (uint32_t) flags;
1546 dbus_message_append_args(
1548 DBUS_TYPE_INT32, &i_interface,
1549 DBUS_TYPE_INT32, &i_protocol,
1550 DBUS_TYPE_INT32, &i_aprotocol,
1551 DBUS_TYPE_STRING, &pt,
1552 DBUS_TYPE_STRING, &host_name,
1553 DBUS_TYPE_UINT32, &u_flags,
1557 assert(event == AVAHI_RESOLVER_FAILURE);
1558 append_server_error(reply);
1561 dbus_message_set_destination(reply, i->client->name);
1562 dbus_connection_send(server->bus, reply, NULL);
1563 dbus_message_unref(reply);
1566 static DBusHandlerResult msg_async_address_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1568 AsyncAddressResolverInfo *i = userdata;
1574 dbus_error_init(&error);
1576 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1577 dbus_message_get_interface(m),
1578 dbus_message_get_path(m),
1579 dbus_message_get_member(m));
1582 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1583 return handle_introspect(c, m, "AddressResolver.Introspect");
1585 /* Access control */
1586 if (strcmp(dbus_message_get_sender(m), i->client->name))
1587 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1589 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ADDRESS_RESOLVER, "Free")) {
1591 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1592 avahi_log_warn("Error parsing AddressResolver::Free message");
1596 async_address_resolver_free(i);
1597 return respond_ok(c, m);
1601 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1604 if (dbus_error_is_set(&error))
1605 dbus_error_free(&error);
1607 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1610 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) {
1611 AsyncHostNameResolverInfo *i = userdata;
1617 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, map_resolve_signal_name(event));
1619 if (event == AVAHI_RESOLVER_FOUND) {
1620 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1621 int32_t i_interface, i_protocol, i_aprotocol;
1626 avahi_address_snprint(t, sizeof(t), a);
1628 i_interface = (int32_t) interface;
1629 i_protocol = (int32_t) protocol;
1630 i_aprotocol = (int32_t) a->proto;
1631 u_flags = (uint32_t) flags;
1633 dbus_message_append_args(
1635 DBUS_TYPE_INT32, &i_interface,
1636 DBUS_TYPE_INT32, &i_protocol,
1637 DBUS_TYPE_STRING, &host_name,
1638 DBUS_TYPE_INT32, &i_aprotocol,
1639 DBUS_TYPE_STRING, &pt,
1640 DBUS_TYPE_UINT32, &u_flags,
1643 assert(event == AVAHI_RESOLVER_FAILURE);
1644 append_server_error(reply);
1647 dbus_message_set_destination(reply, i->client->name);
1648 dbus_connection_send(server->bus, reply, NULL);
1649 dbus_message_unref(reply);
1652 static DBusHandlerResult msg_async_host_name_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1654 AsyncHostNameResolverInfo *i = userdata;
1660 dbus_error_init(&error);
1662 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1663 dbus_message_get_interface(m),
1664 dbus_message_get_path(m),
1665 dbus_message_get_member(m));
1668 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1669 return handle_introspect(c, m, "HostNameResolver.Introspect");
1671 /* Access control */
1672 if (strcmp(dbus_message_get_sender(m), i->client->name))
1673 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1675 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_HOST_NAME_RESOLVER, "Free")) {
1677 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1678 avahi_log_warn("Error parsing HostNameResolver::Free message");
1682 async_host_name_resolver_free(i);
1683 return respond_ok(c, m);
1686 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1689 if (dbus_error_is_set(&error))
1690 dbus_error_free(&error);
1692 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1695 static void async_service_resolver_callback(
1696 AvahiSServiceResolver *r,
1697 AvahiIfIndex interface,
1698 AvahiProtocol protocol,
1699 AvahiResolverEvent event,
1703 const char *host_name,
1704 const AvahiAddress *a,
1706 AvahiStringList *txt,
1707 AvahiLookupResultFlags flags,
1710 AsyncServiceResolverInfo *i = userdata;
1716 reply = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, map_resolve_signal_name(event));
1718 if (event == AVAHI_RESOLVER_FOUND) {
1719 char t[AVAHI_ADDRESS_STR_MAX], *pt = t;
1720 int32_t i_interface, i_protocol, i_aprotocol;
1725 /* avahi_log_debug(__FILE__": [%s] Successfully resolved service <%s.%s.%s>", i->path, name, type, domain); */
1728 avahi_address_snprint(t, sizeof(t), a);
1735 if (is_our_own_service(i->client, interface, protocol, name, type, domain) > 0)
1736 flags |= AVAHI_LOOKUP_RESULT_OUR_OWN;
1738 i_interface = (int32_t) interface;
1739 i_protocol = (int32_t) protocol;
1741 i_aprotocol = (int32_t) a->proto;
1743 i_aprotocol = AVAHI_PROTO_UNSPEC;
1744 u_flags = (uint32_t) flags;
1746 dbus_message_append_args(
1748 DBUS_TYPE_INT32, &i_interface,
1749 DBUS_TYPE_INT32, &i_protocol,
1750 DBUS_TYPE_STRING, &name,
1751 DBUS_TYPE_STRING, &type,
1752 DBUS_TYPE_STRING, &domain,
1753 DBUS_TYPE_STRING, &host_name,
1754 DBUS_TYPE_INT32, &i_aprotocol,
1755 DBUS_TYPE_STRING, &pt,
1756 DBUS_TYPE_UINT16, &port,
1759 append_string_list(reply, txt);
1761 dbus_message_append_args(
1763 DBUS_TYPE_UINT32, &u_flags,
1766 assert(event == AVAHI_RESOLVER_FAILURE);
1767 append_server_error(reply);
1770 dbus_message_set_destination(reply, i->client->name);
1771 dbus_connection_send(server->bus, reply, NULL);
1772 dbus_message_unref(reply);
1775 static DBusHandlerResult msg_async_service_resolver_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1777 AsyncServiceResolverInfo *i = userdata;
1783 dbus_error_init(&error);
1785 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1786 dbus_message_get_interface(m),
1787 dbus_message_get_path(m),
1788 dbus_message_get_member(m));
1791 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1792 return handle_introspect(c, m, "ServiceResolver.Introspect");
1794 /* Access control */
1795 if (strcmp(dbus_message_get_sender(m), i->client->name))
1796 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1798 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_RESOLVER, "Free")) {
1800 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1801 avahi_log_warn("Error parsing ServiceResolver::Free message");
1805 async_service_resolver_free(i);
1806 return respond_ok(c, m);
1809 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1812 if (dbus_error_is_set(&error))
1813 dbus_error_free(&error);
1815 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1818 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, AVAHI_GCC_UNUSED void *userdata) {
1821 dbus_error_init(&error);
1823 avahi_log_debug(__FILE__": interface=%s, path=%s, member=%s",
1824 dbus_message_get_interface(m),
1825 dbus_message_get_path(m),
1826 dbus_message_get_member(m));
1828 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1829 return handle_introspect(c, m, "Server.introspect");
1831 else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1833 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1834 avahi_log_warn("Error parsing Server::GetHostName message");
1838 return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1840 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1842 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1843 avahi_log_warn("Error parsing Server::GetDomainName message");
1847 return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1849 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1851 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1852 avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1856 return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1858 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1860 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1861 avahi_log_warn("Error parsing Server::GetVersionString message");
1865 return respond_string(c, m, PACKAGE_STRING);
1867 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1868 AvahiServerState state;
1870 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1871 avahi_log_warn("Error parsing Server::GetState message");
1875 state = avahi_server_get_state(avahi_server);
1876 return respond_int32(c, m, (int32_t) state);
1878 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetLocalServiceCookie")) {
1880 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1881 avahi_log_warn("Error parsing Server::GetLocalServiceCookie message");
1885 return respond_uint32(c, m, avahi_server_get_local_service_cookie(avahi_server));
1887 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1890 char name[IF_NAMESIZE];
1893 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1894 avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1898 #ifdef VALGRIND_WORKAROUND
1899 return respond_string(c, m, "blah");
1902 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1903 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1905 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1906 return respond_error(c, m, AVAHI_ERR_OS, txt);
1909 if ((!if_indextoname(idx, name))) {
1911 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1913 return respond_error(c, m, AVAHI_ERR_OS, txt);
1918 return respond_string(c, m, name);
1921 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1926 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1927 avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1931 #ifdef VALGRIND_WORKAROUND
1932 return respond_int32(c, m, 1);
1934 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
1935 if ((fd = socket(AF_INET6, SOCK_DGRAM, 0)) < 0) {
1937 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1938 return respond_error(c, m, AVAHI_ERR_OS, txt);
1941 if (!(idx = if_nametoindex(n))) {
1943 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1945 return respond_error(c, m, AVAHI_ERR_OS, txt);
1950 return respond_int32(c, m, idx);
1953 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1956 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1957 avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1961 t = avahi_alternative_host_name(n);
1962 respond_string(c, m, t);
1965 return DBUS_HANDLER_RESULT_HANDLED;
1967 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1970 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1971 avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1975 t = avahi_alternative_service_name(n);
1976 respond_string(c, m, t);
1979 return DBUS_HANDLER_RESULT_HANDLED;
1981 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1984 static const DBusObjectPathVTable vtable = {
1986 msg_entry_group_impl,
1993 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1994 avahi_log_warn("Error parsing Server::EntryGroupNew message");
1998 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1999 avahi_log_warn("Too many clients, client request failed.");
2000 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2003 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
2004 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2005 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2008 i = avahi_new(EntryGroupInfo, 1);
2009 i->id = ++client->current_id;
2011 i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
2013 AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
2014 client->n_objects++;
2016 if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
2017 entry_group_free(i);
2018 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2021 dbus_connection_register_object_path(c, i->path, &vtable, i);
2022 return respond_path(c, m, i->path);
2024 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
2026 int32_t interface, protocol, aprotocol;
2029 SyncHostNameResolverInfo *i;
2031 if (!dbus_message_get_args(
2033 DBUS_TYPE_INT32, &interface,
2034 DBUS_TYPE_INT32, &protocol,
2035 DBUS_TYPE_STRING, &name,
2036 DBUS_TYPE_INT32, &aprotocol,
2037 DBUS_TYPE_UINT32, &flags,
2038 DBUS_TYPE_INVALID) || !name) {
2039 avahi_log_warn("Error parsing Server::ResolveHostName message");
2043 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2044 avahi_log_warn("Too many clients, client request failed.");
2045 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2048 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
2049 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2050 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2053 i = avahi_new(SyncHostNameResolverInfo, 1);
2055 i->message = dbus_message_ref(m);
2056 AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i);
2057 client->n_objects++;
2059 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))) {
2060 sync_host_name_resolver_free(i);
2061 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2064 return DBUS_HANDLER_RESULT_HANDLED;
2066 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
2068 int32_t interface, protocol;
2071 SyncAddressResolverInfo *i;
2074 if (!dbus_message_get_args(
2076 DBUS_TYPE_INT32, &interface,
2077 DBUS_TYPE_INT32, &protocol,
2078 DBUS_TYPE_STRING, &address,
2079 DBUS_TYPE_UINT32, &flags,
2080 DBUS_TYPE_INVALID) || !address) {
2081 avahi_log_warn("Error parsing Server::ResolveAddress message");
2085 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
2086 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
2088 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2089 avahi_log_warn("Too many clients, client request failed.");
2090 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2093 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
2094 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2095 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2098 i = avahi_new(SyncAddressResolverInfo, 1);
2100 i->message = dbus_message_ref(m);
2101 AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i);
2102 client->n_objects++;
2104 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, sync_address_resolver_callback, i))) {
2105 sync_address_resolver_free(i);
2106 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2109 return DBUS_HANDLER_RESULT_HANDLED;
2111 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
2113 DomainBrowserInfo *i;
2114 static const DBusObjectPathVTable vtable = {
2116 msg_domain_browser_impl,
2122 int32_t interface, protocol, type;
2126 if (!dbus_message_get_args(
2128 DBUS_TYPE_INT32, &interface,
2129 DBUS_TYPE_INT32, &protocol,
2130 DBUS_TYPE_STRING, &domain,
2131 DBUS_TYPE_INT32, &type,
2132 DBUS_TYPE_UINT32, &flags,
2133 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
2134 avahi_log_warn("Error parsing Server::DomainBrowserNew message");
2138 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2139 avahi_log_warn("Too many clients, client request failed.");
2140 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2143 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
2144 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2145 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2151 i = avahi_new(DomainBrowserInfo, 1);
2152 i->id = ++client->current_id;
2154 i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
2155 AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
2156 client->n_objects++;
2158 if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, (AvahiLookupFlags) flags, domain_browser_callback, i))) {
2159 domain_browser_free(i);
2160 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2163 dbus_connection_register_object_path(c, i->path, &vtable, i);
2164 return respond_path(c, m, i->path);
2166 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
2168 ServiceTypeBrowserInfo *i;
2169 static const DBusObjectPathVTable vtable = {
2171 msg_service_type_browser_impl,
2177 int32_t interface, protocol;
2181 if (!dbus_message_get_args(
2183 DBUS_TYPE_INT32, &interface,
2184 DBUS_TYPE_INT32, &protocol,
2185 DBUS_TYPE_STRING, &domain,
2186 DBUS_TYPE_UINT32, &flags,
2187 DBUS_TYPE_INVALID)) {
2188 avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
2192 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2193 avahi_log_warn("Too many clients, client request failed.");
2194 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2198 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
2199 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2200 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2206 i = avahi_new(ServiceTypeBrowserInfo, 1);
2207 i->id = ++client->current_id;
2209 i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
2210 AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
2211 client->n_objects++;
2213 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))) {
2214 service_type_browser_free(i);
2215 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2218 dbus_connection_register_object_path(c, i->path, &vtable, i);
2219 return respond_path(c, m, i->path);
2221 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
2223 ServiceBrowserInfo *i;
2224 static const DBusObjectPathVTable vtable = {
2226 msg_service_browser_impl,
2232 int32_t interface, protocol;
2234 char *domain, *type;
2236 if (!dbus_message_get_args(
2238 DBUS_TYPE_INT32, &interface,
2239 DBUS_TYPE_INT32, &protocol,
2240 DBUS_TYPE_STRING, &type,
2241 DBUS_TYPE_STRING, &domain,
2242 DBUS_TYPE_UINT32, &flags,
2243 DBUS_TYPE_INVALID) || !type) {
2244 avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
2248 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2249 avahi_log_warn("Too many clients, client request failed.");
2250 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2254 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
2255 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2256 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2262 i = avahi_new(ServiceBrowserInfo, 1);
2263 i->id = ++client->current_id;
2265 i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
2266 AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
2267 client->n_objects++;
2269 if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, (AvahiLookupFlags) flags, service_browser_callback, i))) {
2270 service_browser_free(i);
2271 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2274 dbus_connection_register_object_path(c, i->path, &vtable, i);
2275 return respond_path(c, m, i->path);
2277 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
2279 int32_t interface, protocol, aprotocol;
2281 char *name, *type, *domain;
2282 SyncServiceResolverInfo *i;
2284 if (!dbus_message_get_args(
2286 DBUS_TYPE_INT32, &interface,
2287 DBUS_TYPE_INT32, &protocol,
2288 DBUS_TYPE_STRING, &name,
2289 DBUS_TYPE_STRING, &type,
2290 DBUS_TYPE_STRING, &domain,
2291 DBUS_TYPE_INT32, &aprotocol,
2292 DBUS_TYPE_UINT32, &flags,
2293 DBUS_TYPE_INVALID) || !type) {
2294 avahi_log_warn("Error parsing Server::ResolveService message");
2298 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2299 avahi_log_warn("Too many clients, client request failed.");
2300 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2303 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
2304 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
2305 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2314 i = avahi_new(SyncServiceResolverInfo, 1);
2316 i->message = dbus_message_ref(m);
2317 AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i);
2318 client->n_objects++;
2320 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))) {
2321 sync_service_resolver_free(i);
2322 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2325 return DBUS_HANDLER_RESULT_HANDLED;
2327 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceResolverNew")) {
2329 int32_t interface, protocol, aprotocol;
2331 char *name, *type, *domain;
2332 AsyncServiceResolverInfo *i;
2333 static const DBusObjectPathVTable vtable = {
2335 msg_async_service_resolver_impl,
2342 if (!dbus_message_get_args(
2344 DBUS_TYPE_INT32, &interface,
2345 DBUS_TYPE_INT32, &protocol,
2346 DBUS_TYPE_STRING, &name,
2347 DBUS_TYPE_STRING, &type,
2348 DBUS_TYPE_STRING, &domain,
2349 DBUS_TYPE_INT32, &aprotocol,
2350 DBUS_TYPE_UINT32, &flags,
2351 DBUS_TYPE_INVALID) || !type) {
2352 avahi_log_warn("Error parsing Server::ServiceResolverNew message");
2356 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2357 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2358 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2361 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
2362 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2363 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2372 i = avahi_new(AsyncServiceResolverInfo, 1);
2373 i->id = ++client->current_id;
2375 i->path = avahi_strdup_printf("/Client%u/ServiceResolver%u", client->id, i->id);
2376 AVAHI_LLIST_PREPEND(AsyncServiceResolverInfo, async_service_resolvers, client->async_service_resolvers, i);
2377 client->n_objects++;
2379 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))) {
2380 async_service_resolver_free(i);
2381 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2384 /* avahi_log_debug(__FILE__": [%s], new service resolver for <%s.%s.%s>", i->path, name, type, domain); */
2386 dbus_connection_register_object_path(c, i->path, &vtable, i);
2387 return respond_path(c, m, i->path);
2389 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "HostNameResolverNew")) {
2391 int32_t interface, protocol, aprotocol;
2394 AsyncHostNameResolverInfo *i;
2395 static const DBusObjectPathVTable vtable = {
2397 msg_async_host_name_resolver_impl,
2404 if (!dbus_message_get_args(
2406 DBUS_TYPE_INT32, &interface,
2407 DBUS_TYPE_INT32, &protocol,
2408 DBUS_TYPE_STRING, &name,
2409 DBUS_TYPE_INT32, &aprotocol,
2410 DBUS_TYPE_UINT32, &flags,
2411 DBUS_TYPE_INVALID) || !name) {
2412 avahi_log_warn("Error parsing Server::HostNameResolverNew message");
2416 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2417 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2418 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2421 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
2422 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2423 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2426 i = avahi_new(AsyncHostNameResolverInfo, 1);
2427 i->id = ++client->current_id;
2429 i->path = avahi_strdup_printf("/Client%u/HostNameResolver%u", client->id, i->id);
2430 AVAHI_LLIST_PREPEND(AsyncHostNameResolverInfo, async_host_name_resolvers, client->async_host_name_resolvers, i);
2431 client->n_objects++;
2433 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))) {
2434 async_host_name_resolver_free(i);
2435 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2438 dbus_connection_register_object_path(c, i->path, &vtable, i);
2439 return respond_path(c, m, i->path);
2441 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "AddressResolverNew")) {
2443 int32_t interface, protocol;
2446 AsyncAddressResolverInfo *i;
2448 static const DBusObjectPathVTable vtable = {
2450 msg_async_address_resolver_impl,
2457 if (!dbus_message_get_args(
2459 DBUS_TYPE_INT32, &interface,
2460 DBUS_TYPE_INT32, &protocol,
2461 DBUS_TYPE_STRING, &address,
2462 DBUS_TYPE_UINT32, &flags,
2463 DBUS_TYPE_INVALID) || !address) {
2464 avahi_log_warn("Error parsing Server::AddressResolverNew message");
2468 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
2469 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
2471 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
2472 avahi_log_warn(__FILE__": Too many clients, client request failed.");
2473 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
2476 if (client->n_objects >= OBJECTS_PER_CLIENT_MAX) {
2477 avahi_log_warn(__FILE__": Too many objects for client '%s', client request failed.", client->name);
2478 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
2481 i = avahi_new(AsyncAddressResolverInfo, 1);
2482 i->id = ++client->current_id;
2484 i->path = avahi_strdup_printf("/Client%u/AddressResolver%u", client->id, i->id);
2485 AVAHI_LLIST_PREPEND(AsyncAddressResolverInfo, async_address_resolvers, client->async_address_resolvers, i);
2486 client->n_objects++;
2488 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, (AvahiLookupFlags) flags, async_address_resolver_callback, i))) {
2489 async_address_resolver_free(i);
2490 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
2493 dbus_connection_register_object_path(c, i->path, &vtable, i);
2494 return respond_path(c, m, i->path);
2497 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
2500 if (dbus_error_is_set(&error))
2501 dbus_error_free(&error);
2503 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
2506 void dbus_protocol_server_state_changed(AvahiServerState state) {
2514 m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
2515 t = (int32_t) state;
2517 if (state == AVAHI_SERVER_COLLISION)
2518 e = AVAHI_DBUS_ERR_COLLISION;
2519 else if (state == AVAHI_SERVER_FAILURE)
2520 e = avahi_error_number_to_dbus(avahi_server_errno(avahi_server));
2522 e = AVAHI_DBUS_ERR_OK;
2524 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_STRING, &e, DBUS_TYPE_INVALID);
2525 dbus_connection_send(server->bus, m, NULL);
2526 dbus_message_unref(m);
2529 int dbus_protocol_setup(const AvahiPoll *poll_api) {
2532 static const DBusObjectPathVTable server_vtable = {
2541 dbus_error_init(&error);
2543 server = avahi_new(Server, 1);
2544 AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
2545 server->current_id = 0;
2546 server->n_clients = 0;
2548 if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
2549 assert(dbus_error_is_set(&error));
2550 avahi_log_error("dbus_bus_get(): %s", error.message);
2554 if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) {
2555 avahi_log_error("avahi_dbus_connection_glue() failed");
2559 if (dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
2560 if (dbus_error_is_set(&error)) {
2561 avahi_log_error("dbus_bus_request_name(): %s", error.message);
2565 avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'");
2569 if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) {
2570 avahi_log_error("dbus_connection_add_filter() failed");
2574 dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
2576 if (dbus_error_is_set(&error)) {
2577 avahi_log_error("dbus_bus_add_match(): %s", error.message);
2581 if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
2582 avahi_log_error("dbus_connection_register_object_path() failed");
2590 dbus_connection_disconnect(server->bus);
2591 dbus_connection_unref(server->bus);
2594 if (dbus_error_is_set(&error))
2595 dbus_error_free(&error);
2602 void dbus_protocol_shutdown(void) {
2606 while (server->clients)
2607 client_free(server->clients);
2609 assert(server->n_clients == 0);
2612 dbus_connection_disconnect(server->bus);
2613 dbus_connection_unref(server->bus);