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/llist.h>
40 #include <avahi-common/malloc.h>
41 #include <avahi-common/dbus.h>
42 #include <avahi-common/dbus-watch-glue.h>
43 #include <avahi-core/log.h>
44 #include <avahi-core/core.h>
46 #include "dbus-protocol.h"
49 typedef struct Server Server;
50 typedef struct Client Client;
51 typedef struct EntryGroupInfo EntryGroupInfo;
52 typedef struct HostNameResolverInfo HostNameResolverInfo;
53 typedef struct AddressResolverInfo AddressResolverInfo;
54 typedef struct DomainBrowserInfo DomainBrowserInfo;
55 typedef struct ServiceTypeBrowserInfo ServiceTypeBrowserInfo;
56 typedef struct ServiceBrowserInfo ServiceBrowserInfo;
57 typedef struct ServiceResolverInfo ServiceResolverInfo;
59 #define MAX_CLIENTS 20
60 #define MAX_OBJECTS_PER_CLIENT 50
61 #define MAX_ENTRIES_PER_ENTRY_GROUP 20
63 /* #define VALGRIND_WORKAROUND */
65 struct EntryGroupInfo {
68 AvahiSEntryGroup *entry_group;
73 AVAHI_LLIST_FIELDS(EntryGroupInfo, entry_groups);
76 struct HostNameResolverInfo {
78 AvahiSHostNameResolver *host_name_resolver;
81 AVAHI_LLIST_FIELDS(HostNameResolverInfo, host_name_resolvers);
84 struct AddressResolverInfo {
86 AvahiSAddressResolver *address_resolver;
89 AVAHI_LLIST_FIELDS(AddressResolverInfo, address_resolvers);
92 struct DomainBrowserInfo {
95 AvahiSDomainBrowser *domain_browser;
98 AVAHI_LLIST_FIELDS(DomainBrowserInfo, domain_browsers);
101 struct ServiceTypeBrowserInfo {
104 AvahiSServiceTypeBrowser *service_type_browser;
107 AVAHI_LLIST_FIELDS(ServiceTypeBrowserInfo, service_type_browsers);
110 struct ServiceBrowserInfo {
113 AvahiSServiceBrowser *service_browser;
116 AVAHI_LLIST_FIELDS(ServiceBrowserInfo, service_browsers);
119 struct ServiceResolverInfo {
121 AvahiSServiceResolver *service_resolver;
122 DBusMessage *message;
124 AVAHI_LLIST_FIELDS(ServiceResolverInfo, service_resolvers);
133 AVAHI_LLIST_FIELDS(Client, clients);
134 AVAHI_LLIST_HEAD(EntryGroupInfo, entry_groups);
135 AVAHI_LLIST_HEAD(HostNameResolverInfo, host_name_resolvers);
136 AVAHI_LLIST_HEAD(AddressResolverInfo, address_resolvers);
137 AVAHI_LLIST_HEAD(DomainBrowserInfo, domain_browsers);
138 AVAHI_LLIST_HEAD(ServiceTypeBrowserInfo, service_type_browsers);
139 AVAHI_LLIST_HEAD(ServiceBrowserInfo, service_browsers);
140 AVAHI_LLIST_HEAD(ServiceResolverInfo, service_resolvers);
145 AVAHI_LLIST_HEAD(Client, clients);
150 static Server *server = NULL;
152 static void entry_group_free(EntryGroupInfo *i) {
156 avahi_s_entry_group_free(i->entry_group);
157 dbus_connection_unregister_object_path(server->bus, i->path);
159 AVAHI_LLIST_REMOVE(EntryGroupInfo, entry_groups, i->client->entry_groups, i);
161 i->client->n_objects--;
162 assert(i->client->n_objects >= 0);
167 static void host_name_resolver_free(HostNameResolverInfo *i) {
170 if (i->host_name_resolver)
171 avahi_s_host_name_resolver_free(i->host_name_resolver);
172 dbus_message_unref(i->message);
173 AVAHI_LLIST_REMOVE(HostNameResolverInfo, host_name_resolvers, i->client->host_name_resolvers, i);
175 i->client->n_objects--;
176 assert(i->client->n_objects >= 0);
181 static void address_resolver_free(AddressResolverInfo *i) {
184 if (i->address_resolver)
185 avahi_s_address_resolver_free(i->address_resolver);
186 dbus_message_unref(i->message);
187 AVAHI_LLIST_REMOVE(AddressResolverInfo, address_resolvers, i->client->address_resolvers, i);
189 i->client->n_objects--;
190 assert(i->client->n_objects >= 0);
195 static void domain_browser_free(DomainBrowserInfo *i) {
198 if (i->domain_browser)
199 avahi_s_domain_browser_free(i->domain_browser);
200 dbus_connection_unregister_object_path(server->bus, i->path);
202 AVAHI_LLIST_REMOVE(DomainBrowserInfo, domain_browsers, i->client->domain_browsers, i);
204 i->client->n_objects--;
205 assert(i->client->n_objects >= 0);
210 static void service_type_browser_free(ServiceTypeBrowserInfo *i) {
213 if (i->service_type_browser)
214 avahi_s_service_type_browser_free(i->service_type_browser);
215 dbus_connection_unregister_object_path(server->bus, i->path);
217 AVAHI_LLIST_REMOVE(ServiceTypeBrowserInfo, service_type_browsers, i->client->service_type_browsers, i);
219 i->client->n_objects--;
220 assert(i->client->n_objects >= 0);
225 static void service_browser_free(ServiceBrowserInfo *i) {
228 if (i->service_browser)
229 avahi_s_service_browser_free(i->service_browser);
230 dbus_connection_unregister_object_path(server->bus, i->path);
232 AVAHI_LLIST_REMOVE(ServiceBrowserInfo, service_browsers, i->client->service_browsers, i);
234 i->client->n_objects--;
235 assert(i->client->n_objects >= 0);
240 static void service_resolver_free(ServiceResolverInfo *i) {
243 if (i->service_resolver)
244 avahi_s_service_resolver_free(i->service_resolver);
245 dbus_message_unref(i->message);
246 AVAHI_LLIST_REMOVE(ServiceResolverInfo, service_resolvers, i->client->service_resolvers, i);
248 i->client->n_objects--;
249 assert(i->client->n_objects >= 0);
254 static void client_free(Client *c) {
259 while (c->entry_groups)
260 entry_group_free(c->entry_groups);
262 while (c->host_name_resolvers)
263 host_name_resolver_free(c->host_name_resolvers);
265 while (c->address_resolvers)
266 address_resolver_free(c->address_resolvers);
268 while (c->domain_browsers)
269 domain_browser_free(c->domain_browsers);
271 while (c->service_type_browsers)
272 service_type_browser_free(c->service_type_browsers);
274 while (c->service_browsers)
275 service_browser_free(c->service_browsers);
277 while (c->service_resolvers)
278 service_resolver_free(c->service_resolvers);
280 assert(c->n_objects == 0);
283 AVAHI_LLIST_REMOVE(Client, clients, server->clients, c);
286 server->n_clients --;
287 assert(server->n_clients >= 0);
290 static Client *client_get(const char *name, int create) {
296 for (client = server->clients; client; client = client->clients_next)
297 if (!strcmp(name, client->name))
303 if (server->n_clients >= MAX_CLIENTS)
306 /* If not existant yet, create a new entry */
307 client = avahi_new(Client, 1);
308 client->id = server->current_id++;
309 client->name = avahi_strdup(name);
310 client->current_id = 0;
311 client->n_objects = 0;
312 AVAHI_LLIST_HEAD_INIT(EntryGroupInfo, client->entry_groups);
313 AVAHI_LLIST_HEAD_INIT(HostNameResolverInfo, client->host_name_resolvers);
314 AVAHI_LLIST_HEAD_INIT(AddressResolverInfo, client->address_resolvers);
315 AVAHI_LLIST_HEAD_INIT(DomainBrowserInfo, client->domain_browsers);
316 AVAHI_LLIST_HEAD_INIT(ServiceTypeBrowserInfo, client->service_type_browsers);
317 AVAHI_LLIST_HEAD_INIT(ServiceBrowserInfo, client->service_browsers);
318 AVAHI_LLIST_HEAD_INIT(ServiceResolverInfo, client->service_resolvers);
320 AVAHI_LLIST_PREPEND(Client, clients, server->clients, client);
323 assert(server->n_clients > 0);
328 static DBusHandlerResult respond_error(DBusConnection *c, DBusMessage *m, int error, const char *text) {
331 const char * const table[- AVAHI_ERR_MAX] = {
333 AVAHI_DBUS_ERR_FAILURE,
334 AVAHI_DBUS_ERR_BAD_STATE,
335 AVAHI_DBUS_ERR_INVALID_HOST_NAME,
336 AVAHI_DBUS_ERR_INVALID_DOMAIN_NAME,
337 AVAHI_DBUS_ERR_NO_NETWORK,
338 AVAHI_DBUS_ERR_INVALID_TTL,
339 AVAHI_DBUS_ERR_IS_PATTERN,
340 AVAHI_DBUS_ERR_LOCAL_COLLISION,
341 AVAHI_DBUS_ERR_INVALID_RECORD,
342 AVAHI_DBUS_ERR_INVALID_SERVICE_NAME,
343 AVAHI_DBUS_ERR_INVALID_SERVICE_TYPE,
344 AVAHI_DBUS_ERR_INVALID_PORT,
345 AVAHI_DBUS_ERR_INVALID_KEY,
346 AVAHI_DBUS_ERR_INVALID_ADDRESS,
347 AVAHI_DBUS_ERR_TIMEOUT,
348 AVAHI_DBUS_ERR_TOO_MANY_CLIENTS,
349 AVAHI_DBUS_ERR_TOO_MANY_OBJECTS,
350 AVAHI_DBUS_ERR_TOO_MANY_ENTRIES,
352 AVAHI_DBUS_ERR_ACCESS_DENIED,
353 AVAHI_DBUS_ERR_INVALID_OPERATION,
354 AVAHI_DBUS_ERR_DBUS_ERROR,
355 AVAHI_DBUS_ERR_NOT_CONNECTED,
356 AVAHI_DBUS_ERR_NO_MEMORY,
357 AVAHI_DBUS_ERR_INVALID_OBJECT
360 assert(-error > -AVAHI_OK);
361 assert(-error < -AVAHI_ERR_MAX);
363 reply = dbus_message_new_error(m, table[-error], text ? text : avahi_strerror(error));
364 dbus_connection_send(c, reply, NULL);
365 dbus_message_unref(reply);
367 return DBUS_HANDLER_RESULT_HANDLED;
370 static DBusHandlerResult respond_string(DBusConnection *c, DBusMessage *m, const char *text) {
373 reply = dbus_message_new_method_return(m);
374 dbus_message_append_args(reply, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID);
375 dbus_connection_send(c, reply, NULL);
376 dbus_message_unref(reply);
378 return DBUS_HANDLER_RESULT_HANDLED;
381 static DBusHandlerResult respond_int32(DBusConnection *c, DBusMessage *m, int32_t i) {
384 reply = dbus_message_new_method_return(m);
385 dbus_message_append_args(reply, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID);
386 dbus_connection_send(c, reply, NULL);
387 dbus_message_unref(reply);
389 return DBUS_HANDLER_RESULT_HANDLED;
392 static DBusHandlerResult respond_ok(DBusConnection *c, DBusMessage *m) {
395 reply = dbus_message_new_method_return(m);
396 dbus_connection_send(c, reply, NULL);
397 dbus_message_unref(reply);
399 return DBUS_HANDLER_RESULT_HANDLED;
402 static DBusHandlerResult respond_path(DBusConnection *c, DBusMessage *m, const char *path) {
405 reply = dbus_message_new_method_return(m);
406 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
407 dbus_connection_send(c, reply, NULL);
408 dbus_message_unref(reply);
410 return DBUS_HANDLER_RESULT_HANDLED;
413 static char *file_get_contents(char *fname) {
421 if (!(fd = open(fname, O_RDONLY))) {
422 avahi_log_error("Failed to open %s: %s", fname, strerror(errno));
426 if (fstat(fd, &st) < 0) {
427 avahi_log_error("stat(%s) failed: %s", fname, strerror(errno));
431 if (!(S_ISREG(st.st_mode))) {
432 avahi_log_error("Invalid file %s", fname);
436 if (st.st_size > 1024*1024) { /** 1MB */
437 avahi_log_error("File too large %s", fname);
441 buf = avahi_new(char, st.st_size+1);
443 if ((size = read(fd, buf, st.st_size)) < 0) {
444 avahi_log_error("read() failed: %s\n", strerror(errno));
464 static DBusHandlerResult handle_introspect(DBusConnection *c, DBusMessage *m, const char *fname) {
465 char *path, *contents;
472 dbus_error_init(&error);
474 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
475 avahi_log_error("Error parsing Introspect message: %s", error.message);
479 path = avahi_strdup_printf("%s/%s", AVAHI_DBUS_INTROSPECTION_DIR, fname);
480 contents = file_get_contents(path);
484 avahi_log_error("Failed to load introspection data.");
488 respond_string(c, m, contents);
489 avahi_free(contents);
491 return DBUS_HANDLER_RESULT_HANDLED;
494 if (dbus_error_is_set(&error))
495 dbus_error_free(&error);
497 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
501 static DBusHandlerResult msg_signal_filter_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
504 dbus_error_init(&error);
506 /* avahi_log_debug("dbus: interface=%s, path=%s, member=%s", */
507 /* dbus_message_get_interface(m), */
508 /* dbus_message_get_path(m), */
509 /* dbus_message_get_member(m)); */
511 if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected")) {
512 /* No, we shouldn't quit, but until we get somewhere
513 * usefull such that we can restore our state, we will */
514 avahi_log_warn("Disconnnected from d-bus, terminating...");
516 raise(SIGQUIT); /* The signal handler will catch this and terminate the process cleanly*/
518 return DBUS_HANDLER_RESULT_HANDLED;
520 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameAcquired")) {
523 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID)) {
524 avahi_log_warn("Error parsing NameAcquired message");
528 /* avahi_log_info("dbus: name acquired (%s)", name); */
529 return DBUS_HANDLER_RESULT_HANDLED;
531 } else if (dbus_message_is_signal(m, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) {
532 char *name, *old, *new;
534 if (!dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) {
535 avahi_log_warn("Error parsing NameOwnerChanged message");
542 if ((client = client_get(name, FALSE))) {
543 /* avahi_log_info("dbus: client %s vanished", name); */
550 if (dbus_error_is_set(&error))
551 dbus_error_free(&error);
553 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
556 static void entry_group_callback(AvahiServer *s, AvahiSEntryGroup *g, AvahiEntryGroupState state, void* userdata) {
557 EntryGroupInfo *i = userdata;
565 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "StateChanged");
567 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
568 dbus_message_set_destination(m, i->client->name);
569 dbus_connection_send(server->bus, m, NULL);
570 dbus_message_unref(m);
573 static DBusHandlerResult msg_entry_group_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
575 EntryGroupInfo *i = userdata;
581 dbus_error_init(&error);
583 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
584 dbus_message_get_interface(m),
585 dbus_message_get_path(m),
586 dbus_message_get_member(m));
589 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
590 return handle_introspect(c, m, "EntryGroup.introspect");
593 if (strcmp(dbus_message_get_sender(m), i->client->name))
594 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
596 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Free")) {
598 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
599 avahi_log_warn("Error parsing EntryGroup::Free message");
604 return respond_ok(c, m);
606 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Commit")) {
608 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
609 avahi_log_warn("Error parsing EntryGroup::Commit message");
613 avahi_s_entry_group_commit(i->entry_group);
614 return respond_ok(c, m);
617 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "Reset")) {
619 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
620 avahi_log_warn("Error parsing EntryGroup::Reset message");
624 avahi_s_entry_group_reset(i->entry_group);
625 return respond_ok(c, m);
627 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "IsEmpty")) {
631 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
632 avahi_log_warn("Error parsing EntryGroup::IsEmpty message");
636 b = !!avahi_s_entry_group_is_empty(i->entry_group);
638 reply = dbus_message_new_method_return(m);
639 dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
640 dbus_connection_send(c, reply, NULL);
641 dbus_message_unref(reply);
643 return DBUS_HANDLER_RESULT_HANDLED;
645 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "GetState")) {
646 AvahiEntryGroupState state;
648 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
649 avahi_log_warn("Error parsing EntryGroup::GetState message");
653 state = avahi_s_entry_group_get_state(i->entry_group);
654 return respond_int32(c, m, (int32_t) state);
656 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddService")) {
657 int32_t interface, protocol;
658 char *type, *name, *domain, *host;
660 AvahiStringList *strlst;
661 DBusMessageIter iter, sub;
664 if (!dbus_message_get_args(
666 DBUS_TYPE_INT32, &interface,
667 DBUS_TYPE_INT32, &protocol,
668 DBUS_TYPE_STRING, &name,
669 DBUS_TYPE_STRING, &type,
670 DBUS_TYPE_STRING, &domain,
671 DBUS_TYPE_STRING, &host,
672 DBUS_TYPE_UINT16, &port,
673 DBUS_TYPE_INVALID) || !type || !name) {
674 avahi_log_warn("Error parsing EntryGroup::AddService message");
678 dbus_message_iter_init(m, &iter);
680 for (j = 0; j < 7; j++)
681 dbus_message_iter_next(&iter);
683 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
684 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY) {
685 avahi_log_warn("Error parsing EntryGroup::AddService message 2");
690 dbus_message_iter_recurse(&iter, &sub);
693 DBusMessageIter sub2;
697 if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
700 assert(at == DBUS_TYPE_ARRAY);
702 if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE) {
703 avahi_log_warn("Error parsing EntryGroup::AddService message");
707 dbus_message_iter_recurse(&sub, &sub2);
708 dbus_message_iter_get_fixed_array(&sub2, &k, &n);
709 strlst = avahi_string_list_add_arbitrary(strlst, k, n);
711 dbus_message_iter_next(&sub);
714 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
715 avahi_string_list_free(strlst);
716 avahi_log_warn("Too many entries per entry group, client request failed.");
717 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
720 if (domain && !*domain)
726 if (avahi_server_add_service_strlst(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, host, port, strlst) < 0) {
727 avahi_string_list_free(strlst);
728 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
732 avahi_string_list_free(strlst);
734 return respond_ok(c, m);
736 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_ENTRY_GROUP, "AddAddress")) {
737 int32_t interface, protocol;
738 char *name, *address;
741 if (!dbus_message_get_args(
743 DBUS_TYPE_INT32, &interface,
744 DBUS_TYPE_INT32, &protocol,
745 DBUS_TYPE_STRING, &name,
746 DBUS_TYPE_STRING, &address,
747 DBUS_TYPE_INVALID) || !name || !address) {
748 avahi_log_warn("Error parsing EntryGroup::AddAddress message");
752 if (i->n_entries >= MAX_ENTRIES_PER_ENTRY_GROUP) {
753 avahi_log_warn("Too many entries per entry group, client request failed.");
754 return respond_error(c, m, AVAHI_ERR_TOO_MANY_ENTRIES, NULL);
757 if (!(avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))) {
758 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
761 if (avahi_server_add_address(avahi_server, i->entry_group, (AvahiIfIndex) interface, (AvahiProtocol) protocol, 0, name, &a) < 0)
762 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
766 return respond_ok(c, m);
769 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
772 if (dbus_error_is_set(&error))
773 dbus_error_free(&error);
775 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
778 static void host_name_resolver_callback(AvahiSHostNameResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const char *host_name, const AvahiAddress *a, void* userdata) {
779 HostNameResolverInfo *i = userdata;
785 if (event == AVAHI_RESOLVER_FOUND) {
786 char t[256], *pt = t;
787 int32_t i_interface, i_protocol, i_aprotocol;
791 avahi_address_snprint(t, sizeof(t), a);
793 i_interface = (int32_t) interface;
794 i_protocol = (int32_t) protocol;
795 i_aprotocol = (int32_t) a->family;
797 reply = dbus_message_new_method_return(i->message);
798 dbus_message_append_args(
800 DBUS_TYPE_INT32, &i_interface,
801 DBUS_TYPE_INT32, &i_protocol,
802 DBUS_TYPE_STRING, &host_name,
803 DBUS_TYPE_INT32, &i_aprotocol,
804 DBUS_TYPE_STRING, &pt,
807 dbus_connection_send(server->bus, reply, NULL);
808 dbus_message_unref(reply);
810 assert(event == AVAHI_RESOLVER_TIMEOUT);
812 respond_error(server->bus, i->message, AVAHI_ERR_TIMEOUT, NULL);
815 host_name_resolver_free(i);
818 static void address_resolver_callback(AvahiSAddressResolver *r, AvahiIfIndex interface, AvahiProtocol protocol, AvahiResolverEvent event, const AvahiAddress *address, const char *host_name, void* userdata) {
819 AddressResolverInfo *i = userdata;
825 if (event == AVAHI_RESOLVER_FOUND) {
826 char t[256], *pt = t;
827 int32_t i_interface, i_protocol, i_aprotocol;
831 avahi_address_snprint(t, sizeof(t), address);
833 i_interface = (int32_t) interface;
834 i_protocol = (int32_t) protocol;
835 i_aprotocol = (int32_t) address->family;
837 reply = dbus_message_new_method_return(i->message);
838 dbus_message_append_args(
840 DBUS_TYPE_INT32, &i_interface,
841 DBUS_TYPE_INT32, &i_protocol,
842 DBUS_TYPE_INT32, &i_aprotocol,
843 DBUS_TYPE_STRING, &pt,
844 DBUS_TYPE_STRING, &host_name,
847 dbus_connection_send(server->bus, reply, NULL);
848 dbus_message_unref(reply);
850 assert(event == AVAHI_RESOLVER_TIMEOUT);
851 respond_error(server->bus, i->message, AVAHI_ERR_TIMEOUT, NULL);
854 address_resolver_free(i);
857 static DBusHandlerResult msg_domain_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
859 DomainBrowserInfo *i = userdata;
865 dbus_error_init(&error);
867 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
868 dbus_message_get_interface(m),
869 dbus_message_get_path(m),
870 dbus_message_get_member(m));
873 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
874 return handle_introspect(c, m, "DomainBrowser.introspect");
877 if (strcmp(dbus_message_get_sender(m), i->client->name))
878 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
880 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, "Free")) {
882 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
883 avahi_log_warn("Error parsing DomainBrowser::Free message");
887 domain_browser_free(i);
888 return respond_ok(c, m);
892 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
895 if (dbus_error_is_set(&error))
896 dbus_error_free(&error);
898 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
901 static void domain_browser_callback(AvahiSDomainBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *domain, void* userdata) {
902 DomainBrowserInfo *i = userdata;
904 int32_t i_interface, i_protocol;
910 i_interface = (int32_t) interface;
911 i_protocol = (int32_t) protocol;
913 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_DOMAIN_BROWSER, event == AVAHI_BROWSER_NEW ? "ItemNew" : "ItemRemove");
914 dbus_message_append_args(
916 DBUS_TYPE_INT32, &i_interface,
917 DBUS_TYPE_INT32, &i_protocol,
918 DBUS_TYPE_STRING, &domain,
920 dbus_message_set_destination(m, i->client->name);
921 dbus_connection_send(server->bus, m, NULL);
922 dbus_message_unref(m);
925 static DBusHandlerResult msg_service_type_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
927 ServiceTypeBrowserInfo *i = userdata;
933 dbus_error_init(&error);
935 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
936 dbus_message_get_interface(m),
937 dbus_message_get_path(m),
938 dbus_message_get_member(m));
941 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
942 return handle_introspect(c, m, "ServiceTypeBrowser.introspect");
945 if (strcmp(dbus_message_get_sender(m), i->client->name))
946 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
948 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, "Free")) {
950 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
951 avahi_log_warn("Error parsing ServiceTypeBrowser::Free message");
955 service_type_browser_free(i);
956 return respond_ok(c, m);
960 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
963 if (dbus_error_is_set(&error))
964 dbus_error_free(&error);
966 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
969 static void service_type_browser_callback(AvahiSServiceTypeBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *type, const char *domain, void* userdata) {
970 ServiceTypeBrowserInfo *i = userdata;
972 int32_t i_interface, i_protocol;
979 i_interface = (int32_t) interface;
980 i_protocol = (int32_t) protocol;
982 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_TYPE_BROWSER, event == AVAHI_BROWSER_NEW ? "ItemNew" : "ItemRemove");
983 dbus_message_append_args(
985 DBUS_TYPE_INT32, &i_interface,
986 DBUS_TYPE_INT32, &i_protocol,
987 DBUS_TYPE_STRING, &type,
988 DBUS_TYPE_STRING, &domain,
990 dbus_message_set_destination(m, i->client->name);
991 dbus_connection_send(server->bus, m, NULL);
992 dbus_message_unref(m);
995 static DBusHandlerResult msg_service_browser_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
997 ServiceBrowserInfo *i = userdata;
1003 dbus_error_init(&error);
1005 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
1006 dbus_message_get_interface(m),
1007 dbus_message_get_path(m),
1008 dbus_message_get_member(m));
1011 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1012 return handle_introspect(c, m, "ServiceBrowser.Introspect");
1014 /* Access control */
1015 if (strcmp(dbus_message_get_sender(m), i->client->name))
1016 return respond_error(c, m, AVAHI_ERR_ACCESS_DENIED, NULL);
1018 if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, "Free")) {
1020 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1021 avahi_log_warn("Error parsing ServiceBrowser::Free message");
1025 service_browser_free(i);
1026 return respond_ok(c, m);
1030 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1033 if (dbus_error_is_set(&error))
1034 dbus_error_free(&error);
1036 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1039 static void service_browser_callback(AvahiSServiceBrowser *b, AvahiIfIndex interface, AvahiProtocol protocol, AvahiBrowserEvent event, const char *name, const char *type, const char *domain, void* userdata) {
1040 ServiceBrowserInfo *i = userdata;
1042 int32_t i_interface, i_protocol;
1050 i_interface = (int32_t) interface;
1051 i_protocol = (int32_t) protocol;
1053 m = dbus_message_new_signal(i->path, AVAHI_DBUS_INTERFACE_SERVICE_BROWSER, event == AVAHI_BROWSER_NEW ? "ItemNew" : "ItemRemove");
1054 dbus_message_append_args(
1056 DBUS_TYPE_INT32, &i_interface,
1057 DBUS_TYPE_INT32, &i_protocol,
1058 DBUS_TYPE_STRING, &name,
1059 DBUS_TYPE_STRING, &type,
1060 DBUS_TYPE_STRING, &domain,
1062 dbus_message_set_destination(m, i->client->name);
1063 dbus_connection_send(server->bus, m, NULL);
1064 dbus_message_unref(m);
1067 static void service_resolver_callback(
1068 AvahiSServiceResolver *r,
1069 AvahiIfIndex interface,
1070 AvahiProtocol protocol,
1071 AvahiResolverEvent event,
1075 const char *host_name,
1076 const AvahiAddress *a,
1078 AvahiStringList *txt,
1081 ServiceResolverInfo *i = userdata;
1086 if (event == AVAHI_RESOLVER_FOUND) {
1087 char t[256], *pt = t;
1088 int32_t i_interface, i_protocol, i_aprotocol;
1092 DBusMessageIter iter, sub;
1097 avahi_address_snprint(t, sizeof(t), a);
1099 i_interface = (int32_t) interface;
1100 i_protocol = (int32_t) protocol;
1101 i_aprotocol = (int32_t) a->family;
1103 reply = dbus_message_new_method_return(i->message);
1104 dbus_message_append_args(
1106 DBUS_TYPE_INT32, &i_interface,
1107 DBUS_TYPE_INT32, &i_protocol,
1108 DBUS_TYPE_STRING, &name,
1109 DBUS_TYPE_STRING, &type,
1110 DBUS_TYPE_STRING, &domain,
1111 DBUS_TYPE_STRING, &host_name,
1112 DBUS_TYPE_INT32, &i_aprotocol,
1113 DBUS_TYPE_STRING, &pt,
1114 DBUS_TYPE_UINT16, &port,
1117 dbus_message_iter_init_append(reply, &iter);
1118 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
1120 for (p = txt, j = n-1; p; p = p->next, j--) {
1121 DBusMessageIter sub2;
1122 const uint8_t *data = p->text;
1124 dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
1125 dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
1126 dbus_message_iter_close_container(&sub, &sub2);
1129 dbus_message_iter_close_container(&iter, &sub);
1131 dbus_connection_send(server->bus, reply, NULL);
1132 dbus_message_unref(reply);
1134 assert(event == AVAHI_RESOLVER_TIMEOUT);
1136 respond_error(server->bus, i->message, AVAHI_ERR_TIMEOUT, NULL);
1139 service_resolver_free(i);
1142 static DBusHandlerResult msg_server_impl(DBusConnection *c, DBusMessage *m, void *userdata) {
1145 dbus_error_init(&error);
1147 avahi_log_debug("dbus: interface=%s, path=%s, member=%s",
1148 dbus_message_get_interface(m),
1149 dbus_message_get_path(m),
1150 dbus_message_get_member(m));
1152 if (dbus_message_is_method_call(m, DBUS_INTERFACE_INTROSPECTABLE, "Introspect"))
1153 return handle_introspect(c, m, "Server.introspect");
1155 else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostName")) {
1157 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1158 avahi_log_warn("Error parsing Server::GetHostName message");
1162 return respond_string(c, m, avahi_server_get_host_name(avahi_server));
1164 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetDomainName")) {
1166 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1167 avahi_log_warn("Error parsing Server::GetDomainName message");
1171 return respond_string(c, m, avahi_server_get_domain_name(avahi_server));
1173 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetHostNameFqdn")) {
1175 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1176 avahi_log_warn("Error parsing Server::GetHostNameFqdn message");
1180 return respond_string(c, m, avahi_server_get_host_name_fqdn(avahi_server));
1182 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetVersionString")) {
1184 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1185 avahi_log_warn("Error parsing Server::GetVersionString message");
1189 return respond_string(c, m, PACKAGE_STRING);
1191 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetState")) {
1192 AvahiServerState state;
1194 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INVALID))) {
1195 avahi_log_warn("Error parsing Server::GetState message");
1199 state = avahi_server_get_state(avahi_server);
1200 return respond_int32(c, m, (int32_t) state);
1202 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceNameByIndex")) {
1207 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_INT32, &idx, DBUS_TYPE_INVALID))) {
1208 avahi_log_warn("Error parsing Server::GetNetworkInterfaceNameByIndex message");
1212 #ifdef VALGRIND_WORKAROUND
1213 return respond_string(c, m, "blah");
1216 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1218 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1219 return respond_error(c, m, AVAHI_ERR_OS, txt);
1222 memset(&ifr, 0, sizeof(ifr));
1223 ifr.ifr_ifindex = idx;
1225 if (ioctl(fd, SIOCGIFNAME, &ifr) < 0) {
1227 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1229 return respond_error(c, m, AVAHI_ERR_OS, txt);
1234 return respond_string(c, m, ifr.ifr_name);
1237 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetNetworkInterfaceIndexByName")) {
1242 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1243 avahi_log_warn("Error parsing Server::GetNetworkInterfaceIndexByName message");
1247 #ifdef VALGRIND_WORKAROUND
1248 return respond_int32(c, m, 1);
1250 if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
1252 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1253 return respond_error(c, m, AVAHI_ERR_OS, txt);
1256 memset(&ifr, 0, sizeof(ifr));
1257 snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "%s", n);
1259 if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0) {
1261 snprintf(txt, sizeof(txt), "OS Error: %s", strerror(errno));
1263 return respond_error(c, m, AVAHI_ERR_OS, txt);
1268 return respond_int32(c, m, ifr.ifr_ifindex);
1271 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeHostName")) {
1274 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1275 avahi_log_warn("Error parsing Server::GetAlternativeHostName message");
1279 t = avahi_alternative_host_name(n);
1280 respond_string(c, m, t);
1283 return DBUS_HANDLER_RESULT_HANDLED;
1285 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "GetAlternativeServiceName")) {
1288 if (!(dbus_message_get_args(m, &error, DBUS_TYPE_STRING, &n, DBUS_TYPE_INVALID)) || !n) {
1289 avahi_log_warn("Error parsing Server::GetAlternativeServiceName message");
1293 t = avahi_alternative_service_name(n);
1294 respond_string(c, m, t);
1297 return DBUS_HANDLER_RESULT_HANDLED;
1299 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "EntryGroupNew")) {
1302 static const DBusObjectPathVTable vtable = {
1304 msg_entry_group_impl,
1311 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
1312 avahi_log_warn("Error parsing Server::EntryGroupNew message");
1316 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1317 avahi_log_warn("Too many clients, client request failed.");
1318 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1321 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1322 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1323 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1326 i = avahi_new(EntryGroupInfo, 1);
1327 i->id = ++client->current_id;
1329 i->path = avahi_strdup_printf("/Client%u/EntryGroup%u", client->id, i->id);
1331 AVAHI_LLIST_PREPEND(EntryGroupInfo, entry_groups, client->entry_groups, i);
1332 client->n_objects++;
1334 if (!(i->entry_group = avahi_s_entry_group_new(avahi_server, entry_group_callback, i))) {
1335 entry_group_free(i);
1336 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1339 dbus_connection_register_object_path(c, i->path, &vtable, i);
1340 return respond_path(c, m, i->path);
1342 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveHostName")) {
1344 int32_t interface, protocol, aprotocol;
1346 HostNameResolverInfo *i;
1348 if (!dbus_message_get_args(
1350 DBUS_TYPE_INT32, &interface,
1351 DBUS_TYPE_INT32, &protocol,
1352 DBUS_TYPE_STRING, &name,
1353 DBUS_TYPE_INT32, &aprotocol,
1354 DBUS_TYPE_INVALID) || !name) {
1355 avahi_log_warn("Error parsing Server::ResolveHostName message");
1359 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1360 avahi_log_warn("Too many clients, client request failed.");
1361 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1364 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1365 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1366 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1369 i = avahi_new(HostNameResolverInfo, 1);
1371 i->message = dbus_message_ref(m);
1372 AVAHI_LLIST_PREPEND(HostNameResolverInfo, host_name_resolvers, client->host_name_resolvers, i);
1373 client->n_objects++;
1375 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))) {
1376 host_name_resolver_free(i);
1377 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1380 return DBUS_HANDLER_RESULT_HANDLED;
1382 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveAddress")) {
1384 int32_t interface, protocol;
1386 AddressResolverInfo *i;
1389 if (!dbus_message_get_args(
1391 DBUS_TYPE_INT32, &interface,
1392 DBUS_TYPE_INT32, &protocol,
1393 DBUS_TYPE_STRING, &address,
1394 DBUS_TYPE_INVALID) || !address) {
1395 avahi_log_warn("Error parsing Server::ResolveAddress message");
1399 if (!avahi_address_parse(address, AVAHI_PROTO_UNSPEC, &a))
1400 return respond_error(c, m, AVAHI_ERR_INVALID_ADDRESS, NULL);
1402 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1403 avahi_log_warn("Too many clients, client request failed.");
1404 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1407 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1408 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1409 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1412 i = avahi_new(AddressResolverInfo, 1);
1414 i->message = dbus_message_ref(m);
1415 AVAHI_LLIST_PREPEND(AddressResolverInfo, address_resolvers, client->address_resolvers, i);
1416 client->n_objects++;
1418 if (!(i->address_resolver = avahi_s_address_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, &a, address_resolver_callback, i))) {
1419 address_resolver_free(i);
1420 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1423 return DBUS_HANDLER_RESULT_HANDLED;
1425 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "DomainBrowserNew")) {
1427 DomainBrowserInfo *i;
1428 static const DBusObjectPathVTable vtable = {
1430 msg_domain_browser_impl,
1436 int32_t interface, protocol, type;
1440 if (!dbus_message_get_args(
1442 DBUS_TYPE_INT32, &interface,
1443 DBUS_TYPE_INT32, &protocol,
1444 DBUS_TYPE_STRING, &domain,
1445 DBUS_TYPE_INT32, &type,
1446 DBUS_TYPE_INVALID) || type < 0 || type >= AVAHI_DOMAIN_BROWSER_MAX) {
1447 avahi_log_warn("Error parsing Server::DomainBrowserNew message");
1451 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1452 avahi_log_warn("Too many clients, client request failed.");
1453 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1456 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1457 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1458 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1464 i = avahi_new(DomainBrowserInfo, 1);
1465 i->id = ++client->current_id;
1467 i->path = avahi_strdup_printf("/Client%u/DomainBrowser%u", client->id, i->id);
1468 AVAHI_LLIST_PREPEND(DomainBrowserInfo, domain_browsers, client->domain_browsers, i);
1469 client->n_objects++;
1471 if (!(i->domain_browser = avahi_s_domain_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, (AvahiDomainBrowserType) type, domain_browser_callback, i))) {
1472 domain_browser_free(i);
1473 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1476 dbus_connection_register_object_path(c, i->path, &vtable, i);
1477 return respond_path(c, m, i->path);
1479 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceTypeBrowserNew")) {
1481 ServiceTypeBrowserInfo *i;
1482 static const DBusObjectPathVTable vtable = {
1484 msg_service_type_browser_impl,
1490 int32_t interface, protocol;
1493 if (!dbus_message_get_args(
1495 DBUS_TYPE_INT32, &interface,
1496 DBUS_TYPE_INT32, &protocol,
1497 DBUS_TYPE_STRING, &domain,
1498 DBUS_TYPE_INVALID)) {
1499 avahi_log_warn("Error parsing Server::ServiceTypeBrowserNew message");
1503 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1504 avahi_log_warn("Too many clients, client request failed.");
1505 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1509 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1510 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1511 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1517 i = avahi_new(ServiceTypeBrowserInfo, 1);
1518 i->id = ++client->current_id;
1520 i->path = avahi_strdup_printf("/Client%u/ServiceTypeBrowser%u", client->id, i->id);
1521 AVAHI_LLIST_PREPEND(ServiceTypeBrowserInfo, service_type_browsers, client->service_type_browsers, i);
1522 client->n_objects++;
1524 if (!(i->service_type_browser = avahi_s_service_type_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, domain, service_type_browser_callback, i))) {
1525 service_type_browser_free(i);
1526 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1529 dbus_connection_register_object_path(c, i->path, &vtable, i);
1530 return respond_path(c, m, i->path);
1532 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ServiceBrowserNew")) {
1534 ServiceBrowserInfo *i;
1535 static const DBusObjectPathVTable vtable = {
1537 msg_service_browser_impl,
1543 int32_t interface, protocol;
1544 char *domain, *type;
1546 if (!dbus_message_get_args(
1548 DBUS_TYPE_INT32, &interface,
1549 DBUS_TYPE_INT32, &protocol,
1550 DBUS_TYPE_STRING, &type,
1551 DBUS_TYPE_STRING, &domain,
1552 DBUS_TYPE_INVALID) || !type) {
1553 avahi_log_warn("Error parsing Server::ServiceBrowserNew message");
1557 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1558 avahi_log_warn("Too many clients, client request failed.");
1559 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1563 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1564 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1565 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1571 i = avahi_new(ServiceBrowserInfo, 1);
1572 i->id = ++client->current_id;
1574 i->path = avahi_strdup_printf("/Client%u/ServiceBrowser%u", client->id, i->id);
1575 AVAHI_LLIST_PREPEND(ServiceBrowserInfo, service_browsers, client->service_browsers, i);
1576 client->n_objects++;
1578 if (!(i->service_browser = avahi_s_service_browser_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, type, domain, service_browser_callback, i))) {
1579 service_browser_free(i);
1580 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1583 dbus_connection_register_object_path(c, i->path, &vtable, i);
1584 return respond_path(c, m, i->path);
1586 } else if (dbus_message_is_method_call(m, AVAHI_DBUS_INTERFACE_SERVER, "ResolveService")) {
1588 int32_t interface, protocol, aprotocol;
1589 char *name, *type, *domain;
1590 ServiceResolverInfo *i;
1592 if (!dbus_message_get_args(
1594 DBUS_TYPE_INT32, &interface,
1595 DBUS_TYPE_INT32, &protocol,
1596 DBUS_TYPE_STRING, &name,
1597 DBUS_TYPE_STRING, &type,
1598 DBUS_TYPE_STRING, &domain,
1599 DBUS_TYPE_INT32, &aprotocol,
1600 DBUS_TYPE_INVALID) || !name || !type) {
1601 avahi_log_warn("Error parsing Server::ResolveService message");
1605 if (!(client = client_get(dbus_message_get_sender(m), TRUE))) {
1606 avahi_log_warn("Too many clients, client request failed.");
1607 return respond_error(c, m, AVAHI_ERR_TOO_MANY_CLIENTS, NULL);
1610 if (client->n_objects >= MAX_OBJECTS_PER_CLIENT) {
1611 avahi_log_warn("Too many objects for client '%s', client request failed.", client->name);
1612 return respond_error(c, m, AVAHI_ERR_TOO_MANY_OBJECTS, NULL);
1618 i = avahi_new(ServiceResolverInfo, 1);
1620 i->message = dbus_message_ref(m);
1621 AVAHI_LLIST_PREPEND(ServiceResolverInfo, service_resolvers, client->service_resolvers, i);
1622 client->n_objects++;
1624 if (!(i->service_resolver = avahi_s_service_resolver_new(avahi_server, (AvahiIfIndex) interface, (AvahiProtocol) protocol, name, type, domain, (AvahiProtocol) aprotocol, service_resolver_callback, i))) {
1625 service_resolver_free(i);
1626 return respond_error(c, m, avahi_server_errno(avahi_server), NULL);
1629 return DBUS_HANDLER_RESULT_HANDLED;
1632 avahi_log_warn("Missed message %s::%s()", dbus_message_get_interface(m), dbus_message_get_member(m));
1635 if (dbus_error_is_set(&error))
1636 dbus_error_free(&error);
1638 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
1641 void dbus_protocol_server_state_changed(AvahiServerState state) {
1648 m = dbus_message_new_signal(AVAHI_DBUS_PATH_SERVER, AVAHI_DBUS_INTERFACE_SERVER, "StateChanged");
1649 t = (int32_t) state;
1650 dbus_message_append_args(m, DBUS_TYPE_INT32, &t, DBUS_TYPE_INVALID);
1651 dbus_connection_send(server->bus, m, NULL);
1652 dbus_message_unref(m);
1655 int dbus_protocol_setup(const AvahiPoll *poll_api) {
1658 static const DBusObjectPathVTable server_vtable = {
1668 dbus_error_init(&error);
1670 server = avahi_new(Server, 1);
1671 AVAHI_LLIST_HEAD_INIT(Clients, server->clients);
1672 server->current_id = 0;
1673 server->n_clients = 0;
1675 server->bus = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
1676 if (dbus_error_is_set(&error)) {
1677 avahi_log_warn("dbus_bus_get(): %s", error.message);
1681 avahi_dbus_connection_glue(server->bus, poll_api);
1683 dbus_bus_request_name(server->bus, AVAHI_DBUS_NAME, 0, &error);
1684 if (dbus_error_is_set(&error)) {
1685 avahi_log_warn("dbus_bus_request_name(): %s", error.message);
1689 dbus_bus_add_match(server->bus, "type='signal',""interface='" DBUS_INTERFACE_DBUS "'", &error);
1691 dbus_connection_add_filter(server->bus, msg_signal_filter_impl, (void*) poll_api, NULL);
1692 dbus_connection_register_object_path(server->bus, AVAHI_DBUS_PATH_SERVER, &server_vtable, NULL);
1698 dbus_connection_disconnect(server->bus);
1699 dbus_connection_unref(server->bus);
1702 dbus_error_free (&error);
1708 void dbus_protocol_shutdown(void) {
1712 while (server->clients)
1713 client_free(server->clients);
1715 assert(server->n_clients == 0);
1718 dbus_connection_disconnect(server->bus);
1719 dbus_connection_unref(server->bus);