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