Use the QmpSession json parser introduced in previous patch to generalize the handling in both qemu & qemu-ga. Unfortunately, since the introduction of OOB, it's not as common as it was before that. We may want to move some of OOB logic in common qmp-dispatch.c/QmpSession though.
The QEMU monitor has peculiar handling of the stream of commands, for OOB command processing, which can be solved by overriding the json emit callback. Signed-off-by: Marc-André Lureau <marcandre.lur...@redhat.com> --- include/qapi/qmp/dispatch.h | 1 + include/qapi/qmp/json-parser.h | 7 ++++--- monitor/monitor-internal.h | 1 - monitor/qmp.c | 13 +++++-------- qapi/qmp-dispatch.c | 4 +++- qga/main.c | 2 +- qobject/json-streamer.c | 3 +-- tests/test-qmp-cmds.c | 11 ++++++----- 8 files changed, 21 insertions(+), 21 deletions(-) diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h index c84edff7d2..b3ca6c9ff2 100644 --- a/include/qapi/qmp/dispatch.h +++ b/include/qapi/qmp/dispatch.h @@ -53,6 +53,7 @@ const QmpCommand *qmp_find_command(const QmpCommandList *cmds, const char *name); void qmp_session_init(QmpSession *session, const QmpCommandList *cmds, + JSONMessageEmit *emit, QmpDispatchReturn *return_cb); static inline void qmp_session_feed(QmpSession *session, const char *buf, size_t count) diff --git a/include/qapi/qmp/json-parser.h b/include/qapi/qmp/json-parser.h index 7345a9bd5c..6f168e8007 100644 --- a/include/qapi/qmp/json-parser.h +++ b/include/qapi/qmp/json-parser.h @@ -14,6 +14,8 @@ #ifndef QAPI_QMP_JSON_PARSER_H #define QAPI_QMP_JSON_PARSER_H +typedef void (JSONMessageEmit)(void *opaque, QObject *json, Error *err); + typedef struct JSONLexer { int start_state, state; GString *token; @@ -21,7 +23,7 @@ typedef struct JSONLexer { } JSONLexer; typedef struct JSONMessageParser { - void (*emit)(void *opaque, QObject *json, Error *err); + JSONMessageEmit *emit; void *opaque; va_list *ap; JSONLexer lexer; @@ -32,8 +34,7 @@ typedef struct JSONMessageParser { } JSONMessageParser; void json_message_parser_init(JSONMessageParser *parser, - void (*emit)(void *opaque, QObject *json, - Error *err), + JSONMessageEmit *emit, void *opaque, va_list *ap); void json_message_parser_feed(JSONMessageParser *parser, diff --git a/monitor/monitor-internal.h b/monitor/monitor-internal.h index 65d587eafb..65cf668b20 100644 --- a/monitor/monitor-internal.h +++ b/monitor/monitor-internal.h @@ -125,7 +125,6 @@ struct MonitorHMP { typedef struct { Monitor common; - JSONMessageParser parser; bool pretty; /* * When a client connects, we're in capabilities negotiation mode. diff --git a/monitor/qmp.c b/monitor/qmp.c index b215cb70f3..cd29494e28 100644 --- a/monitor/qmp.c +++ b/monitor/qmp.c @@ -217,7 +217,7 @@ void monitor_qmp_bh_dispatcher(void *data) static void handle_qmp_command(void *opaque, QObject *req, Error *err) { - MonitorQMP *mon = opaque; + MonitorQMP *mon = container_of(opaque, MonitorQMP, session); QObject *id = NULL; QDict *qdict; QMPRequest *req_obj; @@ -279,7 +279,7 @@ static void monitor_qmp_read(void *opaque, const uint8_t *buf, int size) { MonitorQMP *mon = opaque; - json_message_parser_feed(&mon->parser, (const char *) buf, size); + qmp_session_feed(&mon->session, (const char *) buf, size); } static QDict *qmp_greeting(MonitorQMP *mon) @@ -309,7 +309,9 @@ static void monitor_qmp_event(void *opaque, int event) switch (event) { case CHR_EVENT_OPENED: qmp_session_init(&mon->session, - &qmp_cap_negotiation_commands, dispatch_return_cb); + &qmp_cap_negotiation_commands, + handle_qmp_command, + dispatch_return_cb); monitor_qmp_caps_reset(mon); data = qmp_greeting(mon); qmp_send_response(mon, data); @@ -325,9 +327,6 @@ static void monitor_qmp_event(void *opaque, int event) */ monitor_qmp_cleanup_queues(mon); qmp_session_destroy(&mon->session); - json_message_parser_destroy(&mon->parser); - json_message_parser_init(&mon->parser, handle_qmp_command, - mon, NULL); mon_refcount--; monitor_fdsets_cleanup(); break; @@ -337,7 +336,6 @@ static void monitor_qmp_event(void *opaque, int event) void monitor_data_destroy_qmp(MonitorQMP *mon) { qmp_session_destroy(&mon->session); - json_message_parser_destroy(&mon->parser); qemu_mutex_destroy(&mon->qmp_queue_lock); monitor_qmp_cleanup_req_queue_locked(mon); g_queue_free(mon->qmp_requests); @@ -373,7 +371,6 @@ void monitor_init_qmp(Chardev *chr, bool pretty) qemu_chr_fe_init(&mon->common.chr, chr, &error_abort); qemu_chr_fe_set_echo(&mon->common.chr, true); - json_message_parser_init(&mon->parser, handle_qmp_command, mon, NULL); if (mon->common.use_io_thread) { /* * Make sure the old iowatch is gone. It's possible when diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c index 803ec626cd..f2c376d005 100644 --- a/qapi/qmp-dispatch.c +++ b/qapi/qmp-dispatch.c @@ -182,12 +182,14 @@ static void qmp_json_emit(void *opaque, QObject *obj, Error *err) void qmp_session_init(QmpSession *session, const QmpCommandList *cmds, + JSONMessageEmit *emit, QmpDispatchReturn *return_cb) { assert(return_cb); assert(!session->return_cb); - json_message_parser_init(&session->parser, qmp_json_emit, session, NULL); + json_message_parser_init(&session->parser, emit ?: qmp_json_emit, + session, NULL); session->cmds = cmds; session->return_cb = return_cb; } diff --git a/qga/main.c b/qga/main.c index 057368eb16..b005550c70 100644 --- a/qga/main.c +++ b/qga/main.c @@ -1319,7 +1319,7 @@ static GAState *initialize_agent(GAConfig *config, int socket_activation) s->command_state = ga_command_state_new(); ga_command_state_init(s, s->command_state); ga_command_state_init_all(s->command_state); - qmp_session_init(&s->session, &ga_commands, dispatch_return_cb); + qmp_session_init(&s->session, &ga_commands, NULL, dispatch_return_cb); #ifndef _WIN32 if (!register_signal_handlers()) { diff --git a/qobject/json-streamer.c b/qobject/json-streamer.c index 47dd7ea576..2a440f2a9e 100644 --- a/qobject/json-streamer.c +++ b/qobject/json-streamer.c @@ -100,8 +100,7 @@ out_emit: } void json_message_parser_init(JSONMessageParser *parser, - void (*emit)(void *opaque, QObject *json, - Error *err), + JSONMessageEmit *emit, void *opaque, va_list *ap) { parser->emit = emit; diff --git a/tests/test-qmp-cmds.c b/tests/test-qmp-cmds.c index 7b3bccc091..8e46f88f6f 100644 --- a/tests/test-qmp-cmds.c +++ b/tests/test-qmp-cmds.c @@ -127,7 +127,7 @@ static void test_dispatch_cmd(void) QmpSession session = { 0, }; QDict *req = qdict_new(); - qmp_session_init(&session, &qmp_commands, dispatch_cmd_return); + qmp_session_init(&session, &qmp_commands, NULL, dispatch_cmd_return); qdict_put_str(req, "execute", "user_def_cmd"); qmp_dispatch(&session, QOBJECT(req), false); @@ -141,7 +141,7 @@ static void test_dispatch_cmd_oob(void) QmpSession session = { 0, }; QDict *req = qdict_new(); - qmp_session_init(&session, &qmp_commands, dispatch_cmd_return); + qmp_session_init(&session, &qmp_commands, NULL, dispatch_cmd_return); qdict_put_str(req, "exec-oob", "test-flags-command"); qmp_dispatch(&session, QOBJECT(req), true); @@ -163,7 +163,8 @@ static void test_dispatch_cmd_failure(void) QDict *req = qdict_new(); QDict *args = qdict_new(); - qmp_session_init(&session, &qmp_commands, dispatch_cmd_failure_return); + qmp_session_init(&session, &qmp_commands, NULL, + dispatch_cmd_failure_return); qdict_put_str(req, "execute", "user_def_cmd2"); qmp_dispatch(&session, QOBJECT(req), false); @@ -189,7 +190,7 @@ static void test_dispatch_cmd_success_response(void) QmpSession session = { 0, }; QDict *req = qdict_new(); - qmp_session_init(&session, &qmp_commands, (QmpDispatchReturn *)abort); + qmp_session_init(&session, &qmp_commands, NULL, (QmpDispatchReturn *)abort); qdict_put_str(req, "execute", "cmd-success-response"); qmp_dispatch(&session, QOBJECT(req), false); @@ -210,7 +211,7 @@ static QObject *test_qmp_dispatch(QDict *req) QmpSession session = { 0, }; QObject *ret; - qmp_session_init(&session, &qmp_commands, dispatch_return); + qmp_session_init(&session, &qmp_commands, NULL, dispatch_return); qmp_dispatch(&session, QOBJECT(req), false); ret = dispatch_ret; dispatch_ret = NULL; -- 2.22.0.428.g6d5b264208