reckless-rpc: initial boilerplate
Trying a single command first - reckless-search to test launching a reckless process and processing the result.
This commit is contained in:
committed by
ShahanaFarooqui
parent
5073942eef
commit
f69c4d6385
@@ -63,6 +63,9 @@ PLUGIN_FUNDER_HEADER := \
|
||||
plugins/funder_policy.h
|
||||
PLUGIN_FUNDER_OBJS := $(PLUGIN_FUNDER_SRC:.c=.o)
|
||||
|
||||
PLUGIN_RECKLESSRPC_SRC := plugins/recklessrpc.c
|
||||
PLUGIN_RECKLESSRPC_OBJS := $(PLUGIN_RECKLESSRPC_SRC:.c=.o)
|
||||
|
||||
PLUGIN_ALL_SRC := \
|
||||
$(PLUGIN_AUTOCLEAN_SRC) \
|
||||
$(PLUGIN_chanbackup_SRC) \
|
||||
@@ -77,7 +80,8 @@ PLUGIN_ALL_SRC := \
|
||||
$(PLUGIN_PAY_LIB_SRC) \
|
||||
$(PLUGIN_PAY_SRC) \
|
||||
$(PLUGIN_SPENDER_SRC) \
|
||||
$(PLUGIN_RECOVER_SRC)
|
||||
$(PLUGIN_RECOVER_SRC) \
|
||||
$(PLUGIN_RECKLESSRPC_SRC)
|
||||
|
||||
PLUGIN_ALL_HEADER := \
|
||||
$(PLUGIN_PAY_HEADER) \
|
||||
@@ -97,6 +101,7 @@ C_PLUGINS := \
|
||||
plugins/keysend \
|
||||
plugins/offers \
|
||||
plugins/pay \
|
||||
plugins/recklessrpc \
|
||||
plugins/recover \
|
||||
plugins/txprepare \
|
||||
plugins/cln-renepay \
|
||||
@@ -216,6 +221,8 @@ plugins/funder: bitcoin/psbt.o common/psbt_open.o $(PLUGIN_FUNDER_OBJS) $(PLUGIN
|
||||
|
||||
plugins/recover: common/gossmap.o common/sciddir_or_pubkey.o common/fp16.o $(PLUGIN_RECOVER_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS)
|
||||
|
||||
plugins/recklessrpc: $(PLUGIN_RECKLESSRPC_OBJS) $(PLUGIN_LIB_OBJS) $(PLUGIN_COMMON_OBJS) $(JSMN_OBJS)
|
||||
|
||||
# This covers all the low-level list RPCs which return simple arrays
|
||||
SQL_LISTRPCS := listchannels listforwards listhtlcs listinvoices listnodes listoffers listpeers listpeerchannels listclosedchannels listtransactions listsendpays bkpr-listaccountevents bkpr-listincome
|
||||
SQL_LISTRPCS_SCHEMAS := $(foreach l,$(SQL_LISTRPCS),doc/schemas/lightning-$l.json)
|
||||
|
||||
190
plugins/recklessrpc.c
Normal file
190
plugins/recklessrpc.c
Normal file
@@ -0,0 +1,190 @@
|
||||
/* This plugin provides RPC access to the reckless standalone utility.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include <ccan/array_size/array_size.h>
|
||||
#include <ccan/io/io.h>
|
||||
#include <ccan/pipecmd/pipecmd.h>
|
||||
#include <ccan/tal/str/str.h>
|
||||
#include <common/json_param.h>
|
||||
#include <common/json_parse_simple.h>
|
||||
#include <common/json_stream.h>
|
||||
#include <errno.h>
|
||||
#include <plugins/libplugin.h>
|
||||
#include <signal.h>
|
||||
|
||||
static struct plugin *plugin;
|
||||
|
||||
struct reckless {
|
||||
struct command *cmd;
|
||||
int stdinfd;
|
||||
int stdoutfd;
|
||||
int stderrfd;
|
||||
char *stdoutbuf;
|
||||
char *stderrbuf;
|
||||
size_t stdout_read; /* running total */
|
||||
size_t stdout_new; /* new since last read */
|
||||
pid_t pid;
|
||||
};
|
||||
|
||||
static struct io_plan *read_more(struct io_conn *conn, struct reckless *rkls)
|
||||
{
|
||||
rkls->stdout_read += rkls->stdout_new;
|
||||
if (rkls->stdout_read == tal_count(rkls->stdoutbuf))
|
||||
tal_resize(&rkls->stdoutbuf, rkls->stdout_read * 2);
|
||||
return io_read_partial(conn, rkls->stdoutbuf + rkls->stdout_read,
|
||||
tal_count(rkls->stdoutbuf) - rkls->stdout_read,
|
||||
&rkls->stdout_new, read_more, rkls);
|
||||
}
|
||||
|
||||
static struct command_result *reckless_result(struct io_conn *conn,
|
||||
struct reckless *reckless)
|
||||
{
|
||||
struct json_stream *response;
|
||||
response = jsonrpc_stream_success(reckless->cmd);
|
||||
json_array_start(response, "result");
|
||||
const jsmntok_t *results, *result, *logs, *log;
|
||||
size_t i;
|
||||
jsmn_parser parser;
|
||||
jsmntok_t *toks;
|
||||
toks = tal_arr(reckless, jsmntok_t, 500);
|
||||
jsmn_init(&parser);
|
||||
if (jsmn_parse(&parser, reckless->stdoutbuf,
|
||||
strlen(reckless->stdoutbuf), toks, tal_count(toks)) <= 0) {
|
||||
plugin_log(plugin, LOG_DBG, "need more json tokens");
|
||||
assert(false);
|
||||
}
|
||||
|
||||
results = json_get_member(reckless->stdoutbuf, toks, "result");
|
||||
json_for_each_arr(i, result, results) {
|
||||
json_add_string(response,
|
||||
NULL,
|
||||
json_strdup(reckless, reckless->stdoutbuf,
|
||||
result));
|
||||
}
|
||||
json_array_end(response);
|
||||
json_array_start(response, "log");
|
||||
logs = json_get_member(reckless->stdoutbuf, toks, "log");
|
||||
json_for_each_arr(i, log, logs) {
|
||||
json_add_string(response,
|
||||
NULL,
|
||||
json_strdup(reckless, reckless->stdoutbuf,
|
||||
log));
|
||||
}
|
||||
json_array_end(response);
|
||||
|
||||
return command_finished(reckless->cmd, response);
|
||||
}
|
||||
|
||||
static void reckless_conn_finish(struct io_conn *conn,
|
||||
struct reckless *reckless)
|
||||
{
|
||||
/* FIXME: avoid EBADFD - leave stdin fd open? */
|
||||
if (errno && errno != 9)
|
||||
plugin_log(plugin, LOG_DBG, "err: %s", strerror(errno));
|
||||
reckless_result(conn, reckless);
|
||||
if (reckless->pid > 0) {
|
||||
int status;
|
||||
pid_t p;
|
||||
p = waitpid(reckless->pid, &status, WNOHANG);
|
||||
/* Did the reckless process exit? */
|
||||
if (p != reckless->pid && reckless->pid) {
|
||||
plugin_log(plugin, LOG_DBG, "reckless failed to exit "
|
||||
"(%i), killing now.", status);
|
||||
kill(reckless->pid, SIGKILL);
|
||||
}
|
||||
}
|
||||
plugin_log(plugin, LOG_DBG, "Reckless subprocess complete.");
|
||||
plugin_log(plugin, LOG_DBG, "output: %s", reckless->stdoutbuf);
|
||||
io_close(conn);
|
||||
tal_free(reckless);
|
||||
}
|
||||
|
||||
static struct io_plan *conn_init(struct io_conn *conn, struct reckless *rkls)
|
||||
{
|
||||
io_set_finish(conn, reckless_conn_finish, rkls);
|
||||
return read_more(conn, rkls);
|
||||
}
|
||||
|
||||
static struct command_result *reckless_call(struct command *cmd,
|
||||
const char *call)
|
||||
{
|
||||
if (!call)
|
||||
return command_fail(cmd, PLUGIN_ERROR, "invalid reckless call");
|
||||
char **my_call;
|
||||
my_call = tal_arrz(tmpctx, char *, 0);
|
||||
tal_arr_expand(&my_call, "reckless");
|
||||
tal_arr_expand(&my_call, "-v");
|
||||
tal_arr_expand(&my_call, "--json");
|
||||
tal_arr_expand(&my_call, "search");
|
||||
tal_arr_expand(&my_call, (char *) call);
|
||||
tal_arr_expand(&my_call, NULL);
|
||||
struct reckless *reckless;
|
||||
reckless = tal(NULL, struct reckless);
|
||||
reckless->cmd = cmd;
|
||||
reckless->stdoutbuf = tal_arrz(reckless, char, 1024);
|
||||
reckless->stderrbuf = tal_arrz(reckless, char, 1024);
|
||||
reckless->stdout_read = 0;
|
||||
reckless->stdout_new = 0;
|
||||
char * full_cmd;
|
||||
full_cmd = tal_fmt(tmpctx, "calling:");
|
||||
for (int i=0; i<tal_count(my_call); i++)
|
||||
tal_append_fmt(&full_cmd, " %s", my_call[i]);
|
||||
plugin_log(plugin, LOG_DBG, "%s", full_cmd);
|
||||
tal_free(full_cmd);
|
||||
|
||||
reckless->pid = pipecmdarr(&reckless->stdinfd, &reckless->stdoutfd,
|
||||
&reckless->stderrfd, my_call);
|
||||
|
||||
/* FIXME: fail if invalid pid*/
|
||||
io_new_conn(reckless, reckless->stdoutfd, conn_init, reckless);
|
||||
tal_free(my_call);
|
||||
return command_still_pending(cmd);
|
||||
}
|
||||
|
||||
static struct command_result *json_search(struct command *cmd,
|
||||
const char *buf,
|
||||
const jsmntok_t *params)
|
||||
{
|
||||
const char *search_target;
|
||||
/* Allow check command to evaluate. */
|
||||
if (!param(cmd, buf, params,
|
||||
p_req("plugin", param_string, &search_target),
|
||||
NULL))
|
||||
return command_param_failed();
|
||||
return reckless_call(cmd, search_target);
|
||||
}
|
||||
|
||||
static const char *init(struct plugin *p,
|
||||
const char *buf UNUSED,
|
||||
const jsmntok_t *config UNUSED)
|
||||
{
|
||||
plugin = p;
|
||||
plugin_log(p, LOG_DBG, "plugin initialized!");
|
||||
/* FIXME: TODO: scan for reckless config info */
|
||||
/* FIXME: TODO: assume default reckless config using ld config dets */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const struct plugin_command commands[] = {
|
||||
{
|
||||
"reckless-search",
|
||||
json_search,
|
||||
},
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
setup_locale();
|
||||
|
||||
plugin_main(argv, init, NULL, PLUGIN_RESTARTABLE, true,
|
||||
NULL,
|
||||
commands, ARRAY_SIZE(commands),
|
||||
NULL, 0, /* Notifications */
|
||||
NULL, 0, /* Hooks */
|
||||
NULL, 0, /* Notification topics */
|
||||
NULL); /* plugin options */
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user