Coverage Report

Created: 2025-06-13 06:20

/src/glib/gio/gdbusmethodinvocation.c
Line
Count
Source (jump to first uncovered line)
1
/* GDBus - GLib D-Bus Library
2
 *
3
 * Copyright (C) 2008-2010 Red Hat, Inc.
4
 *
5
 * SPDX-License-Identifier: LGPL-2.1-or-later
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General
18
 * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
19
 *
20
 * Author: David Zeuthen <davidz@redhat.com>
21
 */
22
23
#include "config.h"
24
25
#include <stdlib.h>
26
27
#include "gdbusutils.h"
28
#include "gdbusconnection.h"
29
#include "gdbusmessage.h"
30
#include "gdbusmethodinvocation.h"
31
#include "gdbusintrospection.h"
32
#include "gdbuserror.h"
33
#include "gdbusprivate.h"
34
#include "gioerror.h"
35
36
#ifdef G_OS_UNIX
37
#include "gunixfdlist.h"
38
#endif
39
40
#include "glibintl.h"
41
42
/**
43
 * GDBusMethodInvocation:
44
 *
45
 * Instances of the `GDBusMethodInvocation` class are used when
46
 * handling D-Bus method calls. It provides a way to asynchronously
47
 * return results and errors.
48
 *
49
 * The normal way to obtain a `GDBusMethodInvocation` object is to receive
50
 * it as an argument to the `handle_method_call()` function in a
51
 * [type@Gio.DBusInterfaceVTable] that was passed to
52
 * [method@Gio.DBusConnection.register_object].
53
 *
54
 * Since: 2.26
55
 */
56
57
typedef struct _GDBusMethodInvocationClass GDBusMethodInvocationClass;
58
59
/**
60
 * GDBusMethodInvocationClass:
61
 *
62
 * Class structure for #GDBusMethodInvocation.
63
 *
64
 * Since: 2.26
65
 */
66
struct _GDBusMethodInvocationClass
67
{
68
  /*< private >*/
69
  GObjectClass parent_class;
70
};
71
72
struct _GDBusMethodInvocation
73
{
74
  /*< private >*/
75
  GObject parent_instance;
76
77
  /* construct-only properties */
78
  gchar           *sender;
79
  gchar           *object_path;
80
  gchar           *interface_name;
81
  gchar           *method_name;
82
  GDBusMethodInfo *method_info;
83
  GDBusPropertyInfo *property_info;
84
  GDBusConnection *connection;
85
  GDBusMessage    *message;
86
  GVariant        *parameters;
87
  gpointer         user_data;
88
};
89
90
G_DEFINE_TYPE (GDBusMethodInvocation, g_dbus_method_invocation, G_TYPE_OBJECT)
91
92
static void
93
g_dbus_method_invocation_finalize (GObject *object)
94
0
{
95
0
  GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (object);
96
97
0
  g_free (invocation->sender);
98
0
  g_free (invocation->object_path);
99
0
  g_free (invocation->interface_name);
100
0
  g_free (invocation->method_name);
101
0
  if (invocation->method_info)
102
0
      g_dbus_method_info_unref (invocation->method_info);
103
0
  if (invocation->property_info)
104
0
      g_dbus_property_info_unref (invocation->property_info);
105
0
  g_object_unref (invocation->connection);
106
0
  g_object_unref (invocation->message);
107
0
  g_variant_unref (invocation->parameters);
108
109
0
  G_OBJECT_CLASS (g_dbus_method_invocation_parent_class)->finalize (object);
110
0
}
111
112
static void
113
g_dbus_method_invocation_class_init (GDBusMethodInvocationClass *klass)
114
0
{
115
0
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
116
117
0
  gobject_class->finalize = g_dbus_method_invocation_finalize;
118
0
}
119
120
static void
121
g_dbus_method_invocation_init (GDBusMethodInvocation *invocation)
122
0
{
123
0
}
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
g_dbus_method_invocation_get_sender (GDBusMethodInvocation *invocation)
140
0
{
141
0
  g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
142
0
  return invocation->sender;
143
0
}
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
g_dbus_method_invocation_get_object_path (GDBusMethodInvocation *invocation)
157
0
{
158
0
  g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
159
0
  return invocation->object_path;
160
0
}
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
g_dbus_method_invocation_get_interface_name (GDBusMethodInvocation *invocation)
184
0
{
185
0
  g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
186
0
  return invocation->interface_name;
187
0
}
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
g_dbus_method_invocation_get_method_info (GDBusMethodInvocation *invocation)
206
0
{
207
0
  g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
208
0
  return invocation->method_info;
209
0
}
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
g_dbus_method_invocation_get_property_info (GDBusMethodInvocation *invocation)
233
0
{
234
0
  g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
235
0
  return invocation->property_info;
236
0
}
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
g_dbus_method_invocation_get_method_name (GDBusMethodInvocation *invocation)
250
0
{
251
0
  g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
252
0
  return invocation->method_name;
253
0
}
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
g_dbus_method_invocation_get_connection (GDBusMethodInvocation *invocation)
267
0
{
268
0
  g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
269
0
  return invocation->connection;
270
0
}
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
g_dbus_method_invocation_get_message (GDBusMethodInvocation *invocation)
292
0
{
293
0
  g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
294
0
  return invocation->message;
295
0
}
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
g_dbus_method_invocation_get_parameters (GDBusMethodInvocation *invocation)
310
0
{
311
0
  g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
312
0
  return invocation->parameters;
313
0
}
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
g_dbus_method_invocation_get_user_data (GDBusMethodInvocation *invocation)
327
0
{
328
0
  g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
329
0
  return invocation->user_data;
330
0
}
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
_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
0
{
363
0
  GDBusMethodInvocation *invocation;
364
365
0
  g_return_val_if_fail (sender == NULL || g_dbus_is_name (sender), NULL);
366
0
  g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
367
0
  g_return_val_if_fail (interface_name == NULL || g_dbus_is_interface_name (interface_name), NULL);
368
0
  g_return_val_if_fail (g_dbus_is_member_name (method_name), NULL);
369
0
  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
370
0
  g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
371
0
  g_return_val_if_fail (g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL);
372
373
0
  invocation = G_DBUS_METHOD_INVOCATION (g_object_new (G_TYPE_DBUS_METHOD_INVOCATION, NULL));
374
0
  invocation->sender = g_strdup (sender);
375
0
  invocation->object_path = g_strdup (object_path);
376
0
  invocation->interface_name = g_strdup (interface_name);
377
0
  invocation->method_name = g_strdup (method_name);
378
0
  if (method_info)
379
0
    invocation->method_info = g_dbus_method_info_ref ((GDBusMethodInfo *)method_info);
380
0
  if (property_info)
381
0
    invocation->property_info = g_dbus_property_info_ref ((GDBusPropertyInfo *)property_info);
382
0
  invocation->connection = g_object_ref (connection);
383
0
  invocation->message = g_object_ref (message);
384
0
  invocation->parameters = g_variant_ref (parameters);
385
0
  invocation->user_data = user_data;
386
387
0
  return invocation;
388
0
}
389
390
/* ---------------------------------------------------------------------------------------------------- */
391
392
static void
393
g_dbus_method_invocation_return_value_internal (GDBusMethodInvocation *invocation,
394
                                                GVariant              *parameters,
395
                                                GUnixFDList           *fd_list)
396
0
{
397
0
  GDBusMessage *reply;
398
0
  GError *error;
399
400
0
  g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
401
0
  g_return_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE));
402
403
0
  if (g_dbus_message_get_flags (invocation->message) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED)
404
0
    goto out;
405
406
0
  if (parameters == NULL)
407
0
    parameters = g_variant_new_tuple (NULL, 0);
408
409
  /* if we have introspection data, check that the signature of @parameters is correct */
410
0
  if (invocation->method_info != NULL)
411
0
    {
412
0
      GVariantType *type;
413
414
0
      type = _g_dbus_compute_complete_signature (invocation->method_info->out_args);
415
416
0
      if (!g_variant_is_of_type (parameters, type))
417
0
        {
418
0
          gchar *type_string = g_variant_type_dup_string (type);
419
420
0
          g_warning ("Type of return value is incorrect: expected '%s', got '%s'",
421
0
         type_string, g_variant_get_type_string (parameters));
422
0
          g_variant_type_free (type);
423
0
          g_free (type_string);
424
0
          goto out;
425
0
        }
426
0
      g_variant_type_free (type);
427
0
    }
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
0
  if (invocation->property_info != NULL)
436
0
    {
437
0
      if (g_str_equal (invocation->method_name, "Get"))
438
0
        {
439
0
          GVariant *nested;
440
441
0
          if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(v)")))
442
0
            {
443
0
              g_warning ("Type of return value for property 'Get' call should be '(v)' but got '%s'",
444
0
                         g_variant_get_type_string (parameters));
445
0
              goto out;
446
0
            }
447
448
          /* Go deeper and make sure that the value inside of the
449
           * variant matches the property type.
450
           */
451
0
          g_variant_get (parameters, "(v)", &nested);
452
0
          if (!g_str_equal (g_variant_get_type_string (nested), invocation->property_info->signature))
453
0
            {
454
0
              g_warning ("Value returned from property 'Get' call for '%s' should be '%s' but is '%s'",
455
0
                         invocation->property_info->name, invocation->property_info->signature,
456
0
                         g_variant_get_type_string (nested));
457
0
              g_variant_unref (nested);
458
0
              goto out;
459
0
            }
460
0
          g_variant_unref (nested);
461
0
        }
462
463
0
      else if (g_str_equal (invocation->method_name, "Set"))
464
0
        {
465
0
          if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE_UNIT))
466
0
            {
467
0
              g_warning ("Type of return value for property 'Set' call should be '()' but got '%s'",
468
0
                         g_variant_get_type_string (parameters));
469
0
              goto out;
470
0
            }
471
0
        }
472
473
0
      else
474
0
        g_assert_not_reached ();
475
0
    }
476
0
  else if (g_str_equal (invocation->interface_name, DBUS_INTERFACE_PROPERTIES) &&
477
0
           g_str_equal (invocation->method_name, "GetAll"))
478
0
    {
479
0
      if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(a{sv})")))
480
0
        {
481
0
          g_warning ("Type of return value for property 'GetAll' call should be '(a{sv})' but got '%s'",
482
0
                     g_variant_get_type_string (parameters));
483
0
          goto out;
484
0
        }
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
0
    }
491
492
0
  if (G_UNLIKELY (_g_dbus_debug_return ()))
493
0
    {
494
0
      _g_dbus_debug_print_lock ();
495
0
      g_print ("========================================================================\n"
496
0
               "GDBus-debug:Return:\n"
497
0
               " >>>> METHOD RETURN\n"
498
0
               "      in response to %s.%s()\n"
499
0
               "      on object %s\n"
500
0
               "      to name %s\n"
501
0
               "      reply-serial %d\n",
502
0
               invocation->interface_name, invocation->method_name,
503
0
               invocation->object_path,
504
0
               invocation->sender,
505
0
               g_dbus_message_get_serial (invocation->message));
506
0
      _g_dbus_debug_print_unlock ();
507
0
    }
508
509
0
  reply = g_dbus_message_new_method_reply (invocation->message);
510
0
  g_dbus_message_set_body (reply, g_steal_pointer (&parameters));
511
512
0
#ifdef G_OS_UNIX
513
0
  if (fd_list != NULL)
514
0
    g_dbus_message_set_unix_fd_list (reply, fd_list);
515
0
#endif
516
517
0
  error = NULL;
518
0
  if (!g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error))
519
0
    {
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
0
    }
524
0
  g_object_unref (reply);
525
526
0
 out:
527
0
  if (parameters != NULL)
528
0
    {
529
0
      g_variant_ref_sink (parameters);
530
0
      g_variant_unref (parameters);
531
0
    }
532
533
0
  g_object_unref (invocation);
534
0
}
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
g_dbus_method_invocation_return_value (GDBusMethodInvocation *invocation,
578
                                       GVariant              *parameters)
579
0
{
580
0
  g_dbus_method_invocation_return_value_internal (invocation, parameters, NULL);
581
0
}
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
g_dbus_method_invocation_return_value_with_unix_fd_list (GDBusMethodInvocation *invocation,
602
                                                         GVariant              *parameters,
603
                                                         GUnixFDList           *fd_list)
604
0
{
605
0
  g_dbus_method_invocation_return_value_internal (invocation, parameters, fd_list);
606
0
}
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
g_dbus_method_invocation_return_error (GDBusMethodInvocation *invocation,
644
                                       GQuark                 domain,
645
                                       gint                   code,
646
                                       const gchar           *format,
647
                                       ...)
648
0
{
649
0
  va_list var_args;
650
651
0
  g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
652
0
  g_return_if_fail (format != NULL);
653
654
0
  va_start (var_args, format);
655
0
  g_dbus_method_invocation_return_error_valist (invocation,
656
0
                                                domain,
657
0
                                                code,
658
0
                                                format,
659
0
                                                var_args);
660
0
  va_end (var_args);
661
0
}
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
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
0
{
687
0
  gchar *literal_message;
688
689
0
  g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
690
0
  g_return_if_fail (format != NULL);
691
692
0
  literal_message = g_strdup_vprintf (format, var_args);
693
0
  g_dbus_method_invocation_return_error_literal (invocation,
694
0
                                                 domain,
695
0
                                                 code,
696
0
                                                 literal_message);
697
0
  g_free (literal_message);
698
0
}
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
g_dbus_method_invocation_return_error_literal (GDBusMethodInvocation *invocation,
717
                                               GQuark                 domain,
718
                                               gint                   code,
719
                                               const gchar           *message)
720
0
{
721
0
  GError *error;
722
723
0
  g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
724
0
  g_return_if_fail (message != NULL);
725
726
0
  error = g_error_new_literal (domain, code, message);
727
0
  g_dbus_method_invocation_return_gerror (invocation, error);
728
0
  g_error_free (error);
729
0
}
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
g_dbus_method_invocation_return_gerror (GDBusMethodInvocation *invocation,
747
                                        const GError          *error)
748
0
{
749
0
  gchar *dbus_error_name;
750
751
0
  g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
752
0
  g_return_if_fail (error != NULL);
753
754
0
  dbus_error_name = g_dbus_error_encode_gerror (error);
755
756
0
  g_dbus_method_invocation_return_dbus_error (invocation,
757
0
                                              dbus_error_name,
758
0
                                              error->message);
759
0
  g_free (dbus_error_name);
760
0
}
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
g_dbus_method_invocation_take_error (GDBusMethodInvocation *invocation,
778
                                     GError                *error)
779
0
{
780
0
  g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
781
0
  g_return_if_fail (error != NULL);
782
0
  g_dbus_method_invocation_return_gerror (invocation, error);
783
0
  g_error_free (error);
784
0
}
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
g_dbus_method_invocation_return_dbus_error (GDBusMethodInvocation *invocation,
802
                                            const gchar           *error_name,
803
                                            const gchar           *error_message)
804
0
{
805
0
  GDBusMessage *reply;
806
807
0
  g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
808
0
  g_return_if_fail (error_name != NULL && g_dbus_is_name (error_name));
809
0
  g_return_if_fail (error_message != NULL);
810
811
0
  if (g_dbus_message_get_flags (invocation->message) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED)
812
0
    goto out;
813
814
0
  if (G_UNLIKELY (_g_dbus_debug_return ()))
815
0
    {
816
0
      _g_dbus_debug_print_lock ();
817
0
      g_print ("========================================================================\n"
818
0
               "GDBus-debug:Return:\n"
819
0
               " >>>> METHOD ERROR %s\n"
820
0
               "      message '%s'\n"
821
0
               "      in response to %s.%s()\n"
822
0
               "      on object %s\n"
823
0
               "      to name %s\n"
824
0
               "      reply-serial %d\n",
825
0
               error_name,
826
0
               error_message,
827
0
               invocation->interface_name, invocation->method_name,
828
0
               invocation->object_path,
829
0
               invocation->sender,
830
0
               g_dbus_message_get_serial (invocation->message));
831
0
      _g_dbus_debug_print_unlock ();
832
0
    }
833
834
0
  reply = g_dbus_message_new_method_error_literal (invocation->message,
835
0
                                                   error_name,
836
0
                                                   error_message);
837
0
  g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
838
0
  g_object_unref (reply);
839
840
0
out:
841
0
  g_object_unref (invocation);
842
0
}