qmp-dispatch.c 3.7 KB

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