mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-07 01:33:56 -06:00
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:
parent
9b286e76c8
commit
6cc5a6159a
7 changed files with 149 additions and 23 deletions
|
@ -165,7 +165,6 @@ dbus_display_console_class_init(DBusDisplayConsoleClass *klass)
|
|||
gobject_class->dispose = dbus_display_console_dispose;
|
||||
}
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
static void
|
||||
listener_vanished_cb(DBusDisplayListener *listener)
|
||||
{
|
||||
|
@ -177,7 +176,6 @@ listener_vanished_cb(DBusDisplayListener *listener)
|
|||
g_hash_table_remove(ddc->listeners, name);
|
||||
qkbd_state_lift_all_keys(ddc->kbd);
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
dbus_console_set_ui_info(DBusDisplayConsole *ddc,
|
||||
|
@ -211,11 +209,47 @@ dbus_console_set_ui_info(DBusDisplayConsole *ddc,
|
|||
return DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
|
||||
#ifdef G_OS_UNIX
|
||||
#ifdef G_OS_WIN32
|
||||
bool
|
||||
dbus_win32_import_socket(GDBusMethodInvocation *invocation,
|
||||
GVariant *arg_listener, int *socket)
|
||||
{
|
||||
gsize n;
|
||||
WSAPROTOCOL_INFOW *info = (void *)g_variant_get_fixed_array(arg_listener, &n, 1);
|
||||
|
||||
if (!info || n != sizeof(*info)) {
|
||||
g_dbus_method_invocation_return_error(
|
||||
invocation,
|
||||
DBUS_DISPLAY_ERROR,
|
||||
DBUS_DISPLAY_ERROR_FAILED,
|
||||
"Failed to get socket infos");
|
||||
return false;
|
||||
}
|
||||
|
||||
*socket = WSASocketW(FROM_PROTOCOL_INFO,
|
||||
FROM_PROTOCOL_INFO,
|
||||
FROM_PROTOCOL_INFO,
|
||||
info, 0, 0);
|
||||
if (*socket == INVALID_SOCKET) {
|
||||
g_autofree gchar *emsg = g_win32_error_message(WSAGetLastError());
|
||||
g_dbus_method_invocation_return_error(
|
||||
invocation,
|
||||
DBUS_DISPLAY_ERROR,
|
||||
DBUS_DISPLAY_ERROR_FAILED,
|
||||
"Couldn't create socket: %s", emsg);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
dbus_console_register_listener(DBusDisplayConsole *ddc,
|
||||
GDBusMethodInvocation *invocation,
|
||||
#ifdef G_OS_UNIX
|
||||
GUnixFDList *fd_list,
|
||||
#endif
|
||||
GVariant *arg_listener)
|
||||
{
|
||||
const char *sender = g_dbus_method_invocation_get_sender(invocation);
|
||||
|
@ -237,6 +271,11 @@ dbus_console_register_listener(DBusDisplayConsole *ddc,
|
|||
return DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
|
||||
#ifdef G_OS_WIN32
|
||||
if (!dbus_win32_import_socket(invocation, arg_listener, &fd)) {
|
||||
return DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
#else
|
||||
fd = g_unix_fd_list_get(fd_list, g_variant_get_handle(arg_listener), &err);
|
||||
if (err) {
|
||||
g_dbus_method_invocation_return_error(
|
||||
|
@ -246,6 +285,7 @@ dbus_console_register_listener(DBusDisplayConsole *ddc,
|
|||
"Couldn't get peer fd: %s", err->message);
|
||||
return DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
socket = g_socket_new_from_fd(fd, &err);
|
||||
if (err) {
|
||||
|
@ -254,13 +294,21 @@ dbus_console_register_listener(DBusDisplayConsole *ddc,
|
|||
DBUS_DISPLAY_ERROR,
|
||||
DBUS_DISPLAY_ERROR_FAILED,
|
||||
"Couldn't make a socket: %s", err->message);
|
||||
#ifdef G_OS_WIN32
|
||||
closesocket(fd);
|
||||
#else
|
||||
close(fd);
|
||||
#endif
|
||||
return DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
socket_conn = g_socket_connection_factory_create_connection(socket);
|
||||
|
||||
qemu_dbus_display1_console_complete_register_listener(
|
||||
ddc->iface, invocation, NULL);
|
||||
ddc->iface, invocation
|
||||
#ifdef G_OS_UNIX
|
||||
, NULL
|
||||
#endif
|
||||
);
|
||||
|
||||
listener_conn = g_dbus_connection_new_sync(
|
||||
G_IO_STREAM(socket_conn),
|
||||
|
@ -287,7 +335,6 @@ dbus_console_register_listener(DBusDisplayConsole *ddc,
|
|||
trace_dbus_registered_listener(sender);
|
||||
return DBUS_METHOD_INVOCATION_HANDLED;
|
||||
}
|
||||
#endif
|
||||
|
||||
static gboolean
|
||||
dbus_kbd_press(DBusDisplayConsole *ddc,
|
||||
|
@ -516,10 +563,8 @@ dbus_display_console_new(DBusDisplay *display, QemuConsole *con)
|
|||
"device-address", device_addr,
|
||||
NULL);
|
||||
g_object_connect(ddc->iface,
|
||||
#ifdef G_OS_UNIX
|
||||
"swapped-signal::handle-register-listener",
|
||||
dbus_console_register_listener, ddc,
|
||||
#endif
|
||||
"swapped-signal::handle-set-uiinfo",
|
||||
dbus_console_set_ui_info, ddc,
|
||||
NULL);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue