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