Statistics
| Branch: | Revision:

root / qapi / qmp-dispatch.c @ e2d87bff

History | View | Annotate | Download (2.9 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) && ret == NULL) {
98
            ret = QOBJECT(qdict_new());
99
        }
100
        break;
101
    }
102

    
103
    QDECREF(args);
104

    
105
    return ret;
106
}
107

    
108
QObject *qmp_dispatch(QObject *request)
109
{
110
    Error *err = NULL;
111
    QObject *ret;
112
    QDict *rsp;
113

    
114
    ret = do_qmp_dispatch(request, &err);
115

    
116
    rsp = qdict_new();
117
    if (err) {
118
        qdict_put_obj(rsp, "error", error_get_qobject(err));
119
        error_free(err);
120
    } else if (ret) {
121
        qdict_put_obj(rsp, "return", ret);
122
    } else {
123
        QDECREF(rsp);
124
        return NULL;
125
    }
126

    
127
    return QOBJECT(rsp);
128
}