qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH v3 20/38] QmpSession: add json parser and use it in


From: Marc-André Lureau
Subject: [Qemu-devel] [PATCH v3 20/38] QmpSession: add json parser and use it in qga
Date: Mon, 26 Mar 2018 17:08:58 +0200

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 <address@hidden>
---
 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(-)

diff --git a/include/qapi/qmp/dispatch.h b/include/qapi/qmp/dispatch.h
index 7bf0b6a437..cd425b8574 100644
--- a/include/qapi/qmp/dispatch.h
+++ b/include/qapi/qmp/dispatch.h
@@ -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);
diff --git a/monitor.c b/monitor.c
index 93ecb03d04..66046d4854 100644
--- a/monitor.c
+++ b/monitor.c
@@ -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);
 
diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c
index 5274aa59cc..5352b25e90 100644
--- a/qapi/qmp-dispatch.c
+++ b/qapi/qmp-dispatch.c
@@ -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)
diff --git a/qga/main.c b/qga/main.c
index 46349395ba..ce7efff3b4 100644
--- a/qga/main.c
+++ b/qga/main.c
@@ -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);
-- 
2.17.0.rc1.1.g4c4f2b46a3




reply via email to

[Prev in Thread] Current Thread [Next in Thread]