ui/dbus: win32 support

D-Bus doesn't support fd-passing on Windows (AF_UNIX doesn't have
SCM_RIGHTS yet, but there are other means to share objects. I have
proposed various solutions upstream, but none seem fitting enough atm).

To make the "-display dbus" work on Windows, implement an alternative
D-Bus interface where all the 'h' (FDs) arguments are replaced with
'ay' (WSASocketW data), and sockets are passed to the other end via
WSADuplicateSocket().

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20230606115658.677673-6-marcandre.lureau@redhat.com>
This commit is contained in:
Marc-André Lureau 2023-06-06 15:56:42 +04:00
parent 9b286e76c8
commit 6cc5a6159a
7 changed files with 149 additions and 23 deletions

View file

@ -110,18 +110,24 @@ dbus_chardev_init(DBusDisplay *dpy)
dbus_display_chardev_foreach, dpy);
}
#ifdef G_OS_UNIX
static gboolean
dbus_chr_register(
DBusChardev *dc,
GDBusMethodInvocation *invocation,
#ifdef G_OS_UNIX
GUnixFDList *fd_list,
#endif
GVariant *arg_stream,
QemuDBusDisplay1Chardev *object)
{
g_autoptr(GError) err = NULL;
int fd;
#ifdef G_OS_WIN32
if (!dbus_win32_import_socket(invocation, arg_stream, &fd)) {
return DBUS_METHOD_INVOCATION_HANDLED;
}
#else
fd = g_unix_fd_list_get(fd_list, g_variant_get_handle(arg_stream), &err);
if (err) {
g_dbus_method_invocation_return_error(
@ -131,13 +137,18 @@ dbus_chr_register(
"Couldn't get peer FD: %s", err->message);
return DBUS_METHOD_INVOCATION_HANDLED;
}
#endif
if (qemu_chr_add_client(CHARDEV(dc), fd) < 0) {
g_dbus_method_invocation_return_error(invocation,
DBUS_DISPLAY_ERROR,
DBUS_DISPLAY_ERROR_FAILED,
"Couldn't register FD!");
#ifdef G_OS_WIN32
closesocket(fd);
#else
close(fd);
#endif
return DBUS_METHOD_INVOCATION_HANDLED;
}
@ -145,10 +156,13 @@ dbus_chr_register(
"owner", g_dbus_method_invocation_get_sender(invocation),
NULL);
qemu_dbus_display1_chardev_complete_register(object, invocation, NULL);
qemu_dbus_display1_chardev_complete_register(object, invocation
#ifndef G_OS_WIN32
, NULL
#endif
);
return DBUS_METHOD_INVOCATION_HANDLED;
}
#endif
static gboolean
dbus_chr_send_break(
@ -179,10 +193,8 @@ dbus_chr_open(Chardev *chr, ChardevBackend *backend,
dc->iface = qemu_dbus_display1_chardev_skeleton_new();
g_object_set(dc->iface, "name", backend->u.dbus.data->name, NULL);
g_object_connect(dc->iface,
#ifdef G_OS_UNIX
"swapped-signal::handle-register",
dbus_chr_register, dc,
#endif
"swapped-signal::handle-send-break",
dbus_chr_send_break, dc,
NULL);