(root)/
glib-2.79.0/
gio/
gdbusnameowning.c
       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 "gdbusnameowning.h"
      29  #include "gdbuserror.h"
      30  #include "gdbusprivate.h"
      31  #include "gdbusconnection.h"
      32  
      33  #include "glibintl.h"
      34  
      35  G_LOCK_DEFINE_STATIC (lock);
      36  
      37  /* ---------------------------------------------------------------------------------------------------- */
      38  
      39  typedef enum
      40  {
      41    PREVIOUS_CALL_NONE = 0,
      42    PREVIOUS_CALL_ACQUIRED,
      43    PREVIOUS_CALL_LOST,
      44  } PreviousCall;
      45  
      46  typedef struct
      47  {
      48    gint                      ref_count;  /* (atomic) */
      49    guint                     id;
      50    GBusNameOwnerFlags        flags;
      51    gchar                    *name;
      52    GBusAcquiredCallback      bus_acquired_handler;
      53    GBusNameAcquiredCallback  name_acquired_handler;
      54    GBusNameLostCallback      name_lost_handler;
      55    gpointer                  user_data;
      56    GDestroyNotify            user_data_free_func;
      57    GMainContext             *main_context;
      58  
      59    PreviousCall              previous_call;
      60  
      61    GDBusConnection          *connection;
      62    gulong                    disconnected_signal_handler_id;
      63    guint                     name_acquired_subscription_id;
      64    guint                     name_lost_subscription_id;
      65  
      66    gboolean                  cancelled; /* must hold lock when reading or modifying */
      67  
      68    gboolean                  needs_release;
      69  } Client;
      70  
      71  static guint next_global_id = 1;
      72  static GHashTable *map_id_to_client = NULL;
      73  
      74  
      75  static Client *
      76  client_ref (Client *client)
      77  {
      78    g_atomic_int_inc (&client->ref_count);
      79    return client;
      80  }
      81  
      82  static void
      83  client_unref (Client *client)
      84  {
      85    if (g_atomic_int_dec_and_test (&client->ref_count))
      86      {
      87        if (client->connection != NULL)
      88          {
      89            if (client->disconnected_signal_handler_id > 0)
      90              g_signal_handler_disconnect (client->connection, client->disconnected_signal_handler_id);
      91            if (client->name_acquired_subscription_id > 0)
      92              g_dbus_connection_signal_unsubscribe (client->connection, client->name_acquired_subscription_id);
      93            if (client->name_lost_subscription_id > 0)
      94              g_dbus_connection_signal_unsubscribe (client->connection, client->name_lost_subscription_id);
      95            g_object_unref (client->connection);
      96          }
      97        g_main_context_unref (client->main_context);
      98        g_free (client->name);
      99        if (client->user_data_free_func != NULL)
     100          client->user_data_free_func (client->user_data);
     101        g_free (client);
     102      }
     103  }
     104  
     105  /* ---------------------------------------------------------------------------------------------------- */
     106  
     107  
     108  typedef enum
     109  {
     110    CALL_TYPE_NAME_ACQUIRED,
     111    CALL_TYPE_NAME_LOST
     112  } CallType;
     113  
     114  typedef struct
     115  {
     116    Client *client;
     117  
     118    /* keep this separate because client->connection may
     119     * be set to NULL after scheduling the call
     120     */
     121    GDBusConnection *connection;
     122  
     123    /* set to TRUE to call acquired */
     124    CallType call_type;
     125  } CallHandlerData;
     126  
     127  static void
     128  call_handler_data_free (CallHandlerData *data)
     129  {
     130    if (data->connection != NULL)
     131      g_object_unref (data->connection);
     132    client_unref (data->client);
     133    g_free (data);
     134  }
     135  
     136  static void
     137  actually_do_call (Client *client, GDBusConnection *connection, CallType call_type)
     138  {
     139    switch (call_type)
     140      {
     141      case CALL_TYPE_NAME_ACQUIRED:
     142        if (client->name_acquired_handler != NULL)
     143          {
     144            client->name_acquired_handler (connection,
     145                                           client->name,
     146                                           client->user_data);
     147          }
     148        break;
     149  
     150      case CALL_TYPE_NAME_LOST:
     151        if (client->name_lost_handler != NULL)
     152          {
     153            client->name_lost_handler (connection,
     154                                       client->name,
     155                                       client->user_data);
     156          }
     157        break;
     158  
     159      default:
     160        g_assert_not_reached ();
     161        break;
     162      }
     163  }
     164  
     165  static gboolean
     166  call_in_idle_cb (gpointer _data)
     167  {
     168    CallHandlerData *data = _data;
     169    actually_do_call (data->client, data->connection, data->call_type);
     170    return FALSE;
     171  }
     172  
     173  static void
     174  schedule_call_in_idle (Client *client, CallType  call_type)
     175  {
     176    CallHandlerData *data;
     177    GSource *idle_source;
     178  
     179    data = g_new0 (CallHandlerData, 1);
     180    data->client = client_ref (client);
     181    data->connection = client->connection != NULL ? g_object_ref (client->connection) : NULL;
     182    data->call_type = call_type;
     183  
     184    idle_source = g_idle_source_new ();
     185    g_source_set_priority (idle_source, G_PRIORITY_HIGH);
     186    g_source_set_callback (idle_source,
     187                           call_in_idle_cb,
     188                           data,
     189                           (GDestroyNotify) call_handler_data_free);
     190    g_source_set_static_name (idle_source, "[gio, gdbusnameowning.c] call_in_idle_cb");
     191    g_source_attach (idle_source, client->main_context);
     192    g_source_unref (idle_source);
     193  }
     194  
     195  static void
     196  do_call (Client *client, CallType call_type)
     197  {
     198    GMainContext *current_context;
     199  
     200    /* only schedule in idle if we're not in the right thread */
     201    current_context = g_main_context_ref_thread_default ();
     202    if (current_context != client->main_context)
     203      schedule_call_in_idle (client, call_type);
     204    else
     205      actually_do_call (client, client->connection, call_type);
     206    g_main_context_unref (current_context);
     207  }
     208  
     209  static void
     210  call_acquired_handler (Client *client)
     211  {
     212    G_LOCK (lock);
     213    if (client->previous_call != PREVIOUS_CALL_ACQUIRED)
     214      {
     215        client->previous_call = PREVIOUS_CALL_ACQUIRED;
     216        if (!client->cancelled)
     217          {
     218            G_UNLOCK (lock);
     219            do_call (client, CALL_TYPE_NAME_ACQUIRED);
     220            goto out;
     221          }
     222      }
     223    G_UNLOCK (lock);
     224   out:
     225    ;
     226  }
     227  
     228  static void
     229  call_lost_handler (Client  *client)
     230  {
     231    G_LOCK (lock);
     232    if (client->previous_call != PREVIOUS_CALL_LOST)
     233      {
     234        client->previous_call = PREVIOUS_CALL_LOST;
     235        if (!client->cancelled)
     236          {
     237            G_UNLOCK (lock);
     238            do_call (client, CALL_TYPE_NAME_LOST);
     239            goto out;
     240          }
     241      }
     242    G_UNLOCK (lock);
     243   out:
     244    ;
     245  }
     246  
     247  /* ---------------------------------------------------------------------------------------------------- */
     248  
     249  static void
     250  on_name_lost_or_acquired (GDBusConnection  *connection,
     251                            const gchar      *sender_name,
     252                            const gchar      *object_path,
     253                            const gchar      *interface_name,
     254                            const gchar      *signal_name,
     255                            GVariant         *parameters,
     256                            gpointer          user_data)
     257  {
     258    Client *client = user_data;
     259    const gchar *name;
     260  
     261    if (g_strcmp0 (object_path, "/org/freedesktop/DBus") != 0 ||
     262        g_strcmp0 (interface_name, "org.freedesktop.DBus") != 0 ||
     263        g_strcmp0 (sender_name, "org.freedesktop.DBus") != 0)
     264      goto out;
     265  
     266    if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(s)")))
     267      {
     268        g_warning ("%s signal had unexpected signature %s", signal_name,
     269                   g_variant_get_type_string (parameters));
     270        goto out;
     271      }
     272  
     273    if (g_strcmp0 (signal_name, "NameLost") == 0)
     274      {
     275        g_variant_get (parameters, "(&s)", &name);
     276        if (g_strcmp0 (name, client->name) == 0)
     277          {
     278            call_lost_handler (client);
     279          }
     280      }
     281    else if (g_strcmp0 (signal_name, "NameAcquired") == 0)
     282      {
     283        g_variant_get (parameters, "(&s)", &name);
     284        if (g_strcmp0 (name, client->name) == 0)
     285          {
     286            call_acquired_handler (client);
     287          }
     288      }
     289   out:
     290    ;
     291  }
     292  
     293  /* ---------------------------------------------------------------------------------------------------- */
     294  
     295  static void
     296  request_name_cb (GObject      *source_object,
     297                   GAsyncResult *res,
     298                   gpointer      user_data)
     299  {
     300    Client *client = user_data;
     301    GVariant *result;
     302    guint32 request_name_reply;
     303    gboolean unsubscribe;
     304  
     305    request_name_reply = 0;
     306    result = NULL;
     307  
     308    /* don't use client->connection - it may be NULL already */
     309    result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
     310                                            res,
     311                                            NULL);
     312    if (result != NULL)
     313      {
     314        g_variant_get (result, "(u)", &request_name_reply);
     315        g_variant_unref (result);
     316      }
     317  
     318    unsubscribe = FALSE;
     319  
     320    switch (request_name_reply)
     321      {
     322      case 1: /* DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER */
     323        /* We got the name - now listen for NameLost and NameAcquired */
     324        call_acquired_handler (client);
     325        break;
     326  
     327      case 2: /* DBUS_REQUEST_NAME_REPLY_IN_QUEUE */
     328        /* Waiting in line - listen for NameLost and NameAcquired */
     329        call_lost_handler (client);
     330        break;
     331  
     332      default:
     333        /* assume we couldn't get the name - explicit fallthrough */
     334      case 3: /* DBUS_REQUEST_NAME_REPLY_EXISTS */
     335      case 4: /* DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER */
     336        /* Some other part of the process is already owning the name */
     337        call_lost_handler (client);
     338        unsubscribe = TRUE;
     339        client->needs_release = FALSE;
     340        break;
     341      }
     342  
     343    /* If we’re not the owner and not in the queue, there’s no point in continuing
     344     * to listen to NameAcquired or NameLost. */
     345    if (unsubscribe)
     346      {
     347        GDBusConnection *connection = NULL;
     348  
     349        /* make sure we use a known good Connection object since it may be set to
     350         * NULL at any point after being cancelled
     351         */
     352        G_LOCK (lock);
     353        if (!client->cancelled)
     354          connection = g_object_ref (client->connection);
     355        G_UNLOCK (lock);
     356  
     357        if (connection != NULL)
     358          {
     359            if (client->name_acquired_subscription_id > 0)
     360              g_dbus_connection_signal_unsubscribe (client->connection, client->name_acquired_subscription_id);
     361            if (client->name_lost_subscription_id > 0)
     362              g_dbus_connection_signal_unsubscribe (client->connection, client->name_lost_subscription_id);
     363            client->name_acquired_subscription_id = 0;
     364            client->name_lost_subscription_id = 0;
     365  
     366            g_object_unref (connection);
     367          }
     368      }
     369  
     370    client_unref (client);
     371  }
     372  
     373  /* ---------------------------------------------------------------------------------------------------- */
     374  
     375  static void
     376  on_connection_disconnected (GDBusConnection *connection,
     377                              gboolean         remote_peer_vanished,
     378                              GError          *error,
     379                              gpointer         user_data)
     380  {
     381    Client *client = user_data;
     382  
     383    if (client->disconnected_signal_handler_id > 0)
     384      g_signal_handler_disconnect (client->connection, client->disconnected_signal_handler_id);
     385    if (client->name_acquired_subscription_id > 0)
     386      g_dbus_connection_signal_unsubscribe (client->connection, client->name_acquired_subscription_id);
     387    if (client->name_lost_subscription_id > 0)
     388      g_dbus_connection_signal_unsubscribe (client->connection, client->name_lost_subscription_id);
     389    g_object_unref (client->connection);
     390    client->disconnected_signal_handler_id = 0;
     391    client->name_acquired_subscription_id = 0;
     392    client->name_lost_subscription_id = 0;
     393    client->connection = NULL;
     394  
     395    call_lost_handler (client);
     396  }
     397  
     398  /* ---------------------------------------------------------------------------------------------------- */
     399  
     400  static void
     401  has_connection (Client *client)
     402  {
     403    /* listen for disconnection */
     404    client->disconnected_signal_handler_id = g_signal_connect (client->connection,
     405                                                               "closed",
     406                                                               G_CALLBACK (on_connection_disconnected),
     407                                                               client);
     408  
     409    /* Start listening to NameLost and NameAcquired messages. We hold
     410     * references to the Client in the signal closures, since it’s possible
     411     * for a signal to be in-flight after unsubscribing the signal handler.
     412     * This creates a reference count cycle, but that’s explicitly broken by
     413     * disconnecting the signal handlers before calling client_unref() in
     414     * g_bus_unown_name().
     415     *
     416     * Subscribe to NameLost and NameAcquired before calling RequestName() to
     417     * avoid the potential race of losing the name between receiving a reply to
     418     * RequestName() and subscribing to NameLost. The #PreviousCall state will
     419     * ensure that the user callbacks get called an appropriate number of times. */
     420    client->name_lost_subscription_id =
     421      g_dbus_connection_signal_subscribe (client->connection,
     422                                          "org.freedesktop.DBus",
     423                                          "org.freedesktop.DBus",
     424                                          "NameLost",
     425                                          "/org/freedesktop/DBus",
     426                                          client->name,
     427                                          G_DBUS_SIGNAL_FLAGS_NONE,
     428                                          on_name_lost_or_acquired,
     429                                          client_ref (client),
     430                                          (GDestroyNotify) client_unref);
     431    client->name_acquired_subscription_id =
     432      g_dbus_connection_signal_subscribe (client->connection,
     433                                          "org.freedesktop.DBus",
     434                                          "org.freedesktop.DBus",
     435                                          "NameAcquired",
     436                                          "/org/freedesktop/DBus",
     437                                          client->name,
     438                                          G_DBUS_SIGNAL_FLAGS_NONE,
     439                                          on_name_lost_or_acquired,
     440                                          client_ref (client),
     441                                          (GDestroyNotify) client_unref);
     442  
     443    /* attempt to acquire the name */
     444    client->needs_release = TRUE;
     445    g_dbus_connection_call (client->connection,
     446                            "org.freedesktop.DBus",  /* bus name */
     447                            "/org/freedesktop/DBus", /* object path */
     448                            "org.freedesktop.DBus",  /* interface name */
     449                            "RequestName",           /* method name */
     450                            g_variant_new ("(su)",
     451                                           client->name,
     452                                           client->flags),
     453                            G_VARIANT_TYPE ("(u)"),
     454                            G_DBUS_CALL_FLAGS_NONE,
     455                            -1,
     456                            NULL,
     457                            (GAsyncReadyCallback) request_name_cb,
     458                            client_ref (client));
     459  }
     460  
     461  
     462  static void
     463  connection_get_cb (GObject      *source_object,
     464                     GAsyncResult *res,
     465                     gpointer      user_data)
     466  {
     467    Client *client = user_data;
     468  
     469    /* must not do anything if already cancelled */
     470    G_LOCK (lock);
     471    if (client->cancelled)
     472      {
     473        G_UNLOCK (lock);
     474        goto out;
     475      }
     476    G_UNLOCK (lock);
     477  
     478    client->connection = g_bus_get_finish (res, NULL);
     479    if (client->connection == NULL)
     480      {
     481        call_lost_handler (client);
     482        goto out;
     483      }
     484  
     485    /* No need to schedule this in idle as we're already in the thread
     486     * that the user called g_bus_own_name() from. This is because
     487     * g_bus_get() guarantees that.
     488     *
     489     * Also, we need to ensure that the handler is invoked *before*
     490     * we call RequestName(). Otherwise there is a race.
     491     */
     492    if (client->bus_acquired_handler != NULL)
     493      {
     494        client->bus_acquired_handler (client->connection,
     495                                      client->name,
     496                                      client->user_data);
     497      }
     498  
     499    has_connection (client);
     500  
     501   out:
     502    client_unref (client);
     503  }
     504  
     505  /* ---------------------------------------------------------------------------------------------------- */
     506  
     507  /**
     508   * g_bus_own_name_on_connection:
     509   * @connection: a #GDBusConnection
     510   * @name: the well-known name to own
     511   * @flags: a set of flags from the #GBusNameOwnerFlags enumeration
     512   * @name_acquired_handler: (nullable) (scope notified): handler to invoke when
     513   *   @name is acquired or %NULL
     514   * @name_lost_handler: (nullable) (scope notified): handler to invoke when @name
     515   *   is lost or %NULL
     516   * @user_data: user data to pass to handlers
     517   * @user_data_free_func: (nullable): function for freeing @user_data or %NULL
     518   *
     519   * Like g_bus_own_name() but takes a #GDBusConnection instead of a
     520   * #GBusType.
     521   *
     522   * Returns: an identifier (never 0) that can be used with
     523   *     g_bus_unown_name() to stop owning the name
     524   *
     525   * Since: 2.26
     526   */
     527  guint
     528  g_bus_own_name_on_connection (GDBusConnection          *connection,
     529                                const gchar              *name,
     530                                GBusNameOwnerFlags        flags,
     531                                GBusNameAcquiredCallback  name_acquired_handler,
     532                                GBusNameLostCallback      name_lost_handler,
     533                                gpointer                  user_data,
     534                                GDestroyNotify            user_data_free_func)
     535  {
     536    Client *client;
     537  
     538    g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
     539    g_return_val_if_fail (g_dbus_is_name (name) && !g_dbus_is_unique_name (name), 0);
     540  
     541    G_LOCK (lock);
     542  
     543    client = g_new0 (Client, 1);
     544    client->ref_count = 1;
     545    client->id = next_global_id++; /* TODO: uh oh, handle overflow */
     546    client->name = g_strdup (name);
     547    client->flags = flags;
     548    client->name_acquired_handler = name_acquired_handler;
     549    client->name_lost_handler = name_lost_handler;
     550    client->user_data = user_data;
     551    client->user_data_free_func = user_data_free_func;
     552    client->main_context = g_main_context_ref_thread_default ();
     553  
     554    client->connection = g_object_ref (connection);
     555  
     556    if (map_id_to_client == NULL)
     557      {
     558        map_id_to_client = g_hash_table_new (g_direct_hash, g_direct_equal);
     559      }
     560    g_hash_table_insert (map_id_to_client,
     561                         GUINT_TO_POINTER (client->id),
     562                         client);
     563  
     564    G_UNLOCK (lock);
     565  
     566    has_connection (client);
     567  
     568    return client->id;
     569  }
     570  
     571  /**
     572   * g_bus_own_name:
     573   * @bus_type: the type of bus to own a name on
     574   * @name: the well-known name to own
     575   * @flags: a set of flags from the #GBusNameOwnerFlags enumeration
     576   * @bus_acquired_handler: (nullable) (scope notified): handler to invoke when
     577   *   connected to the bus of type @bus_type or %NULL
     578   * @name_acquired_handler: (nullable) (scope notified): handler to invoke when
     579   *   @name is acquired or %NULL
     580   * @name_lost_handler: (nullable) (scope notified): handler to invoke when @name
     581   *   is lost or %NULL
     582   * @user_data: user data to pass to handlers
     583   * @user_data_free_func: (nullable): function for freeing @user_data or %NULL
     584   *
     585   * Starts acquiring @name on the bus specified by @bus_type and calls
     586   * @name_acquired_handler and @name_lost_handler when the name is
     587   * acquired respectively lost. Callbacks will be invoked in the 
     588   * [thread-default main context][g-main-context-push-thread-default]
     589   * of the thread you are calling this function from.
     590   *
     591   * You are guaranteed that one of the @name_acquired_handler and @name_lost_handler
     592   * callbacks will be invoked after calling this function - there are three
     593   * possible cases:
     594   * 
     595   * - @name_lost_handler with a %NULL connection (if a connection to the bus
     596   *   can't be made).
     597   *
     598   * - @bus_acquired_handler then @name_lost_handler (if the name can't be
     599   *   obtained)
     600   *
     601   * - @bus_acquired_handler then @name_acquired_handler (if the name was
     602   *   obtained).
     603   *
     604   * When you are done owning the name, just call g_bus_unown_name()
     605   * with the owner id this function returns.
     606   *
     607   * If the name is acquired or lost (for example another application
     608   * could acquire the name if you allow replacement or the application
     609   * currently owning the name exits), the handlers are also invoked.
     610   * If the #GDBusConnection that is used for attempting to own the name
     611   * closes, then @name_lost_handler is invoked since it is no longer
     612   * possible for other processes to access the process.
     613   *
     614   * You cannot use g_bus_own_name() several times for the same name (unless
     615   * interleaved with calls to g_bus_unown_name()) - only the first call
     616   * will work.
     617   *
     618   * Another guarantee is that invocations of @name_acquired_handler
     619   * and @name_lost_handler are guaranteed to alternate; that
     620   * is, if @name_acquired_handler is invoked then you are
     621   * guaranteed that the next time one of the handlers is invoked, it
     622   * will be @name_lost_handler. The reverse is also true.
     623   *
     624   * If you plan on exporting objects (using e.g.
     625   * g_dbus_connection_register_object()), note that it is generally too late
     626   * to export the objects in @name_acquired_handler. Instead, you can do this
     627   * in @bus_acquired_handler since you are guaranteed that this will run
     628   * before @name is requested from the bus.
     629   *
     630   * This behavior makes it very simple to write applications that wants
     631   * to [own names][gdbus-owning-names] and export objects.
     632   * Simply register objects to be exported in @bus_acquired_handler and
     633   * unregister the objects (if any) in @name_lost_handler.
     634   *
     635   * Returns: an identifier (never 0) that can be used with
     636   *     g_bus_unown_name() to stop owning the name.
     637   *
     638   * Since: 2.26
     639   */
     640  guint
     641  g_bus_own_name (GBusType                  bus_type,
     642                  const gchar              *name,
     643                  GBusNameOwnerFlags        flags,
     644                  GBusAcquiredCallback      bus_acquired_handler,
     645                  GBusNameAcquiredCallback  name_acquired_handler,
     646                  GBusNameLostCallback      name_lost_handler,
     647                  gpointer                  user_data,
     648                  GDestroyNotify            user_data_free_func)
     649  {
     650    Client *client;
     651  
     652    g_return_val_if_fail (g_dbus_is_name (name) && !g_dbus_is_unique_name (name), 0);
     653  
     654    G_LOCK (lock);
     655  
     656    client = g_new0 (Client, 1);
     657    client->ref_count = 1;
     658    client->id = next_global_id++; /* TODO: uh oh, handle overflow */
     659    client->name = g_strdup (name);
     660    client->flags = flags;
     661    client->bus_acquired_handler = bus_acquired_handler;
     662    client->name_acquired_handler = name_acquired_handler;
     663    client->name_lost_handler = name_lost_handler;
     664    client->user_data = user_data;
     665    client->user_data_free_func = user_data_free_func;
     666    client->main_context = g_main_context_ref_thread_default ();
     667  
     668    if (map_id_to_client == NULL)
     669      {
     670        map_id_to_client = g_hash_table_new (g_direct_hash, g_direct_equal);
     671      }
     672    g_hash_table_insert (map_id_to_client,
     673                         GUINT_TO_POINTER (client->id),
     674                         client);
     675  
     676    g_bus_get (bus_type,
     677               NULL,
     678               connection_get_cb,
     679               client_ref (client));
     680  
     681    G_UNLOCK (lock);
     682  
     683    return client->id;
     684  }
     685  
     686  typedef struct {
     687    GClosure *bus_acquired_closure;
     688    GClosure *name_acquired_closure;
     689    GClosure *name_lost_closure;
     690  } OwnNameData;
     691  
     692  static OwnNameData *
     693  own_name_data_new (GClosure *bus_acquired_closure,
     694                     GClosure *name_acquired_closure,
     695                     GClosure *name_lost_closure)
     696  {
     697    OwnNameData *data;
     698  
     699    data = g_new0 (OwnNameData, 1);
     700  
     701    if (bus_acquired_closure != NULL)
     702      {
     703        data->bus_acquired_closure = g_closure_ref (bus_acquired_closure);
     704        g_closure_sink (bus_acquired_closure);
     705        if (G_CLOSURE_NEEDS_MARSHAL (bus_acquired_closure))
     706          g_closure_set_marshal (bus_acquired_closure, g_cclosure_marshal_generic);
     707      }
     708  
     709    if (name_acquired_closure != NULL)
     710      {
     711        data->name_acquired_closure = g_closure_ref (name_acquired_closure);
     712        g_closure_sink (name_acquired_closure);
     713        if (G_CLOSURE_NEEDS_MARSHAL (name_acquired_closure))
     714          g_closure_set_marshal (name_acquired_closure, g_cclosure_marshal_generic);
     715      }
     716  
     717    if (name_lost_closure != NULL)
     718      {
     719        data->name_lost_closure = g_closure_ref (name_lost_closure);
     720        g_closure_sink (name_lost_closure);
     721        if (G_CLOSURE_NEEDS_MARSHAL (name_lost_closure))
     722          g_closure_set_marshal (name_lost_closure, g_cclosure_marshal_generic);
     723      }
     724  
     725    return data;
     726  }
     727  
     728  static void
     729  own_with_closures_on_bus_acquired (GDBusConnection *connection,
     730                                     const gchar     *name,
     731                                     gpointer         user_data)
     732  {
     733    OwnNameData *data = user_data;
     734    GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT };
     735  
     736    g_value_init (&params[0], G_TYPE_DBUS_CONNECTION);
     737    g_value_set_object (&params[0], connection);
     738  
     739    g_value_init (&params[1], G_TYPE_STRING);
     740    g_value_set_string (&params[1], name);
     741  
     742    g_closure_invoke (data->bus_acquired_closure, NULL, 2, params, NULL);
     743  
     744    g_value_unset (params + 0);
     745    g_value_unset (params + 1);
     746  }
     747  
     748  static void
     749  own_with_closures_on_name_acquired (GDBusConnection *connection,
     750                                      const gchar     *name,
     751                                      gpointer         user_data)
     752  {
     753    OwnNameData *data = user_data;
     754    GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT };
     755  
     756    g_value_init (&params[0], G_TYPE_DBUS_CONNECTION);
     757    g_value_set_object (&params[0], connection);
     758  
     759    g_value_init (&params[1], G_TYPE_STRING);
     760    g_value_set_string (&params[1], name);
     761  
     762    g_closure_invoke (data->name_acquired_closure, NULL, 2, params, NULL);
     763  
     764    g_value_unset (params + 0);
     765    g_value_unset (params + 1);
     766  }
     767  
     768  static void
     769  own_with_closures_on_name_lost (GDBusConnection *connection,
     770                                  const gchar     *name,
     771                                  gpointer         user_data)
     772  {
     773    OwnNameData *data = user_data;
     774    GValue params[2] = { G_VALUE_INIT, G_VALUE_INIT };
     775  
     776    g_value_init (&params[0], G_TYPE_DBUS_CONNECTION);
     777    g_value_set_object (&params[0], connection);
     778  
     779    g_value_init (&params[1], G_TYPE_STRING);
     780    g_value_set_string (&params[1], name);
     781  
     782    g_closure_invoke (data->name_lost_closure, NULL, 2, params, NULL);
     783  
     784    g_value_unset (params + 0);
     785    g_value_unset (params + 1);
     786  }
     787  
     788  static void
     789  bus_own_name_free_func (gpointer user_data)
     790  {
     791    OwnNameData *data = user_data;
     792  
     793    if (data->bus_acquired_closure != NULL)
     794      g_closure_unref (data->bus_acquired_closure);
     795  
     796    if (data->name_acquired_closure != NULL)
     797      g_closure_unref (data->name_acquired_closure);
     798  
     799    if (data->name_lost_closure != NULL)
     800      g_closure_unref (data->name_lost_closure);
     801  
     802    g_free (data);
     803  }
     804  
     805  /**
     806   * g_bus_own_name_with_closures: (rename-to g_bus_own_name)
     807   * @bus_type: the type of bus to own a name on
     808   * @name: the well-known name to own
     809   * @flags: a set of flags from the #GBusNameOwnerFlags enumeration
     810   * @bus_acquired_closure: (nullable): #GClosure to invoke when connected to
     811   *     the bus of type @bus_type or %NULL
     812   * @name_acquired_closure: (nullable): #GClosure to invoke when @name is
     813   *     acquired or %NULL
     814   * @name_lost_closure: (nullable): #GClosure to invoke when @name is lost or
     815   *     %NULL
     816   *
     817   * Version of g_bus_own_name() using closures instead of callbacks for
     818   * easier binding in other languages.
     819   *
     820   * Returns: an identifier (never 0) that can be used with
     821   *     g_bus_unown_name() to stop owning the name.
     822   *
     823   * Since: 2.26
     824   */
     825  guint
     826  g_bus_own_name_with_closures (GBusType            bus_type,
     827                                const gchar        *name,
     828                                GBusNameOwnerFlags  flags,
     829                                GClosure           *bus_acquired_closure,
     830                                GClosure           *name_acquired_closure,
     831                                GClosure           *name_lost_closure)
     832  {
     833    return g_bus_own_name (bus_type,
     834            name,
     835            flags,
     836            bus_acquired_closure != NULL ? own_with_closures_on_bus_acquired : NULL,
     837            name_acquired_closure != NULL ? own_with_closures_on_name_acquired : NULL,
     838            name_lost_closure != NULL ? own_with_closures_on_name_lost : NULL,
     839            own_name_data_new (bus_acquired_closure,
     840                               name_acquired_closure,
     841                               name_lost_closure),
     842            bus_own_name_free_func);
     843  }
     844  
     845  /**
     846   * g_bus_own_name_on_connection_with_closures: (rename-to g_bus_own_name_on_connection)
     847   * @connection: a #GDBusConnection
     848   * @name: the well-known name to own
     849   * @flags: a set of flags from the #GBusNameOwnerFlags enumeration
     850   * @name_acquired_closure: (nullable): #GClosure to invoke when @name is
     851   *     acquired or %NULL
     852   * @name_lost_closure: (nullable): #GClosure to invoke when @name is lost
     853   *     or %NULL
     854   *
     855   * Version of g_bus_own_name_on_connection() using closures instead of
     856   * callbacks for easier binding in other languages.
     857   *
     858   * Returns: an identifier (never 0) that can be used with
     859   *     g_bus_unown_name() to stop owning the name.
     860   *
     861   * Since: 2.26
     862   */
     863  guint
     864  g_bus_own_name_on_connection_with_closures (GDBusConnection    *connection,
     865                                              const gchar        *name,
     866                                              GBusNameOwnerFlags  flags,
     867                                              GClosure           *name_acquired_closure,
     868                                              GClosure           *name_lost_closure)
     869  {
     870    return g_bus_own_name_on_connection (connection,
     871            name,
     872            flags,
     873            name_acquired_closure != NULL ? own_with_closures_on_name_acquired : NULL,
     874            name_lost_closure != NULL ? own_with_closures_on_name_lost : NULL,
     875            own_name_data_new (NULL,
     876                               name_acquired_closure,
     877                               name_lost_closure),
     878            bus_own_name_free_func);
     879  }
     880  
     881  /**
     882   * g_bus_unown_name:
     883   * @owner_id: an identifier obtained from g_bus_own_name()
     884   *
     885   * Stops owning a name.
     886   *
     887   * Note that there may still be D-Bus traffic to process (relating to owning
     888   * and unowning the name) in the current thread-default #GMainContext after
     889   * this function has returned. You should continue to iterate the #GMainContext
     890   * until the #GDestroyNotify function passed to g_bus_own_name() is called, in
     891   * order to avoid memory leaks through callbacks queued on the #GMainContext
     892   * after it’s stopped being iterated.
     893   *
     894   * Since: 2.26
     895   */
     896  void
     897  g_bus_unown_name (guint owner_id)
     898  {
     899    Client *client;
     900  
     901    g_return_if_fail (owner_id > 0);
     902  
     903    client = NULL;
     904  
     905    G_LOCK (lock);
     906    if (owner_id == 0 || map_id_to_client == NULL ||
     907        (client = g_hash_table_lookup (map_id_to_client, GUINT_TO_POINTER (owner_id))) == NULL)
     908      {
     909        g_warning ("Invalid id %d passed to g_bus_unown_name()", owner_id);
     910        goto out;
     911      }
     912  
     913    client->cancelled = TRUE;
     914    g_warn_if_fail (g_hash_table_remove (map_id_to_client, GUINT_TO_POINTER (owner_id)));
     915  
     916   out:
     917    G_UNLOCK (lock);
     918  
     919    /* do callback without holding lock */
     920    if (client != NULL)
     921      {
     922        /* Release the name if needed */
     923        if (client->needs_release &&
     924            client->connection != NULL &&
     925            !g_dbus_connection_is_closed (client->connection))
     926          {
     927            GVariant *result;
     928            GError *error;
     929            guint32 release_name_reply;
     930  
     931            /* TODO: it kinda sucks having to do a sync call to release the name - but if
     932             * we don't, then a subsequent grab of the name will make the bus daemon return
     933             * IN_QUEUE which will trigger name_lost().
     934             *
     935             * I believe this is a bug in the bus daemon.
     936             */
     937            error = NULL;
     938            result = g_dbus_connection_call_sync (client->connection,
     939                                                  "org.freedesktop.DBus",  /* bus name */
     940                                                  "/org/freedesktop/DBus", /* object path */
     941                                                  "org.freedesktop.DBus",  /* interface name */
     942                                                  "ReleaseName",           /* method name */
     943                                                  g_variant_new ("(s)", client->name),
     944                                                  G_VARIANT_TYPE ("(u)"),
     945                                                  G_DBUS_CALL_FLAGS_NONE,
     946                                                  -1,
     947                                                  NULL,
     948                                                  &error);
     949            if (result == NULL)
     950              {
     951                g_warning ("Error releasing name %s: %s", client->name, error->message);
     952                g_error_free (error);
     953              }
     954            else
     955              {
     956                g_variant_get (result, "(u)", &release_name_reply);
     957                if (release_name_reply != 1 /* DBUS_RELEASE_NAME_REPLY_RELEASED */)
     958                  {
     959                    g_warning ("Unexpected reply %d when releasing name %s", release_name_reply, client->name);
     960                  }
     961                else
     962                  {
     963                    client->needs_release = FALSE;
     964                  }
     965                g_variant_unref (result);
     966              }
     967          }
     968  
     969        if (client->disconnected_signal_handler_id > 0)
     970          g_signal_handler_disconnect (client->connection, client->disconnected_signal_handler_id);
     971        if (client->name_acquired_subscription_id > 0)
     972          g_dbus_connection_signal_unsubscribe (client->connection, client->name_acquired_subscription_id);
     973        if (client->name_lost_subscription_id > 0)
     974          g_dbus_connection_signal_unsubscribe (client->connection, client->name_lost_subscription_id);
     975        client->disconnected_signal_handler_id = 0;
     976        client->name_acquired_subscription_id = 0;
     977        client->name_lost_subscription_id = 0;
     978        if (client->connection != NULL)
     979          {
     980            g_object_unref (client->connection);
     981            client->connection = NULL;
     982          }
     983  
     984        client_unref (client);
     985      }
     986  }