Statistics
| Branch: | Revision:

root / qapi / qmp-dispatch.c @ e2d87bff

History | View | Annotate | Download (2.9 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 ab02ab2a Michael Roth
#include "error.h"
18 ab02ab2a Michael Roth
#include "error_int.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 ab02ab2a Michael Roth
        if (!error_is_set(errp) && ret == NULL) {
98 ab02ab2a Michael Roth
            ret = QOBJECT(qdict_new());
99 ab02ab2a Michael Roth
        }
100 ab02ab2a Michael Roth
        break;
101 ab02ab2a Michael Roth
    }
102 ab02ab2a Michael Roth
103 ab02ab2a Michael Roth
    QDECREF(args);
104 ab02ab2a Michael Roth
105 ab02ab2a Michael Roth
    return ret;
106 ab02ab2a Michael Roth
}
107 ab02ab2a Michael Roth
108 ab02ab2a Michael Roth
QObject *qmp_dispatch(QObject *request)
109 ab02ab2a Michael Roth
{
110 ab02ab2a Michael Roth
    Error *err = NULL;
111 ab02ab2a Michael Roth
    QObject *ret;
112 ab02ab2a Michael Roth
    QDict *rsp;
113 ab02ab2a Michael Roth
114 ab02ab2a Michael Roth
    ret = do_qmp_dispatch(request, &err);
115 ab02ab2a Michael Roth
116 ab02ab2a Michael Roth
    rsp = qdict_new();
117 ab02ab2a Michael Roth
    if (err) {
118 ab02ab2a Michael Roth
        qdict_put_obj(rsp, "error", error_get_qobject(err));
119 ab02ab2a Michael Roth
        error_free(err);
120 ab02ab2a Michael Roth
    } else if (ret) {
121 ab02ab2a Michael Roth
        qdict_put_obj(rsp, "return", ret);
122 ab02ab2a Michael Roth
    } else {
123 ab02ab2a Michael Roth
        QDECREF(rsp);
124 ab02ab2a Michael Roth
        return NULL;
125 ab02ab2a Michael Roth
    }
126 ab02ab2a Michael Roth
127 ab02ab2a Michael Roth
    return QOBJECT(rsp);
128 ab02ab2a Michael Roth
}