From nobody Tue Feb 10 20:47:47 2026 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1686052743; cv=none; d=zohomail.com; s=zohoarc; b=RskixnOVSDga6i68WsVeH+TMi/Mgkcijj/hYV3PLFjRkiVVghbdkIuinJoOO/r0BIa3FDVHGKtmJYRfCNbq+f6WLPSO2JUj76ahYQn9WYdBiqRu7pNtdwtmS2mycx5jMUxmnYUn2v3PjlNjhSoGjsN4Uk8zbIIon2xOF+7n37sI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1686052743; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=CZek60IdUXVopL0fOifxwaQzKtonox4OSfDDLjj9SuE=; b=bF3cuDMoy9MCQq0/L4FoW2JkLy9+MvU00XkJj2F8hkhrVOMeLpgCBXBBCm2WWlV6uFJm7wM3d1UDNkK8qkyuPT0VLsCwejm8yRgy5ylxf8J1t9qbARj6LZ/GwBpBYjdNsG/yMqeeMdhgE6L73bMdb6e8VCj4qY8rx56WieBS6Yg= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=pass header.from= (p=none dis=none) Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 168605274334386.66859273498142; Tue, 6 Jun 2023 04:59:03 -0700 (PDT) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1q6VJZ-00009C-FF; Tue, 06 Jun 2023 07:57:29 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1q6VJX-00008i-C7 for qemu-devel@nongnu.org; Tue, 06 Jun 2023 07:57:27 -0400 Received: from us-smtp-delivery-124.mimecast.com ([170.10.129.124]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1q6VJV-0005jl-2V for qemu-devel@nongnu.org; Tue, 06 Jun 2023 07:57:27 -0400 Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-385-6VWqlNOjPyWp5EYwKfQJEg-1; Tue, 06 Jun 2023 07:57:23 -0400 Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.rdu2.redhat.com [10.11.54.1]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 0FFF285A5A8; Tue, 6 Jun 2023 11:57:23 +0000 (UTC) Received: from localhost (unknown [10.39.208.7]) by smtp.corp.redhat.com (Postfix) with ESMTP id 6845340CFD47; Tue, 6 Jun 2023 11:57:21 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1686052644; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=CZek60IdUXVopL0fOifxwaQzKtonox4OSfDDLjj9SuE=; b=XFVdG8OeYQkK8Rb439AOmDfNsbY2lrTzzmus9j48vwYIhUUbbiWmSJ98X4p4MuERtZv0w/ 7r4km/gwSDQxQQ8yMow/j82ldbBCZo/jSy7dU6UN02VbJIlu1B/kfNw7vdpMY2uOZqMWzd yEFgOLso0h1CQebBdxAlu/84A1KWDf4= X-MC-Unique: 6VWqlNOjPyWp5EYwKfQJEg-1 From: marcandre.lureau@redhat.com To: qemu-devel@nongnu.org Cc: Gerd Hoffmann , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Paolo Bonzini , =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , Thomas Huth , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= Subject: [PATCH 05/21] ui/dbus: win32 support Date: Tue, 6 Jun 2023 15:56:42 +0400 Message-Id: <20230606115658.677673-6-marcandre.lureau@redhat.com> In-Reply-To: <20230606115658.677673-1-marcandre.lureau@redhat.com> References: <20230606115658.677673-1-marcandre.lureau@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable X-Scanned-By: MIMEDefang 3.1 on 10.11.54.1 Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=170.10.129.124; envelope-from=marcandre.lureau@redhat.com; helo=us-smtp-delivery-124.mimecast.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.001, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: qemu-devel-bounces+importer=patchew.org@nongnu.org X-ZohoMail-DKIM: pass (identity @redhat.com) X-ZM-MESSAGEID: 1686052744421100004 From: Marc-Andr=C3=A9 Lureau 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=C3=A9 Lureau --- meson.build | 4 +-- ui/dbus.h | 6 +++++ audio/dbusaudio.c | 44 +++++++++++++++++++++++++++------ ui/dbus-chardev.c | 22 +++++++++++++---- ui/dbus-console.c | 59 ++++++++++++++++++++++++++++++++++++++------ ui/dbus-display1.xml | 28 +++++++++++++++++++++ ui/meson.build | 9 ++++++- 7 files changed, 149 insertions(+), 23 deletions(-) diff --git a/meson.build b/meson.build index a61d3e9b06..ce7138a69f 100644 --- a/meson.build +++ b/meson.build @@ -838,6 +838,8 @@ if gdbus_codegen.found() and get_option('cfi') gdbus_codegen_error =3D '@0@ uses gdbus-codegen, which does not support = control flow integrity' endif =20 +xml_pp =3D find_program('scripts/xml-preprocess.py') + lttng =3D not_found if 'ust' in get_option('trace_backends') lttng =3D dependency('lttng-ust', required: true, version: '>=3D 2.1', @@ -2008,8 +2010,6 @@ dbus_display =3D get_option('dbus_display') \ error_message: '-display dbus requires glib>=3D2.64') \ .require(gdbus_codegen.found(), error_message: gdbus_codegen_error.format('-display dbus')) \ - .require(targetos !=3D 'windows', - error_message: '-display dbus is not available on Windows') \ .allowed() =20 have_virtfs =3D get_option('virtfs') \ diff --git a/ui/dbus.h b/ui/dbus.h index 9c149e7b41..1e8c24a48e 100644 --- a/ui/dbus.h +++ b/ui/dbus.h @@ -62,6 +62,12 @@ struct DBusDisplay { Notifier notifier; }; =20 +#ifdef WIN32 +bool +dbus_win32_import_socket(GDBusMethodInvocation *invocation, + GVariant *arg_listener, int *socket); +#endif + #define TYPE_DBUS_DISPLAY "dbus-display" OBJECT_DECLARE_SIMPLE_TYPE(DBusDisplay, DBUS_DISPLAY) =20 diff --git a/audio/dbusaudio.c b/audio/dbusaudio.c index de59467d9e..7a11fbfb42 100644 --- a/audio/dbusaudio.c +++ b/audio/dbusaudio.c @@ -33,6 +33,7 @@ #include #endif =20 +#include "ui/dbus.h" #include "ui/dbus-display1.h" =20 #define AUDIO_CAP "dbus" @@ -422,7 +423,6 @@ dbus_audio_fini(void *opaque) g_free(da); } =20 -#ifdef G_OS_UNIX static void listener_out_vanished_cb(GDBusConnection *connection, gboolean remote_peer_vanished, @@ -448,7 +448,9 @@ listener_in_vanished_cb(GDBusConnection *connection, static gboolean dbus_audio_register_listener(AudioState *s, GDBusMethodInvocation *invocation, +#ifdef G_OS_UNIX GUnixFDList *fd_list, +#endif GVariant *arg_listener, bool out) { @@ -475,6 +477,11 @@ dbus_audio_register_listener(AudioState *s, return DBUS_METHOD_INVOCATION_HANDLED; } =20 +#ifdef G_OS_WIN32 + if (!dbus_win32_import_socket(invocation, arg_listener, &fd)) { + return DBUS_METHOD_INVOCATION_HANDLED; + } +#else fd =3D g_unix_fd_list_get(fd_list, g_variant_get_handle(arg_listener),= &err); if (err) { g_dbus_method_invocation_return_error(invocation, @@ -484,6 +491,7 @@ dbus_audio_register_listener(AudioState *s, err->message); return DBUS_METHOD_INVOCATION_HANDLED; } +#endif =20 socket =3D g_socket_new_from_fd(fd, &err); if (err) { @@ -492,15 +500,28 @@ dbus_audio_register_listener(AudioState *s, 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 =3D g_socket_connection_factory_create_connection(socket); if (out) { qemu_dbus_display1_audio_complete_register_out_listener( - da->iface, invocation, NULL); + da->iface, invocation +#ifdef G_OS_UNIX + , NULL +#endif + ); } else { qemu_dbus_display1_audio_complete_register_in_listener( - da->iface, invocation, NULL); + da->iface, invocation +#ifdef G_OS_UNIX + , NULL +#endif + ); } =20 listener_conn =3D @@ -578,24 +599,33 @@ dbus_audio_register_listener(AudioState *s, static gboolean dbus_audio_register_out_listener(AudioState *s, GDBusMethodInvocation *invocation, +#ifdef G_OS_UNIX GUnixFDList *fd_list, +#endif GVariant *arg_listener) { return dbus_audio_register_listener(s, invocation, - fd_list, arg_listener, true); +#ifdef G_OS_UNIX + fd_list, +#endif + arg_listener, true); =20 } =20 static gboolean dbus_audio_register_in_listener(AudioState *s, GDBusMethodInvocation *invocation, +#ifdef G_OS_UNIX GUnixFDList *fd_list, +#endif GVariant *arg_listener) { return dbus_audio_register_listener(s, invocation, - fd_list, arg_listener, false); -} +#ifdef G_OS_UNIX + fd_list, #endif + arg_listener, false); +} =20 static void dbus_audio_set_server(AudioState *s, GDBusObjectManagerServer *server, boo= l p2p) @@ -610,14 +640,12 @@ dbus_audio_set_server(AudioState *s, GDBusObjectManag= erServer *server, bool p2p) =20 da->audio =3D g_dbus_object_skeleton_new(DBUS_DISPLAY1_AUDIO_PATH); da->iface =3D qemu_dbus_display1_audio_skeleton_new(); -#ifdef G_OS_UNIX g_object_connect(da->iface, "swapped-signal::handle-register-in-listener", dbus_audio_register_in_listener, s, "swapped-signal::handle-register-out-listener", dbus_audio_register_out_listener, s, NULL); -#endif =20 g_dbus_object_skeleton_add_interface(G_DBUS_OBJECT_SKELETON(da->audio), G_DBUS_INTERFACE_SKELETON(da->ifa= ce)); diff --git a/ui/dbus-chardev.c b/ui/dbus-chardev.c index 7154d81a9a..1d3a7122a1 100644 --- a/ui/dbus-chardev.c +++ b/ui/dbus-chardev.c @@ -110,18 +110,24 @@ dbus_chardev_init(DBusDisplay *dpy) dbus_display_chardev_foreach, dpy); } =20 -#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 =3D NULL; int fd; =20 +#ifdef G_OS_WIN32 + if (!dbus_win32_import_socket(invocation, arg_stream, &fd)) { + return DBUS_METHOD_INVOCATION_HANDLED; + } +#else fd =3D 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 =20 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; } =20 @@ -145,10 +156,13 @@ dbus_chr_register( "owner", g_dbus_method_invocation_get_sender(invocation), NULL); =20 - 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 =20 static gboolean dbus_chr_send_break( @@ -179,10 +193,8 @@ dbus_chr_open(Chardev *chr, ChardevBackend *backend, dc->iface =3D 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); diff --git a/ui/dbus-console.c b/ui/dbus-console.c index fd50fd3200..f0a060dc81 100644 --- a/ui/dbus-console.c +++ b/ui/dbus-console.c @@ -162,7 +162,6 @@ dbus_display_console_class_init(DBusDisplayConsoleClass= *klass) gobject_class->dispose =3D dbus_display_console_dispose; } =20 -#ifdef G_OS_UNIX static void listener_vanished_cb(DBusDisplayListener *listener) { @@ -174,7 +173,6 @@ listener_vanished_cb(DBusDisplayListener *listener) g_hash_table_remove(ddc->listeners, name); qkbd_state_lift_all_keys(ddc->kbd); } -#endif =20 static gboolean dbus_console_set_ui_info(DBusDisplayConsole *ddc, @@ -208,11 +206,47 @@ dbus_console_set_ui_info(DBusDisplayConsole *ddc, return DBUS_METHOD_INVOCATION_HANDLED; } =20 -#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 =3D (void *)g_variant_get_fixed_array(arg_list= ener, &n, 1); + + if (!info || n !=3D sizeof(*info)) { + g_dbus_method_invocation_return_error( + invocation, + DBUS_DISPLAY_ERROR, + DBUS_DISPLAY_ERROR_FAILED, + "Failed to get socket infos"); + return false; + } + + *socket =3D WSASocketW(FROM_PROTOCOL_INFO, + FROM_PROTOCOL_INFO, + FROM_PROTOCOL_INFO, + info, 0, 0); + if (*socket =3D=3D INVALID_SOCKET) { + g_autofree gchar *emsg =3D 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 =3D g_dbus_method_invocation_get_sender(invocation); @@ -234,6 +268,11 @@ dbus_console_register_listener(DBusDisplayConsole *ddc, return DBUS_METHOD_INVOCATION_HANDLED; } =20 +#ifdef G_OS_WIN32 + if (!dbus_win32_import_socket(invocation, arg_listener, &fd)) { + return DBUS_METHOD_INVOCATION_HANDLED; + } +#else fd =3D g_unix_fd_list_get(fd_list, g_variant_get_handle(arg_listener),= &err); if (err) { g_dbus_method_invocation_return_error( @@ -243,6 +282,7 @@ dbus_console_register_listener(DBusDisplayConsole *ddc, "Couldn't get peer fd: %s", err->message); return DBUS_METHOD_INVOCATION_HANDLED; } +#endif =20 socket =3D g_socket_new_from_fd(fd, &err); if (err) { @@ -251,13 +291,21 @@ dbus_console_register_listener(DBusDisplayConsole *dd= c, 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 =3D g_socket_connection_factory_create_connection(socket); =20 qemu_dbus_display1_console_complete_register_listener( - ddc->iface, invocation, NULL); + ddc->iface, invocation +#ifdef G_OS_UNIX + , NULL +#endif + ); =20 listener_conn =3D g_dbus_connection_new_sync( G_IO_STREAM(socket_conn), @@ -284,7 +332,6 @@ dbus_console_register_listener(DBusDisplayConsole *ddc, trace_dbus_registered_listener(sender); return DBUS_METHOD_INVOCATION_HANDLED; } -#endif =20 static gboolean dbus_kbd_press(DBusDisplayConsole *ddc, @@ -473,10 +520,8 @@ dbus_display_console_new(DBusDisplay *display, QemuCon= sole *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); diff --git a/ui/dbus-display1.xml b/ui/dbus-display1.xml index c3b2293376..80eae363f0 100644 --- a/ui/dbus-display1.xml +++ b/ui/dbus-display1.xml @@ -56,7 +56,13 @@ :dbus:iface:`org.qemu.Display1.Listener` interface. --> + + + + + + =20 + + + + + + + =20 + + + + + + =20 @@ -719,7 +741,13 @@ The current handler, if any, will be replaced. --> + + + + + + =20