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