Merge remote branch 'gvdb/master'
[platform/upstream/glib.git] / gio / gdbusmethodinvocation.c
1 /* GDBus - GLib D-Bus Library
2  *
3  * Copyright (C) 2008-2010 Red Hat, Inc.
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General
16  * Public License along with this library; if not, write to the
17  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
18  * Boston, MA 02111-1307, USA.
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
35 #include "glibintl.h"
36
37 /**
38  * SECTION:gdbusmethodinvocation
39  * @short_description: Object for handling remote calls
40  * @include: gio/gio.h
41  *
42  * Instances of the #GDBusMethodInvocation class are used when
43  * handling D-Bus method calls. It provides a way to asynchronously
44  * return results and errors.
45  *
46  * The normal way to obtain a #GDBusMethodInvocation object is to receive
47  * it as an argument to the handle_method_call() function in a
48  * #GDBusInterfaceVTable that was passed to g_dbus_connection_register_object().
49  */
50
51 typedef struct _GDBusMethodInvocationClass GDBusMethodInvocationClass;
52
53 /**
54  * GDBusMethodInvocationClass:
55  *
56  * Class structure for #GDBusMethodInvocation.
57  *
58  * Since: 2.26
59  */
60 struct _GDBusMethodInvocationClass
61 {
62   /*< private >*/
63   GObjectClass parent_class;
64 };
65
66 /**
67  * GDBusMethodInvocation:
68  *
69  * The #GDBusMethodInvocation structure contains only private data and
70  * should only be accessed using the provided API.
71  *
72  * Since: 2.26
73  */
74 struct _GDBusMethodInvocation
75 {
76   /*< private >*/
77   GObject parent_instance;
78
79   /* construct-only properties */
80   gchar           *sender;
81   gchar           *object_path;
82   gchar           *interface_name;
83   gchar           *method_name;
84   const GDBusMethodInfo *method_info;
85   GDBusConnection *connection;
86   GDBusMessage    *message;
87   GVariant        *parameters;
88   gpointer         user_data;
89 };
90
91 G_DEFINE_TYPE (GDBusMethodInvocation, g_dbus_method_invocation, G_TYPE_OBJECT);
92
93 static void
94 g_dbus_method_invocation_finalize (GObject *object)
95 {
96   GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (object);
97
98   g_free (invocation->sender);
99   g_free (invocation->object_path);
100   g_free (invocation->interface_name);
101   g_free (invocation->method_name);
102   g_object_unref (invocation->connection);
103   g_object_unref (invocation->message);
104   g_variant_unref (invocation->parameters);
105
106   G_OBJECT_CLASS (g_dbus_method_invocation_parent_class)->finalize (object);
107 }
108
109 static void
110 g_dbus_method_invocation_class_init (GDBusMethodInvocationClass *klass)
111 {
112   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
113
114   gobject_class->finalize = g_dbus_method_invocation_finalize;
115 }
116
117 static void
118 g_dbus_method_invocation_init (GDBusMethodInvocation *invocation)
119 {
120 }
121
122 /**
123  * g_dbus_method_invocation_get_sender:
124  * @invocation: A #GDBusMethodInvocation.
125  *
126  * Gets the bus name that invoked the method.
127  *
128  * Returns: A string. Do not free, it is owned by @invocation.
129  *
130  * Since: 2.26
131  */
132 const gchar *
133 g_dbus_method_invocation_get_sender (GDBusMethodInvocation *invocation)
134 {
135   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
136   return invocation->sender;
137 }
138
139 /**
140  * g_dbus_method_invocation_get_object_path:
141  * @invocation: A #GDBusMethodInvocation.
142  *
143  * Gets the object path the method was invoked on.
144  *
145  * Returns: A string. Do not free, it is owned by @invocation.
146  *
147  * Since: 2.26
148  */
149 const gchar *
150 g_dbus_method_invocation_get_object_path (GDBusMethodInvocation *invocation)
151 {
152   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
153   return invocation->object_path;
154 }
155
156 /**
157  * g_dbus_method_invocation_get_interface_name:
158  * @invocation: A #GDBusMethodInvocation.
159  *
160  * Gets the name of the D-Bus interface the method was invoked on.
161  *
162  * Returns: A string. Do not free, it is owned by @invocation.
163  *
164  * Since: 2.26
165  */
166 const gchar *
167 g_dbus_method_invocation_get_interface_name (GDBusMethodInvocation *invocation)
168 {
169   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
170   return invocation->interface_name;
171 }
172
173 /**
174  * g_dbus_method_invocation_get_method_info:
175  * @invocation: A #GDBusMethodInvocation.
176  *
177  * Gets information about the method call, if any.
178  *
179  * Returns: A #GDBusMethodInfo or %NULL. Do not free, it is owned by @invocation.
180  *
181  * Since: 2.26
182  */
183 const GDBusMethodInfo *
184 g_dbus_method_invocation_get_method_info (GDBusMethodInvocation *invocation)
185 {
186   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
187   return invocation->method_info;
188 }
189
190 /**
191  * g_dbus_method_invocation_get_method_name:
192  * @invocation: A #GDBusMethodInvocation.
193  *
194  * Gets the name of the method that was invoked.
195  *
196  * Returns: A string. Do not free, it is owned by @invocation.
197  *
198  * Since: 2.26
199  */
200 const gchar *
201 g_dbus_method_invocation_get_method_name (GDBusMethodInvocation *invocation)
202 {
203   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
204   return invocation->method_name;
205 }
206
207 /**
208  * g_dbus_method_invocation_get_connection:
209  * @invocation: A #GDBusMethodInvocation.
210  *
211  * Gets the #GDBusConnection the method was invoked on.
212  *
213  * Returns: (transfer none):A #GDBusConnection. Do not free, it is owned by @invocation.
214  *
215  * Since: 2.26
216  */
217 GDBusConnection *
218 g_dbus_method_invocation_get_connection (GDBusMethodInvocation *invocation)
219 {
220   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
221   return invocation->connection;
222 }
223
224 /**
225  * g_dbus_method_invocation_get_message:
226  * @invocation: A #GDBusMethodInvocation.
227  *
228  * Gets the #GDBusMessage for the method invocation. This is useful if
229  * you need to use low-level protocol features, such as UNIX file
230  * descriptor passing, that cannot be properly expressed in the
231  * #GVariant API.
232  *
233  * See <xref linkend="gdbus-server"/> and <xref
234  * linkend="gdbus-unix-fd-client"/> for an example of how to use this
235  * low-level API to send and receive UNIX file descriptors.
236  *
237  * Returns: (transfer none): #GDBusMessage. Do not free, it is owned by @invocation.
238  *
239  * Since: 2.26
240  */
241 GDBusMessage *
242 g_dbus_method_invocation_get_message (GDBusMethodInvocation *invocation)
243 {
244   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
245   return invocation->message;
246 }
247
248 /**
249  * g_dbus_method_invocation_get_parameters:
250  * @invocation: A #GDBusMethodInvocation.
251  *
252  * Gets the parameters of the method invocation.
253  *
254  * Returns: A #GVariant. Do not free, it is owned by @invocation.
255  *
256  * Since: 2.26
257  */
258 GVariant *
259 g_dbus_method_invocation_get_parameters (GDBusMethodInvocation *invocation)
260 {
261   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
262   return invocation->parameters;
263 }
264
265 /**
266  * g_dbus_method_invocation_get_user_data: (skip)
267  * @invocation: A #GDBusMethodInvocation.
268  *
269  * Gets the @user_data #gpointer passed to g_dbus_connection_register_object().
270  *
271  * Returns: A #gpointer.
272  *
273  * Since: 2.26
274  */
275 gpointer
276 g_dbus_method_invocation_get_user_data (GDBusMethodInvocation *invocation)
277 {
278   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
279   return invocation->user_data;
280 }
281
282 /* < internal >
283  * _g_dbus_method_invocation_new:
284  * @sender: The bus name that invoked the method or %NULL if @connection is not a bus connection.
285  * @object_path: The object path the method was invoked on.
286  * @interface_name: The name of the D-Bus interface the method was invoked on.
287  * @method_name: The name of the method that was invoked.
288  * @method_info: Information about the method call or %NULL.
289  * @connection: The #GDBusConnection the method was invoked on.
290  * @message: The D-Bus message as a #GDBusMessage.
291  * @parameters: The parameters as a #GVariant tuple.
292  * @user_data: The @user_data #gpointer passed to g_dbus_connection_register_object().
293  *
294  * Creates a new #GDBusMethodInvocation object.
295  *
296  * Returns: A #GDBusMethodInvocation. Free with g_object_unref().
297  *
298  * Since: 2.26
299  */
300 GDBusMethodInvocation *
301 _g_dbus_method_invocation_new (const gchar           *sender,
302                                const gchar           *object_path,
303                                const gchar           *interface_name,
304                                const gchar           *method_name,
305                                const GDBusMethodInfo *method_info,
306                                GDBusConnection       *connection,
307                                GDBusMessage          *message,
308                                GVariant              *parameters,
309                                gpointer               user_data)
310 {
311   GDBusMethodInvocation *invocation;
312
313   g_return_val_if_fail (sender == NULL || g_dbus_is_name (sender), NULL);
314   g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
315   g_return_val_if_fail (interface_name == NULL || g_dbus_is_interface_name (interface_name), NULL);
316   g_return_val_if_fail (g_dbus_is_member_name (method_name), NULL);
317   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
318   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
319   g_return_val_if_fail (g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL);
320
321   invocation = G_DBUS_METHOD_INVOCATION (g_object_new (G_TYPE_DBUS_METHOD_INVOCATION, NULL));
322   invocation->sender = g_strdup (sender);
323   invocation->object_path = g_strdup (object_path);
324   invocation->interface_name = g_strdup (interface_name);
325   invocation->method_name = g_strdup (method_name);
326   invocation->method_info = g_dbus_method_info_ref ((GDBusMethodInfo *)method_info);
327   invocation->connection = g_object_ref (connection);
328   invocation->message = g_object_ref (message);
329   invocation->parameters = g_variant_ref (parameters);
330   invocation->user_data = user_data;
331
332   return invocation;
333 }
334
335 /* ---------------------------------------------------------------------------------------------------- */
336
337 /**
338  * g_dbus_method_invocation_return_value:
339  * @invocation: A #GDBusMethodInvocation.
340  * @parameters: A #GVariant tuple with out parameters for the method or %NULL if not passing any parameters.
341  *
342  * Finishes handling a D-Bus method call by returning @parameters.
343  * If the @parameters GVariant is floating, it is consumed.
344  *
345  * It is an error if @parameters is not of the right format.
346  *
347  * This method will free @invocation, you cannot use it afterwards.
348  *
349  * Since: 2.26
350  */
351 void
352 g_dbus_method_invocation_return_value (GDBusMethodInvocation *invocation,
353                                        GVariant              *parameters)
354 {
355   GDBusMessage *reply;
356   GError *error;
357
358   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
359   g_return_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE));
360
361   if (parameters == NULL)
362     parameters = g_variant_new_tuple (NULL, 0);
363
364   /* if we have introspection data, check that the signature of @parameters is correct */
365   if (invocation->method_info != NULL)
366     {
367       GVariantType *type;
368
369       type = _g_dbus_compute_complete_signature (invocation->method_info->out_args);
370
371       if (!g_variant_is_of_type (parameters, type))
372         {
373           gchar *type_string = g_variant_type_dup_string (type);
374
375           g_warning (_("Type of return value is incorrect, got `%s', expected `%s'"),
376                      g_variant_get_type_string (parameters), type_string);
377           g_variant_type_free (type);
378           g_free (type_string);
379           goto out;
380         }
381       g_variant_type_free (type);
382     }
383
384   if (G_UNLIKELY (_g_dbus_debug_return ()))
385     {
386       _g_dbus_debug_print_lock ();
387       g_print ("========================================================================\n"
388                "GDBus-debug:Return:\n"
389                " >>>> METHOD RETURN\n"
390                "      in response to %s.%s()\n"
391                "      on object %s\n"
392                "      to name %s\n"
393                "      reply-serial %d\n",
394                invocation->interface_name, invocation->method_name,
395                invocation->object_path,
396                invocation->sender,
397                g_dbus_message_get_serial (invocation->message));
398       _g_dbus_debug_print_unlock ();
399     }
400
401   reply = g_dbus_message_new_method_reply (invocation->message);
402   g_dbus_message_set_body (reply, parameters);
403   error = NULL;
404   if (!g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error))
405     {
406       g_warning (_("Error sending message: %s"), error->message);
407       g_error_free (error);
408     }
409   g_object_unref (reply);
410
411  out:
412   g_object_unref (invocation);
413 }
414
415 /* ---------------------------------------------------------------------------------------------------- */
416
417 /**
418  * g_dbus_method_invocation_return_error:
419  * @invocation: A #GDBusMethodInvocation.
420  * @domain: A #GQuark for the #GError error domain.
421  * @code: The error code.
422  * @format: printf()-style format.
423  * @...: Parameters for @format.
424  *
425  * Finishes handling a D-Bus method call by returning an error.
426  *
427  * See g_dbus_error_encode_gerror() for details about what error name
428  * will be returned on the wire. In a nutshell, if the given error is
429  * registered using g_dbus_error_register_error() the name given
430  * during registration is used. Otherwise, a name of the form
431  * <literal>org.gtk.GDBus.UnmappedGError.Quark...</literal> is
432  * used. This provides transparent mapping of #GError between
433  * applications using GDBus.
434  *
435  * If you are writing an application intended to be portable,
436  * <emphasis>always</emphasis> register errors with g_dbus_error_register_error()
437  * or use g_dbus_method_invocation_return_dbus_error().
438  *
439  * This method will free @invocation, you cannot use it afterwards.
440  *
441  * Since: 2.26
442  */
443 void
444 g_dbus_method_invocation_return_error (GDBusMethodInvocation *invocation,
445                                        GQuark                 domain,
446                                        gint                   code,
447                                        const gchar           *format,
448                                        ...)
449 {
450   va_list var_args;
451
452   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
453   g_return_if_fail (format != NULL);
454
455   va_start (var_args, format);
456   g_dbus_method_invocation_return_error_valist (invocation,
457                                                 domain,
458                                                 code,
459                                                 format,
460                                                 var_args);
461   va_end (var_args);
462 }
463
464 /**
465  * g_dbus_method_invocation_return_error_valist:
466  * @invocation: A #GDBusMethodInvocation.
467  * @domain: A #GQuark for the #GError error domain.
468  * @code: The error code.
469  * @format: printf()-style format.
470  * @var_args: #va_list of parameters for @format.
471  *
472  * Like g_dbus_method_invocation_return_error() but intended for
473  * language bindings.
474  *
475  * This method will free @invocation, you cannot use it afterwards.
476  *
477  * Since: 2.26
478  */
479 void
480 g_dbus_method_invocation_return_error_valist (GDBusMethodInvocation *invocation,
481                                               GQuark                 domain,
482                                               gint                   code,
483                                               const gchar           *format,
484                                               va_list                var_args)
485 {
486   gchar *literal_message;
487
488   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
489   g_return_if_fail (format != NULL);
490
491   literal_message = g_strdup_vprintf (format, var_args);
492   g_dbus_method_invocation_return_error_literal (invocation,
493                                                  domain,
494                                                  code,
495                                                  literal_message);
496   g_free (literal_message);
497 }
498
499 /**
500  * g_dbus_method_invocation_return_error_literal:
501  * @invocation: A #GDBusMethodInvocation.
502  * @domain: A #GQuark for the #GError error domain.
503  * @code: The error code.
504  * @message: The error message.
505  *
506  * Like g_dbus_method_invocation_return_error() but without printf()-style formatting.
507  *
508  * This method will free @invocation, you cannot use it afterwards.
509  *
510  * Since: 2.26
511  */
512 void
513 g_dbus_method_invocation_return_error_literal (GDBusMethodInvocation *invocation,
514                                                GQuark                 domain,
515                                                gint                   code,
516                                                const gchar           *message)
517 {
518   GError *error;
519
520   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
521   g_return_if_fail (message != NULL);
522
523   error = g_error_new_literal (domain, code, message);
524   g_dbus_method_invocation_return_gerror (invocation, error);
525   g_error_free (error);
526 }
527
528 /**
529  * g_dbus_method_invocation_return_gerror:
530  * @invocation: A #GDBusMethodInvocation.
531  * @error: A #GError.
532  *
533  * Like g_dbus_method_invocation_return_error() but takes a #GError
534  * instead of the error domain, error code and message.
535  *
536  * This method will free @invocation, you cannot use it afterwards.
537  *
538  * Since: 2.26
539  */
540 void
541 g_dbus_method_invocation_return_gerror (GDBusMethodInvocation *invocation,
542                                         const GError          *error)
543 {
544   gchar *dbus_error_name;
545
546   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
547   g_return_if_fail (error != NULL);
548
549   dbus_error_name = g_dbus_error_encode_gerror (error);
550
551   g_dbus_method_invocation_return_dbus_error (invocation,
552                                               dbus_error_name,
553                                               error->message);
554   g_free (dbus_error_name);
555 }
556
557 /**
558  * g_dbus_method_invocation_return_dbus_error:
559  * @invocation: A #GDBusMethodInvocation.
560  * @error_name: A valid D-Bus error name.
561  * @error_message: A valid D-Bus error message.
562  *
563  * Finishes handling a D-Bus method call by returning an error.
564  *
565  * This method will free @invocation, you cannot use it afterwards.
566  *
567  * Since: 2.26
568  */
569 void
570 g_dbus_method_invocation_return_dbus_error (GDBusMethodInvocation *invocation,
571                                             const gchar           *error_name,
572                                             const gchar           *error_message)
573 {
574   GDBusMessage *reply;
575
576   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
577   g_return_if_fail (error_name != NULL && g_dbus_is_name (error_name));
578   g_return_if_fail (error_message != NULL);
579
580   if (G_UNLIKELY (_g_dbus_debug_return ()))
581     {
582       _g_dbus_debug_print_lock ();
583       g_print ("========================================================================\n"
584                "GDBus-debug:Return:\n"
585                " >>>> METHOD ERROR %s\n"
586                "      message `%s'\n"
587                "      in response to %s.%s()\n"
588                "      on object %s\n"
589                "      to name %s\n"
590                "      reply-serial %d\n",
591                error_name,
592                error_message,
593                invocation->interface_name, invocation->method_name,
594                invocation->object_path,
595                invocation->sender,
596                g_dbus_message_get_serial (invocation->message));
597       _g_dbus_debug_print_unlock ();
598     }
599
600   reply = g_dbus_message_new_method_error_literal (invocation->message,
601                                                    error_name,
602                                                    error_message);
603   g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
604   g_object_unref (reply);
605
606   g_object_unref (invocation);
607 }