qemu/qapi/qmp-dispatch.c
<<
>>
Prefs
   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/osdep.h"
  15#include "qapi/error.h"
  16#include "qapi/qmp/types.h"
  17#include "qapi/qmp/dispatch.h"
  18#include "qapi/qmp/json-parser.h"
  19#include "qapi-types.h"
  20#include "qapi/qmp/qerror.h"
  21
  22static QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp)
  23{
  24    const QDictEntry *ent;
  25    const char *arg_name;
  26    const QObject *arg_obj;
  27    bool has_exec_key = false;
  28    QDict *dict = NULL;
  29
  30    if (qobject_type(request) != QTYPE_QDICT) {
  31        error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT,
  32                   "request is not a dictionary");
  33        return NULL;
  34    }
  35
  36    dict = qobject_to_qdict(request);
  37
  38    for (ent = qdict_first(dict); ent;
  39         ent = qdict_next(dict, ent)) {
  40        arg_name = qdict_entry_key(ent);
  41        arg_obj = qdict_entry_value(ent);
  42
  43        if (!strcmp(arg_name, "execute")) {
  44            if (qobject_type(arg_obj) != QTYPE_QSTRING) {
  45                error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute",
  46                           "string");
  47                return NULL;
  48            }
  49            has_exec_key = true;
  50        } else if (strcmp(arg_name, "arguments")) {
  51            error_setg(errp, QERR_QMP_EXTRA_MEMBER, arg_name);
  52            return NULL;
  53        }
  54    }
  55
  56    if (!has_exec_key) {
  57        error_setg(errp, QERR_QMP_BAD_INPUT_OBJECT, "execute");
  58        return NULL;
  59    }
  60
  61    return dict;
  62}
  63
  64static QObject *do_qmp_dispatch(QObject *request, Error **errp)
  65{
  66    Error *local_err = NULL;
  67    const char *command;
  68    QDict *args, *dict;
  69    QmpCommand *cmd;
  70    QObject *ret = NULL;
  71
  72    dict = qmp_dispatch_check_obj(request, errp);
  73    if (!dict) {
  74        return NULL;
  75    }
  76
  77    command = qdict_get_str(dict, "execute");
  78    cmd = qmp_find_command(command);
  79    if (cmd == NULL) {
  80        error_set(errp, ERROR_CLASS_COMMAND_NOT_FOUND,
  81                  "The command %s has not been found", command);
  82        return NULL;
  83    }
  84    if (!cmd->enabled) {
  85        error_setg(errp, "The command %s has been disabled for this instance",
  86                   command);
  87        return NULL;
  88    }
  89
  90    if (!qdict_haskey(dict, "arguments")) {
  91        args = qdict_new();
  92    } else {
  93        args = qdict_get_qdict(dict, "arguments");
  94        QINCREF(args);
  95    }
  96
  97    switch (cmd->type) {
  98    case QCT_NORMAL:
  99        cmd->fn(args, &ret, &local_err);
 100        if (local_err) {
 101            error_propagate(errp, local_err);
 102        } else if (cmd->options & QCO_NO_SUCCESS_RESP) {
 103            g_assert(!ret);
 104        } else if (!ret) {
 105            ret = QOBJECT(qdict_new());
 106        }
 107        break;
 108    }
 109
 110    QDECREF(args);
 111
 112    return ret;
 113}
 114
 115QObject *qmp_build_error_object(Error *err)
 116{
 117    return qobject_from_jsonf("{ 'class': %s, 'desc': %s }",
 118                              QapiErrorClass_lookup[error_get_class(err)],
 119                              error_get_pretty(err));
 120}
 121
 122QObject *qmp_dispatch(QObject *request)
 123{
 124    Error *err = NULL;
 125    QObject *ret;
 126    QDict *rsp;
 127
 128    ret = do_qmp_dispatch(request, &err);
 129
 130    rsp = qdict_new();
 131    if (err) {
 132        qdict_put_obj(rsp, "error", qmp_build_error_object(err));
 133        error_free(err);
 134    } else if (ret) {
 135        qdict_put_obj(rsp, "return", ret);
 136    } else {
 137        QDECREF(rsp);
 138        return NULL;
 139    }
 140
 141    return QOBJECT(rsp);
 142}
 143