Add g_dbus_method_invocation_take_error() convenience method
[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. If there are no input
253  * parameters then this will return a GVariant with 0 children rather than NULL.
254  *
255  * Returns: (transfer none): A #GVariant tuple. Do not unref this because it is owned by @invocation.
256  *
257  * Since: 2.26
258  */
259 GVariant *
260 g_dbus_method_invocation_get_parameters (GDBusMethodInvocation *invocation)
261 {
262   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
263   return invocation->parameters;
264 }
265
266 /**
267  * g_dbus_method_invocation_get_user_data: (skip)
268  * @invocation: A #GDBusMethodInvocation.
269  *
270  * Gets the @user_data #gpointer passed to g_dbus_connection_register_object().
271  *
272  * Returns: A #gpointer.
273  *
274  * Since: 2.26
275  */
276 gpointer
277 g_dbus_method_invocation_get_user_data (GDBusMethodInvocation *invocation)
278 {
279   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
280   return invocation->user_data;
281 }
282
283 /* < internal >
284  * _g_dbus_method_invocation_new:
285  * @sender: The bus name that invoked the method or %NULL if @connection is not a bus connection.
286  * @object_path: The object path the method was invoked on.
287  * @interface_name: The name of the D-Bus interface the method was invoked on.
288  * @method_name: The name of the method that was invoked.
289  * @method_info: Information about the method call or %NULL.
290  * @connection: The #GDBusConnection the method was invoked on.
291  * @message: The D-Bus message as a #GDBusMessage.
292  * @parameters: The parameters as a #GVariant tuple.
293  * @user_data: The @user_data #gpointer passed to g_dbus_connection_register_object().
294  *
295  * Creates a new #GDBusMethodInvocation object.
296  *
297  * Returns: A #GDBusMethodInvocation. Free with g_object_unref().
298  *
299  * Since: 2.26
300  */
301 GDBusMethodInvocation *
302 _g_dbus_method_invocation_new (const gchar           *sender,
303                                const gchar           *object_path,
304                                const gchar           *interface_name,
305                                const gchar           *method_name,
306                                const GDBusMethodInfo *method_info,
307                                GDBusConnection       *connection,
308                                GDBusMessage          *message,
309                                GVariant              *parameters,
310                                gpointer               user_data)
311 {
312   GDBusMethodInvocation *invocation;
313
314   g_return_val_if_fail (sender == NULL || g_dbus_is_name (sender), NULL);
315   g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
316   g_return_val_if_fail (interface_name == NULL || g_dbus_is_interface_name (interface_name), NULL);
317   g_return_val_if_fail (g_dbus_is_member_name (method_name), NULL);
318   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
319   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
320   g_return_val_if_fail (g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL);
321
322   invocation = G_DBUS_METHOD_INVOCATION (g_object_new (G_TYPE_DBUS_METHOD_INVOCATION, NULL));
323   invocation->sender = g_strdup (sender);
324   invocation->object_path = g_strdup (object_path);
325   invocation->interface_name = g_strdup (interface_name);
326   invocation->method_name = g_strdup (method_name);
327   invocation->method_info = g_dbus_method_info_ref ((GDBusMethodInfo *)method_info);
328   invocation->connection = g_object_ref (connection);
329   invocation->message = g_object_ref (message);
330   invocation->parameters = g_variant_ref (parameters);
331   invocation->user_data = user_data;
332
333   return invocation;
334 }
335
336 /* ---------------------------------------------------------------------------------------------------- */
337
338 /**
339  * g_dbus_method_invocation_return_value:
340  * @invocation: (transfer full): A #GDBusMethodInvocation.
341  * @parameters: (allow-none): A #GVariant tuple with out parameters for the method or %NULL if not passing any parameters.
342  *
343  * Finishes handling a D-Bus method call by returning @parameters.
344  * If the @parameters GVariant is floating, it is consumed.
345  *
346  * It is an error if @parameters is not of the right format.
347  *
348  * This method will free @invocation, you cannot use it afterwards.
349  *
350  * Since: 2.26
351  */
352 void
353 g_dbus_method_invocation_return_value (GDBusMethodInvocation *invocation,
354                                        GVariant              *parameters)
355 {
356   GDBusMessage *reply;
357   GError *error;
358
359   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
360   g_return_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE));
361
362   if (parameters == NULL)
363     parameters = g_variant_new_tuple (NULL, 0);
364
365   /* if we have introspection data, check that the signature of @parameters is correct */
366   if (invocation->method_info != NULL)
367     {
368       GVariantType *type;
369
370       type = _g_dbus_compute_complete_signature (invocation->method_info->out_args);
371
372       if (!g_variant_is_of_type (parameters, type))
373         {
374           gchar *type_string = g_variant_type_dup_string (type);
375
376           g_warning ("Type of return value is incorrect, got `%s', expected `%s'",
377                      g_variant_get_type_string (parameters), type_string);
378           g_variant_type_free (type);
379           g_free (type_string);
380           goto out;
381         }
382       g_variant_type_free (type);
383     }
384
385   if (G_UNLIKELY (_g_dbus_debug_return ()))
386     {
387       _g_dbus_debug_print_lock ();
388       g_print ("========================================================================\n"
389                "GDBus-debug:Return:\n"
390                " >>>> METHOD RETURN\n"
391                "      in response to %s.%s()\n"
392                "      on object %s\n"
393                "      to name %s\n"
394                "      reply-serial %d\n",
395                invocation->interface_name, invocation->method_name,
396                invocation->object_path,
397                invocation->sender,
398                g_dbus_message_get_serial (invocation->message));
399       _g_dbus_debug_print_unlock ();
400     }
401
402   reply = g_dbus_message_new_method_reply (invocation->message);
403   g_dbus_message_set_body (reply, parameters);
404   error = NULL;
405   if (!g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error))
406     {
407       g_warning ("Error sending message: %s", error->message);
408       g_error_free (error);
409     }
410   g_object_unref (reply);
411
412  out:
413   g_object_unref (invocation);
414 }
415
416 /* ---------------------------------------------------------------------------------------------------- */
417
418 /**
419  * g_dbus_method_invocation_return_error:
420  * @invocation: (transfer full): A #GDBusMethodInvocation.
421  * @domain: A #GQuark for the #GError error domain.
422  * @code: The error code.
423  * @format: printf()-style format.
424  * @...: Parameters for @format.
425  *
426  * Finishes handling a D-Bus method call by returning an error.
427  *
428  * See g_dbus_error_encode_gerror() for details about what error name
429  * will be returned on the wire. In a nutshell, if the given error is
430  * registered using g_dbus_error_register_error() the name given
431  * during registration is used. Otherwise, a name of the form
432  * <literal>org.gtk.GDBus.UnmappedGError.Quark...</literal> is
433  * used. This provides transparent mapping of #GError between
434  * applications using GDBus.
435  *
436  * If you are writing an application intended to be portable,
437  * <emphasis>always</emphasis> register errors with g_dbus_error_register_error()
438  * or use g_dbus_method_invocation_return_dbus_error().
439  *
440  * This method will free @invocation, you cannot use it afterwards.
441  *
442  * Since: 2.26
443  */
444 void
445 g_dbus_method_invocation_return_error (GDBusMethodInvocation *invocation,
446                                        GQuark                 domain,
447                                        gint                   code,
448                                        const gchar           *format,
449                                        ...)
450 {
451   va_list var_args;
452
453   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
454   g_return_if_fail (format != NULL);
455
456   va_start (var_args, format);
457   g_dbus_method_invocation_return_error_valist (invocation,
458                                                 domain,
459                                                 code,
460                                                 format,
461                                                 var_args);
462   va_end (var_args);
463 }
464
465 /**
466  * g_dbus_method_invocation_return_error_valist:
467  * @invocation: (transfer full): A #GDBusMethodInvocation.
468  * @domain: A #GQuark for the #GError error domain.
469  * @code: The error code.
470  * @format: printf()-style format.
471  * @var_args: #va_list of parameters for @format.
472  *
473  * Like g_dbus_method_invocation_return_error() but intended for
474  * language bindings.
475  *
476  * This method will free @invocation, you cannot use it afterwards.
477  *
478  * Since: 2.26
479  */
480 void
481 g_dbus_method_invocation_return_error_valist (GDBusMethodInvocation *invocation,
482                                               GQuark                 domain,
483                                               gint                   code,
484                                               const gchar           *format,
485                                               va_list                var_args)
486 {
487   gchar *literal_message;
488
489   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
490   g_return_if_fail (format != NULL);
491
492   literal_message = g_strdup_vprintf (format, var_args);
493   g_dbus_method_invocation_return_error_literal (invocation,
494                                                  domain,
495                                                  code,
496                                                  literal_message);
497   g_free (literal_message);
498 }
499
500 /**
501  * g_dbus_method_invocation_return_error_literal:
502  * @invocation: (transfer full): A #GDBusMethodInvocation.
503  * @domain: A #GQuark for the #GError error domain.
504  * @code: The error code.
505  * @message: The error message.
506  *
507  * Like g_dbus_method_invocation_return_error() but without printf()-style formatting.
508  *
509  * This method will free @invocation, you cannot use it afterwards.
510  *
511  * Since: 2.26
512  */
513 void
514 g_dbus_method_invocation_return_error_literal (GDBusMethodInvocation *invocation,
515                                                GQuark                 domain,
516                                                gint                   code,
517                                                const gchar           *message)
518 {
519   GError *error;
520
521   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
522   g_return_if_fail (message != NULL);
523
524   error = g_error_new_literal (domain, code, message);
525   g_dbus_method_invocation_return_gerror (invocation, error);
526   g_error_free (error);
527 }
528
529 /**
530  * g_dbus_method_invocation_return_gerror:
531  * @invocation: (transfer full): A #GDBusMethodInvocation.
532  * @error: A #GError.
533  *
534  * Like g_dbus_method_invocation_return_error() but takes a #GError
535  * instead of the error domain, error code and message.
536  *
537  * This method will free @invocation, you cannot use it afterwards.
538  *
539  * Since: 2.26
540  */
541 void
542 g_dbus_method_invocation_return_gerror (GDBusMethodInvocation *invocation,
543                                         const GError          *error)
544 {
545   gchar *dbus_error_name;
546
547   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
548   g_return_if_fail (error != NULL);
549
550   dbus_error_name = g_dbus_error_encode_gerror (error);
551
552   g_dbus_method_invocation_return_dbus_error (invocation,
553                                               dbus_error_name,
554                                               error->message);
555   g_free (dbus_error_name);
556 }
557
558 /**
559  * g_dbus_method_invocation_take_error: (skip)
560  * @invocation: (transfer full): A #GDBusMethodInvocation.
561  * @error: (transfer full): A #GError.
562  *
563  * Like g_dbus_method_invocation_return_gerror() but takes ownership
564  * of @error so the caller does not need to free it.
565  *
566  * This method will free @invocation, you cannot use it afterwards.
567  *
568  * Since: 2.30
569  */
570 void
571 g_dbus_method_invocation_take_error (GDBusMethodInvocation *invocation,
572                                      GError                *error)
573 {
574   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
575   g_return_if_fail (error != NULL);
576   g_dbus_method_invocation_return_gerror (invocation, error);
577   g_error_free (error);
578 }
579
580 /**
581  * g_dbus_method_invocation_return_dbus_error:
582  * @invocation: (transfer full): A #GDBusMethodInvocation.
583  * @error_name: A valid D-Bus error name.
584  * @error_message: A valid D-Bus error message.
585  *
586  * Finishes handling a D-Bus method call by returning an error.
587  *
588  * This method will free @invocation, you cannot use it afterwards.
589  *
590  * Since: 2.26
591  */
592 void
593 g_dbus_method_invocation_return_dbus_error (GDBusMethodInvocation *invocation,
594                                             const gchar           *error_name,
595                                             const gchar           *error_message)
596 {
597   GDBusMessage *reply;
598
599   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
600   g_return_if_fail (error_name != NULL && g_dbus_is_name (error_name));
601   g_return_if_fail (error_message != NULL);
602
603   if (G_UNLIKELY (_g_dbus_debug_return ()))
604     {
605       _g_dbus_debug_print_lock ();
606       g_print ("========================================================================\n"
607                "GDBus-debug:Return:\n"
608                " >>>> METHOD ERROR %s\n"
609                "      message `%s'\n"
610                "      in response to %s.%s()\n"
611                "      on object %s\n"
612                "      to name %s\n"
613                "      reply-serial %d\n",
614                error_name,
615                error_message,
616                invocation->interface_name, invocation->method_name,
617                invocation->object_path,
618                invocation->sender,
619                g_dbus_message_get_serial (invocation->message));
620       _g_dbus_debug_print_unlock ();
621     }
622
623   reply = g_dbus_message_new_method_error_literal (invocation->message,
624                                                    error_name,
625                                                    error_message);
626   g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
627   g_object_unref (reply);
628
629   g_object_unref (invocation);
630 }