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