#include "gmarshal-internal.h"
#ifdef G_OS_UNIX
+#ifdef KDBUS
+#include "gkdbus.h"
+#endif
#include "gunixconnection.h"
#include "gunixfdmessage.h"
#endif
*/
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
G_LOCK (message_bus_lock);
CONNECTION_LOCK (connection);
+
if (connection->worker != NULL)
{
_g_dbus_worker_stop (connection->worker);
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)
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
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 ();
}
/**
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;
* 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
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;
}
/* ---------------------------------------------------------------------------------------------------- */
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);
/* TODO: check all necessary headers are present */
+ ret = FALSE;
+ blob = NULL;
+
if (out_serial != NULL)
*out_serial = 0;
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);
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;
}
/**
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;
}
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,
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);
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);
* 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.
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;
}
/* 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;
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);
/* 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);
+#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)
{
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)
{
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_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)
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)
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);
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
* 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.
*
*/
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,
/* 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)
{
* 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);
}
else
{
- g_variant_ref_sink (parameters);
+ g_variant_ref (parameters);
}
#if 0
"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;
"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;
"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;
_("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;
"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;
"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;
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);
"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;
_("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);
* 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.
*
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:
{
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);
}
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);
}
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);
}
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:
}
/* ---------------------------------------------------------------------------------------------------- */
+#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