Statistics
| Branch: | Revision:

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
}