From a65f2ef22a5471446263ebb613b1db9e0869cf3f Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 6 Jun 2023 10:08:53 +0930 Subject: [PATCH] plugins: libplugin support for dynamic config options. Signed-off-by: Rusty Russell --- plugins/libplugin.c | 70 ++++++++++++++++++++++++++++++++++++--------- plugins/libplugin.h | 16 +++++++---- 2 files changed, 68 insertions(+), 18 deletions(-) diff --git a/plugins/libplugin.c b/plugins/libplugin.c index 2f59057c6..109ba9588 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -915,6 +915,7 @@ handle_getmanifest(struct command *getmanifest_cmd, json_add_string(params, "type", p->opts[i].type); json_add_string(params, "description", p->opts[i].description); json_add_bool(params, "deprecated", p->opts[i].deprecated); + json_add_bool(params, "dynamic", p->opts[i].dynamic); json_object_end(params); } json_array_end(params); @@ -1136,6 +1137,15 @@ static struct feature_set *json_to_feature_set(struct plugin *plugin, return fset; } +static struct plugin_option *find_opt(struct plugin *plugin, const char *name) +{ + for (size_t i = 0; i < tal_count(plugin->opts); i++) { + if (streq(plugin->opts[i].name, name)) + return &plugin->opts[i]; + } + return NULL; +} + static struct command_result *handle_init(struct command *cmd, const char *buf, const jsmntok_t *params) @@ -1197,19 +1207,17 @@ static struct command_result *handle_init(struct command *cmd, opttok = json_get_member(buf, params, "options"); json_for_each_obj(i, t, opttok) { - char *opt = json_strdup(NULL, buf, t); - for (size_t optnum = 0; optnum < tal_count(p->opts); optnum++) { - char *problem; - if (!streq(p->opts[optnum].name, opt)) - continue; - problem = p->opts[optnum].handle(p, json_strdup(opt, buf, t+1), - p->opts[optnum].arg); - if (problem) - plugin_err(p, "option '%s': %s", - p->opts[optnum].name, problem); - break; - } - tal_free(opt); + const char *name, *problem; + struct plugin_option *popt; + + name = json_strdup(tmpctx, buf, t); + popt = find_opt(p, name); + if (!popt) + plugin_err(p, "lightningd specified unknown option '%s'?", name); + + problem = popt->handle(p, json_strdup(tmpctx, buf, t+1), popt->arg); + if (problem) + plugin_err(p, "option '%s': %s", popt->name, problem); } if (p->init) { @@ -1638,6 +1646,41 @@ static void ld_command_handle(struct plugin *plugin, } } + /* Dynamic parameters */ + if (streq(cmd->methodname, "setconfig")) { + const jsmntok_t *valtok; + const char *config, *val, *problem; + struct plugin_option *popt; + struct command_result *ret; + config = json_strdup(tmpctx, plugin->buffer, + json_get_member(plugin->buffer, paramstok, "config")); + popt = find_opt(plugin, config); + if (!popt) { + plugin_err(plugin, + "lightningd setconfig unknown option '%s'?", + config); + } + if (!popt->dynamic) { + plugin_err(plugin, + "lightningd setconfig non-dynamic option '%s'?", + config); + } + valtok = json_get_member(plugin->buffer, paramstok, "val"); + if (valtok) + val = json_strdup(tmpctx, plugin->buffer, valtok); + else + val = "true"; + + problem = popt->handle(plugin, val, popt->arg); + if (problem) + ret = command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "%s", problem); + else + ret = command_finished(cmd, jsonrpc_stream_success(cmd)); + assert(ret == &complete); + return; + } + plugin_err(plugin, "Unknown command '%s'", cmd->methodname); } @@ -1842,6 +1885,7 @@ static struct plugin *new_plugin(const tal_t *ctx, o.handle = va_arg(ap, char *(*)(struct plugin *, const char *str, void *arg)); o.arg = va_arg(ap, void *); o.deprecated = va_arg(ap, int); /* bool gets promoted! */ + o.dynamic = va_arg(ap, int); /* bool gets promoted! */ tal_arr_expand(&p->opts, o); } diff --git a/plugins/libplugin.h b/plugins/libplugin.h index 83b03f4bf..efda2f492 100644 --- a/plugins/libplugin.h +++ b/plugins/libplugin.h @@ -81,6 +81,8 @@ struct plugin_option { void *arg; /* If true, this options *disabled* if allow-deprecated-apis = false */ bool deprecated; + /* If true, allow setting after plugin has initialized */ + bool dynamic; }; /* Create an array of these, one for each notification you subscribe to. */ @@ -401,7 +403,7 @@ static inline void *plugin_option_cb_check(char *(*set)(struct plugin *plugin, } /* Macro to define arguments */ -#define plugin_option_(name, type, description, set, arg, deprecated) \ +#define plugin_option_(name, type, description, set, arg, deprecated, dynamic) \ (name), \ (type), \ (description), \ @@ -410,13 +412,17 @@ static inline void *plugin_option_cb_check(char *(*set)(struct plugin *plugin, struct plugin *, \ const char *)), \ (arg), \ - (deprecated) + (deprecated), \ + (dynamic) #define plugin_option(name, type, description, set, arg) \ - plugin_option_((name), (type), (description), (set), (arg), false) + plugin_option_((name), (type), (description), (set), (arg), false, false) -#define plugin_option_deprecated(name, type, description, set, arg) \ - plugin_option_((name), (type), (description), (set), (arg), true) +#define plugin_option_dynamic(name, type, description, set, arg) \ + plugin_option_((name), (type), (description), (set), (arg), false, true) + +#define plugin_option_deprecated(name, type, description, set, arg) \ + plugin_option_((name), (type), (description), (set), (arg), true, false) /* Standard helpers */ char *u64_option(struct plugin *plugin, const char *arg, u64 *i);