Branch data Line data Source code
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 : 13140 : G_DEFINE_TYPE (GDBusMethodInvocation, g_dbus_method_invocation, G_TYPE_OBJECT)
91 : :
92 : : static void
93 : 952 : g_dbus_method_invocation_finalize (GObject *object)
94 : : {
95 : 952 : GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (object);
96 : :
97 : 952 : g_free (invocation->sender);
98 : 952 : g_free (invocation->object_path);
99 : 952 : g_free (invocation->interface_name);
100 : 952 : g_free (invocation->method_name);
101 : 952 : if (invocation->method_info)
102 : 937 : g_dbus_method_info_unref (invocation->method_info);
103 : 952 : if (invocation->property_info)
104 : 12 : g_dbus_property_info_unref (invocation->property_info);
105 : 952 : g_object_unref (invocation->connection);
106 : 952 : g_object_unref (invocation->message);
107 : 952 : g_variant_unref (invocation->parameters);
108 : :
109 : 952 : G_OBJECT_CLASS (g_dbus_method_invocation_parent_class)->finalize (object);
110 : 952 : }
111 : :
112 : : static void
113 : 22 : g_dbus_method_invocation_class_init (GDBusMethodInvocationClass *klass)
114 : : {
115 : 22 : GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
116 : :
117 : 22 : gobject_class->finalize = g_dbus_method_invocation_finalize;
118 : 22 : }
119 : :
120 : : static void
121 : 953 : g_dbus_method_invocation_init (GDBusMethodInvocation *invocation)
122 : : {
123 : 953 : }
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 : 826 : g_dbus_method_invocation_get_sender (GDBusMethodInvocation *invocation)
137 : : {
138 : 826 : g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
139 : 826 : 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 : 996 : g_dbus_method_invocation_get_object_path (GDBusMethodInvocation *invocation)
154 : : {
155 : 996 : g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
156 : 996 : 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 : 999 : g_dbus_method_invocation_get_interface_name (GDBusMethodInvocation *invocation)
176 : : {
177 : 999 : g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
178 : 999 : 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 : 66 : g_dbus_method_invocation_get_method_info (GDBusMethodInvocation *invocation)
198 : : {
199 : 66 : g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
200 : 66 : 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 : 5 : g_dbus_method_invocation_get_property_info (GDBusMethodInvocation *invocation)
225 : : {
226 : 5 : g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
227 : 5 : 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 : 832 : g_dbus_method_invocation_get_method_name (GDBusMethodInvocation *invocation)
242 : : {
243 : 832 : g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
244 : 832 : 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 : 2539 : g_dbus_method_invocation_get_connection (GDBusMethodInvocation *invocation)
259 : : {
260 : 2539 : g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
261 : 2539 : 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 : 213 : g_dbus_method_invocation_get_message (GDBusMethodInvocation *invocation)
283 : : {
284 : 213 : g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
285 : 213 : 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 : 821 : g_dbus_method_invocation_get_parameters (GDBusMethodInvocation *invocation)
301 : : {
302 : 821 : g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
303 : 821 : 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 : 814 : g_dbus_method_invocation_get_user_data (GDBusMethodInvocation *invocation)
318 : : {
319 : 814 : g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
320 : 814 : 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 : 953 : _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 : 953 : g_return_val_if_fail (sender == NULL || g_dbus_is_name (sender), NULL);
357 : 953 : g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
358 : 953 : g_return_val_if_fail (interface_name == NULL || g_dbus_is_interface_name (interface_name), NULL);
359 : 953 : g_return_val_if_fail (g_dbus_is_member_name (method_name), NULL);
360 : 953 : g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
361 : 953 : g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
362 : 953 : g_return_val_if_fail (g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL);
363 : :
364 : 953 : invocation = G_DBUS_METHOD_INVOCATION (g_object_new (G_TYPE_DBUS_METHOD_INVOCATION, NULL));
365 : 953 : invocation->sender = g_strdup (sender);
366 : 953 : invocation->object_path = g_strdup (object_path);
367 : 953 : invocation->interface_name = g_strdup (interface_name);
368 : 953 : invocation->method_name = g_strdup (method_name);
369 : 953 : if (method_info)
370 : 938 : invocation->method_info = g_dbus_method_info_ref ((GDBusMethodInfo *)method_info);
371 : 953 : if (property_info)
372 : 12 : invocation->property_info = g_dbus_property_info_ref ((GDBusPropertyInfo *)property_info);
373 : 953 : invocation->connection = g_object_ref (connection);
374 : 953 : invocation->message = g_object_ref (message);
375 : 953 : invocation->parameters = g_variant_ref (parameters);
376 : 953 : invocation->user_data = user_data;
377 : :
378 : 953 : return invocation;
379 : : }
380 : :
381 : : /* ---------------------------------------------------------------------------------------------------- */
382 : :
383 : : static void
384 : 733 : 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 : 733 : g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
392 : 733 : g_return_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE));
393 : :
394 : 733 : if (g_dbus_message_get_flags (invocation->message) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED)
395 : 179 : goto out;
396 : :
397 : 554 : if (parameters == NULL)
398 : 97 : parameters = g_variant_new_tuple (NULL, 0);
399 : :
400 : : /* if we have introspection data, check that the signature of @parameters is correct */
401 : 554 : if (invocation->method_info != NULL)
402 : : {
403 : : GVariantType *type;
404 : :
405 : 544 : type = _g_dbus_compute_complete_signature (invocation->method_info->out_args);
406 : :
407 : 544 : if (!g_variant_is_of_type (parameters, type))
408 : : {
409 : 1 : gchar *type_string = g_variant_type_dup_string (type);
410 : :
411 : 1 : g_warning ("Type of return value is incorrect: expected '%s', got '%s'",
412 : : type_string, g_variant_get_type_string (parameters));
413 : 1 : g_variant_type_free (type);
414 : 1 : g_free (type_string);
415 : 1 : goto out;
416 : : }
417 : 543 : 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 : 553 : if (invocation->property_info != NULL)
427 : : {
428 : 8 : if (g_str_equal (invocation->method_name, "Get"))
429 : : {
430 : : GVariant *nested;
431 : :
432 : 5 : if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(v)")))
433 : : {
434 : 2 : g_warning ("Type of return value for property 'Get' call should be '(v)' but got '%s'",
435 : : g_variant_get_type_string (parameters));
436 : 3 : goto out;
437 : : }
438 : :
439 : : /* Go deeper and make sure that the value inside of the
440 : : * variant matches the property type.
441 : : */
442 : 3 : g_variant_get (parameters, "(v)", &nested);
443 : 3 : if (!g_str_equal (g_variant_get_type_string (nested), invocation->property_info->signature))
444 : : {
445 : 1 : 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 : 1 : g_variant_unref (nested);
449 : 1 : goto out;
450 : : }
451 : 2 : g_variant_unref (nested);
452 : : }
453 : :
454 : 3 : else if (g_str_equal (invocation->method_name, "Set"))
455 : : {
456 : 3 : if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE_UNIT))
457 : : {
458 : 1 : g_warning ("Type of return value for property 'Set' call should be '()' but got '%s'",
459 : : g_variant_get_type_string (parameters));
460 : 1 : goto out;
461 : : }
462 : : }
463 : :
464 : : else
465 : : g_assert_not_reached ();
466 : : }
467 : 545 : else if (g_str_equal (invocation->interface_name, DBUS_INTERFACE_PROPERTIES) &&
468 : 2 : g_str_equal (invocation->method_name, "GetAll"))
469 : : {
470 : 2 : if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(a{sv})")))
471 : : {
472 : 1 : 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 : 1 : 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 : 548 : if (G_UNLIKELY (_g_dbus_debug_return ()))
484 : : {
485 : 0 : _g_dbus_debug_print_lock ();
486 : 0 : 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 : 0 : _g_dbus_debug_print_unlock ();
498 : : }
499 : :
500 : 548 : reply = g_dbus_message_new_method_reply (invocation->message);
501 : 548 : g_dbus_message_set_body (reply, g_steal_pointer (¶meters));
502 : :
503 : : #ifdef G_OS_UNIX
504 : 548 : if (fd_list != NULL)
505 : 5 : g_dbus_message_set_unix_fd_list (reply, fd_list);
506 : : #endif
507 : :
508 : 548 : error = NULL;
509 : 548 : if (!g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error))
510 : : {
511 : 0 : if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED))
512 : 0 : g_warning ("Error sending message: %s", error->message);
513 : 0 : g_error_free (error);
514 : : }
515 : 548 : g_object_unref (reply);
516 : :
517 : 733 : out:
518 : 733 : if (parameters != NULL)
519 : : {
520 : 13 : g_variant_ref_sink (parameters);
521 : 13 : g_variant_unref (parameters);
522 : : }
523 : :
524 : 733 : 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 : 721 : g_dbus_method_invocation_return_value (GDBusMethodInvocation *invocation,
569 : : GVariant *parameters)
570 : : {
571 : 721 : g_dbus_method_invocation_return_value_internal (invocation, parameters, NULL);
572 : 721 : }
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 : 12 : g_dbus_method_invocation_return_value_with_unix_fd_list (GDBusMethodInvocation *invocation,
593 : : GVariant *parameters,
594 : : GUnixFDList *fd_list)
595 : : {
596 : 12 : g_dbus_method_invocation_return_value_internal (invocation, parameters, fd_list);
597 : 12 : }
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 : 23 : 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 : 23 : g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
643 : 23 : g_return_if_fail (format != NULL);
644 : :
645 : 23 : va_start (var_args, format);
646 : 23 : g_dbus_method_invocation_return_error_valist (invocation,
647 : : domain,
648 : : code,
649 : : format,
650 : : var_args);
651 : 23 : 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 : 23 : 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 : 23 : g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
681 : 23 : g_return_if_fail (format != NULL);
682 : :
683 : 23 : literal_message = g_strdup_vprintf (format, var_args);
684 : 23 : g_dbus_method_invocation_return_error_literal (invocation,
685 : : domain,
686 : : code,
687 : : literal_message);
688 : 23 : 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 : 23 : 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 : 23 : g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
715 : 23 : g_return_if_fail (message != NULL);
716 : :
717 : 23 : error = g_error_new_literal (domain, code, message);
718 : 23 : g_dbus_method_invocation_return_gerror (invocation, error);
719 : 23 : 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 : 25 : g_dbus_method_invocation_return_gerror (GDBusMethodInvocation *invocation,
738 : : const GError *error)
739 : : {
740 : : gchar *dbus_error_name;
741 : :
742 : 25 : g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
743 : 25 : g_return_if_fail (error != NULL);
744 : :
745 : 25 : dbus_error_name = g_dbus_error_encode_gerror (error);
746 : :
747 : 25 : g_dbus_method_invocation_return_dbus_error (invocation,
748 : : dbus_error_name,
749 : 25 : error->message);
750 : 25 : 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 : 2 : g_dbus_method_invocation_take_error (GDBusMethodInvocation *invocation,
769 : : GError *error)
770 : : {
771 : 2 : g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
772 : 2 : g_return_if_fail (error != NULL);
773 : 2 : g_dbus_method_invocation_return_gerror (invocation, error);
774 : 2 : 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 : 31 : 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 : 31 : g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
799 : 31 : g_return_if_fail (error_name != NULL && g_dbus_is_name (error_name));
800 : 31 : g_return_if_fail (error_message != NULL);
801 : :
802 : 31 : if (g_dbus_message_get_flags (invocation->message) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED)
803 : 1 : goto out;
804 : :
805 : 30 : if (G_UNLIKELY (_g_dbus_debug_return ()))
806 : : {
807 : 0 : _g_dbus_debug_print_lock ();
808 : 0 : 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 : 0 : _g_dbus_debug_print_unlock ();
823 : : }
824 : :
825 : 30 : reply = g_dbus_message_new_method_error_literal (invocation->message,
826 : : error_name,
827 : : error_message);
828 : 30 : g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
829 : 30 : g_object_unref (reply);
830 : :
831 : 31 : out:
832 : 31 : g_object_unref (invocation);
833 : : }
|