This repository was archived by the owner on May 5, 2021. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 28
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Given an object recieved via QMP, this code uses the dispatch table provided by qmp_registry.c to call the corresponding marshalling/dispatch function and format return values/errors for delivery to the QMP. Currently only synchronous QMP functions are supported, but this will also be used for async QMP functions and QMP guest proxy dispatch as well. Signed-off-by: Michael Roth <[email protected]> Signed-off-by: Luiz Capitulino <[email protected]>
- Loading branch information
1 parent
43c20a4
commit ab02ab2
Showing
3 changed files
with
127 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
/* | ||
* Core Definitions for QAPI/QMP Dispatch | ||
* | ||
* Copyright IBM, Corp. 2011 | ||
* | ||
* Authors: | ||
* Anthony Liguori <[email protected]> | ||
* | ||
* 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-objects.h" | ||
#include "qapi/qmp-core.h" | ||
#include "json-parser.h" | ||
#include "error.h" | ||
#include "error_int.h" | ||
#include "qerror.h" | ||
|
||
static QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp) | ||
{ | ||
const QDictEntry *ent; | ||
const char *arg_name; | ||
const QObject *arg_obj; | ||
bool has_exec_key = false; | ||
QDict *dict = NULL; | ||
|
||
if (qobject_type(request) != QTYPE_QDICT) { | ||
error_set(errp, QERR_QMP_BAD_INPUT_OBJECT, | ||
"request is not a dictionary"); | ||
return NULL; | ||
} | ||
|
||
dict = qobject_to_qdict(request); | ||
|
||
for (ent = qdict_first(dict); ent; | ||
ent = qdict_next(dict, ent)) { | ||
arg_name = qdict_entry_key(ent); | ||
arg_obj = qdict_entry_value(ent); | ||
|
||
if (!strcmp(arg_name, "execute")) { | ||
if (qobject_type(arg_obj) != QTYPE_QSTRING) { | ||
error_set(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute", | ||
"string"); | ||
return NULL; | ||
} | ||
has_exec_key = true; | ||
} else if (strcmp(arg_name, "arguments")) { | ||
error_set(errp, QERR_QMP_EXTRA_MEMBER, arg_name); | ||
return NULL; | ||
} | ||
} | ||
|
||
if (!has_exec_key) { | ||
error_set(errp, QERR_QMP_BAD_INPUT_OBJECT, "execute"); | ||
return NULL; | ||
} | ||
|
||
return dict; | ||
} | ||
|
||
static QObject *do_qmp_dispatch(QObject *request, Error **errp) | ||
{ | ||
const char *command; | ||
QDict *args, *dict; | ||
QmpCommand *cmd; | ||
QObject *ret = NULL; | ||
|
||
|
||
dict = qmp_dispatch_check_obj(request, errp); | ||
if (!dict || error_is_set(errp)) { | ||
return NULL; | ||
} | ||
|
||
command = qdict_get_str(dict, "execute"); | ||
cmd = qmp_find_command(command); | ||
if (cmd == NULL) { | ||
error_set(errp, QERR_COMMAND_NOT_FOUND, command); | ||
return NULL; | ||
} | ||
|
||
if (!qdict_haskey(dict, "arguments")) { | ||
args = qdict_new(); | ||
} else { | ||
args = qdict_get_qdict(dict, "arguments"); | ||
QINCREF(args); | ||
} | ||
|
||
switch (cmd->type) { | ||
case QCT_NORMAL: | ||
cmd->fn(args, &ret, errp); | ||
if (!error_is_set(errp) && ret == NULL) { | ||
ret = QOBJECT(qdict_new()); | ||
} | ||
break; | ||
} | ||
|
||
QDECREF(args); | ||
|
||
return ret; | ||
} | ||
|
||
QObject *qmp_dispatch(QObject *request) | ||
{ | ||
Error *err = NULL; | ||
QObject *ret; | ||
QDict *rsp; | ||
|
||
ret = do_qmp_dispatch(request, &err); | ||
|
||
rsp = qdict_new(); | ||
if (err) { | ||
qdict_put_obj(rsp, "error", error_get_qobject(err)); | ||
error_free(err); | ||
} else if (ret) { | ||
qdict_put_obj(rsp, "return", ret); | ||
} else { | ||
QDECREF(rsp); | ||
return NULL; | ||
} | ||
|
||
return QOBJECT(rsp); | ||
} |