ecs: fix ecs monitor to work properly
authorJinhyung Choi <jinh0.choi@samsung.com>
Tue, 20 Dec 2016 10:19:57 +0000 (19:19 +0900)
committerSeokYeon Hwang <syeon.hwang@samsung.com>
Wed, 21 Dec 2016 09:30:23 +0000 (18:30 +0900)
Change-Id: I6a0275cec1253c35a2058e8627f8076a0b183653
Signed-off-by: Jinhyung Choi <jinh0.choi@samsung.com>
tizen/src/ecs/ecs_mon.c

index 9d94bae..8a492ea 100644 (file)
@@ -41,6 +41,7 @@
 #include "qapi/qmp/qjson.h"
 #include "qapi/qmp/json-parser.h"
 #include "qmp-introspect.h"
+#include "qapi/qmp/dispatch.h"
 
 #include "ecs.h"
 #include "hw/virtio/maru_virtio_evdi.h"
@@ -54,8 +55,7 @@ typedef struct mon_fd_t mon_fd_t;
 struct mon_fd_t {
     char *name;
     int fd;
-    QLIST_ENTRY(mon_fd_t)
-    next;
+    QLIST_ENTRY(mon_fd_t) next;
 };
 
 typedef struct mon_cmd_t {
@@ -63,10 +63,7 @@ typedef struct mon_cmd_t {
     const char *args_type;
     const char *params;
     const char *help;
-    union {
-        void (*cmd)(Monitor *mon, const QDict *qdict);
-        void (*cmd_new)(QDict *params, QObject **ret_data, Error **errp);
-    } mhandler;
+    void (*cmd)(Monitor *mon, const QDict *qdict);
     /* @sub_table is a list of 2nd level of commands. If it do not exist,
      * mhandler should be used. If it exist, sub_table[?].mhandler should be
      * used, and mhandler of 1st level plays the role of help function.
@@ -75,33 +72,6 @@ typedef struct mon_cmd_t {
     void (*command_completion)(ReadLineState *rs, int nb_args, const char *str);
 } mon_cmd_t;
 
-/*
-void send_to_client(int fd, const char *data, const int len)
-{
-    char c;
-    uint8_t outbuf[OUT_BUF_SIZE];
-    int outbuf_index = 0;
-
-    for (;;) {
-        c = *data++;
-        if (outbuf_index >= OUT_BUF_SIZE - 1) {
-            INFO("string is too long: overflow buffer.");
-            return;
-        }
-#ifndef _WIN32
-        if (c == '\n') {
-            outbuf[outbuf_index++] = '\r';
-        }
-#endif
-        outbuf[outbuf_index++] = c;
-        if (c == '\0') {
-            break;
-        }
-    }
-    ecs_write(fd, outbuf, outbuf_index);
-}
-*/
-
 #define QMP_ACCEPT_UNKNOWNS 1
 
 bool send_monitor_ntf(const char *data, int size)
@@ -203,12 +173,12 @@ static void ecs_protocol_emitter(ECS_Client *clii, const char *type,
 
     if (!err) {
         /* success response */
-        qmp = qdict_new();
         if (data) {
             qobject_incref(data);
-            qdict_put_obj(qmp, "return", data);
+            qmp = qobject_to_qdict(data);
         } else {
             /* return an empty QDict by default */
+            qmp = qdict_new();
             qdict_put(qmp, "return", qdict_new());
         }
 
@@ -228,194 +198,6 @@ static void ecs_protocol_emitter(ECS_Client *clii, const char *type,
     QDECREF(qmp);
 }
 
-static void ecs_qmp_call_cmd(ECS_Client *clii, Monitor *mon, const char *type,
-        const mon_cmd_t *cmd, QDict *params)
-{
-    QObject *data = NULL;
-    Error *local_err = NULL;
-
-    cmd->mhandler.cmd_new(params, &data, &local_err);
-    ecs_protocol_emitter(clii, type, data, local_err);
-    qobject_decref(data);
-}
-
-static void qmp_device_add(QDict *qdict, QObject **ret_data, Error **errp)
-{
-}
-
-static void qmp_capabilities(QDict *params, QObject **ret_data, Error **errp)
-{
-}
-
-static void qmp_query_qmp_schema(QDict *qdict, QObject **ret_data,
-                                 Error **errp)
-{
-    *ret_data = qobject_from_json(qmp_schema_json);
-}
-
-static const mon_cmd_t qmp_cmds[] = {
-#include "qmp-commands-old.h"
-        { /* NULL */}, };
-
-static void check_mandatory_args(const QDict *cmd_args, const QDict *client_args,
-        int *flags, Error **errp)
-{
-    const QDictEntry *ent;
-
-    for (ent = qdict_first(cmd_args); ent; ent = qdict_next(cmd_args, ent)) {
-        const char *cmd_arg_name = qdict_entry_key(ent);
-        QString *type = qobject_to_qstring(qdict_entry_value(ent));
-        assert(type != NULL);
-
-        if (qstring_get_str(type)[0] == 'O') {
-            assert((*flags & QMP_ACCEPT_UNKNOWNS) == 0);
-            *flags |= QMP_ACCEPT_UNKNOWNS;
-        } else if (qstring_get_str(type)[0] != '-'
-                && qstring_get_str(type)[1] != '?'
-                && !qdict_haskey(client_args, cmd_arg_name)) {
-            error_setg(errp, QERR_MISSING_PARAMETER, cmd_arg_name);
-            return;
-        }
-    }
-}
-
-static void check_client_args_type(const QDict *client_args,
-        const QDict *cmd_args, int flags, Error **errp)
-{
-    const QDictEntry *ent;
-
-    for (ent = qdict_first(client_args); ent;
-            ent = qdict_next(client_args, ent)) {
-        QObject *obj;
-        QString *arg_type;
-        const QObject *client_arg = qdict_entry_value(ent);
-        const char *client_arg_name = qdict_entry_key(ent);
-
-        obj = qdict_get(cmd_args, client_arg_name);
-        if (!obj) {
-            if (flags & QMP_ACCEPT_UNKNOWNS) {
-                continue;
-            }
-            error_setg(errp, QERR_INVALID_PARAMETER, client_arg_name);
-            return;
-        }
-
-        arg_type = qobject_to_qstring(obj);
-        assert(arg_type != NULL);
-
-        switch (qstring_get_str(arg_type)[0]) {
-        case 'F':
-        case 'B':
-        case 's':
-            if (qobject_type(client_arg) != QTYPE_QSTRING) {
-                error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
-                        client_arg_name, "string");
-                return;
-            }
-            break;
-        case 'i':
-        case 'l':
-        case 'M':
-        case 'o':
-            if (qobject_type(client_arg) != QTYPE_QINT) {
-                error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
-                        client_arg_name, "int");
-                return;
-            }
-            break;
-        case 'T':
-            if (qobject_type(client_arg) != QTYPE_QINT
-                    && qobject_type(client_arg) != QTYPE_QFLOAT) {
-                error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
-                        client_arg_name, "number");
-                return;
-            }
-            break;
-        case 'b':
-        case '-':
-            if (qobject_type(client_arg) != QTYPE_QBOOL) {
-                error_setg(errp, QERR_INVALID_PARAMETER_TYPE,
-                        client_arg_name, "bool");
-                return;
-            }
-            break;
-        case 'O':
-            assert(flags & QMP_ACCEPT_UNKNOWNS);
-            break;
-        case 'q':
-            break;
-        case '/':
-        case '.':
-        default:
-            abort();
-        }
-    }
-}
-
-static QDict *qdict_from_args_type(const char *args_type)
-{
-    int i;
-    QDict *qdict;
-    QString *key, *type, *cur_qs;
-
-    assert(args_type != NULL);
-
-    qdict = qdict_new();
-
-    if (args_type == NULL || args_type[0] == '\0') {
-        goto out;
-    }
-
-    key = qstring_new();
-    type = qstring_new();
-
-    cur_qs = key;
-
-    for (i = 0;; i++) {
-        switch (args_type[i]) {
-        case ',':
-        case '\0':
-            qdict_put(qdict, qstring_get_str(key), type);
-            QDECREF(key);
-            if (args_type[i] == '\0') {
-                goto out;
-            }
-            type = qstring_new();
-            cur_qs = key = qstring_new();
-            break;
-        case ':':
-            cur_qs = type;
-            break;
-        default:
-            qstring_append_chr(cur_qs, args_type[i]);
-            break;
-        }
-    }
-
-    out: return qdict;
-}
-
-static void qmp_check_client_args(const mon_cmd_t *cmd, QDict *client_args, Error **errp)
-{
-    Error *err = NULL;
-    int flags;
-    QDict *cmd_args;
-
-    cmd_args = qdict_from_args_type(cmd->args_type);
-
-    flags = 0;
-    check_mandatory_args(cmd_args, client_args, &flags, &err);
-    if (err) {
-        goto out;
-    }
-
-    check_client_args_type(client_args, cmd_args, flags, &err);
-
-out:
-    error_propagate(errp, err);
-    QDECREF(cmd_args);
-}
-
 static QDict *qmp_check_input_obj(QObject *input_obj, Error **errp)
 {
     const QDictEntry *ent;
@@ -464,112 +246,62 @@ static QDict *qmp_check_input_obj(QObject *input_obj, Error **errp)
     return input_dict;
 }
 
-static int compare_cmd(const char *name, const char *list)
-{
-    const char *p, *pstart;
-    int len;
-    len = strlen(name);
-    p = list;
-    for (;;) {
-        pstart = p;
-        p = strchr(p, '|');
-        if (!p) {
-            p = pstart + strlen(pstart);
-        }
-        if ((p - pstart) == len && !memcmp(pstart, name, len)) {
-            return 1;
-        }
-        if (*p == '\0') {
-            break;
-        }
-        p++;
-    }
-    return 0;
-}
-
-static const mon_cmd_t *search_dispatch_table(const mon_cmd_t *disp_table,
-        const char *cmdname)
-{
-    const mon_cmd_t *cmd;
-
-    for (cmd = disp_table; cmd->name != NULL; cmd++) {
-        if (compare_cmd(cmdname, cmd->name)) {
-            return cmd;
-        }
-    }
-
-    return NULL;
-}
-
-static const mon_cmd_t *qmp_find_cmd(const char *cmdname)
-{
-    return search_dispatch_table(qmp_cmds, cmdname);
-}
-
 void handle_qmp_command(JSONMessageParser *parser, GQueue *tokens,
         void *opaque)
 {
-    Error *local_err = NULL;
-    QObject *obj;
-    QDict *input, *args;
-    const mon_cmd_t *cmd;
-    const char *cmd_name;
-    const char *type_name;
-    Monitor *mon = cur_mon;
+    QObject *req, *rsp = NULL, *id = NULL;
+    QDict *qdict = NULL;
     ECS_Client *clii = opaque;
+    Error *err = NULL;
+    char* type = NULL;
 
-    args = input = NULL;
-
-    obj = json_parser_parse(tokens, NULL);
-    if (!obj) {
-        /* FIXME: should be triggered in json_parser_parse() */
-        error_setg(&local_err, QERR_JSON_PARSING);
+    req = json_parser_parse_err(tokens, NULL, &err);
+    if (err || !req || qobject_type(req) != QTYPE_QDICT) {
+        if (!err) {
+            error_setg(&err, QERR_JSON_PARSING);
+        }
         goto err_out;
     }
 
-    input = qmp_check_input_obj(obj, &local_err);
-    if (!input) {
-        qobject_decref(obj);
+    qdict = qmp_check_input_obj(req, &err);
+    if (!qdict) {
         goto err_out;
     }
 
-    cmd_name = qdict_get_str(input, "execute");
-#if 0
-    trace_handle_qmp_command(mon, cmd_name);
-#endif
+    id = qdict_get(qdict, "id");
+    qobject_incref(id);
+    qdict_del(qdict, "id");
 
-    cmd = qmp_find_cmd(cmd_name);
-    if (!cmd) {
-        error_set(&local_err, ERROR_CLASS_COMMAND_NOT_FOUND,
-            "The command %s has not been found", cmd_name);
-        goto err_out;
+    if (qdict_haskey(qdict, "type")) {
+        type = g_strdup(qdict_get_str(qdict, "type"));
+        qdict_del(qdict, "type");
     }
 
-    type_name = qdict_get_str(qobject_to_qdict(obj), COMMANDS_TYPE);
+    req = QOBJECT(qdict);
 
-    obj = qdict_get(input, "arguments");
-    if (!obj) {
-        args = qdict_new();
-    } else {
-        args = qobject_to_qdict(obj);
-        QINCREF(args);
-    }
+    rsp = qmp_dispatch(req);
 
-    qmp_check_client_args(cmd, args, &local_err);
-    if (local_err) {
-        goto err_out;
-    }
+    ecs_protocol_emitter(clii, (const char*)type, rsp, err);
 
-    ecs_qmp_call_cmd(clii, mon, type_name, cmd, args);
+    g_free(type);
+err_out:
+    if (err) {
+        qdict = qdict_new();
+        qdict_put_obj(qdict, "error", qmp_build_error_object(err));
+        error_free(err);
+        rsp = QOBJECT(qdict);
+    }
 
-    goto out;
+    if (rsp) {
+        if (id) {
+            qdict_put_obj(qobject_to_qdict(rsp), "id", id);
+            id = NULL;
+        }
+    }
 
-err_out:
-    ecs_protocol_emitter(clii, NULL, NULL, local_err);
-out:
-    error_free(local_err);
-    QDECREF(input);
-    QDECREF(args);
+    qobject_decref(id);
+    qobject_decref(rsp);
+    qobject_decref(req);
 }
 
 bool msgproc_monitor_req(ECS_Client *ccli, ECS__MonitorReq *msg)
@@ -578,3 +310,4 @@ bool msgproc_monitor_req(ECS_Client *ccli, ECS__MonitorReq *msg)
     ecs_json_message_parser_feed(&(ccli->parser), (const char *) msg->command, strlen(msg->command));
     return true;
 }
+