aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/qapi/qmp/dispatch.h2
-rw-r--r--monitor.c79
-rw-r--r--qapi/qmp-dispatch.c12
-rw-r--r--tests/qmp-test.c4
4 files changed, 30 insertions, 67 deletions
diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h
index 303a15ba84..514bfc45b0 100644
--- a/include/qapi/qmp/dispatch.h
+++ b/include/qapi/qmp/dispatch.h
@@ -48,8 +48,6 @@ bool qmp_command_is_enabled(const QmpCommand *cmd);
const char *qmp_command_name(const QmpCommand *cmd);
bool qmp_has_success_response(const QmpCommand *cmd);
QObject *qmp_build_error_object(Error *err);
-QDict *qmp_dispatch_check_obj(const QObject *request, bool allow_oob,
- Error **errp);
QObject *qmp_dispatch(QmpCommandList *cmds, QObject *request,
bool allow_oob);
bool qmp_is_oob(QDict *dict);
diff --git a/monitor.c b/monitor.c
index c49214cd8f..be2a856d1c 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1290,48 +1290,6 @@ static void qmp_caps_apply(Monitor *mon, QMPCapabilityList *list)
}
}
-/*
- * Return true if check successful, or false otherwise. When false is
- * returned, detailed error will be in errp if provided.
- */
-static bool qmp_cmd_oob_check(Monitor *mon, QDict *req, Error **errp)
-{
- const char *command;
- QmpCommand *cmd;
-
- command = qdict_get_try_str(req, "execute");
- if (!command) {
- command = qdict_get_try_str(req, "exec-oob");
- }
- if (!command) {
- error_setg(errp, "Command field 'execute' missing");
- return false;
- }
-
- cmd = qmp_find_command(mon->qmp.commands, command);
- if (!cmd) {
- if (mon->qmp.commands == &qmp_cap_negotiation_commands) {
- error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
- "Expecting capabilities negotiation "
- "with 'qmp_capabilities'");
- } else {
- error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
- "The command %s has not been found", command);
- }
- return false;
- }
-
- if (qmp_is_oob(req)) {
- if (!(cmd->options & QCO_ALLOW_OOB)) {
- error_setg(errp, "The command %s does not support OOB",
- command);
- return false;
- }
- }
-
- return true;
-}
-
void qmp_qmp_capabilities(bool has_enable, QMPCapabilityList *enable,
Error **errp)
{
@@ -4171,6 +4129,7 @@ static void monitor_qmp_dispatch(Monitor *mon, QObject *req, QObject *id)
{
Monitor *old_mon;
QObject *rsp;
+ QDict *error;
old_mon = cur_mon;
cur_mon = mon;
@@ -4179,6 +4138,19 @@ static void monitor_qmp_dispatch(Monitor *mon, QObject *req, QObject *id)
cur_mon = old_mon;
+ if (mon->qmp.commands == &qmp_cap_negotiation_commands) {
+ error = qdict_get_qdict(qobject_to(QDict, rsp), "error");
+ if (error
+ && !g_strcmp0(qdict_get_try_str(error, "class"),
+ QapiErrorClass_str(ERROR_CLASS_COMMAND_NOT_FOUND))) {
+ /* Provide a more useful error message */
+ qdict_del(error, "desc");
+ qdict_put_str(error, "desc", "Expecting capabilities negotiation"
+ " with 'qmp_capabilities'");
+ }
+ }
+
+ /* Respond if necessary */
monitor_qmp_respond(mon, rsp, NULL, qobject_ref(id));
}
@@ -4256,7 +4228,9 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
error_setg(&err, QERR_JSON_PARSING);
}
if (err) {
- goto err;
+ assert(!req);
+ monitor_qmp_respond(mon, NULL, err, NULL);
+ return;
}
qdict = qobject_to(QDict, req);
@@ -4271,18 +4245,7 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
qobject_unref(req_json);
}
- /* Check against the request in general layout */
- qdict = qmp_dispatch_check_obj(req, qmp_oob_enabled(mon), &err);
- if (!qdict) {
- goto err;
- }
-
- /* Check against OOB specific */
- if (!qmp_cmd_oob_check(mon, qdict, &err)) {
- goto err;
- }
-
- if (qmp_is_oob(qdict)) {
+ if (qdict && qmp_is_oob(qdict)) {
/* Out-of-band (OOB) requests are executed directly in parser. */
trace_monitor_qmp_cmd_out_of_band(qobject_get_try_str(id)
?: "");
@@ -4336,12 +4299,6 @@ static void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens)
/* Kick the dispatcher routine */
qemu_bh_schedule(mon_global.qmp_dispatcher_bh);
- return;
-
-err:
- /* FIXME overtakes queued in-band commands, wrong when !qmp_is_oob() */
- monitor_qmp_respond(mon, NULL, err, NULL);
- qobject_unref(req);
}
static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size)
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index 12be120fe7..6d78f3e9f6 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -20,8 +20,8 @@
#include "qapi/qmp/qbool.h"
#include "sysemu/sysemu.h"
-QDict *qmp_dispatch_check_obj(const QObject *request, bool allow_oob,
- Error **errp)
+static QDict *qmp_dispatch_check_obj(const QObject *request, bool allow_oob,
+ Error **errp)
{
const char *exec_key = NULL;
const QDictEntry *ent;
@@ -78,6 +78,7 @@ static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request,
bool allow_oob, Error **errp)
{
Error *local_err = NULL;
+ bool oob;
const char *command;
QDict *args, *dict;
QmpCommand *cmd;
@@ -89,9 +90,11 @@ static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request,
}
command = qdict_get_try_str(dict, "execute");
+ oob = false;
if (!command) {
assert(allow_oob);
command = qdict_get_str(dict, "exec-oob");
+ oob = true;
}
cmd = qmp_find_command(cmds, command);
if (cmd == NULL) {
@@ -104,6 +107,11 @@ static QObject *do_qmp_dispatch(QmpCommandList *cmds, QObject *request,
command);
return NULL;
}
+ if (oob && !(cmd->options & QCO_ALLOW_OOB)) {
+ error_setg(errp, "The command %s does not support OOB",
+ command);
+ return false;
+ }
if (runstate_check(RUN_STATE_PRECONFIG) &&
!(cmd->options & QCO_ALLOW_PRECONFIG)) {
diff --git a/tests/qmp-test.c b/tests/qmp-test.c
index 9eb20a1a18..ceaf4a6789 100644
--- a/tests/qmp-test.c
+++ b/tests/qmp-test.c
@@ -242,12 +242,12 @@ static void test_qmp_oob(void)
recv_cmd_id(qts, "ib-blocks-1");
recv_cmd_id(qts, "ib-quick-1");
- /* FIXME certain in-band errors overtake slow in-band command */
+ /* Even malformed in-band command fails in-band */
send_cmd_that_blocks(qts, "blocks-2");
qtest_async_qmp(qts, "{ 'id': 'err-2' }");
- recv_cmd_id(qts, NULL);
unblock_blocked_cmd();
recv_cmd_id(qts, "blocks-2");
+ recv_cmd_id(qts, "err-2");
cleanup_blocking_cmd();
qtest_quit(qts);