plugins: add command field to subcommand output.

Makes it possible to write a decent JSON schema, but means we need to carry
additional data, so we create a `struct plugin_command`.

We remove the unused struct dynamic_plugin, too.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
Rusty Russell 2021-06-16 10:32:17 +09:30
parent 0a99b8c64c
commit bf74be3348
4 changed files with 59 additions and 49 deletions

View File

@ -74,7 +74,7 @@ struct plugins *plugins_new(const tal_t *ctx, struct log_book *log_book,
p->log = new_log(p, log_book, NULL, "plugin-manager");
p->ld = ld;
p->startup = true;
p->json_cmds = tal_arr(p, struct command *, 0);
p->plugin_cmds = tal_arr(p, struct plugin_command *, 0);
p->blacklist = tal_arr(p, const char *, 0);
p->shutdown = false;
p->plugin_idx = 0;
@ -154,27 +154,27 @@ static void check_plugins_manifests(struct plugins *plugins)
static void check_plugins_initted(struct plugins *plugins)
{
struct command **json_cmds;
struct plugin_command **plugin_cmds;
if (!plugins_all_in_state(plugins, INIT_COMPLETE))
return;
/* Clear commands first, in case callbacks add new ones.
* Paranoia, but wouldn't that be a nasty bug to find? */
json_cmds = plugins->json_cmds;
plugins->json_cmds = tal_arr(plugins, struct command *, 0);
for (size_t i = 0; i < tal_count(json_cmds); i++)
plugin_cmd_all_complete(plugins, json_cmds[i]);
tal_free(json_cmds);
plugin_cmds = plugins->plugin_cmds;
plugins->plugin_cmds = tal_arr(plugins, struct plugin_command *, 0);
for (size_t i = 0; i < tal_count(plugin_cmds); i++)
plugin_cmd_all_complete(plugins, plugin_cmds[i]);
tal_free(plugin_cmds);
}
struct command_result *plugin_register_all_complete(struct lightningd *ld,
struct command *cmd)
struct plugin_command *pcmd)
{
if (plugins_all_in_state(ld->plugins, INIT_COMPLETE))
return plugin_cmd_all_complete(ld->plugins, cmd);
return plugin_cmd_all_complete(ld->plugins, pcmd);
tal_arr_expand(&ld->plugins->json_cmds, cmd);
tal_arr_expand(&ld->plugins->plugin_cmds, pcmd);
return NULL;
}
@ -216,7 +216,7 @@ static void destroy_plugin(struct plugin *p)
}
struct plugin *plugin_register(struct plugins *plugins, const char* path TAKES,
struct command *start_cmd, bool important,
struct plugin_command *start_cmd, bool important,
const char *parambuf STEALS,
const jsmntok_t *params STEALS)
{

View File

@ -51,8 +51,9 @@ struct plugin {
struct io_conn *stdin_conn, *stdout_conn;
struct plugins *plugins;
const char **plugin_path;
/* If there's a json command which ordered this to start */
struct command *start_cmd;
struct plugin_command *start_cmd;
enum plugin_state plugin_state;
@ -122,7 +123,7 @@ struct plugins {
const char *default_dir;
/* If there are json commands waiting for plugin resolutions. */
struct command **json_cmds;
struct plugin_command **plugin_cmds;
/* Blacklist of plugins from --disable-plugin */
const char **blacklist;
@ -222,7 +223,7 @@ void plugins_free(struct plugins *plugins);
*/
struct plugin *plugin_register(struct plugins *plugins,
const char* path TAKES,
struct command *start_cmd,
struct plugin_command *start_cmd,
bool important,
const char *parambuf STEALS,
const jsmntok_t *params STEALS);
@ -283,7 +284,7 @@ struct plugin *find_plugin_for_command(struct lightningd *ld,
* plugin_cmd_all_complete().
*/
struct command_result *plugin_register_all_complete(struct lightningd *ld,
struct command *cmd);
struct plugin_command *pcmd);
/**
* Send the configure message to all plugins.

View File

@ -6,21 +6,22 @@
#include <sys/types.h>
/* A dummy structure used to give multiple arguments to callbacks. */
struct dynamic_plugin {
struct plugin *plugin;
struct plugin_command {
struct command *cmd;
const char *subcmd;
};
/**
* Returned by all subcommands on success.
*/
static struct command_result *plugin_dynamic_list_plugins(struct command *cmd,
static struct command_result *plugin_dynamic_list_plugins(struct plugin_command *pcmd,
const struct plugins *plugins)
{
struct json_stream *response;
const struct plugin *p;
response = json_stream_success(cmd);
response = json_stream_success(pcmd->cmd);
json_add_string(response, "command", pcmd->subcmd);
json_array_start(response, "plugins");
list_for_each(&plugins->plugins, p, list) {
json_object_start(response, NULL);
@ -30,25 +31,25 @@ static struct command_result *plugin_dynamic_list_plugins(struct command *cmd,
json_object_end(response);
}
json_array_end(response);
return command_success(cmd, response);
return command_success(pcmd->cmd, response);
}
struct command_result *plugin_cmd_killed(struct command *cmd,
struct command_result *plugin_cmd_killed(struct plugin_command *pcmd,
struct plugin *plugin, const char *msg)
{
return command_fail(cmd, PLUGIN_ERROR, "%s: %s", plugin->cmd, msg);
return command_fail(pcmd->cmd, PLUGIN_ERROR, "%s: %s", plugin->cmd, msg);
}
struct command_result *plugin_cmd_succeeded(struct command *cmd,
struct command_result *plugin_cmd_succeeded(struct plugin_command *pcmd,
struct plugin *plugin)
{
return plugin_dynamic_list_plugins(cmd, plugin->plugins);
return plugin_dynamic_list_plugins(pcmd, plugin->plugins);
}
struct command_result *plugin_cmd_all_complete(struct plugins *plugins,
struct command *cmd)
struct plugin_command *pcmd)
{
return plugin_dynamic_list_plugins(cmd, plugins);
return plugin_dynamic_list_plugins(pcmd, plugins);
}
/**
@ -56,25 +57,25 @@ struct command_result *plugin_cmd_all_complete(struct plugins *plugins,
* will give a result 60 seconds later at the most (once init completes).
*/
static struct command_result *
plugin_dynamic_start(struct command *cmd, const char *plugin_path,
plugin_dynamic_start(struct plugin_command *pcmd, const char *plugin_path,
const char *buffer, const jsmntok_t *params)
{
struct plugin *p = plugin_register(cmd->ld->plugins, plugin_path, cmd, false, buffer, params);
struct plugin *p = plugin_register(pcmd->cmd->ld->plugins, plugin_path, pcmd, false, buffer, params);
const char *err;
if (!p)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
return command_fail(pcmd->cmd, JSONRPC2_INVALID_PARAMS,
"%s: already registered",
plugin_path);
/* This will come back via plugin_cmd_killed or plugin_cmd_succeeded */
err = plugin_send_getmanifest(p);
if (err)
return command_fail(cmd, PLUGIN_ERROR,
return command_fail(pcmd->cmd, PLUGIN_ERROR,
"%s: %s",
plugin_path, err);
return command_still_pending(cmd);
return command_still_pending(pcmd->cmd);
}
/**
@ -82,22 +83,22 @@ plugin_dynamic_start(struct command *cmd, const char *plugin_path,
* all contained plugins recursively and then starts them.
*/
static struct command_result *
plugin_dynamic_startdir(struct command *cmd, const char *dir_path)
plugin_dynamic_startdir(struct plugin_command *pcmd, const char *dir_path)
{
const char *err;
struct command_result *res;
err = add_plugin_dir(cmd->ld->plugins, dir_path, false);
err = add_plugin_dir(pcmd->cmd->ld->plugins, dir_path, false);
if (err)
return command_fail(cmd, JSONRPC2_INVALID_PARAMS, "%s", err);
return command_fail(pcmd->cmd, JSONRPC2_INVALID_PARAMS, "%s", err);
/* If none added, this calls plugin_cmd_all_complete immediately */
res = plugin_register_all_complete(cmd->ld, cmd);
res = plugin_register_all_complete(pcmd->cmd->ld, pcmd);
if (res)
return res;
plugins_send_getmanifest(cmd->ld->plugins);
return command_still_pending(cmd);
plugins_send_getmanifest(pcmd->cmd->ld->plugins);
return command_still_pending(pcmd->cmd);
}
static struct command_result *
@ -116,6 +117,7 @@ plugin_dynamic_stop(struct command *cmd, const char *plugin_name)
plugin_kill(p, LOG_INFORM,
"stopped by lightningd via RPC");
response = json_stream_success(cmd);
json_add_string(response, "command", "stop");
json_add_string(response, "result",
take(tal_fmt(NULL, "Successfully stopped %s.",
plugin_name)));
@ -131,20 +133,20 @@ plugin_dynamic_stop(struct command *cmd, const char *plugin_name)
* Look for additions in the default plugin directory.
*/
static struct command_result *
plugin_dynamic_rescan_plugins(struct command *cmd)
plugin_dynamic_rescan_plugins(struct plugin_command *pcmd)
{
struct command_result *res;
/* This will not fail on "already registered" error. */
plugins_add_default_dir(cmd->ld->plugins);
plugins_add_default_dir(pcmd->cmd->ld->plugins);
/* If none added, this calls plugin_cmd_all_complete immediately */
res = plugin_register_all_complete(cmd->ld, cmd);
res = plugin_register_all_complete(pcmd->cmd->ld, pcmd);
if (res)
return res;
plugins_send_getmanifest(cmd->ld->plugins);
return command_still_pending(cmd);
plugins_send_getmanifest(pcmd->cmd->ld->plugins);
return command_still_pending(pcmd->cmd);
}
/**
@ -156,6 +158,7 @@ static struct command_result *json_plugin_control(struct command *cmd,
const jsmntok_t *obj UNNEEDED,
const jsmntok_t *params)
{
struct plugin_command *pcmd;
const char *subcmd;
subcmd = param_subcommand(cmd, buffer, params,
"start", "stop", "startdir",
@ -163,6 +166,10 @@ static struct command_result *json_plugin_control(struct command *cmd,
if (!subcmd)
return command_param_failed();
pcmd = tal(cmd, struct plugin_command);
pcmd->cmd = cmd;
pcmd->subcmd = subcmd;
if (streq(subcmd, "stop")) {
const char *plugin_name;
@ -202,7 +209,7 @@ static struct command_result *json_plugin_control(struct command *cmd,
"plugin") - 1, 1);
}
if (access(plugin_path, X_OK) == 0)
return plugin_dynamic_start(cmd, plugin_path,
return plugin_dynamic_start(pcmd, plugin_path,
buffer, mod_params);
else
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
@ -218,7 +225,7 @@ static struct command_result *json_plugin_control(struct command *cmd,
return command_param_failed();
if (access(dir_path, F_OK) == 0)
return plugin_dynamic_startdir(cmd, dir_path);
return plugin_dynamic_startdir(pcmd, dir_path);
else
return command_fail(cmd, JSONRPC2_INVALID_PARAMS,
"Could not open %s", dir_path);
@ -228,14 +235,14 @@ static struct command_result *json_plugin_control(struct command *cmd,
NULL))
return command_param_failed();
return plugin_dynamic_rescan_plugins(cmd);
return plugin_dynamic_rescan_plugins(pcmd);
} else if (streq(subcmd, "list")) {
if (!param(cmd, buffer, params,
p_req("subcommand", param_ignore, cmd),
NULL))
return command_param_failed();
return plugin_dynamic_list_plugins(cmd, cmd->ld->plugins);
return plugin_dynamic_list_plugins(pcmd, cmd->ld->plugins);
}
/* subcmd must be one of the above: param_subcommand checked it! */

View File

@ -3,16 +3,18 @@
#include "config.h"
#include <lightningd/plugin.h>
struct plugin_command;
/* Plugin startup failed */
struct command_result *plugin_cmd_killed(struct command *cmd,
struct command_result *plugin_cmd_killed(struct plugin_command *pcmd,
struct plugin *plugin, const char *msg);
/* Plugin startup succeeded */
struct command_result *plugin_cmd_succeeded(struct command *cmd,
struct command_result *plugin_cmd_succeeded(struct plugin_command *pcmd,
struct plugin *plugin);
/* All plugins succeeded/failed */
struct command_result *plugin_cmd_all_complete(struct plugins *plugins,
struct command *cmd);
struct plugin_command *pcmd);
#endif /* LIGHTNING_LIGHTNINGD_PLUGIN_CONTROL_H */