Hi, On Fri, Sep 21, 2018 at 02:31:40PM +0400, Marc-André Lureau wrote: > Hi > > On Fri, Sep 21, 2018 at 1:24 PM Victor Toso <victortoso@xxxxxxxxxx> wrote: > > > > Hi, > > > > On Thu, Sep 20, 2018 at 12:01:37AM +0400, marcandre.lureau@xxxxxxxxxx wrote: > > > From: Marc-André Lureau <marcandre.lureau@xxxxxxxxxx> > > > > > > Add a few helper functions to deal with a QMP port channel, in order > > > to ease json handling, and wrapping a few commands. > > > > > > (by convention, the port should have the name > > > "org.qemu.monitor.qmp.0", but it's not strictly required) > > > > > > This helper is put into use in the virt-viewer "Add QEMU-like UI: VT > > > console & basic VM status" series. > > > > > > Note: this adds a strong dependency on json-glib for > > > spice-client-glib, a widely available and fairly small > > > library. > > > > > > QMP specification is: > > > https://git.qemu.org/?p=qemu.git;a=blob;f=docs/interop/qmp-spec.txt > > > > > > Signed-off-by: Marc-André Lureau <marcandre.lureau@xxxxxxxxxx> > > > --- > > > configure.ac | 2 + > > > doc/reference/spice-gtk-docs.xml | 1 + > > > doc/reference/spice-gtk-sections.txt | 27 ++ > > > meson.build | 2 + > > > src/Makefile.am | 6 + > > > src/map-file | 9 + > > > src/meson.build | 4 + > > > src/qmp-port.c | 575 +++++++++++++++++++++++++++ > > > src/qmp-port.h | 122 ++++++ > > > src/spice-client.h | 1 + > > > src/spice-glib-sym-file | 9 + > > > 11 files changed, 758 insertions(+) > > > create mode 100644 src/qmp-port.c > > > create mode 100644 src/qmp-port.h > > > > > > v2: after Victor review > > > - add meson build > > > > Thanks > > > > > - print only corresponding message when dispatch failed > > > - warn/critical on unknown task/id > > > - fix PortChannel/QmpPort weak ref relationship > > > - some renaming > > > > > > diff --git a/configure.ac b/configure.ac > > > index 7b32e29..e686d76 100644 > > > --- a/configure.ac > > > +++ b/configure.ac > > > @@ -173,6 +173,8 @@ PKG_CHECK_MODULES(CAIRO, cairo >= 1.2.0) > > > > > > PKG_CHECK_MODULES(GTHREAD, gthread-2.0) > > > > > > +PKG_CHECK_MODULES(JSON, json-glib-1.0) > > > + > > > AC_ARG_ENABLE([webdav], > > > AS_HELP_STRING([--enable-webdav=@<:@auto/yes/no@:>@], > > > [Enable webdav support @<:@default=auto@:>@]), > > > diff --git a/doc/reference/spice-gtk-docs.xml b/doc/reference/spice-gtk-docs.xml > > > index db5dd3d..696c375 100644 > > > --- a/doc/reference/spice-gtk-docs.xml > > > +++ b/doc/reference/spice-gtk-docs.xml > > > @@ -52,6 +52,7 @@ > > > <xi:include href="xml/spice-audio.xml"/> > > > <xi:include href="xml/smartcard-manager.xml"/> > > > <xi:include href="xml/usb-device-manager.xml"/> > > > + <xi:include href="xml/qmp-port.xml"/> > > > <xi:include href="xml/spice-util.xml"/> > > > <xi:include href="xml/spice-version.xml"/> > > > <xi:include href="xml/spice-uri.xml"/> > > > diff --git a/doc/reference/spice-gtk-sections.txt b/doc/reference/spice-gtk-sections.txt > > > index a85df7a..a0336aa 100644 > > > --- a/doc/reference/spice-gtk-sections.txt > > > +++ b/doc/reference/spice-gtk-sections.txt > > > @@ -494,6 +494,33 @@ SPICE_PORT_CHANNEL_GET_CLASS > > > SpicePortChannelPrivate > > > </SECTION> > > > > > > +<SECTION> > > > +<FILE>qmp-port</FILE> > > > +<TITLE>SpiceQmpPort</TITLE> > > > + > > > +<SUBSECTION> > > > +SpiceQmpPort > > > +SpiceQmpPortVmAction > > > +SpiceQmpStatus > > > +<SUBSECTION> > > > +spice_qmp_port_get > > > +spice_qmp_port_vm_action_async > > > +spice_qmp_port_vm_action_finish > > > +spice_qmp_port_query_status_async > > > +spice_qmp_port_query_status_finish > > > +spice_qmp_status_ref > > > +spice_qmp_status_unref > > > +<SUBSECTION Standard> > > > +SPICE_IS_QMP_PORT > > > +SPICE_IS_QMP_PORT_CLASS > > > +SPICE_QMP_PORT > > > +SPICE_QMP_PORT_CLASS > > > +SPICE_QMP_PORT_GET_CLASS > > > +SPICE_TYPE_QMP_PORT > > > +spice_qmp_port_get_type > > > +spice_qmp_status_get_type > > > +</SECTION> > > > + > > > <SECTION> > > > <FILE>spice-uri</FILE> > > > spice_uri_get_scheme > > > diff --git a/meson.build b/meson.build > > > index 3c20401..875e07f 100644 > > > --- a/meson.build > > > +++ b/meson.build > > > @@ -98,6 +98,8 @@ foreach dep, version : deps > > > spice_gtk_deps += dependency(dep, version : version) > > > endforeach > > > > > > +spice_gtk_deps += dependency('json-glib-1.0') > > > + > > > # TODO: specify minimum version for cairo, jpeg and zlib? > > > deps = ['cairo', 'libjpeg', 'zlib'] > > > if spice_gtk_host_system == 'windows' > > > diff --git a/src/Makefile.am b/src/Makefile.am > > > index 4dd657d..1bb6f9b 100644 > > > --- a/src/Makefile.am > > > +++ b/src/Makefile.am > > > @@ -78,6 +78,7 @@ SPICE_COMMON_CPPFLAGS = \ > > > $(GLIB2_CFLAGS) \ > > > $(GIO_CFLAGS) \ > > > $(GOBJECT2_CFLAGS) \ > > > + $(JSON_CFLAGS) \ > > > $(SSL_CFLAGS) \ > > > $(SASL_CFLAGS) \ > > > $(GSTAUDIO_CFLAGS) \ > > > @@ -182,6 +183,7 @@ libspice_client_glib_2_0_la_LIBADD = \ > > > $(GIO_LIBS) \ > > > $(GOBJECT2_LIBS) \ > > > $(JPEG_LIBS) \ > > > + $(JSON_LIBS) \ > > > $(Z_LIBS) \ > > > $(LZ4_LIBS) \ > > > $(PIXMAN_LIBS) \ > > > @@ -243,6 +245,8 @@ libspice_client_glib_2_0_la_SOURCES = \ > > > channel-smartcard.c \ > > > channel-usbredir.c \ > > > channel-usbredir-priv.h \ > > > + qmp-port.c \ > > > + qmp-port.h \ > > > smartcard-manager.c \ > > > smartcard-manager-priv.h \ > > > spice-uri.c \ > > > @@ -293,6 +297,7 @@ libspice_client_glibinclude_HEADERS = \ > > > channel-smartcard.h \ > > > channel-usbredir.h \ > > > channel-webdav.h \ > > > + qmp-port.h \ > > > usb-device-manager.h \ > > > smartcard-manager.h \ > > > spice-file-transfer-task.h \ > > > @@ -526,6 +531,7 @@ glib_introspection_files = \ > > > channel-record.c \ > > > channel-smartcard.c \ > > > channel-usbredir.c \ > > > + qmp-port.c \ > > > smartcard-manager.c \ > > > usb-device-manager.c \ > > > $(NULL) > > > diff --git a/src/map-file b/src/map-file > > > index cdb81c3..500683c 100644 > > > --- a/src/map-file > > > +++ b/src/map-file > > > @@ -117,6 +117,15 @@ spice_port_channel_write_finish; > > > spice_port_event; > > > spice_port_write_async; > > > spice_port_write_finish; > > > +spice_qmp_port_get; > > > +spice_qmp_port_get_type; > > > +spice_qmp_port_query_status_async; > > > +spice_qmp_port_query_status_finish; > > > +spice_qmp_port_vm_action_async; > > > +spice_qmp_port_vm_action_finish; > > > +spice_qmp_status_get_type; > > > +spice_qmp_status_ref; > > > +spice_qmp_status_unref; > > > spice_record_channel_get_type; > > > spice_record_channel_send_data; > > > spice_record_send_data; > > > diff --git a/src/meson.build b/src/meson.build > > > index 8c9199e..80e777d 100644 > > > --- a/src/meson.build > > > +++ b/src/meson.build > > > @@ -32,6 +32,7 @@ spice_client_glib_headers = [ > > > 'channel-smartcard.h', > > > 'channel-usbredir.h', > > > 'channel-webdav.h', > > > + 'qmp-port.h', > > > 'smartcard-manager.h', > > > 'spice-audio.h', > > > 'spice-channel.h', > > > @@ -70,6 +71,7 @@ spice_client_glib_introspection_sources = [ > > > 'channel-smartcard.c', > > > 'channel-usbredir.c', > > > 'channel-webdav.c', > > > + 'qmp-port.c', > > > 'smartcard-manager.c', > > > 'spice-audio.c', > > > 'spice-channel.c', > > > @@ -98,6 +100,8 @@ spice_client_glib_sources = [ > > > 'decode-zlib.c', > > > 'gio-coroutine.c', > > > 'gio-coroutine.h', > > > + 'qmp-port.c', > > > + 'qmp-port.h', > > > 'smartcard-manager-priv.h', > > > 'spice-audio-priv.h', > > > 'spice-channel-cache.h', > > > diff --git a/src/qmp-port.c b/src/qmp-port.c > > > new file mode 100644 > > > index 0000000..c2e5c03 > > > --- /dev/null > > > +++ b/src/qmp-port.c > > > @@ -0,0 +1,575 @@ > > > +/* -*- Mode: C; c-basic-offset: 4; indent-tabs-mode: nil -*- */ > > > +/* > > > + Copyright (C) 2018 Red Hat, Inc. > > > + > > > + This library is free software; you can redistribute it and/or > > > + modify it under the terms of the GNU Lesser General Public > > > + License as published by the Free Software Foundation; either > > > + version 2.1 of the License, or (at your option) any later version. > > > + > > > + This library 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 > > > + Lesser General Public License for more details. > > > + > > > + You should have received a copy of the GNU Lesser General Public > > > + License along with this library; if not, see <http://www.gnu.org/licenses/>. > > > +*/ > > > +#include "config.h" > > > + > > > +#define _GNU_SOURCE > > > +#include <string.h> > > > +#include <json-glib/json-glib.h> > > > +#include "spice-client.h" > > > + > > > +/** > > > + * SECTION:qmp-port > > > + * @short_description: QMP port helper > > > + * @title: QMP port channel helper > > > + * @section_id: > > > + * @see_also: #SpicePortChannel > > > + * @stability: Stable > > > + * @include: spice-client.h > > > + * > > > + * A helper to handle QMP messages over a %SpicePortChannel. > > > + * > > > + * Since: 0.36 > > > + */ > > > + > > > +typedef struct _SpiceQmpPortPrivate SpiceQmpPortPrivate; > > > + > > > +struct _SpiceQmpPortPrivate > > > +{ > > > + SpicePortChannel *channel; > > > + gboolean ready; > > > + > > > + gint id_counter; > > > + GString *qmp_data; > > > + JsonParser *qmp_parser; > > > + GHashTable *qmp_tasks; > > > +}; > > > + > > > +struct _SpiceQmpPort > > > +{ > > > + GObject parent; > > > + > > > + SpiceQmpPortPrivate *priv; > > > +}; > > > + > > > +struct _SpiceQmpPortClass > > > +{ > > > + GObjectClass parent_class; > > > +}; > > > + > > > +enum { > > > + PROP_CHANNEL = 1, > > > + PROP_READY, > > > + > > > + PROP_LAST, > > > +}; > > > + > > > +enum { > > > + SIGNAL_EVENT, > > > + > > > + SIGNAL_LAST, > > > +}; > > > + > > > +static guint signals[SIGNAL_LAST]; > > > +static GParamSpec *props[PROP_LAST] = { NULL, }; > > > + > > > +G_DEFINE_TYPE_WITH_PRIVATE(SpiceQmpPort, spice_qmp_port, G_TYPE_OBJECT) > > > + > > > +G_DEFINE_BOXED_TYPE(SpiceQmpStatus, spice_qmp_status, spice_qmp_status_ref, spice_qmp_status_unref) > > > + > > > +typedef void (QMPCb)(GTask *task, JsonNode *node); > > > + > > > +static void > > > +qmp_error_return(GTask *task, const gchar *desc) > > > +{ > > > + g_task_return_new_error(task, SPICE_CLIENT_ERROR, > > > + SPICE_CLIENT_ERROR_FAILED, "%s", desc); > > > + g_object_unref(task); > > > +} > > > + > > > +static gboolean > > > +spice_qmp_dispatch_message(SpiceQmpPort *self) > > > +{ > > > + JsonObject *obj = json_node_get_object(json_parser_get_root(self->priv->qmp_parser)); > > > + JsonNode *node; > > > + GTask *task; > > > + const gchar *event; > > > + > > > + if (!self->priv->ready && json_object_get_member(obj, "QMP")) { > > > + g_debug("QMP greeting received"); > > > > As mentioned earlier, self->priv->ready can (should?) be moved > > inside the if, likely to have this check in g_warn_if_fail() like > > it is done to others below. > > Ah sorry, I missed that. > > So QMP greeting isn't that useful to us at this point. > > I can just remove the self->priv->ready from there: > > if (json_object_get_member(obj, "QMP")) { > g_debug("QMP greeting received"); > return: > } > > Would you prefer that? Either way is fine to me ;) Cheers, Victor
Attachment:
signature.asc
Description: PGP signature
_______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel