From a281f4b69286d8621f4b53764772f3a5f08a1f7a Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Wed, 2 Jan 2019 19:23:18 +0100 Subject: [PATCH] plugin: Send jsonrpc_request when calling hooks and dispatch results This ties all the things together, using the serializer to transform the payload into a valid `jsonrpc_request`, sending it to the plugin, and then using the deserializer on the way back before calling the hook callback with the appropriate information. Notice that the serializer and deserializer is skipped if we don't have a plugin that registered for this hook. Signed-off-by: Christian Decker --- lightningd/plugin_hook.c | 49 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/lightningd/plugin_hook.c b/lightningd/plugin_hook.c index df163f66e..1040a41e6 100644 --- a/lightningd/plugin_hook.c +++ b/lightningd/plugin_hook.c @@ -1,5 +1,14 @@ +#include +#include #include +/* Struct containing all the information needed to deserialize and + * dispatch an eventual plugin_hook response. */ +struct plugin_hook_request { + const struct plugin_hook *hook; + void *cb_arg; +}; + static struct plugin_hook *plugin_hook_by_name(const char *name) { static struct plugin_hook **hooks = NULL; @@ -30,7 +39,47 @@ bool plugin_hook_register(struct plugin *plugin, const char *method) /* FIXME(cdecker): Remove dummy hook, once we have a real one */ REGISTER_PLUGIN_HOOK(hello, NULL, void *, NULL, void *, NULL, void *); +/** + * Callback to be passed to the jsonrpc_request. + * + * Unbundles the arguments, deserializes the response and dispatches + * it to the hook callback. + */ +static void plugin_hook_callback(const char *buffer, const jsmntok_t *toks, + const jsmntok_t *idtok, + struct plugin_hook_request *r) +{ + const jsmntok_t *resulttok = json_get_member(buffer, toks, "result"); + void *response = r->hook->deserialize_response(r, buffer, resulttok); + r->hook->response_cb(r->cb_arg, response); + tal_free(r); +} + void plugin_hook_call_(struct lightningd *ld, const struct plugin_hook *hook, void *payload, void *cb_arg) { + struct jsonrpc_request *req; + struct plugin_hook_request *ph_req; + if (hook->plugin) { + /* If we have a plugin that has registered for this + * hook, serialize and call it */ + /* FIXME: technically this is a leak, but we don't + * currently have a list to store these. We might want + * to eventually to inspect in-flight requests. */ + ph_req = notleak(tal(hook->plugin, struct plugin_hook_request)); + req = jsonrpc_request_start(NULL, hook->name, + plugin_hook_callback, ph_req); + ph_req->hook = hook; + ph_req->cb_arg = cb_arg; + hook->serialize_payload(payload, req->stream); + jsonrpc_request_end(req); + plugin_request_send(hook->plugin, req); + } else { + /* If no plugin has registered for this hook, just + * call the callback with a NULL result. Saves us the + * roundtrip to the serializer and deserializer. If we + * were expecting a default response it should have + * been part of the `cb_arg`. */ + hook->response_cb(cb_arg, NULL); + } }