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>
37 #include <dbus/dbus.h>
39 #include <avahi-common/dbus.h>
40 #include <avahi-common/llist.h>
41 #include <avahi-common/malloc.h>
42 #include <avahi-common/dbus.h>
43 #include <avahi-common/dbus-watch-glue.h>
44 #include <avahi-common/alternative.h>
45 #include <avahi-common/error.h>
46 #include <avahi-core/log.h>
47 #include <avahi-core/core.h>
49 #include "dbus-protocol.h"
52 typedef struct Server Server;
53 typedef struct Client Client;
54 typedef struct EntryGroupInfo EntryGroupInfo;
55 typedef struct SyncHostNameResolverInfo SyncHostNameResolverInfo;
56 typedef struct AsyncHostNameResolverInfo AsyncHostNameResolverInfo;
57 typedef struct SyncAddressResolverInfo SyncAddressResolverInfo;
58 typedef struct AsyncAddressResolverInfo AsyncAddressResolverInfo;
59 typedef struct DomainBrowserInfo DomainBrowserInfo;
60 typedef struct ServiceTypeBrowserInfo ServiceTypeBrowserInfo;
61 typedef struct ServiceBrowserInfo ServiceBrowserInfo;
62 typedef struct SyncServiceResolverInfo SyncServiceResolverInfo;
63 typedef struct AsyncServiceResolverInfo AsyncServiceResolverInfo;
65 #define MAX_CLIENTS 20
66 #define MAX_OBJECTS_PER_CLIENT 50
67 #define MAX_ENTRIES_PER_ENTRY_GROUP 20
69 /* #define VALGRIND_WORKAROUND */
71 struct EntryGroupInfo {
74 AvahiSEntryGroup *entry_group;
79 AVAHI_LLIST_FIELDS(EntryGroupInfo, entry_groups);
82 struct SyncHostNameResolverInfo {
84 AvahiSHostNameResolver *host_name_resolver;
87 AVAHI_LLIST_FIELDS(SyncHostNameResolverInfo, sync_host_name_resolvers);
90 struct AsyncHostNameResolverInfo {
93 AvahiSHostNameResolver *host_name_resolver;
96 AVAHI_LLIST_FIELDS(AsyncHostNameResolverInfo, async_host_name_resolvers);
99 struct SyncAddressResolverInfo {
101 AvahiSAddressResolver *address_resolver;
102 DBusMessage *message;
104 AVAHI_LLIST_FIELDS(SyncAddressResolverInfo, sync_address_resolvers);
107 struct AsyncAddressResolverInfo {
110 AvahiSAddressResolver *address_resolver;
113 AVAHI_LLIST_FIELDS(AsyncAddressResolverInfo, async_address_resolvers);
116 struct DomainBrowserInfo {
119 AvahiSDomainBrowser *domain_browser;
122 AVAHI_LLIST_FIELDS(DomainBrowserInfo, domain_browsers);
125 struct ServiceTypeBrowserInfo {
128 AvahiSServiceTypeBrowser *service_type_browser;
131 AVAHI_LLIST_FIELDS(ServiceTypeBrowserInfo, service_type_browsers);
134 struct ServiceBrowserInfo {
137 AvahiSServiceBrowser *service_browser;
140 AVAHI_LLIST_FIELDS(ServiceBrowserInfo, service_browsers);
143 struct SyncServiceResolverInfo {
145 AvahiSServiceResolver *service_resolver;
146 DBusMessage *message;
148 AVAHI_LLIST_FIELDS(SyncServiceResolverInfo, sync_service_resolvers);
151 struct AsyncServiceResolverInfo {
154 AvahiSServiceResolver *service_resolver;
157 AVAHI_LLIST_FIELDS(AsyncServiceResolverInfo, async_service_resolvers);
166 AVAHI_LLIST_FIELDS(Client, clients);
167 AVAHI_LLIST_HEAD(EntryGroupInfo, entry_groups);
168 AVAHI_LLIST_HEAD(SyncHostNameResolverInfo, sync_host_name_resolvers);
169 AVAHI_LLIST_HEAD(AsyncHostNameResolverInfo, async_host_name_resolvers);
170 AVAHI_LLIST_HEAD(SyncAddressResolverInfo, sync_address_resolvers);
171 AVAHI_LLIST_HEAD(AsyncAddressResolverInfo, async_address_resolvers);
172 AVAHI_LLIST_HEAD(DomainBrowserInfo, domain_browsers);
173 AVAHI_LLIST_HEAD(ServiceTypeBrowserInfo, service_type_browsers);
174 AVAHI_LLIST_HEAD(ServiceBrowserInfo, service_browsers);
175 AVAHI_LLIST_HEAD(SyncServiceResolverInfo, sync_service_resolvers);
176 AVAHI_LLIST_HEAD(AsyncServiceResolverInfo, async_service_resolvers);
181 AVAHI_LLIST_HEAD(Client, clients);
186 static Server *server = NULL;
188 static void entry_group_free(EntryGroupInfo *i) {
192 avahi_s_entry_group_free(i->entry_group);
193 dbus_connection_unregister_object_path(server->bus, i->path);
195 AVAHI_LLIST_REMOVE(EntryGroupInfo, entry_groups, i->client->entry_groups, i);
197 i->client->n_objects--;
198 assert(i->client->n_objects >= 0);
203 static void host_name_resolver_free(SyncHostNameResolverInfo *i) {
206 if (i->host_name_resolver)
207 avahi_s_host_name_resolver_free(i->host_name_resolver);
208 dbus_message_unref(i->message);
209 AVAHI_LLIST_REMOVE(SyncHostNameResolverInfo, sync_host_name_resolvers, i->client->sync_host_name_resolvers, i);
211 i->client->n_objects--;
212 assert(i->client->n_objects >= 0);
217 static void address_resolver_free(SyncAddressResolverInfo *i) {
220 if (i->address_resolver)
221 avahi_s_address_resolver_free(i->address_resolver);
222 dbus_message_unref(i->message);
223 AVAHI_LLIST_REMOVE(SyncAddressResolverInfo, sync_address_resolvers, i->client->sync_address_resolvers, i);
225 i->client->n_objects--;
226 assert(i->client->n_objects >= 0);
231 static void domain_browser_free(DomainBrowserInfo *i) {
234 if (i->domain_browser)
235 avahi_s_domain_browser_free(i->domain_browser);
236 dbus_connection_unregister_object_path(server->bus, i->path);
238 AVAHI_LLIST_REMOVE(DomainBrowserInfo, domain_browsers, i->client->domain_browsers, i);
240 i->client->n_objects--;
241 assert(i->client->n_objects >= 0);
246 static void service_type_browser_free(ServiceTypeBrowserInfo *i) {
249 if (i->service_type_browser)
250 avahi_s_service_type_browser_free(i->service_type_browser);
251 dbus_connection_unregister_object_path(server->bus, i->path);
253 AVAHI_LLIST_REMOVE(ServiceTypeBrowserInfo, service_type_browsers, i->client->service_type_browsers, i);
255 i->client->n_objects--;
256 assert(i->client->n_objects >= 0);
261 static void service_browser_free(ServiceBrowserInfo *i) {
264 if (i->service_browser)
265 avahi_s_service_browser_free(i->service_browser);
266 dbus_connection_unregister_object_path(server->bus, i->path);
268 AVAHI_LLIST_REMOVE(ServiceBrowserInfo, service_browsers, i->client->service_browsers, i);
270 i->client->n_objects--;
271 assert(i->client->n_objects >= 0);
276 static void service_resolver_free(SyncServiceResolverInfo *i) {
279 if (i->service_resolver)
280 avahi_s_service_resolver_free(i->service_resolver);
281 dbus_message_unref(i->message);
282 AVAHI_LLIST_REMOVE(SyncServiceResolverInfo, sync_service_resolvers, i->client->sync_service_resolvers, i);
284 i->client->n_objects--;
285 assert(i->client->n_objects >= 0);
290 static void client_free(Client *c) {
295 while (c->entry_groups)
296 entry_group_free(c->entry_groups);
298 while (c->sync_host_name_resolvers)
299 host_name_resolver_free(c->sync_host_name_resolvers);
301 while (c->sync_address_resolvers)
302 address_resolver_free(c->sync_address_resolvers);
304 while (c->domain_browsers)
305 domain_browser_free(c->domain_browsers);
307 while (c->service_type_browsers)
308 service_type_browser_free(c->service_type_browsers);
310 while (c->service_browsers)
311 service_browser_free(c->service_browsers);
313 while (c->sync_service_resolvers)
314 service_resolver_free(c->sync_service_resolvers);
316 assert(c->n_objects == 0);
319 AVAHI_LLIST_REMOVE(Client, clients, server->clients, c);
322 server->n_clients --;
323 assert(server->n_clients >= 0);
326 static Client *client_get(const char *name, int create) {
332 for (client = server->clients; client; client = client->clients_next)
333 if (!strcmp(name, client->name))
339 if (server->n_clients >= MAX_CLIENTS)
342 /* If not existant yet, create a new entry */
343 client = avahi_new(Client, 1);
344 client->id = server->current_id++;
345 client->name = avahi_strdup(name);
346 client->current_id = 0;
347 client->n_objects = 0;
349 AVAHI_LLIST_HEAD_INIT(EntryGroupInfo, client->entry_groups);
350 AVAHI_LLIST_HEAD_INIT(SyncHostNameResolverInfo, client->sync_host_name_resolvers);
351 AVAHI_LLIST_HEAD_INIT(SyncAddressResolverInfo, client->sync_address_resolvers);
352 AVAHI_LLIST_HEAD_INIT(DomainBrowserInfo, client->domain_browsers);
353 AVAHI_LLIST_HEAD_INIT(ServiceTypeBrowserInfo, client->service_type_browsers);
354 AVAHI_LLIST_HEAD_INIT(ServiceBrowserInfo, client->service_browsers);
355 AVAHI_LLIST_HEAD_INIT(SyncServiceResolverInfo, client->sync_service_resolvers);
357 AVAHI_LLIST_PREPEND(Client, clients, server->clients, client);
360 assert(server->n_clients > 0);
365 static DBusHandlerResult respond_error(DBusConnection *c, DBusMessage *m, int error, const char *text) {
368 assert(-error > -AVAHI_OK);
369 assert(-error < -AVAHI_ERR_MAX);
371 reply = dbus_message_new_error(m, avahi_error_number_to_dbus (error), text ? text : avahi_strerror(error));
372 dbus_connection_send(c, reply, NULL);
373 dbus_message_unref(reply);
375 return DBUS_HANDLER_RESULT_HANDLED;
378 static DBusHandlerResult respond_string(DBusConnection *c, DBusMessage *m, const char *text) {
381 reply = dbus_message_new_method_return(m);
382 dbus_message_append_args(reply, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID);
383 dbus_connection_send(c, reply, NULL);
384 dbus_message_unref(reply);
386 return DBUS_HANDLER_RESULT_HANDLED;
389 static DBusHandlerResult respond_int32(DBusConnection *c, DBusMessage *m, int32_t i) {
392 reply = dbus_message_new_method_return(m);
393 dbus_message_append_args(reply, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID);
394 dbus_connection_send(c, reply, NULL);
395 dbus_message_unref(reply);
397 return DBUS_HANDLER_RESULT_HANDLED;
400 static DBusHandlerResult respond_ok(DBusConnection *c, DBusMessage *m) {
403 reply = dbus_message_new_method_return(m);
404 dbus_connection_send(c, reply, NULL);
405 dbus_message_unref(reply);
407 return DBUS_HANDLER_RESULT_HANDLED;
410 static DBusHandlerResult respond_path(DBusConnection *c, DBusMessage *m, const char *path) {
413 reply = dbus_message_new_method_return(m);
414 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
415 dbus_connection_send(c, reply, NULL);
416 dbus_message_unref(reply);
418 return DBUS_HANDLER_RESULT_HANDLED;
421 static char *file_get_contents(char *fname) {
429 if (!(fd = open(fname, O_RDONLY))) {
430 avahi_log_error("Failed to open %s: %s", fname, strerror(errno));
434 if (fstat(fd, &st) < 0) {
435 avahi_log_error("stat(%s) failed: %s", fname, strerror(errno));
439 if (!(S_ISREG(st.st_mode))) {
440 avahi_log_error("Invalid file %s", fname);
444 if (st.st_size > 1024*1024) { /** 1MB */
445 avahi_log_error("File too large %s", fname);
449 buf = avahi_new(char, st.st_size+1);
451 if ((size = read(fd, buf, st.st_size)) < 0) {
452 avahi_log_error("read() failed: %s\n", strerror(errno));
472 static DBusHandlerResult handle_introspect(DBusConnection *c, DBusMessage *m, const char *fname) {
473 char *path, *contents;
480 dbus_error_init(&error);
482 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
483 avahi_log_error("Error parsing Introspect message: %s", error.message);
487 path = avahi_strdup_printf("%s/%s", AVAHI_DBUS_INTROSPECTION_DIR, fname);
488 contents = file_get_contents(path);
492 avahi_log_error("Failed to load introspection data.");
496 respond_string(c, m, contents);
497 avahi_free(contents);
499 return DBUS_HANDLER_RESULT_HANDLED;
502 if (dbus_error_is_set(&error))
503 dbus_error_free(&error);
505 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
509 static DBusHandlerResult msg_signal_filter_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
512 dbus_error_init(&error);
514 /* avahi_log_debug("dbus: interface=%s, path=%s, member=%s", */
515 /* dbus_message_get_interface(m), */
516 /* dbus_message_get_path(m), */
517 /* dbus_message_get_member(m)); */
519 if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
520 /* No, we shouldn't quit, but until we get somewhere
521 * usefull such that we can restore our state, we will */
522 avahi_log_warn("Disconnnected from d-bus, terminating...");
524 raise(SIGQUIT); /* The signal handler will catch this and terminate the process cleanly*/
526 return DBUS_HANDLER_RESULT_HANDLED;
528 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) {
531 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
532 avahi_log_warn("Error parsing NameAcquired message");
536 /* avahi_log_info("dbus: name acquired (%s)", name); */
537 return DBUS_HANDLER_RESULT_HANDLED;
539 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
540 char *name, *old, *new;
542 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) {
543 avahi_log_warn("Error parsing NameOwnerChanged message");
550 if ((client = client_get(name, FALSE))) {
551 /* avahi_log_info("dbus: client %s vanished", name); */
558 if (dbus_error_is_set(&error))
559 dbus_error_free(&error);
561 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
564 static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntryGroupState state, void* userdata) {
565 EntryGroupInfo *i = userdata;
573 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged");
575 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
576 dbus_message_set_destination(m, i->client->name);
577 dbus_connection_send(server->bus, m, NULL);
578 dbus_message_unref(m);
581 static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
583 EntryGroupInfo *i = userdata;
589 dbus_error_init(&error);
591 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
592 dbus_message_get_interface(m),
593 dbus_message_get_path(m),
594 dbus_message_get_member(m));
597 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
598 return handle_introspect(c, m, "EntryGroup.introspect");
601 if (strcmp(dbus_message_get_sender(m), i->client->name))
602 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
604 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) {
606 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
607 avahi_log_warn("Error parsing EntryGroup::Free message");
612 return respond_ok(c, m);
614 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Commit")) {
616 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
617 avahi_log_warn("Error parsing EntryGroup::Commit message");
621 avahi_s_entry_group_commit(i->entry_group);
622 return respond_ok(c, m);
625 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Reset")) {
627 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
628 avahi_log_warn("Error parsing EntryGroup::Reset message");
632 avahi_s_entry_group_reset(i->entry_group);
633 return respond_ok(c, m);
635 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) {
639 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
640 avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
644 b = !!avahi_s_entry_group_is_empty(i->entry_group);
646 reply = dbus_message_new_method_return(m);
647 dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
648 dbus_connection_send(c, reply, NULL);
649 dbus_message_unref(reply);
651 return DBUS_HANDLER_RESULT_HANDLED;
653 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
654 AvahiEntryGroupState state;
656 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
657 avahi_log_warn("Error parsing EntryGroup::GetState message");
661 state = avahi_s_entry_group_get_state(i->entry_group);
662 return respond_int32(c, m, (int32_t) state);
664 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
665 int32_t interface, protocol;
666 char *type, *name, *domain, *host;
668 AvahiStringList *strlst;
669 DBusMessageIter iter, sub;
672 if (!dbus_message_get_args(
674 DBUS_TYPE_INT32, &interface,
675 DBUS_TYPE_INT32, &protocol,
676 DBUS_TYPE_STRING, &name,
677 DBUS_TYPE_STRING, &type,
678 DBUS_TYPE_STRING, &domain,
679 DBUS_TYPE_STRING, &host,
680 DBUS_TYPE_UINT16, &port,
681 DBUS_TYPE_INVALID) || !type || !name) {
682 avahi_log_warn("Error parsing EntryGroup::AddService message");
686 dbus_message_iter_init(m, &iter);
688 for (j = 0; j < 7; j++)
689 dbus_message_iter_next(&iter);
691 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
692 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY) {
693 avahi_log_warn("Error parsing EntryGroup::AddService message 2");
698 dbus_message_iter_recurse(&iter, &sub);
701 DBusMessageIter sub2;
705 if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
708 assert(at == DBUS_TYPE_ARRAY);
710 if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) {
711 avahi_log_warn("Error parsing EntryGroup::AddService message");
715 dbus_message_iter_recurse(&sub, &sub2);
716 dbus_message_iter_get_fixed_array(&sub2, &k, &n);
717 strlst = avahi_string_list_add_arbitrary(strlst, k, n);
719 dbus_message_iter_next(&sub);
722 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
723 avahi_string_list_free(strlst);
724 avahi_log_warn("Too many entries per entry group, client request failed.");
725 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
728 if (domain && !*domain)
734 if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, host, port, strlst) < 0) {
735 avahi_string_list_free(strlst);
736 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
740 avahi_string_list_free(strlst);
742 return respond_ok(c, m);
744 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
745 int32_t interface, protocol;
746 char *name, *address;
749 if (!dbus_message_get_args(
751 DBUS_TYPE_INT32, &interface,
752 DBUS_TYPE_INT32, &protocol,
753 DBUS_TYPE_STRING, &name,
754 DBUS_TYPE_STRING, &address,
755 DBUS_TYPE_INVALID) || !name || !address) {
756 avahi_log_warn("Error parsing EntryGroup::AddAddress message");
760 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
761 avahi_log_warn("Too many entries per entry group, client request failed.");
762 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
765 if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))) {
766 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
769 if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, 0, name, &a) < 0)
770 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
774 return respond_ok(c, m);
777 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
780 if (dbus_error_is_set(&error))
781 dbus_error_free(&error);
783 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
786 static void host_name_resolver_callback(AvahiSHostNameResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *host_name, const AvahiAddress *a, void* userdata) {
787 SyncHostNameResolverInfo *i = userdata;
793 if (event == AVAHI_RESOLVER_FOUND) {
794 char t[256], *pt = t;
795 int32_t i_interface, i_protocol, i_aprotocol;
799 avahi_address_snprint(t, sizeof(t), a);
801 i_interface = (int32_t) interface;
802 i_protocol = (int32_t) protocol;
803 i_aprotocol = (int32_t) a->family;
805 reply = dbus_message_new_method_return(i->message);
806 dbus_message_append_args(
808 DBUS_TYPE_INT32, &i_interface,
809 DBUS_TYPE_INT32, &i_protocol,
810 DBUS_TYPE_STRING, &host_name,
811 DBUS_TYPE_INT32, &i_aprotocol,
812 DBUS_TYPE_STRING, &pt,
815 dbus_connection_send(server->bus, reply, NULL);
816 dbus_message_unref(reply);
818 assert(event == AVAHI_RESOLVER_TIMEOUT);
820 respond_error(server->bus, i->message, AVAHI_ERR_TIMEOUT, NULL);
823 host_name_resolver_free(i);
826 static void address_resolver_callback(AvahiSAddressResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const AvahiAddress *address, const char *host_name, void* userdata) {
827 SyncAddressResolverInfo *i = userdata;
833 if (event == AVAHI_RESOLVER_FOUND) {
834 char t[256], *pt = t;
835 int32_t i_interface, i_protocol, i_aprotocol;
839 avahi_address_snprint(t, sizeof(t), address);
841 i_interface = (int32_t) interface;
842 i_protocol = (int32_t) protocol;
843 i_aprotocol = (int32_t) address->family;
845 reply = dbus_message_new_method_return(i->message);
846 dbus_message_append_args(
848 DBUS_TYPE_INT32, &i_interface,
849 DBUS_TYPE_INT32, &i_protocol,
850 DBUS_TYPE_INT32, &i_aprotocol,
851 DBUS_TYPE_STRING, &pt,
852 DBUS_TYPE_STRING, &host_name,
855 dbus_connection_send(server->bus, reply, NULL);
856 dbus_message_unref(reply);
858 assert(event == AVAHI_RESOLVER_TIMEOUT);
859 respond_error(server->bus, i->message, AVAHI_ERR_TIMEOUT, NULL);
862 address_resolver_free(i);
865 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
867 DomainBrowserInfo *i = userdata;
873 dbus_error_init(&error);
875 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
876 dbus_message_get_interface(m),
877 dbus_message_get_path(m),
878 dbus_message_get_member(m));
881 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
882 return handle_introspect(c, m, "DomainBrowser.introspect");
885 if (strcmp(dbus_message_get_sender(m), i->client->name))
886 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
888 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
890 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
891 avahi_log_warn("Error parsing DomainBrowser::Free message");
895 domain_browser_free(i);
896 return respond_ok(c, m);
900 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
903 if (dbus_error_is_set(&error))
904 dbus_error_free(&error);
906 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
909 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, void* userdata) {
910 DomainBrowserInfo *i = userdata;
912 int32_t i_interface, i_protocol;
918 i_interface = (int32_t) interface;
919 i_protocol = (int32_t) protocol;
921 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, event == AVAHI_BROWSER_NEW ? "ItemNew" : "ItemRemove");
922 dbus_message_append_args(
924 DBUS_TYPE_INT32, &i_interface,
925 DBUS_TYPE_INT32, &i_protocol,
926 DBUS_TYPE_STRING, &domain,
928 dbus_message_set_destination(m, i->client->name);
929 dbus_connection_send(server->bus, m, NULL);
930 dbus_message_unref(m);
933 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
935 ServiceTypeBrowserInfo *i = userdata;
941 dbus_error_init(&error);
943 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
944 dbus_message_get_interface(m),
945 dbus_message_get_path(m),
946 dbus_message_get_member(m));
949 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
950 return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
953 if (strcmp(dbus_message_get_sender(m), i->client->name))
954 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
956 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
958 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
959 avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
963 service_type_browser_free(i);
964 return respond_ok(c, m);
968 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
971 if (dbus_error_is_set(&error))
972 dbus_error_free(&error);
974 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
977 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, void* userdata) {
978 ServiceTypeBrowserInfo *i = userdata;
980 int32_t i_interface, i_protocol;
987 i_interface = (int32_t) interface;
988 i_protocol = (int32_t) protocol;
990 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, event == AVAHI_BROWSER_NEW ? "ItemNew" : "ItemRemove");
991 dbus_message_append_args(
993 DBUS_TYPE_INT32, &i_interface,
994 DBUS_TYPE_INT32, &i_protocol,
995 DBUS_TYPE_STRING, &type,
996 DBUS_TYPE_STRING, &domain,
998 dbus_message_set_destination(m, i->client->name);
999 dbus_connection_send(server->bus, m, NULL);
1000 dbus_message_unref(m);
1003 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1005 ServiceBrowserInfo *i = userdata;
1011 dbus_error_init(&error);
1013 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
1014 dbus_message_get_interface(m),
1015 dbus_message_get_path(m),
1016 dbus_message_get_member(m));
1019 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1020 return handle_introspect(c, m, "ServiceBrowser.Introspect");
1022 /* Access control */
1023 if (strcmp(dbus_message_get_sender(m), i->client->name))
1024 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1026 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
1028 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1029 avahi_log_warn("Error parsing ServiceBrowser::Free message");
1033 service_browser_free(i);
1034 return respond_ok(c, m);
1038 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1041 if (dbus_error_is_set(&error))
1042 dbus_error_free(&error);
1044 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1047 static void service_browser_callback(AvahiSServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, void* userdata) {
1048 ServiceBrowserInfo *i = userdata;
1050 int32_t i_interface, i_protocol;
1058 i_interface = (int32_t) interface;
1059 i_protocol = (int32_t) protocol;
1061 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, event == AVAHI_BROWSER_NEW ? "ItemNew" : "ItemRemove");
1062 dbus_message_append_args(
1064 DBUS_TYPE_INT32, &i_interface,
1065 DBUS_TYPE_INT32, &i_protocol,
1066 DBUS_TYPE_STRING, &name,
1067 DBUS_TYPE_STRING, &type,
1068 DBUS_TYPE_STRING, &domain,
1070 dbus_message_set_destination(m, i->client->name);
1071 dbus_connection_send(server->bus, m, NULL);
1072 dbus_message_unref(m);
1075 static void service_resolver_callback(
1076 AvahiSServiceResolver *r,
1077 AvahiIfIndex interface,
1078 AvahiProtocol protocol,
1079 AvahiResolverEvent event,
1083 const char *host_name,
1084 const AvahiAddress *a,
1086 AvahiStringList *txt,
1089 SyncServiceResolverInfo *i = userdata;
1094 if (event == AVAHI_RESOLVER_FOUND) {
1095 char t[256], *pt = t;
1096 int32_t i_interface, i_protocol, i_aprotocol;
1100 DBusMessageIter iter, sub;
1105 avahi_address_snprint(t, sizeof(t), a);
1107 i_interface = (int32_t) interface;
1108 i_protocol = (int32_t) protocol;
1109 i_aprotocol = (int32_t) a->family;
1111 reply = dbus_message_new_method_return(i->message);
1112 dbus_message_append_args(
1114 DBUS_TYPE_INT32, &i_interface,
1115 DBUS_TYPE_INT32, &i_protocol,
1116 DBUS_TYPE_STRING, &name,
1117 DBUS_TYPE_STRING, &type,
1118 DBUS_TYPE_STRING, &domain,
1119 DBUS_TYPE_STRING, &host_name,
1120 DBUS_TYPE_INT32, &i_aprotocol,
1121 DBUS_TYPE_STRING, &pt,
1122 DBUS_TYPE_UINT16, &port,
1125 dbus_message_iter_init_append(reply, &iter);
1126 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1128 for (p = txt, j = n-1; p; p = p->next, j--) {
1129 DBusMessageIter sub2;
1130 const uint8_t *data = p->text;
1132 dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1133 dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
1134 dbus_message_iter_close_container(&sub, &sub2);
1137 dbus_message_iter_close_container(&iter, &sub);
1139 dbus_connection_send(server->bus, reply, NULL);
1140 dbus_message_unref(reply);
1142 assert(event == AVAHI_RESOLVER_TIMEOUT);
1144 respond_error(server->bus, i->message, AVAHI_ERR_TIMEOUT, NULL);
1147 service_resolver_free(i);
1150 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1153 dbus_error_init(&error);
1155 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
1156 dbus_message_get_interface(m),
1157 dbus_message_get_path(m),
1158 dbus_message_get_member(m));
1160 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1161 return handle_introspect(c, m, "Server.introspect");
1163 else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1165 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1166 avahi_log_warn("Error parsing Server::GetHostName message");
1170 return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1172 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1174 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1175 avahi_log_warn("Error parsing Server::GetDomainName message");
1179 return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1181 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1183 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1184 avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1188 return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1190 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1192 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1193 avahi_log_warn("Error parsing Server::GetVersionString message");
1197 return respond_string(c, m, PACKAGE_STRING);
1199 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1200 AvahiServerState state;
1202 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1203 avahi_log_warn("Error parsing Server::GetState message");
1207 state = avahi_server_get_state(avahi_server);
1208 return respond_int32(c, m, (int32_t) state);
1210 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1215 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1216 avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1220 #ifdef VALGRIND_WORKAROUND
1221 return respond_string(c, m, "blah");
1224 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1226 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1227 return respond_error(c, m, AVAHI_ERR_OS, txt);
1230 memset(&ifr, 0, sizeof(ifr));
1231 ifr.ifr_ifindex = idx;
1233 if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) {
1235 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1237 return respond_error(c, m, AVAHI_ERR_OS, txt);
1242 return respond_string(c, m, ifr.ifr_name);
1245 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1250 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1251 avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1255 #ifdef VALGRIND_WORKAROUND
1256 return respond_int32(c, m, 1);
1258 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1260 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1261 return respond_error(c, m, AVAHI_ERR_OS, txt);
1264 memset(&ifr, 0, sizeof(ifr));
1265 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", n);
1267 if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
1269 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1271 return respond_error(c, m, AVAHI_ERR_OS, txt);
1276 return respond_int32(c, m, ifr.ifr_ifindex);
1279 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1282 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1283 avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1287 t = avahi_alternative_host_name(n);
1288 respond_string(c, m, t);
1291 return DBUS_HANDLER_RESULT_HANDLED;
1293 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1296 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1297 avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1301 t = avahi_alternative_service_name(n);
1302 respond_string(c, m, t);
1305 return DBUS_HANDLER_RESULT_HANDLED;
1307 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1310 static const DBusObjectPathVTable vtable = {
1312 msg_entry_group_impl,
1319 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1320 avahi_log_warn("Error parsing Server::EntryGroupNew message");
1324 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1325 avahi_log_warn("Too many clients, client request failed.");
1326 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1329 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1330 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1331 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1334 i = avahi_new(EntryGroupInfo, 1);
1335 i->id = ++client->current_id;
1337 i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1339 AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1340 client->n_objects++;
1342 if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1343 entry_group_free(i);
1344 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1347 dbus_connection_register_object_path(c, i->path, &vtable, i);
1348 return respond_path(c, m, i->path);
1350 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1352 int32_t interface, protocol, aprotocol;
1354 SyncHostNameResolverInfo *i;
1356 if (!dbus_message_get_args(
1358 DBUS_TYPE_INT32, &interface,
1359 DBUS_TYPE_INT32, &protocol,
1360 DBUS_TYPE_STRING, &name,
1361 DBUS_TYPE_INT32, &aprotocol,
1362 DBUS_TYPE_INVALID) || !name) {
1363 avahi_log_warn("Error parsing Server::ResolveHostName message");
1367 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1368 avahi_log_warn("Too many clients, client request failed.");
1369 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1372 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1373 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1374 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1377 i = avahi_new(SyncHostNameResolverInfo, 1);
1379 i->message = dbus_message_ref(m);
1380 AVAHI_LLIST_PREPEND(SyncHostNameResolverInfo, sync_host_name_resolvers, client->sync_host_name_resolvers, i);
1381 client->n_objects++;
1383 if (!(i->host_name_resolver = avahi_s_host_name_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, (AvahiProtocol) aprotocol, host_name_resolver_callback, i))) {
1384 host_name_resolver_free(i);
1385 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1388 return DBUS_HANDLER_RESULT_HANDLED;
1390 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1392 int32_t interface, protocol;
1394 SyncAddressResolverInfo *i;
1397 if (!dbus_message_get_args(
1399 DBUS_TYPE_INT32, &interface,
1400 DBUS_TYPE_INT32, &protocol,
1401 DBUS_TYPE_STRING, &address,
1402 DBUS_TYPE_INVALID) || !address) {
1403 avahi_log_warn("Error parsing Server::ResolveAddress message");
1407 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
1408 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
1410 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1411 avahi_log_warn("Too many clients, client request failed.");
1412 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1415 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1416 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1417 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1420 i = avahi_new(SyncAddressResolverInfo, 1);
1422 i->message = dbus_message_ref(m);
1423 AVAHI_LLIST_PREPEND(SyncAddressResolverInfo, sync_address_resolvers, client->sync_address_resolvers, i);
1424 client->n_objects++;
1426 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, address_resolver_callback, i))) {
1427 address_resolver_free(i);
1428 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1431 return DBUS_HANDLER_RESULT_HANDLED;
1433 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
1435 DomainBrowserInfo *i;
1436 static const DBusObjectPathVTable vtable = {
1438 msg_domain_browser_impl,
1444 int32_t interface, protocol, type;
1448 if (!dbus_message_get_args(
1450 DBUS_TYPE_INT32, &interface,
1451 DBUS_TYPE_INT32, &protocol,
1452 DBUS_TYPE_STRING, &domain,
1453 DBUS_TYPE_INT32, &type,
1454 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
1455 avahi_log_warn("Error parsing Server::DomainBrowserNew message");
1459 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1460 avahi_log_warn("Too many clients, client request failed.");
1461 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1464 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1465 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1466 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1472 i = avahi_new(DomainBrowserInfo, 1);
1473 i->id = ++client->current_id;
1475 i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
1476 AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
1477 client->n_objects++;
1479 if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, domain_browser_callback, i))) {
1480 domain_browser_free(i);
1481 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1484 dbus_connection_register_object_path(c, i->path, &vtable, i);
1485 return respond_path(c, m, i->path);
1487 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
1489 ServiceTypeBrowserInfo *i;
1490 static const DBusObjectPathVTable vtable = {
1492 msg_service_type_browser_impl,
1498 int32_t interface, protocol;
1501 if (!dbus_message_get_args(
1503 DBUS_TYPE_INT32, &interface,
1504 DBUS_TYPE_INT32, &protocol,
1505 DBUS_TYPE_STRING, &domain,
1506 DBUS_TYPE_INVALID)) {
1507 avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
1511 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1512 avahi_log_warn("Too many clients, client request failed.");
1513 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1517 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1518 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1519 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1525 i = avahi_new(ServiceTypeBrowserInfo, 1);
1526 i->id = ++client->current_id;
1528 i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
1529 AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
1530 client->n_objects++;
1532 if (!(i->service_type_browser = avahi_s_service_type_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, service_type_browser_callback, i))) {
1533 service_type_browser_free(i);
1534 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1537 dbus_connection_register_object_path(c, i->path, &vtable, i);
1538 return respond_path(c, m, i->path);
1540 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
1542 ServiceBrowserInfo *i;
1543 static const DBusObjectPathVTable vtable = {
1545 msg_service_browser_impl,
1551 int32_t interface, protocol;
1552 char *domain, *type;
1554 if (!dbus_message_get_args(
1556 DBUS_TYPE_INT32, &interface,
1557 DBUS_TYPE_INT32, &protocol,
1558 DBUS_TYPE_STRING, &type,
1559 DBUS_TYPE_STRING, &domain,
1560 DBUS_TYPE_INVALID) || !type) {
1561 avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
1565 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1566 avahi_log_warn("Too many clients, client request failed.");
1567 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1571 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1572 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1573 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1579 i = avahi_new(ServiceBrowserInfo, 1);
1580 i->id = ++client->current_id;
1582 i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
1583 AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
1584 client->n_objects++;
1586 if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, service_browser_callback, i))) {
1587 service_browser_free(i);
1588 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1591 dbus_connection_register_object_path(c, i->path, &vtable, i);
1592 return respond_path(c, m, i->path);
1594 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
1596 int32_t interface, protocol, aprotocol;
1597 char *name, *type, *domain;
1598 SyncServiceResolverInfo *i;
1600 if (!dbus_message_get_args(
1602 DBUS_TYPE_INT32, &interface,
1603 DBUS_TYPE_INT32, &protocol,
1604 DBUS_TYPE_STRING, &name,
1605 DBUS_TYPE_STRING, &type,
1606 DBUS_TYPE_STRING, &domain,
1607 DBUS_TYPE_INT32, &aprotocol,
1608 DBUS_TYPE_INVALID) || !name || !type) {
1609 avahi_log_warn("Error parsing Server::ResolveService message");
1613 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1614 avahi_log_warn("Too many clients, client request failed.");
1615 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1618 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1619 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1620 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1626 i = avahi_new(SyncServiceResolverInfo, 1);
1628 i->message = dbus_message_ref(m);
1629 AVAHI_LLIST_PREPEND(SyncServiceResolverInfo, sync_service_resolvers, client->sync_service_resolvers, i);
1630 client->n_objects++;
1632 if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, service_resolver_callback, i))) {
1633 service_resolver_free(i);
1634 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1637 return DBUS_HANDLER_RESULT_HANDLED;
1640 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1643 if (dbus_error_is_set(&error))
1644 dbus_error_free(&error);
1646 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1649 void dbus_protocol_server_state_changed(AvahiServerState state) {
1656 m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
1657 t = (int32_t) state;
1658 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
1659 dbus_connection_send(server->bus, m, NULL);
1660 dbus_message_unref(m);
1663 int dbus_protocol_setup(const AvahiPoll *poll_api) {
1666 static const DBusObjectPathVTable server_vtable = {
1675 dbus_error_init(&error);
1677 server = avahi_new(Server, 1);
1678 AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
1679 server->current_id = 0;
1680 server->n_clients = 0;
1682 if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
1683 assert(dbus_error_is_set(&error));
1684 avahi_log_error("dbus_bus_get(): %s", error.message);
1688 if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) {
1689 avahi_log_error("avahi_dbus_connection_glue() failed");
1693 if (dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1694 if (dbus_error_is_set(&error)) {
1695 avahi_log_error("dbus_bus_request_name(): %s", error.message);
1699 avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'");
1703 if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) {
1704 avahi_log_error("dbus_connection_add_filter() failed");
1708 dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
1710 if (dbus_error_is_set(&error)) {
1711 avahi_log_error("dbus_bus_add_match(): %s", error.message);
1715 if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
1716 avahi_log_error("dbus_connection_register_object_path() failed");
1724 dbus_connection_disconnect(server->bus);
1725 dbus_connection_unref(server->bus);
1728 if (dbus_error_is_set(&error))
1729 dbus_error_free(&error);
1736 void dbus_protocol_shutdown(void) {
1740 while (server->clients)
1741 client_free(server->clients);
1743 assert(server->n_clients == 0);
1746 dbus_connection_disconnect(server->bus);
1747 dbus_connection_unref(server->bus);