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