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
34 #include <avahi-common/error.h>
35 #include <avahi-common/dbus.h>
36 #include <avahi-common/malloc.h>
37 #include <avahi-core/log.h>
38 #include <avahi-core/core.h>
41 #include "dbus-util.h"
43 DBusHandlerResult avahi_dbus_respond_error(DBusConnection *c, DBusMessage *m, int error, const char *text) {
46 assert(-error > -AVAHI_OK);
47 assert(-error < -AVAHI_ERR_MAX);
50 text = avahi_strerror(error);
52 reply = dbus_message_new_error(m, avahi_error_number_to_dbus(error), text);
53 dbus_connection_send(c, reply, NULL);
54 dbus_message_unref(reply);
56 avahi_log_debug(__FILE__": Responding error '%s' (%i)", text, error);
58 return DBUS_HANDLER_RESULT_HANDLED;
61 DBusHandlerResult avahi_dbus_respond_string(DBusConnection *c, DBusMessage *m, const char *text) {
64 reply = dbus_message_new_method_return(m);
65 dbus_message_append_args(reply, DBUS_TYPE_STRING, &text, DBUS_TYPE_INVALID);
66 dbus_connection_send(c, reply, NULL);
67 dbus_message_unref(reply);
69 return DBUS_HANDLER_RESULT_HANDLED;
72 DBusHandlerResult avahi_dbus_respond_int32(DBusConnection *c, DBusMessage *m, int32_t i) {
75 reply = dbus_message_new_method_return(m);
76 dbus_message_append_args(reply, DBUS_TYPE_INT32, &i, DBUS_TYPE_INVALID);
77 dbus_connection_send(c, reply, NULL);
78 dbus_message_unref(reply);
80 return DBUS_HANDLER_RESULT_HANDLED;
83 DBusHandlerResult avahi_dbus_respond_uint32(DBusConnection *c, DBusMessage *m, uint32_t u) {
86 reply = dbus_message_new_method_return(m);
87 dbus_message_append_args(reply, DBUS_TYPE_UINT32, &u, DBUS_TYPE_INVALID);
88 dbus_connection_send(c, reply, NULL);
89 dbus_message_unref(reply);
91 return DBUS_HANDLER_RESULT_HANDLED;
94 DBusHandlerResult avahi_dbus_respond_boolean(DBusConnection *c, DBusMessage *m, int b) {
97 reply = dbus_message_new_method_return(m);
98 dbus_message_append_args(reply, DBUS_TYPE_BOOLEAN, &b, DBUS_TYPE_INVALID);
99 dbus_connection_send(c, reply, NULL);
100 dbus_message_unref(reply);
102 return DBUS_HANDLER_RESULT_HANDLED;
105 DBusHandlerResult avahi_dbus_respond_ok(DBusConnection *c, DBusMessage *m) {
108 reply = dbus_message_new_method_return(m);
109 dbus_connection_send(c, reply, NULL);
110 dbus_message_unref(reply);
112 return DBUS_HANDLER_RESULT_HANDLED;
115 DBusHandlerResult avahi_dbus_respond_path(DBusConnection *c, DBusMessage *m, const char *path) {
118 reply = dbus_message_new_method_return(m);
119 dbus_message_append_args(reply, DBUS_TYPE_OBJECT_PATH, &path, DBUS_TYPE_INVALID);
120 dbus_connection_send(c, reply, NULL);
121 dbus_message_unref(reply);
123 return DBUS_HANDLER_RESULT_HANDLED;
126 void avahi_dbus_append_server_error(DBusMessage *reply) {
129 t = avahi_error_number_to_dbus(avahi_server_errno(avahi_server));
131 dbus_message_append_args(
133 DBUS_TYPE_STRING, &t,
137 const char *avahi_dbus_map_browse_signal_name(AvahiBrowserEvent e) {
139 case AVAHI_BROWSER_NEW : return "ItemNew";
140 case AVAHI_BROWSER_REMOVE : return "ItemRemove";
141 case AVAHI_BROWSER_FAILURE : return "Failure";
142 case AVAHI_BROWSER_CACHE_EXHAUSTED : return "CacheExhausted";
143 case AVAHI_BROWSER_ALL_FOR_NOW : return "AllForNow";
149 const char *avahi_dbus_map_resolve_signal_name(AvahiResolverEvent e) {
151 case AVAHI_RESOLVER_FOUND : return "Found";
152 case AVAHI_RESOLVER_FAILURE : return "Failure";
158 static char *file_get_contents(char *fname) {
166 if (!(fd = open(fname, O_RDONLY))) {
167 avahi_log_error("Failed to open %s: %s", fname, strerror(errno));
171 if (fstat(fd, &st) < 0) {
172 avahi_log_error("stat(%s) failed: %s", fname, strerror(errno));
176 if (!(S_ISREG(st.st_mode))) {
177 avahi_log_error("Invalid file %s", fname);
181 if (st.st_size > 1024*1024) { /** 1MB */
182 avahi_log_error("File too large %s", fname);
186 buf = avahi_new(char, st.st_size+1);
188 if ((size = read(fd, buf, st.st_size)) < 0) {
189 avahi_log_error("read() failed: %s\n", strerror(errno));
209 DBusHandlerResult avahi_dbus_handle_introspect(DBusConnection *c, DBusMessage *m, const char *fname) {
210 char *path, *contents;
217 dbus_error_init(&error);
219 if (!dbus_message_get_args(m, &error, DBUS_TYPE_INVALID)) {
220 avahi_log_error("Error parsing Introspect message: %s", error.message);
224 path = avahi_strdup_printf("%s/%s", AVAHI_DBUS_INTROSPECTION_DIR, fname);
225 contents = file_get_contents(path);
229 avahi_log_error("Failed to load introspection data.");
233 avahi_dbus_respond_string(c, m, contents);
234 avahi_free(contents);
236 return DBUS_HANDLER_RESULT_HANDLED;
239 if (dbus_error_is_set(&error))
240 dbus_error_free(&error);
242 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
246 void avahi_dbus_append_string_list(DBusMessage *reply, AvahiStringList *txt) {
248 DBusMessageIter iter, sub;
252 dbus_message_iter_init_append(reply, &iter);
253 dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "ay", &sub);
255 for (p = txt; p; p = p->next) {
256 DBusMessageIter sub2;
257 const uint8_t *data = p->text;
259 dbus_message_iter_open_container(&sub, DBUS_TYPE_ARRAY, "y", &sub2);
260 dbus_message_iter_append_fixed_array(&sub2, DBUS_TYPE_BYTE, &data, p->size);
261 dbus_message_iter_close_container(&sub, &sub2);
264 dbus_message_iter_close_container(&iter, &sub);
267 int avahi_dbus_read_rdata(DBusMessage *m, int idx, void **rdata, uint32_t *size) {
268 DBusMessageIter iter, sub;
274 dbus_message_iter_init(m, &iter);
276 for (j = 0; j < idx; j++)
277 dbus_message_iter_next(&iter);
279 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
280 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE)
283 dbus_message_iter_recurse(&iter, &sub);
284 dbus_message_iter_get_fixed_array(&sub, &k, &n);
292 avahi_log_warn("Error parsing data");
299 int avahi_dbus_read_strlst(DBusMessage *m, int idx, AvahiStringList **l) {
300 DBusMessageIter iter, sub;
302 AvahiStringList *strlst = NULL;
307 dbus_message_iter_init(m, &iter);
309 for (j = 0; j < idx; j++)
310 dbus_message_iter_next(&iter);
312 if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY ||
313 dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_ARRAY)
316 dbus_message_iter_recurse(&iter, &sub);
319 DBusMessageIter sub2;
323 if ((at = dbus_message_iter_get_arg_type(&sub)) == DBUS_TYPE_INVALID)
326 assert(at == DBUS_TYPE_ARRAY);
328 if (dbus_message_iter_get_element_type(&sub) != DBUS_TYPE_BYTE)
331 dbus_message_iter_recurse(&sub, &sub2);
332 dbus_message_iter_get_fixed_array(&sub2, &k, &n);
333 strlst = avahi_string_list_add_arbitrary(strlst, k, n);
335 dbus_message_iter_next(&sub);
343 avahi_log_warn("Error parsing TXT data");
345 avahi_string_list_free(strlst);
350 int avahi_dbus_is_our_own_service(Client *c, AvahiIfIndex interface, AvahiProtocol protocol, const char *name, const char *type, const char *domain) {
353 if (avahi_server_get_group_of_service(avahi_server, interface, protocol, name, type, domain, &g) == AVAHI_OK) {
356 for (egi = c->entry_groups; egi; egi = egi->entry_groups_next)
357 if (egi->entry_group == g)