Statistics
| Branch: | Revision:

root / qapi / qmp-dispatch.c @ d34b867d

History | View | Annotate | Download (3.1 kB)

1
/*
2
 * Core Definitions for QAPI/QMP Dispatch
3
 *
4
 * Copyright IBM, Corp. 2011
5
 *
6
 * Authors:
7
 *  Anthony Liguori   <aliguori@us.ibm.com>
8
 *
9
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10
 * See the COPYING.LIB file in the top-level directory.
11
 *
12
 */
13

    
14
#include "qemu-objects.h"
15
#include "qapi/qmp-core.h"
16
#include "json-parser.h"
17
#include "error.h"
18
#include "error_int.h"
19
#include "qerror.h"
20

    
21
static QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp)
22
{
23
    const QDictEntry *ent;
24
    const char *arg_name;
25
    const QObject *arg_obj;
26
    bool has_exec_key = false;
27
    QDict *dict = NULL;
28

    
29
    if (qobject_type(request) != QTYPE_QDICT) {
30
        error_set(errp, QERR_QMP_BAD_INPUT_OBJECT,
31
                  "request is not a dictionary");
32
        return NULL;
33
    }
34

    
35
    dict = qobject_to_qdict(request);
36

    
37
    for (ent = qdict_first(dict); ent;
38
         ent = qdict_next(dict, ent)) {
39
        arg_name = qdict_entry_key(ent);
40
        arg_obj = qdict_entry_value(ent);
41

    
42
        if (!strcmp(arg_name, "execute")) {
43
            if (qobject_type(arg_obj) != QTYPE_QSTRING) {
44
                error_set(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute",
45
                          "string");
46
                return NULL;
47
            }
48
            has_exec_key = true;
49
        } else if (strcmp(arg_name, "arguments")) {
50
            error_set(errp, QERR_QMP_EXTRA_MEMBER, arg_name);
51
            return NULL;
52
        }
53
    }
54

    
55
    if (!has_exec_key) {
56
        error_set(errp, QERR_QMP_BAD_INPUT_OBJECT, "execute");
57
        return NULL;
58
    }
59

    
60
    return dict;
61
}
62

    
63
static QObject *do_qmp_dispatch(QObject *request, Error **errp)
64
{
65
    const char *command;
66
    QDict *args, *dict;
67
    QmpCommand *cmd;
68
    QObject *ret = NULL;
69

    
70

    
71
    dict = qmp_dispatch_check_obj(request, errp);
72
    if (!dict || error_is_set(errp)) {
73
        return NULL;
74
    }
75

    
76
    command = qdict_get_str(dict, "execute");
77
    cmd = qmp_find_command(command);
78
    if (cmd == NULL) {
79
        error_set(errp, QERR_COMMAND_NOT_FOUND, command);
80
        return NULL;
81
    }
82
    if (!cmd->enabled) {
83
        error_set(errp, QERR_COMMAND_DISABLED, command);
84
        return NULL;
85
    }
86

    
87
    if (!qdict_haskey(dict, "arguments")) {
88
        args = qdict_new();
89
    } else {
90
        args = qdict_get_qdict(dict, "arguments");
91
        QINCREF(args);
92
    }
93

    
94
    switch (cmd->type) {
95
    case QCT_NORMAL:
96
        cmd->fn(args, &ret, errp);
97
        if (!error_is_set(errp)) {
98
            if (cmd->options & QCO_NO_SUCCESS_RESP) {
99
                g_assert(!ret);
100
            } else if (!ret) {
101
                ret = QOBJECT(qdict_new());
102
            }
103
        }
104
        break;
105
    }
106

    
107
    QDECREF(args);
108

    
109
    return ret;
110
}
111

    
112
QObject *qmp_dispatch(QObject *request)
113
{
114
    Error *err = NULL;
115
    QObject *ret;
116
    QDict *rsp;
117

    
118
    ret = do_qmp_dispatch(request, &err);
119

    
120
    rsp = qdict_new();
121
    if (err) {
122
        qdict_put_obj(rsp, "error", error_get_qobject(err));
123
        error_free(err);
124
    } else if (ret) {
125
        qdict_put_obj(rsp, "return", ret);
126
    } else {
127
        QDECREF(rsp);
128
        return NULL;
129
    }
130

    
131
    return QOBJECT(rsp);
132
}