mirror of
https://github.com/aljazceru/lightning.git
synced 2026-01-05 23:24:21 +01:00
jsonrpc: probe sites for usage information once, at start.
We store it in a strmap. This means we call the jsonrpc handler earlier, so all callers need to call param() before they do anything else; only json_listaddrs and json_help needed fixing. Plugins still use '[usage]' for now. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
This commit is contained in:
@@ -21,6 +21,7 @@
|
||||
#include <ccan/err/err.h>
|
||||
#include <ccan/io/io.h>
|
||||
#include <ccan/str/hex/hex.h>
|
||||
#include <ccan/strmap/strmap.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/bech32.h>
|
||||
#include <common/json_command.h>
|
||||
@@ -38,6 +39,7 @@
|
||||
#include <lightningd/json.h>
|
||||
#include <lightningd/jsonrpc.h>
|
||||
#include <lightningd/log.h>
|
||||
#include <lightningd/memdump.h>
|
||||
#include <lightningd/options.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/socket.h>
|
||||
@@ -106,6 +108,10 @@ struct jsonrpc {
|
||||
struct io_listener *rpc_listener;
|
||||
struct json_command **commands;
|
||||
struct log *log;
|
||||
|
||||
/* Map from json command names to usage strings: we don't put this inside
|
||||
* struct json_command as it's good practice to have those const. */
|
||||
STRMAP(const char *) usagemap;
|
||||
};
|
||||
|
||||
/* The command itself usually owns the stream, because jcon may get closed.
|
||||
@@ -304,10 +310,11 @@ static void json_add_help_command(struct command *cmd,
|
||||
struct json_command *json_command)
|
||||
{
|
||||
char *usage;
|
||||
cmd->mode = CMD_USAGE;
|
||||
json_command->dispatch(cmd, NULL, NULL, NULL);
|
||||
usage = tal_fmt(cmd, "%s %s", json_command->name, cmd->usage);
|
||||
|
||||
usage = tal_fmt(cmd, "%s %s",
|
||||
json_command->name,
|
||||
strmap_get(&cmd->ld->jsonrpc->usagemap,
|
||||
json_command->name));
|
||||
json_object_start(response, NULL);
|
||||
|
||||
json_add_string(response, "command", usage);
|
||||
@@ -347,7 +354,7 @@ static struct command_result *json_help(struct command *cmd,
|
||||
{
|
||||
struct json_stream *response;
|
||||
const jsmntok_t *cmdtok;
|
||||
struct json_command **commands = cmd->ld->jsonrpc->commands;
|
||||
struct json_command **commands;
|
||||
const struct json_command *one_cmd;
|
||||
|
||||
if (!param(cmd, buffer, params,
|
||||
@@ -355,6 +362,7 @@ static struct command_result *json_help(struct command *cmd,
|
||||
NULL))
|
||||
return command_param_failed();
|
||||
|
||||
commands = cmd->ld->jsonrpc->commands;
|
||||
if (cmdtok) {
|
||||
one_cmd = find_command(commands, buffer, cmdtok);
|
||||
if (!one_cmd)
|
||||
@@ -771,6 +779,7 @@ static struct io_plan *incoming_jcon_connected(struct io_conn *conn,
|
||||
|
||||
static void destroy_json_command(struct json_command *command, struct jsonrpc *rpc)
|
||||
{
|
||||
strmap_del(&rpc->usagemap, command->name, NULL);
|
||||
for (size_t i = 0; i < tal_count(rpc->commands); i++) {
|
||||
if (rpc->commands[i] == command) {
|
||||
tal_arr_remove(&rpc->commands, i);
|
||||
@@ -780,9 +789,7 @@ static void destroy_json_command(struct json_command *command, struct jsonrpc *r
|
||||
abort();
|
||||
}
|
||||
|
||||
/* For built-in ones, they're not tal objects, so no destructor */
|
||||
static bool jsonrpc_command_add_perm(struct jsonrpc *rpc,
|
||||
struct json_command *command)
|
||||
static bool command_add(struct jsonrpc *rpc, struct json_command *command)
|
||||
{
|
||||
size_t count = tal_count(rpc->commands);
|
||||
|
||||
@@ -795,23 +802,54 @@ static bool jsonrpc_command_add_perm(struct jsonrpc *rpc,
|
||||
return true;
|
||||
}
|
||||
|
||||
bool jsonrpc_command_add(struct jsonrpc *rpc, struct json_command *command)
|
||||
/* Built-in commands get called to construct usage string via param() */
|
||||
static void setup_command_usage(struct lightningd *ld,
|
||||
struct json_command *command)
|
||||
{
|
||||
if (!jsonrpc_command_add_perm(rpc, command))
|
||||
const struct command_result *res;
|
||||
struct command *dummy;
|
||||
|
||||
/* Call it with minimal cmd, to fill out usagemap */
|
||||
dummy = tal(tmpctx, struct command);
|
||||
dummy->mode = CMD_USAGE;
|
||||
dummy->ld = ld;
|
||||
dummy->json_cmd = command;
|
||||
res = command->dispatch(dummy, NULL, NULL, NULL);
|
||||
assert(res == ¶m_failed);
|
||||
assert(strmap_get(&ld->jsonrpc->usagemap, command->name));
|
||||
}
|
||||
|
||||
bool jsonrpc_command_add(struct jsonrpc *rpc, struct json_command *command,
|
||||
const char *usage TAKES)
|
||||
{
|
||||
if (!command_add(rpc, command))
|
||||
return false;
|
||||
usage = tal_strdup(command, usage);
|
||||
strmap_add(&rpc->usagemap, command->name, usage);
|
||||
tal_add_destructor2(command, destroy_json_command, rpc);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool jsonrpc_command_add_perm(struct lightningd *ld,
|
||||
struct jsonrpc *rpc,
|
||||
struct json_command *command)
|
||||
{
|
||||
if (!command_add(rpc, command))
|
||||
return false;
|
||||
setup_command_usage(ld, command);
|
||||
return true;
|
||||
}
|
||||
|
||||
void jsonrpc_setup(struct lightningd *ld)
|
||||
{
|
||||
struct json_command **commands = get_cmdlist();
|
||||
|
||||
ld->jsonrpc = tal(ld, struct jsonrpc);
|
||||
strmap_init(&ld->jsonrpc->usagemap);
|
||||
ld->jsonrpc->commands = tal_arr(ld->jsonrpc, struct json_command *, 0);
|
||||
ld->jsonrpc->log = new_log(ld->jsonrpc, ld->log_book, "jsonrpc");
|
||||
for (size_t i=0; i<num_cmdlist; i++) {
|
||||
if (!jsonrpc_command_add_perm(ld->jsonrpc, commands[i]))
|
||||
if (!jsonrpc_command_add_perm(ld, ld->jsonrpc, commands[i]))
|
||||
fatal("Cannot add duplicate command %s",
|
||||
commands[i]->name);
|
||||
}
|
||||
@@ -823,9 +861,11 @@ bool command_usage_only(const struct command *cmd)
|
||||
return cmd->mode == CMD_USAGE;
|
||||
}
|
||||
|
||||
void command_set_usage(struct command *cmd, const char *usage)
|
||||
void command_set_usage(struct command *cmd, const char *usage TAKES)
|
||||
{
|
||||
cmd->usage = usage;
|
||||
usage = tal_strdup(cmd->ld, usage);
|
||||
if (!strmap_add(&cmd->ld->jsonrpc->usagemap, cmd->json_cmd->name, usage))
|
||||
fatal("Two usages for command %s?", cmd->json_cmd->name);
|
||||
}
|
||||
|
||||
bool command_check_only(const struct command *cmd)
|
||||
@@ -1141,3 +1181,11 @@ static const struct json_command check_command = {
|
||||
};
|
||||
|
||||
AUTODATA(json_command, &check_command);
|
||||
|
||||
#if DEVELOPER
|
||||
void jsonrpc_remove_memleak(struct htable *memtable,
|
||||
const struct jsonrpc *jsonrpc)
|
||||
{
|
||||
memleak_remove_strmap(memtable, &jsonrpc->usagemap);
|
||||
}
|
||||
#endif /* DEVELOPER */
|
||||
|
||||
Reference in New Issue
Block a user