gdbus: integrate kdbus into GDBus core 75/46575/1 tizen_3.0.m1_mobile tizen_3.0.m1_tv accepted/tizen/mobile/20150903.233546 accepted/tizen/tv/20150903.233557 accepted/tizen/wearable/20150903.233610 submit/tizen/20150903.132411 submit/tizen_common/20151015.190624 submit/tizen_common/20151019.135620 tizen_3.0.m1_mobile_release tizen_3.0.m1_tv_release tizen_3.0.m2.a1_mobile_release tizen_3.0.m2.a1_tv_release
authorLukasz Skalski <l.skalski@samsung.com>
Fri, 21 Aug 2015 15:42:53 +0000 (17:42 +0200)
committerKarol Lewandowski <k.lewandowsk@samsung.com>
Fri, 21 Aug 2015 16:37:06 +0000 (18:37 +0200)
Patch includes also changes made by Ryan Lortie <desrt@desrt.ca>

https://bugzilla.gnome.org/show_bug.cgi?id=721861

Change-Id: I6bab6fee34787816efeb42d8e3e60c4c551a8a2b

16 files changed:
gio/Makefile.am
gio/gapplicationimpl-dbus.c
gio/gdbusaddress.c
gio/gdbusconnection.c
gio/gdbusconnection.h
gio/gdbusmessage.c
gio/gdbusmethodinvocation.c
gio/gdbusmethodinvocation.h
gio/gdbusnameowning.c
gio/gdbusnamewatching.c
gio/gdbusobjectmanagerclient.c
gio/gdbusprivate.c
gio/gdbusprivate.h
gio/gdbusutils.c
gio/gioenums.h
gio/gunixfdlist.h

index 28aea41..3be62b1 100644 (file)
@@ -254,6 +254,10 @@ platform_libadd += xdgmime/libxdgmime.la
 platform_deps += xdgmime/libxdgmime.la
 unix_sources = \
        gfiledescriptorbased.c  \
+       gkdbus.c                \
+       gkdbus.h                \
+       gkdbusfakedaemon.c      \
+       gkdbusfakedaemon.h      \
        gunixconnection.c       \
        gunixcredentialsmessage.c       \
        gunixfdlist.c           \
index 94cf6ea..bbe6a51 100644 (file)
@@ -346,8 +346,7 @@ g_application_impl_attempt_primary (GApplicationImpl  *impl,
     NULL /* set_property */
   };
   GApplicationClass *app_class = G_APPLICATION_GET_CLASS (impl->app);
-  GVariant *reply;
-  guint32 rval;
+  GBusRequestNameReplyFlags rval;
 
   if (org_gtk_Application == NULL)
     {
@@ -425,19 +424,13 @@ g_application_impl_attempt_primary (GApplicationImpl  *impl,
    * in the case that we can't do that.
    */
   /* DBUS_NAME_FLAG_DO_NOT_QUEUE: 0x4 */
-  reply = g_dbus_connection_call_sync (impl->session_bus, "org.freedesktop.DBus", "/org/freedesktop/DBus",
-                                       "org.freedesktop.DBus", "RequestName",
-                                       g_variant_new ("(su)", impl->bus_name, 0x4), G_VARIANT_TYPE ("(u)"),
-                                       0, -1, cancellable, error);
+  rval = g_dbus_request_name (impl->session_bus, impl->bus_name, G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE, error);
 
-  if (reply == NULL)
+  if (rval == G_BUS_REQUEST_NAME_FLAGS_ERROR)
     return FALSE;
 
-  g_variant_get (reply, "(u)", &rval);
-  g_variant_unref (reply);
-
   /* DBUS_REQUEST_NAME_REPLY_EXISTS: 3 */
-  impl->primary = (rval != 3);
+  impl->primary = (rval != G_BUS_REQUEST_NAME_FLAGS_EXISTS);
 
   return TRUE;
 }
@@ -479,10 +472,7 @@ g_application_impl_stop_primary (GApplicationImpl *impl)
 
   if (impl->primary && impl->bus_name)
     {
-      g_dbus_connection_call (impl->session_bus, "org.freedesktop.DBus",
-                              "/org/freedesktop/DBus", "org.freedesktop.DBus",
-                              "ReleaseName", g_variant_new ("(s)", impl->bus_name),
-                              NULL, G_DBUS_CALL_FLAGS_NONE, -1, NULL, NULL, NULL);
+      g_dbus_release_name (impl->session_bus, impl->bus_name, NULL);
       impl->primary = FALSE;
     }
 }
@@ -852,13 +842,13 @@ g_dbus_command_line_get_stdin (GApplicationCommandLine *cmdline)
 
   if (fd_list && g_unix_fd_list_get_length (fd_list))
     {
-      gint *fds, n_fds, i;
+      const gint *fds;
 
-      fds = g_unix_fd_list_steal_fds (fd_list, &n_fds);
-      result = g_unix_input_stream_new (fds[0], TRUE);
-      for (i = 1; i < n_fds; i++)
-        (void) g_close (fds[i], NULL);
-      g_free (fds);
+      fds = g_unix_fd_list_peek_fds (fd_list, NULL);
+      result = g_unix_input_stream_new (fds[0], FALSE);
+      g_object_weak_ref (G_OBJECT (result),
+                         (GWeakNotify) g_object_unref,
+                         g_object_ref (fd_list));
     }
 
   return result;
index 6d17b7c..40c314f 100644 (file)
@@ -41,6 +41,7 @@
 #include "gdbusdaemon.h"
 
 #ifdef G_OS_UNIX
+#include "gkdbus.h"
 #include <gio/gunixsocketaddress.h>
 #endif
 
@@ -521,8 +522,9 @@ out:
 
 /* ---------------------------------------------------------------------------------------------------- */
 
-static GIOStream *
+static GObject *
 g_dbus_address_try_connect_one (const gchar   *address_entry,
+                                gboolean       kdbus_okay,
                                 gchar        **out_guid,
                                 GCancellable  *cancellable,
                                 GError       **error);
@@ -532,14 +534,15 @@ g_dbus_address_try_connect_one (const gchar   *address_entry,
  * point. That way we can implement a D-Bus transport over X11 without
  * making libgio link to libX11...
  */
-static GIOStream *
+static GObject *
 g_dbus_address_connect (const gchar   *address_entry,
                         const gchar   *transport_name,
+                        gboolean       kdbus_okay,
                         GHashTable    *key_value_pairs,
                         GCancellable  *cancellable,
                         GError       **error)
 {
-  GIOStream *ret;
+  GObject *ret;
   GSocketConnectable *connectable;
   const gchar *nonce_file;
 
@@ -551,6 +554,29 @@ g_dbus_address_connect (const gchar   *address_entry,
     {
     }
 #ifdef G_OS_UNIX
+  else if (kdbus_okay && g_str_equal (transport_name, "kernel"))
+    {
+      GKDBusWorker *worker;
+      const gchar *path;
+
+      path = g_hash_table_lookup (key_value_pairs, "path");
+
+      if (path == NULL)
+        {
+          g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT,
+                       _("Error in address '%s' - the kernel transport requires a path"),
+                       address_entry);
+        }
+      else
+        {
+          worker = _g_kdbus_worker_new (path, error);
+
+          if (worker == NULL)
+            return NULL;
+
+          return G_OBJECT (worker);
+        }
+    }
   else if (g_strcmp0 (transport_name, "unix") == 0)
     {
       const gchar *path;
@@ -641,7 +667,7 @@ g_dbus_address_connect (const gchar   *address_entry,
       autolaunch_address = get_session_address_platform_specific (error);
       if (autolaunch_address != NULL)
         {
-          ret = g_dbus_address_try_connect_one (autolaunch_address, NULL, cancellable, error);
+          ret = g_dbus_address_try_connect_one (autolaunch_address, kdbus_okay, NULL, cancellable, error);
           g_free (autolaunch_address);
           goto out;
         }
@@ -676,7 +702,7 @@ g_dbus_address_connect (const gchar   *address_entry,
       if (connection == NULL)
         goto out;
 
-      ret = G_IO_STREAM (connection);
+      ret = G_OBJECT (connection);
 
       if (nonce_file != NULL)
         {
@@ -729,7 +755,7 @@ g_dbus_address_connect (const gchar   *address_entry,
             }
           fclose (f);
 
-          if (!g_output_stream_write_all (g_io_stream_get_output_stream (ret),
+          if (!g_output_stream_write_all (g_io_stream_get_output_stream (G_IO_STREAM (connection)),
                                           nonce_contents,
                                           16,
                                           NULL,
@@ -749,13 +775,14 @@ g_dbus_address_connect (const gchar   *address_entry,
   return ret;
 }
 
-static GIOStream *
+static GObject *
 g_dbus_address_try_connect_one (const gchar   *address_entry,
+                                gboolean       kdbus_okay,
                                 gchar        **out_guid,
                                 GCancellable  *cancellable,
                                 GError       **error)
 {
-  GIOStream *ret;
+  GObject *ret;
   GHashTable *key_value_pairs;
   gchar *transport_name;
   const gchar *guid;
@@ -772,6 +799,7 @@ g_dbus_address_try_connect_one (const gchar   *address_entry,
 
   ret = g_dbus_address_connect (address_entry,
                                 transport_name,
+                                kdbus_okay,
                                 key_value_pairs,
                                 cancellable,
                                 error);
@@ -939,7 +967,25 @@ g_dbus_address_get_stream_sync (const gchar   *address,
                                 GCancellable  *cancellable,
                                 GError       **error)
 {
-  GIOStream *ret;
+  GObject *result;
+
+  result = g_dbus_address_get_stream_internal (address, FALSE, out_guid, cancellable, error);
+  g_assert (result == NULL || G_IS_IO_STREAM (result));
+
+  if (result)
+    return G_IO_STREAM (result);
+
+  return NULL;
+}
+
+GObject *
+g_dbus_address_get_stream_internal (const gchar   *address,
+                                    gboolean       kdbus_okay,
+                                    gchar        **out_guid,
+                                    GCancellable  *cancellable,
+                                    GError       **error)
+{
+  GObject *ret;
   gchar **addr_array;
   guint n;
   GError *last_error;
@@ -966,6 +1012,7 @@ g_dbus_address_get_stream_sync (const gchar   *address,
 
       this_error = NULL;
       ret = g_dbus_address_try_connect_one (addr,
+                                            kdbus_okay,
                                             out_guid,
                                             cancellable,
                                             &this_error);
@@ -1512,7 +1559,7 @@ g_dbus_address_get_for_bus_sync (GBusType       bus_type,
       ret = g_strdup (g_getenv ("DBUS_SYSTEM_BUS_ADDRESS"));
       if (ret == NULL)
         {
-          ret = g_strdup ("unix:path=/var/run/dbus/system_bus_socket");
+          ret = g_strdup ("kernel:path=/sys/fs/kdbus/0-system/bus;unix:path=/var/run/dbus/system_bus_socket");
         }
       break;
 
@@ -1520,7 +1567,8 @@ g_dbus_address_get_for_bus_sync (GBusType       bus_type,
       ret = g_strdup (g_getenv ("DBUS_SESSION_BUS_ADDRESS"));
       if (ret == NULL)
         {
-          ret = get_session_address_platform_specific (&local_error);
+          ret = g_strdup_printf ("kernel:path=%s/kdbus;%s", g_get_user_runtime_dir (),
+                                  get_session_address_platform_specific (&local_error));
         }
       break;
 
index cd53c96..a409590 100644 (file)
 #include "gsimpleasyncresult.h"
 
 #ifdef G_OS_UNIX
+#include "gkdbus.h"
 #include "gunixconnection.h"
 #include "gunixfdmessage.h"
 #endif
@@ -388,6 +389,10 @@ struct _GDBusConnection
    */
   GDBusWorker *worker;
 
+#ifdef G_OS_UNIX
+  GKDBusWorker *kdbus_worker;
+#endif
+
   /* If connected to a message bus, this contains the unique name assigned to
    * us by the bus (e.g. ":1.42").
    * Read-only after initable_init(), so it may be read if you either
@@ -625,6 +630,7 @@ g_dbus_connection_dispose (GObject *object)
 
   G_LOCK (message_bus_lock);
   CONNECTION_LOCK (connection);
+
   if (connection->worker != NULL)
     {
       _g_dbus_worker_stop (connection->worker);
@@ -632,6 +638,15 @@ g_dbus_connection_dispose (GObject *object)
       if (alive_connections != NULL)
         g_warn_if_fail (g_hash_table_remove (alive_connections, connection));
     }
+#ifdef G_OS_UNIX
+  else if (connection->kdbus_worker != NULL)
+    {
+      _g_kdbus_worker_stop (connection->kdbus_worker);
+      connection->kdbus_worker = NULL;
+      if (alive_connections != NULL)
+        g_warn_if_fail (g_hash_table_remove (alive_connections, connection));
+    }
+#endif
   else
     {
       if (alive_connections != NULL)
@@ -1112,6 +1127,17 @@ g_dbus_connection_init (GDBusConnection *connection)
   connection->filters = g_ptr_array_new ();
 }
 
+#ifdef G_OS_UNIX
+gboolean
+_g_dbus_connection_is_kdbus (GDBusConnection *connection)
+{
+  if (connection->kdbus_worker)
+    return TRUE;
+  else
+    return FALSE;
+}
+#endif
+
 /**
  * g_dbus_connection_get_stream:
  * @connection: a #GDBusConnection
@@ -1158,8 +1184,14 @@ g_dbus_connection_start_message_processing (GDBusConnection *connection)
   if (!check_initialized (connection))
     return;
 
-  g_assert (connection->worker != NULL);
-  _g_dbus_worker_unfreeze (connection->worker);
+  if (connection->worker)
+    _g_dbus_worker_unfreeze (connection->worker);
+#ifdef G_OS_UNIX
+  else if (connection->kdbus_worker)
+    _g_kdbus_worker_unfreeze (connection->kdbus_worker);
+#endif
+  else
+    g_assert_not_reached ();
 }
 
 /**
@@ -1345,11 +1377,20 @@ g_dbus_connection_flush_sync (GDBusConnection  *connection,
   if (!check_unclosed (connection, 0, error))
     goto out;
 
-  g_assert (connection->worker != NULL);
-
-  ret = _g_dbus_worker_flush_sync (connection->worker,
-                                   cancellable,
-                                   error);
+  if (connection->worker != NULL)
+    {
+      ret = _g_dbus_worker_flush_sync (connection->worker,
+                                       cancellable,
+                                       error);
+    }
+#ifdef G_OS_UNIX
+  else if (connection->kdbus_worker != NULL)
+    {
+      ret = _g_kdbus_worker_flush_sync (connection->kdbus_worker);
+    }
+#endif
+  else
+    g_assert_not_reached();
 
  out:
   return ret;
@@ -1472,14 +1513,25 @@ g_dbus_connection_close (GDBusConnection     *connection,
   if (!check_initialized (connection))
     return;
 
-  g_assert (connection->worker != NULL);
-
   simple = g_simple_async_result_new (G_OBJECT (connection),
                                       callback,
                                       user_data,
                                       g_dbus_connection_close);
   g_simple_async_result_set_check_cancellable (simple, cancellable);
-  _g_dbus_worker_close (connection->worker, cancellable, simple);
+
+  if (connection->worker)
+    {
+      _g_dbus_worker_close (connection->worker, cancellable, simple);
+    }
+#ifdef G_OS_UNIX
+  else if (connection->kdbus_worker)
+    {
+      _g_kdbus_worker_close (connection->kdbus_worker, cancellable, simple);
+    }
+#endif
+  else
+    g_assert_not_reached();
+
   g_object_unref (simple);
 }
 
@@ -1591,6 +1643,628 @@ g_dbus_connection_close_sync (GDBusConnection  *connection,
 /* ---------------------------------------------------------------------------------------------------- */
 
 /**
+ * g_dbus_request_name:
+ * @connection: a #GDBusConnection
+ * @name: well-known bus name (name to request)
+ * @flags: a set of flags from the GBusNameOwnerFlags enumeration
+ * @error: return location for error or %NULL
+ *
+ * Synchronously acquires name on the bus and returns status code
+ * from the #GBusRequestNameReplyFlags enumeration.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: status code or %G_BUS_REQUEST_NAME_FLAGS_ERROR
+ *     if @error is set.
+ *
+ * Since: 2.44
+ */
+GBusRequestNameReplyFlags
+g_dbus_request_name (GDBusConnection     *connection,
+                     const gchar         *name,
+                     GBusNameOwnerFlags   flags,
+                     GError             **error)
+{
+  GVariant *result;
+  guint32 request_name_reply;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), G_BUS_RELEASE_NAME_FLAGS_ERROR);
+  g_return_val_if_fail (g_dbus_is_name (name) && !g_dbus_is_unique_name (name), G_BUS_RELEASE_NAME_FLAGS_ERROR);
+  g_return_val_if_fail (error == NULL || *error == NULL, G_BUS_RELEASE_NAME_FLAGS_ERROR);
+
+#ifdef G_OS_UNIX
+  if (connection->kdbus_worker)
+    return _g_kdbus_RequestName (connection->kdbus_worker, name, flags, error);
+#endif
+
+  result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/org/freedesktop/DBus",
+                                        "org.freedesktop.DBus", "RequestName",
+                                        g_variant_new ("(su)", name, flags), G_VARIANT_TYPE ("(u)"),
+                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+  if (result != NULL)
+    {
+      g_variant_get (result, "(u)", &request_name_reply);
+      g_variant_unref (result);
+    }
+  else
+    request_name_reply = G_BUS_REQUEST_NAME_FLAGS_ERROR;
+
+  return (GBusRequestNameReplyFlags) request_name_reply;
+}
+
+/**
+ * g_dbus_release_name:
+ * @connection: a #GDBusConnection
+ * @name: well-known bus name (name to release)
+ * @error: return location for error or %NULL
+ *
+ * Synchronously releases name on the bus and returns status code
+ * from the #GBusReleaseNameReplyFlags enumeration.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: status code or %G_BUS_RELEASE_NAME_FLAGS_ERROR
+ *     if @error is set.
+ *
+ * Since: 2.44
+ */
+GBusReleaseNameReplyFlags
+g_dbus_release_name (GDBusConnection  *connection,
+                     const gchar      *name,
+                     GError          **error)
+{
+  GVariant *result;
+  guint32 release_name_reply;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), G_BUS_RELEASE_NAME_FLAGS_ERROR);
+  g_return_val_if_fail (g_dbus_is_name (name) && !g_dbus_is_unique_name (name), G_BUS_RELEASE_NAME_FLAGS_ERROR);
+  g_return_val_if_fail (error == NULL || *error == NULL, G_BUS_RELEASE_NAME_FLAGS_ERROR);
+
+#ifdef G_OS_UNIX
+  if (connection->kdbus_worker)
+    return _g_kdbus_ReleaseName (connection->kdbus_worker, name, error);
+#endif
+
+  result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/org/freedesktop/DBus",
+                                        "org.freedesktop.DBus", "ReleaseName",
+                                        g_variant_new ("(s)", name), G_VARIANT_TYPE ("(u)"),
+                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+  if (result != NULL)
+    {
+      g_variant_get (result, "(u)", &release_name_reply);
+      g_variant_unref (result);
+    }
+  else
+    release_name_reply = G_BUS_RELEASE_NAME_FLAGS_ERROR;
+
+  return (GBusReleaseNameReplyFlags) release_name_reply;
+}
+
+/**
+ * g_dbus_add_match:
+ * @connection: a #GDBusConnection
+ * @match_rule: match rule to add to the @connection
+ * @error: return location for error or %NULL
+ *
+ * Synchronously adds a match rule to match messages.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE
+ *     if @error is set.
+ *
+ * Since: 2.44
+ */
+gboolean
+g_dbus_add_match (GDBusConnection  *connection,
+                  const gchar      *match_rule,
+                  GError          **error)
+{
+  GVariant *result;
+  gboolean ret;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  result = NULL;
+  ret = FALSE;
+
+  if (match_rule[0] == '-')
+    return ret;
+
+#ifdef G_OS_UNIX
+  if (connection->kdbus_worker)
+    return _g_kdbus_AddMatch (connection->kdbus_worker, match_rule, error);
+#endif
+
+  result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/org/freedesktop/DBus",
+                                        "org.freedesktop.DBus", "AddMatch",
+                                        g_variant_new ("(s)", match_rule), NULL,
+                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+  if (result != NULL)
+    {
+      ret = TRUE;
+      g_variant_unref (result);
+    }
+
+  return ret;
+}
+
+/**
+ * g_dbus_remove_match:
+ * @connection: a #GDBusConnection
+ * @match_rule: match rule to remove from the @connection
+ * @error: return location for error or %NULL
+ *
+ * Synchronously removes the first rule that matches.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE
+ *     if @error is set.
+ *
+ * Since: 2.44
+ */
+gboolean
+g_dbus_remove_match (GDBusConnection  *connection,
+                     const gchar      *match_rule,
+                     GError          **error)
+{
+  GVariant *result;
+  gboolean ret;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  result = NULL;
+  ret = FALSE;
+
+  if (match_rule[0] == '-')
+    return ret;
+
+#ifdef G_OS_UNIX
+  if (connection->kdbus_worker)
+    return _g_kdbus_RemoveMatch (connection->kdbus_worker, match_rule, error);
+#endif
+
+  result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/org/freedesktop/DBus",
+                                        "org.freedesktop.DBus", "RemoveMatch",
+                                        g_variant_new ("(s)", match_rule), NULL,
+                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+  if (result != NULL)
+    {
+      ret = TRUE;
+      g_variant_unref (result);
+    }
+
+  return ret;
+}
+
+/**
+ * g_dbus_get_bus_id:
+ * @connection: a #GDBusConnection
+ * @error: return location for error or %NULL
+ *
+ * Synchronously returns the unique ID of the bus.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: the unique ID of the bus or %NULL if @error is set.
+ *     Free with g_free().
+ *
+ * Since: 2.44
+ */
+gchar *
+g_dbus_get_bus_id (GDBusConnection  *connection,
+                   GError          **error)
+{
+  GVariant *result;
+  gchar *bus_id;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+  result = NULL;
+  bus_id = NULL;
+
+#ifdef G_OS_UNIX
+  if (connection->kdbus_worker)
+    return _g_kdbus_GetBusId (connection->kdbus_worker, error);
+#endif
+
+  result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/",
+                                        "org.freedesktop.DBus", "GetId",
+                                        NULL, G_VARIANT_TYPE ("(s)"),
+                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+  if (result != NULL)
+    {
+      g_variant_get (result, "(s)", &bus_id);
+      g_variant_unref (result);
+    }
+
+  return bus_id;
+}
+
+typedef enum
+{
+  LIST_NAMES,
+  LIST_ACTIVATABLE_NAMES,
+  LIST_QUEUED_OWNERS
+} GDBusListNameType;
+
+static gchar **
+_g_dbus_get_list_internal (GDBusConnection    *connection,
+                           const gchar        *name,
+                           GDBusListNameType   list_name_type,
+                           GError            **error)
+{
+  gchar **strv;
+  GVariant *result;
+  GVariantIter *iter;
+  gchar *str;
+  gsize n, i;
+
+  result = NULL;
+  strv = NULL;
+
+  if (list_name_type == LIST_QUEUED_OWNERS)
+    {
+#ifdef G_OS_UNIX
+      if (connection->kdbus_worker)
+        return _g_kdbus_GetListQueuedOwners (connection->kdbus_worker, name, error);
+#endif
+
+      result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/",
+                                            "org.freedesktop.DBus", "ListQueuedOwners",
+                                            g_variant_new ("(s)", name), G_VARIANT_TYPE ("(as)"),
+                                            G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+    }
+  else
+    {
+      gchar *method_name;
+
+      if (list_name_type == LIST_NAMES)
+        method_name = "ListNames";
+      else
+        method_name = "ListActivatableNames";
+
+#ifdef G_OS_UNIX
+      if (connection->kdbus_worker)
+        return _g_kdbus_GetListNames (connection->kdbus_worker, list_name_type, error);
+#endif
+
+      result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/",
+                                            "org.freedesktop.DBus", method_name,
+                                            NULL, G_VARIANT_TYPE ("(as)"),
+                                            G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+    }
+
+  if (result != NULL)
+    {
+      g_variant_get (result, "(as)", &iter);
+      n = g_variant_iter_n_children (iter);
+      strv = g_new (gchar *, n + 1);
+
+      i = 0;
+      while (g_variant_iter_loop (iter, "s", &str))
+        {
+          strv[i] = g_strdup (str);
+          i++;
+        }
+      strv[i] = NULL;
+
+      g_variant_iter_free (iter);
+      g_variant_unref (result);
+    }
+
+  return strv;
+}
+
+/**
+ * g_dbus_get_list_names:
+ * @connection: a #GDBusConnection
+ * @error: return location for error or %NULL
+ *
+ * Synchronously returns a list of all currently-owned names on the bus.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: a list of all currently-owned names on the bus or %NULL if
+ *     @error is set. Free with g_strfreev().
+ *
+ * Since: 2.44
+ */
+gchar **
+g_dbus_get_list_names (GDBusConnection  *connection,
+                       GError          **error)
+{
+  gchar **strv;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+  strv = _g_dbus_get_list_internal (connection, NULL, LIST_NAMES, error);
+
+  return strv;
+}
+
+/**
+ * g_dbus_get_list_activatable_names:
+ * @connection: a #GDBusConnection
+ * @error: return location for error or %NULL
+ *
+ * Synchronously returns a list of all names that can be activated on the bus.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: a list of all names that can be activated on the bus or %NULL if
+ *     @error is set. Free with g_strfreev().
+ *
+ * Since: 2.44
+ */
+gchar **
+g_dbus_get_list_activatable_names (GDBusConnection  *connection,
+                                   GError          **error)
+{
+  gchar **strv;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+  strv = _g_dbus_get_list_internal (connection, NULL, LIST_ACTIVATABLE_NAMES, error);
+
+  return strv;
+}
+
+/**
+ * g_dbus_get_list_queued_names:
+ * @connection: a #GDBusConnection
+ * @name: a unique or well-known bus name
+ * @error: return location for error or %NULL
+ *
+ * Synchronously returns the unique bus names of connections currently queued
+ * for the @name.
+ *
+ * If @name contains a value not compatible with the D-Bus syntax and naming
+ * conventions for bus names, the operation returns %NULL and @error is set.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: the unique bus names of connections currently queued for the @name
+ *     or %NULL if @error is set. Free with g_strfreev().
+ *
+ * Since: 2.44
+ */
+gchar **
+g_dbus_get_list_queued_owners (GDBusConnection  *connection,
+                               const gchar      *name,
+                               GError          **error)
+{
+  gchar **strv;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
+  g_return_val_if_fail (name == NULL || g_dbus_is_name (name), NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+  strv = _g_dbus_get_list_internal (connection, name, LIST_QUEUED_OWNERS, error);
+
+  return strv;
+}
+
+/**
+ * g_dbus_get_name_owner:
+ * @connection: a #GDBusConnection
+ * @name: well-known bus name to get the owner of
+ * @error: return location for error or %NULL
+ *
+ * Synchronously returns the unique connection name of the primary owner of
+ * the name given. If the requested name doesn't have an owner, an @error is
+ * returned.
+ *
+ * If @name contains a value not compatible with the D-Bus syntax and naming
+ * conventions for bus names, the operation returns %NULL and @error is set.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: the unique connection name of the primary owner of the
+ *     name given. If the requested name doesn't have an owner, function
+ *     returns %NULL and @error is set. Free with g_free().
+ *
+ * Since: 2.44
+ */
+gchar *
+g_dbus_get_name_owner (GDBusConnection  *connection,
+                       const gchar      *name,
+                       GError          **error)
+{
+  GVariant *result;
+  gchar *name_owner;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
+  g_return_val_if_fail (name == NULL || g_dbus_is_name (name), NULL);
+  g_return_val_if_fail (error == NULL || *error == NULL, NULL);
+
+  name_owner = NULL;
+  result = NULL;
+
+#ifdef G_OS_UNIX
+  if (connection->kdbus_worker)
+    return _g_kdbus_GetNameOwner (connection->kdbus_worker, name, error);
+#endif
+
+  result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/",
+                                        "org.freedesktop.DBus", "GetNameOwner",
+                                        g_variant_new ("(s)", name), G_VARIANT_TYPE ("(s)"),
+                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+  if (result != NULL)
+    {
+      g_variant_get (result, "(s)", &name_owner);
+      g_variant_unref (result);
+    }
+  else
+    name_owner = NULL;
+
+  return name_owner;
+}
+
+/**
+ * g_dbus_get_connection_pid:
+ * @connection: a #GDBusConnection
+ * @name: a unique or well-known bus name of the connection to query
+ * @error: return location for error or %NULL
+ *
+ * Synchronously returns the Unix process ID of the process connected to the
+ * bus. If unable to determine it, an @error is returned.
+ *
+ * If @name contains a value not compatible with the D-Bus syntax and naming
+ * conventions for bus names, the operation returns -1 and @error is set.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: the Unix process ID of the process connected to the bus or -1
+ *     if @error is set.
+ *
+ * Since: 2.44
+ */
+pid_t
+g_dbus_get_connection_pid (GDBusConnection  *connection,
+                           const gchar      *name,
+                           GError          **error)
+{
+  GVariant *result;
+  pid_t pid;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), -1);
+  g_return_val_if_fail (name == NULL || g_dbus_is_name (name), -1);
+  g_return_val_if_fail (error == NULL || *error == NULL, -1);
+
+  result = NULL;
+  pid = -1;
+
+#ifdef G_OS_UNIX
+  if (connection->kdbus_worker)
+    return _g_kdbus_GetConnectionUnixProcessID (connection->kdbus_worker, name, error);
+#endif
+
+  result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/",
+                                        "org.freedesktop.DBus", "GetConnectionUnixProcessID",
+                                        g_variant_new ("(s)", name), G_VARIANT_TYPE ("(u)"),
+                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+  if (result != NULL)
+    {
+      g_variant_get (result, "(u)", &pid);
+      g_variant_unref (result);
+    }
+
+  return pid;
+}
+
+/**
+ * g_dbus_get_connection_uid:
+ * @connection: a #GDBusConnection
+ * @name: a unique or well-known bus name of the connection to query
+ * @error: return location for error or %NULL
+ *
+ * Synchronously returns the Unix user ID of the process connected to the
+ * bus. If unable to determine it, an @error is returned.
+ *
+ * If @name contains a value not compatible with the D-Bus syntax and naming
+ * conventions for bus names, the operation returns -1 and @error is set.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: the Unix user ID of the process connected to the bus or -1
+ *     if @error is set.
+ *
+ * Since: 2.44
+ */
+uid_t
+g_dbus_get_connection_uid (GDBusConnection  *connection,
+                           const gchar      *name,
+                           GError          **error)
+{
+  GVariant *result;
+  uid_t uid;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), -1);
+  g_return_val_if_fail (name == NULL || g_dbus_is_name (name), -1);
+  g_return_val_if_fail (error == NULL || *error == NULL, -1);
+
+  result = NULL;
+  uid = -1;
+
+#ifdef G_OS_UNIX
+  if (connection->kdbus_worker)
+    return _g_kdbus_GetConnectionUnixUser (connection->kdbus_worker, name, error);
+#endif
+
+  result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/",
+                                        "org.freedesktop.DBus", "GetConnectionUnixUser",
+                                        g_variant_new ("(s)", name), G_VARIANT_TYPE ("(u)"),
+                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+  if (result != NULL)
+    {
+      g_variant_get (result, "(u)", &uid);
+      g_variant_unref (result);
+    }
+
+  return uid;
+}
+
+/**
+ * g_dbus_start_service_by_name:
+ * @connection: a #GDBusConnection
+ * @name: name of the service to start
+ * @flags: (currently not used)
+ * @error: return location for error or %NULL
+ *
+ * Synchronously tries to launch the executable associated
+ * with a @name.
+ *
+ * The calling thread is blocked until a reply is received.
+ *
+ * Returns: status code or %G_BUS_START_SERVICE_REPLY_ERROR
+ *     if @error is set.
+ *
+ * Since: 2.44
+ */
+GBusStartServiceReplyFlags
+g_dbus_start_service_by_name (GDBusConnection  *connection,
+                              const gchar      *name,
+                              guint32           flags,
+                              GError          **error)
+{
+  GVariant *result;
+  guint32 ret;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), -1);
+  g_return_val_if_fail (name == NULL || g_dbus_is_name (name), -1);
+  g_return_val_if_fail (error == NULL || *error == NULL, -1);
+
+  result = NULL;
+  ret = G_BUS_START_SERVICE_REPLY_ERROR;
+
+#ifdef G_OS_UNIX
+  if (connection->kdbus_worker)
+    return _g_kdbus_StartServiceByName (connection->kdbus_worker, name, flags, error);
+#endif
+
+  result = g_dbus_connection_call_sync (connection, "org.freedesktop.DBus", "/",
+                                        "org.freedesktop.DBus", "StartServiceByName",
+                                        g_variant_new ("(su)", name, flags), G_VARIANT_TYPE ("(u)"),
+                                        G_DBUS_CALL_FLAGS_NONE, -1, NULL, error);
+  if (result != NULL)
+    {
+      g_variant_get (result, "(u)", &ret);
+      g_variant_unref (result);
+    }
+
+  return (GBusStartServiceReplyFlags) ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
  * g_dbus_connection_get_last_serial:
  * @connection: a #GDBusConnection
  *
@@ -1658,31 +2332,39 @@ g_dbus_connection_send_message_unlocked (GDBusConnection   *connection,
                        error))
     goto out;
 
-  blob = g_dbus_message_to_blob (message,
-                                 &blob_size,
-                                 connection->capabilities,
-                                 error);
-  if (blob == NULL)
-    goto out;
+  if (!(flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL))
+    g_dbus_message_set_serial (message, ++connection->last_serial);
 
-  if (flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL)
-    serial_to_use = g_dbus_message_get_serial (message);
-  else
-    serial_to_use = ++connection->last_serial; /* TODO: handle overflow */
+  serial_to_use = g_dbus_message_get_serial (message);
 
-  switch (blob[0])
+  /*
+   * serializes message to a blob
+   */
+  if (connection->worker)
     {
-    case 'l':
-      ((guint32 *) blob)[2] = GUINT32_TO_LE (serial_to_use);
-      break;
-    case 'B':
-      ((guint32 *) blob)[2] = GUINT32_TO_BE (serial_to_use);
-      break;
-    default:
-      g_assert_not_reached ();
-      break;
+      blob = g_dbus_message_to_blob (message,
+                                     &blob_size,
+                                     connection->capabilities,
+                                     error);
+      if (blob == NULL)
+        goto out;
+
+      switch (blob[0])
+        {
+        case 'l':
+          ((guint32 *) blob)[2] = GUINT32_TO_LE (serial_to_use);
+          break;
+        case 'B':
+          ((guint32 *) blob)[2] = GUINT32_TO_BE (serial_to_use);
+          break;
+        default:
+          g_assert_not_reached ();
+          break;
+        }
     }
 
+  g_dbus_message_lock (message);
+
 #if 0
   g_printerr ("Writing message of %" G_GSIZE_FORMAT " bytes (serial %d) on %p:\n",
               blob_size, serial_to_use, connection);
@@ -1705,17 +2387,25 @@ g_dbus_connection_send_message_unlocked (GDBusConnection   *connection,
                         g_thread_self (),
                         GUINT_TO_POINTER (serial_to_use));
 
-  if (!(flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL))
-    g_dbus_message_set_serial (message, serial_to_use);
+  ret = TRUE;
 
-  g_dbus_message_lock (message);
-  _g_dbus_worker_send_message (connection->worker,
-                               message,
-                               (gchar*) blob,
-                               blob_size);
-  blob = NULL; /* since _g_dbus_worker_send_message() steals the blob */
+  if (connection->worker)
+    {
+      _g_dbus_worker_send_message (connection->worker,
+                                   message,
+                                   (gchar*) blob,
+                                   blob_size);
+    }
+#ifdef G_OS_UNIX
+  else if (connection->kdbus_worker)
+    {
+      ret = _g_kdbus_worker_send_message (connection->kdbus_worker, message, -1, error);
+    }
+#endif
+  else
+    g_assert_not_reached ();
 
-  ret = TRUE;
+  blob = NULL; /* since _g_dbus_worker_send_message() steals the blob */
 
  out:
   g_free (blob);
@@ -2238,32 +2928,79 @@ g_dbus_connection_send_message_with_reply_sync (GDBusConnection        *connecti
   g_return_val_if_fail (timeout_msec >= 0 || timeout_msec == -1, NULL);
   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
 
-  data = g_new0 (SendMessageSyncData, 1);
-  data->context = g_main_context_new ();
-  data->loop = g_main_loop_new (data->context, FALSE);
-
-  g_main_context_push_thread_default (data->context);
-
-  g_dbus_connection_send_message_with_reply (connection,
-                                             message,
-                                             flags,
-                                             timeout_msec,
-                                             out_serial,
-                                             cancellable,
-                                             (GAsyncReadyCallback) send_message_with_reply_sync_cb,
-                                             data);
-  g_main_loop_run (data->loop);
-  reply = g_dbus_connection_send_message_with_reply_finish (connection,
-                                                            data->res,
-                                                            error);
+  reply = NULL;
 
-  g_main_context_pop_thread_default (data->context);
+  if (connection->worker)
+    {
+      data = g_new0 (SendMessageSyncData, 1);
+      data->context = g_main_context_new ();
+      data->loop = g_main_loop_new (data->context, FALSE);
 
-  g_main_context_unref (data->context);
-  g_main_loop_unref (data->loop);
-  g_object_unref (data->res);
-  g_free (data);
+      g_main_context_push_thread_default (data->context);
 
+      g_dbus_connection_send_message_with_reply (connection,
+                                                 message,
+                                                 flags,
+                                                 timeout_msec,
+                                                 out_serial,
+                                                 cancellable,
+                                                 (GAsyncReadyCallback) send_message_with_reply_sync_cb,
+                                                 data);
+      g_main_loop_run (data->loop);
+      reply = g_dbus_connection_send_message_with_reply_finish (connection,
+                                                                data->res,
+                                                                error);
+
+      g_main_context_pop_thread_default (data->context);
+
+      g_main_context_unref (data->context);
+      g_main_loop_unref (data->loop);
+      g_object_unref (data->res);
+      g_free (data);
+    }
+#ifdef G_OS_UNIX
+  else if (connection->kdbus_worker)
+    {
+      /* kdbus supports blocking synchronous calls, so let's use them instead of mainloops */
+      /* TODO: Add support for GCancellable - https://developer.gnome.org/gio/stable/GTask.html */
+
+      volatile guint32 serial;
+      guint32 serial_to_use;
+
+      CONNECTION_LOCK (connection);
+
+      if (timeout_msec == -1)
+        timeout_msec = 25 * 1000;
+
+      if (out_serial == NULL)
+        out_serial = &serial;
+      else
+        *out_serial = 0;
+
+      if (!check_unclosed (connection,
+                           (flags & SEND_MESSAGE_FLAGS_INITIALIZING) ? MAY_BE_UNINITIALIZED : 0,
+                           error))
+        goto out;
+
+      if (!(flags & G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL))
+        g_dbus_message_set_serial (message, ++connection->last_serial);
+
+      serial_to_use = g_dbus_message_get_serial (message);
+
+      g_dbus_message_lock (message);
+
+      if (out_serial != NULL)
+        *out_serial = serial_to_use;
+
+      _g_kdbus_worker_send_message_sync (connection->kdbus_worker, message, &reply, timeout_msec, error);
+
+      CONNECTION_UNLOCK (connection);
+    }
+#endif /* G_OS_UNIX */
+  else
+    g_assert_not_reached ();
+
+out:
   return reply;
 }
 
@@ -2285,8 +3022,7 @@ typedef struct
 
 /* Called in GDBusWorker's thread - we must not block - with no lock held */
 static void
-on_worker_message_received (GDBusWorker  *worker,
-                            GDBusMessage *message,
+on_worker_message_received (GDBusMessage *message,
                             gpointer      user_data)
 {
   GDBusConnection *connection;
@@ -2306,7 +3042,23 @@ on_worker_message_received (GDBusWorker  *worker,
   g_object_ref (connection);
   G_UNLOCK (message_bus_lock);
 
-  //g_debug ("in on_worker_message_received");
+#ifdef G_OS_UNIX
+  if (_g_dbus_connection_is_kdbus (connection))
+    {
+      if (G_UNLIKELY (_g_dbus_debug_message ()))
+        {
+          gchar *s;
+          _g_dbus_debug_print_lock ();
+          g_print ("========================================================================\n"
+                   "GDBus-debug:Message:\n"
+                   "  <<<< RECEIVED D-Bus message\n");
+          s = g_dbus_message_print (message, 2);
+          g_print ("%s", s);
+          g_free (s);
+          _g_dbus_debug_print_unlock ();
+        }
+    }
+#endif
 
   g_object_ref (message);
   g_dbus_message_lock (message);
@@ -2387,8 +3139,7 @@ on_worker_message_received (GDBusWorker  *worker,
 
 /* Called in GDBusWorker's thread, lock is not held */
 static GDBusMessage *
-on_worker_message_about_to_be_sent (GDBusWorker  *worker,
-                                    GDBusMessage *message,
+on_worker_message_about_to_be_sent (GDBusMessage *message,
                                     gpointer      user_data)
 {
   GDBusConnection *connection;
@@ -2464,10 +3215,9 @@ cancel_method_on_close (gpointer key, gpointer value, gpointer user_data)
 
 /* Called in GDBusWorker's thread - we must not block - without lock held */
 static void
-on_worker_closed (GDBusWorker *worker,
-                  gboolean     remote_peer_vanished,
-                  GError      *error,
-                  gpointer     user_data)
+on_worker_closed (gboolean  remote_peer_vanished,
+                  GError   *error,
+                  gpointer  user_data)
 {
   GDBusConnection *connection;
   gboolean alive;
@@ -2529,6 +3279,7 @@ initable_init (GInitable     *initable,
                GError       **error)
 {
   GDBusConnection *connection = G_DBUS_CONNECTION (initable);
+  gboolean initially_frozen;
   gboolean ret;
 
   /* This method needs to be idempotent to work with the singleton
@@ -2566,6 +3317,8 @@ initable_init (GInitable     *initable,
    */
   if (connection->address != NULL)
     {
+      GObject *ret;
+
       g_assert (connection->stream == NULL);
 
       if ((connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER) ||
@@ -2578,12 +3331,20 @@ initable_init (GInitable     *initable,
           goto out;
         }
 
-      connection->stream = g_dbus_address_get_stream_sync (connection->address,
-                                                           NULL, /* TODO: out_guid */
-                                                           cancellable,
-                                                           &connection->initialization_error);
-      if (connection->stream == NULL)
+      ret = g_dbus_address_get_stream_internal (connection->address, TRUE,
+                                                NULL, /* TODO: out_guid */
+                                                cancellable, &connection->initialization_error);
+      if (ret == NULL)
         goto out;
+
+      if (G_IS_IO_STREAM (ret))
+        connection->stream = G_IO_STREAM (ret);
+#ifdef G_OS_UNIX
+      else if (G_IS_KDBUS_WORKER (ret))
+        connection->kdbus_worker = G_KDBUS_WORKER (ret);
+#endif
+      else
+        g_assert_not_reached ();
     }
   else if (connection->stream != NULL)
     {
@@ -2594,6 +3355,16 @@ initable_init (GInitable     *initable,
       g_assert_not_reached ();
     }
 
+#ifdef G_OS_UNIX
+  /* Skip authentication process for kdbus transport */
+  if (connection->kdbus_worker)
+    {
+      /* kdbus connection always supports exchanging UNIX file descriptors with the remote peer */
+      connection->capabilities |= G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING;
+      goto authenticated;
+    }
+#endif
+
   /* Authenticate the connection */
   if (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER)
     {
@@ -2632,6 +3403,8 @@ initable_init (GInitable     *initable,
       connection->authentication_observer = NULL;
     }
 
+authenticated:
+
   //g_output_stream_flush (G_SOCKET_CONNECTION (connection->stream)
 
   //g_debug ("haz unix fd passing powers: %d", connection->capabilities & G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING);
@@ -2652,13 +3425,32 @@ initable_init (GInitable     *initable,
   g_hash_table_insert (alive_connections, connection, connection);
   G_UNLOCK (message_bus_lock);
 
-  connection->worker = _g_dbus_worker_new (connection->stream,
-                                           connection->capabilities,
-                                           ((connection->flags & G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING) != 0),
-                                           on_worker_message_received,
-                                           on_worker_message_about_to_be_sent,
-                                           on_worker_closed,
-                                           connection);
+  initially_frozen = (connection->flags & G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING) != 0;
+
+  if (0)
+    {
+    }
+#ifdef G_OS_UNIX
+  else if (connection->kdbus_worker)
+    {
+      _g_kdbus_worker_associate (connection->kdbus_worker,
+                                 connection->capabilities,
+                                 on_worker_message_received,
+                                 on_worker_message_about_to_be_sent,
+                                 on_worker_closed,
+                                 connection);
+    }
+#endif
+  else
+    {
+      connection->worker = _g_dbus_worker_new (connection->stream,
+                                               connection->capabilities,
+                                               initially_frozen,
+                                               on_worker_message_received,
+                                               on_worker_message_about_to_be_sent,
+                                               on_worker_closed,
+                                               connection);
+    }
 
   /* if a bus connection, call org.freedesktop.DBus.Hello - this is how we're getting a name */
   if (connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)
@@ -2675,25 +3467,46 @@ initable_init (GInitable     *initable,
           goto out;
         }
 
-      hello_result = g_dbus_connection_call_sync (connection,
-                                                  "org.freedesktop.DBus", /* name */
-                                                  "/org/freedesktop/DBus", /* path */
-                                                  "org.freedesktop.DBus", /* interface */
-                                                  "Hello",
-                                                  NULL, /* parameters */
-                                                  G_VARIANT_TYPE ("(s)"),
-                                                  CALL_FLAGS_INITIALIZING,
-                                                  -1,
-                                                  NULL, /* TODO: cancellable */
-                                                  &connection->initialization_error);
-      if (hello_result == NULL)
-        goto out;
+      if (connection->worker)
+        {
+          hello_result = g_dbus_connection_call_sync (connection,
+                                                      "org.freedesktop.DBus", /* name */
+                                                      "/org/freedesktop/DBus", /* path */
+                                                      "org.freedesktop.DBus", /* interface */
+                                                      "Hello",
+                                                      NULL, /* parameters */
+                                                      G_VARIANT_TYPE ("(s)"),
+                                                      CALL_FLAGS_INITIALIZING,
+                                                      -1,
+                                                      NULL, /* TODO: cancellable */
+                                                      &connection->initialization_error);
+          if (hello_result == NULL)
+            goto out;
+
+          g_variant_get (hello_result, "(s)", &connection->bus_unique_name);
+          g_variant_unref (hello_result);
+        }
+#ifdef G_OS_UNIX
+      else if (connection->kdbus_worker)
+        {
+          const gchar *unique_name;
+
+          unique_name = _g_kdbus_Hello (connection->kdbus_worker, &connection->initialization_error);
+          if (unique_name == NULL)
+            goto out;
 
-      g_variant_get (hello_result, "(s)", &connection->bus_unique_name);
-      g_variant_unref (hello_result);
-      //g_debug ("unique name is '%s'", connection->bus_unique_name);
+          connection->bus_unique_name = g_strdup (unique_name);
+        }
+#endif
+      else
+        g_assert_not_reached ();
     }
 
+#ifdef G_OS_UNIX
+  if (connection->kdbus_worker && !initially_frozen)
+    _g_kdbus_worker_unfreeze (connection->kdbus_worker);
+#endif
+
   ret = TRUE;
  out:
   if (!ret)
@@ -3549,8 +4362,34 @@ g_dbus_connection_signal_subscribe (GDBusConnection     *connection,
    */
   if (connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION)
     {
-      if (!is_signal_data_for_name_lost_or_acquired (signal_data))
-        add_match_rule (connection, signal_data->rule);
+      if (connection->worker)
+        {
+          if (!is_signal_data_for_name_lost_or_acquired (signal_data))
+            add_match_rule (connection, signal_data->rule);
+        }
+#ifdef G_OS_UNIX
+      else if (connection->kdbus_worker)
+        {
+          if (g_strcmp0 (signal_data->sender_unique_name, "org.freedesktop.DBus") == 0 &&
+              g_strcmp0 (signal_data->interface_name, "org.freedesktop.DBus") == 0 &&
+              g_strcmp0 (signal_data->object_path, "/org/freedesktop/DBus") == 0 &&
+              (g_strcmp0 (signal_data->member, "NameLost") == 0 ||
+               g_strcmp0 (signal_data->member, "NameAcquired") == 0 ||
+               g_strcmp0 (signal_data->member, "NameOwnerChanged") == 0))
+            {
+              if (g_strcmp0 (signal_data->member, "NameAcquired") == 0)
+                _g_kdbus_subscribe_name_acquired (connection->kdbus_worker, signal_data->rule, arg0, NULL);
+              else if (g_strcmp0 (signal_data->member, "NameLost") == 0)
+                _g_kdbus_subscribe_name_lost (connection->kdbus_worker, signal_data->rule, arg0, NULL);
+              else if (g_strcmp0 (signal_data->member, "NameOwnerChanged") == 0)
+                _g_kdbus_subscribe_name_owner_changed (connection->kdbus_worker, signal_data->rule, arg0, NULL);
+            }
+          else
+            _g_kdbus_AddMatch (connection->kdbus_worker, signal_data->rule, NULL);
+        }
+#endif
+      else
+        g_assert_not_reached ();
     }
 
   signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array,
@@ -3625,7 +4464,6 @@ unsubscribe_id_internal (GDBusConnection *connection,
 
           /* remove the match rule from the bus unless NameLost or NameAcquired (see subscribe()) */
           if ((connection->flags & G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION) &&
-              !is_signal_data_for_name_lost_or_acquired (signal_data) &&
               !g_dbus_connection_is_closed (connection) &&
               !connection->finalizing)
             {
@@ -3635,7 +4473,19 @@ unsubscribe_id_internal (GDBusConnection *connection,
                * so on_worker_closed() can't happen between the check we just
                * did, and releasing the lock later.
                */
-              remove_match_rule (connection, signal_data->rule);
+              if (connection->worker)
+                {
+                  if (!is_signal_data_for_name_lost_or_acquired (signal_data))
+                    remove_match_rule (connection, signal_data->rule);
+                }
+#ifdef G_OS_UNIX
+              else if (connection->kdbus_worker)
+                {
+                  _g_kdbus_RemoveMatch (connection->kdbus_worker, signal_data->rule, NULL);
+                }
+#endif
+              else
+                g_assert_not_reached ();
             }
 
           signal_data_free (signal_data);
@@ -3728,7 +4578,7 @@ emit_signal_instance_in_idle_cb (gpointer data)
     }
   else
     {
-      g_variant_ref_sink (parameters);
+      g_variant_ref (parameters);
     }
 
 #if 0
index ba054db..ee51357 100644 (file)
@@ -91,6 +91,58 @@ GDBusConnection *g_dbus_connection_new_for_address_sync       (const gchar
 
 /* ---------------------------------------------------------------------------------------------------- */
 
+gboolean                     _g_dbus_connection_is_kdbus         (GDBusConnection     *connection);
+
+/* GLIB_AVAILABLE_IN_2_44 */
+GBusRequestNameReplyFlags    g_dbus_request_name                 (GDBusConnection     *connection,
+                                                                  const gchar         *name,
+                                                                  GBusNameOwnerFlags   flags,
+                                                                  GError             **error);
+/* GLIB_AVAILABLE_IN_2_44 */
+GBusReleaseNameReplyFlags    g_dbus_release_name                 (GDBusConnection     *connection,
+                                                                  const gchar         *name,
+                                                                  GError             **error);
+/* GLIB_AVAILABLE_IN_2_44 */
+gboolean                     g_dbus_add_match                    (GDBusConnection     *connection,
+                                                                  const gchar         *match_rule,
+                                                                  GError             **error);
+/* GLIB_AVAILABLE_IN_2_44 */
+gboolean                     g_dbus_remove_match                 (GDBusConnection     *connection,
+                                                                  const gchar         *match_rule,
+                                                                  GError             **error);
+/* GLIB_AVAILABLE_IN_2_44 */
+gchar                       *g_dbus_get_bus_id                   (GDBusConnection     *connection,
+                                                                  GError             **error);
+/* GLIB_AVAILABLE_IN_2_44 */
+gchar                      **g_dbus_get_list_names               (GDBusConnection     *connection,
+                                                                  GError             **error);
+/* GLIB_AVAILABLE_IN_2_44 */
+gchar                      **g_dbus_get_list_activatable_names   (GDBusConnection     *connection,
+                                                                  GError             **error);
+/* GLIB_AVAILABLE_IN_2_44 */
+gchar                      **g_dbus_get_list_queued_owners       (GDBusConnection     *connection,
+                                                                  const gchar         *name,
+                                                                  GError             **error);
+/* GLIB_AVAILABLE_IN_2_44 */
+gchar                       *g_dbus_get_name_owner               (GDBusConnection     *connection,
+                                                                  const gchar         *name,
+                                                                  GError             **error);
+/* GLIB_AVAILABLE_IN_2_44 */
+pid_t                        g_dbus_get_connection_pid           (GDBusConnection     *connection,
+                                                                  const gchar         *name,
+                                                                  GError             **error);
+/* GLIB_AVAILABLE_IN_2_44 */
+uid_t                        g_dbus_get_connection_uid           (GDBusConnection     *connection,
+                                                                  const gchar         *name,
+                                                                  GError             **error);
+/* GLIB_AVAILABLE_IN_2_44 */
+GBusStartServiceReplyFlags   g_dbus_start_service_by_name        (GDBusConnection     *connection,
+                                                                  const gchar         *name,
+                                                                  guint32              flags,
+                                                                  GError             **error);
+
+/* ---------------------------------------------------------------------------------------------------- */
+
 GLIB_AVAILABLE_IN_ALL
 void             g_dbus_connection_start_message_processing   (GDBusConnection    *connection);
 GLIB_AVAILABLE_IN_ALL
index 766609e..a0e1f7b 100644 (file)
@@ -3628,3 +3628,10 @@ g_dbus_message_copy (GDBusMessage  *message,
 #endif
   return ret;
 }
+
+void
+g_dbus_message_init_header_iter (GDBusMessage   *message,
+                                 GHashTableIter *iter)
+{
+  g_hash_table_iter_init (iter, message->headers);
+}
index 5bd850b..412ed36 100644 (file)
@@ -306,6 +306,44 @@ g_dbus_method_invocation_get_parameters (GDBusMethodInvocation *invocation)
 }
 
 /**
+ * g_dbus_method_invocation_peek_unix_fd:
+ * @invocation: A #GDBusMethodInvocation.
+ * @index_: the index
+ *
+ * Gets the fd associated with @index in the method invocation.
+ *
+ * If there is no file descriptor at the given index, -1 is returned.
+ *
+ * The returned file descriptor is owned by the message and must not be
+ * closed by the caller.  Use dup() if you want your own copy.
+ *
+ * Returns: the file descriptor, or -1
+ */
+#ifdef G_OS_UNIX
+gint
+g_dbus_method_invocation_peek_unix_fd (GDBusMethodInvocation *invocation,
+                                       guint                  index_)
+{
+  GUnixFDList *fd_list;
+
+  fd_list = g_dbus_message_get_unix_fd_list (invocation->message);
+
+  if (fd_list)
+    {
+      const gint *fds;
+      gint n_fds;
+
+      fds = g_unix_fd_list_peek_fds (fd_list, &n_fds);
+
+      if (index_ < (guint) n_fds)
+        return fds[index_];
+    }
+
+  return -1;
+}
+#endif
+
+/**
  * g_dbus_method_invocation_get_user_data: (skip)
  * @invocation: A #GDBusMethodInvocation.
  *
index 6354e41..1d24283 100644 (file)
@@ -53,6 +53,11 @@ GLIB_AVAILABLE_IN_ALL
 GDBusMessage          *g_dbus_method_invocation_get_message          (GDBusMethodInvocation *invocation);
 GLIB_AVAILABLE_IN_ALL
 GVariant              *g_dbus_method_invocation_get_parameters       (GDBusMethodInvocation *invocation);
+#ifdef G_OS_UNIX
+GLIB_AVAILABLE_IN_2_44
+gint                   g_dbus_method_invocation_peek_unix_fd         (GDBusMethodInvocation *invocation,
+                                                                      guint                  index_);
+#endif
 GLIB_AVAILABLE_IN_ALL
 gpointer               g_dbus_method_invocation_get_user_data        (GDBusMethodInvocation *invocation);
 
index 00b2dfd..245d476 100644 (file)
@@ -296,40 +296,23 @@ on_name_lost_or_acquired (GDBusConnection  *connection,
 /* ---------------------------------------------------------------------------------------------------- */
 
 static void
-request_name_cb (GObject      *source_object,
-                 GAsyncResult *res,
-                 gpointer      user_data)
+process_request_name_reply (Client                    *client,
+                            GBusRequestNameReplyFlags  request_name_reply)
 {
-  Client *client = user_data;
-  GVariant *result;
-  guint32 request_name_reply;
   gboolean subscribe;
 
-  request_name_reply = 0;
-  result = NULL;
-
-  /* don't use client->connection - it may be NULL already */
-  result = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source_object),
-                                          res,
-                                          NULL);
-  if (result != NULL)
-    {
-      g_variant_get (result, "(u)", &request_name_reply);
-      g_variant_unref (result);
-    }
-
   subscribe = FALSE;
 
   switch (request_name_reply)
     {
-    case 1: /* DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER */
+    case G_BUS_REQUEST_NAME_FLAGS_PRIMARY_OWNER:
       /* We got the name - now listen for NameLost and NameAcquired */
       call_acquired_handler (client);
       subscribe = TRUE;
       client->needs_release = TRUE;
       break;
 
-    case 2: /* DBUS_REQUEST_NAME_REPLY_IN_QUEUE */
+    case G_BUS_REQUEST_NAME_FLAGS_IN_QUEUE:
       /* Waiting in line - listen for NameLost and NameAcquired */
       call_lost_handler (client);
       subscribe = TRUE;
@@ -338,8 +321,8 @@ request_name_cb (GObject      *source_object,
 
     default:
       /* assume we couldn't get the name - explicit fallthrough */
-    case 3: /* DBUS_REQUEST_NAME_REPLY_EXISTS */
-    case 4: /* DBUS_REQUEST_NAME_REPLY_ALREADY_OWNER */
+    case G_BUS_REQUEST_NAME_FLAGS_EXISTS:
+    case G_BUS_REQUEST_NAME_FLAGS_ALREADY_OWNER:
       /* Some other part of the process is already owning the name */
       call_lost_handler (client);
       break;
@@ -387,8 +370,6 @@ request_name_cb (GObject      *source_object,
           g_object_unref (connection);
         }
     }
-
-  client_unref (client);
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
@@ -421,27 +402,25 @@ on_connection_disconnected (GDBusConnection *connection,
 static void
 has_connection (Client *client)
 {
+  GError *error = NULL;
+  GBusRequestNameReplyFlags request_name_reply;
+
+  request_name_reply = G_BUS_REQUEST_NAME_FLAGS_ERROR;
+
   /* listen for disconnection */
   client->disconnected_signal_handler_id = g_signal_connect (client->connection,
                                                              "closed",
                                                              G_CALLBACK (on_connection_disconnected),
                                                              client);
-
   /* attempt to acquire the name */
-  g_dbus_connection_call (client->connection,
-                          "org.freedesktop.DBus",  /* bus name */
-                          "/org/freedesktop/DBus", /* object path */
-                          "org.freedesktop.DBus",  /* interface name */
-                          "RequestName",           /* method name */
-                          g_variant_new ("(su)",
-                                         client->name,
-                                         client->flags),
-                          G_VARIANT_TYPE ("(u)"),
-                          G_DBUS_CALL_FLAGS_NONE,
-                          -1,
-                          NULL,
-                          (GAsyncReadyCallback) request_name_cb,
-                          client_ref (client));
+  request_name_reply = g_dbus_request_name (client->connection, client->name, client->flags, &error);
+  if (request_name_reply == G_BUS_REQUEST_NAME_FLAGS_ERROR)
+    {
+      g_warning ("Error requesting name %s: %s", client->name, error->message);
+      g_error_free (error);
+    }
+
+  process_request_name_reply (client, request_name_reply);
 }
 
 
@@ -898,9 +877,10 @@ g_bus_unown_name (guint owner_id)
           client->connection != NULL &&
           !g_dbus_connection_is_closed (client->connection))
         {
-          GVariant *result;
+          GBusReleaseNameReplyFlags release_name_reply;
           GError *error;
-          guint32 release_name_reply;
+
+          error = NULL;
 
           /* TODO: it kinda sucks having to do a sync call to release the name - but if
            * we don't, then a subsequent grab of the name will make the bus daemon return
@@ -908,32 +888,16 @@ g_bus_unown_name (guint owner_id)
            *
            * I believe this is a bug in the bus daemon.
            */
-          error = NULL;
-          result = g_dbus_connection_call_sync (client->connection,
-                                                "org.freedesktop.DBus",  /* bus name */
-                                                "/org/freedesktop/DBus", /* object path */
-                                                "org.freedesktop.DBus",  /* interface name */
-                                                "ReleaseName",           /* method name */
-                                                g_variant_new ("(s)", client->name),
-                                                G_VARIANT_TYPE ("(u)"),
-                                                G_DBUS_CALL_FLAGS_NONE,
-                                                -1,
-                                                NULL,
-                                                &error);
-          if (result == NULL)
+
+          release_name_reply = g_dbus_release_name (client->connection, client->name, &error);
+          if (release_name_reply == G_BUS_RELEASE_NAME_FLAGS_ERROR)
             {
               g_warning ("Error releasing name %s: %s", client->name, error->message);
               g_error_free (error);
             }
           else
-            {
-              g_variant_get (result, "(u)", &release_name_reply);
-              if (release_name_reply != 1 /* DBUS_RELEASE_NAME_REPLY_RELEASED */)
-                {
-                  g_warning ("Unexpected reply %d when releasing name %s", release_name_reply, client->name);
-                }
-              g_variant_unref (result);
-            }
+            if (release_name_reply != G_BUS_RELEASE_NAME_FLAGS_RELEASED)
+              g_warning ("Unexpected reply %d when releasing name %s", release_name_reply, client->name);
         }
 
       if (client->disconnected_signal_handler_id > 0)
index 07713db..252a510 100644 (file)
@@ -322,6 +322,22 @@ on_name_owner_changed (GDBusConnection *connection,
 /* ---------------------------------------------------------------------------------------------------- */
 
 static void
+process_get_name_owner (Client      *client,
+                        const char  *name_owner)
+{
+  if (name_owner != NULL)
+    {
+      g_warn_if_fail (client->name_owner == NULL);
+      client->name_owner = g_strdup (name_owner);
+      call_appeared_handler (client);
+    }
+  else
+    call_vanished_handler (client, FALSE);
+
+  client->initialized = TRUE;
+}
+
+static void
 get_name_owner_cb (GObject      *source_object,
                    GAsyncResult *res,
                    gpointer      user_data)
@@ -341,18 +357,7 @@ get_name_owner_cb (GObject      *source_object,
       g_variant_get (result, "(&s)", &name_owner);
     }
 
-  if (name_owner != NULL)
-    {
-      g_warn_if_fail (client->name_owner == NULL);
-      client->name_owner = g_strdup (name_owner);
-      call_appeared_handler (client);
-    }
-  else
-    {
-      call_vanished_handler (client, FALSE);
-    }
-
-  client->initialized = TRUE;
+  process_get_name_owner (client, name_owner);
 
   if (result != NULL)
     g_variant_unref (result);
@@ -364,23 +369,53 @@ get_name_owner_cb (GObject      *source_object,
 static void
 invoke_get_name_owner (Client *client)
 {
-  g_dbus_connection_call (client->connection,
-                          "org.freedesktop.DBus",  /* bus name */
-                          "/org/freedesktop/DBus", /* object path */
-                          "org.freedesktop.DBus",  /* interface name */
-                          "GetNameOwner",          /* method name */
-                          g_variant_new ("(s)", client->name),
-                          G_VARIANT_TYPE ("(s)"),
-                          G_DBUS_CALL_FLAGS_NONE,
-                          -1,
-                          NULL,
-                          (GAsyncReadyCallback) get_name_owner_cb,
-                          client_ref (client));
+  if (_g_dbus_connection_is_kdbus (client->connection))
+    {
+      char *name_owner;
+
+      name_owner = g_dbus_get_name_owner (client->connection,
+                                          client->name,
+                                          NULL);
+      process_get_name_owner (client, name_owner);
+      if (name_owner != NULL)
+        g_free (name_owner);
+    }
+  else
+    {
+      g_dbus_connection_call (client->connection,
+                              "org.freedesktop.DBus",  /* bus name */
+                              "/org/freedesktop/DBus", /* object path */
+                              "org.freedesktop.DBus",  /* interface name */
+                              "GetNameOwner",          /* method name */
+                              g_variant_new ("(s)", client->name),
+                              G_VARIANT_TYPE ("(s)"),
+                              G_DBUS_CALL_FLAGS_NONE,
+                              -1,
+                              NULL,
+                              (GAsyncReadyCallback) get_name_owner_cb,
+                              client_ref (client));
+    }
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
 
 static void
+process_start_service_by_name (Client                      *client,
+                               GBusStartServiceReplyFlags   result)
+{
+  if (result == G_BUS_START_SERVICE_REPLY_SUCCESS)
+    invoke_get_name_owner (client);
+  else if (result == G_BUS_START_SERVICE_REPLY_ALREADY_RUNNING)
+    invoke_get_name_owner (client);
+  else
+    {
+      g_warning ("Unexpected reply %d from StartServiceByName() method", result);
+      call_vanished_handler (client, FALSE);
+      client->initialized = TRUE;
+    }
+}
+
+static void
 start_service_by_name_cb (GObject      *source_object,
                           GAsyncResult *res,
                           gpointer      user_data)
@@ -398,20 +433,7 @@ start_service_by_name_cb (GObject      *source_object,
       guint32 start_service_result;
       g_variant_get (result, "(u)", &start_service_result);
 
-      if (start_service_result == 1) /* DBUS_START_REPLY_SUCCESS */
-        {
-          invoke_get_name_owner (client);
-        }
-      else if (start_service_result == 2) /* DBUS_START_REPLY_ALREADY_RUNNING */
-        {
-          invoke_get_name_owner (client);
-        }
-      else
-        {
-          g_warning ("Unexpected reply %d from StartServiceByName() method", start_service_result);
-          call_vanished_handler (client, FALSE);
-          client->initialized = TRUE;
-        }
+      process_start_service_by_name (client, (GBusStartServiceReplyFlags) start_service_result);
     }
   else
     {
@@ -457,18 +479,26 @@ has_connection (Client *client)
 
   if (client->flags & G_BUS_NAME_WATCHER_FLAGS_AUTO_START)
     {
-      g_dbus_connection_call (client->connection,
-                              "org.freedesktop.DBus",  /* bus name */
-                              "/org/freedesktop/DBus", /* object path */
-                              "org.freedesktop.DBus",  /* interface name */
-                              "StartServiceByName",    /* method name */
-                              g_variant_new ("(su)", client->name, 0),
-                              G_VARIANT_TYPE ("(u)"),
-                              G_DBUS_CALL_FLAGS_NONE,
-                              -1,
-                              NULL,
-                              (GAsyncReadyCallback) start_service_by_name_cb,
-                              client_ref (client));
+      if (_g_dbus_connection_is_kdbus (client->connection))
+        {
+          GBusStartServiceReplyFlags result;
+
+          result = g_dbus_start_service_by_name (client->connection, client->name, 0, NULL);
+          process_start_service_by_name (client, result);
+        }
+      else
+        g_dbus_connection_call (client->connection,
+                                "org.freedesktop.DBus",  /* bus name */
+                                "/org/freedesktop/DBus", /* object path */
+                                "org.freedesktop.DBus",  /* interface name */
+                                "StartServiceByName",    /* method name */
+                                g_variant_new ("(su)", client->name, 0),
+                                G_VARIANT_TYPE ("(u)"),
+                                G_DBUS_CALL_FLAGS_NONE,
+                                -1,
+                                NULL,
+                                (GAsyncReadyCallback) start_service_by_name_cb,
+                                client_ref (client));
     }
   else
     {
index 5755e74..d7cbec6 100644 (file)
@@ -1097,7 +1097,6 @@ subscribe_signals (GDBusObjectManagerClient *manager,
                    const gchar *name_owner)
 {
   GError *error = NULL;
-  GVariant *ret;
 
   g_return_if_fail (G_IS_DBUS_OBJECT_MANAGER_CLIENT (manager));
   g_return_if_fail (manager->priv->signal_subscription_id == 0);
@@ -1123,22 +1122,7 @@ subscribe_signals (GDBusObjectManagerClient *manager,
 
       /* The bus daemon may not implement path_namespace so gracefully
        * handle this by using a fallback triggered if @error is set. */
-      ret = g_dbus_connection_call_sync (manager->priv->connection,
-                                         "org.freedesktop.DBus",
-                                         "/org/freedesktop/DBus",
-                                         "org.freedesktop.DBus",
-                                         "AddMatch",
-                                         g_variant_new ("(s)",
-                                                        manager->priv->match_rule),
-                                         NULL, /* reply_type */
-                                         G_DBUS_CALL_FLAGS_NONE,
-                                         -1, /* default timeout */
-                                         NULL, /* TODO: Cancellable */
-                                         &error);
-
-      /* yay, bus daemon supports path_namespace */
-      if (ret != NULL)
-        g_variant_unref (ret);
+      g_dbus_add_match (manager->priv->connection, manager->priv->match_rule, &error);
     }
 
   if (error == NULL)
@@ -1208,19 +1192,9 @@ maybe_unsubscribe_signals (GDBusObjectManagerClient *manager)
       /* Since the AddMatch call succeeded this is guaranteed to not
        * fail - therefore, don't bother checking the return value
        */
-      g_dbus_connection_call (manager->priv->connection,
-                              "org.freedesktop.DBus",
-                              "/org/freedesktop/DBus",
-                              "org.freedesktop.DBus",
-                              "RemoveMatch",
-                              g_variant_new ("(s)",
-                                             manager->priv->match_rule),
-                              NULL, /* reply_type */
-                              G_DBUS_CALL_FLAGS_NONE,
-                              -1, /* default timeout */
-                              NULL, /* GCancellable */
-                              NULL, /* GAsyncReadyCallback */
-                              NULL); /* user data */
+      g_dbus_remove_match (manager->priv->connection,
+                           manager->priv->match_rule,
+                           NULL);
       g_free (manager->priv->match_rule);
       manager->priv->match_rule = NULL;
     }
index 60af6c6..8afa97e 100644 (file)
@@ -478,7 +478,7 @@ _g_dbus_worker_emit_disconnected (GDBusWorker  *worker,
                                   GError       *error)
 {
   if (!g_atomic_int_get (&worker->stopped))
-    worker->disconnected_callback (worker, remote_peer_vanished, error, worker->user_data);
+    worker->disconnected_callback (remote_peer_vanished, error, worker->user_data);
 }
 
 static void
@@ -486,7 +486,7 @@ _g_dbus_worker_emit_message_received (GDBusWorker  *worker,
                                       GDBusMessage *message)
 {
   if (!g_atomic_int_get (&worker->stopped))
-    worker->message_received_callback (worker, message, worker->user_data);
+    worker->message_received_callback (message, worker->user_data);
 }
 
 static GDBusMessage *
@@ -495,7 +495,7 @@ _g_dbus_worker_emit_message_about_to_be_sent (GDBusWorker  *worker,
 {
   GDBusMessage *ret;
   if (!g_atomic_int_get (&worker->stopped))
-    ret = worker->message_about_to_be_sent_callback (worker, message, worker->user_data);
+    ret = worker->message_about_to_be_sent_callback (message, worker->user_data);
   else
     ret = message;
   return ret;
index 0e38121..094891e 100644 (file)
@@ -33,16 +33,13 @@ G_BEGIN_DECLS
 
 typedef struct GDBusWorker GDBusWorker;
 
-typedef void (*GDBusWorkerMessageReceivedCallback) (GDBusWorker   *worker,
-                                                    GDBusMessage  *message,
+typedef void (*GDBusWorkerMessageReceivedCallback) (GDBusMessage  *message,
                                                     gpointer       user_data);
 
-typedef GDBusMessage *(*GDBusWorkerMessageAboutToBeSentCallback) (GDBusWorker   *worker,
-                                                                  GDBusMessage  *message,
+typedef GDBusMessage *(*GDBusWorkerMessageAboutToBeSentCallback) (GDBusMessage  *message,
                                                                   gpointer       user_data);
 
-typedef void (*GDBusWorkerDisconnectedCallback)    (GDBusWorker   *worker,
-                                                    gboolean       remote_peer_vanished,
+typedef void (*GDBusWorkerDisconnectedCallback)    (gboolean       remote_peer_vanished,
                                                     GError        *error,
                                                     gpointer       user_data);
 
@@ -145,6 +142,17 @@ void _g_dbus_object_proxy_remove_interface (GDBusObjectProxy *proxy,
 /* Implemented in gdbusconnection.c */
 GDBusConnection *_g_bus_get_singleton_if_exists (GBusType bus_type);
 
+void g_dbus_message_init_header_iter (GDBusMessage   *message,
+                                      GHashTableIter *iter);
+
+GObject *
+g_dbus_address_get_stream_internal (const gchar   *address,
+                                    gboolean       kdbus_okay,
+                                    gchar        **out_uuid,
+                                    GCancellable  *cancellable,
+                                    GError       **error);
+
+
 G_END_DECLS
 
 #endif /* __G_DBUS_PRIVATE_H__ */
index 4e17749..1ecc57b 100644 (file)
@@ -419,6 +419,11 @@ g_dbus_gvariant_to_gvalue (GVariant  *value,
       g_value_set_uint64 (out_gvalue, g_variant_get_uint64 (value));
       break;
 
+    case G_VARIANT_CLASS_FLOAT:
+      g_value_init (out_gvalue, G_TYPE_FLOAT);
+      g_value_set_float (out_gvalue, g_variant_get_float (value));
+      break;
+
     case G_VARIANT_CLASS_DOUBLE:
       g_value_init (out_gvalue, G_TYPE_DOUBLE);
       g_value_set_double (out_gvalue, g_variant_get_double (value));
@@ -593,6 +598,10 @@ g_dbus_gvalue_to_gvariant (const GValue       *gvalue,
           ret = g_variant_ref_sink (g_variant_new_uint64 (g_value_get_uint64 (gvalue)));
           break;
 
+        case G_VARIANT_CLASS_FLOAT:
+          ret = g_variant_ref_sink (g_variant_new_float (g_value_get_float (gvalue)));
+          break;
+
         case G_VARIANT_CLASS_DOUBLE:
           ret = g_variant_ref_sink (g_variant_new_double (g_value_get_double (gvalue)));
           break;
index 6b8ab72..75fb02a 100644 (file)
@@ -931,6 +931,7 @@ typedef enum
  * @G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT: Allow another message bus connection to claim the name.
  * @G_BUS_NAME_OWNER_FLAGS_REPLACE: If another message bus connection owns the name and have
  * specified #G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT, then take the name from the other connection.
+ * @G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE: Do not place message bus connection in a queue to own the name.
  *
  * Flags used in g_bus_own_name().
  *
@@ -940,10 +941,71 @@ typedef enum
 {
   G_BUS_NAME_OWNER_FLAGS_NONE = 0,                    /*< nick=none >*/
   G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT = (1<<0),  /*< nick=allow-replacement >*/
-  G_BUS_NAME_OWNER_FLAGS_REPLACE = (1<<1)            /*< nick=replace >*/
+  G_BUS_NAME_OWNER_FLAGS_REPLACE = (1<<1),            /*< nick=replace >*/
+  G_BUS_NAME_OWNER_FLAGS_DO_NOT_QUEUE = (1<<2)        /*< nick=do-not-queue >*/
 } GBusNameOwnerFlags;
 
 /**
+ * GBusRequestNameReplyFlags:
+ * @G_BUS_REQUEST_NAME_FLAGS_ERROR: Error flag.
+ * @G_BUS_REQUEST_NAME_FLAGS_PRIMARY_OWNER: Caller is now the primary owner of the name, replacing
+ * any previous owner.
+ * @G_BUS_REQUEST_NAME_FLAGS_IN_QUEUE: The name already had an owner, the application will be
+ * placed in a queue.
+ * @G_BUS_REQUEST_NAME_FLAGS_EXISTS: The name already has an owner.
+ * @G_BUS_REQUEST_NAME_FLAGS_ALREADY_OWNER: The application trying to request ownership of a name
+ * is already the owner of it.
+ *
+ * Flags used in g_dbus_request_name().
+ *
+ * Since: 2.44
+ */
+typedef enum
+{
+  G_BUS_REQUEST_NAME_FLAGS_ERROR = 0,
+  G_BUS_REQUEST_NAME_FLAGS_PRIMARY_OWNER = 1,
+  G_BUS_REQUEST_NAME_FLAGS_IN_QUEUE = 2,
+  G_BUS_REQUEST_NAME_FLAGS_EXISTS = 3,
+  G_BUS_REQUEST_NAME_FLAGS_ALREADY_OWNER = 4
+} GBusRequestNameReplyFlags;
+
+/**
+ * GBusReleaseNameReplyFlags:
+ * @G_BUS_RELEASE_NAME_FLAGS_ERROR: Error flag.
+ * @G_BUS_RELEASE_NAME_FLAGS_RELEASED: The caller has released his claim on the given name.
+ * @G_BUS_RELEASE_NAME_FLAGS_NON_EXISTENT: The given name does not exist on this bus.
+ * @G_BUS_RELEASE_NAME_FLAGS_NOT_OWNER: The caller not waiting in the queue to own this name.
+ *
+ * Flags used in g_dbus_release_name().
+ *
+ * Since: 2.44
+ */
+typedef enum
+{
+  G_BUS_RELEASE_NAME_FLAGS_ERROR = 0,
+  G_BUS_RELEASE_NAME_FLAGS_RELEASED = 1,
+  G_BUS_RELEASE_NAME_FLAGS_NON_EXISTENT = 2,
+  G_BUS_RELEASE_NAME_FLAGS_NOT_OWNER = 3
+} GBusReleaseNameReplyFlags;
+
+/**
+ * GBusStartServiceReplyFlags:
+ * @G_BUS_START_SERVICE_REPLY_ERROR: Error flag.
+ * @G_BUS_START_SERVICE_REPLY_SUCCESS: The service was successfully started.
+ * @G_BUS_START_SERVICE_REPLY_ALREADY_RUNNING: A connection already owns the given name.
+ *
+ * Flags used in g_dbus_start_service_by_name().
+ *
+ * Since: 2.44
+ */
+typedef enum
+{
+  G_BUS_START_SERVICE_REPLY_ERROR = 0,
+  G_BUS_START_SERVICE_REPLY_SUCCESS = 1,
+  G_BUS_START_SERVICE_REPLY_ALREADY_RUNNING = 2
+} GBusStartServiceReplyFlags;
+
+/**
  * GBusNameWatcherFlags:
  * @G_BUS_NAME_WATCHER_FLAGS_NONE: No flags set.
  * @G_BUS_NAME_WATCHER_FLAGS_AUTO_START: If no-one owns the name when
@@ -1230,6 +1292,9 @@ typedef enum {
  * @G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED: A reply is not expected.
  * @G_DBUS_MESSAGE_FLAGS_NO_AUTO_START: The bus must not launch an
  * owner for the destination name in response to this message.
+ * @G_DBUS_MESSAGE_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION: Inform the
+ * receiving side that the caller is prepared to wait for interactive
+ * authorization.
  *
  * Message flags used in #GDBusMessage.
  *
@@ -1238,7 +1303,8 @@ typedef enum {
 typedef enum {
   G_DBUS_MESSAGE_FLAGS_NONE = 0,
   G_DBUS_MESSAGE_FLAGS_NO_REPLY_EXPECTED = (1<<0),
-  G_DBUS_MESSAGE_FLAGS_NO_AUTO_START = (1<<1)
+  G_DBUS_MESSAGE_FLAGS_NO_AUTO_START = (1<<1),
+  G_DBUS_MESSAGE_FLAGS_ALLOW_INTERACTIVE_AUTHORIZATION = (1<<2)
 } GDBusMessageFlags;
 
 /**
index d159dbb..04ab94e 100644 (file)
@@ -69,6 +69,9 @@ GLIB_AVAILABLE_IN_ALL
 GUnixFDList *           g_unix_fd_list_new_from_array                   (const gint   *fds,
                                                                          gint          n_fds);
 
+GLIB_AVAILABLE_IN_2_44
+void                    g_unix_fd_list_lock                             (GUnixFDList  *list);
+
 GLIB_AVAILABLE_IN_ALL
 gint                    g_unix_fd_list_append                           (GUnixFDList  *list,
                                                                          gint          fd,