Merge branch 'upstream' into tizen
[platform/upstream/glib.git] / gio / gdbusconnection.c
old mode 100644 (file)
new mode 100755 (executable)
index d730111..339a198
 #include "gmarshal-internal.h"
 
 #ifdef G_OS_UNIX
+#ifdef KDBUS
+#include "gkdbus.h"
+#endif
 #include "gunixconnection.h"
 #include "gunixfdmessage.h"
 #endif
@@ -379,6 +382,12 @@ struct _GDBusConnection
    */
   GDBusWorker *worker;
 
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  GKDBusWorker *kdbus_worker;
+#endif
+#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
@@ -616,6 +625,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);
@@ -623,6 +633,17 @@ 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
+#ifdef KDBUS
+  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
+#endif
   else
     {
       if (alive_connections != NULL)
@@ -1109,6 +1130,19 @@ g_dbus_connection_init (GDBusConnection *connection)
   connection->filters = g_ptr_array_new ();
 }
 
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+gboolean
+_g_dbus_connection_is_kdbus (GDBusConnection *connection)
+{
+  if (connection->kdbus_worker)
+    return TRUE;
+  else
+    return FALSE;
+}
+#endif
+#endif
+
 /**
  * g_dbus_connection_get_stream:
  * @connection: a #GDBusConnection
@@ -1155,8 +1189,16 @@ 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
+#ifdef KDBUS
+  else if (connection->kdbus_worker)
+    _g_kdbus_worker_unfreeze (connection->kdbus_worker);
+#endif
+#endif
+  else
+    g_assert_not_reached ();
 }
 
 /**
@@ -1347,11 +1389,22 @@ 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
+#ifdef KDBUS
+  else if (connection->kdbus_worker != NULL)
+    {
+      ret = _g_kdbus_worker_flush_sync (connection->kdbus_worker);
+    }
+#endif
+#endif
+  else
+    g_assert_not_reached();
 
  out:
   return ret;
@@ -1451,7 +1504,7 @@ schedule_closed_unlocked (GDBusConnection *connection,
  * of the thread that @connection was constructed in.
  *
  * This is an asynchronous method. When the operation is finished,
- * @callback will be invoked in the 
+ * @callback will be invoked in the
  * [thread-default main context][g-main-context-push-thread-default]
  * of the thread you are calling this method from. You can
  * then call g_dbus_connection_close_finish() to get the result of the
@@ -1470,108 +1523,763 @@ g_dbus_connection_close (GDBusConnection     *connection,
 
   g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
 
-  /* do not use g_return_val_if_fail(), we want the memory barrier */
-  if (!check_initialized (connection))
-    return;
+  /* do not use g_return_val_if_fail(), we want the memory barrier */
+  if (!check_initialized (connection))
+    return;
+
+  task = g_task_new (connection, cancellable, callback, user_data);
+  g_task_set_source_tag (task, g_dbus_connection_close);
+  if (connection->worker)
+    {
+      _g_dbus_worker_close (connection->worker, task);
+    }
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  else if (connection->kdbus_worker)
+    {
+      _g_kdbus_worker_close (connection->kdbus_worker, task);
+    }
+#endif
+#endif
+  else
+    g_assert_not_reached();
+  g_object_unref (task);
+}
+
+/**
+ * g_dbus_connection_close_finish:
+ * @connection: a #GDBusConnection
+ * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed
+ *     to g_dbus_connection_close()
+ * @error: return location for error or %NULL
+ *
+ * Finishes an operation started with g_dbus_connection_close().
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if @error is set
+ *
+ * Since: 2.26
+ */
+gboolean
+g_dbus_connection_close_finish (GDBusConnection  *connection,
+                                GAsyncResult     *res,
+                                GError          **error)
+{
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
+  g_return_val_if_fail (g_task_is_valid (res, connection), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+typedef struct {
+    GMainLoop *loop;
+    GAsyncResult *result;
+} SyncCloseData;
+
+/* Can be called by any thread, without the connection lock */
+static void
+sync_close_cb (GObject *source_object,
+               GAsyncResult *res,
+               gpointer user_data)
+{
+  SyncCloseData *data = user_data;
+
+  data->result = g_object_ref (res);
+  g_main_loop_quit (data->loop);
+}
+
+/**
+ * g_dbus_connection_close_sync:
+ * @connection: a #GDBusConnection
+ * @cancellable: (nullable): a #GCancellable or %NULL
+ * @error: return location for error or %NULL
+ *
+ * Synchronously closes @connection. The calling thread is blocked
+ * until this is done. See g_dbus_connection_close() for the
+ * asynchronous version of this method and more details about what it
+ * does.
+ *
+ * Returns: %TRUE if the operation succeeded, %FALSE if @error is set
+ *
+ * Since: 2.26
+ */
+gboolean
+g_dbus_connection_close_sync (GDBusConnection  *connection,
+                              GCancellable     *cancellable,
+                              GError          **error)
+{
+  gboolean ret;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  ret = FALSE;
+
+  if (check_unclosed (connection, 0, error))
+    {
+      GMainContext *context;
+      SyncCloseData data;
+
+      context = g_main_context_new ();
+      g_main_context_push_thread_default (context);
+      data.loop = g_main_loop_new (context, TRUE);
+      data.result = NULL;
+
+      g_dbus_connection_close (connection, cancellable, sync_close_cb, &data);
+      g_main_loop_run (data.loop);
+      ret = g_dbus_connection_close_finish (connection, data.result, error);
+
+      g_object_unref (data.result);
+      g_main_loop_unref (data.loop);
+      g_main_context_pop_thread_default (context);
+      g_main_context_unref (context);
+    }
+
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * 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
+#ifdef KDBUS
+  if (connection->kdbus_worker)
+    return _g_kdbus_RequestName (connection->kdbus_worker, name, flags, error);
+#endif
+#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
+#ifdef KDBUS
+  if (connection->kdbus_worker)
+    return _g_kdbus_ReleaseName (connection->kdbus_worker, name, error);
+#endif
+#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
+#ifdef KDBUS
+  if (connection->kdbus_worker)
+    return _g_kdbus_AddMatch (connection->kdbus_worker, match_rule, error);
+#endif
+#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
+#ifdef KDBUS
+  if (connection->kdbus_worker)
+    return _g_kdbus_RemoveMatch (connection->kdbus_worker, match_rule, error);
+#endif
+#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
+#ifdef KDBUS
+  if (connection->kdbus_worker)
+    return _g_kdbus_GetBusId (connection->kdbus_worker, error);
+#endif
+#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
+#ifdef KDBUS
+      if (connection->kdbus_worker)
+        return _g_kdbus_GetListQueuedOwners (connection->kdbus_worker, name, error);
+#endif
+#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
+#ifdef KDBUS
+      if (connection->kdbus_worker)
+        return _g_kdbus_GetListNames (connection->kdbus_worker, list_name_type, error);
+#endif
+#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
+#ifdef KDBUS
+  if (connection->kdbus_worker)
+    return _g_kdbus_GetNameOwner (connection->kdbus_worker, name, error);
+#endif
+#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
+#ifdef KDBUS
+  if (connection->kdbus_worker)
+    return _g_kdbus_GetConnectionUnixProcessID (connection->kdbus_worker, name, error);
+#endif
+#endif
 
-  g_assert (connection->worker != NULL);
+  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);
+    }
 
-  task = g_task_new (connection, cancellable, callback, user_data);
-  g_task_set_source_tag (task, g_dbus_connection_close);
-  _g_dbus_worker_close (connection->worker, task);
-  g_object_unref (task);
+  return pid;
 }
 
 /**
- * g_dbus_connection_close_finish:
+ * g_dbus_get_connection_uid:
  * @connection: a #GDBusConnection
- * @res: a #GAsyncResult obtained from the #GAsyncReadyCallback passed
- *     to g_dbus_connection_close()
+ * @name: a unique or well-known bus name of the connection to query
  * @error: return location for error or %NULL
  *
- * Finishes an operation started with g_dbus_connection_close().
+ * Synchronously returns the Unix user ID of the process connected to the
+ * bus. If unable to determine it, an @error is returned.
  *
- * Returns: %TRUE if the operation succeeded, %FALSE if @error is set
+ * 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.
  *
- * Since: 2.26
+ * 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
  */
-gboolean
-g_dbus_connection_close_finish (GDBusConnection  *connection,
-                                GAsyncResult     *res,
-                                GError          **error)
+uid_t
+g_dbus_get_connection_uid (GDBusConnection  *connection,
+                           const gchar      *name,
+                           GError          **error)
 {
-  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
-  g_return_val_if_fail (g_task_is_valid (res, connection), FALSE);
-  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+  GVariant *result;
+  uid_t uid;
 
-  return g_task_propagate_boolean (G_TASK (res), error);
-}
+  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);
 
-typedef struct {
-    GMainLoop *loop;
-    GAsyncResult *result;
-} SyncCloseData;
+  result = NULL;
+  uid = -1;
 
-/* Can be called by any thread, without the connection lock */
-static void
-sync_close_cb (GObject *source_object,
-               GAsyncResult *res,
-               gpointer user_data)
-{
-  SyncCloseData *data = user_data;
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  if (connection->kdbus_worker)
+    return _g_kdbus_GetConnectionUnixUser (connection->kdbus_worker, name, error);
+#endif
+#endif
 
-  data->result = g_object_ref (res);
-  g_main_loop_quit (data->loop);
+  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_connection_close_sync:
+ * g_dbus_start_service_by_name:
  * @connection: a #GDBusConnection
- * @cancellable: (nullable): a #GCancellable or %NULL
+ * @name: name of the service to start
+ * @flags: (currently not used)
  * @error: return location for error or %NULL
  *
- * Synchronously closes @connection. The calling thread is blocked
- * until this is done. See g_dbus_connection_close() for the
- * asynchronous version of this method and more details about what it
- * does.
+ * Synchronously tries to launch the executable associated
+ * with a @name.
  *
- * Returns: %TRUE if the operation succeeded, %FALSE if @error is set
+ * The calling thread is blocked until a reply is received.
  *
- * Since: 2.26
+ * Returns: status code or %G_BUS_START_SERVICE_REPLY_ERROR
+ *     if @error is set.
+ *
+ * Since: 2.44
  */
-gboolean
-g_dbus_connection_close_sync (GDBusConnection  *connection,
-                              GCancellable     *cancellable,
+GBusStartServiceReplyFlags
+g_dbus_start_service_by_name (GDBusConnection  *connection,
+                              const gchar      *name,
+                              guint32           flags,
                               GError          **error)
 {
-  gboolean ret;
-
-  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
-  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-  ret = FALSE;
+  GVariant *result;
+  guint32 ret;
 
-  if (check_unclosed (connection, 0, error))
-    {
-      GMainContext *context;
-      SyncCloseData data;
+  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);
 
-      context = g_main_context_new ();
-      g_main_context_push_thread_default (context);
-      data.loop = g_main_loop_new (context, TRUE);
-      data.result = NULL;
+  result = NULL;
+  ret = G_BUS_START_SERVICE_REPLY_ERROR;
 
-      g_dbus_connection_close (connection, cancellable, sync_close_cb, &data);
-      g_main_loop_run (data.loop);
-      ret = g_dbus_connection_close_finish (connection, data.result, error);
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  if (connection->kdbus_worker)
+    return _g_kdbus_StartServiceByName (connection->kdbus_worker, name, flags, NULL, error);
+#endif
+#endif
 
-      g_object_unref (data.result);
-      g_main_loop_unref (data.loop);
-      g_main_context_pop_thread_default (context);
-      g_main_context_unref (context);
+  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 ret;
+  return (GBusStartServiceReplyFlags) ret;
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
@@ -1614,11 +2322,13 @@ g_dbus_connection_send_message_unlocked (GDBusConnection   *connection,
                                          GDBusMessage      *message,
                                          GDBusSendMessageFlags flags,
                                          guint32           *out_serial,
-                                         GError           **error)
+                                         GError           **error,
+                                         gint timeout_msec)
 {
   guchar *blob;
   gsize blob_size;
   guint32 serial_to_use;
+  gboolean ret;
 
   CONNECTION_ENSURE_LOCK (connection);
 
@@ -1627,6 +2337,9 @@ g_dbus_connection_send_message_unlocked (GDBusConnection   *connection,
 
   /* TODO: check all necessary headers are present */
 
+  ret = FALSE;
+  blob = NULL;
+
   if (out_serial != NULL)
     *out_serial = 0;
 
@@ -1638,33 +2351,41 @@ g_dbus_connection_send_message_unlocked (GDBusConnection   *connection,
   if (!check_unclosed (connection,
                        (flags & SEND_MESSAGE_FLAGS_INITIALIZING) ? MAY_BE_UNINITIALIZED : 0,
                        error))
-    return FALSE;
+    goto out;
 
-  blob = g_dbus_message_to_blob (message,
-                                 &blob_size,
-                                 connection->capabilities,
-                                 error);
-  if (blob == NULL)
-    return FALSE;
+  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);
@@ -1687,17 +2408,32 @@ 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);
+  if (connection->worker)
+    {
+      _g_dbus_worker_send_message (connection->worker,
+                                   message,
+                                   (gchar*) blob,
+                                   blob_size);
+    }
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  else if (connection->kdbus_worker)
+    {
+      ret = _g_kdbus_worker_send_message (connection->kdbus_worker, message, timeout_msec, error);
+    }
+#endif
+#endif
+  else
+    g_assert_not_reached ();
 
-  _g_dbus_worker_send_message (connection->worker,
-                               message,
-                               (gchar*) blob, /* transfer ownership */
-                               blob_size);
+  blob = NULL; /* since _g_dbus_worker_send_message() steals the blob */
 
-  return TRUE;
+ out:
+  g_free (blob);
+
+  return ret;
 }
 
 /**
@@ -1751,7 +2487,7 @@ g_dbus_connection_send_message (GDBusConnection        *connection,
   g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
 
   CONNECTION_LOCK (connection);
-  ret = g_dbus_connection_send_message_unlocked (connection, message, flags, (guint32 *) out_serial, error);
+  ret = g_dbus_connection_send_message_unlocked (connection, message, flags, (guint32 *) out_serial, error, -1);
   CONNECTION_UNLOCK (connection);
   return ret;
 }
@@ -1924,9 +2660,6 @@ g_dbus_connection_send_message_with_reply_unlocked (GDBusConnection     *connect
   if (out_serial == NULL)
     out_serial = &serial;
 
-  if (timeout_msec == -1)
-    timeout_msec = 25 * 1000;
-
   data = g_slice_new0 (SendMessageData);
   task = g_task_new (connection, cancellable, callback, user_data);
   g_task_set_source_tag (task,
@@ -1939,7 +2672,7 @@ g_dbus_connection_send_message_with_reply_unlocked (GDBusConnection     *connect
       return;
     }
 
-  if (!g_dbus_connection_send_message_unlocked (connection, message, flags, out_serial, &error))
+  if (!g_dbus_connection_send_message_unlocked (connection, message, flags, out_serial, &error, timeout_msec))
     {
       g_task_return_error (task, error);
       g_object_unref (task);
@@ -1955,9 +2688,16 @@ g_dbus_connection_send_message_with_reply_unlocked (GDBusConnection     *connect
                                                             g_object_unref);
     }
 
-  if (timeout_msec != G_MAXINT)
+  if (timeout_msec != G_MAXINT
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+        /* Userspace timeouts unnecessary on unix/kdbus - kdbus handles timeouts. */
+        && !connection->kdbus_worker
+#endif
+#endif
+     )
     {
-      data->timeout_source = g_timeout_source_new (timeout_msec);
+      data->timeout_source = g_timeout_source_new (timeout_msec == -1 ? DBUS_DEFAULT_TIMEOUT_MSEC : timeout_msec);
       g_task_attach_source (task, data->timeout_source,
                             (GSourceFunc) send_message_with_reply_timeout_cb);
       g_source_unref (data->timeout_source);
@@ -1999,7 +2739,7 @@ g_dbus_connection_send_message_with_reply_unlocked (GDBusConnection     *connect
  * the operation fails with %G_IO_ERROR_INVALID_ARGUMENT.
  *
  * This is an asynchronous method. When the operation is finished, @callback
- * will be invoked in the 
+ * will be invoked in the
  * [thread-default main context][g-main-context-push-thread-default]
  * of the thread you are calling this method from. You can then call
  * g_dbus_connection_send_message_with_reply_finish() to get the result of the operation.
@@ -2161,32 +2901,102 @@ 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.res = NULL;
-  data.context = g_main_context_new ();
-  data.loop = g_main_loop_new (data.context, FALSE);
+  if (connection->worker)
+    {
+      data.res = NULL;
+      data.context = g_main_context_new ();
+      data.loop = g_main_loop_new (data.context, FALSE);
 
-  g_main_context_push_thread_default (data.context);
+      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_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);
+      if (data.res)
+        g_object_unref (data.res);
+    }
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  else if (connection->kdbus_worker)
+    {
+      /* kdbus supports blocking synchronous calls, so let's use them instead of mainloops */
+
+      volatile guint32 serial;
+      guint32 serial_to_use;
+
+      reply = NULL;
+
+      CONNECTION_LOCK (connection);
+
+      if (out_serial == NULL)
+        out_serial = &serial;
+      else
+        *out_serial = 0;
+
+      /*
+       * Check that we never actually send a message if the GCancellable
+       * is already cancelled
+       */
+      if (g_cancellable_is_cancelled (cancellable))
+        {
+          g_set_error_literal (error,
+                               G_IO_ERROR,
+                               G_IO_ERROR_CANCELLED,
+                               _("Operation was cancelled"));
+          CONNECTION_UNLOCK (connection);
+          goto out;
+        }
+
+      if (!check_unclosed (connection,
+                           (flags & SEND_MESSAGE_FLAGS_INITIALIZING) ? MAY_BE_UNINITIALIZED : 0,
+                           error))
+        {
+          CONNECTION_UNLOCK (connection);
+          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_main_context_pop_thread_default (data.context);
+      g_dbus_message_lock (message);
+
+      if (out_serial != NULL)
+        *out_serial = serial_to_use;
+
+      CONNECTION_UNLOCK (connection);
 
-  g_main_context_unref (data.context);
-  g_main_loop_unref (data.loop);
-  if (data.res)
-    g_object_unref (data.res);
+      /* Reference is still kept for the connection, so there is no worry
+       * that it will be freed. Same for connection->kdbus_worker - by reference
+       * from the connection. Inside _g_kdbus_worker_send_message_sync only
+       * initialized-once, read-only fields from kdbus_worker are used, except
+       * 'matches', which now has got its own mutex.
+       */
+      _g_kdbus_worker_send_message_sync (connection->kdbus_worker, message,
+                                         &reply, timeout_msec, cancellable, error);
+
+    }
+#endif /* G_OS_UNIX */
+#endif /* G_OS_UNIX */
+  else
+    g_assert_not_reached ();
 
+out:
   return reply;
 }
 
@@ -2255,8 +3065,7 @@ free_filter_list (FilterData **filters)
 
 /* 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;
@@ -2275,7 +3084,25 @@ 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
+#ifdef KDBUS
+  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
+#endif
 
   g_object_ref (message);
   g_dbus_message_lock (message);
@@ -2353,8 +3180,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;
@@ -2426,10 +3252,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;
@@ -2491,6 +3316,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
@@ -2528,6 +3354,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) ||
@@ -2541,12 +3369,22 @@ 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
+#ifdef KDBUS
+      else if (G_IS_KDBUS_WORKER (ret))
+        connection->kdbus_worker = G_KDBUS_WORKER (ret);
+#endif
+#endif
+      else
+        g_assert_not_reached ();
     }
   else if (connection->stream != NULL)
     {
@@ -2557,6 +3395,22 @@ initable_init (GInitable     *initable,
       g_assert_not_reached ();
     }
 
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  /* Skip authentication process for kdbus transport */
+  if (connection->kdbus_worker)
+    {
+      if (!_g_kdbus_can_connect (connection->kdbus_worker,
+                                 &connection->initialization_error))
+        goto out;
+
+      /* kdbus connection always supports exchanging UNIX file descriptors with the remote peer */
+      connection->capabilities |= G_DBUS_CAPABILITY_FLAGS_UNIX_FD_PASSING;
+      goto authenticated;
+    }
+#endif
+#endif
+
   /* Authenticate the connection */
   if (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER)
     {
@@ -2596,6 +3450,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);
@@ -2616,13 +3472,34 @@ initable_init (GInitable     *initable,
   g_hash_table_add (alive_connections, 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
+#ifdef KDBUS
+  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
+#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)
@@ -2639,25 +3516,50 @@ 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
+#ifdef KDBUS
+      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
+#endif
+      else
+        g_assert_not_reached ();
     }
 
+#ifdef G_OS_UNIX
+#ifdef KDBUS
+  if (connection->kdbus_worker && !initially_frozen)
+    _g_kdbus_worker_unfreeze (connection->kdbus_worker);
+#endif
+#endif
+
   ret = TRUE;
  out:
   if (!ret)
@@ -3377,7 +4279,8 @@ add_match_rule (GDBusConnection *connection,
                                                 message,
                                                 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
                                                 NULL,
-                                                &error))
+                                                &error,
+                                                -1))
     {
       g_critical ("Error while sending AddMatch() message: %s", error->message);
       g_error_free (error);
@@ -3409,7 +4312,8 @@ remove_match_rule (GDBusConnection *connection,
                                                 message,
                                                 G_DBUS_SEND_MESSAGE_FLAGS_NONE,
                                                 NULL,
-                                                &error))
+                                                &error,
+                                                -1))
     {
       /* If we could get G_IO_ERROR_CLOSED here, it wouldn't be reasonable to
        * critical; but we're holding the lock, and our caller checked whether
@@ -3456,7 +4360,7 @@ is_signal_data_for_name_lost_or_acquired (SignalData *signal_data)
  *     subscription is removed or %NULL
  *
  * Subscribes to signals on @connection and invokes @callback with a whenever
- * the signal is received. Note that @callback will be invoked in the 
+ * the signal is received. Note that @callback will be invoked in the
  * [thread-default main context][g-main-context-push-thread-default]
  * of the thread you are calling this method from.
  *
@@ -3604,8 +4508,60 @@ 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
+#ifdef KDBUS
+      else if (connection->kdbus_worker)
+        {
+          gboolean special_rule = FALSE;
+          /* rule for special message */
+          if (!signal_data->sender_unique_name[0] || g_strcmp0 (signal_data->sender_unique_name, "org.freedesktop.DBus") == 0)
+            {
+              if (signal_data->sender_unique_name[0])  /* So, this is org.freedesktop.DBus */
+                special_rule = TRUE;
+              if (!signal_data->object_path || g_strcmp0 (signal_data->object_path, "/org/freedesktop/DBus") == 0)
+                {
+                  if (!signal_data->interface_name || g_strcmp0 (signal_data->interface_name, "org.freedesktop.DBus") == 0)
+                    {
+                      /* By https://dbus.freedesktop.org/doc/dbus-specification.html, org.freedesktop.DBus
+                       * has three signal types: NameAcquired, NameLost, NameOwnerChanged (all covered below).
+                       *
+                       * 1. if sender is NULL and other parameters are matched with special rule, add BOTH special and standard,
+                       *   - (NULL, NULL or DBUS, NULL or DBUS, NULL or Special Name)
+                       *
+                       *    if other parameters are NOT matched with special rule, add standard rule
+                       *   - (NULL, X, X, "NotSpecial")
+                       *
+                       * 2. if sender is 'org.freedesktop.DBus' and other parameters are matched with special rule, add special rule
+                       *   - (org.freedesktop.DBus, NULL or DBUS, NULL or DBUS, NULL or Special Name)
+                       *
+                       *    if other parameters are NOT matched with special rule, then ignore
+                       *   - (org.freedesktop.DBus, X, X, "NotSpecial")
+                       *
+                       * for every other cases, add standard rule,
+                       */
+
+                      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 (!signal_data->member || g_strcmp0 (signal_data->member, "NameOwnerChanged") == 0)
+                        _g_kdbus_subscribe_name_owner_changed (connection->kdbus_worker, signal_data->rule, arg0, NULL);
+                    }
+                }
+            }
+            /* standard rule */
+            if (!special_rule)
+              _g_kdbus_AddMatch (connection->kdbus_worker, signal_data->rule, NULL);
+        }
+#endif
+#endif
+      else
+        g_assert_not_reached ();
     }
 
   signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array,
@@ -3684,7 +4640,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)
             {
@@ -3694,7 +4649,21 @@ 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
+#ifdef KDBUS
+              else if (connection->kdbus_worker)
+                {
+                  _g_kdbus_RemoveMatch (connection->kdbus_worker, signal_data->rule, NULL);
+                }
+#endif
+#endif
+              else
+                g_assert_not_reached ();
             }
 
           signal_data_free (signal_data);
@@ -3778,7 +4747,7 @@ emit_signal_instance_in_idle_cb (gpointer data)
     }
   else
     {
-      g_variant_ref_sink (parameters);
+      g_variant_ref (parameters);
     }
 
 #if 0
@@ -4330,7 +5299,7 @@ validate_and_maybe_schedule_property_getset (GDBusConnection            *connect
                                                "org.freedesktop.DBus.Error.InvalidArgs",
                                                _("No such property “%s”"),
                                                property_name);
-      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
       g_object_unref (reply);
       handled = TRUE;
       goto out;
@@ -4342,7 +5311,7 @@ validate_and_maybe_schedule_property_getset (GDBusConnection            *connect
                                                "org.freedesktop.DBus.Error.InvalidArgs",
                                                _("Property “%s” is not readable"),
                                                property_name);
-      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
       g_object_unref (reply);
       handled = TRUE;
       goto out;
@@ -4353,7 +5322,7 @@ validate_and_maybe_schedule_property_getset (GDBusConnection            *connect
                                                "org.freedesktop.DBus.Error.InvalidArgs",
                                                _("Property “%s” is not writable"),
                                                property_name);
-      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
       g_object_unref (reply);
       handled = TRUE;
       goto out;
@@ -4374,7 +5343,7 @@ validate_and_maybe_schedule_property_getset (GDBusConnection            *connect
                                                    _("Error setting property “%s”: Expected type “%s” but got “%s”"),
                                                    property_name, property_info->signature,
                                                    g_variant_get_type_string (value));
-          g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+          g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
           g_variant_unref (value);
           g_object_unref (reply);
           handled = TRUE;
@@ -4478,7 +5447,7 @@ handle_getset_property (GDBusConnection *connection,
                                                "org.freedesktop.DBus.Error.InvalidArgs",
                                                _("No such interface “%s”"),
                                                interface_name);
-      g_dbus_connection_send_message_unlocked (eo->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+      g_dbus_connection_send_message_unlocked (eo->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
       g_object_unref (reply);
       handled = TRUE;
       goto out;
@@ -4686,7 +5655,7 @@ handle_get_all_properties (GDBusConnection *connection,
                                                "org.freedesktop.DBus.Error.InvalidArgs",
                                                _("No such interface “%s”"),
                                                interface_name);
-      g_dbus_connection_send_message_unlocked (eo->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+      g_dbus_connection_send_message_unlocked (eo->connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
       g_object_unref (reply);
       handled = TRUE;
       goto out;
@@ -4876,7 +5845,7 @@ handle_introspect (GDBusConnection *connection,
 
   reply = g_dbus_message_new_method_reply (message);
   g_dbus_message_set_body (reply, g_variant_new ("(s)", s->str));
-  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
   g_object_unref (reply);
   g_string_free (s, TRUE);
 
@@ -5002,7 +5971,7 @@ validate_and_maybe_schedule_method_call (GDBusConnection            *connection,
                                                "org.freedesktop.DBus.Error.UnknownMethod",
                                                _("No such method “%s”"),
                                                g_dbus_message_get_member (message));
-      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
       g_object_unref (reply);
       handled = TRUE;
       goto out;
@@ -5034,7 +6003,7 @@ validate_and_maybe_schedule_method_call (GDBusConnection            *connection,
                                                _("Type of message, “%s”, does not match expected type “%s”"),
                                                g_variant_get_type_string (parameters),
                                                type_string);
-      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+      g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
       g_variant_type_free (in_type);
       g_variant_unref (parameters);
       g_object_unref (reply);
@@ -5151,7 +6120,7 @@ obj_message_func (GDBusConnection *connection,
  * D-Bus interface that is described in @interface_info.
  *
  * Calls to functions in @vtable (and @user_data_free_func) will happen
- * in the 
+ * in the
  * [thread-default main context][g-main-context-push-thread-default]
  * of the thread you are calling this method from.
  *
@@ -5718,6 +6687,16 @@ decode_method_reply (GDBusMessage        *reply,
 
     case G_DBUS_MESSAGE_TYPE_ERROR:
       g_dbus_message_to_gerror (reply, error);
+      if (error == NULL || *error == NULL)
+        break;
+      if ((*error)->code == G_DBUS_ERROR_NO_REPLY)
+        {
+          g_clear_error(error);
+          g_set_error (error,
+                       G_IO_ERROR,
+                       G_IO_ERROR_TIMED_OUT,
+                       _("Timeout was reached"));
+        }
       break;
 
     default:
@@ -7001,7 +7980,7 @@ handle_generic_ping_unlocked (GDBusConnection *connection,
 {
   GDBusMessage *reply;
   reply = g_dbus_message_new_method_reply (message);
-  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
   g_object_unref (reply);
 }
 
@@ -7034,7 +8013,7 @@ handle_generic_get_machine_id_unlocked (GDBusConnection *connection,
       reply = g_dbus_message_new_method_reply (message);
       g_dbus_message_set_body (reply, g_variant_new ("(s)", connection->machine_id));
     }
-  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
   g_object_unref (reply);
 }
 
@@ -7061,7 +8040,7 @@ handle_generic_introspect_unlocked (GDBusConnection *connection,
 
   reply = g_dbus_message_new_method_reply (message);
   g_dbus_message_set_body (reply, g_variant_new ("(s)", s->str));
-  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
   g_object_unref (reply);
   g_string_free (s, TRUE);
 }
@@ -7210,7 +8189,7 @@ distribute_method_call (GDBusConnection *connection,
                                            object_path);
     }
 
-  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL);
+  g_dbus_connection_send_message_unlocked (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL, -1);
   g_object_unref (reply);
 
  out:
@@ -7517,3 +8496,10 @@ g_bus_get_finish (GAsyncResult  *res,
 }
 
 /* ---------------------------------------------------------------------------------------------------- */
+#ifdef _TIZEN_DBUS_TOUCH
+static void __attribute__((constructor)) glib_type_dbus_connection_gc( void )
+{
+       GObject* temp = g_type_class_ref(G_TYPE_DBUS_CONNECTION);
+       g_type_class_unref(temp);
+}
+#endif