{"id":1571488,"url":"http://patchwork.ozlabs.org/api/patches/1571488/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/patch/20211221065855.142578-27-marcandre.lureau@redhat.com/","project":{"id":14,"url":"http://patchwork.ozlabs.org/api/projects/14/?format=json","name":"QEMU Development","link_name":"qemu-devel","list_id":"qemu-devel.nongnu.org","list_email":"qemu-devel@nongnu.org","web_url":"","scm_url":"","webscm_url":"","list_archive_url":"","list_archive_url_format":"","commit_url_format":""},"msgid":"<20211221065855.142578-27-marcandre.lureau@redhat.com>","list_archive_url":null,"date":"2021-12-21T06:58:45","name":"[PULL,v2,26/36] ui/dbus: add p2p=on/off option","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"8c67cd90ccea1624ce61ae4889607c0eb77f98d0","submitter":{"id":66774,"url":"http://patchwork.ozlabs.org/api/people/66774/?format=json","name":"Marc-André Lureau","email":"marcandre.lureau@redhat.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/qemu-devel/patch/20211221065855.142578-27-marcandre.lureau@redhat.com/mbox/","series":[{"id":277865,"url":"http://patchwork.ozlabs.org/api/series/277865/?format=json","web_url":"http://patchwork.ozlabs.org/project/qemu-devel/list/?series=277865","date":"2021-12-21T06:58:19","name":"[PULL,v2,01/36] ui/vdagent: add CHECK_SPICE_PROTOCOL_VERSION","version":2,"mbox":"http://patchwork.ozlabs.org/series/277865/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/1571488/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/1571488/checks/","tags":{},"related":[],"headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@bilbo.ozlabs.org","Authentication-Results":["bilbo.ozlabs.org;\n\tdkim=pass (1024-bit key;\n unprotected) header.d=redhat.com header.i=@redhat.com header.a=rsa-sha256\n header.s=mimecast20190719 header.b=VTMb80UK;\n\tdkim-atps=neutral","ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=nongnu.org\n (client-ip=209.51.188.17; helo=lists.gnu.org;\n envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n receiver=<UNKNOWN>)","relay.mimecast.com;\n auth=pass smtp.auth=CUSA124A263 smtp.mailfrom=marcandre.lureau@redhat.com"],"Received":["from lists.gnu.org (lists.gnu.org [209.51.188.17])\n\t(using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits))\n\t(No client certificate requested)\n\tby bilbo.ozlabs.org (Postfix) with ESMTPS id 4JJ7dn0FGWz9s3q\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 21 Dec 2021 18:39:57 +1100 (AEDT)","from localhost ([::1]:46474 helo=lists1p.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.90_1)\n\t(envelope-from <qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>)\n\tid 1mzZkY-0003Ps-P6\n\tfor incoming@patchwork.ozlabs.org; Tue, 21 Dec 2021 02:39:54 -0500","from eggs.gnu.org ([209.51.188.92]:59090)\n by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <marcandre.lureau@redhat.com>)\n id 1mzZEW-0001S2-FG\n for qemu-devel@nongnu.org; Tue, 21 Dec 2021 02:06:48 -0500","from us-smtp-delivery-124.mimecast.com ([170.10.129.124]:39115)\n by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256)\n (Exim 4.90_1) (envelope-from <marcandre.lureau@redhat.com>)\n id 1mzZET-0002Qs-Uq\n for qemu-devel@nongnu.org; Tue, 21 Dec 2021 02:06:48 -0500","from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com\n [209.132.183.4]) by relay.mimecast.com with ESMTP with STARTTLS\n (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id\n us-mta-399-zD4elxu7Pp6MtVR8DjtirA-1; Tue, 21 Dec 2021 02:06:41 -0500","from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com\n [10.5.11.11])\n (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits))\n (No client certificate requested)\n by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 7DC3B1853020;\n Tue, 21 Dec 2021 07:06:40 +0000 (UTC)","from localhost (unknown [10.39.208.37])\n by smtp.corp.redhat.com (Postfix) with ESMTP id 6E1CA7EA32;\n Tue, 21 Dec 2021 07:06:30 +0000 (UTC)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com;\n s=mimecast20190719; t=1640070404;\n h=from:from:reply-to:subject:subject:date:date:message-id:message-id:\n to:to:cc:cc:mime-version:mime-version:content-type:content-type:\n content-transfer-encoding:content-transfer-encoding:\n in-reply-to:in-reply-to:references:references;\n bh=IHM1osYo3oJvMNI6G05bmm0qANxq+mU1JiUaImCEw8U=;\n b=VTMb80UKNo43UcQ3XZrJr/+26Gg1hMgrZoONymjI4ZvCLbv8v3/65OJs+Y0uBY3rQ4TkCu\n 7OAy3SGlTzjgqa85Hs+Um9BU+e++tJCR6ERs3xN7RDvr4uRU8P9WaJQ6tSeuvEfNLSdCDh\n dfzXOsoKfb+TyRhlbjjT1guQKgCpJ4g=","X-MC-Unique":"zD4elxu7Pp6MtVR8DjtirA-1","From":"marcandre.lureau@redhat.com","To":"qemu-devel@nongnu.org","Subject":"[PULL v2 26/36] ui/dbus: add p2p=on/off option","Date":"Tue, 21 Dec 2021 10:58:45 +0400","Message-Id":"<20211221065855.142578-27-marcandre.lureau@redhat.com>","In-Reply-To":"<20211221065855.142578-1-marcandre.lureau@redhat.com>","References":"<20211221065855.142578-1-marcandre.lureau@redhat.com>","MIME-Version":"1.0","X-Scanned-By":"MIMEDefang 2.79 on 10.5.11.11","X-Mimecast-Spam-Score":"0","X-Mimecast-Originator":"redhat.com","Content-Type":"text/plain; charset=UTF-8","Content-Transfer-Encoding":"8bit","Received-SPF":"pass client-ip=170.10.129.124;\n envelope-from=marcandre.lureau@redhat.com;\n helo=us-smtp-delivery-124.mimecast.com","X-Spam_score_int":"-29","X-Spam_score":"-3.0","X-Spam_bar":"---","X-Spam_report":"(-3.0 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-0.203,\n DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1,\n RCVD_IN_DNSWL_LOW=-0.7, RCVD_IN_MSPIKE_H3=0.001, RCVD_IN_MSPIKE_WL=0.001,\n SPF_HELO_NONE=0.001, SPF_PASS=-0.001 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":"<qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<https://lists.nongnu.org/archive/html/qemu-devel>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n <mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Cc":"peter.maydell@linaro.org, richard.henderson@linaro.org, =?utf-8?q?Marc-A?=\n\t=?utf-8?q?ndr=C3=A9_Lureau?= <marcandre.lureau@redhat.com>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"\"Qemu-devel\"\n <qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>"},"content":"From: Marc-André Lureau <marcandre.lureau@redhat.com>\n\nAdd an option to use direct connections instead of via the bus. Clients\nare accepted with QMP add_client.\n\nThis allows to provide the D-Bus display without a bus. It also\nsimplifies the testing setup (some CI have issues to setup a D-Bus bus\nin a container).\n\nSigned-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>\nAcked-by: Gerd Hoffmann <kraxel@redhat.com>\n---\n qapi/misc.json            |   4 +-\n qapi/ui.json              |   6 ++-\n include/qemu/cutils.h     |   5 ++\n include/ui/dbus-display.h |  17 ++++++\n include/ui/dbus-module.h  |  11 ++++\n ui/dbus.h                 |   2 +\n monitor/qmp-cmds.c        |  13 +++++\n ui/dbus-console.c         |   2 +-\n ui/dbus-listener.c        |   2 +-\n ui/dbus-module.c          |  35 ++++++++++++\n ui/dbus.c                 | 109 ++++++++++++++++++++++++++++++++++++--\n qemu-options.hx           |   6 ++-\n ui/meson.build            |   3 ++\n 13 files changed, 203 insertions(+), 12 deletions(-)\n create mode 100644 include/ui/dbus-display.h\n create mode 100644 include/ui/dbus-module.h\n create mode 100644 ui/dbus-module.c","diff":"diff --git a/qapi/misc.json b/qapi/misc.json\nindex 358548abe1ad..e8054f415b21 100644\n--- a/qapi/misc.json\n+++ b/qapi/misc.json\n@@ -14,8 +14,8 @@\n # Allow client connections for VNC, Spice and socket based\n # character devices to be passed in to QEMU via SCM_RIGHTS.\n #\n-# @protocol: protocol name. Valid names are \"vnc\", \"spice\" or the\n-#            name of a character device (eg. from -chardev id=XXXX)\n+# @protocol: protocol name. Valid names are \"vnc\", \"spice\", \"@dbus-display\" or\n+#            the name of a character device (eg. from -chardev id=XXXX)\n #\n # @fdname: file descriptor name previously passed via 'getfd' command\n #\ndiff --git a/qapi/ui.json b/qapi/ui.json\nindex 80855328b1d4..d435e9472264 100644\n--- a/qapi/ui.json\n+++ b/qapi/ui.json\n@@ -1131,12 +1131,16 @@\n # @rendernode: Which DRM render node should be used. Default is the first\n #              available node on the host.\n #\n+# @p2p: Whether to use peer-to-peer connections (accepted through\n+#       ``add_client``).\n+#\n # Since: 7.0\n #\n ##\n { 'struct'  : 'DisplayDBus',\n   'data'    : { '*rendernode' : 'str',\n-                '*addr': 'str' } }\n+                '*addr': 'str',\n+                '*p2p': 'bool' } }\n \n  ##\n  # @DisplayGLMode:\ndiff --git a/include/qemu/cutils.h b/include/qemu/cutils.h\nindex 986ed8e15f41..320543950c4c 100644\n--- a/include/qemu/cutils.h\n+++ b/include/qemu/cutils.h\n@@ -209,4 +209,9 @@ int qemu_pstrcmp0(const char **str1, const char **str2);\n  */\n char *get_relocated_path(const char *dir);\n \n+static inline const char *yes_no(bool b)\n+{\n+     return b ? \"yes\" : \"no\";\n+}\n+\n #endif\ndiff --git a/include/ui/dbus-display.h b/include/ui/dbus-display.h\nnew file mode 100644\nindex 000000000000..88f153c2371d\n--- /dev/null\n+++ b/include/ui/dbus-display.h\n@@ -0,0 +1,17 @@\n+#ifndef DBUS_DISPLAY_H_\n+#define DBUS_DISPLAY_H_\n+\n+#include \"qapi/error.h\"\n+#include \"ui/dbus-module.h\"\n+\n+static inline bool qemu_using_dbus_display(Error **errp)\n+{\n+    if (!using_dbus_display) {\n+        error_set(errp, ERROR_CLASS_DEVICE_NOT_ACTIVE,\n+                  \"D-Bus display is not in use\");\n+        return false;\n+    }\n+    return true;\n+}\n+\n+#endif /* DBUS_DISPLAY_H_ */\ndiff --git a/include/ui/dbus-module.h b/include/ui/dbus-module.h\nnew file mode 100644\nindex 000000000000..ace4a17a5c25\n--- /dev/null\n+++ b/include/ui/dbus-module.h\n@@ -0,0 +1,11 @@\n+#ifndef DBUS_MODULE_H_\n+#define DBUS_MODULE_H_\n+\n+struct QemuDBusDisplayOps {\n+    bool (*add_client)(int csock, Error **errp);\n+};\n+\n+extern int using_dbus_display;\n+extern struct QemuDBusDisplayOps qemu_dbus_display;\n+\n+#endif /* DBUS_MODULE_H_*/\ndiff --git a/ui/dbus.h b/ui/dbus.h\nindex d3c9598dd133..4698d324632e 100644\n--- a/ui/dbus.h\n+++ b/ui/dbus.h\n@@ -34,6 +34,7 @@ struct DBusDisplay {\n     Object parent;\n \n     DisplayGLMode gl_mode;\n+    bool p2p;\n     char *dbus_addr;\n     DisplayGLCtx glctx;\n \n@@ -41,6 +42,7 @@ struct DBusDisplay {\n     GDBusObjectManagerServer *server;\n     QemuDBusDisplay1VM *iface;\n     GPtrArray *consoles;\n+    GCancellable *add_client_cancellable;\n };\n \n #define TYPE_DBUS_DISPLAY \"dbus-display\"\ndiff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c\nindex 343353e27a7a..14e3beeaafcf 100644\n--- a/monitor/qmp-cmds.c\n+++ b/monitor/qmp-cmds.c\n@@ -24,6 +24,7 @@\n #include \"chardev/char.h\"\n #include \"ui/qemu-spice.h\"\n #include \"ui/console.h\"\n+#include \"ui/dbus-display.h\"\n #include \"sysemu/kvm.h\"\n #include \"sysemu/runstate.h\"\n #include \"sysemu/runstate-action.h\"\n@@ -285,6 +286,18 @@ void qmp_add_client(const char *protocol, const char *fdname,\n         skipauth = has_skipauth ? skipauth : false;\n         vnc_display_add_client(NULL, fd, skipauth);\n         return;\n+#endif\n+#ifdef CONFIG_DBUS_DISPLAY\n+    } else if (strcmp(protocol, \"@dbus-display\") == 0) {\n+        if (!qemu_using_dbus_display(errp)) {\n+            close(fd);\n+            return;\n+        }\n+        if (!qemu_dbus_display.add_client(fd, errp)) {\n+            close(fd);\n+            return;\n+        }\n+        return;\n #endif\n     } else if ((s = qemu_chr_find(protocol)) != NULL) {\n         if (qemu_chr_add_client(s, fd) < 0) {\ndiff --git a/ui/dbus-console.c b/ui/dbus-console.c\nindex 1ccf638c1061..e062f721d761 100644\n--- a/ui/dbus-console.c\n+++ b/ui/dbus-console.c\n@@ -219,7 +219,7 @@ dbus_console_register_listener(DBusDisplayConsole *ddc,\n     DBusDisplayListener *listener;\n     int fd;\n \n-    if (g_hash_table_contains(ddc->listeners, sender)) {\n+    if (sender && g_hash_table_contains(ddc->listeners, sender)) {\n         g_dbus_method_invocation_return_error(\n             invocation,\n             DBUS_DISPLAY_ERROR,\ndiff --git a/ui/dbus-listener.c b/ui/dbus-listener.c\nindex 20094fc18abe..81c119b13a2c 100644\n--- a/ui/dbus-listener.c\n+++ b/ui/dbus-listener.c\n@@ -440,7 +440,7 @@ dbus_display_listener_init(DBusDisplayListener *ddl)\n const char *\n dbus_display_listener_get_bus_name(DBusDisplayListener *ddl)\n {\n-    return ddl->bus_name;\n+    return ddl->bus_name ?: \"p2p\";\n }\n \n DBusDisplayConsole *\ndiff --git a/ui/dbus-module.c b/ui/dbus-module.c\nnew file mode 100644\nindex 000000000000..c8771fe48c7d\n--- /dev/null\n+++ b/ui/dbus-module.c\n@@ -0,0 +1,35 @@\n+/*\n+ * D-Bus module support.\n+ *\n+ * Copyright (C) 2021 Red Hat, Inc.\n+ *\n+ * This program is free software; you can redistribute it and/or\n+ * modify it under the terms of the GNU General Public License as\n+ * published by the Free Software Foundation; either version 2 or\n+ * (at your option) version 3 of the License.\n+ *\n+ * This program is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+ * GNU General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU General Public License\n+ * along with this program; if not, see <http://www.gnu.org/licenses/>.\n+ */\n+\n+#include \"qemu/osdep.h\"\n+#include \"qapi/error.h\"\n+#include \"ui/dbus-module.h\"\n+\n+int using_dbus_display;\n+\n+static bool\n+qemu_dbus_display_add_client(int csock, Error **errp)\n+{\n+    error_setg(errp, \"D-Bus display isn't enabled\");\n+    return false;\n+}\n+\n+struct QemuDBusDisplayOps qemu_dbus_display = {\n+    .add_client = qemu_dbus_display_add_client,\n+};\ndiff --git a/ui/dbus.c b/ui/dbus.c\nindex 12da8ffe31e0..847a66782116 100644\n--- a/ui/dbus.c\n+++ b/ui/dbus.c\n@@ -22,10 +22,12 @@\n  * THE SOFTWARE.\n  */\n #include \"qemu/osdep.h\"\n+#include \"qemu/cutils.h\"\n #include \"qemu/dbus.h\"\n #include \"qemu/option.h\"\n #include \"qom/object_interfaces.h\"\n #include \"sysemu/sysemu.h\"\n+#include \"ui/dbus-module.h\"\n #include \"ui/egl-helpers.h\"\n #include \"ui/egl-context.h\"\n #include \"qapi/error.h\"\n@@ -33,6 +35,8 @@\n \n #include \"dbus.h\"\n \n+static DBusDisplay *dbus_display;\n+\n static QEMUGLContext dbus_create_context(DisplayGLCtx *dgc,\n                                          QEMUGLParams *params)\n {\n@@ -73,9 +77,14 @@ dbus_display_finalize(Object *o)\n \n     g_clear_object(&dd->server);\n     g_clear_pointer(&dd->consoles, g_ptr_array_unref);\n+    if (dd->add_client_cancellable) {\n+        g_cancellable_cancel(dd->add_client_cancellable);\n+    }\n+    g_clear_object(&dd->add_client_cancellable);\n     g_clear_object(&dd->bus);\n     g_clear_object(&dd->iface);\n     g_free(dd->dbus_addr);\n+    dbus_display = NULL;\n }\n \n static bool\n@@ -115,7 +124,10 @@ dbus_display_complete(UserCreatable *uc, Error **errp)\n         return;\n     }\n \n-    if (dd->dbus_addr && *dd->dbus_addr) {\n+    if (dd->p2p) {\n+        /* wait for dbus_display_add_client() */\n+        dbus_display = dd;\n+    } else if (dd->dbus_addr && *dd->dbus_addr) {\n         dd->bus = g_dbus_connection_new_for_address_sync(dd->dbus_addr,\n                         G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |\n                         G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,\n@@ -151,10 +163,85 @@ dbus_display_complete(UserCreatable *uc, Error **errp)\n                  \"console-ids\", console_ids,\n                  NULL);\n \n-    g_dbus_object_manager_server_set_connection(dd->server, dd->bus);\n-    g_bus_own_name_on_connection(dd->bus, \"org.qemu\",\n-                                 G_BUS_NAME_OWNER_FLAGS_NONE,\n-                                 NULL, NULL, NULL, NULL);\n+    if (dd->bus) {\n+        g_dbus_object_manager_server_set_connection(dd->server, dd->bus);\n+        g_bus_own_name_on_connection(dd->bus, \"org.qemu\",\n+                                     G_BUS_NAME_OWNER_FLAGS_NONE,\n+                                     NULL, NULL, NULL, NULL);\n+    }\n+}\n+\n+static void\n+dbus_display_add_client_ready(GObject *source_object,\n+                              GAsyncResult *res,\n+                              gpointer user_data)\n+{\n+    g_autoptr(GError) err = NULL;\n+    g_autoptr(GDBusConnection) conn = NULL;\n+\n+    g_clear_object(&dbus_display->add_client_cancellable);\n+\n+    conn = g_dbus_connection_new_finish(res, &err);\n+    if (!conn) {\n+        error_printf(\"Failed to accept D-Bus client: %s\", err->message);\n+    }\n+\n+    g_dbus_object_manager_server_set_connection(dbus_display->server, conn);\n+}\n+\n+\n+static bool\n+dbus_display_add_client(int csock, Error **errp)\n+{\n+    g_autoptr(GError) err = NULL;\n+    g_autoptr(GSocket) socket = NULL;\n+    g_autoptr(GSocketConnection) conn = NULL;\n+    g_autofree char *guid = g_dbus_generate_guid();\n+\n+    if (!dbus_display) {\n+        error_setg(errp, \"p2p connections not accepted in bus mode\");\n+        return false;\n+    }\n+\n+    if (dbus_display->add_client_cancellable) {\n+        g_cancellable_cancel(dbus_display->add_client_cancellable);\n+    }\n+\n+    socket = g_socket_new_from_fd(csock, &err);\n+    if (!socket) {\n+        error_setg(errp, \"Failed to setup D-Bus socket: %s\", err->message);\n+        return false;\n+    }\n+\n+    conn = g_socket_connection_factory_create_connection(socket);\n+\n+    dbus_display->add_client_cancellable = g_cancellable_new();\n+\n+    g_dbus_connection_new(G_IO_STREAM(conn),\n+                          guid,\n+                          G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER,\n+                          NULL,\n+                          dbus_display->add_client_cancellable,\n+                          dbus_display_add_client_ready,\n+                          NULL);\n+\n+    return true;\n+}\n+\n+static bool\n+get_dbus_p2p(Object *o, Error **errp)\n+{\n+    DBusDisplay *dd = DBUS_DISPLAY(o);\n+\n+    return dd->p2p;\n+}\n+\n+static void\n+set_dbus_p2p(Object *o, bool p2p, Error **errp)\n+{\n+    DBusDisplay *dd = DBUS_DISPLAY(o);\n+\n+    dd->p2p = p2p;\n }\n \n static char *\n@@ -196,6 +283,7 @@ dbus_display_class_init(ObjectClass *oc, void *data)\n     UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);\n \n     ucc->complete = dbus_display_complete;\n+    object_class_property_add_bool(oc, \"p2p\", get_dbus_p2p, set_dbus_p2p);\n     object_class_property_add_str(oc, \"addr\", get_dbus_addr, set_dbus_addr);\n     object_class_property_add_enum(oc, \"gl-mode\",\n                                    \"DisplayGLMode\", &DisplayGLMode_lookup,\n@@ -222,11 +310,19 @@ dbus_init(DisplayState *ds, DisplayOptions *opts)\n {\n     DisplayGLMode mode = opts->has_gl ? opts->gl : DISPLAYGL_MODE_OFF;\n \n+    if (opts->u.dbus.addr && opts->u.dbus.p2p) {\n+        error_report(\"dbus: can't accept both addr=X and p2p=yes options\");\n+        exit(1);\n+    }\n+\n+    using_dbus_display = 1;\n+\n     object_new_with_props(TYPE_DBUS_DISPLAY,\n                           object_get_objects_root(),\n                           \"dbus-display\", &error_fatal,\n                           \"addr\", opts->u.dbus.addr ?: \"\",\n                           \"gl-mode\", DisplayGLMode_str(mode),\n+                          \"p2p\", yes_no(opts->u.dbus.p2p),\n                           NULL);\n }\n \n@@ -251,6 +347,9 @@ static QemuDisplay qemu_display_dbus = {\n \n static void register_dbus(void)\n {\n+    qemu_dbus_display = (struct QemuDBusDisplayOps) {\n+        .add_client = dbus_display_add_client,\n+    };\n     type_register_static(&dbus_display_info);\n     qemu_display_register(&qemu_display_dbus);\n }\ndiff --git a/qemu-options.hx b/qemu-options.hx\nindex 38983a919b12..977e0873a12c 100644\n--- a/qemu-options.hx\n+++ b/qemu-options.hx\n@@ -1901,8 +1901,10 @@ SRST\n \n         ``addr=<dbusaddr>`` : D-Bus bus address to connect to.\n \n-        ``gl=on|off|core|es`` : Use OpenGL for rendering (the D-interface will\n-        share framebuffers with DMABUF file descriptors).\n+        ``p2p=yes|no`` : Use peer-to-peer connection, accepted via QMP ``add_client``.\n+\n+        ``gl=on|off|core|es`` : Use OpenGL for rendering (the D-Bus interface\n+        will share framebuffers with DMABUF file descriptors).\n \n     ``sdl``\n         Display video output via SDL (usually in a separate graphics\ndiff --git a/ui/meson.build b/ui/meson.build\nindex 6270aa768b6a..80f21704ada6 100644\n--- a/ui/meson.build\n+++ b/ui/meson.build\n@@ -14,6 +14,9 @@ softmmu_ss.add(files(\n   'qemu-pixman.c',\n   'util.c',\n ))\n+if dbus_display\n+  softmmu_ss.add(files('dbus-module.c'))\n+endif\n softmmu_ss.add([spice_headers, files('spice-module.c')])\n softmmu_ss.add(when: spice_protocol, if_true: files('vdagent.c'))\n \n","prefixes":["PULL","v2","26/36"]}