From patchwork Wed Jun 22 12:59:30 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Michael Roth X-Patchwork-Id: 101482 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 485B7B6F9A for ; Thu, 23 Jun 2011 00:16:56 +1000 (EST) Received: from localhost ([::1]:47392 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QZOEe-0006td-5n for incoming@patchwork.ozlabs.org; Wed, 22 Jun 2011 10:16:52 -0400 Received: from eggs.gnu.org ([140.186.70.92]:59625) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QZN3h-0004Mh-7P for qemu-devel@nongnu.org; Wed, 22 Jun 2011 09:01:31 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1QZN3f-0000d3-5s for qemu-devel@nongnu.org; Wed, 22 Jun 2011 09:01:29 -0400 Received: from mout.perfora.net ([74.208.4.194]:58734) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1QZN3e-0000cv-TZ for qemu-devel@nongnu.org; Wed, 22 Jun 2011 09:01:27 -0400 Received: from localhost.localdomain ([32.97.110.59]) by mrelay.perfora.net (node=mrus4) with ESMTP (Nemesis) id 0LoEnh-1REmPK3paj-00gEqi; Wed, 22 Jun 2011 09:01:22 -0400 From: Michael Roth To: qemu-devel@nongnu.org Date: Wed, 22 Jun 2011 07:59:30 -0500 Message-Id: <1308747579-23086-10-git-send-email-mdroth@linux.vnet.ibm.com> X-Mailer: git-send-email 1.7.0.4 In-Reply-To: <1308747579-23086-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1308747579-23086-1-git-send-email-mdroth@linux.vnet.ibm.com> X-Provags-ID: V02:K0:M55Z0d0M8HVipXiCbCQZxq8k33VLD9jJsnAxH0sGG0U gyjpM9HQqjX9rIIejjd6ePvdFCX7jRBuVsqlpIndJbGzqIL4Uw ss35mfJ9+9OQs79j99Vt0LcZ4ypNK4/pc2P7mBjeT9RmZ+nGJZ 2/w24dPRxhjK2GbbE5gJwwsaSlS/h4rn+6r9iIERf9huoXfQjE HZTRWX/2WQSu+ZAeBKpikCV+vcq2oxuk9eRTsFBw0o= X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 74.208.4.194 Cc: aliguori@linux.vnet.ibm.com, Jes.Sorensen@redhat.com, agl@linux.vnet.ibm.com, mdroth@linux.vnet.ibm.com, lcapitulino@redhat.com Subject: [Qemu-devel] [PATCH v4 09/18] qapi: add QMP dispatch functions X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Given an object recieved via QMP, this code uses the dispatch table provided by qmp_registry.c to call the corresponding marshalling/dispatch function and format return values/errors for delivery to the QMP. Currently only synchronous QMP functions are supported, but this will also be used for async QMP functions and QMP guest proxy dispatch as well. Signed-off-by: Michael Roth --- Makefile.objs | 2 +- qapi/qmp-core.h | 1 + qapi/qmp-dispatch.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 1 deletions(-) create mode 100644 qapi/qmp-dispatch.c diff --git a/Makefile.objs b/Makefile.objs index 092f314..7e82587 100644 --- a/Makefile.objs +++ b/Makefile.objs @@ -368,7 +368,7 @@ libcacard-y = cac.o event.o vcard.o vreader.o vcard_emul_nss.o vcard_emul_type.o # qapi qapi-nested-y = qapi-visit-core.o qmp-input-visitor.o qmp-output-visitor.o qapi-dealloc-visitor.o -qapi-nested-y += qmp-registry.o +qapi-nested-y += qmp-registry.o qmp-dispatch.o qapi-obj-y = $(addprefix qapi/, $(qapi-nested-y)) vl.o: QEMU_CFLAGS+=$(GPROF_CFLAGS) diff --git a/qapi/qmp-core.h b/qapi/qmp-core.h index 99e929f..f1c26e4 100644 --- a/qapi/qmp-core.h +++ b/qapi/qmp-core.h @@ -35,6 +35,7 @@ typedef struct QmpCommand void qmp_register_command(const char *name, QmpCommandFunc *fn); QmpCommand *qmp_find_command(const char *name); +QObject *qmp_dispatch(QObject *request); #endif diff --git a/qapi/qmp-dispatch.c b/qapi/qmp-dispatch.c new file mode 100644 index 0000000..5584693 --- /dev/null +++ b/qapi/qmp-dispatch.c @@ -0,0 +1,124 @@ +/* + * Core Definitions for QAPI/QMP Dispatch + * + * Copyright IBM, Corp. 2011 + * + * Authors: + * Anthony Liguori + * + * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. + * See the COPYING.LIB file in the top-level directory. + * + */ + +#include "qemu-objects.h" +#include "qapi/qmp-core.h" +#include "json-parser.h" +#include "error.h" +#include "error_int.h" +#include "qerror.h" + +static QDict *qmp_dispatch_check_obj(const QObject *request, Error **errp) +{ + const QDictEntry *ent; + const char *arg_name; + const QObject *arg_obj; + bool has_exec_key = false; + QDict *dict = NULL; + + if (qobject_type(request) != QTYPE_QDICT) { + error_set(errp, QERR_QMP_BAD_INPUT_OBJECT, + "request is not a dictionary"); + return NULL; + } + + dict = qobject_to_qdict(request); + + for (ent = qdict_first(dict); ent; + ent = qdict_next(dict, ent)) { + arg_name = qdict_entry_key(ent); + arg_obj = qdict_entry_value(ent); + + if (!strcmp(arg_name, "execute")) { + if (qobject_type(arg_obj) != QTYPE_QSTRING) { + error_set(errp, QERR_QMP_BAD_INPUT_OBJECT_MEMBER, "execute", + "string"); + return NULL; + } + has_exec_key = true; + } else if (strcmp(arg_name, "arguments")) { + error_set(errp, QERR_QMP_EXTRA_MEMBER, arg_name); + return NULL; + } + } + + if (!has_exec_key) { + error_set(errp, QERR_QMP_BAD_INPUT_OBJECT, "execute"); + return NULL; + } + + return dict; +} + +static QObject *do_qmp_dispatch(QObject *request, Error **errp) +{ + const char *command; + QDict *args, *dict; + QmpCommand *cmd; + QObject *ret = NULL; + + + dict = qmp_dispatch_check_obj(request, errp); + if (!dict || error_is_set(errp)) { + return NULL; + } + + command = qdict_get_str(dict, "execute"); + cmd = qmp_find_command(command); + if (cmd == NULL) { + error_set(errp, QERR_COMMAND_NOT_FOUND, command); + return NULL; + } + + if (!qdict_haskey(dict, "arguments")) { + args = qdict_new(); + } else { + args = qdict_get_qdict(dict, "arguments"); + QINCREF(args); + } + + switch (cmd->type) { + case QCT_NORMAL: + cmd->fn(args, &ret, errp); + if (!error_is_set(errp) && ret == NULL) { + ret = QOBJECT(qdict_new()); + } + break; + } + + QDECREF(args); + + return ret; +} + +QObject *qmp_dispatch(QObject *request) +{ + Error *err = NULL; + QObject *ret; + QDict *rsp; + + ret = do_qmp_dispatch(request, &err); + + rsp = qdict_new(); + if (err) { + qdict_put_obj(rsp, "error", error_get_qobject(err)); + error_free(err); + } else if (ret) { + qdict_put_obj(rsp, "return", ret); + } else { + QDECREF(rsp); + return NULL; + } + + return QOBJECT(rsp); +}