From e50e57712a4c9f60d44a039bd2636ee01a358452 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 6 Jun 2023 10:08:53 +0930 Subject: [PATCH] setconfig: hook into plugin infrastructure for setconfig. If it's a plugin opt, we'll need a callback, so reshuffle logic. Also add infra to map option name to plugin and option. Signed-off-by: Rusty Russell --- lightningd/configs.c | 90 ++++++++++++++++++++++++++------------------ lightningd/plugin.c | 51 ++++++++++++++++++++----- lightningd/plugin.h | 8 ++++ 3 files changed, 104 insertions(+), 45 deletions(-) diff --git a/lightningd/configs.c b/lightningd/configs.c index 4258b0509..8e3932366 100644 --- a/lightningd/configs.c +++ b/lightningd/configs.c @@ -550,48 +550,19 @@ static void configvar_save(struct lightningd *ld, } } -static struct command_result *json_setconfig(struct command *cmd, - const char *buffer, - const jsmntok_t *obj UNNEEDED, - const jsmntok_t *params) +static struct command_result *setconfig_success(struct command *cmd, + const struct opt_table *ot, + const char *val) { struct json_stream *response; - const struct opt_table *ot; - const char *val, **names, *confline; - char *err; - - if (!param(cmd, buffer, params, - p_req("config", param_opt_dynamic_config, &ot), - p_opt("val", param_string, &val), - NULL)) - return command_param_failed(); - - /* We don't handle DYNAMIC MULTI, at least yet! */ - assert(!(ot->type & OPT_MULTI)); + const char **names, *confline; names = opt_names_arr(tmpctx, ot); - if (ot->type & OPT_NOARG) { - if (val) - return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "%s does not take a value", - ot->names + 2); - confline = tal_strdup(tmpctx, names[0]); - err = ot->cb(ot->u.arg); - } else { - assert(ot->type & OPT_HASARG); - if (!val) - return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "%s requires a value", - ot->names + 2); + if (val) confline = tal_fmt(tmpctx, "%s=%s", names[0], val); - err = ot->cb_arg(val, ot->u.arg); - } - - if (err) { - return command_fail(cmd, JSONRPC2_INVALID_PARAMS, - "Error setting %s: %s", ot->names + 2, err); - } + else + confline = names[0]; configvar_save(cmd->ld, names, confline); @@ -603,6 +574,53 @@ static struct command_result *json_setconfig(struct command *cmd, return command_success(cmd, response); } +static struct command_result *json_setconfig(struct command *cmd, + const char *buffer, + const jsmntok_t *obj UNNEEDED, + const jsmntok_t *params) +{ + const struct opt_table *ot; + const char *val; + char *err; + + if (!param(cmd, buffer, params, + p_req("config", param_opt_dynamic_config, &ot), + p_opt("val", param_string, &val), + NULL)) + return command_param_failed(); + + /* We don't handle DYNAMIC MULTI, at least yet! */ + assert(!(ot->type & OPT_MULTI)); + + if (ot->type & OPT_NOARG) { + if (val) + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "%s does not take a value", + ot->names + 2); + if (is_plugin_opt(ot)) + return plugin_set_dynamic_opt(cmd, ot, NULL, + setconfig_success); + err = ot->cb(ot->u.arg); + } else { + assert(ot->type & OPT_HASARG); + if (!val) + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "%s requires a value", + ot->names + 2); + if (is_plugin_opt(ot)) + return plugin_set_dynamic_opt(cmd, ot, val, + setconfig_success); + err = ot->cb_arg(val, ot->u.arg); + } + + if (err) { + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "Error setting %s: %s", ot->names + 2, err); + } + + return setconfig_success(cmd, ot, val); +} + static const struct json_command setconfig_command = { "setconfig", "utility", diff --git a/lightningd/plugin.c b/lightningd/plugin.c index 299ed25a2..f4fe228f1 100644 --- a/lightningd/plugin.c +++ b/lightningd/plugin.c @@ -1379,6 +1379,27 @@ static struct plugin_opt *plugin_opt_find(const struct plugin *plugin, return NULL; } +/* Find the plugin_opt for this ot */ +static struct plugin *plugin_opt_find_any(const struct plugins *plugins, + const struct opt_table *ot, + struct plugin_opt **poptp) +{ + struct plugin *plugin; + + /* Find the plugin that registered this RPC call */ + list_for_each(&plugins->plugins, plugin, list) { + struct plugin_opt *popt = plugin_opt_find(plugin, ot->names+2); + if (popt) { + if (poptp) + *poptp = popt; + return plugin; + } + } + + /* Reaching here is possible, if a plugin was stopped! */ + return NULL; +} + void json_add_config_plugin(struct json_stream *stream, const struct plugins *plugins, const char *fieldname, @@ -1391,15 +1412,9 @@ void json_add_config_plugin(struct json_stream *stream, return; /* Find the plugin that registered this RPC call */ - list_for_each(&plugins->plugins, plugin, list) { - struct plugin_opt *popt = plugin_opt_find(plugin, ot->names+2); - if (popt) { - json_add_string(stream, fieldname, plugin->cmd); - return; - } - } - - /* Reaching here is possible, if a plugin was stopped! */ + plugin = plugin_opt_find_any(plugins, ot, NULL); + if (plugin) + json_add_string(stream, fieldname, plugin->cmd); } /* Start command might have included plugin-specific parameters. @@ -2041,6 +2056,24 @@ bool plugins_config(struct plugins *plugins) return true; } +struct command_result *plugin_set_dynamic_opt(struct command *cmd, + const struct opt_table *ot, + const char *val, + struct command_result *(*success) + (struct command *, + const struct opt_table *, + const char *)) +{ + struct plugin_opt *popt; + struct plugin *plugin; + + plugin = plugin_opt_find_any(cmd->ld->plugins, ot, &popt); + assert(plugin); + + return command_fail(cmd, JSONRPC2_INVALID_PARAMS, + "FIXME: Implement dynamic"); +} + /** json_add_opt_plugins_array * * @brief add a named array of plugins to the given response, diff --git a/lightningd/plugin.h b/lightningd/plugin.h index 587a214be..fc50cd457 100644 --- a/lightningd/plugin.h +++ b/lightningd/plugin.h @@ -365,4 +365,12 @@ void json_add_config_plugin(struct json_stream *stream, const char *fieldname, const struct opt_table *ot); +/* Attempt to setconfig an option in a plugin. Calls success or fail, may be async! */ +struct command_result *plugin_set_dynamic_opt(struct command *cmd, + const struct opt_table *ot, + const char *val, + struct command_result *(*success) + (struct command *, + const struct opt_table *, + const char *)); #endif /* LIGHTNING_LIGHTNINGD_PLUGIN_H */