On Mon, Apr 18, 2011 at 4:02 PM, Michael Roth <mdr...@linux.vnet.ibm.com> wrote: > +static int qmp_proxy_cancel_request(QmpProxy *p, QmpProxyRequest *r) > +{ > + if (r && r->cb) { > + r->cb(r->opaque, NULL, NULL); > + } > + > + return 0; > +} > + > +static int qmp_proxy_cancel_all(QmpProxy *p) > +{ > + QmpProxyRequest *r, *tmp; > + QTAILQ_FOREACH_SAFE(r, &p->requests, entry, tmp) { > + qmp_proxy_cancel_request(p, r); > + QTAILQ_REMOVE(&p->requests, r, entry); > + } > + > + return 0; > +}
qmp_proxy_cancel_all() will remove requests from the list. qmp_proxy_cancel_request() will not remove it from the list. This could cause confusion in the future if someone adds a call to qmp_proxy_cancel_request() without realizing that it will not remove the request from the list. The two function's names are similar, it would be nice if they acted the same way. > +static void qmp_proxy_process_event(JSONMessageParser *parser, QList *tokens) > +{ > + QmpProxy *p = container_of(parser, QmpProxy, parser); > + QmpProxyRequest *r; > + QObject *obj; > + QDict *qdict; > + Error *err = NULL; > + > + fprintf(stderr, "qmp proxy: called\n"); > + obj = json_parser_parse_err(tokens, NULL, &err); > + if (!obj) { > + fprintf(stderr, "qmp proxy: failed to parse\n"); > + return; > + } else { > + fprintf(stderr, "qmp proxy: parse successful\n"); > + qdict = qobject_to_qdict(obj); > + } > + > + if (qdict_haskey(qdict, "_control_event")) { > + /* handle transport-level control event */ > + qmp_proxy_process_control_event(p, qdict); > + } else if (qdict_haskey(qdict, "return")) { > + /* handle proxied qmp command response */ > + fprintf(stderr, "received return\n"); > + r = QTAILQ_FIRST(&p->requests); > + if (!r) { > + fprintf(stderr, "received return, but no request queued\n"); QDECREF(qdict)? > + return; > + } > + /* XXX: can't assume type here */ > + fprintf(stderr, "recieved response for cmd: %s\nreturn: %s\n", > + r->name, qstring_get_str(qobject_to_json(QOBJECT(qdict)))); > + r->cb(r->opaque, qdict_get(qdict, "return"), NULL); > + QTAILQ_REMOVE(&p->requests, r, entry); > + qemu_free(r); > + fprintf(stderr, "done handling response\n"); > + } else { > + fprintf(stderr, "received invalid payload format\n"); > + } > + > + QDECREF(qdict); > +} > +void qmp_proxy_send_request(QmpProxy *p, const char *name, > + const QDict *args, Error **errp, > + QmpGuestCompletionFunc *cb, void *opaque) > +{ > + QmpProxyRequest *r = qemu_mallocz(sizeof(QmpProxyRequest)); > + QDict *payload = qdict_new(); > + QString *json; > + > + /* TODO: don't really need to hold on to name/args after encoding */ > + r->name = name; > + r->args = args; > + r->cb = cb; > + r->opaque = opaque; > + > + qdict_put_obj(payload, "execute", QOBJECT(qstring_from_str(r->name))); > + /* TODO: casting a const so we can add it to our dictionary. bad. */ > + qdict_put_obj(payload, "arguments", QOBJECT((QDict *)args)); > + > + json = qobject_to_json(QOBJECT((QDict *)payload)); > + if (!json) { > + goto out_bad; > + } > + > + QTAILQ_INSERT_TAIL(&p->requests, r, entry); > + g_string_append(p->tx, qstring_get_str(json)); > + QDECREF(json); > + qmp_proxy_write(p); > + return; > + > +out_bad: > + cb(opaque, NULL, NULL); > + qemu_free(r); Need to free payload? > +} > + > +QmpProxy *qmp_proxy_new(CharDriverState *chr) > +{ > + QmpProxy *p = qemu_mallocz(sizeof(QmpProxy)); > + > + signal_init(&guest_agent_up_event); > + signal_init(&guest_agent_reset_event); > + > + /* there's a reason for this madness */ Helpful comment :) > + p->tx_timer = qemu_new_timer(rt_clock, qmp_proxy_write_handler, p); > + p->tx_timer_interval = 10; > + p->tx = g_string_new(""); > + p->chr = chr; > + json_message_parser_init(&p->parser, qmp_proxy_process_event); > + QTAILQ_INIT(&p->requests); > + > + return p; > +} > + > +void qmp_proxy_close(QmpProxy *p) > +{ > + qmp_proxy_cancel_all(p); > + g_string_free(p->tx, TRUE); Free tx_timer? > + qemu_free(p); > +}