From: Marc-André Lureau <marcandre.lur...@redhat.com>

Existing clients may not handle async replies very well. In order
to avoid the potential issues, let's introduce a capability that
the client must declare in order to make use of async commands.

Eventually, client should already handle unexpected events after a
command is sent, instead of the reply. It shouldn't be much more
complicated to handle unmatched returns from previous async commands.

Signed-off-by: Marc-André Lureau <marcandre.lur...@redhat.com>
---
 monitor.c        | 28 ++++++++++++++++++++++++++--
 qapi-schema.json | 16 ++++++++++++++--
 2 files changed, 40 insertions(+), 4 deletions(-)

diff --git a/monitor.c b/monitor.c
index ca3db31..fda1ddd 100644
--- a/monitor.c
+++ b/monitor.c
@@ -524,8 +524,31 @@ static void monitor_qapi_event_init(void)
     qmp_event_set_func_emit(monitor_qapi_event_queue);
 }
 
-void qmp_qmp_capabilities(Error **errp)
+static void disable_async(QmpCommand *cmd, void *opaque)
 {
+    if (cmd->type == QCT_ASYNC) {
+        cmd->enabled = FALSE;
+    }
+}
+
+void qmp_qmp_capabilities(bool has_capabilities,
+                          QMPCapabilityList *capabilities, Error **errp)
+{
+    bool has_async = false;
+
+    if (has_capabilities) {
+        while (capabilities) {
+            if (capabilities->value == QMP_CAPABILITY_ASYNC) {
+                has_async = true;
+            }
+            capabilities = capabilities->next;
+        }
+    }
+
+    if (!has_async) {
+        qmp_for_each_command(disable_async, NULL);
+    }
+
     cur_mon->qmp.in_command_mode = true;
 }
 
@@ -3694,7 +3717,8 @@ static QObject *get_qmp_greeting(void)
     assert(cmd && cmd->fn);
     cmd->fn(NULL, &ver, NULL);
 
-    return qobject_from_jsonf("{'QMP':{'version': %p,'capabilities': 
[]}}",ver);
+    return qobject_from_jsonf("{'QMP':{'version': %p,'capabilities': ["
+                              "'async']}}", ver);
 }
 
 static void monitor_qmp_event(void *opaque, int event)
diff --git a/qapi-schema.json b/qapi-schema.json
index b01de49..99c986d 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -70,11 +70,23 @@
 # = QMP commands
 
 ##
+# @QMPCapability
+#
+# QMP protocol capabilities
+#
+# @async: enables async messages
+#
+# Since: 2.5
+##
+{ 'enum': 'QMPCapability',
+  'data': ['async'] }
+
+##
 # @qmp_capabilities:
 #
 # Enable QMP capabilities.
 #
-# Arguments: None.
+# @capabilities: #optional an array of QMPCapability
 #
 # Example:
 #
@@ -84,7 +96,7 @@
 # Notes: This command must be issued before issuing any other command.
 #
 ##
-{ 'command': 'qmp_capabilities' }
+{ 'command': 'qmp_capabilities', 'data': { '*capabilities': ['QMPCapability'] 
} }
 
 ##
 # @LostTickPolicy:
-- 
2.4.3


Reply via email to