| /* GDBus - GLib D-Bus Library | |
| * | |
| * Copyright (C) 2008-2010 Red Hat, Inc. | |
| * | |
| * SPDX-License-Identifier: LGPL-2.1-or-later | |
| * | |
| * This library is free software; you can redistribute it and/or | |
| * modify it under the terms of the GNU Lesser General Public | |
| * License as published by the Free Software Foundation; either | |
| * version 2.1 of the License, or (at your option) any later version. | |
| * | |
| * This library is distributed in the hope that it will be useful, | |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
| * Lesser General Public License for more details. | |
| * | |
| * You should have received a copy of the GNU Lesser General | |
| * Public License along with this library; if not, see <http://www.gnu.org/licenses/>. | |
| * | |
| * Author: David Zeuthen <davidz@redhat.com> | |
| */ | |
| #include "config.h" | |
| #include <stdlib.h> | |
| #include "gdbusutils.h" | |
| #include "gdbusconnection.h" | |
| #include "gdbusmessage.h" | |
| #include "gdbusmethodinvocation.h" | |
| #include "gdbusintrospection.h" | |
| #include "gdbuserror.h" | |
| #include "gdbusprivate.h" | |
| #include "gioerror.h" | |
| #ifdef G_OS_UNIX | |
| #include "gunixfdlist.h" | |
| #endif | |
| #include "glibintl.h" | |
| /** | |
| * GDBusMethodInvocation: | |
| * | |
| * Instances of the `GDBusMethodInvocation` class are used when | |
| * handling D-Bus method calls. It provides a way to asynchronously | |
| * return results and errors. | |
| * | |
| * The normal way to obtain a `GDBusMethodInvocation` object is to receive | |
| * it as an argument to the `handle_method_call()` function in a | |
| * [type@Gio.DBusInterfaceVTable] that was passed to | |
| * [method@Gio.DBusConnection.register_object]. | |
| * | |
| * Since: 2.26 | |
| */ | |
| typedef struct _GDBusMethodInvocationClass GDBusMethodInvocationClass; | |
| /** | |
| * GDBusMethodInvocationClass: | |
| * | |
| * Class structure for #GDBusMethodInvocation. | |
| * | |
| * Since: 2.26 | |
| */ | |
| struct _GDBusMethodInvocationClass | |
| { | |
| /*< private >*/ | |
| GObjectClass parent_class; | |
| }; | |
| struct _GDBusMethodInvocation | |
| { | |
| /*< private >*/ | |
| GObject parent_instance; | |
| /* construct-only properties */ | |
| gchar *sender; | |
| gchar *object_path; | |
| gchar *interface_name; | |
| gchar *method_name; | |
| GDBusMethodInfo *method_info; | |
| GDBusPropertyInfo *property_info; | |
| GDBusConnection *connection; | |
| GDBusMessage *message; | |
| GVariant *parameters; | |
| gpointer user_data; | |
| }; | |
| G_DEFINE_TYPE (GDBusMethodInvocation, g_dbus_method_invocation, G_TYPE_OBJECT) | |
| static void | |
| g_dbus_method_invocation_finalize (GObject *object) | |
| { | |
| GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (object); | |
| g_free (invocation->sender); | |
| g_free (invocation->object_path); | |
| g_free (invocation->interface_name); | |
| g_free (invocation->method_name); | |
| if (invocation->method_info) | |
| g_dbus_method_info_unref (invocation->method_info); | |
| if (invocation->property_info) | |
| g_dbus_property_info_unref (invocation->property_info); | |
| g_object_unref (invocation->connection); | |
| g_object_unref (invocation->message); | |
| g_variant_unref (invocation->parameters); | |
| G_OBJECT_CLASS (g_dbus_method_invocation_parent_class)->finalize (object); | |
| } | |
| static void | |
| g_dbus_method_invocation_class_init (GDBusMethodInvocationClass *klass) | |
| { | |
| GObjectClass *gobject_class = G_OBJECT_CLASS (klass); | |
| gobject_class->finalize = g_dbus_method_invocation_finalize; | |
| } | |
| static void | |
| g_dbus_method_invocation_init (GDBusMethodInvocation *invocation) | |
| { | |
| } | |
| /** | |
| * g_dbus_method_invocation_get_sender: | |
| * @invocation: A #GDBusMethodInvocation. | |
| * | |
| * Gets the bus name that invoked the method. | |
| * | |
| * Returns: A string. Do not free, it is owned by @invocation. | |
| * | |
| * Since: 2.26 | |
| */ | |
| const gchar * | |
| g_dbus_method_invocation_get_sender (GDBusMethodInvocation *invocation) | |
| { | |
| g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL); | |
| return invocation->sender; | |
| } | |
| /** | |
| * g_dbus_method_invocation_get_object_path: | |
| * @invocation: A #GDBusMethodInvocation. | |
| * | |
| * Gets the object path the method was invoked on. | |
| * | |
| * Returns: A string. Do not free, it is owned by @invocation. | |
| * | |
| * Since: 2.26 | |
| */ | |
| const gchar * | |
| g_dbus_method_invocation_get_object_path (GDBusMethodInvocation *invocation) | |
| { | |
| g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL); | |
| return invocation->object_path; | |
| } | |
| /** | |
| * g_dbus_method_invocation_get_interface_name: | |
| * @invocation: A #GDBusMethodInvocation. | |
| * | |
| * Gets the name of the D-Bus interface the method was invoked on. | |
| * | |
| * If this method call is a property Get, Set or GetAll call that has | |
| * been redirected to the method call handler then | |
| * "org.freedesktop.DBus.Properties" will be returned. See | |
| * #GDBusInterfaceVTable for more information. | |
| * | |
| * Returns: A string. Do not free, it is owned by @invocation. | |
| * | |
| * Since: 2.26 | |
| */ | |
| const gchar * | |
| g_dbus_method_invocation_get_interface_name (GDBusMethodInvocation *invocation) | |
| { | |
| g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL); | |
| return invocation->interface_name; | |
| } | |
| /** | |
| * g_dbus_method_invocation_get_method_info: | |
| * @invocation: A #GDBusMethodInvocation. | |
| * | |
| * Gets information about the method call, if any. | |
| * | |
| * If this method invocation is a property Get, Set or GetAll call that | |
| * has been redirected to the method call handler then %NULL will be | |
| * returned. See g_dbus_method_invocation_get_property_info() and | |
| * #GDBusInterfaceVTable for more information. | |
| * | |
| * Returns: (nullable): A #GDBusMethodInfo or %NULL. Do not free, it is owned by @invocation. | |
| * | |
| * Since: 2.26 | |
| */ | |
| const GDBusMethodInfo * | |
| g_dbus_method_invocation_get_method_info (GDBusMethodInvocation *invocation) | |
| { | |
| g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL); | |
| return invocation->method_info; | |
| } | |
| /** | |
| * g_dbus_method_invocation_get_property_info: | |
| * @invocation: A #GDBusMethodInvocation | |
| * | |
| * Gets information about the property that this method call is for, if | |
| * any. | |
| * | |
| * This will only be set in the case of an invocation in response to a | |
| * property Get or Set call that has been directed to the method call | |
| * handler for an object on account of its property_get() or | |
| * property_set() vtable pointers being unset. | |
| * | |
| * See #GDBusInterfaceVTable for more information. | |
| * | |
| * If the call was GetAll, %NULL will be returned. | |
| * | |
| * Returns: (nullable) (transfer none): a #GDBusPropertyInfo or %NULL | |
| * | |
| * Since: 2.38 | |
| */ | |
| const GDBusPropertyInfo * | |
| g_dbus_method_invocation_get_property_info (GDBusMethodInvocation *invocation) | |
| { | |
| g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL); | |
| return invocation->property_info; | |
| } | |
| /** | |
| * g_dbus_method_invocation_get_method_name: | |
| * @invocation: A #GDBusMethodInvocation. | |
| * | |
| * Gets the name of the method that was invoked. | |
| * | |
| * Returns: A string. Do not free, it is owned by @invocation. | |
| * | |
| * Since: 2.26 | |
| */ | |
| const gchar * | |
| g_dbus_method_invocation_get_method_name (GDBusMethodInvocation *invocation) | |
| { | |
| g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL); | |
| return invocation->method_name; | |
| } | |
| /** | |
| * g_dbus_method_invocation_get_connection: | |
| * @invocation: A #GDBusMethodInvocation. | |
| * | |
| * Gets the #GDBusConnection the method was invoked on. | |
| * | |
| * Returns: (transfer none):A #GDBusConnection. Do not free, it is owned by @invocation. | |
| * | |
| * Since: 2.26 | |
| */ | |
| GDBusConnection * | |
| g_dbus_method_invocation_get_connection (GDBusMethodInvocation *invocation) | |
| { | |
| g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL); | |
| return invocation->connection; | |
| } | |
| /** | |
| * g_dbus_method_invocation_get_message: | |
| * @invocation: A #GDBusMethodInvocation. | |
| * | |
| * Gets the #GDBusMessage for the method invocation. This is useful if | |
| * you need to use low-level protocol features, such as UNIX file | |
| * descriptor passing, that cannot be properly expressed in the | |
| * #GVariant API. | |
| * | |
| * See this [server][gdbus-server] and [client][gdbus-unix-fd-client] | |
| * for an example of how to use this low-level API to send and receive | |
| * UNIX file descriptors. | |
| * | |
| * Returns: (transfer none): #GDBusMessage. Do not free, it is owned by @invocation. | |
| * | |
| * Since: 2.26 | |
| */ | |
| GDBusMessage * | |
| g_dbus_method_invocation_get_message (GDBusMethodInvocation *invocation) | |
| { | |
| g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL); | |
| return invocation->message; | |
| } | |
| /** | |
| * g_dbus_method_invocation_get_parameters: | |
| * @invocation: A #GDBusMethodInvocation. | |
| * | |
| * Gets the parameters of the method invocation. If there are no input | |
| * parameters then this will return a GVariant with 0 children rather than NULL. | |
| * | |
| * Returns: (transfer none): A #GVariant tuple. Do not unref this because it is owned by @invocation. | |
| * | |
| * Since: 2.26 | |
| */ | |
| GVariant * | |
| g_dbus_method_invocation_get_parameters (GDBusMethodInvocation *invocation) | |
| { | |
| g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL); | |
| return invocation->parameters; | |
| } | |
| /** | |
| * g_dbus_method_invocation_get_user_data: (skip) | |
| * @invocation: A #GDBusMethodInvocation. | |
| * | |
| * Gets the @user_data #gpointer passed to g_dbus_connection_register_object(). | |
| * | |
| * Returns: A #gpointer. | |
| * | |
| * Since: 2.26 | |
| */ | |
| gpointer | |
| g_dbus_method_invocation_get_user_data (GDBusMethodInvocation *invocation) | |
| { | |
| g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL); | |
| return invocation->user_data; | |
| } | |
| /* < internal > | |
| * _g_dbus_method_invocation_new: | |
| * @sender: (nullable): The bus name that invoked the method or %NULL if @connection is not a bus connection. | |
| * @object_path: The object path the method was invoked on. | |
| * @interface_name: The name of the D-Bus interface the method was invoked on. | |
| * @method_name: The name of the method that was invoked. | |
| * @method_info: (nullable): Information about the method call or %NULL. | |
| * @property_info: (nullable): Information about the property or %NULL. | |
| * @connection: The #GDBusConnection the method was invoked on. | |
| * @message: The D-Bus message as a #GDBusMessage. | |
| * @parameters: The parameters as a #GVariant tuple. | |
| * @user_data: The @user_data #gpointer passed to g_dbus_connection_register_object(). | |
| * | |
| * Creates a new #GDBusMethodInvocation object. | |
| * | |
| * Returns: A #GDBusMethodInvocation. Free with g_object_unref(). | |
| * | |
| * Since: 2.26 | |
| */ | |
| GDBusMethodInvocation * | |
| _g_dbus_method_invocation_new (const gchar *sender, | |
| const gchar *object_path, | |
| const gchar *interface_name, | |
| const gchar *method_name, | |
| const GDBusMethodInfo *method_info, | |
| const GDBusPropertyInfo *property_info, | |
| GDBusConnection *connection, | |
| GDBusMessage *message, | |
| GVariant *parameters, | |
| gpointer user_data) | |
| { | |
| GDBusMethodInvocation *invocation; | |
| g_return_val_if_fail (sender == NULL || g_dbus_is_name (sender), NULL); | |
| g_return_val_if_fail (g_variant_is_object_path (object_path), NULL); | |
| g_return_val_if_fail (interface_name == NULL || g_dbus_is_interface_name (interface_name), NULL); | |
| g_return_val_if_fail (g_dbus_is_member_name (method_name), NULL); | |
| g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL); | |
| g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL); | |
| g_return_val_if_fail (g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL); | |
| invocation = G_DBUS_METHOD_INVOCATION (g_object_new (G_TYPE_DBUS_METHOD_INVOCATION, NULL)); | |
| invocation->sender = g_strdup (sender); | |
| invocation->object_path = g_strdup (object_path); | |
| invocation->interface_name = g_strdup (interface_name); | |
| invocation->method_name = g_strdup (method_name); | |
| if (method_info) | |
| invocation->method_info = g_dbus_method_info_ref ((GDBusMethodInfo *)method_info); | |
| if (property_info) | |
| invocation->property_info = g_dbus_property_info_ref ((GDBusPropertyInfo *)property_info); | |
| invocation->connection = g_object_ref (connection); | |
| invocation->message = g_object_ref (message); | |
| invocation->parameters = g_variant_ref (parameters); | |
| invocation->user_data = user_data; | |
| return invocation; | |
| } | |
| /* ---------------------------------------------------------------------------------------------------- */ | |
| static void | |
| g_dbus_method_invocation_return_value_internal (GDBusMethodInvocation *invocation, | |
| GVariant *parameters, | |
| GUnixFDList *fd_list) | |
| { | |
| GDBusMessage *reply; | |
| GError *error; | |
| g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); | |
| g_return_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE)); | |
| if (g_dbus_message_get_flags (invocation->message) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED) | |
| goto out; | |
| if (parameters == NULL) | |
| parameters = g_variant_new_tuple (NULL, 0); | |
| /* if we have introspection data, check that the signature of @parameters is correct */ | |
| if (invocation->method_info != NULL) | |
| { | |
| GVariantType *type; | |
| type = _g_dbus_compute_complete_signature (invocation->method_info->out_args); | |
| if (!g_variant_is_of_type (parameters, type)) | |
| { | |
| gchar *type_string = g_variant_type_dup_string (type); | |
| g_warning ("Type of return value is incorrect: expected '%s', got '%s'", | |
| type_string, g_variant_get_type_string (parameters)); | |
| g_variant_type_free (type); | |
| g_free (type_string); | |
| goto out; | |
| } | |
| g_variant_type_free (type); | |
| } | |
| /* property_info is only non-NULL if set that way from | |
| * GDBusConnection, so this must be the case of async property | |
| * handling on either 'Get' or 'Set'. | |
| * | |
| * property_info is NULL for 'GetAll'. | |
| */ | |
| if (invocation->property_info != NULL) | |
| { | |
| if (g_str_equal (invocation->method_name, "Get")) | |
| { | |
| GVariant *nested; | |
| if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(v)"))) | |
| { | |
| g_warning ("Type of return value for property 'Get' call should be '(v)' but got '%s'", | |
| g_variant_get_type_string (parameters)); | |
| goto out; | |
| } | |
| /* Go deeper and make sure that the value inside of the | |
| * variant matches the property type. | |
| */ | |
| g_variant_get (parameters, "(v)", &nested); | |
| if (!g_str_equal (g_variant_get_type_string (nested), invocation->property_info->signature)) | |
| { | |
| g_warning ("Value returned from property 'Get' call for '%s' should be '%s' but is '%s'", | |
| invocation->property_info->name, invocation->property_info->signature, | |
| g_variant_get_type_string (nested)); | |
| g_variant_unref (nested); | |
| goto out; | |
| } | |
| g_variant_unref (nested); | |
| } | |
| else if (g_str_equal (invocation->method_name, "Set")) | |
| { | |
| if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE_UNIT)) | |
| { | |
| g_warning ("Type of return value for property 'Set' call should be '()' but got '%s'", | |
| g_variant_get_type_string (parameters)); | |
| goto out; | |
| } | |
| } | |
| else | |
| g_assert_not_reached (); | |
| } | |
| else if (g_str_equal (invocation->interface_name, DBUS_INTERFACE_PROPERTIES) && | |
| g_str_equal (invocation->method_name, "GetAll")) | |
| { | |
| if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(a{sv})"))) | |
| { | |
| g_warning ("Type of return value for property 'GetAll' call should be '(a{sv})' but got '%s'", | |
| g_variant_get_type_string (parameters)); | |
| goto out; | |
| } | |
| /* Could iterate the list of properties and make sure that all | |
| * of them are actually on the interface and with the correct | |
| * types, but let's not do that for now... | |
| */ | |
| } | |
| if (G_UNLIKELY (_g_dbus_debug_return ())) | |
| { | |
| _g_dbus_debug_print_lock (); | |
| g_print ("========================================================================\n" | |
| "GDBus-debug:Return:\n" | |
| " >>>> METHOD RETURN\n" | |
| " in response to %s.%s()\n" | |
| " on object %s\n" | |
| " to name %s\n" | |
| " reply-serial %d\n", | |
| invocation->interface_name, invocation->method_name, | |
| invocation->object_path, | |
| invocation->sender, | |
| g_dbus_message_get_serial (invocation->message)); | |
| _g_dbus_debug_print_unlock (); | |
| } | |
| reply = g_dbus_message_new_method_reply (invocation->message); | |
| g_dbus_message_set_body (reply, g_steal_pointer (¶meters)); | |
| #ifdef G_OS_UNIX | |
| if (fd_list != NULL) | |
| g_dbus_message_set_unix_fd_list (reply, fd_list); | |
| #endif | |
| error = NULL; | |
| if (!g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error)) | |
| { | |
| if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED)) | |
| g_warning ("Error sending message: %s", error->message); | |
| g_error_free (error); | |
| } | |
| g_object_unref (reply); | |
| out: | |
| if (parameters != NULL) | |
| { | |
| g_variant_ref_sink (parameters); | |
| g_variant_unref (parameters); | |
| } | |
| g_object_unref (invocation); | |
| } | |
| /** | |
| * g_dbus_method_invocation_return_value: | |
| * @invocation: (transfer full): A #GDBusMethodInvocation. | |
| * @parameters: (nullable): A #GVariant tuple with out parameters for the method or %NULL if not passing any parameters. | |
| * | |
| * Finishes handling a D-Bus method call by returning @parameters. | |
| * If the @parameters GVariant is floating, it is consumed. | |
| * | |
| * It is an error if @parameters is not of the right format: it must be a tuple | |
| * containing the out-parameters of the D-Bus method. Even if the method has a | |
| * single out-parameter, it must be contained in a tuple. If the method has no | |
| * out-parameters, @parameters may be %NULL or an empty tuple. | |
| * | |
| * |[<!-- language="C" --> | |
| * GDBusMethodInvocation *invocation = some_invocation; | |
| * g_autofree gchar *result_string = NULL; | |
| * g_autoptr (GError) error = NULL; | |
| * | |
| * result_string = calculate_result (&error); | |
| * | |
| * if (error != NULL) | |
| * g_dbus_method_invocation_return_gerror (invocation, error); | |
| * else | |
| * g_dbus_method_invocation_return_value (invocation, | |
| * g_variant_new ("(s)", result_string)); | |
| * | |
| * // Do not free @invocation here; returning a value does that | |
| * ]| | |
| * | |
| * This method will take ownership of @invocation. See | |
| * #GDBusInterfaceVTable for more information about the ownership of | |
| * @invocation. | |
| * | |
| * Since 2.48, if the method call requested for a reply not to be sent | |
| * then this call will sink @parameters and free @invocation, but | |
| * otherwise do nothing (as per the recommendations of the D-Bus | |
| * specification). | |
| * | |
| * Since: 2.26 | |
| */ | |
| void | |
| g_dbus_method_invocation_return_value (GDBusMethodInvocation *invocation, | |
| GVariant *parameters) | |
| { | |
| g_dbus_method_invocation_return_value_internal (invocation, parameters, NULL); | |
| } | |
| #ifdef G_OS_UNIX | |
| /** | |
| * g_dbus_method_invocation_return_value_with_unix_fd_list: | |
| * @invocation: (transfer full): A #GDBusMethodInvocation. | |
| * @parameters: (nullable): A #GVariant tuple with out parameters for the method or %NULL if not passing any parameters. | |
| * @fd_list: (nullable): A #GUnixFDList or %NULL. | |
| * | |
| * Like g_dbus_method_invocation_return_value() but also takes a #GUnixFDList. | |
| * | |
| * This method is only available on UNIX. | |
| * | |
| * This method will take ownership of @invocation. See | |
| * #GDBusInterfaceVTable for more information about the ownership of | |
| * @invocation. | |
| * | |
| * Since: 2.30 | |
| */ | |
| void | |
| g_dbus_method_invocation_return_value_with_unix_fd_list (GDBusMethodInvocation *invocation, | |
| GVariant *parameters, | |
| GUnixFDList *fd_list) | |
| { | |
| g_dbus_method_invocation_return_value_internal (invocation, parameters, fd_list); | |
| } | |
| #endif | |
| /* ---------------------------------------------------------------------------------------------------- */ | |
| /** | |
| * g_dbus_method_invocation_return_error: | |
| * @invocation: (transfer full): A #GDBusMethodInvocation. | |
| * @domain: A #GQuark for the #GError error domain. | |
| * @code: The error code. | |
| * @format: printf()-style format. | |
| * @...: Parameters for @format. | |
| * | |
| * Finishes handling a D-Bus method call by returning an error. | |
| * | |
| * See g_dbus_error_encode_gerror() for details about what error name | |
| * will be returned on the wire. In a nutshell, if the given error is | |
| * registered using g_dbus_error_register_error() the name given | |
| * during registration is used. Otherwise, a name of the form | |
| * `org.gtk.GDBus.UnmappedGError.Quark...` is used. This provides | |
| * transparent mapping of #GError between applications using GDBus. | |
| * | |
| * If you are writing an application intended to be portable, | |
| * always register errors with g_dbus_error_register_error() | |
| * or use g_dbus_method_invocation_return_dbus_error(). | |
| * | |
| * This method will take ownership of @invocation. See | |
| * #GDBusInterfaceVTable for more information about the ownership of | |
| * @invocation. | |
| * | |
| * Since 2.48, if the method call requested for a reply not to be sent | |
| * then this call will free @invocation but otherwise do nothing (as per | |
| * the recommendations of the D-Bus specification). | |
| * | |
| * Since: 2.26 | |
| */ | |
| void | |
| g_dbus_method_invocation_return_error (GDBusMethodInvocation *invocation, | |
| GQuark domain, | |
| gint code, | |
| const gchar *format, | |
| ...) | |
| { | |
| va_list var_args; | |
| g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); | |
| g_return_if_fail (format != NULL); | |
| va_start (var_args, format); | |
| g_dbus_method_invocation_return_error_valist (invocation, | |
| domain, | |
| code, | |
| format, | |
| var_args); | |
| va_end (var_args); | |
| } | |
| /** | |
| * g_dbus_method_invocation_return_error_valist: | |
| * @invocation: (transfer full): A #GDBusMethodInvocation. | |
| * @domain: A #GQuark for the #GError error domain. | |
| * @code: The error code. | |
| * @format: printf()-style format. | |
| * @var_args: #va_list of parameters for @format. | |
| * | |
| * Like g_dbus_method_invocation_return_error() but intended for | |
| * language bindings. | |
| * | |
| * This method will take ownership of @invocation. See | |
| * #GDBusInterfaceVTable for more information about the ownership of | |
| * @invocation. | |
| * | |
| * Since: 2.26 | |
| */ | |
| void | |
| g_dbus_method_invocation_return_error_valist (GDBusMethodInvocation *invocation, | |
| GQuark domain, | |
| gint code, | |
| const gchar *format, | |
| va_list var_args) | |
| { | |
| gchar *literal_message; | |
| g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); | |
| g_return_if_fail (format != NULL); | |
| literal_message = g_strdup_vprintf (format, var_args); | |
| g_dbus_method_invocation_return_error_literal (invocation, | |
| domain, | |
| code, | |
| literal_message); | |
| g_free (literal_message); | |
| } | |
| /** | |
| * g_dbus_method_invocation_return_error_literal: | |
| * @invocation: (transfer full): A #GDBusMethodInvocation. | |
| * @domain: A #GQuark for the #GError error domain. | |
| * @code: The error code. | |
| * @message: The error message. | |
| * | |
| * Like g_dbus_method_invocation_return_error() but without printf()-style formatting. | |
| * | |
| * This method will take ownership of @invocation. See | |
| * #GDBusInterfaceVTable for more information about the ownership of | |
| * @invocation. | |
| * | |
| * Since: 2.26 | |
| */ | |
| void | |
| g_dbus_method_invocation_return_error_literal (GDBusMethodInvocation *invocation, | |
| GQuark domain, | |
| gint code, | |
| const gchar *message) | |
| { | |
| GError *error; | |
| g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); | |
| g_return_if_fail (message != NULL); | |
| error = g_error_new_literal (domain, code, message); | |
| g_dbus_method_invocation_return_gerror (invocation, error); | |
| g_error_free (error); | |
| } | |
| /** | |
| * g_dbus_method_invocation_return_gerror: | |
| * @invocation: (transfer full): A #GDBusMethodInvocation. | |
| * @error: A #GError. | |
| * | |
| * Like g_dbus_method_invocation_return_error() but takes a #GError | |
| * instead of the error domain, error code and message. | |
| * | |
| * This method will take ownership of @invocation. See | |
| * #GDBusInterfaceVTable for more information about the ownership of | |
| * @invocation. | |
| * | |
| * Since: 2.26 | |
| */ | |
| void | |
| g_dbus_method_invocation_return_gerror (GDBusMethodInvocation *invocation, | |
| const GError *error) | |
| { | |
| gchar *dbus_error_name; | |
| g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); | |
| g_return_if_fail (error != NULL); | |
| dbus_error_name = g_dbus_error_encode_gerror (error); | |
| g_dbus_method_invocation_return_dbus_error (invocation, | |
| dbus_error_name, | |
| error->message); | |
| g_free (dbus_error_name); | |
| } | |
| /** | |
| * g_dbus_method_invocation_take_error: (skip) | |
| * @invocation: (transfer full): A #GDBusMethodInvocation. | |
| * @error: (transfer full): A #GError. | |
| * | |
| * Like g_dbus_method_invocation_return_gerror() but takes ownership | |
| * of @error so the caller does not need to free it. | |
| * | |
| * This method will take ownership of @invocation. See | |
| * #GDBusInterfaceVTable for more information about the ownership of | |
| * @invocation. | |
| * | |
| * Since: 2.30 | |
| */ | |
| void | |
| g_dbus_method_invocation_take_error (GDBusMethodInvocation *invocation, | |
| GError *error) | |
| { | |
| g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); | |
| g_return_if_fail (error != NULL); | |
| g_dbus_method_invocation_return_gerror (invocation, error); | |
| g_error_free (error); | |
| } | |
| /** | |
| * g_dbus_method_invocation_return_dbus_error: | |
| * @invocation: (transfer full): A #GDBusMethodInvocation. | |
| * @error_name: A valid D-Bus error name. | |
| * @error_message: A valid D-Bus error message. | |
| * | |
| * Finishes handling a D-Bus method call by returning an error. | |
| * | |
| * This method will take ownership of @invocation. See | |
| * #GDBusInterfaceVTable for more information about the ownership of | |
| * @invocation. | |
| * | |
| * Since: 2.26 | |
| */ | |
| void | |
| g_dbus_method_invocation_return_dbus_error (GDBusMethodInvocation *invocation, | |
| const gchar *error_name, | |
| const gchar *error_message) | |
| { | |
| GDBusMessage *reply; | |
| g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); | |
| g_return_if_fail (error_name != NULL && g_dbus_is_name (error_name)); | |
| g_return_if_fail (error_message != NULL); | |
| if (g_dbus_message_get_flags (invocation->message) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED) | |
| goto out; | |
| if (G_UNLIKELY (_g_dbus_debug_return ())) | |
| { | |
| _g_dbus_debug_print_lock (); | |
| g_print ("========================================================================\n" | |
| "GDBus-debug:Return:\n" | |
| " >>>> METHOD ERROR %s\n" | |
| " message '%s'\n" | |
| " in response to %s.%s()\n" | |
| " on object %s\n" | |
| " to name %s\n" | |
| " reply-serial %d\n", | |
| error_name, | |
| error_message, | |
| invocation->interface_name, invocation->method_name, | |
| invocation->object_path, | |
| invocation->sender, | |
| g_dbus_message_get_serial (invocation->message)); | |
| _g_dbus_debug_print_unlock (); | |
| } | |
| reply = g_dbus_message_new_method_error_literal (invocation->message, | |
| error_name, | |
| error_message); | |
| g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); | |
| g_object_unref (reply); | |
| out: | |
| g_object_unref (invocation); | |
| } |