From 98032981cd75a26f54f7d002965be960e03b0599 Mon Sep 17 00:00:00 2001 From: Christian Hergert Date: Sun, 26 Feb 2023 10:57:50 -0800 Subject: [PATCH] util: add socketpair GDBusConnection helper --- lib/mks-util-private.h | 10 +++- lib/mks-util.c | 132 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 141 insertions(+), 1 deletion(-) diff --git a/lib/mks-util-private.h b/lib/mks-util-private.h index b24aebc..5aeb28e 100644 --- a/lib/mks-util-private.h +++ b/lib/mks-util-private.h @@ -22,6 +22,7 @@ #include #include +#include G_BEGIN_DECLS @@ -31,6 +32,13 @@ G_BEGIN_DECLS (CAIRO_VERSION_MAJOR == (major) && CAIRO_VERSION_MINOR == (minor) && \ CAIRO_VERSION_MICRO >= (micro))) -gboolean mks_scroll_event_is_inverted (GdkEvent *event); +gboolean mks_scroll_event_is_inverted (GdkEvent *event); +void mks_socketpair_connection_new (GDBusConnectionFlags flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +GDBusConnection *mks_socketpair_connection_new_finish (GAsyncResult *result, + int *peer_fd, + GError **error); G_END_DECLS diff --git a/lib/mks-util.c b/lib/mks-util.c index aeea6da..d6d31d0 100644 --- a/lib/mks-util.c +++ b/lib/mks-util.c @@ -20,6 +20,9 @@ #include "config.h" +#include +#include + #include "mks-util-private.h" static GSettings *mouse_settings; @@ -86,3 +89,132 @@ mks_scroll_event_is_inverted (GdkEvent *event) return FALSE; } } + +static gboolean +create_socketpair (int *us, + int *them, + GError **error) +{ + int fds[2]; + int rv; + + rv = socketpair (AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, fds); + + if (rv != 0) + { + int errsv = errno; + g_set_error_literal (error, + G_IO_ERROR, + g_io_error_from_errno (errsv), + g_strerror (errsv)); + return FALSE; + } + + *us = fds[0]; + *them = fds[1]; + + return TRUE; +} + +static void +fdptr_clear (gpointer data) +{ + int *fdptr = data; + if (*fdptr != -1) + close (*fdptr); + *fdptr = -1; + g_free (fdptr); +} + +static void +mks_socketpair_connection_cb (GObject *object, + GAsyncResult *result, + gpointer user_data) +{ + g_autoptr(GTask) task = user_data; + g_autoptr(GDBusConnection) ret = NULL; + g_autoptr(GError) error = NULL; + + g_assert (G_IS_ASYNC_RESULT (result)); + g_assert (G_IS_TASK (task)); + + if (!(ret = g_dbus_connection_new_finish (result, &error))) + g_task_return_error (task, g_steal_pointer (&error)); + else + g_task_return_pointer (task, g_steal_pointer (&ret), g_object_unref); +} + +void +mks_socketpair_connection_new (GDBusConnectionFlags flags, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_autoptr(GSocketConnection) io_stream = NULL; + g_autoptr(GSocket) socket = NULL; + g_autoptr(GError) error = NULL; + g_autoptr(GTask) task = NULL; + g_autofd int us = -1; + g_autofd int them = -1; + int *fdptr; + + g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable)); + + task = g_task_new (NULL, cancellable, callback, user_data); + g_task_set_source_tag (task, mks_socketpair_connection_new); + g_task_set_task_data (task, GINT_TO_POINTER (-1), NULL); + + if (!create_socketpair (&us, &them, &error) || + !(socket = g_socket_new_from_fd (us, &error))) + { + g_task_return_error (task, g_steal_pointer (&error)); + return; + } + + io_stream = g_socket_connection_factory_create_connection (socket); + fdptr = g_memdup2 (&them, sizeof them); + g_task_set_task_data (task, fdptr, fdptr_clear); + + us = -1; + them = -1; + + g_dbus_connection_new (G_IO_STREAM (io_stream), + NULL, + flags | G_DBUS_CONNECTION_FLAGS_DELAY_MESSAGE_PROCESSING, + NULL, + cancellable, + mks_socketpair_connection_cb, + g_steal_pointer (&task)); + +} + +/** + * mks_socketpair_connection_new_finish: + * @result: a #GAsyncResult + * @peer_fd: (out): a location for a socketpair file-descriptor + * @error: (out): a location for a #GError, or %NULL + * + * Completes the asynchronous request to create a socketpair()-based + * D-Bus connection. + * + * Returns: (transfer full): a #GDBusConnection and @peer_fd is set + * if successful; otherwise %NULL and @error is set. + */ +GDBusConnection * +mks_socketpair_connection_new_finish (GAsyncResult *result, + int *peer_fd, + GError **error) +{ + GDBusConnection *ret; + int *fdptr; + + g_return_val_if_fail (G_IS_TASK (result), NULL); + g_return_val_if_fail (peer_fd != NULL, NULL); + + fdptr = g_task_get_task_data (G_TASK (result)); + + if ((ret = g_task_propagate_pointer (G_TASK (result), error))) + *peer_fd = g_steal_fd (fdptr); + + return ret; +}