From ba5f0266130b6fe8e9910235d7cedd102bf839f0 Mon Sep 17 00:00:00 2001 From: Jinhyung Choi Date: Tue, 20 Dec 2016 19:19:57 +0900 Subject: [PATCH] ecs: fix ecs monitor to work properly Change-Id: I6a0275cec1253c35a2058e8627f8076a0b183653 Signed-off-by: Jinhyung Choi --- tizen/src/ecs/ecs_mon.c | 353 ++++++------------------------------------------ 1 file changed, 43 insertions(+), 310 deletions(-) diff --git a/tizen/src/ecs/ecs_mon.c b/tizen/src/ecs/ecs_mon.c index 9d94bae..8a492ea 100644 --- a/tizen/src/ecs/ecs_mon.c +++ b/tizen/src/ecs/ecs_mon.c @@ -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; } + -- 2.7.4