LCOV - code coverage report
Current view: top level - src/plugins/bluez - valent-bluez-channel-service.c (source / functions) Coverage Total Hit
Test: Code Coverage Lines: 74.1 % 228 169
Test Date: 2025-11-09 04:19:42 Functions: 85.7 % 21 18
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 39.3 % 150 59

             Branch data     Line data    Source code
       1                 :             : // SPDX-License-Identifier: GPL-3.0-or-later
       2                 :             : // SPDX-FileCopyrightText: Andy Holmes <andrew.g.r.holmes@gmail.com>
       3                 :             : 
       4                 :             : #define G_LOG_DOMAIN "valent-bluez-channel-service"
       5                 :             : 
       6                 :             : #include "config.h"
       7                 :             : 
       8                 :             : #include <valent.h>
       9                 :             : 
      10                 :             : #include "valent-bluez-device.h"
      11                 :             : #include "valent-bluez-muxer.h"
      12                 :             : #include "valent-bluez-profile.h"
      13                 :             : 
      14                 :             : #include "valent-bluez-channel-service.h"
      15                 :             : 
      16                 :             : #define DEFAULT_BUFFER_SIZE 4096
      17                 :             : 
      18                 :             : 
      19                 :             : struct _ValentBluezChannelService
      20                 :             : {
      21                 :             :   ValentChannelService  parent_instance;
      22                 :             : 
      23                 :             :   GDBusProxy           *proxy;
      24                 :             :   ValentBluezProfile   *profile;
      25                 :             :   GHashTable           *devices;
      26                 :             :   GHashTable           *muxers;
      27                 :             : };
      28                 :             : 
      29                 :             : static void   g_async_initable_iface_init (GAsyncInitableIface *iface);
      30                 :             : 
      31   [ +  +  +  - ]:          14 : G_DEFINE_FINAL_TYPE_WITH_CODE (ValentBluezChannelService, valent_bluez_channel_service, VALENT_TYPE_CHANNEL_SERVICE,
      32                 :             :                                G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, g_async_initable_iface_init))
      33                 :             : 
      34                 :             : /*
      35                 :             :  * ValentBluezProfile Callbacks
      36                 :             :  */
      37                 :             : static void
      38                 :           2 : valent_bluez_muxer_handshake_cb (ValentBluezMuxer *muxer,
      39                 :             :                                  GAsyncResult     *result,
      40                 :             :                                  gpointer          user_data)
      41                 :             : {
      42                 :           2 :   g_autoptr (GTask) task = G_TASK (g_steal_pointer (&user_data));
      43                 :           2 :   ValentBluezChannelService *self = g_task_get_source_object (task);
      44                 :           2 :   const char *object_path = g_task_get_task_data (task);
      45         [ +  - ]:           2 :   g_autoptr (ValentChannel) channel = NULL;
      46         [ +  - ]:           2 :   g_autoptr (GError) error = NULL;
      47                 :             : 
      48                 :           2 :   channel = valent_bluez_muxer_handshake_finish (muxer, result, &error);
      49         [ +  - ]:           2 :   if (channel != NULL)
      50                 :             :     {
      51         [ -  + ]:           2 :       g_hash_table_replace (self->muxers,
      52                 :           2 :                             g_strdup (object_path),
      53                 :             :                             g_object_ref (muxer));
      54                 :           2 :       valent_channel_service_channel (VALENT_CHANNEL_SERVICE (self), channel);
      55                 :             :     }
      56         [ #  # ]:           0 :   else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
      57                 :             :     {
      58                 :           0 :       g_warning ("%s(): \"%s\": %s", G_STRFUNC, object_path, error->message);
      59                 :             :     }
      60                 :             : 
      61         [ -  + ]:           2 :   g_task_return_boolean (task, TRUE);
      62                 :           2 : }
      63                 :             : 
      64                 :             : static void
      65                 :           2 : on_connection_opened (ValentBluezProfile *profile,
      66                 :             :                       GSocketConnection  *connection,
      67                 :             :                       const char         *object_path,
      68                 :             :                       gpointer            user_data)
      69                 :             : {
      70                 :           2 :   ValentBluezChannelService *self = VALENT_BLUEZ_CHANNEL_SERVICE (user_data);
      71                 :           4 :   g_autoptr (JsonNode) identity = NULL;
      72         [ +  - ]:           2 :   g_autoptr (GTask) task = NULL;
      73         [ +  - ]:           2 :   g_autoptr (GCancellable) cancellable = NULL;
      74                 :             : 
      75         [ -  + ]:           2 :   g_assert (VALENT_IS_BLUEZ_CHANNEL_SERVICE (self));
      76   [ +  -  +  -  :           2 :   g_assert (G_IS_SOCKET_CONNECTION (connection));
             -  +  -  - ]
      77         [ +  - ]:           2 :   g_assert (object_path != NULL);
      78                 :             : 
      79                 :           2 :   task = g_task_new (self, NULL, NULL, NULL);
      80         [ -  + ]:           4 :   g_task_set_task_data (task, g_strdup (object_path), g_free);
      81         [ +  - ]:           2 :   g_task_set_source_tag (task, on_connection_opened);
      82                 :             : 
      83                 :           2 :   cancellable = valent_object_ref_cancellable (VALENT_OBJECT (self));
      84                 :           2 :   identity = valent_channel_service_ref_identity (VALENT_CHANNEL_SERVICE (self));
      85         [ +  - ]:           2 :   valent_bluez_muxer_handshake (G_IO_STREAM (connection),
      86                 :             :                                 identity,
      87                 :             :                                 cancellable,
      88                 :             :                                 (GAsyncReadyCallback)valent_bluez_muxer_handshake_cb,
      89                 :             :                                 g_object_ref (task));
      90                 :           2 : }
      91                 :             : 
      92                 :             : static void
      93                 :           0 : on_connection_closed (ValentBluezProfile *profile,
      94                 :             :                       const char         *object_path,
      95                 :             :                       gpointer            user_data)
      96                 :             : {
      97                 :           0 :   ValentBluezChannelService *self = VALENT_BLUEZ_CHANNEL_SERVICE (user_data);
      98                 :           0 :   gpointer key, value;
      99                 :             : 
     100         [ #  # ]:           0 :   g_assert (VALENT_IS_BLUEZ_CHANNEL_SERVICE (self));
     101         [ #  # ]:           0 :   g_assert (object_path != NULL);
     102                 :             : 
     103         [ #  # ]:           0 :   if (g_hash_table_steal_extended (self->muxers, object_path, &key, &value))
     104                 :             :     {
     105                 :           0 :       valent_bluez_muxer_close (value, NULL, NULL);
     106                 :           0 :       g_free (key);
     107                 :           0 :       g_object_unref (value);
     108                 :             :     }
     109                 :           0 : }
     110                 :             : 
     111                 :             : /*
     112                 :             :  * GDBusObjectManager
     113                 :             :  */
     114                 :             : static void
     115                 :           6 : on_interfaces_added (ValentBluezChannelService *self,
     116                 :             :                      const char                *object_path,
     117                 :             :                      GVariant                  *interfaces)
     118                 :             : {
     119                 :           6 :   GDBusConnection *connection;
     120                 :           6 :   GVariantIter iter;
     121                 :           6 :   const char *interface;
     122                 :           6 :   GVariant *properties;
     123                 :             : 
     124                 :           6 :   connection = g_dbus_proxy_get_connection (self->proxy);
     125                 :           6 :   g_variant_iter_init (&iter, interfaces);
     126         [ +  + ]:          16 :   while (g_variant_iter_next (&iter, "{&s@a{sv}}", &interface, &properties))
     127                 :             :     {
     128         [ +  + ]:          10 :       if (g_strcmp0 (interface, "org.bluez.Device1") == 0)
     129                 :             :         {
     130                 :          12 :           g_autoptr (ValentBluezDevice) device = NULL;
     131                 :             : 
     132                 :           2 :           device = valent_bluez_device_new (connection,
     133                 :             :                                             object_path,
     134                 :             :                                             properties);
     135   [ -  +  +  - ]:           4 :           g_hash_table_replace (self->devices,
     136                 :           2 :                                 g_strdup (object_path),
     137                 :             :                                 g_object_ref (device));
     138                 :             :         }
     139                 :             : 
     140                 :          10 :       g_variant_unref (properties);
     141                 :             :     }
     142                 :           6 : }
     143                 :             : 
     144                 :             : static void
     145                 :           0 : on_interfaces_removed (ValentBluezChannelService  *self,
     146                 :             :                        const char                 *object_path,
     147                 :             :                        const char                **interfaces)
     148                 :             : {
     149                 :           0 :   gpointer key, value;
     150                 :             : 
     151         [ #  # ]:           0 :   g_assert (VALENT_IS_BLUEZ_CHANNEL_SERVICE (self));
     152         [ #  # ]:           0 :   g_assert (object_path != NULL);
     153                 :             : 
     154         [ #  # ]:           0 :   if (!g_strv_contains (interfaces, "org.bluez.Device1"))
     155                 :           0 :     return;
     156                 :             : 
     157         [ #  # ]:           0 :   if (g_hash_table_steal_extended (self->muxers, object_path, &key, &value))
     158                 :             :     {
     159                 :           0 :       valent_bluez_muxer_close (value, NULL, NULL);
     160                 :           0 :       g_free (key);
     161                 :           0 :       g_object_unref (value);
     162                 :             :     }
     163                 :             : 
     164                 :           0 :   g_hash_table_remove (self->devices, object_path);
     165                 :             : }
     166                 :             : 
     167                 :             : static void
     168                 :           0 : on_g_signal (GDBusProxy                *proxy,
     169                 :             :              char                      *sender_name,
     170                 :             :              char                      *signal_name,
     171                 :             :              GVariant                  *parameters,
     172                 :             :              ValentBluezChannelService *self)
     173                 :             : {
     174                 :           0 :   g_autofree char *name_owner = NULL;
     175                 :             : 
     176         [ #  # ]:           0 :   g_assert (VALENT_IS_BLUEZ_CHANNEL_SERVICE (self));
     177                 :             : 
     178                 :           0 :   name_owner = g_dbus_proxy_get_name_owner (proxy);
     179         [ #  # ]:           0 :   if (name_owner != NULL)
     180                 :           0 :     return;
     181                 :             : 
     182         [ #  # ]:           0 :   if (g_strcmp0 (signal_name, "InterfacesAdded") == 0)
     183                 :             :     {
     184                 :           0 :       const char *object_path;
     185                 :           0 :       GVariant *ifaces_props;
     186                 :             : 
     187                 :           0 :       g_variant_get (parameters, "(&o@a{sa{sv}})", &object_path, &ifaces_props);
     188                 :           0 :       on_interfaces_added (self, object_path, ifaces_props);
     189                 :             :     }
     190         [ #  # ]:           0 :   else if (g_strcmp0 (signal_name, "InterfacesRemoved") == 0)
     191                 :             :     {
     192                 :           0 :       const char *object_path;
     193                 :           0 :       const char **interfaces;
     194                 :             : 
     195                 :           0 :       g_variant_get (parameters, "(&o^a&s)", &object_path, &interfaces);
     196                 :           0 :       on_interfaces_removed (self, object_path, interfaces);
     197                 :             :     }
     198                 :             : }
     199                 :             : 
     200                 :             : static void
     201                 :           2 : activate_cb (GObject      *object,
     202                 :             :              GAsyncResult *result,
     203                 :             :              gpointer      user_data)
     204                 :             : {
     205                 :           2 :   ValentBluezChannelService *self = g_task_get_source_object (G_TASK (result));
     206                 :           4 :   g_autoptr (GError) error = NULL;
     207                 :             : 
     208         [ +  - ]:           2 :   if (g_task_propagate_boolean (G_TASK (result), &error))
     209                 :             :     {
     210                 :           2 :       valent_extension_plugin_state_changed (VALENT_EXTENSION (self),
     211                 :             :                                              VALENT_PLUGIN_STATE_ACTIVE,
     212                 :             :                                              NULL);
     213                 :             :     }
     214                 :             :   else
     215                 :             :     {
     216                 :           0 :       valent_extension_plugin_state_changed (VALENT_EXTENSION (self),
     217                 :             :                                              VALENT_PLUGIN_STATE_ERROR,
     218                 :             :                                              error);
     219                 :             :     }
     220                 :           2 : }
     221                 :             : 
     222                 :             : static void
     223                 :           2 : get_managed_objects_cb (GDBusProxy   *proxy,
     224                 :             :                         GAsyncResult *result,
     225                 :             :                         gpointer      user_data)
     226                 :             : {
     227                 :           4 :   g_autoptr (GTask) task = G_TASK (g_steal_pointer (&user_data));
     228                 :           2 :   ValentBluezChannelService *self = g_task_get_source_object (task);
     229         [ +  - ]:           2 :   g_autoptr (GVariant) reply = NULL;
     230         [ -  - ]:           2 :   g_autoptr (GVariant) objects = NULL;
     231                 :           2 :   GError *error = NULL;
     232                 :           2 :   const char *object_path;
     233                 :           2 :   GVariant *interfaces;
     234                 :           2 :   GVariantIter iter;
     235                 :             : 
     236                 :           2 :   reply = g_dbus_proxy_call_finish (proxy, result, &error);
     237         [ -  + ]:           2 :   if (reply == NULL)
     238                 :             :     {
     239                 :           0 :       g_task_return_error (task, g_steal_pointer (&error));
     240         [ #  # ]:           0 :       return;
     241                 :             :     }
     242                 :             : 
     243                 :           2 :   objects = g_variant_get_child_value (reply, 0);
     244                 :           2 :   g_variant_iter_init (&iter, objects);
     245         [ +  + ]:           8 :   while (g_variant_iter_next (&iter, "{&o@a{sa{sv}}}", &object_path, &interfaces))
     246                 :             :     {
     247                 :           6 :       on_interfaces_added (self, object_path, interfaces);
     248                 :           6 :       g_variant_unref (interfaces);
     249                 :             :     }
     250                 :             : 
     251         [ +  - ]:           2 :   g_task_return_boolean (task, TRUE);
     252                 :             : }
     253                 :             : 
     254                 :             : static inline void
     255                 :           2 : valent_bluez_profile_register_cb (ValentBluezProfile *profile,
     256                 :             :                                   GAsyncResult       *result,
     257                 :             :                                   gpointer            user_data)
     258                 :             : {
     259                 :           4 :   g_autoptr (GTask) task = G_TASK (g_steal_pointer (&user_data));
     260                 :           2 :   ValentBluezChannelService *self = g_task_get_source_object (task);
     261                 :           2 :   GCancellable *cancellable = g_task_get_cancellable (task);
     262                 :           2 :   GError *error = NULL;
     263                 :             : 
     264         [ -  + ]:           2 :   if (!valent_bluez_profile_register_finish (profile, result, &error))
     265                 :             :     {
     266                 :           0 :       g_task_return_error (task, g_steal_pointer (&error));
     267         [ #  # ]:           0 :       return;
     268                 :             :     }
     269                 :             : 
     270         [ +  - ]:           2 :   g_dbus_proxy_call (self->proxy,
     271                 :             :                      "GetManagedObjects",
     272                 :             :                      NULL,
     273                 :             :                      G_DBUS_CALL_FLAGS_NONE,
     274                 :             :                      -1,
     275                 :             :                      cancellable,
     276                 :             :                      (GAsyncReadyCallback)get_managed_objects_cb,
     277                 :             :                      g_object_ref (task));
     278                 :             : }
     279                 :             : 
     280                 :             : static void
     281                 :           2 : on_name_owner_changed (GDBusProxy                *proxy,
     282                 :             :                        GParamSpec                *pspec,
     283                 :             :                        ValentBluezChannelService *self)
     284                 :             : {
     285                 :           4 :   g_autofree char *name_owner = NULL;
     286                 :             : 
     287         [ -  + ]:           2 :   g_assert (VALENT_IS_BLUEZ_CHANNEL_SERVICE (self));
     288                 :             : 
     289                 :           2 :   name_owner = g_dbus_proxy_get_name_owner (proxy);
     290         [ +  - ]:           2 :   if (name_owner != NULL)
     291                 :             :     {
     292                 :           2 :       g_autoptr (GTask) task = NULL;
     293         [ +  - ]:           2 :       g_autoptr (GCancellable) destroy = NULL;
     294                 :             : 
     295                 :           2 :       destroy = valent_object_ref_cancellable (VALENT_OBJECT (self));
     296                 :           2 :       task = g_task_new (self, destroy, activate_cb, NULL);
     297         [ +  - ]:           2 :       g_task_set_source_tag (task, on_name_owner_changed);
     298         [ +  - ]:           2 :       valent_bluez_profile_register (self->profile,
     299                 :             :                                      g_dbus_proxy_get_connection (proxy),
     300                 :             :                                      destroy,
     301                 :             :                                      (GAsyncReadyCallback)valent_bluez_profile_register_cb,
     302                 :             :                                      g_object_ref (task));
     303                 :             :     }
     304                 :             :   else
     305                 :             :     {
     306                 :           0 :       GHashTableIter iter;
     307                 :           0 :       ValentBluezMuxer *connection;
     308                 :             : 
     309                 :           0 :       g_hash_table_iter_init (&iter, self->muxers);
     310         [ #  # ]:           0 :       while (g_hash_table_iter_next (&iter, NULL, (void **)&connection))
     311                 :             :         {
     312                 :           0 :           valent_bluez_muxer_close (connection, NULL, NULL);
     313                 :           0 :           g_hash_table_iter_remove (&iter);
     314                 :             :         }
     315                 :             : 
     316                 :           0 :       g_hash_table_remove_all (self->devices);
     317                 :           0 :       valent_bluez_profile_unregister (self->profile);
     318                 :           0 :       valent_extension_plugin_state_changed (VALENT_EXTENSION (self),
     319                 :             :                                              VALENT_PLUGIN_STATE_INACTIVE,
     320                 :             :                                              NULL);
     321                 :             :     }
     322                 :           2 : }
     323                 :             : 
     324                 :             : /*
     325                 :             :  * ValentChannelService
     326                 :             :  */
     327                 :             : static void
     328                 :           2 : valent_bluez_channel_service_build_identity (ValentChannelService *service)
     329                 :             : {
     330                 :           2 :   ValentChannelServiceClass *klass;
     331                 :           4 :   g_autoptr (JsonNode) identity = NULL;
     332                 :             : 
     333         [ -  + ]:           2 :   g_assert (VALENT_IS_BLUEZ_CHANNEL_SERVICE (service));
     334                 :             : 
     335                 :             :   /* Chain-up */
     336                 :           2 :   klass = VALENT_CHANNEL_SERVICE_CLASS (valent_bluez_channel_service_parent_class);
     337                 :           2 :   klass->build_identity (service);
     338                 :             : 
     339                 :             :   /* Set the certificate on the packet
     340                 :             :    */
     341                 :           2 :   identity = valent_channel_service_ref_identity (service);
     342         [ +  - ]:           2 :   if (identity != NULL)
     343                 :             :     {
     344                 :           2 :       g_autoptr (GTlsCertificate) certificate = NULL;
     345         [ +  - ]:           2 :       g_autofree char *certificate_pem = NULL;
     346                 :           2 :       JsonObject *body;
     347                 :             : 
     348                 :           2 :       certificate = valent_channel_service_ref_certificate (service);
     349                 :           2 :       g_object_get (certificate, "certificate-pem", &certificate_pem, NULL);
     350                 :             : 
     351                 :           2 :       body = valent_packet_get_body (identity);
     352                 :           2 :       json_object_set_string_member (body, "certificate", certificate_pem);
     353                 :             :     }
     354                 :           2 : }
     355                 :             : 
     356                 :             : static void
     357                 :           2 : valent_bluez_channel_service_identify (ValentChannelService *service,
     358                 :             :                                        const char           *target)
     359                 :             : {
     360                 :           2 :   ValentBluezChannelService *self = VALENT_BLUEZ_CHANNEL_SERVICE (service);
     361                 :           2 :   g_autofree char *name_owner = NULL;
     362                 :           2 :   ValentBluezDevice *device;
     363                 :             : 
     364         [ -  + ]:           2 :   g_assert (VALENT_IS_BLUEZ_CHANNEL_SERVICE (self));
     365                 :             : 
     366                 :           2 :   name_owner = g_dbus_proxy_get_name_owner (self->proxy);
     367         [ -  + ]:           2 :   if (name_owner == NULL)
     368                 :           0 :     return;
     369                 :             : 
     370         [ -  + ]:           2 :   if (target != NULL)
     371                 :             :     {
     372                 :           0 :       device = g_hash_table_lookup (self->devices, target);
     373         [ #  # ]:           0 :       if (device != NULL)
     374                 :           0 :         valent_bluez_device_connect (device);
     375                 :             :     }
     376                 :             :   else
     377                 :             :     {
     378                 :           2 :       GHashTableIter iter;
     379                 :             : 
     380                 :           2 :       g_hash_table_iter_init (&iter, self->devices);
     381         [ +  + ]:           4 :       while (g_hash_table_iter_next (&iter, NULL, (void **)&device))
     382                 :           2 :         valent_bluez_device_connect (device);
     383                 :             :     }
     384                 :             : }
     385                 :             : 
     386                 :             : static void
     387                 :           2 : g_dbus_proxy_new_for_bus_cb (GObject      *object,
     388                 :             :                              GAsyncResult *result,
     389                 :             :                              gpointer      user_data)
     390                 :             : {
     391                 :           2 :   g_autoptr (GTask) task = G_TASK (user_data);
     392                 :           2 :   ValentBluezChannelService *self = g_task_get_source_object (task);
     393                 :           2 :   GError *error = NULL;
     394                 :             : 
     395                 :           2 :   self->proxy = g_dbus_proxy_new_for_bus_finish (result, &error);
     396         [ -  + ]:           2 :   if (self->proxy == NULL)
     397                 :             :     {
     398                 :           0 :       g_task_return_error (task, g_steal_pointer (&error));
     399         [ #  # ]:           0 :       return;
     400                 :             :     }
     401                 :             : 
     402                 :           2 :   g_signal_connect_object (self->proxy,
     403                 :             :                            "g-signal",
     404                 :             :                            G_CALLBACK (on_g_signal),
     405                 :             :                            self,
     406                 :             :                            G_CONNECT_DEFAULT);
     407                 :           2 :   g_signal_connect_object (self->proxy,
     408                 :             :                            "notify::g-name-owner",
     409                 :             :                            G_CALLBACK (on_name_owner_changed),
     410                 :             :                            self,
     411                 :             :                            G_CONNECT_DEFAULT);
     412                 :           2 :   on_name_owner_changed (self->proxy, NULL, self);
     413                 :             : 
     414         [ +  - ]:           2 :   g_task_return_boolean (task, TRUE);
     415                 :             : }
     416                 :             : 
     417                 :             : /*
     418                 :             :  * GAsyncInitable
     419                 :             :  */
     420                 :             : static void
     421                 :           2 : valent_bluez_channel_service_init_async (GAsyncInitable      *initable,
     422                 :             :                                          int                  io_priority,
     423                 :             :                                          GCancellable        *cancellable,
     424                 :             :                                          GAsyncReadyCallback  callback,
     425                 :             :                                          gpointer             user_data)
     426                 :             : {
     427                 :           4 :   g_autoptr (GTask) task = NULL;
     428                 :             : 
     429         [ -  + ]:           2 :   g_assert (VALENT_IS_CHANNEL_SERVICE (initable));
     430   [ -  +  -  -  :           2 :   g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
             -  -  -  - ]
     431                 :             : 
     432                 :           2 :   task = g_task_new (initable, cancellable, callback, user_data);
     433                 :           2 :   g_task_set_priority (task, io_priority);
     434         [ +  - ]:           2 :   g_task_set_source_tag (task, valent_bluez_channel_service_init_async);
     435                 :             : 
     436         [ +  - ]:           2 :   g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM,
     437                 :             :                             G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START,
     438                 :             :                             NULL,
     439                 :             :                             "org.bluez",
     440                 :             :                             "/",
     441                 :             :                             "org.freedesktop.DBus.ObjectManager",
     442                 :             :                             cancellable,
     443                 :             :                             (GAsyncReadyCallback)g_dbus_proxy_new_for_bus_cb,
     444                 :             :                             g_object_ref (task));
     445                 :           2 : }
     446                 :             : 
     447                 :             : static void
     448                 :           1 : g_async_initable_iface_init (GAsyncInitableIface *iface)
     449                 :             : {
     450                 :           1 :   iface->init_async = valent_bluez_channel_service_init_async;
     451                 :           1 : }
     452                 :             : 
     453                 :             : /*
     454                 :             :  * ValentObject
     455                 :             :  */
     456                 :             : static void
     457                 :           4 : valent_bluez_channel_service_destroy (ValentObject *object)
     458                 :             : {
     459                 :           4 :   ValentBluezChannelService *self = VALENT_BLUEZ_CHANNEL_SERVICE (object);
     460                 :             : 
     461         [ +  + ]:           4 :   if (self->proxy != NULL)
     462                 :             :     {
     463                 :           2 :       g_signal_handlers_disconnect_by_data (self->proxy, self);
     464         [ +  - ]:           2 :       g_clear_object (&self->proxy);
     465                 :             :     }
     466                 :             : 
     467         [ +  - ]:           4 :   if (self->profile != NULL)
     468                 :             :     {
     469                 :           4 :       g_signal_handlers_disconnect_by_data (self->profile, self);
     470                 :           4 :       valent_bluez_profile_unregister (self->profile);
     471                 :             :     }
     472                 :             : 
     473                 :           4 :   VALENT_OBJECT_CLASS (valent_bluez_channel_service_parent_class)->destroy (object);
     474                 :           4 : }
     475                 :             : 
     476                 :             : /*
     477                 :             :  * GObject
     478                 :             :  */
     479                 :             : static void
     480                 :           2 : valent_bluez_channel_service_finalize (GObject *object)
     481                 :             : {
     482                 :           2 :   ValentBluezChannelService *self = VALENT_BLUEZ_CHANNEL_SERVICE (object);
     483                 :             : 
     484         [ -  + ]:           2 :   g_clear_object (&self->proxy);
     485         [ +  - ]:           2 :   g_clear_object (&self->profile);
     486         [ +  - ]:           2 :   g_clear_pointer (&self->devices, g_hash_table_unref);
     487         [ +  - ]:           2 :   g_clear_pointer (&self->muxers, g_hash_table_unref);
     488                 :             : 
     489                 :           2 :   G_OBJECT_CLASS (valent_bluez_channel_service_parent_class)->finalize (object);
     490                 :           2 : }
     491                 :             : 
     492                 :             : static void
     493                 :           1 : valent_bluez_channel_service_class_init (ValentBluezChannelServiceClass *klass)
     494                 :             : {
     495                 :           1 :   GObjectClass *object_class = G_OBJECT_CLASS (klass);
     496                 :           1 :   ValentObjectClass *vobject_class = VALENT_OBJECT_CLASS (klass);
     497                 :           1 :   ValentChannelServiceClass *service_class = VALENT_CHANNEL_SERVICE_CLASS (klass);
     498                 :             : 
     499                 :           1 :   object_class->finalize = valent_bluez_channel_service_finalize;
     500                 :             : 
     501                 :           1 :   vobject_class->destroy = valent_bluez_channel_service_destroy;
     502                 :             : 
     503                 :           1 :   service_class->build_identity = valent_bluez_channel_service_build_identity;
     504                 :           1 :   service_class->identify = valent_bluez_channel_service_identify;
     505                 :             : }
     506                 :             : 
     507                 :             : static void
     508                 :           2 : valent_bluez_channel_service_init (ValentBluezChannelService *self)
     509                 :             : {
     510                 :           2 :   self->profile = valent_bluez_profile_new ();
     511                 :           2 :   g_signal_connect_object (self->profile,
     512                 :             :                            "connection-opened",
     513                 :             :                            G_CALLBACK (on_connection_opened),
     514                 :             :                            self,
     515                 :             :                            G_CONNECT_DEFAULT);
     516                 :           2 :   g_signal_connect_object (self->profile,
     517                 :             :                            "connection-closed",
     518                 :             :                            G_CALLBACK (on_connection_closed),
     519                 :             :                            self,
     520                 :             :                            G_CONNECT_DEFAULT);
     521                 :             : 
     522                 :           2 :   self->devices = g_hash_table_new_full (g_str_hash,
     523                 :             :                                          g_str_equal,
     524                 :             :                                          g_free,
     525                 :             :                                          g_object_unref);
     526                 :           2 :   self->muxers = g_hash_table_new_full (g_str_hash,
     527                 :             :                                         g_str_equal,
     528                 :             :                                         g_free,
     529                 :             :                                         g_object_unref);
     530                 :           2 : }
     531                 :             : 
        

Generated by: LCOV version 2.0-1