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 <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2023-06-06 10:08:53 +09:30
parent 703ffdf59b
commit e50e57712a
3 changed files with 104 additions and 45 deletions

View File

@ -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",

View File

@ -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,

View File

@ -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 */