[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PULL 26/36] ui/dbus: add p2p=on/off option
From: |
marcandre . lureau |
Subject: |
[PULL 26/36] ui/dbus: add p2p=on/off option |
Date: |
Fri, 17 Dec 2021 18:37:46 +0400 |
From: Marc-André Lureau <marcandre.lureau@redhat.com>
Add an option to use direct connections instead of via the bus. Clients
are accepted with QMP add_client.
This allows to provide the D-Bus display without a bus. It also
simplifies the testing setup (some CI have issues to setup a D-Bus bus
in a container).
Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Acked-by: Gerd Hoffmann <kraxel@redhat.com>
---
qapi/misc.json | 4 +-
qapi/ui.json | 6 ++-
include/qemu/cutils.h | 5 ++
include/ui/dbus-display.h | 17 ++++++
include/ui/dbus-module.h | 11 ++++
ui/dbus.h | 2 +
monitor/qmp-cmds.c | 13 +++++
ui/dbus-console.c | 2 +-
ui/dbus-listener.c | 2 +-
ui/dbus-module.c | 35 ++++++++++++
ui/dbus.c | 109 ++++++++++++++++++++++++++++++++++++--
qemu-options.hx | 6 ++-
ui/meson.build | 3 ++
13 files changed, 203 insertions(+), 12 deletions(-)
create mode 100644 include/ui/dbus-display.h
create mode 100644 include/ui/dbus-module.h
create mode 100644 ui/dbus-module.c
diff --git a/qapi/misc.json b/qapi/misc.json
index 358548abe1ad..e8054f415b21 100644
--- a/qapi/misc.json
+++ b/qapi/misc.json
@@ -14,8 +14,8 @@
# Allow client connections for VNC, Spice and socket based
# character devices to be passed in to QEMU via SCM_RIGHTS.
#
-# @protocol: protocol name. Valid names are "vnc", "spice" or the
-# name of a character device (eg. from -chardev id=XXXX)
+# @protocol: protocol name. Valid names are "vnc", "spice", "@dbus-display" or
+# the name of a character device (eg. from -chardev id=XXXX)
#
# @fdname: file descriptor name previously passed via 'getfd' command
#
diff --git a/qapi/ui.json b/qapi/ui.json
index 5ca604bd901b..f23d012cb810 100644
--- a/qapi/ui.json
+++ b/qapi/ui.json
@@ -1131,12 +1131,16 @@
# @rendernode: Which DRM render node should be used. Default is the first
# available node on the host.
#
+# @p2p: Whether to use peer-to-peer connections (accepted through
+# ``add_client``).
+#
# Since: 6.2
#
##
{ 'struct' : 'DisplayDBus',
'data' : { '*rendernode' : 'str',
- '*addr': 'str' } }
+ '*addr': 'str',
+ '*p2p': 'bool' } }
##
# @DisplayGLMode:
diff --git a/include/qemu/cutils.h b/include/qemu/cutils.h
index 986ed8e15f41..320543950c4c 100644
--- a/include/qemu/cutils.h
+++ b/include/qemu/cutils.h
@@ -209,4 +209,9 @@ int qemu_pstrcmp0(const char **str1, const char **str2);
*/
char *get_relocated_path(const char *dir);
+static inline const char *yes_no(bool b)
+{
+ return b ? "yes" : "no";
+}
+
#endif
diff --git a/include/ui/dbus-display.h b/include/ui/dbus-display.h
new file mode 100644
index 000000000000..88f153c2371d
--- /dev/null
+++ b/include/ui/dbus-display.h
@@ -0,0 +1,17 @@
+#ifndef DBUS_DISPLAY_H_
+#define DBUS_DISPLAY_H_
+
+#include "qapi/error.h"
+#include "ui/dbus-module.h"
+
+static inline bool qemu_using_dbus_display(Error **errp)
+{
+ if (!using_dbus_display) {
+ error_set(errp, ERROR_CLASS_DEVICE_NOT_ACTIVE,
+ "D-Bus display is not in use");
+ return false;
+ }
+ return true;
+}
+
+#endif /* DBUS_DISPLAY_H_ */
diff --git a/include/ui/dbus-module.h b/include/ui/dbus-module.h
new file mode 100644
index 000000000000..ace4a17a5c25
--- /dev/null
+++ b/include/ui/dbus-module.h
@@ -0,0 +1,11 @@
+#ifndef DBUS_MODULE_H_
+#define DBUS_MODULE_H_
+
+struct QemuDBusDisplayOps {
+ bool (*add_client)(int csock, Error **errp);
+};
+
+extern int using_dbus_display;
+extern struct QemuDBusDisplayOps qemu_dbus_display;
+
+#endif /* DBUS_MODULE_H_*/
diff --git a/ui/dbus.h b/ui/dbus.h
index d3c9598dd133..4698d324632e 100644
--- a/ui/dbus.h
+++ b/ui/dbus.h
@@ -34,6 +34,7 @@ struct DBusDisplay {
Object parent;
DisplayGLMode gl_mode;
+ bool p2p;
char *dbus_addr;
DisplayGLCtx glctx;
@@ -41,6 +42,7 @@ struct DBusDisplay {
GDBusObjectManagerServer *server;
QemuDBusDisplay1VM *iface;
GPtrArray *consoles;
+ GCancellable *add_client_cancellable;
};
#define TYPE_DBUS_DISPLAY "dbus-display"
diff --git a/monitor/qmp-cmds.c b/monitor/qmp-cmds.c
index 343353e27a7a..14e3beeaafcf 100644
--- a/monitor/qmp-cmds.c
+++ b/monitor/qmp-cmds.c
@@ -24,6 +24,7 @@
#include "chardev/char.h"
#include "ui/qemu-spice.h"
#include "ui/console.h"
+#include "ui/dbus-display.h"
#include "sysemu/kvm.h"
#include "sysemu/runstate.h"
#include "sysemu/runstate-action.h"
@@ -285,6 +286,18 @@ void qmp_add_client(const char *protocol, const char
*fdname,
skipauth = has_skipauth ? skipauth : false;
vnc_display_add_client(NULL, fd, skipauth);
return;
+#endif
+#ifdef CONFIG_DBUS_DISPLAY
+ } else if (strcmp(protocol, "@dbus-display") == 0) {
+ if (!qemu_using_dbus_display(errp)) {
+ close(fd);
+ return;
+ }
+ if (!qemu_dbus_display.add_client(fd, errp)) {
+ close(fd);
+ return;
+ }
+ return;
#endif
} else if ((s = qemu_chr_find(protocol)) != NULL) {
if (qemu_chr_add_client(s, fd) < 0) {
diff --git a/ui/dbus-console.c b/ui/dbus-console.c
index 1ccf638c1061..e062f721d761 100644
--- a/ui/dbus-console.c
+++ b/ui/dbus-console.c
@@ -219,7 +219,7 @@ dbus_console_register_listener(DBusDisplayConsole *ddc,
DBusDisplayListener *listener;
int fd;
- if (g_hash_table_contains(ddc->listeners, sender)) {
+ if (sender && g_hash_table_contains(ddc->listeners, sender)) {
g_dbus_method_invocation_return_error(
invocation,
DBUS_DISPLAY_ERROR,
diff --git a/ui/dbus-listener.c b/ui/dbus-listener.c
index 20094fc18abe..81c119b13a2c 100644
--- a/ui/dbus-listener.c
+++ b/ui/dbus-listener.c
@@ -440,7 +440,7 @@ dbus_display_listener_init(DBusDisplayListener *ddl)
const char *
dbus_display_listener_get_bus_name(DBusDisplayListener *ddl)
{
- return ddl->bus_name;
+ return ddl->bus_name ?: "p2p";
}
DBusDisplayConsole *
diff --git a/ui/dbus-module.c b/ui/dbus-module.c
new file mode 100644
index 000000000000..c8771fe48c7d
--- /dev/null
+++ b/ui/dbus-module.c
@@ -0,0 +1,35 @@
+/*
+ * D-Bus module support.
+ *
+ * Copyright (C) 2021 Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 or
+ * (at your option) version 3 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "qemu/osdep.h"
+#include "qapi/error.h"
+#include "ui/dbus-module.h"
+
+int using_dbus_display;
+
+static bool
+qemu_dbus_display_add_client(int csock, Error **errp)
+{
+ error_setg(errp, "D-Bus display isn't enabled");
+ return false;
+}
+
+struct QemuDBusDisplayOps qemu_dbus_display = {
+ .add_client = qemu_dbus_display_add_client,
+};
diff --git a/ui/dbus.c b/ui/dbus.c
index 12da8ffe31e0..847a66782116 100644
--- a/ui/dbus.c
+++ b/ui/dbus.c
@@ -22,10 +22,12 @@
* THE SOFTWARE.
*/
#include "qemu/osdep.h"
+#include "qemu/cutils.h"
#include "qemu/dbus.h"
#include "qemu/option.h"
#include "qom/object_interfaces.h"
#include "sysemu/sysemu.h"
+#include "ui/dbus-module.h"
#include "ui/egl-helpers.h"
#include "ui/egl-context.h"
#include "qapi/error.h"
@@ -33,6 +35,8 @@
#include "dbus.h"
+static DBusDisplay *dbus_display;
+
static QEMUGLContext dbus_create_context(DisplayGLCtx *dgc,
QEMUGLParams *params)
{
@@ -73,9 +77,14 @@ dbus_display_finalize(Object *o)
g_clear_object(&dd->server);
g_clear_pointer(&dd->consoles, g_ptr_array_unref);
+ if (dd->add_client_cancellable) {
+ g_cancellable_cancel(dd->add_client_cancellable);
+ }
+ g_clear_object(&dd->add_client_cancellable);
g_clear_object(&dd->bus);
g_clear_object(&dd->iface);
g_free(dd->dbus_addr);
+ dbus_display = NULL;
}
static bool
@@ -115,7 +124,10 @@ dbus_display_complete(UserCreatable *uc, Error **errp)
return;
}
- if (dd->dbus_addr && *dd->dbus_addr) {
+ if (dd->p2p) {
+ /* wait for dbus_display_add_client() */
+ dbus_display = dd;
+ } else if (dd->dbus_addr && *dd->dbus_addr) {
dd->bus = g_dbus_connection_new_for_address_sync(dd->dbus_addr,
G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT |
G_DBUS_CONNECTION_FLAGS_MESSAGE_BUS_CONNECTION,
@@ -151,10 +163,85 @@ dbus_display_complete(UserCreatable *uc, Error **errp)
"console-ids", console_ids,
NULL);
- g_dbus_object_manager_server_set_connection(dd->server, dd->bus);
- g_bus_own_name_on_connection(dd->bus, "org.qemu",
- G_BUS_NAME_OWNER_FLAGS_NONE,
- NULL, NULL, NULL, NULL);
+ if (dd->bus) {
+ g_dbus_object_manager_server_set_connection(dd->server, dd->bus);
+ g_bus_own_name_on_connection(dd->bus, "org.qemu",
+ G_BUS_NAME_OWNER_FLAGS_NONE,
+ NULL, NULL, NULL, NULL);
+ }
+}
+
+static void
+dbus_display_add_client_ready(GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ g_autoptr(GError) err = NULL;
+ g_autoptr(GDBusConnection) conn = NULL;
+
+ g_clear_object(&dbus_display->add_client_cancellable);
+
+ conn = g_dbus_connection_new_finish(res, &err);
+ if (!conn) {
+ error_printf("Failed to accept D-Bus client: %s", err->message);
+ }
+
+ g_dbus_object_manager_server_set_connection(dbus_display->server, conn);
+}
+
+
+static bool
+dbus_display_add_client(int csock, Error **errp)
+{
+ g_autoptr(GError) err = NULL;
+ g_autoptr(GSocket) socket = NULL;
+ g_autoptr(GSocketConnection) conn = NULL;
+ g_autofree char *guid = g_dbus_generate_guid();
+
+ if (!dbus_display) {
+ error_setg(errp, "p2p connections not accepted in bus mode");
+ return false;
+ }
+
+ if (dbus_display->add_client_cancellable) {
+ g_cancellable_cancel(dbus_display->add_client_cancellable);
+ }
+
+ socket = g_socket_new_from_fd(csock, &err);
+ if (!socket) {
+ error_setg(errp, "Failed to setup D-Bus socket: %s", err->message);
+ return false;
+ }
+
+ conn = g_socket_connection_factory_create_connection(socket);
+
+ dbus_display->add_client_cancellable = g_cancellable_new();
+
+ g_dbus_connection_new(G_IO_STREAM(conn),
+ guid,
+ G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_SERVER,
+ NULL,
+ dbus_display->add_client_cancellable,
+ dbus_display_add_client_ready,
+ NULL);
+
+ return true;
+}
+
+static bool
+get_dbus_p2p(Object *o, Error **errp)
+{
+ DBusDisplay *dd = DBUS_DISPLAY(o);
+
+ return dd->p2p;
+}
+
+static void
+set_dbus_p2p(Object *o, bool p2p, Error **errp)
+{
+ DBusDisplay *dd = DBUS_DISPLAY(o);
+
+ dd->p2p = p2p;
}
static char *
@@ -196,6 +283,7 @@ dbus_display_class_init(ObjectClass *oc, void *data)
UserCreatableClass *ucc = USER_CREATABLE_CLASS(oc);
ucc->complete = dbus_display_complete;
+ object_class_property_add_bool(oc, "p2p", get_dbus_p2p, set_dbus_p2p);
object_class_property_add_str(oc, "addr", get_dbus_addr, set_dbus_addr);
object_class_property_add_enum(oc, "gl-mode",
"DisplayGLMode", &DisplayGLMode_lookup,
@@ -222,11 +310,19 @@ dbus_init(DisplayState *ds, DisplayOptions *opts)
{
DisplayGLMode mode = opts->has_gl ? opts->gl : DISPLAYGL_MODE_OFF;
+ if (opts->u.dbus.addr && opts->u.dbus.p2p) {
+ error_report("dbus: can't accept both addr=X and p2p=yes options");
+ exit(1);
+ }
+
+ using_dbus_display = 1;
+
object_new_with_props(TYPE_DBUS_DISPLAY,
object_get_objects_root(),
"dbus-display", &error_fatal,
"addr", opts->u.dbus.addr ?: "",
"gl-mode", DisplayGLMode_str(mode),
+ "p2p", yes_no(opts->u.dbus.p2p),
NULL);
}
@@ -251,6 +347,9 @@ static QemuDisplay qemu_display_dbus = {
static void register_dbus(void)
{
+ qemu_dbus_display = (struct QemuDBusDisplayOps) {
+ .add_client = dbus_display_add_client,
+ };
type_register_static(&dbus_display_info);
qemu_display_register(&qemu_display_dbus);
}
diff --git a/qemu-options.hx b/qemu-options.hx
index 901aef7da428..bcaf00140abc 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -1901,8 +1901,10 @@ SRST
``addr=<dbusaddr>`` : D-Bus bus address to connect to.
- ``gl=on|off|core|es`` : Use OpenGL for rendering (the D-interface will
- share framebuffers with DMABUF file descriptors).
+ ``p2p=yes|no`` : Use peer-to-peer connection, accepted via QMP
``add_client``.
+
+ ``gl=on|off|core|es`` : Use OpenGL for rendering (the D-Bus interface
+ will share framebuffers with DMABUF file descriptors).
``sdl``
Display video output via SDL (usually in a separate graphics
diff --git a/ui/meson.build b/ui/meson.build
index 6270aa768b6a..80f21704ada6 100644
--- a/ui/meson.build
+++ b/ui/meson.build
@@ -14,6 +14,9 @@ softmmu_ss.add(files(
'qemu-pixman.c',
'util.c',
))
+if dbus_display
+ softmmu_ss.add(files('dbus-module.c'))
+endif
softmmu_ss.add([spice_headers, files('spice-module.c')])
softmmu_ss.add(when: spice_protocol, if_true: files('vdagent.c'))
--
2.34.1.8.g35151cf07204
- [PULL 16/36] ui: split the GL context in a different object, (continued)
- [PULL 16/36] ui: split the GL context in a different object, marcandre . lureau, 2021/12/17
- [PULL 17/36] ui: move qemu_spice_fill_device_address to ui/util.c, marcandre . lureau, 2021/12/17
- [PULL 18/36] console: save current scanout details, marcandre . lureau, 2021/12/17
- [PULL 19/36] scripts: teach modinfo to skip non-C sources, marcandre . lureau, 2021/12/17
- [PULL 20/36] docs/sphinx: add sphinx modules to include D-Bus documentation, marcandre . lureau, 2021/12/17
- [PULL 21/36] backends: move dbus-vmstate1.xml to backends/, marcandre . lureau, 2021/12/17
- [PULL 22/36] docs: move D-Bus VMState documentation to source XML, marcandre . lureau, 2021/12/17
- [PULL 23/36] docs: add dbus-display documentation, marcandre . lureau, 2021/12/17
- [PULL 24/36] build-sys: set glib dependency version, marcandre . lureau, 2021/12/17
- [PULL 25/36] ui: add a D-Bus display backend, marcandre . lureau, 2021/12/17
- [PULL 26/36] ui/dbus: add p2p=on/off option,
marcandre . lureau <=
- [PULL 27/36] tests/qtests: add qtest_qmp_add_client(), marcandre . lureau, 2021/12/17
- [PULL 28/36] tests: start dbus-display-test, marcandre . lureau, 2021/12/17
- [PULL 29/36] audio: add "dbus" audio backend, marcandre . lureau, 2021/12/17
- [PULL 30/36] ui/dbus: add clipboard interface, marcandre . lureau, 2021/12/17
- [PULL 31/36] chardev: teach socket to accept no addresses, marcandre . lureau, 2021/12/17
- [PULL 32/36] chardev: make socket derivable, marcandre . lureau, 2021/12/17
- [PULL 33/36] option: add g_auto for QemuOpts, marcandre . lureau, 2021/12/17
- [PULL 34/36] ui/dbus: add chardev backend & interface, marcandre . lureau, 2021/12/17
- [PULL 35/36] ui/dbus: register D-Bus VC handler, marcandre . lureau, 2021/12/17
- [PULL 36/36] MAINTAINERS: update D-Bus section, marcandre . lureau, 2021/12/17