1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
3 * LADI Session Handler (ladish)
5 * Copyright (C) 2008, 2009 Nedko Arnaudov <nedko@arnaudov.name>
6 * Copyright (C) 2008 Juuso Alasuutari <juuso.alasuutari@gmail.com>
8 **************************************************************************
9 * This file contains D-Bus methods helpers
10 **************************************************************************
12 * Licensed under the Academic Free License version 2.1
14 * LADI Session Handler is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 2 of the License, or
17 * (at your option) any later version.
19 * LADI Session Handler is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
24 * You should have received a copy of the GNU General Public License
25 * along with LADI Session Handler. If not, see <http://www.gnu.org/licenses/>
26 * or write to the Free Software Foundation, Inc.,
27 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
30 #include "../common.h"
31 #include "../common/safety.h"
36 * Construct a void method return.
38 * The operation can only fail due to lack of memory, in which case
39 * there's no sense in trying to construct an error return. Instead,
40 * call->reply will be set to NULL and handled in send_method_return().
43 method_return_new_void(method_call_t
*call
)
45 if (!(call
->reply
= dbus_message_new_method_return(call
->message
))) {
46 lash_error("Ran out of memory trying to construct method return");
51 * Construct a method return which holds a single argument or, if
52 * the type parameter is DBUS_TYPE_INVALID, no arguments at all
55 * The operation can only fail due to lack of memory, in which case
56 * there's no sense in trying to construct an error return. Instead,
57 * call->reply will be set to NULL and handled in send_method_return().
60 method_return_new_single(method_call_t
*call
,
65 lash_error("Invalid arguments");
69 call
->reply
= dbus_message_new_method_return(call
->message
);
74 /* Void method return requested by caller. */
75 // TODO: do we really need this?
76 if (type
== DBUS_TYPE_INVALID
)
79 /* Prevent crash on NULL input string. */
80 if (type
== DBUS_TYPE_STRING
&& !(*((const char **) arg
)))
81 *((const char **) arg
) = "";
85 dbus_message_iter_init_append(call
->reply
, &iter
);
87 if (dbus_message_iter_append_basic(&iter
, type
, arg
))
90 dbus_message_unref(call
->reply
);
94 lash_error("Ran out of memory trying to construct method return");
98 method_return_new_valist(method_call_t
*call
,
103 lash_error("Call pointer is NULL");
107 if (type
== DBUS_TYPE_INVALID
) {
108 lash_error("No argument(s) supplied");
114 call
->reply
= dbus_message_new_method_return(call
->message
);
118 va_start(argp
, type
);
120 if (dbus_message_append_args_valist(call
->reply
, type
, argp
)) {
127 dbus_message_unref(call
->reply
);
131 lash_error("Ran out of memory trying to construct method return");
135 * Send a method return.
137 * If call->reply is NULL, i.e. a previous attempt to construct
138 * a return has failed, attempt to send a void return.
141 method_return_send(method_call_t
*call
)
145 if (!dbus_connection_send(call
->connection
, call
->reply
, NULL
))
146 lash_error("Ran out of memory trying to queue "
149 dbus_connection_flush(call
->connection
);
151 dbus_message_unref(call
->reply
);
154 lash_debug("Message was NULL, trying to construct a void return");
156 if ((call
->reply
= dbus_message_new_method_return(call
->message
))) {
157 lash_debug("Constructed a void return, trying to queue it");
160 lash_error("Failed to construct method return!");
166 method_return_verify(DBusMessage
*msg
,
169 if (!msg
|| dbus_message_get_type(msg
) != DBUS_MESSAGE_TYPE_ERROR
)
174 if (!dbus_message_get_args(msg
, &g_dbus_error
,
175 DBUS_TYPE_STRING
, &ptr
,
176 DBUS_TYPE_INVALID
)) {
177 lash_error("Cannot read description from D-Bus error message: %s ",
178 g_dbus_error
.message
);
179 dbus_error_free(&g_dbus_error
);
190 * Append a variant type to a D-Bus message.
191 * Return false if something fails, true otherwise.
194 method_iter_append_variant(DBusMessageIter
*iter
,
198 DBusMessageIter sub_iter
;
204 /* Open a variant container. */
205 if (!dbus_message_iter_open_container(iter
, DBUS_TYPE_VARIANT
,
206 (const char *) s
, &sub_iter
))
209 /* Append the supplied value. */
210 if (!dbus_message_iter_append_basic(&sub_iter
, type
, arg
)) {
211 dbus_message_iter_close_container(iter
, &sub_iter
);
215 /* Close the container. */
216 if (!dbus_message_iter_close_container(iter
, &sub_iter
))
222 static __inline__
bool
223 method_iter_append_variant_raw(DBusMessageIter
*iter
,
227 DBusMessageIter variant_iter
, array_iter
;
229 /* Open a variant container. */
230 if (!dbus_message_iter_open_container(iter
, DBUS_TYPE_VARIANT
,
231 "ay", &variant_iter
))
234 /* Open an array container. */
235 if (!dbus_message_iter_open_container(&variant_iter
, DBUS_TYPE_ARRAY
,
239 /* Append the supplied data. */
240 if (!dbus_message_iter_append_fixed_array(&array_iter
, DBUS_TYPE_BYTE
, buf
, len
)) {
241 dbus_message_iter_close_container(&variant_iter
, &array_iter
);
245 /* Close the containers. */
246 if (!dbus_message_iter_close_container(&variant_iter
, &array_iter
))
248 else if (!dbus_message_iter_close_container(iter
, &variant_iter
))
254 dbus_message_iter_close_container(iter
, &variant_iter
);
259 method_iter_append_dict_entry(DBusMessageIter
*iter
,
265 DBusMessageIter dict_iter
;
267 if (!dbus_message_iter_open_container(iter
, DBUS_TYPE_DICT_ENTRY
,
271 if (!dbus_message_iter_append_basic(&dict_iter
, DBUS_TYPE_STRING
, &key
))
275 if (!method_iter_append_variant_raw(&dict_iter
, value
, length
))
277 } else if (!method_iter_append_variant(&dict_iter
, type
, value
))
280 if (!dbus_message_iter_close_container(iter
, &dict_iter
))
286 dbus_message_iter_close_container(iter
, &dict_iter
);
291 method_iter_get_dict_entry(DBusMessageIter
*iter
,
292 const char **key_ptr
,
297 if (!iter
|| !key_ptr
|| !value_ptr
|| !type_ptr
) {
298 lash_error("Invalid arguments");
302 DBusMessageIter dict_iter
, variant_iter
;
304 if (dbus_message_iter_get_arg_type(iter
) != DBUS_TYPE_DICT_ENTRY
) {
305 lash_error("Iterator does not point to a dict entry container");
309 dbus_message_iter_recurse(iter
, &dict_iter
);
311 if (dbus_message_iter_get_arg_type(&dict_iter
) != DBUS_TYPE_STRING
) {
312 lash_error("Cannot find key in dict entry container");
316 dbus_message_iter_get_basic(&dict_iter
, key_ptr
);
318 if (!dbus_message_iter_next(&dict_iter
)
319 || dbus_message_iter_get_arg_type(&dict_iter
) != DBUS_TYPE_VARIANT
) {
320 lash_error("Cannot find variant container in dict entry");
324 dbus_message_iter_recurse(&dict_iter
, &variant_iter
);
326 *type_ptr
= dbus_message_iter_get_arg_type(&variant_iter
);
327 if (*type_ptr
== DBUS_TYPE_INVALID
) {
328 lash_error("Cannot find value in variant container");
332 if (*type_ptr
== DBUS_TYPE_ARRAY
) {
333 DBusMessageIter array_iter
;
336 if (dbus_message_iter_get_element_type(&variant_iter
)
338 lash_error("Dict entry value is a non-byte array");
343 dbus_message_iter_recurse(&variant_iter
, &array_iter
);
344 dbus_message_iter_get_fixed_array(&array_iter
, value_ptr
, &n
);
349 dbus_message_iter_get_basic(&variant_iter
, value_ptr
);