QLIST_ENTRY(MonFdset) next;
};
-typedef struct MonitorControl {
+typedef struct {
QObject *id;
JSONMessageParser parser;
- int command_mode;
-} MonitorControl;
+ /*
+ * When a client connects, we're in capabilities negotiation mode.
+ * When command qmp_capabilities succeeds, we go into command
+ * mode.
+ */
+ bool in_command_mode; /* are we in command mode? */
+} MonitorQMP;
/*
* To prevent flooding clients, events can be throttled. The
int mux_out;
ReadLineState *rs;
- MonitorControl *mc;
+ MonitorQMP qmp;
CPUState *mon_cpu;
BlockCompletionFunc *password_completion_cb;
void *password_opaque;
static void monitor_command_cb(void *opaque, const char *cmdline,
void *readline_opaque);
-static inline int qmp_cmd_mode(const Monitor *mon)
-{
- return (mon->mc ? mon->mc->command_mode : 0);
-}
-
-/* Return true if in control mode, false otherwise */
-static inline int monitor_ctrl_mode(const Monitor *mon)
+/**
+ * Is @mon a QMP monitor?
+ */
+static inline bool monitor_is_qmp(const Monitor *mon)
{
return (mon->flags & MONITOR_USE_CONTROL);
}
-/* Return non-zero iff we have a current monitor, and it is in QMP mode. */
-int monitor_cur_is_qmp(void)
+/**
+ * Is the current monitor, if any, a QMP monitor?
+ */
+bool monitor_cur_is_qmp(void)
{
- return cur_mon && monitor_ctrl_mode(cur_mon);
+ return cur_mon && monitor_is_qmp(cur_mon);
}
void monitor_read_command(Monitor *mon, int show_prompt)
if (!mon)
return;
- if (monitor_ctrl_mode(mon)) {
+ if (monitor_is_qmp(mon)) {
return;
}
return 0;
}
-static inline int monitor_has_error(const Monitor *mon)
-{
- return mon->error != NULL;
-}
-
static void monitor_json_emitter(Monitor *mon, const QObject *data)
{
QString *json;
QDECREF(json);
}
-static QDict *build_qmp_error_dict(const QError *err)
+static QDict *build_qmp_error_dict(Error *err)
{
QObject *obj;
- obj = qobject_from_jsonf("{ 'error': { 'class': %s, 'desc': %p } }",
- ErrorClass_lookup[err->err_class],
- qerror_human(err));
+ obj = qobject_from_jsonf("{ 'error': { 'class': %s, 'desc': %s } }",
+ ErrorClass_lookup[error_get_class(err)],
+ error_get_pretty(err));
return qobject_to_qdict(obj);
}
-static void monitor_protocol_emitter(Monitor *mon, QObject *data)
+static void monitor_protocol_emitter(Monitor *mon, QObject *data,
+ Error *err)
{
QDict *qmp;
trace_monitor_protocol_emitter(mon);
- if (!monitor_has_error(mon)) {
+ if (!err) {
/* success response */
qmp = qdict_new();
if (data) {
}
} else {
/* error response */
- qmp = build_qmp_error_dict(mon->error);
- QDECREF(mon->error);
- mon->error = NULL;
+ qmp = build_qmp_error_dict(err);
}
- if (mon->mc->id) {
- qdict_put_obj(qmp, "id", mon->mc->id);
- mon->mc->id = NULL;
+ if (mon->qmp.id) {
+ qdict_put_obj(qmp, "id", mon->qmp.id);
+ mon->qmp.id = NULL;
}
monitor_json_emitter(mon, QOBJECT(qmp));
trace_monitor_protocol_event_emit(event, data);
QLIST_FOREACH(mon, &mon_list, entry) {
- if (monitor_ctrl_mode(mon) && qmp_cmd_mode(mon)) {
+ if (monitor_is_qmp(mon) && mon->qmp.in_command_mode) {
monitor_json_emitter(mon, data);
}
}
static int do_qmp_capabilities(Monitor *mon, const QDict *params,
QObject **ret_data)
{
- /* Will setup QMP capabilities in the future */
- if (monitor_ctrl_mode(mon)) {
- mon->mc->command_mode = 1;
- }
-
+ mon->qmp.in_command_mode = true;
return 0;
}
-static void handle_user_command(Monitor *mon, const char *cmdline);
+static void handle_hmp_command(Monitor *mon, const char *cmdline);
static void monitor_data_init(Monitor *mon)
{
}
}
- handle_user_command(&hmp, command_line);
+ handle_hmp_command(&hmp, command_line);
cur_mon = old_mon;
qemu_mutex_lock(&hmp.out_lock);
}
}
-static void handle_user_command(Monitor *mon, const char *cmdline)
+static void handle_hmp_command(Monitor *mon, const char *cmdline)
{
QDict *qdict;
const mon_cmd_t *cmd;
return (mon->suspend_cnt == 0) ? 1 : 0;
}
-static bool invalid_qmp_mode(const Monitor *mon, const mon_cmd_t *cmd)
+static bool invalid_qmp_mode(const Monitor *mon, const mon_cmd_t *cmd,
+ Error **errp)
{
bool is_cap = cmd->mhandler.cmd_new == do_qmp_capabilities;
- if (is_cap && qmp_cmd_mode(mon)) {
- qerror_report(ERROR_CLASS_COMMAND_NOT_FOUND,
- "Capabilities negotiation is already complete, command "
- "'%s' ignored", cmd->name);
+
+ if (is_cap && mon->qmp.in_command_mode) {
+ error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
+ "Capabilities negotiation is already complete, command "
+ "'%s' ignored", cmd->name);
return true;
}
- if (!is_cap && !qmp_cmd_mode(mon)) {
- qerror_report(ERROR_CLASS_COMMAND_NOT_FOUND,
- "Expecting capabilities negotiation with "
- "'qmp_capabilities' before command '%s'", cmd->name);
+ if (!is_cap && !mon->qmp.in_command_mode) {
+ error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
+ "Expecting capabilities negotiation with "
+ "'qmp_capabilities' before command '%s'", cmd->name);
return true;
}
return false;
"arguments", "object");
return NULL;
}
+ } else if (!strcmp(arg_name, "id")) {
+ /* Any string is acceptable as "id", so nothing to check */
} else {
error_set(errp, QERR_QMP_EXTRA_MEMBER, arg_name);
return NULL;
obj = json_parser_parse(tokens, NULL);
if (!obj) {
// FIXME: should be triggered in json_parser_parse()
- qerror_report(QERR_JSON_PARSING);
+ error_set(&local_err, QERR_JSON_PARSING);
goto err_out;
}
input = qmp_check_input_obj(obj, &local_err);
if (!input) {
- qerror_report_err(local_err);
qobject_decref(obj);
goto err_out;
}
- mon->mc->id = qdict_get(input, "id");
- qobject_incref(mon->mc->id);
+ mon->qmp.id = qdict_get(input, "id");
+ qobject_incref(mon->qmp.id);
cmd_name = qdict_get_str(input, "execute");
trace_handle_qmp_command(mon, cmd_name);
cmd = qmp_find_cmd(cmd_name);
if (!cmd) {
- qerror_report(ERROR_CLASS_COMMAND_NOT_FOUND,
- "The command %s has not been found", cmd_name);
+ error_set(&local_err, ERROR_CLASS_COMMAND_NOT_FOUND,
+ "The command %s has not been found", cmd_name);
goto err_out;
}
- if (invalid_qmp_mode(mon, cmd)) {
+ if (invalid_qmp_mode(mon, cmd, &local_err)) {
goto err_out;
}
qmp_check_client_args(cmd, args, &local_err);
if (local_err) {
- qerror_report_err(local_err);
goto err_out;
}
if (cmd->mhandler.cmd_new(mon, args, &data)) {
/* Command failed... */
- if (!monitor_has_error(mon)) {
+ if (!mon->error) {
/* ... without setting an error, so make one up */
- qerror_report(QERR_UNDEFINED_ERROR);
+ error_set(&local_err, QERR_UNDEFINED_ERROR);
}
}
+ if (mon->error) {
+ error_set(&local_err, mon->error->err_class, "%s",
+ mon->error->err_msg);
+ }
err_out:
- monitor_protocol_emitter(mon, data);
+ monitor_protocol_emitter(mon, data, local_err);
qobject_decref(data);
+ QDECREF(mon->error);
+ mon->error = NULL;
QDECREF(input);
QDECREF(args);
}
-/**
- * monitor_control_read(): Read and handle QMP input
- */
-static void monitor_control_read(void *opaque, const uint8_t *buf, int size)
+static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size)
{
Monitor *old_mon = cur_mon;
cur_mon = opaque;
- json_message_parser_feed(&cur_mon->mc->parser, (const char *) buf, size);
+ json_message_parser_feed(&cur_mon->qmp.parser, (const char *) buf, size);
cur_mon = old_mon;
}
if (size == 0 || buf[size - 1] != 0)
monitor_printf(cur_mon, "corrupted command\n");
else
- handle_user_command(cur_mon, (char *)buf);
+ handle_hmp_command(cur_mon, (char *)buf);
}
cur_mon = old_mon;
Monitor *mon = opaque;
monitor_suspend(mon);
- handle_user_command(mon, cmdline);
+ handle_hmp_command(mon, cmdline);
monitor_resume(mon);
}
return qobject_from_jsonf("{'QMP':{'version': %p,'capabilities': []}}",ver);
}
-/**
- * monitor_control_event(): Print QMP gretting
- */
-static void monitor_control_event(void *opaque, int event)
+static void monitor_qmp_event(void *opaque, int event)
{
QObject *data;
Monitor *mon = opaque;
switch (event) {
case CHR_EVENT_OPENED:
- mon->mc->command_mode = 0;
+ mon->qmp.in_command_mode = false;
data = get_qmp_greeting();
monitor_json_emitter(mon, data);
qobject_decref(data);
mon_refcount++;
break;
case CHR_EVENT_CLOSED:
- json_message_parser_destroy(&mon->mc->parser);
- json_message_parser_init(&mon->mc->parser, handle_qmp_command);
+ json_message_parser_destroy(&mon->qmp.parser);
+ json_message_parser_init(&mon->qmp.parser, handle_qmp_command);
mon_refcount--;
monitor_fdsets_cleanup();
break;
monitor_read_command(mon, 0);
}
- if (monitor_ctrl_mode(mon)) {
- mon->mc = g_malloc0(sizeof(MonitorControl));
- /* Control mode requires special handlers */
- qemu_chr_add_handlers(chr, monitor_can_read, monitor_control_read,
- monitor_control_event, mon);
+ if (monitor_is_qmp(mon)) {
+ qemu_chr_add_handlers(chr, monitor_can_read, monitor_qmp_read,
+ monitor_qmp_event, mon);
qemu_chr_fe_set_echo(chr, true);
-
- json_message_parser_init(&mon->mc->parser, handle_qmp_command);
+ json_message_parser_init(&mon->qmp.parser, handle_qmp_command);
} else {
qemu_chr_add_handlers(chr, monitor_can_read, monitor_read,
monitor_event, mon);