From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from [140.186.70.92] (port=33664 helo=eggs.gnu.org) by lists.gnu.org with esmtp (Exim 4.43) id 1Q3Czr-00006A-U7 for qemu-devel@nongnu.org; Fri, 25 Mar 2011 15:48:38 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Q3Czn-0006Mw-B8 for qemu-devel@nongnu.org; Fri, 25 Mar 2011 15:48:32 -0400 Received: from e4.ny.us.ibm.com ([32.97.182.144]:51088) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Q3Czn-0006Ml-4i for qemu-devel@nongnu.org; Fri, 25 Mar 2011 15:48:31 -0400 Received: from d01dlp01.pok.ibm.com (d01dlp01.pok.ibm.com [9.56.224.56]) by e4.ny.us.ibm.com (8.14.4/8.13.1) with ESMTP id p2PJSreC020296 for ; Fri, 25 Mar 2011 15:28:53 -0400 Received: from d01relay01.pok.ibm.com (d01relay01.pok.ibm.com [9.56.227.233]) by d01dlp01.pok.ibm.com (Postfix) with ESMTP id D65C738C8038 for ; Fri, 25 Mar 2011 15:48:24 -0400 (EDT) Received: from d01av03.pok.ibm.com (d01av03.pok.ibm.com [9.56.224.217]) by d01relay01.pok.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p2PJmUsV382734 for ; Fri, 25 Mar 2011 15:48:30 -0400 Received: from d01av03.pok.ibm.com (loopback [127.0.0.1]) by d01av03.pok.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p2PJmUBN024952 for ; Fri, 25 Mar 2011 16:48:30 -0300 From: Michael Roth Date: Fri, 25 Mar 2011 14:47:56 -0500 Message-Id: <1301082479-4058-10-git-send-email-mdroth@linux.vnet.ibm.com> In-Reply-To: <1301082479-4058-1-git-send-email-mdroth@linux.vnet.ibm.com> References: <1301082479-4058-1-git-send-email-mdroth@linux.vnet.ibm.com> Subject: [Qemu-devel] [RFC][PATCH v1 09/12] guest agent: core marshal/dispatch interfaces List-Id: qemu-devel.nongnu.org List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: aliguori@linux.vnet.ibm.com, agl@linux.vnet.ibm.com, mdroth@linux.vnet.ibm.com, Jes.Sorensen@redhat.com These are basically a stripped-down, guest-side analogue to what's in qmp_core.c: definitions used by qmp-gen.py-generated marshalling code to handle dispatch and a registration of command->function mappings (minus all the bits related to Qmp sessions/server/events). As a result of that, there is a little bit of code duplication here. It wouldn't be difficult to make the common bits shareable, but there isn't much. The guest agent will use these interfaces to handle dispatch/execution of requests it gets from the proxy. Signed-off-by: Michael Roth --- guest-agent-core.c | 143 ++++++++++++++++++++++++++++++++++++++++++++++++++++ guest-agent-core.h | 21 ++++++++ 2 files changed, 164 insertions(+), 0 deletions(-) create mode 100644 guest-agent-core.c create mode 100644 guest-agent-core.h diff --git a/guest-agent-core.c b/guest-agent-core.c new file mode 100644 index 0000000..6c3b031 --- /dev/null +++ b/guest-agent-core.c @@ -0,0 +1,143 @@ +/* + * QEMU Guest Agent core functions + * + * Copyright IBM Corp. 2011 + * + * Authors: + * Adam Litke + * Michael Roth + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#include "guest-agent-core.h" + +typedef enum QmpCommandType +{ + QCT_NORMAL, + QCT_ASYNC, +} QmpCommandType; + +typedef struct QmpCommand +{ + const char *name; + QmpCommandType type; + QmpCommandFunc *fn; + QmpAsyncCommandFunc *afn; + QTAILQ_ENTRY(QmpCommand) node; +} QmpCommand; + +static QTAILQ_HEAD(, QmpCommand) qmp_commands = + QTAILQ_HEAD_INITIALIZER(qmp_commands); + +QmpMarshalState *qmp_state_get_mstate(QmpState *sess) +{ + return NULL; +} + +void qga_register_command(const char *name, QmpCommandFunc *fn) +{ + QmpCommand *cmd = qemu_mallocz(sizeof(*cmd)); + + cmd->name = name; + cmd->type = QCT_NORMAL; + cmd->fn = fn; + QTAILQ_INSERT_TAIL(&qmp_commands, cmd, node); +} + +static QmpCommand *qmp_find_command(const char *name) +{ + QmpCommand *i; + + QTAILQ_FOREACH(i, &qmp_commands, node) { + if (strcmp(i->name, name) == 0) { + return i; + } + } + return NULL; +} + +static QObject *qga_dispatch_err(QObject *request, Error **errp) +{ + const char *command; + QDict *args, *dict; + QmpCommand *cmd; + QObject *ret = NULL; + + if (qobject_type(request) != QTYPE_QDICT) { + error_set(errp, QERR_JSON_PARSE_ERROR, "request is not a dictionary"); + goto out; + } + + dict = qobject_to_qdict(request); + if (!qdict_haskey(dict, "execute")) { + error_set(errp, QERR_JSON_PARSE_ERROR, "no execute key"); + goto out; + } + + command = qdict_get_str(dict, "execute"); + cmd = qmp_find_command(command); + if (cmd == NULL) { + error_set(errp, QERR_COMMAND_NOT_FOUND, command); + goto out; + } + + 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(NULL, args, &ret, errp); + if (ret == NULL) { + ret = QOBJECT(qdict_new()); + } + break; + case QCT_ASYNC: { + QmpCommandState *s = qemu_mallocz(sizeof(*s)); + // FIXME save async commands and do something + // smart if disconnect occurs before completion + //s->state = state; + s->tag = NULL; + if (qdict_haskey(dict, "tag")) { + s->tag = qdict_get(dict, "tag"); + qobject_incref(s->tag); + } + cmd->afn(args, errp, s); + ret = NULL; + } + break; + } + + QDECREF(args); + +out: + qobject_decref(request); + + return ret; +} + +QObject *qga_dispatch(QObject *request, Error **errp) +{ + Error *err = NULL; + QObject *ret; + QDict *rsp; + + ret = qga_dispatch_err(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); +} diff --git a/guest-agent-core.h b/guest-agent-core.h new file mode 100644 index 0000000..18126b0 --- /dev/null +++ b/guest-agent-core.h @@ -0,0 +1,21 @@ +/* + * QEMU Guest Agent core declarations + * + * Copyright IBM Corp. 2011 + * + * Authors: + * Adam Litke + * Michael Roth + * + * This work is licensed under the terms of the GNU GPL, version 2 or later. + * See the COPYING file in the top-level directory. + */ +#include "qmp-core.h" +#include "qapi-types-core.h" +#include "qmp-marshal-types-core.h" +#include "qemu-common.h" +#include "qdict.h" + +QObject *qga_dispatch(QObject *obj, Error **errp); +void qga_register_command(const char *name, QmpCommandFunc *fn); +void qga_init_marshal(void); -- 1.7.0.4