From b8584a744b06faf9a5add23edaf10e4e81463a1b Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Fri, 28 Dec 2018 21:23:08 +0100 Subject: [PATCH] plugin: Add hooks that a plugin might register This is the first use of the `hooks` autodata field, and it required a dummy element in order for the section not to be dropped, it'll be removed once we have actual hooks. --- lightningd/plugin.c | 34 ++++++++++++++++++++++++++++++---- lightningd/plugin_hook.c | 30 ++++++++++++++++++++++++++++++ lightningd/plugin_hook.h | 2 +- 3 files changed, 61 insertions(+), 5 deletions(-) diff --git a/lightningd/plugin.c b/lightningd/plugin.c index ce792d5de..c4fae8aec 100644 --- a/lightningd/plugin.c +++ b/lightningd/plugin.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include #include @@ -787,6 +788,30 @@ static bool plugin_subscriptions_add(struct plugin *plugin, const char *buffer, return true; } +static bool plugin_hooks_add(struct plugin *plugin, const char *buffer, + const jsmntok_t *resulttok) +{ + const jsmntok_t *hookstok = json_get_member(buffer, resulttok, "hooks"); + if (!hookstok) + return true; + + for (int i = 0; i < hookstok->size; i++) { + char *name = json_strdup(NULL, plugin->buffer, + json_get_arr(hookstok, i)); + if (!plugin_hook_register(plugin, name)) { + plugin_kill(plugin, + "could not register hook '%s', either the " + "name doesn't exist or another plugin " + "already registered it.", + name); + tal_free(name); + return false; + } + tal_free(name); + } + return true; +} + static void plugin_manifest_timeout(struct plugin *plugin) { log_broken(plugin->log, "The plugin failed to respond to \"getmanifest\" in time, terminating."); @@ -816,12 +841,13 @@ static void plugin_manifest_cb(const char *buffer, return; } - if (!plugin_opts_add(plugin, buffer, resulttok) - || !plugin_rpcmethods_add(plugin, buffer, resulttok) - || !plugin_subscriptions_add(plugin, buffer, resulttok)) + if (!plugin_opts_add(plugin, buffer, resulttok) || + !plugin_rpcmethods_add(plugin, buffer, resulttok) || + !plugin_subscriptions_add(plugin, buffer, resulttok) || + !plugin_hooks_add(plugin, buffer, resulttok)) plugin_kill( plugin, - "Failed to register options, methods, or subscriptions."); + "Failed to register options, methods, hooks, or subscriptions."); /* Reset timer, it'd kill us otherwise. */ tal_free(plugin->timeout_timer); } diff --git a/lightningd/plugin_hook.c b/lightningd/plugin_hook.c index 728b3d336..df163f66e 100644 --- a/lightningd/plugin_hook.c +++ b/lightningd/plugin_hook.c @@ -1,5 +1,35 @@ #include +static struct plugin_hook *plugin_hook_by_name(const char *name) +{ + static struct plugin_hook **hooks = NULL; + static size_t num_hooks; + if (!hooks) + hooks = autodata_get(hooks, &num_hooks); + + for (size_t i=0; iname, name)) + return hooks[i]; + return NULL; +} + +bool plugin_hook_register(struct plugin *plugin, const char *method) +{ + struct plugin_hook *hook = plugin_hook_by_name(method); + if (!hook) { + /* No such hook name registered */ + return false; + } else if (hook->plugin != NULL) { + /* Another plugin already registered for this name */ + return false; + } + hook->plugin = plugin; + return true; +} + +/* FIXME(cdecker): Remove dummy hook, once we have a real one */ +REGISTER_PLUGIN_HOOK(hello, NULL, void *, NULL, void *, NULL, void *); + void plugin_hook_call_(struct lightningd *ld, const struct plugin_hook *hook, void *payload, void *cb_arg) { diff --git a/lightningd/plugin_hook.h b/lightningd/plugin_hook.h index bd75a43b1..dcbf53292 100644 --- a/lightningd/plugin_hook.h +++ b/lightningd/plugin_hook.h @@ -73,7 +73,7 @@ void plugin_hook_call_(struct lightningd *ld, const struct plugin_hook *hook, */ /* FIXME: Find a way to avoid back-to-back declaration and definition */ #define PLUGIN_HOOK_CALL_DEF(name, payload_type, response_cb_arg_type) \ - static inline void plugin_hook_call_##name( \ + UNNEEDED static inline void plugin_hook_call_##name( \ struct lightningd *ld, payload_type payload, \ response_cb_arg_type cb_arg) \ { \