@@ -15,6 +15,7 @@
#define QAPI_QMP_DISPATCH_H
#include "qemu/queue.h"
+#include "qapi/qmp/json-streamer.h"
typedef void (QmpCommandFunc)(QDict *, QObject **, Error **);
@@ -40,6 +41,7 @@ typedef struct QmpSession QmpSession;
typedef void (QmpDispatchReturn) (QmpSession *session, QDict *rsp);
struct QmpSession {
+ JSONMessageParser parser;
QmpDispatchReturn *return_cb;
QmpCommandList *cmds;
};
@@ -48,9 +50,16 @@ void qmp_register_command(QmpCommandList *cmds, const char *name,
QmpCommandFunc *fn, QmpCommandOptions options);
void qmp_unregister_command(QmpCommandList *cmds, const char *name);
QmpCommand *qmp_find_command(QmpCommandList *cmds, const char *name);
+
void qmp_session_init(QmpSession *session,
QmpCommandList *cmds, QmpDispatchReturn *return_cb);
+static inline void
+qmp_session_feed(QmpSession *session, const char *buf, size_t count)
+{
+ json_message_parser_feed(&session->parser, buf, count);
+}
+
void qmp_session_destroy(QmpSession *session);
void qmp_dispatch(QmpSession *session, QDict *request);
void qmp_disable_command(QmpCommandList *cmds, const char *name);
@@ -3934,11 +3934,8 @@ static void dispatch_return_cb(QmpSession *session, QDict *rsp)
*/
static void monitor_qmp_dispatch_one(QMPRequest *req_obj)
{
- Monitor *mon, *old_mon;
- QDict *req;
-
- req = req_obj->req;
- mon = req_obj->mon;
+ Monitor *old_mon, *mon = req_obj->mon;
+ QDict *req = req_obj->req;
g_free(req_obj);
@@ -146,12 +146,43 @@ bool qmp_is_oob(const QDict *dict)
return qbool_get_bool(bool_obj);
}
+static void qmp_json_parser_emit(JSONMessageParser *parser, GQueue *tokens)
+{
+ QmpSession *session = container_of(parser, QmpSession, parser);
+ QObject *obj;
+ QDict *req;
+ Error *err = NULL;
+
+ obj = json_parser_parse_err(tokens, NULL, &err);
+ if (err) {
+ goto end;
+ }
+
+ req = qmp_dispatch_check_obj(obj, &err);
+ if (err) {
+ goto end;
+ }
+
+ qmp_dispatch(session, req);
+
+end:
+ if (err) {
+ QDict *rsp = qdict_new();
+ qdict_put_obj(rsp, "error", qmp_build_error_object(err));
+ error_free(err);
+ session->return_cb(session, rsp);
+ QDECREF(rsp);
+ }
+ qobject_decref(obj);
+}
+
void qmp_session_init(QmpSession *session,
QmpCommandList *cmds, QmpDispatchReturn *return_cb)
{
assert(return_cb);
assert(!session->return_cb);
+ json_message_parser_init(&session->parser, qmp_json_parser_emit);
session->cmds = cmds;
session->return_cb = return_cb;
}
@@ -164,6 +195,7 @@ void qmp_session_destroy(QmpSession *session)
session->cmds = NULL;
session->return_cb = NULL;
+ json_message_parser_destroy(&session->parser);
}
void qmp_dispatch(QmpSession *session, QDict *req)
@@ -72,7 +72,6 @@ typedef struct GAPersistentState {
struct GAState {
QmpSession session;
- JSONMessageParser parser;
GMainLoop *main_loop;
GAChannel *channel;
bool virtio; /* fastpath to check for virtio to deal with poll() quirks */
@@ -589,42 +588,6 @@ static void dispatch_return_cb(QmpSession *session, QDict *rsp)
}
}
-/* handle requests/control events coming in over the channel */
-static void process_event(JSONMessageParser *parser, GQueue *tokens)
-{
- GAState *s = container_of(parser, GAState, parser);
- QObject *obj;
- QDict *req;
- Error *err = NULL;
-
- g_assert(s && parser);
-
- g_debug("process_event: called");
-
- obj = json_parser_parse_err(tokens, NULL, &err);
- if (err) {
- goto end;
- }
-
- req = qmp_dispatch_check_obj(obj, &err);
- if (err) {
- goto end;
- }
-
- g_debug("processing command");
- qmp_dispatch(&s->session, req);
-
-end:
- if (err) {
- QDict *rsp = qdict_new();
- qdict_put_obj(rsp, "error", qmp_build_error_object(err));
- error_free(err);
- dispatch_return_cb(&s->session, rsp);
- QDECREF(rsp);
- }
- qobject_decref(obj);
-}
-
/* false return signals GAChannel to close the current client connection */
static gboolean channel_event_cb(GIOCondition condition, gpointer data)
{
@@ -639,7 +602,7 @@ static gboolean channel_event_cb(GIOCondition condition, gpointer data)
case G_IO_STATUS_NORMAL:
buf[count] = 0;
g_debug("read data, count: %d, data: %s", (int)count, buf);
- json_message_parser_feed(&s->parser, (char *)buf, (int)count);
+ qmp_session_feed(&s->session, buf, count);
break;
case G_IO_STATUS_EOF:
g_debug("received EOF");
@@ -1307,7 +1270,6 @@ static int run_agent(GAState *s, 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);
- json_message_parser_init(&s->parser, process_event);
qmp_session_init(&s->session, &ga_commands, dispatch_return_cb);
#ifndef _WIN32
if (!register_signal_handlers()) {
@@ -1431,7 +1393,6 @@ end:
qmp_session_destroy(&s->session);
ga_command_state_cleanup_all(s->command_state);
ga_command_state_free(s->command_state);
- json_message_parser_destroy(&s->parser);
}
if (s->channel) {
ga_channel_free(s->channel);
Move JSON parser to QmpSession, and implement a simple handler to check the parsed tokens and call qmp_dispatch(). This is enough for a simple QMP client, like QGA. The QEMU monitor has more complicated handling of dispatching which will be adressed in following patch to benefit more common code. Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com> --- include/qapi/qmp/dispatch.h | 9 ++++++++ monitor.c | 7 ++----- qapi/qmp-dispatch.c | 32 +++++++++++++++++++++++++++++ qga/main.c | 41 +------------------------------------ 4 files changed, 44 insertions(+), 45 deletions(-)