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-core/log.h>
45 #include <avahi-core/core.h>
47 #include "dbus-protocol.h"
50 typedef struct Server Server;
51 typedef struct Client Client;
52 typedef struct EntryGroupInfo EntryGroupInfo;
53 typedef struct HostNameResolverInfo HostNameResolverInfo;
54 typedef struct AddressResolverInfo AddressResolverInfo;
55 typedef struct DomainBrowserInfo DomainBrowserInfo;
56 typedef struct ServiceTypeBrowserInfo ServiceTypeBrowserInfo;
57 typedef struct ServiceBrowserInfo ServiceBrowserInfo;
58 typedef struct ServiceResolverInfo ServiceResolverInfo;
60 #define MAX_CLIENTS 20
61 #define MAX_OBJECTS_PER_CLIENT 50
62 #define MAX_ENTRIES_PER_ENTRY_GROUP 20
64 /* #define VALGRIND_WORKAROUND */
66 struct EntryGroupInfo {
69 AvahiSEntryGroup *entry_group;
74 AVAHI_LLIST_FIELDS(EntryGroupInfo, entry_groups);
77 struct HostNameResolverInfo {
79 AvahiSHostNameResolver *host_name_resolver;
82 AVAHI_LLIST_FIELDS(HostNameResolverInfo, host_name_resolvers);
85 struct AddressResolverInfo {
87 AvahiSAddressResolver *address_resolver;
90 AVAHI_LLIST_FIELDS(AddressResolverInfo, address_resolvers);
93 struct DomainBrowserInfo {
96 AvahiSDomainBrowser *domain_browser;
99 AVAHI_LLIST_FIELDS(DomainBrowserInfo, domain_browsers);
102 struct ServiceTypeBrowserInfo {
105 AvahiSServiceTypeBrowser *service_type_browser;
108 AVAHI_LLIST_FIELDS(ServiceTypeBrowserInfo, service_type_browsers);
111 struct ServiceBrowserInfo {
114 AvahiSServiceBrowser *service_browser;
117 AVAHI_LLIST_FIELDS(ServiceBrowserInfo, service_browsers);
120 struct ServiceResolverInfo {
122 AvahiSServiceResolver *service_resolver;
123 DBusMessage *message;
125 AVAHI_LLIST_FIELDS(ServiceResolverInfo, service_resolvers);
134 AVAHI_LLIST_FIELDS(Client, clients);
135 AVAHI_LLIST_HEAD(EntryGroupInfo, entry_groups);
136 AVAHI_LLIST_HEAD(HostNameResolverInfo, host_name_resolvers);
137 AVAHI_LLIST_HEAD(AddressResolverInfo, address_resolvers);
138 AVAHI_LLIST_HEAD(DomainBrowserInfo, domain_browsers);
139 AVAHI_LLIST_HEAD(ServiceTypeBrowserInfo, service_type_browsers);
140 AVAHI_LLIST_HEAD(ServiceBrowserInfo, service_browsers);
141 AVAHI_LLIST_HEAD(ServiceResolverInfo, service_resolvers);
146 AVAHI_LLIST_HEAD(Client, clients);
151 static Server *server = NULL;
153 static void entry_group_free(EntryGroupInfo *i) {
157 avahi_s_entry_group_free(i->entry_group);
158 dbus_connection_unregister_object_path(server->bus, i->path);
160 AVAHI_LLIST_REMOVE(EntryGroupInfo, entry_groups, i->client->entry_groups, i);
162 i->client->n_objects--;
163 assert(i->client->n_objects >= 0);
168 static void host_name_resolver_free(HostNameResolverInfo *i) {
171 if (i->host_name_resolver)
172 avahi_s_host_name_resolver_free(i->host_name_resolver);
173 dbus_message_unref(i->message);
174 AVAHI_LLIST_REMOVE(HostNameResolverInfo, host_name_resolvers, i->client->host_name_resolvers, i);
176 i->client->n_objects--;
177 assert(i->client->n_objects >= 0);
182 static void address_resolver_free(AddressResolverInfo *i) {
185 if (i->address_resolver)
186 avahi_s_address_resolver_free(i->address_resolver);
187 dbus_message_unref(i->message);
188 AVAHI_LLIST_REMOVE(AddressResolverInfo, address_resolvers, i->client->address_resolvers, i);
190 i->client->n_objects--;
191 assert(i->client->n_objects >= 0);
196 static void domain_browser_free(DomainBrowserInfo *i) {
199 if (i->domain_browser)
200 avahi_s_domain_browser_free(i->domain_browser);
201 dbus_connection_unregister_object_path(server->bus, i->path);
203 AVAHI_LLIST_REMOVE(DomainBrowserInfo, domain_browsers, i->client->domain_browsers, i);
205 i->client->n_objects--;
206 assert(i->client->n_objects >= 0);
211 static void service_type_browser_free(ServiceTypeBrowserInfo *i) {
214 if (i->service_type_browser)
215 avahi_s_service_type_browser_free(i->service_type_browser);
216 dbus_connection_unregister_object_path(server->bus, i->path);
218 AVAHI_LLIST_REMOVE(ServiceTypeBrowserInfo, service_type_browsers, i->client->service_type_browsers, i);
220 i->client->n_objects--;
221 assert(i->client->n_objects >= 0);
226 static void service_browser_free(ServiceBrowserInfo *i) {
229 if (i->service_browser)
230 avahi_s_service_browser_free(i->service_browser);
231 dbus_connection_unregister_object_path(server->bus, i->path);
233 AVAHI_LLIST_REMOVE(ServiceBrowserInfo, service_browsers, i->client->service_browsers, i);
235 i->client->n_objects--;
236 assert(i->client->n_objects >= 0);
241 static void service_resolver_free(ServiceResolverInfo *i) {
244 if (i->service_resolver)
245 avahi_s_service_resolver_free(i->service_resolver);
246 dbus_message_unref(i->message);
247 AVAHI_LLIST_REMOVE(ServiceResolverInfo, service_resolvers, i->client->service_resolvers, i);
249 i->client->n_objects--;
250 assert(i->client->n_objects >= 0);
255 static void client_free(Client *c) {
260 while (c->entry_groups)
261 entry_group_free(c->entry_groups);
263 while (c->host_name_resolvers)
264 host_name_resolver_free(c->host_name_resolvers);
266 while (c->address_resolvers)
267 address_resolver_free(c->address_resolvers);
269 while (c->domain_browsers)
270 domain_browser_free(c->domain_browsers);
272 while (c->service_type_browsers)
273 service_type_browser_free(c->service_type_browsers);
275 while (c->service_browsers)
276 service_browser_free(c->service_browsers);
278 while (c->service_resolvers)
279 service_resolver_free(c->service_resolvers);
281 assert(c->n_objects == 0);
284 AVAHI_LLIST_REMOVE(Client, clients, server->clients, c);
287 server->n_clients --;
288 assert(server->n_clients >= 0);
291 static Client *client_get(const char *name, int create) {
297 for (client = server->clients; client; client = client->clients_next)
298 if (!strcmp(name, client->name))
304 if (server->n_clients >= MAX_CLIENTS)
307 /* If not existant yet, create a new entry */
308 client = avahi_new(Client, 1);
309 client->id = server->current_id++;
310 client->name = avahi_strdup(name);
311 client->current_id = 0;
312 client->n_objects = 0;
313 AVAHI_LLIST_HEAD_INIT(EntryGroupInfo, client->entry_groups);
314 AVAHI_LLIST_HEAD_INIT(HostNameResolverInfo, client->host_name_resolvers);
315 AVAHI_LLIST_HEAD_INIT(AddressResolverInfo, client->address_resolvers);
316 AVAHI_LLIST_HEAD_INIT(DomainBrowserInfo, client->domain_browsers);
317 AVAHI_LLIST_HEAD_INIT(ServiceTypeBrowserInfo, client->service_type_browsers);
318 AVAHI_LLIST_HEAD_INIT(ServiceBrowserInfo, client->service_browsers);
319 AVAHI_LLIST_HEAD_INIT(ServiceResolverInfo, client->service_resolvers);
321 AVAHI_LLIST_PREPEND(Client, clients, server->clients, client);
324 assert(server->n_clients > 0);
329 static DBusHandlerResult respond_error(DBusConnection *c, DBusMessage *m, int error, const char *text) {
332 assert(-error > -AVAHI_OK);
333 assert(-error < -AVAHI_ERR_MAX);
335 reply = dbus_message_new_error(m, avahi_error_number_to_dbus (error), text ? text : avahi_strerror(error));
336 dbus_connection_send(c, reply, NULL);
337 dbus_message_unref(reply);
339 return DBUS_HANDLER_RESULT_HANDLED;
342 static DBusHandlerResult respond_string(DBusConnection *c, DBusMessage *m, const char *text) {
345 reply = dbus_message_new_method_return(m);
346 dbus_message_append_args(reply, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID);
347 dbus_connection_send(c, reply, NULL);
348 dbus_message_unref(reply);
350 return DBUS_HANDLER_RESULT_HANDLED;
353 static DBusHandlerResult respond_int32(DBusConnection *c, DBusMessage *m, int32_t i) {
356 reply = dbus_message_new_method_return(m);
357 dbus_message_append_args(reply, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID);
358 dbus_connection_send(c, reply, NULL);
359 dbus_message_unref(reply);
361 return DBUS_HANDLER_RESULT_HANDLED;
364 static DBusHandlerResult respond_ok(DBusConnection *c, DBusMessage *m) {
367 reply = dbus_message_new_method_return(m);
368 dbus_connection_send(c, reply, NULL);
369 dbus_message_unref(reply);
371 return DBUS_HANDLER_RESULT_HANDLED;
374 static DBusHandlerResult respond_path(DBusConnection *c, DBusMessage *m, const char *path) {
377 reply = dbus_message_new_method_return(m);
378 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
379 dbus_connection_send(c, reply, NULL);
380 dbus_message_unref(reply);
382 return DBUS_HANDLER_RESULT_HANDLED;
385 static char *file_get_contents(char *fname) {
393 if (!(fd = open(fname, O_RDONLY))) {
394 avahi_log_error("Failed to open %s: %s", fname, strerror(errno));
398 if (fstat(fd, &st) < 0) {
399 avahi_log_error("stat(%s) failed: %s", fname, strerror(errno));
403 if (!(S_ISREG(st.st_mode))) {
404 avahi_log_error("Invalid file %s", fname);
408 if (st.st_size > 1024*1024) { /** 1MB */
409 avahi_log_error("File too large %s", fname);
413 buf = avahi_new(char, st.st_size+1);
415 if ((size = read(fd, buf, st.st_size)) < 0) {
416 avahi_log_error("read() failed: %s\n", strerror(errno));
436 static DBusHandlerResult handle_introspect(DBusConnection *c, DBusMessage *m, const char *fname) {
437 char *path, *contents;
444 dbus_error_init(&error);
446 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
447 avahi_log_error("Error parsing Introspect message: %s", error.message);
451 path = avahi_strdup_printf("%s/%s", AVAHI_DBUS_INTROSPECTION_DIR, fname);
452 contents = file_get_contents(path);
456 avahi_log_error("Failed to load introspection data.");
460 respond_string(c, m, contents);
461 avahi_free(contents);
463 return DBUS_HANDLER_RESULT_HANDLED;
466 if (dbus_error_is_set(&error))
467 dbus_error_free(&error);
469 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
473 static DBusHandlerResult msg_signal_filter_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
476 dbus_error_init(&error);
478 /* avahi_log_debug("dbus: interface=%s, path=%s, member=%s", */
479 /* dbus_message_get_interface(m), */
480 /* dbus_message_get_path(m), */
481 /* dbus_message_get_member(m)); */
483 if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
484 /* No, we shouldn't quit, but until we get somewhere
485 * usefull such that we can restore our state, we will */
486 avahi_log_warn("Disconnnected from d-bus, terminating...");
488 raise(SIGQUIT); /* The signal handler will catch this and terminate the process cleanly*/
490 return DBUS_HANDLER_RESULT_HANDLED;
492 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) {
495 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
496 avahi_log_warn("Error parsing NameAcquired message");
500 /* avahi_log_info("dbus: name acquired (%s)", name); */
501 return DBUS_HANDLER_RESULT_HANDLED;
503 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
504 char *name, *old, *new;
506 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) {
507 avahi_log_warn("Error parsing NameOwnerChanged message");
514 if ((client = client_get(name, FALSE))) {
515 /* avahi_log_info("dbus: client %s vanished", name); */
522 if (dbus_error_is_set(&error))
523 dbus_error_free(&error);
525 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
528 static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntryGroupState state, void* userdata) {
529 EntryGroupInfo *i = userdata;
537 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged");
539 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
540 dbus_message_set_destination(m, i->client->name);
541 dbus_connection_send(server->bus, m, NULL);
542 dbus_message_unref(m);
545 static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
547 EntryGroupInfo *i = userdata;
553 dbus_error_init(&error);
555 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
556 dbus_message_get_interface(m),
557 dbus_message_get_path(m),
558 dbus_message_get_member(m));
561 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
562 return handle_introspect(c, m, "EntryGroup.introspect");
565 if (strcmp(dbus_message_get_sender(m), i->client->name))
566 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
568 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) {
570 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
571 avahi_log_warn("Error parsing EntryGroup::Free message");
576 return respond_ok(c, m);
578 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Commit")) {
580 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
581 avahi_log_warn("Error parsing EntryGroup::Commit message");
585 avahi_s_entry_group_commit(i->entry_group);
586 return respond_ok(c, m);
589 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Reset")) {
591 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
592 avahi_log_warn("Error parsing EntryGroup::Reset message");
596 avahi_s_entry_group_reset(i->entry_group);
597 return respond_ok(c, m);
599 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) {
603 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
604 avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
608 b = !!avahi_s_entry_group_is_empty(i->entry_group);
610 reply = dbus_message_new_method_return(m);
611 dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
612 dbus_connection_send(c, reply, NULL);
613 dbus_message_unref(reply);
615 return DBUS_HANDLER_RESULT_HANDLED;
617 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
618 AvahiEntryGroupState state;
620 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
621 avahi_log_warn("Error parsing EntryGroup::GetState message");
625 state = avahi_s_entry_group_get_state(i->entry_group);
626 return respond_int32(c, m, (int32_t) state);
628 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
629 int32_t interface, protocol;
630 char *type, *name, *domain, *host;
632 AvahiStringList *strlst;
633 DBusMessageIter iter, sub;
636 if (!dbus_message_get_args(
638 DBUS_TYPE_INT32, &interface,
639 DBUS_TYPE_INT32, &protocol,
640 DBUS_TYPE_STRING, &name,
641 DBUS_TYPE_STRING, &type,
642 DBUS_TYPE_STRING, &domain,
643 DBUS_TYPE_STRING, &host,
644 DBUS_TYPE_UINT16, &port,
645 DBUS_TYPE_INVALID) || !type || !name) {
646 avahi_log_warn("Error parsing EntryGroup::AddService message");
650 dbus_message_iter_init(m, &iter);
652 for (j = 0; j < 7; j++)
653 dbus_message_iter_next(&iter);
655 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
656 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY) {
657 avahi_log_warn("Error parsing EntryGroup::AddService message 2");
662 dbus_message_iter_recurse(&iter, &sub);
665 DBusMessageIter sub2;
669 if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
672 assert(at == DBUS_TYPE_ARRAY);
674 if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) {
675 avahi_log_warn("Error parsing EntryGroup::AddService message");
679 dbus_message_iter_recurse(&sub, &sub2);
680 dbus_message_iter_get_fixed_array(&sub2, &k, &n);
681 strlst = avahi_string_list_add_arbitrary(strlst, k, n);
683 dbus_message_iter_next(&sub);
686 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
687 avahi_string_list_free(strlst);
688 avahi_log_warn("Too many entries per entry group, client request failed.");
689 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
692 if (domain && !*domain)
698 if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, host, port, strlst) < 0) {
699 avahi_string_list_free(strlst);
700 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
704 avahi_string_list_free(strlst);
706 return respond_ok(c, m);
708 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
709 int32_t interface, protocol;
710 char *name, *address;
713 if (!dbus_message_get_args(
715 DBUS_TYPE_INT32, &interface,
716 DBUS_TYPE_INT32, &protocol,
717 DBUS_TYPE_STRING, &name,
718 DBUS_TYPE_STRING, &address,
719 DBUS_TYPE_INVALID) || !name || !address) {
720 avahi_log_warn("Error parsing EntryGroup::AddAddress message");
724 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
725 avahi_log_warn("Too many entries per entry group, client request failed.");
726 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
729 if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))) {
730 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
733 if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, 0, name, &a) < 0)
734 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
738 return respond_ok(c, m);
741 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
744 if (dbus_error_is_set(&error))
745 dbus_error_free(&error);
747 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
750 static void host_name_resolver_callback(AvahiSHostNameResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *host_name, const AvahiAddress *a, void* userdata) {
751 HostNameResolverInfo *i = userdata;
757 if (event == AVAHI_RESOLVER_FOUND) {
758 char t[256], *pt = t;
759 int32_t i_interface, i_protocol, i_aprotocol;
763 avahi_address_snprint(t, sizeof(t), a);
765 i_interface = (int32_t) interface;
766 i_protocol = (int32_t) protocol;
767 i_aprotocol = (int32_t) a->family;
769 reply = dbus_message_new_method_return(i->message);
770 dbus_message_append_args(
772 DBUS_TYPE_INT32, &i_interface,
773 DBUS_TYPE_INT32, &i_protocol,
774 DBUS_TYPE_STRING, &host_name,
775 DBUS_TYPE_INT32, &i_aprotocol,
776 DBUS_TYPE_STRING, &pt,
779 dbus_connection_send(server->bus, reply, NULL);
780 dbus_message_unref(reply);
782 assert(event == AVAHI_RESOLVER_TIMEOUT);
784 respond_error(server->bus, i->message, AVAHI_ERR_TIMEOUT, NULL);
787 host_name_resolver_free(i);
790 static void address_resolver_callback(AvahiSAddressResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const AvahiAddress *address, const char *host_name, void* userdata) {
791 AddressResolverInfo *i = userdata;
797 if (event == AVAHI_RESOLVER_FOUND) {
798 char t[256], *pt = t;
799 int32_t i_interface, i_protocol, i_aprotocol;
803 avahi_address_snprint(t, sizeof(t), address);
805 i_interface = (int32_t) interface;
806 i_protocol = (int32_t) protocol;
807 i_aprotocol = (int32_t) address->family;
809 reply = dbus_message_new_method_return(i->message);
810 dbus_message_append_args(
812 DBUS_TYPE_INT32, &i_interface,
813 DBUS_TYPE_INT32, &i_protocol,
814 DBUS_TYPE_INT32, &i_aprotocol,
815 DBUS_TYPE_STRING, &pt,
816 DBUS_TYPE_STRING, &host_name,
819 dbus_connection_send(server->bus, reply, NULL);
820 dbus_message_unref(reply);
822 assert(event == AVAHI_RESOLVER_TIMEOUT);
823 respond_error(server->bus, i->message, AVAHI_ERR_TIMEOUT, NULL);
826 address_resolver_free(i);
829 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
831 DomainBrowserInfo *i = userdata;
837 dbus_error_init(&error);
839 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
840 dbus_message_get_interface(m),
841 dbus_message_get_path(m),
842 dbus_message_get_member(m));
845 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
846 return handle_introspect(c, m, "DomainBrowser.introspect");
849 if (strcmp(dbus_message_get_sender(m), i->client->name))
850 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
852 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
854 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
855 avahi_log_warn("Error parsing DomainBrowser::Free message");
859 domain_browser_free(i);
860 return respond_ok(c, m);
864 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
867 if (dbus_error_is_set(&error))
868 dbus_error_free(&error);
870 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
873 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, void* userdata) {
874 DomainBrowserInfo *i = userdata;
876 int32_t i_interface, i_protocol;
882 i_interface = (int32_t) interface;
883 i_protocol = (int32_t) protocol;
885 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, event == AVAHI_BROWSER_NEW ? "ItemNew" : "ItemRemove");
886 dbus_message_append_args(
888 DBUS_TYPE_INT32, &i_interface,
889 DBUS_TYPE_INT32, &i_protocol,
890 DBUS_TYPE_STRING, &domain,
892 dbus_message_set_destination(m, i->client->name);
893 dbus_connection_send(server->bus, m, NULL);
894 dbus_message_unref(m);
897 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
899 ServiceTypeBrowserInfo *i = userdata;
905 dbus_error_init(&error);
907 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
908 dbus_message_get_interface(m),
909 dbus_message_get_path(m),
910 dbus_message_get_member(m));
913 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
914 return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
917 if (strcmp(dbus_message_get_sender(m), i->client->name))
918 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
920 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
922 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
923 avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
927 service_type_browser_free(i);
928 return respond_ok(c, m);
932 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
935 if (dbus_error_is_set(&error))
936 dbus_error_free(&error);
938 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
941 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, void* userdata) {
942 ServiceTypeBrowserInfo *i = userdata;
944 int32_t i_interface, i_protocol;
951 i_interface = (int32_t) interface;
952 i_protocol = (int32_t) protocol;
954 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, event == AVAHI_BROWSER_NEW ? "ItemNew" : "ItemRemove");
955 dbus_message_append_args(
957 DBUS_TYPE_INT32, &i_interface,
958 DBUS_TYPE_INT32, &i_protocol,
959 DBUS_TYPE_STRING, &type,
960 DBUS_TYPE_STRING, &domain,
962 dbus_message_set_destination(m, i->client->name);
963 dbus_connection_send(server->bus, m, NULL);
964 dbus_message_unref(m);
967 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
969 ServiceBrowserInfo *i = userdata;
975 dbus_error_init(&error);
977 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
978 dbus_message_get_interface(m),
979 dbus_message_get_path(m),
980 dbus_message_get_member(m));
983 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
984 return handle_introspect(c, m, "ServiceBrowser.Introspect");
987 if (strcmp(dbus_message_get_sender(m), i->client->name))
988 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
990 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
992 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
993 avahi_log_warn("Error parsing ServiceBrowser::Free message");
997 service_browser_free(i);
998 return respond_ok(c, m);
1002 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1005 if (dbus_error_is_set(&error))
1006 dbus_error_free(&error);
1008 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1011 static void service_browser_callback(AvahiSServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, void* userdata) {
1012 ServiceBrowserInfo *i = userdata;
1014 int32_t i_interface, i_protocol;
1022 i_interface = (int32_t) interface;
1023 i_protocol = (int32_t) protocol;
1025 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, event == AVAHI_BROWSER_NEW ? "ItemNew" : "ItemRemove");
1026 dbus_message_append_args(
1028 DBUS_TYPE_INT32, &i_interface,
1029 DBUS_TYPE_INT32, &i_protocol,
1030 DBUS_TYPE_STRING, &name,
1031 DBUS_TYPE_STRING, &type,
1032 DBUS_TYPE_STRING, &domain,
1034 dbus_message_set_destination(m, i->client->name);
1035 dbus_connection_send(server->bus, m, NULL);
1036 dbus_message_unref(m);
1039 static void service_resolver_callback(
1040 AvahiSServiceResolver *r,
1041 AvahiIfIndex interface,
1042 AvahiProtocol protocol,
1043 AvahiResolverEvent event,
1047 const char *host_name,
1048 const AvahiAddress *a,
1050 AvahiStringList *txt,
1053 ServiceResolverInfo *i = userdata;
1058 if (event == AVAHI_RESOLVER_FOUND) {
1059 char t[256], *pt = t;
1060 int32_t i_interface, i_protocol, i_aprotocol;
1064 DBusMessageIter iter, sub;
1069 avahi_address_snprint(t, sizeof(t), a);
1071 i_interface = (int32_t) interface;
1072 i_protocol = (int32_t) protocol;
1073 i_aprotocol = (int32_t) a->family;
1075 reply = dbus_message_new_method_return(i->message);
1076 dbus_message_append_args(
1078 DBUS_TYPE_INT32, &i_interface,
1079 DBUS_TYPE_INT32, &i_protocol,
1080 DBUS_TYPE_STRING, &name,
1081 DBUS_TYPE_STRING, &type,
1082 DBUS_TYPE_STRING, &domain,
1083 DBUS_TYPE_STRING, &host_name,
1084 DBUS_TYPE_INT32, &i_aprotocol,
1085 DBUS_TYPE_STRING, &pt,
1086 DBUS_TYPE_UINT16, &port,
1089 dbus_message_iter_init_append(reply, &iter);
1090 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1092 for (p = txt, j = n-1; p; p = p->next, j--) {
1093 DBusMessageIter sub2;
1094 const uint8_t *data = p->text;
1096 dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1097 dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
1098 dbus_message_iter_close_container(&sub, &sub2);
1101 dbus_message_iter_close_container(&iter, &sub);
1103 dbus_connection_send(server->bus, reply, NULL);
1104 dbus_message_unref(reply);
1106 assert(event == AVAHI_RESOLVER_TIMEOUT);
1108 respond_error(server->bus, i->message, AVAHI_ERR_TIMEOUT, NULL);
1111 service_resolver_free(i);
1114 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1117 dbus_error_init(&error);
1119 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
1120 dbus_message_get_interface(m),
1121 dbus_message_get_path(m),
1122 dbus_message_get_member(m));
1124 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1125 return handle_introspect(c, m, "Server.introspect");
1127 else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1129 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1130 avahi_log_warn("Error parsing Server::GetHostName message");
1134 return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1136 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1138 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1139 avahi_log_warn("Error parsing Server::GetDomainName message");
1143 return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1145 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1147 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1148 avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1152 return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1154 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1156 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1157 avahi_log_warn("Error parsing Server::GetVersionString message");
1161 return respond_string(c, m, PACKAGE_STRING);
1163 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1164 AvahiServerState state;
1166 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1167 avahi_log_warn("Error parsing Server::GetState message");
1171 state = avahi_server_get_state(avahi_server);
1172 return respond_int32(c, m, (int32_t) state);
1174 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1179 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1180 avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1184 #ifdef VALGRIND_WORKAROUND
1185 return respond_string(c, m, "blah");
1188 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1190 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1191 return respond_error(c, m, AVAHI_ERR_OS, txt);
1194 memset(&ifr, 0, sizeof(ifr));
1195 ifr.ifr_ifindex = idx;
1197 if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) {
1199 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1201 return respond_error(c, m, AVAHI_ERR_OS, txt);
1206 return respond_string(c, m, ifr.ifr_name);
1209 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1214 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1215 avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1219 #ifdef VALGRIND_WORKAROUND
1220 return respond_int32(c, m, 1);
1222 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1224 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1225 return respond_error(c, m, AVAHI_ERR_OS, txt);
1228 memset(&ifr, 0, sizeof(ifr));
1229 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", n);
1231 if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
1233 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1235 return respond_error(c, m, AVAHI_ERR_OS, txt);
1240 return respond_int32(c, m, ifr.ifr_ifindex);
1243 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1246 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1247 avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1251 t = avahi_alternative_host_name(n);
1252 respond_string(c, m, t);
1255 return DBUS_HANDLER_RESULT_HANDLED;
1257 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1260 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1261 avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1265 t = avahi_alternative_service_name(n);
1266 respond_string(c, m, t);
1269 return DBUS_HANDLER_RESULT_HANDLED;
1271 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1274 static const DBusObjectPathVTable vtable = {
1276 msg_entry_group_impl,
1283 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1284 avahi_log_warn("Error parsing Server::EntryGroupNew message");
1288 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1289 avahi_log_warn("Too many clients, client request failed.");
1290 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1293 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1294 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1295 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1298 i = avahi_new(EntryGroupInfo, 1);
1299 i->id = ++client->current_id;
1301 i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1303 AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1304 client->n_objects++;
1306 if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1307 entry_group_free(i);
1308 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1311 dbus_connection_register_object_path(c, i->path, &vtable, i);
1312 return respond_path(c, m, i->path);
1314 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1316 int32_t interface, protocol, aprotocol;
1318 HostNameResolverInfo *i;
1320 if (!dbus_message_get_args(
1322 DBUS_TYPE_INT32, &interface,
1323 DBUS_TYPE_INT32, &protocol,
1324 DBUS_TYPE_STRING, &name,
1325 DBUS_TYPE_INT32, &aprotocol,
1326 DBUS_TYPE_INVALID) || !name) {
1327 avahi_log_warn("Error parsing Server::ResolveHostName message");
1331 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1332 avahi_log_warn("Too many clients, client request failed.");
1333 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1336 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1337 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1338 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1341 i = avahi_new(HostNameResolverInfo, 1);
1343 i->message = dbus_message_ref(m);
1344 AVAHI_LLIST_PREPEND(HostNameResolverInfo, host_name_resolvers, client->host_name_resolvers, i);
1345 client->n_objects++;
1347 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))) {
1348 host_name_resolver_free(i);
1349 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1352 return DBUS_HANDLER_RESULT_HANDLED;
1354 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1356 int32_t interface, protocol;
1358 AddressResolverInfo *i;
1361 if (!dbus_message_get_args(
1363 DBUS_TYPE_INT32, &interface,
1364 DBUS_TYPE_INT32, &protocol,
1365 DBUS_TYPE_STRING, &address,
1366 DBUS_TYPE_INVALID) || !address) {
1367 avahi_log_warn("Error parsing Server::ResolveAddress message");
1371 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
1372 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
1374 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1375 avahi_log_warn("Too many clients, client request failed.");
1376 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1379 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1380 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1381 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1384 i = avahi_new(AddressResolverInfo, 1);
1386 i->message = dbus_message_ref(m);
1387 AVAHI_LLIST_PREPEND(AddressResolverInfo, address_resolvers, client->address_resolvers, i);
1388 client->n_objects++;
1390 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, address_resolver_callback, i))) {
1391 address_resolver_free(i);
1392 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1395 return DBUS_HANDLER_RESULT_HANDLED;
1397 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
1399 DomainBrowserInfo *i;
1400 static const DBusObjectPathVTable vtable = {
1402 msg_domain_browser_impl,
1408 int32_t interface, protocol, type;
1412 if (!dbus_message_get_args(
1414 DBUS_TYPE_INT32, &interface,
1415 DBUS_TYPE_INT32, &protocol,
1416 DBUS_TYPE_STRING, &domain,
1417 DBUS_TYPE_INT32, &type,
1418 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
1419 avahi_log_warn("Error parsing Server::DomainBrowserNew message");
1423 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1424 avahi_log_warn("Too many clients, client request failed.");
1425 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1428 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1429 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1430 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1436 i = avahi_new(DomainBrowserInfo, 1);
1437 i->id = ++client->current_id;
1439 i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
1440 AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
1441 client->n_objects++;
1443 if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, domain_browser_callback, i))) {
1444 domain_browser_free(i);
1445 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1448 dbus_connection_register_object_path(c, i->path, &vtable, i);
1449 return respond_path(c, m, i->path);
1451 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
1453 ServiceTypeBrowserInfo *i;
1454 static const DBusObjectPathVTable vtable = {
1456 msg_service_type_browser_impl,
1462 int32_t interface, protocol;
1465 if (!dbus_message_get_args(
1467 DBUS_TYPE_INT32, &interface,
1468 DBUS_TYPE_INT32, &protocol,
1469 DBUS_TYPE_STRING, &domain,
1470 DBUS_TYPE_INVALID)) {
1471 avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
1475 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1476 avahi_log_warn("Too many clients, client request failed.");
1477 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1481 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1482 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1483 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1489 i = avahi_new(ServiceTypeBrowserInfo, 1);
1490 i->id = ++client->current_id;
1492 i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
1493 AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
1494 client->n_objects++;
1496 if (!(i->service_type_browser = avahi_s_service_type_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, service_type_browser_callback, i))) {
1497 service_type_browser_free(i);
1498 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1501 dbus_connection_register_object_path(c, i->path, &vtable, i);
1502 return respond_path(c, m, i->path);
1504 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
1506 ServiceBrowserInfo *i;
1507 static const DBusObjectPathVTable vtable = {
1509 msg_service_browser_impl,
1515 int32_t interface, protocol;
1516 char *domain, *type;
1518 if (!dbus_message_get_args(
1520 DBUS_TYPE_INT32, &interface,
1521 DBUS_TYPE_INT32, &protocol,
1522 DBUS_TYPE_STRING, &type,
1523 DBUS_TYPE_STRING, &domain,
1524 DBUS_TYPE_INVALID) || !type) {
1525 avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
1529 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1530 avahi_log_warn("Too many clients, client request failed.");
1531 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1535 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1536 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1537 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1543 i = avahi_new(ServiceBrowserInfo, 1);
1544 i->id = ++client->current_id;
1546 i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
1547 AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
1548 client->n_objects++;
1550 if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, service_browser_callback, i))) {
1551 service_browser_free(i);
1552 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1555 dbus_connection_register_object_path(c, i->path, &vtable, i);
1556 return respond_path(c, m, i->path);
1558 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
1560 int32_t interface, protocol, aprotocol;
1561 char *name, *type, *domain;
1562 ServiceResolverInfo *i;
1564 if (!dbus_message_get_args(
1566 DBUS_TYPE_INT32, &interface,
1567 DBUS_TYPE_INT32, &protocol,
1568 DBUS_TYPE_STRING, &name,
1569 DBUS_TYPE_STRING, &type,
1570 DBUS_TYPE_STRING, &domain,
1571 DBUS_TYPE_INT32, &aprotocol,
1572 DBUS_TYPE_INVALID) || !name || !type) {
1573 avahi_log_warn("Error parsing Server::ResolveService message");
1577 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1578 avahi_log_warn("Too many clients, client request failed.");
1579 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1582 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1583 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1584 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1590 i = avahi_new(ServiceResolverInfo, 1);
1592 i->message = dbus_message_ref(m);
1593 AVAHI_LLIST_PREPEND(ServiceResolverInfo, service_resolvers, client->service_resolvers, i);
1594 client->n_objects++;
1596 if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, service_resolver_callback, i))) {
1597 service_resolver_free(i);
1598 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1601 return DBUS_HANDLER_RESULT_HANDLED;
1604 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1607 if (dbus_error_is_set(&error))
1608 dbus_error_free(&error);
1610 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1613 void dbus_protocol_server_state_changed(AvahiServerState state) {
1620 m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
1621 t = (int32_t) state;
1622 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
1623 dbus_connection_send(server->bus, m, NULL);
1624 dbus_message_unref(m);
1627 int dbus_protocol_setup(const AvahiPoll *poll_api) {
1630 static const DBusObjectPathVTable server_vtable = {
1639 dbus_error_init(&error);
1641 server = avahi_new(Server, 1);
1642 AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
1643 server->current_id = 0;
1644 server->n_clients = 0;
1646 if (!(server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error))) {
1647 assert(dbus_error_is_set(&error));
1648 avahi_log_error("dbus_bus_get(): %s", error.message);
1652 if (avahi_dbus_connection_glue(server->bus, poll_api) < 0) {
1653 avahi_log_error("avahi_dbus_connection_glue() failed");
1657 if (dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, DBUS_NAME_FLAG_PROHIBIT_REPLACEMENT, &error) != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
1658 if (dbus_error_is_set(&error)) {
1659 avahi_log_error("dbus_bus_request_name(): %s", error.message);
1663 avahi_log_error("Failed to acquire DBUS name '"AVAHI_DBUS_NAME"'");
1667 if (!(dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL))) {
1668 avahi_log_error("dbus_connection_add_filter() failed");
1672 dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
1674 if (dbus_error_is_set(&error)) {
1675 avahi_log_error("dbus_bus_add_match(): %s", error.message);
1679 if (!(dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL))) {
1680 avahi_log_error("dbus_connection_register_object_path() failed");
1688 dbus_connection_disconnect(server->bus);
1689 dbus_connection_unref(server->bus);
1692 if (dbus_error_is_set(&error))
1693 dbus_error_free(&error);
1700 void dbus_protocol_shutdown(void) {
1704 while (server->clients)
1705 client_free(server->clients);
1707 assert(server->n_clients == 0);
1710 dbus_connection_disconnect(server->bus);
1711 dbus_connection_unref(server->bus);