1 /* GDBus - GLib D-Bus Library
2 *
3 * Copyright (C) 2008-2010 Red Hat, Inc.
4 *
5 * SPDX-License-Identifier: LGPL-2.1-or-later
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General
18 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 *
20 * Author: David Zeuthen <davidz@redhat.com>
21 */
22
23 #include "config.h"
24
25 #include <stdlib.h>
26
27 #include "gdbusutils.h"
28 #include "gdbusconnection.h"
29 #include "gdbusmessage.h"
30 #include "gdbusmethodinvocation.h"
31 #include "gdbusintrospection.h"
32 #include "gdbuserror.h"
33 #include "gdbusprivate.h"
34 #include "gioerror.h"
35
36 #ifdef G_OS_UNIX
37 #include "gunixfdlist.h"
38 #endif
39
40 #include "glibintl.h"
41
42 /**
43 * GDBusMethodInvocation:
44 *
45 * Instances of the `GDBusMethodInvocation` class are used when
46 * handling D-Bus method calls. It provides a way to asynchronously
47 * return results and errors.
48 *
49 * The normal way to obtain a `GDBusMethodInvocation` object is to receive
50 * it as an argument to the `handle_method_call()` function in a
51 * [type@Gio.DBusInterfaceVTable] that was passed to
52 * [method@Gio.DBusConnection.register_object].
53 *
54 * Since: 2.26
55 */
56
57 typedef struct _GDBusMethodInvocationClass GDBusMethodInvocationClass;
58
59 /**
60 * GDBusMethodInvocationClass:
61 *
62 * Class structure for #GDBusMethodInvocation.
63 *
64 * Since: 2.26
65 */
66 struct _GDBusMethodInvocationClass
67 {
68 /*< private >*/
69 GObjectClass parent_class;
70 };
71
72 struct _GDBusMethodInvocation
73 {
74 /*< private >*/
75 GObject parent_instance;
76
77 /* construct-only properties */
78 gchar *sender;
79 gchar *object_path;
80 gchar *interface_name;
81 gchar *method_name;
82 GDBusMethodInfo *method_info;
83 GDBusPropertyInfo *property_info;
84 GDBusConnection *connection;
85 GDBusMessage *message;
86 GVariant *parameters;
87 gpointer user_data;
88 };
89
90 G_DEFINE_TYPE (GDBusMethodInvocation, g_dbus_method_invocation, G_TYPE_OBJECT)
91
92 static void
93 g_dbus_method_invocation_finalize (GObject *object)
94 {
95 GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (object);
96
97 g_free (invocation->sender);
98 g_free (invocation->object_path);
99 g_free (invocation->interface_name);
100 g_free (invocation->method_name);
101 if (invocation->method_info)
102 g_dbus_method_info_unref (invocation->method_info);
103 if (invocation->property_info)
104 g_dbus_property_info_unref (invocation->property_info);
105 g_object_unref (invocation->connection);
106 g_object_unref (invocation->message);
107 g_variant_unref (invocation->parameters);
108
109 G_OBJECT_CLASS (g_dbus_method_invocation_parent_class)->finalize (object);
110 }
111
112 static void
113 g_dbus_method_invocation_class_init (GDBusMethodInvocationClass *klass)
114 {
115 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
116
117 gobject_class->finalize = g_dbus_method_invocation_finalize;
118 }
119
120 static void
121 g_dbus_method_invocation_init (GDBusMethodInvocation *invocation)
122 {
123 }
124
125 /**
126 * g_dbus_method_invocation_get_sender:
127 * @invocation: A #GDBusMethodInvocation.
128 *
129 * Gets the bus name that invoked the method.
130 *
131 * Returns: A string. Do not free, it is owned by @invocation.
132 *
133 * Since: 2.26
134 */
135 const gchar *
136 g_dbus_method_invocation_get_sender (GDBusMethodInvocation *invocation)
137 {
138 g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
139 return invocation->sender;
140 }
141
142 /**
143 * g_dbus_method_invocation_get_object_path:
144 * @invocation: A #GDBusMethodInvocation.
145 *
146 * Gets the object path the method was invoked on.
147 *
148 * Returns: A string. Do not free, it is owned by @invocation.
149 *
150 * Since: 2.26
151 */
152 const gchar *
153 g_dbus_method_invocation_get_object_path (GDBusMethodInvocation *invocation)
154 {
155 g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
156 return invocation->object_path;
157 }
158
159 /**
160 * g_dbus_method_invocation_get_interface_name:
161 * @invocation: A #GDBusMethodInvocation.
162 *
163 * Gets the name of the D-Bus interface the method was invoked on.
164 *
165 * If this method call is a property Get, Set or GetAll call that has
166 * been redirected to the method call handler then
167 * "org.freedesktop.DBus.Properties" will be returned. See
168 * #GDBusInterfaceVTable for more information.
169 *
170 * Returns: A string. Do not free, it is owned by @invocation.
171 *
172 * Since: 2.26
173 */
174 const gchar *
175 g_dbus_method_invocation_get_interface_name (GDBusMethodInvocation *invocation)
176 {
177 g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
178 return invocation->interface_name;
179 }
180
181 /**
182 * g_dbus_method_invocation_get_method_info:
183 * @invocation: A #GDBusMethodInvocation.
184 *
185 * Gets information about the method call, if any.
186 *
187 * If this method invocation is a property Get, Set or GetAll call that
188 * has been redirected to the method call handler then %NULL will be
189 * returned. See g_dbus_method_invocation_get_property_info() and
190 * #GDBusInterfaceVTable for more information.
191 *
192 * Returns: (nullable): A #GDBusMethodInfo or %NULL. Do not free, it is owned by @invocation.
193 *
194 * Since: 2.26
195 */
196 const GDBusMethodInfo *
197 g_dbus_method_invocation_get_method_info (GDBusMethodInvocation *invocation)
198 {
199 g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
200 return invocation->method_info;
201 }
202
203 /**
204 * g_dbus_method_invocation_get_property_info:
205 * @invocation: A #GDBusMethodInvocation
206 *
207 * Gets information about the property that this method call is for, if
208 * any.
209 *
210 * This will only be set in the case of an invocation in response to a
211 * property Get or Set call that has been directed to the method call
212 * handler for an object on account of its property_get() or
213 * property_set() vtable pointers being unset.
214 *
215 * See #GDBusInterfaceVTable for more information.
216 *
217 * If the call was GetAll, %NULL will be returned.
218 *
219 * Returns: (nullable) (transfer none): a #GDBusPropertyInfo or %NULL
220 *
221 * Since: 2.38
222 */
223 const GDBusPropertyInfo *
224 g_dbus_method_invocation_get_property_info (GDBusMethodInvocation *invocation)
225 {
226 g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
227 return invocation->property_info;
228 }
229
230 /**
231 * g_dbus_method_invocation_get_method_name:
232 * @invocation: A #GDBusMethodInvocation.
233 *
234 * Gets the name of the method that was invoked.
235 *
236 * Returns: A string. Do not free, it is owned by @invocation.
237 *
238 * Since: 2.26
239 */
240 const gchar *
241 g_dbus_method_invocation_get_method_name (GDBusMethodInvocation *invocation)
242 {
243 g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
244 return invocation->method_name;
245 }
246
247 /**
248 * g_dbus_method_invocation_get_connection:
249 * @invocation: A #GDBusMethodInvocation.
250 *
251 * Gets the #GDBusConnection the method was invoked on.
252 *
253 * Returns: (transfer none):A #GDBusConnection. Do not free, it is owned by @invocation.
254 *
255 * Since: 2.26
256 */
257 GDBusConnection *
258 g_dbus_method_invocation_get_connection (GDBusMethodInvocation *invocation)
259 {
260 g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
261 return invocation->connection;
262 }
263
264 /**
265 * g_dbus_method_invocation_get_message:
266 * @invocation: A #GDBusMethodInvocation.
267 *
268 * Gets the #GDBusMessage for the method invocation. This is useful if
269 * you need to use low-level protocol features, such as UNIX file
270 * descriptor passing, that cannot be properly expressed in the
271 * #GVariant API.
272 *
273 * See this [server][gdbus-server] and [client][gdbus-unix-fd-client]
274 * for an example of how to use this low-level API to send and receive
275 * UNIX file descriptors.
276 *
277 * Returns: (transfer none): #GDBusMessage. Do not free, it is owned by @invocation.
278 *
279 * Since: 2.26
280 */
281 GDBusMessage *
282 g_dbus_method_invocation_get_message (GDBusMethodInvocation *invocation)
283 {
284 g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
285 return invocation->message;
286 }
287
288 /**
289 * g_dbus_method_invocation_get_parameters:
290 * @invocation: A #GDBusMethodInvocation.
291 *
292 * Gets the parameters of the method invocation. If there are no input
293 * parameters then this will return a GVariant with 0 children rather than NULL.
294 *
295 * Returns: (transfer none): A #GVariant tuple. Do not unref this because it is owned by @invocation.
296 *
297 * Since: 2.26
298 */
299 GVariant *
300 g_dbus_method_invocation_get_parameters (GDBusMethodInvocation *invocation)
301 {
302 g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
303 return invocation->parameters;
304 }
305
306 /**
307 * g_dbus_method_invocation_get_user_data: (skip)
308 * @invocation: A #GDBusMethodInvocation.
309 *
310 * Gets the @user_data #gpointer passed to g_dbus_connection_register_object().
311 *
312 * Returns: A #gpointer.
313 *
314 * Since: 2.26
315 */
316 gpointer
317 g_dbus_method_invocation_get_user_data (GDBusMethodInvocation *invocation)
318 {
319 g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
320 return invocation->user_data;
321 }
322
323 /* < internal >
324 * _g_dbus_method_invocation_new:
325 * @sender: (nullable): The bus name that invoked the method or %NULL if @connection is not a bus connection.
326 * @object_path: The object path the method was invoked on.
327 * @interface_name: The name of the D-Bus interface the method was invoked on.
328 * @method_name: The name of the method that was invoked.
329 * @method_info: (nullable): Information about the method call or %NULL.
330 * @property_info: (nullable): Information about the property or %NULL.
331 * @connection: The #GDBusConnection the method was invoked on.
332 * @message: The D-Bus message as a #GDBusMessage.
333 * @parameters: The parameters as a #GVariant tuple.
334 * @user_data: The @user_data #gpointer passed to g_dbus_connection_register_object().
335 *
336 * Creates a new #GDBusMethodInvocation object.
337 *
338 * Returns: A #GDBusMethodInvocation. Free with g_object_unref().
339 *
340 * Since: 2.26
341 */
342 GDBusMethodInvocation *
343 _g_dbus_method_invocation_new (const gchar *sender,
344 const gchar *object_path,
345 const gchar *interface_name,
346 const gchar *method_name,
347 const GDBusMethodInfo *method_info,
348 const GDBusPropertyInfo *property_info,
349 GDBusConnection *connection,
350 GDBusMessage *message,
351 GVariant *parameters,
352 gpointer user_data)
353 {
354 GDBusMethodInvocation *invocation;
355
356 g_return_val_if_fail (sender == NULL || g_dbus_is_name (sender), NULL);
357 g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
358 g_return_val_if_fail (interface_name == NULL || g_dbus_is_interface_name (interface_name), NULL);
359 g_return_val_if_fail (g_dbus_is_member_name (method_name), NULL);
360 g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
361 g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
362 g_return_val_if_fail (g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL);
363
364 invocation = G_DBUS_METHOD_INVOCATION (g_object_new (G_TYPE_DBUS_METHOD_INVOCATION, NULL));
365 invocation->sender = g_strdup (sender);
366 invocation->object_path = g_strdup (object_path);
367 invocation->interface_name = g_strdup (interface_name);
368 invocation->method_name = g_strdup (method_name);
369 if (method_info)
370 invocation->method_info = g_dbus_method_info_ref ((GDBusMethodInfo *)method_info);
371 if (property_info)
372 invocation->property_info = g_dbus_property_info_ref ((GDBusPropertyInfo *)property_info);
373 invocation->connection = g_object_ref (connection);
374 invocation->message = g_object_ref (message);
375 invocation->parameters = g_variant_ref (parameters);
376 invocation->user_data = user_data;
377
378 return invocation;
379 }
380
381 /* ---------------------------------------------------------------------------------------------------- */
382
383 static void
384 g_dbus_method_invocation_return_value_internal (GDBusMethodInvocation *invocation,
385 GVariant *parameters,
386 GUnixFDList *fd_list)
387 {
388 GDBusMessage *reply;
389 GError *error;
390
391 g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
392 g_return_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE));
393
394 if (g_dbus_message_get_flags (invocation->message) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED)
395 goto out;
396
397 if (parameters == NULL)
398 parameters = g_variant_new_tuple (NULL, 0);
399
400 /* if we have introspection data, check that the signature of @parameters is correct */
401 if (invocation->method_info != NULL)
402 {
403 GVariantType *type;
404
405 type = _g_dbus_compute_complete_signature (invocation->method_info->out_args);
406
407 if (!g_variant_is_of_type (parameters, type))
408 {
409 gchar *type_string = g_variant_type_dup_string (type);
410
411 g_warning ("Type of return value is incorrect: expected '%s', got '%s'",
412 type_string, g_variant_get_type_string (parameters));
413 g_variant_type_free (type);
414 g_free (type_string);
415 goto out;
416 }
417 g_variant_type_free (type);
418 }
419
420 /* property_info is only non-NULL if set that way from
421 * GDBusConnection, so this must be the case of async property
422 * handling on either 'Get' or 'Set'.
423 *
424 * property_info is NULL for 'GetAll'.
425 */
426 if (invocation->property_info != NULL)
427 {
428 if (g_str_equal (invocation->method_name, "Get"))
429 {
430 GVariant *nested;
431
432 if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(v)")))
433 {
434 g_warning ("Type of return value for property 'Get' call should be '(v)' but got '%s'",
435 g_variant_get_type_string (parameters));
436 goto out;
437 }
438
439 /* Go deeper and make sure that the value inside of the
440 * variant matches the property type.
441 */
442 g_variant_get (parameters, "(v)", &nested);
443 if (!g_str_equal (g_variant_get_type_string (nested), invocation->property_info->signature))
444 {
445 g_warning ("Value returned from property 'Get' call for '%s' should be '%s' but is '%s'",
446 invocation->property_info->name, invocation->property_info->signature,
447 g_variant_get_type_string (nested));
448 g_variant_unref (nested);
449 goto out;
450 }
451 g_variant_unref (nested);
452 }
453
454 else if (g_str_equal (invocation->method_name, "Set"))
455 {
456 if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE_UNIT))
457 {
458 g_warning ("Type of return value for property 'Set' call should be '()' but got '%s'",
459 g_variant_get_type_string (parameters));
460 goto out;
461 }
462 }
463
464 else
465 g_assert_not_reached ();
466 }
467 else if (g_str_equal (invocation->interface_name, "org.freedesktop.DBus.Properties") &&
468 g_str_equal (invocation->method_name, "GetAll"))
469 {
470 if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(a{sv})")))
471 {
472 g_warning ("Type of return value for property 'GetAll' call should be '(a{sv})' but got '%s'",
473 g_variant_get_type_string (parameters));
474 goto out;
475 }
476
477 /* Could iterate the list of properties and make sure that all
478 * of them are actually on the interface and with the correct
479 * types, but let's not do that for now...
480 */
481 }
482
483 if (G_UNLIKELY (_g_dbus_debug_return ()))
484 {
485 _g_dbus_debug_print_lock ();
486 g_print ("========================================================================\n"
487 "GDBus-debug:Return:\n"
488 " >>>> METHOD RETURN\n"
489 " in response to %s.%s()\n"
490 " on object %s\n"
491 " to name %s\n"
492 " reply-serial %d\n",
493 invocation->interface_name, invocation->method_name,
494 invocation->object_path,
495 invocation->sender,
496 g_dbus_message_get_serial (invocation->message));
497 _g_dbus_debug_print_unlock ();
498 }
499
500 reply = g_dbus_message_new_method_reply (invocation->message);
501 g_dbus_message_set_body (reply, g_steal_pointer (¶meters));
502
503 #ifdef G_OS_UNIX
504 if (fd_list != NULL)
505 g_dbus_message_set_unix_fd_list (reply, fd_list);
506 #endif
507
508 error = NULL;
509 if (!g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error))
510 {
511 if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED))
512 g_warning ("Error sending message: %s", error->message);
513 g_error_free (error);
514 }
515 g_object_unref (reply);
516
517 out:
518 if (parameters != NULL)
519 {
520 g_variant_ref_sink (parameters);
521 g_variant_unref (parameters);
522 }
523
524 g_object_unref (invocation);
525 }
526
527 /**
528 * g_dbus_method_invocation_return_value:
529 * @invocation: (transfer full): A #GDBusMethodInvocation.
530 * @parameters: (nullable): A #GVariant tuple with out parameters for the method or %NULL if not passing any parameters.
531 *
532 * Finishes handling a D-Bus method call by returning @parameters.
533 * If the @parameters GVariant is floating, it is consumed.
534 *
535 * It is an error if @parameters is not of the right format: it must be a tuple
536 * containing the out-parameters of the D-Bus method. Even if the method has a
537 * single out-parameter, it must be contained in a tuple. If the method has no
538 * out-parameters, @parameters may be %NULL or an empty tuple.
539 *
540 * |[<!-- language="C" -->
541 * GDBusMethodInvocation *invocation = some_invocation;
542 * g_autofree gchar *result_string = NULL;
543 * g_autoptr (GError) error = NULL;
544 *
545 * result_string = calculate_result (&error);
546 *
547 * if (error != NULL)
548 * g_dbus_method_invocation_return_gerror (invocation, error);
549 * else
550 * g_dbus_method_invocation_return_value (invocation,
551 * g_variant_new ("(s)", result_string));
552 *
553 * // Do not free @invocation here; returning a value does that
554 * ]|
555 *
556 * This method will take ownership of @invocation. See
557 * #GDBusInterfaceVTable for more information about the ownership of
558 * @invocation.
559 *
560 * Since 2.48, if the method call requested for a reply not to be sent
561 * then this call will sink @parameters and free @invocation, but
562 * otherwise do nothing (as per the recommendations of the D-Bus
563 * specification).
564 *
565 * Since: 2.26
566 */
567 void
568 g_dbus_method_invocation_return_value (GDBusMethodInvocation *invocation,
569 GVariant *parameters)
570 {
571 g_dbus_method_invocation_return_value_internal (invocation, parameters, NULL);
572 }
573
574 #ifdef G_OS_UNIX
575 /**
576 * g_dbus_method_invocation_return_value_with_unix_fd_list:
577 * @invocation: (transfer full): A #GDBusMethodInvocation.
578 * @parameters: (nullable): A #GVariant tuple with out parameters for the method or %NULL if not passing any parameters.
579 * @fd_list: (nullable): A #GUnixFDList or %NULL.
580 *
581 * Like g_dbus_method_invocation_return_value() but also takes a #GUnixFDList.
582 *
583 * This method is only available on UNIX.
584 *
585 * This method will take ownership of @invocation. See
586 * #GDBusInterfaceVTable for more information about the ownership of
587 * @invocation.
588 *
589 * Since: 2.30
590 */
591 void
592 g_dbus_method_invocation_return_value_with_unix_fd_list (GDBusMethodInvocation *invocation,
593 GVariant *parameters,
594 GUnixFDList *fd_list)
595 {
596 g_dbus_method_invocation_return_value_internal (invocation, parameters, fd_list);
597 }
598 #endif
599
600 /* ---------------------------------------------------------------------------------------------------- */
601
602 /**
603 * g_dbus_method_invocation_return_error:
604 * @invocation: (transfer full): A #GDBusMethodInvocation.
605 * @domain: A #GQuark for the #GError error domain.
606 * @code: The error code.
607 * @format: printf()-style format.
608 * @...: Parameters for @format.
609 *
610 * Finishes handling a D-Bus method call by returning an error.
611 *
612 * See g_dbus_error_encode_gerror() for details about what error name
613 * will be returned on the wire. In a nutshell, if the given error is
614 * registered using g_dbus_error_register_error() the name given
615 * during registration is used. Otherwise, a name of the form
616 * `org.gtk.GDBus.UnmappedGError.Quark...` is used. This provides
617 * transparent mapping of #GError between applications using GDBus.
618 *
619 * If you are writing an application intended to be portable,
620 * always register errors with g_dbus_error_register_error()
621 * or use g_dbus_method_invocation_return_dbus_error().
622 *
623 * This method will take ownership of @invocation. See
624 * #GDBusInterfaceVTable for more information about the ownership of
625 * @invocation.
626 *
627 * Since 2.48, if the method call requested for a reply not to be sent
628 * then this call will free @invocation but otherwise do nothing (as per
629 * the recommendations of the D-Bus specification).
630 *
631 * Since: 2.26
632 */
633 void
634 g_dbus_method_invocation_return_error (GDBusMethodInvocation *invocation,
635 GQuark domain,
636 gint code,
637 const gchar *format,
638 ...)
639 {
640 va_list var_args;
641
642 g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
643 g_return_if_fail (format != NULL);
644
645 va_start (var_args, format);
646 g_dbus_method_invocation_return_error_valist (invocation,
647 domain,
648 code,
649 format,
650 var_args);
651 va_end (var_args);
652 }
653
654 /**
655 * g_dbus_method_invocation_return_error_valist:
656 * @invocation: (transfer full): A #GDBusMethodInvocation.
657 * @domain: A #GQuark for the #GError error domain.
658 * @code: The error code.
659 * @format: printf()-style format.
660 * @var_args: #va_list of parameters for @format.
661 *
662 * Like g_dbus_method_invocation_return_error() but intended for
663 * language bindings.
664 *
665 * This method will take ownership of @invocation. See
666 * #GDBusInterfaceVTable for more information about the ownership of
667 * @invocation.
668 *
669 * Since: 2.26
670 */
671 void
672 g_dbus_method_invocation_return_error_valist (GDBusMethodInvocation *invocation,
673 GQuark domain,
674 gint code,
675 const gchar *format,
676 va_list var_args)
677 {
678 gchar *literal_message;
679
680 g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
681 g_return_if_fail (format != NULL);
682
683 literal_message = g_strdup_vprintf (format, var_args);
684 g_dbus_method_invocation_return_error_literal (invocation,
685 domain,
686 code,
687 literal_message);
688 g_free (literal_message);
689 }
690
691 /**
692 * g_dbus_method_invocation_return_error_literal:
693 * @invocation: (transfer full): A #GDBusMethodInvocation.
694 * @domain: A #GQuark for the #GError error domain.
695 * @code: The error code.
696 * @message: The error message.
697 *
698 * Like g_dbus_method_invocation_return_error() but without printf()-style formatting.
699 *
700 * This method will take ownership of @invocation. See
701 * #GDBusInterfaceVTable for more information about the ownership of
702 * @invocation.
703 *
704 * Since: 2.26
705 */
706 void
707 g_dbus_method_invocation_return_error_literal (GDBusMethodInvocation *invocation,
708 GQuark domain,
709 gint code,
710 const gchar *message)
711 {
712 GError *error;
713
714 g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
715 g_return_if_fail (message != NULL);
716
717 error = g_error_new_literal (domain, code, message);
718 g_dbus_method_invocation_return_gerror (invocation, error);
719 g_error_free (error);
720 }
721
722 /**
723 * g_dbus_method_invocation_return_gerror:
724 * @invocation: (transfer full): A #GDBusMethodInvocation.
725 * @error: A #GError.
726 *
727 * Like g_dbus_method_invocation_return_error() but takes a #GError
728 * instead of the error domain, error code and message.
729 *
730 * This method will take ownership of @invocation. See
731 * #GDBusInterfaceVTable for more information about the ownership of
732 * @invocation.
733 *
734 * Since: 2.26
735 */
736 void
737 g_dbus_method_invocation_return_gerror (GDBusMethodInvocation *invocation,
738 const GError *error)
739 {
740 gchar *dbus_error_name;
741
742 g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
743 g_return_if_fail (error != NULL);
744
745 dbus_error_name = g_dbus_error_encode_gerror (error);
746
747 g_dbus_method_invocation_return_dbus_error (invocation,
748 dbus_error_name,
749 error->message);
750 g_free (dbus_error_name);
751 }
752
753 /**
754 * g_dbus_method_invocation_take_error: (skip)
755 * @invocation: (transfer full): A #GDBusMethodInvocation.
756 * @error: (transfer full): A #GError.
757 *
758 * Like g_dbus_method_invocation_return_gerror() but takes ownership
759 * of @error so the caller does not need to free it.
760 *
761 * This method will take ownership of @invocation. See
762 * #GDBusInterfaceVTable for more information about the ownership of
763 * @invocation.
764 *
765 * Since: 2.30
766 */
767 void
768 g_dbus_method_invocation_take_error (GDBusMethodInvocation *invocation,
769 GError *error)
770 {
771 g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
772 g_return_if_fail (error != NULL);
773 g_dbus_method_invocation_return_gerror (invocation, error);
774 g_error_free (error);
775 }
776
777 /**
778 * g_dbus_method_invocation_return_dbus_error:
779 * @invocation: (transfer full): A #GDBusMethodInvocation.
780 * @error_name: A valid D-Bus error name.
781 * @error_message: A valid D-Bus error message.
782 *
783 * Finishes handling a D-Bus method call by returning an error.
784 *
785 * This method will take ownership of @invocation. See
786 * #GDBusInterfaceVTable for more information about the ownership of
787 * @invocation.
788 *
789 * Since: 2.26
790 */
791 void
792 g_dbus_method_invocation_return_dbus_error (GDBusMethodInvocation *invocation,
793 const gchar *error_name,
794 const gchar *error_message)
795 {
796 GDBusMessage *reply;
797
798 g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
799 g_return_if_fail (error_name != NULL && g_dbus_is_name (error_name));
800 g_return_if_fail (error_message != NULL);
801
802 if (g_dbus_message_get_flags (invocation->message) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED)
803 goto out;
804
805 if (G_UNLIKELY (_g_dbus_debug_return ()))
806 {
807 _g_dbus_debug_print_lock ();
808 g_print ("========================================================================\n"
809 "GDBus-debug:Return:\n"
810 " >>>> METHOD ERROR %s\n"
811 " message '%s'\n"
812 " in response to %s.%s()\n"
813 " on object %s\n"
814 " to name %s\n"
815 " reply-serial %d\n",
816 error_name,
817 error_message,
818 invocation->interface_name, invocation->method_name,
819 invocation->object_path,
820 invocation->sender,
821 g_dbus_message_get_serial (invocation->message));
822 _g_dbus_debug_print_unlock ();
823 }
824
825 reply = g_dbus_message_new_method_error_literal (invocation->message,
826 error_name,
827 error_message);
828 g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
829 g_object_unref (reply);
830
831 out:
832 g_object_unref (invocation);
833 }