From 7c93cf00bbaeb75057b9eae04437204062074061 Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Fri, 23 Nov 2018 00:38:51 +0100 Subject: [PATCH] plugin: Dispatch incoming RPC calls to appropriate plugin Signed-off-by: Christian Decker <@cdecker> --- lightningd/plugin.c | 77 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 74 insertions(+), 3 deletions(-) diff --git a/lightningd/plugin.c b/lightningd/plugin.c index d3ea17325..f2114cfa9 100644 --- a/lightningd/plugin.c +++ b/lightningd/plugin.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include @@ -72,6 +73,20 @@ struct json_output { const char *json; }; +/* Represents a pending JSON-RPC request that was forwarded to a + * plugin and is currently waiting for it to return the result. */ +struct plugin_rpc_request { + /* The json-serialized ID as it was passed to us by the + * client, will be used to return the result */ + const char *id; + + const char *method; + const char *params; + + struct plugin *plugin; + struct command *cmd; +}; + /* Simple storage for plugin options inbetween registering them on the * command line and passing them off to the plugin */ struct plugin_opt { @@ -399,12 +414,68 @@ static void plugin_rpcmethod_destroy(struct json_command *cmd, jsonrpc_command_remove(rpc, cmd->name); } +static void plugin_rpcmethod_cb(const struct plugin_request *req, + struct plugin_rpc_request *rpc_req) +{ + // Parse + // Extract results or error + // Construct reply + // Return result with appropriate return code. +} + static void plugin_rpcmethod_dispatch(struct command *cmd, const char *buffer, const jsmntok_t *params) { - // FIXME: We could avoid parsing the buffer again if we were - // to also pass in the method name. - cmd->usage = "[params]"; + const jsmntok_t *toks = params, *methtok, *idtok; + struct plugin_rpc_request *request; + struct plugins *plugins = cmd->ld->plugins; + struct plugin *plugin; + + if (cmd->mode == CMD_USAGE) { + cmd->usage = "[params]"; + return; + } + + /* We're given the params, but we need to walk back to the + * root object, so just walk backwards until the current + * element has no parents, that's going to be the root + * element. */ + while (toks->parent != -1) + toks--; + + methtok = json_get_member(buffer, toks, "method"); + idtok = json_get_member(buffer, toks, "id"); + /* We've parsed them before, these should not fail! */ + assert(idtok != NULL && methtok != NULL); + + request = tal(NULL, struct plugin_rpc_request); + request->method = tal_strndup(request, buffer + methtok->start, + methtok->end - methtok->start); + request->id = tal_strndup(request, buffer + idtok->start, + idtok->end - idtok->start); + request->params = tal_strndup(request, buffer + params->start, + params->end - params->start); + request->plugin = NULL; + request->cmd = cmd; + + /* Find the plugin that registered this RPC call */ + list_for_each(&plugins->plugins, plugin, list) { + for (size_t i=0; imethods); i++) { + if (streq(request->method, plugin->methods[i])) { + request->plugin = plugin; + goto found; + } + } + } + +found: + /* This should never happen, it'd mean that a plugin didn't + * cleanup after dying */ + assert(request->plugin); + + tal_steal(request->plugin, request); + plugin_request_send(request->plugin, request->method, request->params, plugin_rpcmethod_cb, request); + command_still_pending(cmd); }