+++ /dev/null
-/*
- * JSON streaming support
- *
- * Copyright IBM, Corp. 2009
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
-#include "ecs-json-streamer.h"
-
-#define MAX_TOKEN_SIZE (64ULL << 20)
-#define MAX_TOKEN_COUNT (2ULL << 20)
-#define MAX_NESTING (1ULL << 10)
-
-static void json_message_free_tokens(ECSJSONMessageParser *parser)
-{
- //TIZEN_VERIFY FIXME
- #if 0
- if (parser->tokens) {
- g_queue_free(parser->tokens);
- parser->tokens = NULL;
- }
- #endif
-}
-
-// TIZEN_VERIFY
-#if 0
-static void ecs_json_message_process_token(JSONLexer *lexer, GString *input,
- JSONTokenType type, int x, int y)
-{
- ECSJSONMessageParser *parser = container_of(lexer, ECSJSONMessageParser, lexer);
- JSONToken *token;
-
- switch (type) {
- case JSON_LCURLY:
- parser->brace_count++;
- break;
- case JSON_RCURLY:
- parser->brace_count--;
- break;
- case JSON_LSQUARE:
- parser->bracket_count++;
- break;
- case JSON_RSQUARE:
- parser->bracket_count--;
- break;
- default:
- break;
- }
-
- token = g_malloc(sizeof(JSONToken) + input->len + 1);
- token->type = type;
- memcpy(token->str, input->str, input->len);
- token->str[input->len] = 0;
- token->x = x;
- token->y = y;
-
- parser->token_size += input->len;
-
- g_queue_push_tail(parser->tokens, token);
-
- if (type == JSON_ERROR) {
- goto out_emit_bad;
- } else if (parser->brace_count < 0 ||
- parser->bracket_count < 0 ||
- (parser->brace_count == 0 &&
- parser->bracket_count == 0)) {
- goto out_emit;
- } else if (parser->token_size > MAX_TOKEN_SIZE ||
- g_queue_get_length(parser->tokens) > MAX_TOKEN_COUNT ||
- parser->bracket_count + parser->brace_count > MAX_NESTING) {
- /* Security consideration, we limit total memory allocated per object
- * and the maximum recursion depth that a message can force.
- */
- goto out_emit_bad;
- }
-
- return;
-
-out_emit_bad:
- /*
- * Clear out token list and tell the parser to emit an error
- * indication by passing it a NULL list
- */
- json_message_free_tokens(parser);
-out_emit:
- /* send current list of tokens to parser and reset tokenizer */
- parser->brace_count = 0;
- parser->bracket_count = 0;
- /* parser->emit takes ownership of parser->tokens. */
- parser->emit(parser, parser->tokens, parser->opaque);
- parser->tokens = g_queue_new();
- parser->token_size = 0;
-}
-#endif
-
-//TIZEN_VERIFY:
-void ecs_json_message_parser_init(ECSJSONMessageParser *parser,
- void (*emit)(void *opaque, QObject *json,
- Error *err),
- void *opaque, va_list *ap) {
- parser->emit = emit;
- parser->opaque = opaque;
- parser->ap = ap;
- parser->brace_count = 0;
- parser->bracket_count = 0;
- g_queue_init(&parser->tokens);
- parser->token_size = 0;
-
- json_lexer_init(&parser->lexer, !!ap);
-}
-
-
-int ecs_json_message_parser_feed(ECSJSONMessageParser *parser,
- const char *buffer, size_t size)
-{
- json_lexer_feed(&parser->lexer, buffer, size);
- return 0;
-}
-
-int ecs_json_message_parser_flush(ECSJSONMessageParser *parser)
-{
- json_lexer_flush(&parser->lexer);
- return 0;
-}
-
-void ecs_json_message_parser_destroy(ECSJSONMessageParser *parser)
-{
- json_lexer_destroy(&parser->lexer);
- json_message_free_tokens(parser);
-}
*
*/
-
-#include "qemu/osdep.h"
-#include "qemu-common.h"
+#include "emulator_common.h"
#include "qemu/queue.h"
#include "qemu/sockets.h"
#include "qemu/option.h"
#include "block/qdict.h"
#include "qapi/error.h"
#include "qapi/qmp/qjson.h"
+#include "qapi/qmp/qerror.h"
#include "qapi/qmp/qstring.h"
#include "qapi/qmp/json-parser.h"
#include "qapi/qmp/dispatch.h"
#include "debug_ch.h"
MULTI_DEBUG_CHANNEL(qemu, ecs);
-
-
-typedef struct mon_cmd_t {
- const char *name;
- const char *args_type;
- const char *params;
- const char *help;
- void (*cmd)(EcsMonitor *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.
- */
- struct mon_cmd_t *sub_table;
- void (*command_completion)(ReadLineState *rs, int nb_args, const char *str);
-} mon_cmd_t;
-
-#define QMP_ACCEPT_UNKNOWNS 1
-
bool send_monitor_ntf(const char *data, int size)
{
ECS__Master master = ECS__MASTER__INIT;
return true;
}
-#if 0
-static void ecs_monitor_flush(ECS_Client *clii, EcsMonitor *mon)
-{
- int ret;
- if (clii && 0 < clii->client_fd && mon && mon->outbuf_index != 0) {
-#if 0
- ret = ecs_write(clii->client_fd, mon->outbuf, mon->outbuf_index);
-#endif
- ret = send_monitor_ntf((char *)mon->outbuf, mon->outbuf_index);
- memset(mon->outbuf, 0, sizeof(mon->outbuf));
- mon->outbuf_index = 0;
+static void ecs_monitor_flush(Monitor *mon)
+{
+ if (mon && mon->outbuf != NULL) {
+ bool ret = send_monitor_ntf(qstring_get_str(mon->outbuf), qstring_get_length(mon->outbuf));
+ qstring_free(mon->outbuf, false);
+ mon->outbuf = NULL;
TRACE("ecs_monitor_flush return value of send_monitor_ntf : %d, \n", ret);
}
}
-static void ecs_monitor_puts(ECS_Client *clii, EcsMonitor *mon, const char *str)
+/* flush at every end of line */
+static void ecs_monitor_puts(Monitor *mon, const char *str)
{
+ int i;
char c;
- if (!clii || !mon) {
- return;
+ if (str == NULL) {
+ str = "\n";
}
- for (;;) {
- c = *str++;
- if (c == '\0') {
- break;
- }
-#ifndef _WIN32
+ LOG_INFO("ecs_monitor_puts - data: %s", str);
+
+ for (i = 0; str[i]; i++) {
+ c = str[i];
if (c == '\n') {
- mon->outbuf[mon->outbuf_index++] = '\r';
+#ifdef _WIN32
+ qstring_append_chr(mon->outbuf, '\r');
+#endif // _WIN32
}
-#endif
- mon->outbuf[mon->outbuf_index++] = c;
- if (mon->outbuf_index >= (sizeof(mon->outbuf) - 2) || c == '\n') {
- mon->outbuf[mon->outbuf_index++] = 0;
- ecs_monitor_flush(clii, mon);
+ qstring_append_chr(mon->outbuf, c);
+ if (c == '\n') {
+ ecs_monitor_flush(mon);
}
}
}
static QDict *build_qmp_error_dict(Error *err)
{
- //TIZEN_VERIFY
- QDict *rsp;
-
- rsp = qdict_from_jsonf_nofail("{ 'error': { 'class': %s, 'desc': %s } }",
+ QDict *rsp = qdict_from_jsonf_nofail("{ 'error': { 'class': %s, 'desc': %s } }",
QapiErrorClass_str(error_get_class(err)),
error_get_pretty(err));
- error_free(err);
return rsp;
}
-static void ecs_json_emitter(ECS_Client *clii, const QObject *data)
+#if 0
+static void ecs_json_emitter(Monitor *mon, const QObject *data)
{
QString *json;
assert(json != NULL);
qstring_append_chr(json, '\n');
- ecs_monitor_puts(clii, clii->cs->mon, qstring_get_str(json));
+ ecs_monitor_puts(mon, qstring_get_str(json));
qobject_unref(json);
}
-static void ecs_protocol_emitter(ECS_Client *clii, const char *type,
+static void ecs_protocol_emitter(Monitor *mon, const char *type,
QObject *data, Error *err)
{
- QDict *qmp;
+ QDict *qmp = NULL;
QObject *obj;
TRACE("ecs_protocol_emitter called.\n");
-#if 0
- trace_monitor_protocol_emitter(clii->cs->mon);
-#endif
-
if (!err) {
/* success response */
if (data) {
qmp = build_qmp_error_dict(err);
}
- ecs_json_emitter(clii, QOBJECT(qmp));
+ ecs_json_emitter(mon, QOBJECT(qmp));
qobject_unref(qmp);
}
-
+#endif //0
static QDict *qmp_check_input_obj(QObject *input_obj, Error **errp)
{
const QDictEntry *ent;
input_dict = qobject_to(QDict, input_obj);
+
for (ent = qdict_first(input_dict); ent;
ent = qdict_next(input_dict, ent)) {
const char *arg_name = qdict_entry_key(ent);
return input_dict;
}
-#endif
-//TIZEN_VERIFY
-#if 0
-/*
- * Emit QMP response @rsp to @mon.
- * Null @rsp can only happen for commands with QCO_NO_SUCCESS_RESP.
- * Nothing is emitted then.
- */
static void ecs_monitor_qmp_respond(MonitorQMP *mon, QDict *rsp)
{
- if (rsp) {
- qmp_send_response(mon, rsp);
+ const QObject *data = QOBJECT(rsp);
+ QString *json;
+
+ //Add type in response
+ if (mon->common.outbuf) {
+ qdict_put(rsp, "type", mon->common.outbuf);
+ qstring_free(mon->common.outbuf , false);
+ mon->common.outbuf = NULL;
+ } else {
+ qdict_put_str(rsp, "type", "unknown");
}
+
+ json = mon->pretty ? qobject_to_json_pretty(data) : qobject_to_json(data);
+ assert(json != NULL);
+
+ qstring_append_chr(json, '\n');
+ ecs_monitor_puts(&mon->common, qstring_get_str(json));
+
+ qobject_unref(json);
+}
+
+static bool ecs_qmp_oob_enabled(MonitorQMP *mon)
+{
+ return mon->capab[QMP_CAPABILITY_OOB];
}
-#endif
static void ecs_monitor_qmp_dispatch(MonitorQMP *mon, QObject *req)
{
- //TIZEN_VERIFY. FIXME: Uncomment
- #if 0
- EcsMonitor *old_mon;
+ Monitor *old_mon;
QDict *rsp;
QDict *error;
old_mon = cur_mon;
cur_mon = &mon->common;
- rsp = qmp_dispatch(mon->commands, req, qmp_oob_enabled(mon));
+ rsp = qmp_dispatch(mon->commands, req, ecs_qmp_oob_enabled(mon));
cur_mon = old_mon;
ecs_monitor_qmp_respond(mon, rsp);
qobject_unref(rsp);
- #endif
-}
-
-static bool ecs_qmp_oob_enabled(MonitorQMP *mon)
-{
- return mon->capab[QMP_CAPABILITY_OOB];
}
void ecs_handle_qmp_command(void *opaque, QObject *req, Error *err)
{
- MonitorQMP *mon = opaque;
+ ECS_Client* ccli = opaque;
+ MonitorQMP *mon = ccli->cs->mon;
QObject *id = NULL;
QDict *qdict;
- QMPRequest *req_obj;
-
+ Error *local_err = NULL;
+
assert(!req != !err);
- qdict = qobject_to(QDict, req);
+ if (err) {
+ local_err = err;
+ goto out_err;
+ }
+
+ qdict = qmp_check_input_obj(req, &local_err);
+
+ if (local_err) {
+ goto out_err;
+ }
if (qdict) {
id = qdict_get(qdict, "id");
+ if (qdict_haskey(qdict, "type")) {
+ //store type in outbuf to return in response
+ mon->common.outbuf = qobject_to(QString, qdict_get(qdict, "type"));
+ qdict_del(qdict, "type");
+ }
} /* else will fail qmp_dispatch() */
if (req && trace_event_get_state_backends(TRACE_HANDLE_QMP_COMMAND)) {
qobject_unref(req_json);
}
- if (qdict && qmp_is_oob(qdict)) {
- /* OOB commands are executed immediately */
+ if (qdict) {
+ /* Consider all commands OOB, OOB commands are executed immediately */
trace_monitor_qmp_cmd_out_of_band(qobject_get_try_str(id) ?: "");
ecs_monitor_qmp_dispatch(mon, req);
qobject_unref(req);
return;
}
+out_err:
- req_obj = g_new0(QMPRequest, 1);
- req_obj->mon = mon;
- req_obj->req = req;
- req_obj->err = err;
-
- /* Protect qmp_requests and fetching its length. */
- qemu_mutex_lock(&mon->qmp_queue_lock);
-
- /*
- * Suspend the monitor when we can't queue more requests after
- * this one. Dequeuing in monitor_qmp_bh_dispatcher() or
- * monitor_qmp_cleanup_queue_and_resume() will resume it.
- * Note that when OOB is disabled, we queue at most one command,
- * for backward compatibility.
- */
- if (!ecs_qmp_oob_enabled(mon) ||
- mon->qmp_requests->length == QMP_REQ_QUEUE_LEN_MAX - 1) {
- monitor_suspend(&mon->common);
- }
-
- /*
- * Put the request to the end of queue so that requests will be
- * handled in time order. Ownership for req_obj, req,
- * etc. will be delivered to the handler side.
- */
- assert(mon->qmp_requests->length < QMP_REQ_QUEUE_LEN_MAX);
- g_queue_push_tail(mon->qmp_requests, req_obj);
- qemu_mutex_unlock(&mon->qmp_queue_lock);
-
- /* Kick the dispatcher routine */
- qemu_bh_schedule(qmp_dispatcher_bh);
- /*
- QObject *req, *rsp = NULL, *id = NULL;
- QDict *qdict = NULL;
- ECS_Client *clii = opaque;
- Error *err = NULL;
- char* type = NULL;
-
- req = json_parser_parse(tokens, NULL, &err);
- if (err || !req || qobject_type(req) != QTYPE_QDICT) {
- if (!err) {
- error_setg(&err, QERR_JSON_PARSING);
- }
- goto err_out;
- }
-
- qdict = qmp_check_input_obj(req, &err);
- if (!qdict) {
- goto err_out;
+ //emit error response
+ if (local_err) {
+ qdict = build_qmp_error_dict(local_err);
+ ecs_monitor_qmp_respond(mon, qdict);
+ error_free(local_err);
}
-
- id = qdict_get(qdict, "id");
- qobject_ref(id);
- qdict_del(qdict, "id");
-
- if (qdict_haskey(qdict, "type")) {
- type = g_strdup(qdict_get_str(qdict, "type"));
- qdict_del(qdict, "type");
- }
-
- req = QOBJECT(qdict);
-
- rsp = qmp_dispatch(req);
-
- ecs_protocol_emitter(clii, (const char*)type, rsp, err);
-
- g_free(type);
-err_out:
- if (err) {
- //TIZEN_VERIFY
- rsp = qmp_error_response(err);
- }
-
- if (rsp) {
- if (id) {
- qdict_put_obj(qobject_to(QDict, rsp), "id", id);
- id = NULL;
- }
- }
-
- qobject_unref(id);
- qobject_unref(rsp);
- qobject_unref(req);*/
}
bool msgproc_monitor_req(ECS_Client *ccli, ECS__MonitorReq *msg)
{
TRACE(">> monitor req: data = %s\n", msg->command);
- ecs_json_message_parser_feed(&(ccli->parser), (const char *) msg->command, strlen(msg->command));
+ json_message_parser_feed(&(ccli->parser), (const char *) msg->command, strlen(msg->command));
return true;
}