LCOV - code coverage report
Current view: top level - glib/gio - gdbusmethodinvocation.c (source / functions) Hit Total Coverage
Test: unnamed Lines: 171 180 95.0 %
Date: 2024-04-23 05:16:05 Functions: 26 26 100.0 %
Branches: 46 54 85.2 %

           Branch data     Line data    Source code
       1                 :            : /* GDBus - GLib D-Bus Library
       2                 :            :  *
       3                 :            :  * Copyright (C) 2008-2010 Red Hat, Inc.
       4                 :            :  *
       5                 :            :  * SPDX-License-Identifier: LGPL-2.1-or-later
       6                 :            :  *
       7                 :            :  * This library is free software; you can redistribute it and/or
       8                 :            :  * modify it under the terms of the GNU Lesser General Public
       9                 :            :  * License as published by the Free Software Foundation; either
      10                 :            :  * version 2.1 of the License, or (at your option) any later version.
      11                 :            :  *
      12                 :            :  * This library is distributed in the hope that it will be useful,
      13                 :            :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      14                 :            :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15                 :            :  * Lesser General Public License for more details.
      16                 :            :  *
      17                 :            :  * You should have received a copy of the GNU Lesser General
      18                 :            :  * Public License along with this library; if not, see <http://www.gnu.org/licenses/>.
      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                 :            : #include "gioerror.h"
      35                 :            : 
      36                 :            : #ifdef G_OS_UNIX
      37                 :            : #include "gunixfdlist.h"
      38                 :            : #endif
      39                 :            : 
      40                 :            : #include "glibintl.h"
      41                 :            : 
      42                 :            : /**
      43                 :            :  * GDBusMethodInvocation:
      44                 :            :  *
      45                 :            :  * Instances of the `GDBusMethodInvocation` class are used when
      46                 :            :  * handling D-Bus method calls. It provides a way to asynchronously
      47                 :            :  * return results and errors.
      48                 :            :  *
      49                 :            :  * The normal way to obtain a `GDBusMethodInvocation` object is to receive
      50                 :            :  * it as an argument to the `handle_method_call()` function in a
      51                 :            :  * [type@Gio.DBusInterfaceVTable] that was passed to
      52                 :            :  * [method@Gio.DBusConnection.register_object].
      53                 :            :  *
      54                 :            :  * Since: 2.26
      55                 :            :  */
      56                 :            : 
      57                 :            : typedef struct _GDBusMethodInvocationClass GDBusMethodInvocationClass;
      58                 :            : 
      59                 :            : /**
      60                 :            :  * GDBusMethodInvocationClass:
      61                 :            :  *
      62                 :            :  * Class structure for #GDBusMethodInvocation.
      63                 :            :  *
      64                 :            :  * Since: 2.26
      65                 :            :  */
      66                 :            : struct _GDBusMethodInvocationClass
      67                 :            : {
      68                 :            :   /*< private >*/
      69                 :            :   GObjectClass parent_class;
      70                 :            : };
      71                 :            : 
      72                 :            : struct _GDBusMethodInvocation
      73                 :            : {
      74                 :            :   /*< private >*/
      75                 :            :   GObject parent_instance;
      76                 :            : 
      77                 :            :   /* construct-only properties */
      78                 :            :   gchar           *sender;
      79                 :            :   gchar           *object_path;
      80                 :            :   gchar           *interface_name;
      81                 :            :   gchar           *method_name;
      82                 :            :   GDBusMethodInfo *method_info;
      83                 :            :   GDBusPropertyInfo *property_info;
      84                 :            :   GDBusConnection *connection;
      85                 :            :   GDBusMessage    *message;
      86                 :            :   GVariant        *parameters;
      87                 :            :   gpointer         user_data;
      88                 :            : };
      89                 :            : 
      90   [ +  +  +  -  :      12555 : G_DEFINE_TYPE (GDBusMethodInvocation, g_dbus_method_invocation, G_TYPE_OBJECT)
                   +  + ]
      91                 :            : 
      92                 :            : static void
      93                 :        882 : g_dbus_method_invocation_finalize (GObject *object)
      94                 :            : {
      95                 :        882 :   GDBusMethodInvocation *invocation = G_DBUS_METHOD_INVOCATION (object);
      96                 :            : 
      97                 :        882 :   g_free (invocation->sender);
      98                 :        882 :   g_free (invocation->object_path);
      99                 :        882 :   g_free (invocation->interface_name);
     100                 :        882 :   g_free (invocation->method_name);
     101         [ +  + ]:        882 :   if (invocation->method_info)
     102                 :        867 :       g_dbus_method_info_unref (invocation->method_info);
     103         [ +  + ]:        882 :   if (invocation->property_info)
     104                 :         12 :       g_dbus_property_info_unref (invocation->property_info);
     105                 :        882 :   g_object_unref (invocation->connection);
     106                 :        882 :   g_object_unref (invocation->message);
     107                 :        882 :   g_variant_unref (invocation->parameters);
     108                 :            : 
     109                 :        882 :   G_OBJECT_CLASS (g_dbus_method_invocation_parent_class)->finalize (object);
     110                 :        882 : }
     111                 :            : 
     112                 :            : static void
     113                 :         22 : g_dbus_method_invocation_class_init (GDBusMethodInvocationClass *klass)
     114                 :            : {
     115                 :         22 :   GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
     116                 :            : 
     117                 :         22 :   gobject_class->finalize = g_dbus_method_invocation_finalize;
     118                 :         22 : }
     119                 :            : 
     120                 :            : static void
     121                 :        883 : g_dbus_method_invocation_init (GDBusMethodInvocation *invocation)
     122                 :            : {
     123                 :        883 : }
     124                 :            : 
     125                 :            : /**
     126                 :            :  * g_dbus_method_invocation_get_sender:
     127                 :            :  * @invocation: A #GDBusMethodInvocation.
     128                 :            :  *
     129                 :            :  * Gets the bus name that invoked the method.
     130                 :            :  *
     131                 :            :  * Returns: A string. Do not free, it is owned by @invocation.
     132                 :            :  *
     133                 :            :  * Since: 2.26
     134                 :            :  */
     135                 :            : const gchar *
     136                 :        849 : g_dbus_method_invocation_get_sender (GDBusMethodInvocation *invocation)
     137                 :            : {
     138                 :        849 :   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
     139                 :        849 :   return invocation->sender;
     140                 :            : }
     141                 :            : 
     142                 :            : /**
     143                 :            :  * g_dbus_method_invocation_get_object_path:
     144                 :            :  * @invocation: A #GDBusMethodInvocation.
     145                 :            :  *
     146                 :            :  * Gets the object path the method was invoked on.
     147                 :            :  *
     148                 :            :  * Returns: A string. Do not free, it is owned by @invocation.
     149                 :            :  *
     150                 :            :  * Since: 2.26
     151                 :            :  */
     152                 :            : const gchar *
     153                 :        919 : g_dbus_method_invocation_get_object_path (GDBusMethodInvocation *invocation)
     154                 :            : {
     155                 :        919 :   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
     156                 :        919 :   return invocation->object_path;
     157                 :            : }
     158                 :            : 
     159                 :            : /**
     160                 :            :  * g_dbus_method_invocation_get_interface_name:
     161                 :            :  * @invocation: A #GDBusMethodInvocation.
     162                 :            :  *
     163                 :            :  * Gets the name of the D-Bus interface the method was invoked on.
     164                 :            :  *
     165                 :            :  * If this method call is a property Get, Set or GetAll call that has
     166                 :            :  * been redirected to the method call handler then
     167                 :            :  * "org.freedesktop.DBus.Properties" will be returned.  See
     168                 :            :  * #GDBusInterfaceVTable for more information.
     169                 :            :  *
     170                 :            :  * Returns: A string. Do not free, it is owned by @invocation.
     171                 :            :  *
     172                 :            :  * Since: 2.26
     173                 :            :  */
     174                 :            : const gchar *
     175                 :        922 : g_dbus_method_invocation_get_interface_name (GDBusMethodInvocation *invocation)
     176                 :            : {
     177                 :        922 :   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
     178                 :        922 :   return invocation->interface_name;
     179                 :            : }
     180                 :            : 
     181                 :            : /**
     182                 :            :  * g_dbus_method_invocation_get_method_info:
     183                 :            :  * @invocation: A #GDBusMethodInvocation.
     184                 :            :  *
     185                 :            :  * Gets information about the method call, if any.
     186                 :            :  *
     187                 :            :  * If this method invocation is a property Get, Set or GetAll call that
     188                 :            :  * has been redirected to the method call handler then %NULL will be
     189                 :            :  * returned.  See g_dbus_method_invocation_get_property_info() and
     190                 :            :  * #GDBusInterfaceVTable for more information.
     191                 :            :  *
     192                 :            :  * Returns: (nullable): A #GDBusMethodInfo or %NULL. Do not free, it is owned by @invocation.
     193                 :            :  *
     194                 :            :  * Since: 2.26
     195                 :            :  */
     196                 :            : const GDBusMethodInfo *
     197                 :         59 : g_dbus_method_invocation_get_method_info (GDBusMethodInvocation *invocation)
     198                 :            : {
     199                 :         59 :   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
     200                 :         59 :   return invocation->method_info;
     201                 :            : }
     202                 :            : 
     203                 :            : /**
     204                 :            :  * g_dbus_method_invocation_get_property_info:
     205                 :            :  * @invocation: A #GDBusMethodInvocation
     206                 :            :  *
     207                 :            :  * Gets information about the property that this method call is for, if
     208                 :            :  * any.
     209                 :            :  *
     210                 :            :  * This will only be set in the case of an invocation in response to a
     211                 :            :  * property Get or Set call that has been directed to the method call
     212                 :            :  * handler for an object on account of its property_get() or
     213                 :            :  * property_set() vtable pointers being unset.
     214                 :            :  *
     215                 :            :  * See #GDBusInterfaceVTable for more information.
     216                 :            :  *
     217                 :            :  * If the call was GetAll, %NULL will be returned.
     218                 :            :  *
     219                 :            :  * Returns: (nullable) (transfer none): a #GDBusPropertyInfo or %NULL
     220                 :            :  *
     221                 :            :  * Since: 2.38
     222                 :            :  */
     223                 :            : const GDBusPropertyInfo *
     224                 :          5 : g_dbus_method_invocation_get_property_info (GDBusMethodInvocation *invocation)
     225                 :            : {
     226                 :          5 :   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
     227                 :          5 :   return invocation->property_info;
     228                 :            : }
     229                 :            : 
     230                 :            : /**
     231                 :            :  * g_dbus_method_invocation_get_method_name:
     232                 :            :  * @invocation: A #GDBusMethodInvocation.
     233                 :            :  *
     234                 :            :  * Gets the name of the method that was invoked.
     235                 :            :  *
     236                 :            :  * Returns: A string. Do not free, it is owned by @invocation.
     237                 :            :  *
     238                 :            :  * Since: 2.26
     239                 :            :  */
     240                 :            : const gchar *
     241                 :        863 : g_dbus_method_invocation_get_method_name (GDBusMethodInvocation *invocation)
     242                 :            : {
     243                 :        863 :   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
     244                 :        863 :   return invocation->method_name;
     245                 :            : }
     246                 :            : 
     247                 :            : /**
     248                 :            :  * g_dbus_method_invocation_get_connection:
     249                 :            :  * @invocation: A #GDBusMethodInvocation.
     250                 :            :  *
     251                 :            :  * Gets the #GDBusConnection the method was invoked on.
     252                 :            :  *
     253                 :            :  * Returns: (transfer none):A #GDBusConnection. Do not free, it is owned by @invocation.
     254                 :            :  *
     255                 :            :  * Since: 2.26
     256                 :            :  */
     257                 :            : GDBusConnection *
     258                 :       2396 : g_dbus_method_invocation_get_connection (GDBusMethodInvocation *invocation)
     259                 :            : {
     260                 :       2396 :   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
     261                 :       2396 :   return invocation->connection;
     262                 :            : }
     263                 :            : 
     264                 :            : /**
     265                 :            :  * g_dbus_method_invocation_get_message:
     266                 :            :  * @invocation: A #GDBusMethodInvocation.
     267                 :            :  *
     268                 :            :  * Gets the #GDBusMessage for the method invocation. This is useful if
     269                 :            :  * you need to use low-level protocol features, such as UNIX file
     270                 :            :  * descriptor passing, that cannot be properly expressed in the
     271                 :            :  * #GVariant API.
     272                 :            :  *
     273                 :            :  * See this [server][gdbus-server] and [client][gdbus-unix-fd-client]
     274                 :            :  * for an example of how to use this low-level API to send and receive
     275                 :            :  * UNIX file descriptors.
     276                 :            :  *
     277                 :            :  * Returns: (transfer none): #GDBusMessage. Do not free, it is owned by @invocation.
     278                 :            :  *
     279                 :            :  * Since: 2.26
     280                 :            :  */
     281                 :            : GDBusMessage *
     282                 :        103 : g_dbus_method_invocation_get_message (GDBusMethodInvocation *invocation)
     283                 :            : {
     284                 :        103 :   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
     285                 :        103 :   return invocation->message;
     286                 :            : }
     287                 :            : 
     288                 :            : /**
     289                 :            :  * g_dbus_method_invocation_get_parameters:
     290                 :            :  * @invocation: A #GDBusMethodInvocation.
     291                 :            :  *
     292                 :            :  * Gets the parameters of the method invocation. If there are no input
     293                 :            :  * parameters then this will return a GVariant with 0 children rather than NULL.
     294                 :            :  *
     295                 :            :  * Returns: (transfer none): A #GVariant tuple. Do not unref this because it is owned by @invocation.
     296                 :            :  *
     297                 :            :  * Since: 2.26
     298                 :            :  */
     299                 :            : GVariant *
     300                 :        852 : g_dbus_method_invocation_get_parameters (GDBusMethodInvocation *invocation)
     301                 :            : {
     302                 :        852 :   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
     303                 :        852 :   return invocation->parameters;
     304                 :            : }
     305                 :            : 
     306                 :            : /**
     307                 :            :  * g_dbus_method_invocation_get_user_data: (skip)
     308                 :            :  * @invocation: A #GDBusMethodInvocation.
     309                 :            :  *
     310                 :            :  * Gets the @user_data #gpointer passed to g_dbus_connection_register_object().
     311                 :            :  *
     312                 :            :  * Returns: A #gpointer.
     313                 :            :  *
     314                 :            :  * Since: 2.26
     315                 :            :  */
     316                 :            : gpointer
     317                 :        845 : g_dbus_method_invocation_get_user_data (GDBusMethodInvocation *invocation)
     318                 :            : {
     319                 :        845 :   g_return_val_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation), NULL);
     320                 :        845 :   return invocation->user_data;
     321                 :            : }
     322                 :            : 
     323                 :            : /* < internal >
     324                 :            :  * _g_dbus_method_invocation_new:
     325                 :            :  * @sender: (nullable): The bus name that invoked the method or %NULL if @connection is not a bus connection.
     326                 :            :  * @object_path: The object path the method was invoked on.
     327                 :            :  * @interface_name: The name of the D-Bus interface the method was invoked on.
     328                 :            :  * @method_name: The name of the method that was invoked.
     329                 :            :  * @method_info: (nullable): Information about the method call or %NULL.
     330                 :            :  * @property_info: (nullable): Information about the property or %NULL.
     331                 :            :  * @connection: The #GDBusConnection the method was invoked on.
     332                 :            :  * @message: The D-Bus message as a #GDBusMessage.
     333                 :            :  * @parameters: The parameters as a #GVariant tuple.
     334                 :            :  * @user_data: The @user_data #gpointer passed to g_dbus_connection_register_object().
     335                 :            :  *
     336                 :            :  * Creates a new #GDBusMethodInvocation object.
     337                 :            :  *
     338                 :            :  * Returns: A #GDBusMethodInvocation. Free with g_object_unref().
     339                 :            :  *
     340                 :            :  * Since: 2.26
     341                 :            :  */
     342                 :            : GDBusMethodInvocation *
     343                 :        883 : _g_dbus_method_invocation_new (const gchar             *sender,
     344                 :            :                                const gchar             *object_path,
     345                 :            :                                const gchar             *interface_name,
     346                 :            :                                const gchar             *method_name,
     347                 :            :                                const GDBusMethodInfo   *method_info,
     348                 :            :                                const GDBusPropertyInfo *property_info,
     349                 :            :                                GDBusConnection         *connection,
     350                 :            :                                GDBusMessage            *message,
     351                 :            :                                GVariant                *parameters,
     352                 :            :                                gpointer                 user_data)
     353                 :            : {
     354                 :            :   GDBusMethodInvocation *invocation;
     355                 :            : 
     356                 :        883 :   g_return_val_if_fail (sender == NULL || g_dbus_is_name (sender), NULL);
     357                 :        883 :   g_return_val_if_fail (g_variant_is_object_path (object_path), NULL);
     358                 :        883 :   g_return_val_if_fail (interface_name == NULL || g_dbus_is_interface_name (interface_name), NULL);
     359                 :        883 :   g_return_val_if_fail (g_dbus_is_member_name (method_name), NULL);
     360                 :        883 :   g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
     361                 :        883 :   g_return_val_if_fail (G_IS_DBUS_MESSAGE (message), NULL);
     362                 :        883 :   g_return_val_if_fail (g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE), NULL);
     363                 :            : 
     364                 :        883 :   invocation = G_DBUS_METHOD_INVOCATION (g_object_new (G_TYPE_DBUS_METHOD_INVOCATION, NULL));
     365                 :        883 :   invocation->sender = g_strdup (sender);
     366                 :        883 :   invocation->object_path = g_strdup (object_path);
     367                 :        883 :   invocation->interface_name = g_strdup (interface_name);
     368                 :        883 :   invocation->method_name = g_strdup (method_name);
     369         [ +  + ]:        883 :   if (method_info)
     370                 :        868 :     invocation->method_info = g_dbus_method_info_ref ((GDBusMethodInfo *)method_info);
     371         [ +  + ]:        883 :   if (property_info)
     372                 :         12 :     invocation->property_info = g_dbus_property_info_ref ((GDBusPropertyInfo *)property_info);
     373                 :        883 :   invocation->connection = g_object_ref (connection);
     374                 :        883 :   invocation->message = g_object_ref (message);
     375                 :        883 :   invocation->parameters = g_variant_ref (parameters);
     376                 :        883 :   invocation->user_data = user_data;
     377                 :            : 
     378                 :        883 :   return invocation;
     379                 :            : }
     380                 :            : 
     381                 :            : /* ---------------------------------------------------------------------------------------------------- */
     382                 :            : 
     383                 :            : static void
     384                 :        774 : g_dbus_method_invocation_return_value_internal (GDBusMethodInvocation *invocation,
     385                 :            :                                                 GVariant              *parameters,
     386                 :            :                                                 GUnixFDList           *fd_list)
     387                 :            : {
     388                 :            :   GDBusMessage *reply;
     389                 :            :   GError *error;
     390                 :            : 
     391                 :        774 :   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
     392                 :        774 :   g_return_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE));
     393                 :            : 
     394         [ +  + ]:        774 :   if (g_dbus_message_get_flags (invocation->message) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED)
     395                 :        205 :     goto out;
     396                 :            : 
     397         [ +  + ]:        569 :   if (parameters == NULL)
     398                 :         95 :     parameters = g_variant_new_tuple (NULL, 0);
     399                 :            : 
     400                 :            :   /* if we have introspection data, check that the signature of @parameters is correct */
     401         [ +  + ]:        569 :   if (invocation->method_info != NULL)
     402                 :            :     {
     403                 :            :       GVariantType *type;
     404                 :            : 
     405                 :        559 :       type = _g_dbus_compute_complete_signature (invocation->method_info->out_args);
     406                 :            : 
     407         [ +  + ]:        559 :       if (!g_variant_is_of_type (parameters, type))
     408                 :            :         {
     409                 :          1 :           gchar *type_string = g_variant_type_dup_string (type);
     410                 :            : 
     411                 :          1 :           g_warning ("Type of return value is incorrect: expected '%s', got '%s'",
     412                 :            :                      type_string, g_variant_get_type_string (parameters));
     413                 :          1 :           g_variant_type_free (type);
     414                 :          1 :           g_free (type_string);
     415                 :          1 :           goto out;
     416                 :            :         }
     417                 :        558 :       g_variant_type_free (type);
     418                 :            :     }
     419                 :            : 
     420                 :            :   /* property_info is only non-NULL if set that way from
     421                 :            :    * GDBusConnection, so this must be the case of async property
     422                 :            :    * handling on either 'Get' or 'Set'.
     423                 :            :    *
     424                 :            :    * property_info is NULL for 'GetAll'.
     425                 :            :    */
     426         [ +  + ]:        568 :   if (invocation->property_info != NULL)
     427                 :            :     {
     428         [ +  + ]:          8 :       if (g_str_equal (invocation->method_name, "Get"))
     429                 :            :         {
     430                 :            :           GVariant *nested;
     431                 :            : 
     432         [ +  + ]:          5 :           if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(v)")))
     433                 :            :             {
     434                 :          2 :               g_warning ("Type of return value for property 'Get' call should be '(v)' but got '%s'",
     435                 :            :                          g_variant_get_type_string (parameters));
     436                 :          3 :               goto out;
     437                 :            :             }
     438                 :            : 
     439                 :            :           /* Go deeper and make sure that the value inside of the
     440                 :            :            * variant matches the property type.
     441                 :            :            */
     442                 :          3 :           g_variant_get (parameters, "(v)", &nested);
     443         [ +  + ]:          3 :           if (!g_str_equal (g_variant_get_type_string (nested), invocation->property_info->signature))
     444                 :            :             {
     445                 :          1 :               g_warning ("Value returned from property 'Get' call for '%s' should be '%s' but is '%s'",
     446                 :            :                          invocation->property_info->name, invocation->property_info->signature,
     447                 :            :                          g_variant_get_type_string (nested));
     448                 :          1 :               g_variant_unref (nested);
     449                 :          1 :               goto out;
     450                 :            :             }
     451                 :          2 :           g_variant_unref (nested);
     452                 :            :         }
     453                 :            : 
     454         [ +  - ]:          3 :       else if (g_str_equal (invocation->method_name, "Set"))
     455                 :            :         {
     456         [ +  + ]:          3 :           if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE_UNIT))
     457                 :            :             {
     458                 :          1 :               g_warning ("Type of return value for property 'Set' call should be '()' but got '%s'",
     459                 :            :                          g_variant_get_type_string (parameters));
     460                 :          1 :               goto out;
     461                 :            :             }
     462                 :            :         }
     463                 :            : 
     464                 :            :       else
     465                 :            :         g_assert_not_reached ();
     466                 :            :     }
     467         [ +  + ]:        560 :   else if (g_str_equal (invocation->interface_name, "org.freedesktop.DBus.Properties") &&
     468         [ +  - ]:          2 :            g_str_equal (invocation->method_name, "GetAll"))
     469                 :            :     {
     470         [ +  + ]:          2 :       if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(a{sv})")))
     471                 :            :         {
     472                 :          1 :           g_warning ("Type of return value for property 'GetAll' call should be '(a{sv})' but got '%s'",
     473                 :            :                      g_variant_get_type_string (parameters));
     474                 :          1 :           goto out;
     475                 :            :         }
     476                 :            : 
     477                 :            :       /* Could iterate the list of properties and make sure that all
     478                 :            :        * of them are actually on the interface and with the correct
     479                 :            :        * types, but let's not do that for now...
     480                 :            :        */
     481                 :            :     }
     482                 :            : 
     483         [ -  + ]:        563 :   if (G_UNLIKELY (_g_dbus_debug_return ()))
     484                 :            :     {
     485                 :          0 :       _g_dbus_debug_print_lock ();
     486                 :          0 :       g_print ("========================================================================\n"
     487                 :            :                "GDBus-debug:Return:\n"
     488                 :            :                " >>>> METHOD RETURN\n"
     489                 :            :                "      in response to %s.%s()\n"
     490                 :            :                "      on object %s\n"
     491                 :            :                "      to name %s\n"
     492                 :            :                "      reply-serial %d\n",
     493                 :            :                invocation->interface_name, invocation->method_name,
     494                 :            :                invocation->object_path,
     495                 :            :                invocation->sender,
     496                 :            :                g_dbus_message_get_serial (invocation->message));
     497                 :          0 :       _g_dbus_debug_print_unlock ();
     498                 :            :     }
     499                 :            : 
     500                 :        563 :   reply = g_dbus_message_new_method_reply (invocation->message);
     501                 :        563 :   g_dbus_message_set_body (reply, g_steal_pointer (&parameters));
     502                 :            : 
     503                 :            : #ifdef G_OS_UNIX
     504         [ +  + ]:        563 :   if (fd_list != NULL)
     505                 :          5 :     g_dbus_message_set_unix_fd_list (reply, fd_list);
     506                 :            : #endif
     507                 :            : 
     508                 :        563 :   error = NULL;
     509         [ -  + ]:        563 :   if (!g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error))
     510                 :            :     {
     511         [ #  # ]:          0 :       if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CLOSED))
     512                 :          0 :         g_warning ("Error sending message: %s", error->message);
     513                 :          0 :       g_error_free (error);
     514                 :            :     }
     515                 :        563 :   g_object_unref (reply);
     516                 :            : 
     517                 :        774 :  out:
     518         [ +  + ]:        774 :   if (parameters != NULL)
     519                 :            :     {
     520                 :         13 :       g_variant_ref_sink (parameters);
     521                 :         13 :       g_variant_unref (parameters);
     522                 :            :     }
     523                 :            : 
     524                 :        774 :   g_object_unref (invocation);
     525                 :            : }
     526                 :            : 
     527                 :            : /**
     528                 :            :  * g_dbus_method_invocation_return_value:
     529                 :            :  * @invocation: (transfer full): A #GDBusMethodInvocation.
     530                 :            :  * @parameters: (nullable): A #GVariant tuple with out parameters for the method or %NULL if not passing any parameters.
     531                 :            :  *
     532                 :            :  * Finishes handling a D-Bus method call by returning @parameters.
     533                 :            :  * If the @parameters GVariant is floating, it is consumed.
     534                 :            :  *
     535                 :            :  * It is an error if @parameters is not of the right format: it must be a tuple
     536                 :            :  * containing the out-parameters of the D-Bus method. Even if the method has a
     537                 :            :  * single out-parameter, it must be contained in a tuple. If the method has no
     538                 :            :  * out-parameters, @parameters may be %NULL or an empty tuple.
     539                 :            :  *
     540                 :            :  * |[<!-- language="C" -->
     541                 :            :  * GDBusMethodInvocation *invocation = some_invocation;
     542                 :            :  * g_autofree gchar *result_string = NULL;
     543                 :            :  * g_autoptr (GError) error = NULL;
     544                 :            :  *
     545                 :            :  * result_string = calculate_result (&error);
     546                 :            :  *
     547                 :            :  * if (error != NULL)
     548                 :            :  *   g_dbus_method_invocation_return_gerror (invocation, error);
     549                 :            :  * else
     550                 :            :  *   g_dbus_method_invocation_return_value (invocation,
     551                 :            :  *                                          g_variant_new ("(s)", result_string));
     552                 :            :  *
     553                 :            :  * // Do not free @invocation here; returning a value does that
     554                 :            :  * ]|
     555                 :            :  *
     556                 :            :  * This method will take ownership of @invocation. See
     557                 :            :  * #GDBusInterfaceVTable for more information about the ownership of
     558                 :            :  * @invocation.
     559                 :            :  *
     560                 :            :  * Since 2.48, if the method call requested for a reply not to be sent
     561                 :            :  * then this call will sink @parameters and free @invocation, but
     562                 :            :  * otherwise do nothing (as per the recommendations of the D-Bus
     563                 :            :  * specification).
     564                 :            :  *
     565                 :            :  * Since: 2.26
     566                 :            :  */
     567                 :            : void
     568                 :        767 : g_dbus_method_invocation_return_value (GDBusMethodInvocation *invocation,
     569                 :            :                                        GVariant              *parameters)
     570                 :            : {
     571                 :        767 :   g_dbus_method_invocation_return_value_internal (invocation, parameters, NULL);
     572                 :        767 : }
     573                 :            : 
     574                 :            : #ifdef G_OS_UNIX
     575                 :            : /**
     576                 :            :  * g_dbus_method_invocation_return_value_with_unix_fd_list:
     577                 :            :  * @invocation: (transfer full): A #GDBusMethodInvocation.
     578                 :            :  * @parameters: (nullable): A #GVariant tuple with out parameters for the method or %NULL if not passing any parameters.
     579                 :            :  * @fd_list: (nullable): A #GUnixFDList or %NULL.
     580                 :            :  *
     581                 :            :  * Like g_dbus_method_invocation_return_value() but also takes a #GUnixFDList.
     582                 :            :  *
     583                 :            :  * This method is only available on UNIX.
     584                 :            :  *
     585                 :            :  * This method will take ownership of @invocation. See
     586                 :            :  * #GDBusInterfaceVTable for more information about the ownership of
     587                 :            :  * @invocation.
     588                 :            :  *
     589                 :            :  * Since: 2.30
     590                 :            :  */
     591                 :            : void
     592                 :          7 : g_dbus_method_invocation_return_value_with_unix_fd_list (GDBusMethodInvocation *invocation,
     593                 :            :                                                          GVariant              *parameters,
     594                 :            :                                                          GUnixFDList           *fd_list)
     595                 :            : {
     596                 :          7 :   g_dbus_method_invocation_return_value_internal (invocation, parameters, fd_list);
     597                 :          7 : }
     598                 :            : #endif
     599                 :            : 
     600                 :            : /* ---------------------------------------------------------------------------------------------------- */
     601                 :            : 
     602                 :            : /**
     603                 :            :  * g_dbus_method_invocation_return_error:
     604                 :            :  * @invocation: (transfer full): A #GDBusMethodInvocation.
     605                 :            :  * @domain: A #GQuark for the #GError error domain.
     606                 :            :  * @code: The error code.
     607                 :            :  * @format: printf()-style format.
     608                 :            :  * @...: Parameters for @format.
     609                 :            :  *
     610                 :            :  * Finishes handling a D-Bus method call by returning an error.
     611                 :            :  *
     612                 :            :  * See g_dbus_error_encode_gerror() for details about what error name
     613                 :            :  * will be returned on the wire. In a nutshell, if the given error is
     614                 :            :  * registered using g_dbus_error_register_error() the name given
     615                 :            :  * during registration is used. Otherwise, a name of the form
     616                 :            :  * `org.gtk.GDBus.UnmappedGError.Quark...` is used. This provides
     617                 :            :  * transparent mapping of #GError between applications using GDBus.
     618                 :            :  *
     619                 :            :  * If you are writing an application intended to be portable,
     620                 :            :  * always register errors with g_dbus_error_register_error()
     621                 :            :  * or use g_dbus_method_invocation_return_dbus_error().
     622                 :            :  *
     623                 :            :  * This method will take ownership of @invocation. See
     624                 :            :  * #GDBusInterfaceVTable for more information about the ownership of
     625                 :            :  * @invocation.
     626                 :            :  *
     627                 :            :  * Since 2.48, if the method call requested for a reply not to be sent
     628                 :            :  * then this call will free @invocation but otherwise do nothing (as per
     629                 :            :  * the recommendations of the D-Bus specification).
     630                 :            :  *
     631                 :            :  * Since: 2.26
     632                 :            :  */
     633                 :            : void
     634                 :         20 : g_dbus_method_invocation_return_error (GDBusMethodInvocation *invocation,
     635                 :            :                                        GQuark                 domain,
     636                 :            :                                        gint                   code,
     637                 :            :                                        const gchar           *format,
     638                 :            :                                        ...)
     639                 :            : {
     640                 :            :   va_list var_args;
     641                 :            : 
     642                 :         20 :   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
     643                 :         20 :   g_return_if_fail (format != NULL);
     644                 :            : 
     645                 :         20 :   va_start (var_args, format);
     646                 :         20 :   g_dbus_method_invocation_return_error_valist (invocation,
     647                 :            :                                                 domain,
     648                 :            :                                                 code,
     649                 :            :                                                 format,
     650                 :            :                                                 var_args);
     651                 :         20 :   va_end (var_args);
     652                 :            : }
     653                 :            : 
     654                 :            : /**
     655                 :            :  * g_dbus_method_invocation_return_error_valist:
     656                 :            :  * @invocation: (transfer full): A #GDBusMethodInvocation.
     657                 :            :  * @domain: A #GQuark for the #GError error domain.
     658                 :            :  * @code: The error code.
     659                 :            :  * @format: printf()-style format.
     660                 :            :  * @var_args: #va_list of parameters for @format.
     661                 :            :  *
     662                 :            :  * Like g_dbus_method_invocation_return_error() but intended for
     663                 :            :  * language bindings.
     664                 :            :  *
     665                 :            :  * This method will take ownership of @invocation. See
     666                 :            :  * #GDBusInterfaceVTable for more information about the ownership of
     667                 :            :  * @invocation.
     668                 :            :  *
     669                 :            :  * Since: 2.26
     670                 :            :  */
     671                 :            : void
     672                 :         20 : g_dbus_method_invocation_return_error_valist (GDBusMethodInvocation *invocation,
     673                 :            :                                               GQuark                 domain,
     674                 :            :                                               gint                   code,
     675                 :            :                                               const gchar           *format,
     676                 :            :                                               va_list                var_args)
     677                 :            : {
     678                 :            :   gchar *literal_message;
     679                 :            : 
     680                 :         20 :   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
     681                 :         20 :   g_return_if_fail (format != NULL);
     682                 :            : 
     683                 :         20 :   literal_message = g_strdup_vprintf (format, var_args);
     684                 :         20 :   g_dbus_method_invocation_return_error_literal (invocation,
     685                 :            :                                                  domain,
     686                 :            :                                                  code,
     687                 :            :                                                  literal_message);
     688                 :         20 :   g_free (literal_message);
     689                 :            : }
     690                 :            : 
     691                 :            : /**
     692                 :            :  * g_dbus_method_invocation_return_error_literal:
     693                 :            :  * @invocation: (transfer full): A #GDBusMethodInvocation.
     694                 :            :  * @domain: A #GQuark for the #GError error domain.
     695                 :            :  * @code: The error code.
     696                 :            :  * @message: The error message.
     697                 :            :  *
     698                 :            :  * Like g_dbus_method_invocation_return_error() but without printf()-style formatting.
     699                 :            :  *
     700                 :            :  * This method will take ownership of @invocation. See
     701                 :            :  * #GDBusInterfaceVTable for more information about the ownership of
     702                 :            :  * @invocation.
     703                 :            :  *
     704                 :            :  * Since: 2.26
     705                 :            :  */
     706                 :            : void
     707                 :         20 : g_dbus_method_invocation_return_error_literal (GDBusMethodInvocation *invocation,
     708                 :            :                                                GQuark                 domain,
     709                 :            :                                                gint                   code,
     710                 :            :                                                const gchar           *message)
     711                 :            : {
     712                 :            :   GError *error;
     713                 :            : 
     714                 :         20 :   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
     715                 :         20 :   g_return_if_fail (message != NULL);
     716                 :            : 
     717                 :         20 :   error = g_error_new_literal (domain, code, message);
     718                 :         20 :   g_dbus_method_invocation_return_gerror (invocation, error);
     719                 :         20 :   g_error_free (error);
     720                 :            : }
     721                 :            : 
     722                 :            : /**
     723                 :            :  * g_dbus_method_invocation_return_gerror:
     724                 :            :  * @invocation: (transfer full): A #GDBusMethodInvocation.
     725                 :            :  * @error: A #GError.
     726                 :            :  *
     727                 :            :  * Like g_dbus_method_invocation_return_error() but takes a #GError
     728                 :            :  * instead of the error domain, error code and message.
     729                 :            :  *
     730                 :            :  * This method will take ownership of @invocation. See
     731                 :            :  * #GDBusInterfaceVTable for more information about the ownership of
     732                 :            :  * @invocation.
     733                 :            :  *
     734                 :            :  * Since: 2.26
     735                 :            :  */
     736                 :            : void
     737                 :         22 : g_dbus_method_invocation_return_gerror (GDBusMethodInvocation *invocation,
     738                 :            :                                         const GError          *error)
     739                 :            : {
     740                 :            :   gchar *dbus_error_name;
     741                 :            : 
     742                 :         22 :   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
     743                 :         22 :   g_return_if_fail (error != NULL);
     744                 :            : 
     745                 :         22 :   dbus_error_name = g_dbus_error_encode_gerror (error);
     746                 :            : 
     747                 :         22 :   g_dbus_method_invocation_return_dbus_error (invocation,
     748                 :            :                                               dbus_error_name,
     749                 :         22 :                                               error->message);
     750                 :         22 :   g_free (dbus_error_name);
     751                 :            : }
     752                 :            : 
     753                 :            : /**
     754                 :            :  * g_dbus_method_invocation_take_error: (skip)
     755                 :            :  * @invocation: (transfer full): A #GDBusMethodInvocation.
     756                 :            :  * @error: (transfer full): A #GError.
     757                 :            :  *
     758                 :            :  * Like g_dbus_method_invocation_return_gerror() but takes ownership
     759                 :            :  * of @error so the caller does not need to free it.
     760                 :            :  *
     761                 :            :  * This method will take ownership of @invocation. See
     762                 :            :  * #GDBusInterfaceVTable for more information about the ownership of
     763                 :            :  * @invocation.
     764                 :            :  *
     765                 :            :  * Since: 2.30
     766                 :            :  */
     767                 :            : void
     768                 :          2 : g_dbus_method_invocation_take_error (GDBusMethodInvocation *invocation,
     769                 :            :                                      GError                *error)
     770                 :            : {
     771                 :          2 :   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
     772                 :          2 :   g_return_if_fail (error != NULL);
     773                 :          2 :   g_dbus_method_invocation_return_gerror (invocation, error);
     774                 :          2 :   g_error_free (error);
     775                 :            : }
     776                 :            : 
     777                 :            : /**
     778                 :            :  * g_dbus_method_invocation_return_dbus_error:
     779                 :            :  * @invocation: (transfer full): A #GDBusMethodInvocation.
     780                 :            :  * @error_name: A valid D-Bus error name.
     781                 :            :  * @error_message: A valid D-Bus error message.
     782                 :            :  *
     783                 :            :  * Finishes handling a D-Bus method call by returning an error.
     784                 :            :  *
     785                 :            :  * This method will take ownership of @invocation. See
     786                 :            :  * #GDBusInterfaceVTable for more information about the ownership of
     787                 :            :  * @invocation.
     788                 :            :  *
     789                 :            :  * Since: 2.26
     790                 :            :  */
     791                 :            : void
     792                 :         28 : g_dbus_method_invocation_return_dbus_error (GDBusMethodInvocation *invocation,
     793                 :            :                                             const gchar           *error_name,
     794                 :            :                                             const gchar           *error_message)
     795                 :            : {
     796                 :            :   GDBusMessage *reply;
     797                 :            : 
     798                 :         28 :   g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation));
     799                 :         28 :   g_return_if_fail (error_name != NULL && g_dbus_is_name (error_name));
     800                 :         28 :   g_return_if_fail (error_message != NULL);
     801                 :            : 
     802         [ +  + ]:         28 :   if (g_dbus_message_get_flags (invocation->message) & G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED)
     803                 :          1 :     goto out;
     804                 :            : 
     805         [ -  + ]:         27 :   if (G_UNLIKELY (_g_dbus_debug_return ()))
     806                 :            :     {
     807                 :          0 :       _g_dbus_debug_print_lock ();
     808                 :          0 :       g_print ("========================================================================\n"
     809                 :            :                "GDBus-debug:Return:\n"
     810                 :            :                " >>>> METHOD ERROR %s\n"
     811                 :            :                "      message '%s'\n"
     812                 :            :                "      in response to %s.%s()\n"
     813                 :            :                "      on object %s\n"
     814                 :            :                "      to name %s\n"
     815                 :            :                "      reply-serial %d\n",
     816                 :            :                error_name,
     817                 :            :                error_message,
     818                 :            :                invocation->interface_name, invocation->method_name,
     819                 :            :                invocation->object_path,
     820                 :            :                invocation->sender,
     821                 :            :                g_dbus_message_get_serial (invocation->message));
     822                 :          0 :       _g_dbus_debug_print_unlock ();
     823                 :            :     }
     824                 :            : 
     825                 :         27 :   reply = g_dbus_message_new_method_error_literal (invocation->message,
     826                 :            :                                                    error_name,
     827                 :            :                                                    error_message);
     828                 :         27 :   g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
     829                 :         27 :   g_object_unref (reply);
     830                 :            : 
     831                 :         28 : out:
     832                 :         28 :   g_object_unref (invocation);
     833                 :            : }

Generated by: LCOV version 1.14