#include "gsimpleasyncresult.h"
#ifdef G_OS_UNIX
+#include "gkdbus.h"
#include "gunixconnection.h"
#include "gunixfdmessage.h"
#endif
* over any transport that can by represented as an #GIOStream.
*
* This class is rarely used directly in D-Bus clients. If you are writing
- * an D-Bus client, it is often easier to use the g_bus_own_name(),
+ * a D-Bus client, it is often easier to use the g_bus_own_name(),
* g_bus_watch_name() or g_dbus_proxy_new_for_bus() APIs.
*
* As an exception to the usual GLib rule that a particular object must not
* #GError, the only valid thing you can do with that #GDBusConnection is to
* free it with g_object_unref().
*
- * <example id="gdbus-server"><title>D-Bus server example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-server.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
+ * ## An example D-Bus server # {#gdbus-server}
*
- * <example id="gdbus-subtree-server"><title>D-Bus subtree example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-subtree.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
+ * Here is an example for a D-Bus server:
+ * [gdbus-example-server.c](https://git.gnome.org/browse/glib/tree/gio/tests/gdbus-example-server.c)
*
- * <example id="gdbus-unix-fd-client"><title>D-Bus UNIX File Descriptor example</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-unix-fd-client.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
+ * ## An example for exporting a subtree # {#gdbus-subtree-server}
*
- * <example id="gdbus-export"><title>Exporting a GObject</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude" parse="text" href="../../../../gio/tests/gdbus-example-export.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
+ * Here is an example for exporting a subtree:
+ * [gdbus-example-subtree.c](https://git.gnome.org/browse/glib/tree/gio/tests/gdbus-example-subtree.c)
+ *
+ * ## An example for file descriptor passing # {#gdbus-unix-fd-client}
+ *
+ * Here is an example for passing UNIX file descriptors:
+ * [gdbus-unix-fd-client.c](https://git.gnome.org/browse/glib/tree/gio/tests/gdbus-unix-fd-client.c)
+ *
+ * ## An example for exporting a GObject # {#gdbus-export}
+ *
+ * Here is an example for exporting a #GObject:
+ * [gdbus-example-export.c](https://git.gnome.org/browse/glib/tree/gio/tests/gdbus-example-export.c)
*/
/* ---------------------------------------------------------------------------------------------------- */
static GWeakRef the_session_bus;
static GWeakRef the_system_bus;
+static GWeakRef the_user_bus;
+static GWeakRef the_machine_bus;
/* Extra pseudo-member of GDBusSendMessageFlags.
* Set by initable_init() to indicate that despite not being initialized yet,
call_destroy_notify_data_in_idle,
data,
(GDestroyNotify) call_destroy_notify_data_free);
+ g_source_set_name (idle_source, "[gio] call_destroy_notify_data_in_idle");
g_source_attach (idle_source, data->context);
g_source_unref (idle_source);
* hold @init_lock or check for initialization first.
*/
GDBusWorker *worker;
+ GKDBusWorker *kdbus_worker;
/* If connected to a message bus, this contains the unique name assigned to
* us by the bus (e.g. ":1.42").
* GDBusConnection:exit-on-close:
*
* A boolean specifying whether the process will be terminated (by
- * calling <literal>raise(SIGTERM)</literal>) if the connection
- * is closed by the remote peer.
+ * calling `raise(SIGTERM)`) if the connection is closed by the
+ * remote peer.
*
- * Note that #GDBusConnection objects returned by g_bus_get_finish() and
- * g_bus_get_sync() will (usually) have this property set to %TRUE.
+ * Note that #GDBusConnection objects returned by g_bus_get_finish()
+ * and g_bus_get_sync() will (usually) have this property set to %TRUE.
*
* Since: 2.26
*/
if (!check_initialized (connection))
return;
- g_assert (connection->worker != NULL);
- _g_dbus_worker_unfreeze (connection->worker);
+ g_assert (connection->worker || connection->kdbus_worker);
+
+ if (connection->kdbus_worker)
+ g_kdbus_worker_unfreeze (connection->kdbus_worker);
+ else
+ _g_dbus_worker_unfreeze (connection->worker);
}
/**
* been sent to the networking buffers in the OS kernel.
*
* This is an asynchronous method. When the operation is finished,
- * @callback will be invoked in the <link
- * linkend="g-main-context-push-thread-default">thread-default main
- * loop</link> of the thread you are calling this method from. You can
+ * @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_flush_finish() to get the result of the
* operation. See g_dbus_connection_flush_sync() for the synchronous
* version.
emit_closed_in_idle,
data,
(GDestroyNotify) emit_closed_data_free);
+ g_source_set_name (idle_source, "[gio] emit_closed_in_idle");
g_source_attach (idle_source, connection->main_context_at_construction);
g_source_unref (idle_source);
}
* %G_IO_ERROR_CLOSED.
*
* When @connection has been closed, the #GDBusConnection::closed
- * signal is emitted in the <link
- * linkend="g-main-context-push-thread-default">thread-default main
- * loop</link> of the thread that @connection was constructed in.
+ * signal is emitted in the
+ * [thread-default main context][g-main-context-push-thread-default]
+ * of the thread that @connection was constructed in.
*
* This is an asynchronous method. When the operation is finished,
- * @callback will be invoked in the <link
- * linkend="g-main-context-push-thread-default">thread-default main
- * loop</link> of the thread you are calling this method from. You can
+ * @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
* operation. See g_dbus_connection_close_sync() for the synchronous
* version.
/* ---------------------------------------------------------------------------------------------------- */
/**
+ * 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.
+ *
+ * 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.4x
+ */
+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);
+
+ if (connection->kdbus_worker)
+ result = _g_kdbus_RequestName (connection->kdbus_worker, name, flags, error);
+ else
+ 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.
+ *
+ * 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.4x
+ */
+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);
+
+ if (connection->kdbus_worker)
+ result = _g_kdbus_ReleaseName (connection->kdbus_worker, name, error);
+ else
+ 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_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.4x
+ */
+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;
+
+ if (connection->kdbus_worker)
+ {
+ result = _g_kdbus_GetBusId (connection->kdbus_worker, error);
+ }
+ else
+ {
+ 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)
+ {
+ if (connection->kdbus_worker)
+ result = _g_kdbus_GetListQueuedOwners (connection->kdbus_worker, name, error);
+ else
+ 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";
+
+ if (connection->kdbus_worker)
+ result = _g_kdbus_GetListNames (connection->kdbus_worker, list_name_type, error);
+ else
+ 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.4x
+ */
+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.4x
+ */
+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.4x
+ */
+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.4x
+ */
+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;
+
+ if (connection->kdbus_worker)
+ result = _g_kdbus_GetNameOwner (connection->kdbus_worker, name, error);
+ else
+ 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 (guint32) -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
+ * (guint32) -1 if @error is set.
+ *
+ * Since: 2.4x
+ */
+guint32
+g_dbus_get_connection_pid (GDBusConnection *connection,
+ const gchar *name,
+ GError **error)
+{
+ GVariant *result;
+ guint32 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;
+
+ if (connection->kdbus_worker)
+ result = _g_kdbus_GetConnectionUnixProcessID (connection->kdbus_worker, name, error);
+ else
+ 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 (guint32) -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
+ * (guint32) -1 if @error is set.
+ *
+ * Since: 2.4x
+ */
+guint32
+g_dbus_get_connection_uid (GDBusConnection *connection,
+ const gchar *name,
+ GError **error)
+{
+ GVariant *result;
+ guint32 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;
+
+ if (connection->kdbus_worker)
+ result = _g_kdbus_GetConnectionUnixUser (connection->kdbus_worker, name, error);
+ else
+ 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_get_last_serial:
* @connection: a #GDBusConnection
*
}
/* ---------------------------------------------------------------------------------------------------- */
-
+#include "gkdbus.h"
/* Can be called by any thread, with the connection lock held */
static gboolean
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);
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);
+ else
+ ret = g_kdbus_worker_send_message (connection->kdbus_worker, message, error);
- ret = TRUE;
+ blob = NULL; /* since _g_dbus_worker_send_message() steals the blob */
out:
g_free (blob);
* %G_IO_ERROR_CLOSED. If @message is not well-formed,
* the operation fails with %G_IO_ERROR_INVALID_ARGUMENT.
*
- * See <xref linkend="gdbus-server"/> and <xref
- * linkend="gdbus-unix-fd-client"/> for an example of how to use this
- * low-level API to send and receive UNIX file descriptors.
+ * See this [server][gdbus-server] and [client][gdbus-unix-fd-client]
+ * for an example of how to use this low-level API to send and receive
+ * UNIX file descriptors.
*
* Note that @message must be unlocked, unless @flags contain the
* %G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL flag.
send_message_with_reply_cancelled_idle_cb,
send_message_data_ref (data),
(GDestroyNotify) send_message_data_unref);
+ g_source_set_name (idle_source, "[gio] send_message_with_reply_cancelled_idle_cb");
g_source_attach (idle_source, data->main_context);
g_source_unref (idle_source);
}
* fail with %G_IO_ERROR_CANCELLED. If @message is not well-formed,
* 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 <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
+ * This is an asynchronous method. When the operation is finished, @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_send_message_with_reply_finish() to get the result of the operation.
* See g_dbus_connection_send_message_with_reply_sync() for the synchronous version.
* Note that @message must be unlocked, unless @flags contain the
* %G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL flag.
*
- * See <xref linkend="gdbus-server"/> and <xref
- * linkend="gdbus-unix-fd-client"/> for an example of how to use this
- * low-level API to send and receive UNIX file descriptors.
+ * See this [server][gdbus-server] and [client][gdbus-unix-fd-client]
+ * for an example of how to use this low-level API to send and receive
+ * UNIX file descriptors.
*
* Since: 2.26
*/
* be of type %G_DBUS_MESSAGE_TYPE_ERROR. Use
* g_dbus_message_to_gerror() to transcode this to a #GError.
*
- * See <xref linkend="gdbus-server"/> and <xref
- * linkend="gdbus-unix-fd-client"/> for an example of how to use this
- * low-level API to send and receive UNIX file descriptors.
+ * See this [server][gdbus-server] and [client][gdbus-unix-fd-client]
+ * for an example of how to use this low-level API to send and receive
+ * UNIX file descriptors.
*
* Returns: (transfer full): a locked #GDBusMessage or %NULL if @error is set
*
* be of type %G_DBUS_MESSAGE_TYPE_ERROR. Use
* g_dbus_message_to_gerror() to transcode this to a #GError.
*
- * See <xref linkend="gdbus-server"/> and <xref
- * linkend="gdbus-unix-fd-client"/> for an example of how to use this
- * low-level API to send and receive UNIX file descriptors.
+ * See this [server][gdbus-server] and [client][gdbus-unix-fd-client]
+ * for an example of how to use this low-level API to send and receive
+ * UNIX file descriptors.
*
* Note that @message must be unlocked, unless @flags contain the
* %G_DBUS_SEND_MESSAGE_FLAGS_PRESERVE_SERIAL flag.
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
data = g_new0 (SendMessageSyncData, 1);
- data->context = g_main_context_new ();
+
+ if (connection->kdbus_worker)
+ data->context = g_main_context_ref_thread_default ();
+ else
+ data->context = g_main_context_new ();
+
data->loop = g_main_loop_new (data->context, FALSE);
g_main_context_push_thread_default (data->context);
/* 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;
/* 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;
/* 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;
GError **error)
{
GDBusConnection *connection = G_DBUS_CONNECTION (initable);
+ gboolean initially_frozen;
gboolean ret;
/* This method needs to be idempotent to work with the singleton
*/
if (connection->address != NULL)
{
+ GObject *ret;
+
g_assert (connection->stream == NULL);
if ((connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER) ||
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);
+ else if (G_IS_KDBUS_WORKER (ret))
+ connection->kdbus_worker = G_KDBUS_WORKER (ret);
+ else
+ g_assert_not_reached ();
}
else if (connection->stream != NULL)
{
g_assert_not_reached ();
}
+ /* [KDBUS] Skip authentication process for kdbus transport */
+ if (connection->kdbus_worker)
+ {
+ goto authenticated;
+ }
+
/* Authenticate the connection */
if (connection->flags & G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER)
{
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);
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 (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);
+ 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)
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 (connection->kdbus_worker)
+ {
+ hello_result = _g_kdbus_Hello (connection->kdbus_worker, &connection->initialization_error);
+ }
+ else
+ {
+ 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_debug ("unique name is '%s'", connection->bus_unique_name);
}
+ if (connection->kdbus_worker && !initially_frozen)
+ g_kdbus_worker_unfreeze (connection->kdbus_worker);
+
ret = TRUE;
out:
if (!ret)
* @user_data_free_func: (allow-none): function to free @user_data with when
* 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 <link
- * linkend="g-main-context-push-thread-default">thread-default main
- * loop</link> of the thread you are calling this method from.
+ * Subscribes to signals on @connection and invokes @callback with a whenever
+ * 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.
*
* If @connection is not a message bus connection, @sender must be
* %NULL.
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->kdbus_worker)
+ _g_kdbus_AddMatch (connection->kdbus_worker, signal_data->rule, subscriber.id);
+ else
+ add_match_rule (connection, signal_data->rule);
+ else
+ {
+ if (connection->kdbus_worker)
+ {
+ if (g_strcmp0 (signal_data->member, "NameAcquired") == 0)
+ _g_kdbus_subscribe_name_acquired (connection->kdbus_worker, arg0);
+ else if (g_strcmp0 (signal_data->member, "NameLost") == 0)
+ _g_kdbus_subscribe_name_lost (connection->kdbus_worker, arg0);
+ }
+ }
}
signal_data_array = g_hash_table_lookup (connection->map_sender_unique_name_to_signal_data_array,
* 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->kdbus_worker)
+ _g_kdbus_RemoveMatch (connection->kdbus_worker, subscription_id);
+ else
+ remove_match_rule (connection, signal_data->rule);
+ }
+ else
+ {
+ if (connection->kdbus_worker)
+ {
+ if (g_strcmp0 (signal_data->member, "NameAcquired") == 0)
+ _g_kdbus_unsubscribe_name_acquired (connection->kdbus_worker);
+ else if (g_strcmp0 (signal_data->member, "NameLost") == 0)
+ _g_kdbus_unsubscribe_name_lost (connection->kdbus_worker);
+ }
}
signal_data_free (signal_data);
}
else
{
- g_variant_ref_sink (parameters);
+ g_variant_ref (parameters);
}
#if 0
emit_signal_instance_in_idle_cb,
signal_instance,
(GDestroyNotify) signal_instance_free);
+ g_source_set_name (idle_source, "[gio] emit_signal_instance_in_idle_cb");
g_source_attach (idle_source, subscriber->context);
g_source_unref (idle_source);
}
is_get ? invoke_get_property_in_idle_cb : invoke_set_property_in_idle_cb,
property_data,
(GDestroyNotify) property_data_free);
+ if (is_get)
+ g_source_set_name (idle_source, "[gio] invoke_get_property_in_idle_cb");
+ else
+ g_source_set_name (idle_source, "[gio] invoke_set_property_in_idle_cb");
g_source_attach (idle_source, main_context);
g_source_unref (idle_source);
invoke_get_all_properties_in_idle_cb,
property_get_all_data,
(GDestroyNotify) property_get_all_data_free);
+ g_source_set_name (idle_source, "[gio] invoke_get_all_properties_in_idle_cb");
g_source_attach (idle_source, main_context);
g_source_unref (idle_source);
call_in_idle_cb,
invocation,
g_object_unref);
+ g_source_set_name (idle_source, "[gio] call_in_idle_cb");
g_source_attach (idle_source, main_context);
g_source_unref (idle_source);
}
* Registers callbacks for exported objects at @object_path with the
* D-Bus interface that is described in @interface_info.
*
- * Calls to functions in @vtable (and @user_data_free_func) will
- * happen in the <link linkend="g-main-context-push-thread-default">thread-default main
- * loop</link> of the thread you are calling this method from.
+ * Calls to functions in @vtable (and @user_data_free_func) will happen
+ * in the
+ * [thread-default main context][g-main-context-push-thread-default]
+ * of the thread you are calling this method from.
*
* Note that all #GVariant values passed to functions in @vtable will match
* the signature given in @interface_info - if a remote caller passes
- * incorrect values, the <literal>org.freedesktop.DBus.Error.InvalidArgs</literal>
+ * incorrect values, the `org.freedesktop.DBus.Error.InvalidArgs`
* is returned to the remote caller.
*
* Additionally, if the remote caller attempts to invoke methods or
* access properties not mentioned in @interface_info the
- * <literal>org.freedesktop.DBus.Error.UnknownMethod</literal> resp.
- * <literal>org.freedesktop.DBus.Error.InvalidArgs</literal> errors
+ * `org.freedesktop.DBus.Error.UnknownMethod` resp.
+ * `org.freedesktop.DBus.Error.InvalidArgs` errors
* are returned to the caller.
*
* It is considered a programming error if the
* reference count is -1, see g_dbus_interface_info_ref()) for as long
* as the object is exported. Also note that @vtable will be copied.
*
- * See <xref linkend="gdbus-server"/> for an example of how to use this method.
+ * See this [server][gdbus-server] for an example of how to use this method.
*
* Returns: 0 if @error is set, otherwise a registration id (never 0)
* that can be used with g_dbus_connection_unregister_object()
*
* If the @parameters #GVariant is floating, it is consumed. This allows
* convenient 'inline' use of g_variant_new(), e.g.:
- * |[
+ * |[<!-- language="C" -->
* g_dbus_connection_call (connection,
* "org.freedesktop.StringThings",
* "/org/freedesktop/StringThings",
* NULL);
* ]|
*
- * This is an asynchronous method. When the operation is finished, @callback will be invoked
- * in the <link linkend="g-main-context-push-thread-default">thread-default main loop</link>
+ * This is an asynchronous method. When the operation is finished,
+ * @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_call_finish() to get the result of the operation.
* See g_dbus_connection_call_sync() for the synchronous version of this
*
* If the @parameters #GVariant is floating, it is consumed.
* This allows convenient 'inline' use of g_variant_new(), e.g.:
- * |[
+ * |[<!-- language="C" -->
* g_dbus_connection_call_sync (connection,
* "org.freedesktop.StringThings",
* "/org/freedesktop/StringThings",
* G_DBUS_CALL_FLAGS_NONE,
* -1,
* NULL,
- * &error);
+ * &error);
* ]|
*
* The calling thread is blocked until a reply is received. See
process_subtree_vtable_message_in_idle_cb,
data,
(GDestroyNotify) subtree_deferred_data_free);
+ g_source_set_name (idle_source, "[gio] process_subtree_vtable_message_in_idle_cb");
g_source_attach (idle_source, es->context);
g_source_unref (idle_source);
* @user_data_free_func: function to call when the subtree is unregistered
* @error: return location for error or %NULL
*
- * Registers a whole subtree of <quote>dynamic</quote> objects.
+ * Registers a whole subtree of dynamic objects.
*
* The @enumerate and @introspection functions in @vtable are used to
* convey, to remote callers, what nodes exist in the subtree rooted
* #gpointer will be used to call into the interface vtable for processing
* the request.
*
- * All calls into user-provided code will be invoked in the <link
- * linkend="g-main-context-push-thread-default">thread-default main
- * loop</link> of the thread you are calling this method from.
+ * All calls into user-provided code will be invoked in the
+ * [thread-default main context][g-main-context-push-thread-default]
+ * of the thread you are calling this method from.
*
* If an existing subtree is already registered at @object_path or
* then @error is set to #G_IO_ERROR_EXISTS.
* g_dbus_connection_register_object()) in a subtree registered with
* g_dbus_connection_register_subtree() - if so, the subtree handler
* is tried as the last resort. One way to think about a subtree
- * handler is to consider it a <quote>fallback handler</quote>
- * for object paths not registered via g_dbus_connection_register_object()
- * or other bindings.
+ * handler is to consider it a fallback handler for object paths not
+ * registered via g_dbus_connection_register_object() or other bindings.
*
* Note that @vtable will be copied so you cannot change it after
* registration.
*
- * See <xref linkend="gdbus-subtree-server"/> for an example of how to use this method.
+ * See this [server][gdbus-subtree-server] for an example of how to use
+ * this method.
*
* Returns: 0 if @error is set, otherwise a subtree registration id (never 0)
* that can be used with g_dbus_connection_unregister_subtree() .
ret = &the_system_bus;
break;
+ case G_BUS_TYPE_USER:
+ ret = &the_user_bus;
+ break;
+
+ case G_BUS_TYPE_MACHINE:
+ ret = &the_machine_bus;
+ break;
+
case G_BUS_TYPE_STARTER:
starter_bus = g_getenv ("DBUS_STARTER_BUS_TYPE");
if (g_strcmp0 (starter_bus, "session") == 0)