The QAPI scripts allow for generating commands that receive parameter input consisting of a list of custom structs, but the QMP input paramter checking did not support receiving a qlist as opposed to a qdict for input.
This patch allows for array input parameters, although no argument validation is performed for commands that accept a list input. Signed-off-by: Jeff Cody <jc...@redhat.com> --- monitor.c | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++---------- monitor.h | 1 + 2 files changed, 61 insertions(+), 12 deletions(-) diff --git a/monitor.c b/monitor.c index a7df995..98e6017 100644 --- a/monitor.c +++ b/monitor.c @@ -125,8 +125,12 @@ typedef struct mon_cmd_t { void (*info)(Monitor *mon); void (*cmd)(Monitor *mon, const QDict *qdict); int (*cmd_new)(Monitor *mon, const QDict *params, QObject **ret_data); + int (*cmd_new_list)(Monitor *mon, const QList *params, + QObject **ret_data); int (*cmd_async)(Monitor *mon, const QDict *params, MonitorCompletion *cb, void *opaque); + int (*cmd_async_list)(Monitor *mon, const QList *params, + MonitorCompletion *cb, void *opaque); } mhandler; bool qapi; int flags; @@ -353,6 +357,11 @@ static inline bool handler_is_async(const mon_cmd_t *cmd) return cmd->flags & MONITOR_CMD_ASYNC; } +static inline bool handler_accepts_array(const mon_cmd_t *cmd) +{ + return cmd->flags & MONITOR_CMD_ARRAY_INPUT; +} + static inline int monitor_has_error(const Monitor *mon) { return mon->error != NULL; @@ -671,6 +680,12 @@ static int qmp_async_cmd_handler(Monitor *mon, const mon_cmd_t *cmd, return cmd->mhandler.cmd_async(mon, params, qmp_monitor_complete, mon); } +static int qmp_async_cmd_handler_array(Monitor *mon, const mon_cmd_t *cmd, + const QList *params) +{ + return cmd->mhandler.cmd_async_list(mon, params, qmp_monitor_complete, mon); +} + static void user_async_cmd_handler(Monitor *mon, const mon_cmd_t *cmd, const QDict *params) { @@ -4310,7 +4325,8 @@ static QDict *qmp_check_input_obj(QObject *input_obj) } has_exec_key = 1; } else if (!strcmp(arg_name, "arguments")) { - if (qobject_type(arg_obj) != QTYPE_QDICT) { + if ((qobject_type(arg_obj) != QTYPE_QDICT) && + (qobject_type(arg_obj) != QTYPE_QLIST)) { qerror_report(QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "arguments", "object"); return NULL; @@ -4345,11 +4361,26 @@ static void qmp_call_cmd(Monitor *mon, const mon_cmd_t *cmd, qobject_decref(data); } +static void qmp_call_cmd_array(Monitor *mon, const mon_cmd_t *cmd, + const QList *params) +{ + int ret; + QObject *data = NULL; + + mon_print_count_init(mon); + + ret = cmd->mhandler.cmd_new_list(mon, params, &data); + handler_audit(mon, cmd, ret); + monitor_protocol_emitter(mon, data); + qobject_decref(data); +} + static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) { int err; QObject *obj; QDict *input, *args; + QList *args_list = NULL; const mon_cmd_t *cmd; const char *cmd_name; Monitor *mon = cur_mon; @@ -4386,26 +4417,42 @@ static void handle_qmp_command(JSONMessageParser *parser, QList *tokens) } obj = qdict_get(input, "arguments"); - if (!obj) { - args = qdict_new(); + if (handler_accepts_array(cmd)) { + if (!obj || (qobject_type(obj) != QTYPE_QLIST)) { + args_list = qlist_new(); + } else { + args_list = qobject_to_qlist(obj); + QINCREF(args_list); + } } else { - args = qobject_to_qdict(obj); - QINCREF(args); - } - - err = qmp_check_client_args(cmd, args); - if (err < 0) { - goto err_out; + if (!obj || (qobject_type(obj) != QTYPE_QDICT)) { + args = qdict_new(); + } else { + args = qobject_to_qdict(obj); + QINCREF(args); + } + err = qmp_check_client_args(cmd, args); + if (err < 0) { + goto err_out; + } } if (handler_is_async(cmd)) { - err = qmp_async_cmd_handler(mon, cmd, args); + if (handler_accepts_array(cmd)) { + err = qmp_async_cmd_handler_array(mon, cmd, args_list); + } else { + err = qmp_async_cmd_handler(mon, cmd, args); + } if (err) { /* emit the error response */ goto err_out; } } else { - qmp_call_cmd(mon, cmd, args); + if (handler_accepts_array(cmd)) { + qmp_call_cmd_array(mon, cmd, args_list); + } else { + qmp_call_cmd(mon, cmd, args); + } } goto out; @@ -4415,6 +4462,7 @@ err_out: out: QDECREF(input); QDECREF(args); + QDECREF(args_list); } /** diff --git a/monitor.h b/monitor.h index b72ea07..499fc1f 100644 --- a/monitor.h +++ b/monitor.h @@ -19,6 +19,7 @@ extern Monitor *default_mon; /* flags for monitor commands */ #define MONITOR_CMD_ASYNC 0x0001 +#define MONITOR_CMD_ARRAY_INPUT 0x0002 /* QMP events */ typedef enum MonitorEvent { -- 1.7.9.rc2.1.g69204