2010-05-06 20:13:59 +02:00
|
|
|
/* GDBus - GLib D-Bus Library
|
|
|
|
*
|
2010-05-09 19:14:55 +02:00
|
|
|
* Copyright (C) 2008-2010 Red Hat, Inc.
|
2010-05-06 20:13:59 +02:00
|
|
|
*
|
|
|
|
* 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 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
|
2014-01-23 12:58:29 +01:00
|
|
|
* Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
2010-05-06 20:13:59 +02:00
|
|
|
*
|
|
|
|
* 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"
|
|
|
|
|
2011-07-21 22:03:27 +02:00
|
|
|
#ifdef G_OS_UNIX
|
|
|
|
#include "gunixfdlist.h"
|
|
|
|
#endif
|
|
|
|
|
2010-05-06 22:34:23 +02:00
|
|
|
#include "glibintl.h"
|
|
|
|
|
2010-05-06 20:13:59 +02:00
|
|
|
/**
|
|
|
|
* SECTION:gdbusmethodinvocation
|
|
|
|
* @short_description: Object for handling remote calls
|
2010-05-06 21:31:45 +02:00
|
|
|
* @include: gio/gio.h
|
2010-05-06 20:13:59 +02:00
|
|
|
*
|
|
|
|
* Instances of the #GDBusMethodInvocation class are used when
|
|
|
|
* handling D-Bus method calls. It provides a way to asynchronously
|
|
|
|
* return results and errors.
|
2010-05-09 07:44:11 +02:00
|
|
|
*
|
|
|
|
* The normal way to obtain a #GDBusMethodInvocation object is to receive
|
|
|
|
* it as an argument to the handle_method_call() function in a
|
|
|
|
* #GDBusInterfaceVTable that was passed to g_dbus_connection_register_object().
|
2010-05-06 20:13:59 +02:00
|
|
|
*/
|
|
|
|
|
2010-07-07 22:35:17 +02:00
|
|
|
typedef struct _GDBusMethodInvocationClass GDBusMethodInvocationClass;
|
|
|
|
|
2010-07-07 21:57:37 +02:00
|
|
|
/**
|
|
|
|
* GDBusMethodInvocationClass:
|
|
|
|
*
|
|
|
|
* Class structure for #GDBusMethodInvocation.
|
|
|
|
*
|
|
|
|
* Since: 2.26
|
|
|
|
*/
|
|
|
|
struct _GDBusMethodInvocationClass
|
|
|
|
{
|
|
|
|
/*< private >*/
|
|
|
|
GObjectClass parent_class;
|
|
|
|
};
|
|
|
|
|
2010-07-07 22:35:17 +02:00
|
|
|
/**
|
|
|
|
* GDBusMethodInvocation:
|
|
|
|
*
|
|
|
|
* The #GDBusMethodInvocation structure contains only private data and
|
|
|
|
* should only be accessed using the provided API.
|
|
|
|
*
|
|
|
|
* Since: 2.26
|
|
|
|
*/
|
|
|
|
struct _GDBusMethodInvocation
|
2010-05-06 20:13:59 +02:00
|
|
|
{
|
2010-07-07 22:35:17 +02:00
|
|
|
/*< private >*/
|
|
|
|
GObject parent_instance;
|
|
|
|
|
2010-05-06 20:13:59 +02:00
|
|
|
/* construct-only properties */
|
|
|
|
gchar *sender;
|
|
|
|
gchar *object_path;
|
|
|
|
gchar *interface_name;
|
|
|
|
gchar *method_name;
|
2013-03-07 18:44:44 +01:00
|
|
|
GDBusMethodInfo *method_info;
|
2013-04-17 15:28:05 +02:00
|
|
|
GDBusPropertyInfo *property_info;
|
2010-05-06 20:13:59 +02:00
|
|
|
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);
|
|
|
|
|
2010-07-07 22:35:17 +02:00
|
|
|
g_free (invocation->sender);
|
|
|
|
g_free (invocation->object_path);
|
|
|
|
g_free (invocation->interface_name);
|
|
|
|
g_free (invocation->method_name);
|
2013-03-07 18:44:44 +01:00
|
|
|
if (invocation->method_info)
|
|
|
|
g_dbus_method_info_unref (invocation->method_info);
|
2010-07-07 22:35:17 +02:00
|
|
|
g_object_unref (invocation->connection);
|
|
|
|
g_object_unref (invocation->message);
|
|
|
|
g_variant_unref (invocation->parameters);
|
2010-05-06 20:13:59 +02:00
|
|
|
|
2010-05-10 04:13:18 +02:00
|
|
|
G_OBJECT_CLASS (g_dbus_method_invocation_parent_class)->finalize (object);
|
2010-05-06 20:13:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
g_dbus_method_invocation_class_init (GDBusMethodInvocationClass *klass)
|
|
|
|
{
|
|
|
|
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
2010-05-12 04:51:14 +02:00
|
|
|
gobject_class->finalize = g_dbus_method_invocation_finalize;
|
2010-05-06 20:13:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
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.
|
2010-05-06 22:02:08 +02:00
|
|
|
*
|
|
|
|
* Since: 2.26
|
2010-05-06 20:13:59 +02:00
|
|
|
*/
|
|
|
|
const gchar *
|
|
|
|
g_dbus_method_invocation_get_sender (GDBusMethodInvocation *invocation)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
|
2010-07-07 22:35:17 +02:00
|
|
|
return invocation->sender;
|
2010-05-06 20:13:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
2010-05-06 22:02:08 +02:00
|
|
|
*
|
|
|
|
* Since: 2.26
|
2010-05-06 20:13:59 +02:00
|
|
|
*/
|
|
|
|
const gchar *
|
|
|
|
g_dbus_method_invocation_get_object_path (GDBusMethodInvocation *invocation)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
|
2010-07-07 22:35:17 +02:00
|
|
|
return invocation->object_path;
|
2010-05-06 20:13:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* g_dbus_method_invocation_get_interface_name:
|
|
|
|
* @invocation: A #GDBusMethodInvocation.
|
|
|
|
*
|
|
|
|
* Gets the name of the D-Bus interface the method was invoked on.
|
|
|
|
*
|
2013-04-17 15:30:15 +02:00
|
|
|
* 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.
|
|
|
|
*
|
2010-05-06 20:13:59 +02:00
|
|
|
* Returns: A string. Do not free, it is owned by @invocation.
|
2010-05-06 22:02:08 +02:00
|
|
|
*
|
|
|
|
* Since: 2.26
|
2010-05-06 20:13:59 +02:00
|
|
|
*/
|
|
|
|
const gchar *
|
|
|
|
g_dbus_method_invocation_get_interface_name (GDBusMethodInvocation *invocation)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
|
2010-07-07 22:35:17 +02:00
|
|
|
return invocation->interface_name;
|
2010-05-06 20:13:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* g_dbus_method_invocation_get_method_info:
|
|
|
|
* @invocation: A #GDBusMethodInvocation.
|
|
|
|
*
|
|
|
|
* Gets information about the method call, if any.
|
|
|
|
*
|
2013-04-17 15:30:15 +02:00
|
|
|
* 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.
|
|
|
|
*
|
2010-05-06 20:13:59 +02:00
|
|
|
* Returns: A #GDBusMethodInfo or %NULL. Do not free, it is owned by @invocation.
|
2010-05-06 22:02:08 +02:00
|
|
|
*
|
|
|
|
* Since: 2.26
|
2010-05-06 20:13:59 +02:00
|
|
|
*/
|
|
|
|
const GDBusMethodInfo *
|
|
|
|
g_dbus_method_invocation_get_method_info (GDBusMethodInvocation *invocation)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
|
2010-07-07 22:35:17 +02:00
|
|
|
return invocation->method_info;
|
2010-05-06 20:13:59 +02:00
|
|
|
}
|
|
|
|
|
2013-04-17 15:28:05 +02:00
|
|
|
/**
|
|
|
|
* g_dbus_method_invocation_get_property_info:
|
|
|
|
* @invocation: A #GDBusMethodInvocation
|
|
|
|
*
|
|
|
|
* Gets information about the property that this method call is for, if
|
|
|
|
* any.
|
|
|
|
*
|
2013-04-17 15:30:15 +02:00
|
|
|
* 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.
|
|
|
|
*
|
2013-04-17 15:28:05 +02:00
|
|
|
* Returns: (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;
|
|
|
|
}
|
|
|
|
|
2010-05-06 20:13:59 +02:00
|
|
|
/**
|
|
|
|
* 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.
|
2010-05-06 22:02:08 +02:00
|
|
|
*
|
|
|
|
* Since: 2.26
|
2010-05-06 20:13:59 +02:00
|
|
|
*/
|
|
|
|
const gchar *
|
|
|
|
g_dbus_method_invocation_get_method_name (GDBusMethodInvocation *invocation)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
|
2010-07-07 22:35:17 +02:00
|
|
|
return invocation->method_name;
|
2010-05-06 20:13:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* g_dbus_method_invocation_get_connection:
|
|
|
|
* @invocation: A #GDBusMethodInvocation.
|
|
|
|
*
|
|
|
|
* Gets the #GDBusConnection the method was invoked on.
|
|
|
|
*
|
2010-09-24 23:24:41 +02:00
|
|
|
* Returns: (transfer none):A #GDBusConnection. Do not free, it is owned by @invocation.
|
2010-05-06 22:02:08 +02:00
|
|
|
*
|
|
|
|
* Since: 2.26
|
2010-05-06 20:13:59 +02:00
|
|
|
*/
|
|
|
|
GDBusConnection *
|
|
|
|
g_dbus_method_invocation_get_connection (GDBusMethodInvocation *invocation)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
|
2010-07-07 22:35:17 +02:00
|
|
|
return invocation->connection;
|
2010-05-06 20:13:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*
|
2014-02-08 18:26:56 +01:00
|
|
|
* 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.
|
2010-05-06 20:13:59 +02:00
|
|
|
*
|
2010-09-24 23:24:41 +02:00
|
|
|
* Returns: (transfer none): #GDBusMessage. Do not free, it is owned by @invocation.
|
2010-05-06 22:02:08 +02:00
|
|
|
*
|
|
|
|
* Since: 2.26
|
2010-05-06 20:13:59 +02:00
|
|
|
*/
|
|
|
|
GDBusMessage *
|
|
|
|
g_dbus_method_invocation_get_message (GDBusMethodInvocation *invocation)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
|
2010-07-07 22:35:17 +02:00
|
|
|
return invocation->message;
|
2010-05-06 20:13:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* g_dbus_method_invocation_get_parameters:
|
|
|
|
* @invocation: A #GDBusMethodInvocation.
|
|
|
|
*
|
2011-04-02 15:42:11 +02:00
|
|
|
* 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.
|
2010-05-06 20:13:59 +02:00
|
|
|
*
|
2011-04-02 15:42:11 +02:00
|
|
|
* Returns: (transfer none): A #GVariant tuple. Do not unref this because it is owned by @invocation.
|
2010-05-06 22:02:08 +02:00
|
|
|
*
|
|
|
|
* Since: 2.26
|
2010-05-06 20:13:59 +02:00
|
|
|
*/
|
|
|
|
GVariant *
|
|
|
|
g_dbus_method_invocation_get_parameters (GDBusMethodInvocation *invocation)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
|
2010-07-07 22:35:17 +02:00
|
|
|
return invocation->parameters;
|
2010-05-06 20:13:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
2010-09-24 23:24:41 +02:00
|
|
|
* g_dbus_method_invocation_get_user_data: (skip)
|
2010-05-06 20:13:59 +02:00
|
|
|
* @invocation: A #GDBusMethodInvocation.
|
|
|
|
*
|
|
|
|
* Gets the @user_data #gpointer passed to g_dbus_connection_register_object().
|
|
|
|
*
|
|
|
|
* Returns: A #gpointer.
|
2010-05-06 22:02:08 +02:00
|
|
|
*
|
|
|
|
* Since: 2.26
|
2010-05-06 20:13:59 +02:00
|
|
|
*/
|
|
|
|
gpointer
|
|
|
|
g_dbus_method_invocation_get_user_data (GDBusMethodInvocation *invocation)
|
|
|
|
{
|
|
|
|
g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
|
2010-07-07 22:35:17 +02:00
|
|
|
return invocation->user_data;
|
2010-05-06 20:13:59 +02:00
|
|
|
}
|
|
|
|
|
2010-08-23 04:56:49 +02:00
|
|
|
/* < internal >
|
|
|
|
* _g_dbus_method_invocation_new:
|
2012-03-24 13:58:45 +01:00
|
|
|
* @sender: (allow-none): The bus name that invoked the method or %NULL if @connection is not a bus connection.
|
2010-05-06 20:13:59 +02:00
|
|
|
* @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.
|
2012-03-24 13:58:45 +01:00
|
|
|
* @method_info: (allow-none): Information about the method call or %NULL.
|
2013-04-17 15:28:05 +02:00
|
|
|
* @property_info: (allow-none): Information about the property or %NULL.
|
2010-05-06 20:13:59 +02:00
|
|
|
* @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().
|
2010-05-06 22:02:08 +02:00
|
|
|
*
|
|
|
|
* Since: 2.26
|
2010-05-06 20:13:59 +02:00
|
|
|
*/
|
|
|
|
GDBusMethodInvocation *
|
2013-04-17 15:28:05 +02:00
|
|
|
_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)
|
2010-05-06 20:13:59 +02:00
|
|
|
{
|
2010-05-12 04:51:14 +02:00
|
|
|
GDBusMethodInvocation *invocation;
|
|
|
|
|
2010-05-06 20:13:59 +02:00
|
|
|
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);
|
|
|
|
|
2010-05-12 04:51:14 +02:00
|
|
|
invocation = G_DBUS_METHOD_INVOCATION (g_object_new (G_TYPE_DBUS_METHOD_INVOCATION, NULL));
|
2010-07-07 22:35:17 +02:00
|
|
|
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);
|
2013-03-07 18:44:44 +01:00
|
|
|
if (method_info)
|
|
|
|
invocation->method_info = g_dbus_method_info_ref ((GDBusMethodInfo *)method_info);
|
2013-04-17 15:28:05 +02:00
|
|
|
if (property_info)
|
|
|
|
invocation->property_info = g_dbus_property_info_ref ((GDBusPropertyInfo *)property_info);
|
2010-07-07 22:35:17 +02:00
|
|
|
invocation->connection = g_object_ref (connection);
|
|
|
|
invocation->message = g_object_ref (message);
|
|
|
|
invocation->parameters = g_variant_ref (parameters);
|
|
|
|
invocation->user_data = user_data;
|
2010-05-12 04:51:14 +02:00
|
|
|
|
|
|
|
return invocation;
|
2010-05-06 20:13:59 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
|
2011-07-21 22:03:27 +02:00
|
|
|
static void
|
|
|
|
g_dbus_method_invocation_return_value_internal (GDBusMethodInvocation *invocation,
|
|
|
|
GVariant *parameters,
|
|
|
|
GUnixFDList *fd_list)
|
2010-05-06 20:13:59 +02:00
|
|
|
{
|
|
|
|
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));
|
|
|
|
|
2010-05-24 22:46:24 +02:00
|
|
|
if (parameters == NULL)
|
|
|
|
parameters = g_variant_new_tuple (NULL, 0);
|
2010-05-06 20:13:59 +02:00
|
|
|
|
|
|
|
/* if we have introspection data, check that the signature of @parameters is correct */
|
2010-07-07 22:35:17 +02:00
|
|
|
if (invocation->method_info != NULL)
|
2010-05-06 20:13:59 +02:00
|
|
|
{
|
2010-05-24 22:46:24 +02:00
|
|
|
GVariantType *type;
|
2010-05-06 20:13:59 +02:00
|
|
|
|
2010-07-07 22:35:17 +02:00
|
|
|
type = _g_dbus_compute_complete_signature (invocation->method_info->out_args);
|
2010-05-06 20:13:59 +02:00
|
|
|
|
2010-05-24 22:46:24 +02:00
|
|
|
if (!g_variant_is_of_type (parameters, type))
|
2010-05-06 20:13:59 +02:00
|
|
|
{
|
2010-05-24 22:46:24 +02:00
|
|
|
gchar *type_string = g_variant_type_dup_string (type);
|
|
|
|
|
2013-05-20 22:54:48 +02:00
|
|
|
g_warning ("Type of return value is incorrect: expected '%s', got '%s''",
|
2012-08-17 05:02:41 +02:00
|
|
|
type_string, g_variant_get_type_string (parameters));
|
2010-05-24 22:46:24 +02:00
|
|
|
g_variant_type_free (type);
|
|
|
|
g_free (type_string);
|
2010-05-06 20:13:59 +02:00
|
|
|
goto out;
|
|
|
|
}
|
2010-05-24 22:46:24 +02:00
|
|
|
g_variant_type_free (type);
|
2010-05-06 20:13:59 +02:00
|
|
|
}
|
|
|
|
|
2013-04-17 15:45:23 +02:00
|
|
|
/* 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', 'Set' or '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));
|
2013-06-22 19:41:12 +02:00
|
|
|
g_variant_unref (nested);
|
|
|
|
goto out;
|
2013-04-17 15:45:23 +02:00
|
|
|
}
|
|
|
|
g_variant_unref (nested);
|
|
|
|
}
|
|
|
|
|
|
|
|
else if (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...
|
|
|
|
*/
|
|
|
|
}
|
|
|
|
|
|
|
|
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 ();
|
|
|
|
}
|
|
|
|
|
2010-08-04 22:59:26 +02:00
|
|
|
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 ();
|
|
|
|
}
|
|
|
|
|
2010-07-07 22:35:17 +02:00
|
|
|
reply = g_dbus_message_new_method_reply (invocation->message);
|
2010-05-06 20:13:59 +02:00
|
|
|
g_dbus_message_set_body (reply, parameters);
|
2011-07-21 22:03:27 +02:00
|
|
|
|
|
|
|
#ifdef G_OS_UNIX
|
|
|
|
if (fd_list != NULL)
|
|
|
|
g_dbus_message_set_unix_fd_list (reply, fd_list);
|
|
|
|
#endif
|
|
|
|
|
2010-05-06 20:13:59 +02:00
|
|
|
error = NULL;
|
2010-07-19 22:07:57 +02:00
|
|
|
if (!g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error))
|
2010-05-06 20:13:59 +02:00
|
|
|
{
|
2015-08-19 22:21:46 +02:00
|
|
|
if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED))
|
gdbus: don't warn when returning a value on a closed connection
g_dbus_method_invocation_return_value(), etc, don't have GError
parameters (which makes sense since they won't usually return errors,
and there's not much you could do if they did), so in the rare case
when something does go wrong, they print a warning.
However, there is at least one situation where the warning is a bad
idea: if you are using private bus connections, and a client connects,
makes a request, and then disconnects before getting the response.
Given that there's nothing the caller can do to prevent this case from
getting hit (since the client might not disconnect until after the
call to g_dbus_method_invocation_return_value() starts) and given that
the server can never actually know for sure that the client has
received the response (it might disconnect after reading the response,
but before processing it), just kill the warning in this case.
https://bugzilla.gnome.org/show_bug.cgi?id=753839
2015-08-19 19:21:00 +02:00
|
|
|
g_warning ("Error sending message: %s", error->message);
|
2010-05-06 20:13:59 +02:00
|
|
|
g_error_free (error);
|
|
|
|
}
|
|
|
|
g_object_unref (reply);
|
|
|
|
|
|
|
|
out:
|
|
|
|
g_object_unref (invocation);
|
|
|
|
}
|
|
|
|
|
2011-07-21 22:03:27 +02:00
|
|
|
/**
|
|
|
|
* g_dbus_method_invocation_return_value:
|
|
|
|
* @invocation: (transfer full): A #GDBusMethodInvocation.
|
|
|
|
* @parameters: (allow-none): 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.
|
|
|
|
*
|
|
|
|
* This method will free @invocation, you cannot use it afterwards.
|
|
|
|
*
|
|
|
|
* Since: 2.26
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
g_dbus_method_invocation_return_value (GDBusMethodInvocation *invocation,
|
|
|
|
GVariant *parameters)
|
|
|
|
{
|
2011-08-17 10:01:14 +02:00
|
|
|
g_dbus_method_invocation_return_value_internal (invocation, parameters, NULL);
|
2011-07-21 22:03:27 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef G_OS_UNIX
|
|
|
|
/**
|
|
|
|
* g_dbus_method_invocation_return_value_with_unix_fd_list:
|
|
|
|
* @invocation: (transfer full): A #GDBusMethodInvocation.
|
|
|
|
* @parameters: (allow-none): A #GVariant tuple with out parameters for the method or %NULL if not passing any parameters.
|
|
|
|
* @fd_list: (allow-none): 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 free @invocation, you cannot use it afterwards.
|
|
|
|
*
|
|
|
|
* Since: 2.30
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
g_dbus_method_invocation_return_value_with_unix_fd_list (GDBusMethodInvocation *invocation,
|
|
|
|
GVariant *parameters,
|
|
|
|
GUnixFDList *fd_list)
|
|
|
|
{
|
2011-08-17 10:01:14 +02:00
|
|
|
g_dbus_method_invocation_return_value_internal (invocation, parameters, fd_list);
|
2011-07-21 22:03:27 +02:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2010-05-06 20:13:59 +02:00
|
|
|
/* ---------------------------------------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/**
|
|
|
|
* g_dbus_method_invocation_return_error:
|
2011-05-03 18:54:45 +02:00
|
|
|
* @invocation: (transfer full): A #GDBusMethodInvocation.
|
2010-05-06 20:13:59 +02:00
|
|
|
* @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
|
2014-02-06 14:04:52 +01:00
|
|
|
* `org.gtk.GDBus.UnmappedGError.Quark...` is used. This provides
|
|
|
|
* transparent mapping of #GError between applications using GDBus.
|
2010-05-06 20:13:59 +02:00
|
|
|
*
|
|
|
|
* If you are writing an application intended to be portable,
|
2014-02-01 02:34:33 +01:00
|
|
|
* always register errors with g_dbus_error_register_error()
|
2010-05-06 20:13:59 +02:00
|
|
|
* or use g_dbus_method_invocation_return_dbus_error().
|
|
|
|
*
|
|
|
|
* This method will free @invocation, you cannot use it afterwards.
|
2010-05-06 22:02:08 +02:00
|
|
|
*
|
|
|
|
* Since: 2.26
|
2010-05-06 20:13:59 +02:00
|
|
|
*/
|
|
|
|
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:
|
2011-05-03 18:54:45 +02:00
|
|
|
* @invocation: (transfer full): A #GDBusMethodInvocation.
|
2010-05-06 20:13:59 +02:00
|
|
|
* @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 free @invocation, you cannot use it afterwards.
|
2010-05-06 22:02:08 +02:00
|
|
|
*
|
|
|
|
* Since: 2.26
|
2010-05-06 20:13:59 +02:00
|
|
|
*/
|
|
|
|
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:
|
2011-05-03 18:54:45 +02:00
|
|
|
* @invocation: (transfer full): A #GDBusMethodInvocation.
|
2010-05-06 20:13:59 +02:00
|
|
|
* @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 free @invocation, you cannot use it afterwards.
|
2010-05-06 22:02:08 +02:00
|
|
|
*
|
|
|
|
* Since: 2.26
|
2010-05-06 20:13:59 +02:00
|
|
|
*/
|
|
|
|
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:
|
2011-05-03 18:54:45 +02:00
|
|
|
* @invocation: (transfer full): A #GDBusMethodInvocation.
|
2010-05-06 20:13:59 +02:00
|
|
|
* @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 free @invocation, you cannot use it afterwards.
|
2010-05-06 22:02:08 +02:00
|
|
|
*
|
|
|
|
* Since: 2.26
|
2010-05-06 20:13:59 +02:00
|
|
|
*/
|
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2011-05-12 02:57:54 +02:00
|
|
|
/**
|
|
|
|
* 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 free @invocation, you cannot use it afterwards.
|
|
|
|
*
|
|
|
|
* 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);
|
|
|
|
}
|
|
|
|
|
2010-05-06 20:13:59 +02:00
|
|
|
/**
|
|
|
|
* g_dbus_method_invocation_return_dbus_error:
|
2011-05-03 18:54:45 +02:00
|
|
|
* @invocation: (transfer full): A #GDBusMethodInvocation.
|
2010-05-06 20:13:59 +02:00
|
|
|
* @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 free @invocation, you cannot use it afterwards.
|
2010-05-06 22:02:08 +02:00
|
|
|
*
|
|
|
|
* Since: 2.26
|
2010-05-06 20:13:59 +02:00
|
|
|
*/
|
|
|
|
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);
|
|
|
|
|
2010-08-04 22:59:26 +02:00
|
|
|
if (G_UNLIKELY (_g_dbus_debug_return ()))
|
|
|
|
{
|
|
|
|
_g_dbus_debug_print_lock ();
|
|
|
|
g_print ("========================================================================\n"
|
|
|
|
"GDBus-debug:Return:\n"
|
|
|
|
" >>>> METHOD ERROR %s\n"
|
2013-05-20 22:54:48 +02:00
|
|
|
" message '%s'\n"
|
2010-08-04 22:59:26 +02:00
|
|
|
" 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 ();
|
|
|
|
}
|
|
|
|
|
2010-07-07 22:35:17 +02:00
|
|
|
reply = g_dbus_message_new_method_error_literal (invocation->message,
|
2010-05-06 20:13:59 +02:00
|
|
|
error_name,
|
|
|
|
error_message);
|
2010-07-19 22:07:57 +02:00
|
|
|
g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
|
2010-05-06 20:13:59 +02:00
|
|
|
g_object_unref (reply);
|
|
|
|
|
|
|
|
g_object_unref (invocation);
|
|
|
|
}
|