root / qapi / qmp-dispatch.c @ dc1c13d9
History | View | Annotate | Download (3.3 kB)
1 | ab02ab2a | Michael Roth | /*
|
---|---|---|---|
2 | ab02ab2a | Michael Roth | * Core Definitions for QAPI/QMP Dispatch
|
3 | ab02ab2a | Michael Roth | *
|
4 | ab02ab2a | Michael Roth | * Copyright IBM, Corp. 2011
|
5 | ab02ab2a | Michael Roth | *
|
6 | ab02ab2a | Michael Roth | * Authors:
|
7 | ab02ab2a | Michael Roth | * Anthony Liguori <aliguori@us.ibm.com>
|
8 | ab02ab2a | Michael Roth | *
|
9 | ab02ab2a | Michael Roth | * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
|
10 | ab02ab2a | Michael Roth | * See the COPYING.LIB file in the top-level directory.
|
11 | ab02ab2a | Michael Roth | *
|
12 | ab02ab2a | Michael Roth | */
|
13 | ab02ab2a | Michael Roth | |
14 | ab02ab2a | Michael Roth | #include "qemu-objects.h" |
15 | ab02ab2a | Michael Roth | #include "qapi/qmp-core.h" |
16 | ab02ab2a | Michael Roth | #include "json-parser.h" |
17 | 93b91c59 | Luiz Capitulino | #include "qapi-types.h" |
18 | ab02ab2a | Michael Roth | #include "error.h" |
19 | ab02ab2a | Michael Roth | #include "qerror.h" |
20 | ab02ab2a | Michael Roth | |
21 | ab02ab2a | Michael Roth | static QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp) |
22 | ab02ab2a | Michael Roth | { |
23 | ab02ab2a | Michael Roth | const QDictEntry *ent;
|
24 | ab02ab2a | Michael Roth | const char *arg_name; |
25 | ab02ab2a | Michael Roth | const QObject *arg_obj;
|
26 | ab02ab2a | Michael Roth | bool has_exec_key = false; |
27 | ab02ab2a | Michael Roth | QDict *dict = NULL;
|
28 | ab02ab2a | Michael Roth | |
29 | ab02ab2a | Michael Roth | if (qobject_type(request) != QTYPE_QDICT) {
|
30 | ab02ab2a | Michael Roth | error_set(errp, QERR_QMP_BAD_INPUT_OBJECT, |
31 | ab02ab2a | Michael Roth | "request is not a dictionary");
|
32 | ab02ab2a | Michael Roth | return NULL; |
33 | ab02ab2a | Michael Roth | } |
34 | ab02ab2a | Michael Roth | |
35 | ab02ab2a | Michael Roth | dict = qobject_to_qdict(request); |
36 | ab02ab2a | Michael Roth | |
37 | ab02ab2a | Michael Roth | for (ent = qdict_first(dict); ent;
|
38 | ab02ab2a | Michael Roth | ent = qdict_next(dict, ent)) { |
39 | ab02ab2a | Michael Roth | arg_name = qdict_entry_key(ent); |
40 | ab02ab2a | Michael Roth | arg_obj = qdict_entry_value(ent); |
41 | ab02ab2a | Michael Roth | |
42 | ab02ab2a | Michael Roth | if (!strcmp(arg_name, "execute")) { |
43 | ab02ab2a | Michael Roth | if (qobject_type(arg_obj) != QTYPE_QSTRING) {
|
44 | ab02ab2a | Michael Roth | error_set(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute",
|
45 | ab02ab2a | Michael Roth | "string");
|
46 | ab02ab2a | Michael Roth | return NULL; |
47 | ab02ab2a | Michael Roth | } |
48 | ab02ab2a | Michael Roth | has_exec_key = true;
|
49 | ab02ab2a | Michael Roth | } else if (strcmp(arg_name, "arguments")) { |
50 | ab02ab2a | Michael Roth | error_set(errp, QERR_QMP_EXTRA_MEMBER, arg_name); |
51 | ab02ab2a | Michael Roth | return NULL; |
52 | ab02ab2a | Michael Roth | } |
53 | ab02ab2a | Michael Roth | } |
54 | ab02ab2a | Michael Roth | |
55 | ab02ab2a | Michael Roth | if (!has_exec_key) {
|
56 | ab02ab2a | Michael Roth | error_set(errp, QERR_QMP_BAD_INPUT_OBJECT, "execute");
|
57 | ab02ab2a | Michael Roth | return NULL; |
58 | ab02ab2a | Michael Roth | } |
59 | ab02ab2a | Michael Roth | |
60 | ab02ab2a | Michael Roth | return dict;
|
61 | ab02ab2a | Michael Roth | } |
62 | ab02ab2a | Michael Roth | |
63 | ab02ab2a | Michael Roth | static QObject *do_qmp_dispatch(QObject *request, Error **errp)
|
64 | ab02ab2a | Michael Roth | { |
65 | ab02ab2a | Michael Roth | const char *command; |
66 | ab02ab2a | Michael Roth | QDict *args, *dict; |
67 | ab02ab2a | Michael Roth | QmpCommand *cmd; |
68 | ab02ab2a | Michael Roth | QObject *ret = NULL;
|
69 | ab02ab2a | Michael Roth | |
70 | ab02ab2a | Michael Roth | |
71 | ab02ab2a | Michael Roth | dict = qmp_dispatch_check_obj(request, errp); |
72 | ab02ab2a | Michael Roth | if (!dict || error_is_set(errp)) {
|
73 | ab02ab2a | Michael Roth | return NULL; |
74 | ab02ab2a | Michael Roth | } |
75 | ab02ab2a | Michael Roth | |
76 | ab02ab2a | Michael Roth | command = qdict_get_str(dict, "execute");
|
77 | ab02ab2a | Michael Roth | cmd = qmp_find_command(command); |
78 | ab02ab2a | Michael Roth | if (cmd == NULL) { |
79 | ab02ab2a | Michael Roth | error_set(errp, QERR_COMMAND_NOT_FOUND, command); |
80 | ab02ab2a | Michael Roth | return NULL; |
81 | ab02ab2a | Michael Roth | } |
82 | abd6cf6d | Michael Roth | if (!cmd->enabled) {
|
83 | abd6cf6d | Michael Roth | error_set(errp, QERR_COMMAND_DISABLED, command); |
84 | abd6cf6d | Michael Roth | return NULL; |
85 | abd6cf6d | Michael Roth | } |
86 | ab02ab2a | Michael Roth | |
87 | ab02ab2a | Michael Roth | if (!qdict_haskey(dict, "arguments")) { |
88 | ab02ab2a | Michael Roth | args = qdict_new(); |
89 | ab02ab2a | Michael Roth | } else {
|
90 | ab02ab2a | Michael Roth | args = qdict_get_qdict(dict, "arguments");
|
91 | ab02ab2a | Michael Roth | QINCREF(args); |
92 | ab02ab2a | Michael Roth | } |
93 | ab02ab2a | Michael Roth | |
94 | ab02ab2a | Michael Roth | switch (cmd->type) {
|
95 | ab02ab2a | Michael Roth | case QCT_NORMAL:
|
96 | ab02ab2a | Michael Roth | cmd->fn(args, &ret, errp); |
97 | d34b867d | Luiz Capitulino | if (!error_is_set(errp)) {
|
98 | d34b867d | Luiz Capitulino | if (cmd->options & QCO_NO_SUCCESS_RESP) {
|
99 | d34b867d | Luiz Capitulino | g_assert(!ret); |
100 | d34b867d | Luiz Capitulino | } else if (!ret) { |
101 | d34b867d | Luiz Capitulino | ret = QOBJECT(qdict_new()); |
102 | d34b867d | Luiz Capitulino | } |
103 | ab02ab2a | Michael Roth | } |
104 | ab02ab2a | Michael Roth | break;
|
105 | ab02ab2a | Michael Roth | } |
106 | ab02ab2a | Michael Roth | |
107 | ab02ab2a | Michael Roth | QDECREF(args); |
108 | ab02ab2a | Michael Roth | |
109 | ab02ab2a | Michael Roth | return ret;
|
110 | ab02ab2a | Michael Roth | } |
111 | ab02ab2a | Michael Roth | |
112 | 93b91c59 | Luiz Capitulino | QObject *qmp_build_error_object(Error *errp) |
113 | 93b91c59 | Luiz Capitulino | { |
114 | 93b91c59 | Luiz Capitulino | return qobject_from_jsonf("{ 'class': %s, 'desc': %s }", |
115 | 93b91c59 | Luiz Capitulino | ErrorClass_lookup[error_get_class(errp)], |
116 | 93b91c59 | Luiz Capitulino | error_get_pretty(errp)); |
117 | 93b91c59 | Luiz Capitulino | } |
118 | 93b91c59 | Luiz Capitulino | |
119 | ab02ab2a | Michael Roth | QObject *qmp_dispatch(QObject *request) |
120 | ab02ab2a | Michael Roth | { |
121 | ab02ab2a | Michael Roth | Error *err = NULL;
|
122 | ab02ab2a | Michael Roth | QObject *ret; |
123 | ab02ab2a | Michael Roth | QDict *rsp; |
124 | ab02ab2a | Michael Roth | |
125 | ab02ab2a | Michael Roth | ret = do_qmp_dispatch(request, &err); |
126 | ab02ab2a | Michael Roth | |
127 | ab02ab2a | Michael Roth | rsp = qdict_new(); |
128 | ab02ab2a | Michael Roth | if (err) {
|
129 | 93b91c59 | Luiz Capitulino | qdict_put_obj(rsp, "error", qmp_build_error_object(err));
|
130 | ab02ab2a | Michael Roth | error_free(err); |
131 | ab02ab2a | Michael Roth | } else if (ret) { |
132 | ab02ab2a | Michael Roth | qdict_put_obj(rsp, "return", ret);
|
133 | ab02ab2a | Michael Roth | } else {
|
134 | ab02ab2a | Michael Roth | QDECREF(rsp); |
135 | ab02ab2a | Michael Roth | return NULL; |
136 | ab02ab2a | Michael Roth | } |
137 | ab02ab2a | Michael Roth | |
138 | ab02ab2a | Michael Roth | return QOBJECT(rsp);
|
139 | ab02ab2a | Michael Roth | } |