2019-01-15 05:13:27 +01:00
|
|
|
/* Helper library for C plugins. */
|
|
|
|
#ifndef LIGHTNING_PLUGINS_LIBPLUGIN_H
|
|
|
|
#define LIGHTNING_PLUGINS_LIBPLUGIN_H
|
|
|
|
#include "config.h"
|
|
|
|
|
2020-01-26 23:54:33 +01:00
|
|
|
#include <ccan/intmap/intmap.h>
|
|
|
|
#include <ccan/membuf/membuf.h>
|
2020-01-24 14:57:12 +01:00
|
|
|
#include <ccan/strmap/strmap.h>
|
2019-08-28 05:36:50 +02:00
|
|
|
#include <ccan/time/time.h>
|
2020-01-24 14:57:12 +01:00
|
|
|
#include <ccan/timer/timer.h>
|
2020-01-26 13:52:29 +01:00
|
|
|
#include <common/errcode.h>
|
2019-01-15 05:13:27 +01:00
|
|
|
#include <common/json.h>
|
|
|
|
#include <common/json_command.h>
|
|
|
|
#include <common/json_helpers.h>
|
|
|
|
#include <common/jsonrpc_errors.h>
|
|
|
|
#include <common/param.h>
|
2019-05-21 09:32:37 +02:00
|
|
|
#include <common/status_levels.h>
|
2019-01-15 05:13:27 +01:00
|
|
|
|
2019-06-12 02:38:54 +02:00
|
|
|
struct json_out;
|
2019-02-23 04:11:14 +01:00
|
|
|
|
2019-07-29 13:46:48 +02:00
|
|
|
enum plugin_restartability {
|
|
|
|
PLUGIN_STATIC,
|
|
|
|
PLUGIN_RESTARTABLE
|
|
|
|
};
|
|
|
|
|
2020-01-27 00:42:00 +01:00
|
|
|
struct rpc_conn {
|
|
|
|
int fd;
|
|
|
|
MEMBUF(char) mb;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct plugin {
|
|
|
|
/* lightningd interaction */
|
|
|
|
struct io_conn *stdin_conn;
|
|
|
|
struct io_conn *stdout_conn;
|
|
|
|
|
|
|
|
/* To read from lightningd */
|
|
|
|
char *buffer;
|
|
|
|
size_t used, len_read;
|
|
|
|
|
|
|
|
/* To write to lightningd */
|
|
|
|
struct json_stream **js_arr;
|
|
|
|
|
2020-01-26 23:54:33 +01:00
|
|
|
/* Asynchronous RPC interaction */
|
|
|
|
struct io_conn *io_rpc_conn;
|
|
|
|
struct json_stream **rpc_js_arr;
|
|
|
|
char *rpc_buffer;
|
|
|
|
size_t rpc_used, rpc_len_read;
|
|
|
|
/* Tracking async RPC requests */
|
|
|
|
UINTMAP(struct out_req *) out_reqs;
|
|
|
|
u64 next_outreq_id;
|
|
|
|
|
|
|
|
/* Synchronous RPC interaction */
|
2020-01-27 00:42:00 +01:00
|
|
|
struct rpc_conn rpc_conn;
|
|
|
|
|
2020-01-26 23:54:33 +01:00
|
|
|
/* Plugin informations */
|
2020-01-27 00:42:00 +01:00
|
|
|
enum plugin_restartability restartability;
|
|
|
|
const struct plugin_command *commands;
|
|
|
|
size_t num_commands;
|
|
|
|
const struct plugin_notification *notif_subs;
|
|
|
|
size_t num_notif_subs;
|
|
|
|
const struct plugin_hook *hook_subs;
|
|
|
|
size_t num_hook_subs;
|
|
|
|
struct plugin_option *opts;
|
|
|
|
|
|
|
|
/* Anything special to do at init ? */
|
|
|
|
void (*init)(struct plugin *p,
|
|
|
|
const char *buf, const jsmntok_t *);
|
|
|
|
/* Has the manifest been sent already ? */
|
|
|
|
bool manifested;
|
|
|
|
/* Has init been received ? */
|
|
|
|
bool initialized;
|
2020-01-24 14:57:12 +01:00
|
|
|
|
|
|
|
/* 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;
|
|
|
|
/* Timers */
|
|
|
|
struct timers timers;
|
|
|
|
size_t in_timer;
|
|
|
|
|
|
|
|
bool deprecated_apis;
|
2020-01-27 00:42:00 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
struct command {
|
|
|
|
u64 *id;
|
|
|
|
const char *methodname;
|
|
|
|
bool usage_only;
|
|
|
|
struct plugin *plugin;
|
|
|
|
};
|
|
|
|
|
2019-01-15 05:13:27 +01:00
|
|
|
/* Create an array of these, one for each command you support. */
|
|
|
|
struct plugin_command {
|
|
|
|
const char *name;
|
2019-05-22 16:27:34 +02:00
|
|
|
const char *category;
|
2019-01-15 05:13:27 +01:00
|
|
|
const char *description;
|
|
|
|
const char *long_description;
|
|
|
|
struct command_result *(*handle)(struct command *cmd,
|
|
|
|
const char *buf,
|
|
|
|
const jsmntok_t *params);
|
|
|
|
};
|
|
|
|
|
2019-05-20 13:09:45 +02:00
|
|
|
/* Create an array of these, one for each --option you support. */
|
|
|
|
struct plugin_option {
|
|
|
|
const char *name;
|
2019-05-26 23:19:00 +02:00
|
|
|
const char *type;
|
2019-05-20 13:09:45 +02:00
|
|
|
const char *description;
|
|
|
|
char *(*handle)(const char *str, void *arg);
|
|
|
|
void *arg;
|
|
|
|
};
|
|
|
|
|
2019-12-04 18:19:14 +01:00
|
|
|
/* Create an array of these, one for each notification you subscribe to. */
|
|
|
|
struct plugin_notification {
|
|
|
|
const char *name;
|
|
|
|
void (*handle)(struct command *cmd,
|
|
|
|
const char *buf,
|
|
|
|
const jsmntok_t *params);
|
|
|
|
};
|
|
|
|
|
2019-12-05 11:28:32 +01:00
|
|
|
/* Create an array of these, one for each hook you subscribe to. */
|
|
|
|
struct plugin_hook {
|
|
|
|
const char *name;
|
|
|
|
struct command_result *(*handle)(struct command *cmd,
|
|
|
|
const char *buf,
|
|
|
|
const jsmntok_t *params);
|
|
|
|
};
|
|
|
|
|
2019-06-12 02:38:54 +02:00
|
|
|
/* Helper to create a zero or single-value JSON object; if @str is NULL,
|
|
|
|
* object is empty. */
|
|
|
|
struct json_out *json_out_obj(const tal_t *ctx,
|
|
|
|
const char *fieldname,
|
|
|
|
const char *str);
|
|
|
|
|
2019-01-15 05:13:27 +01:00
|
|
|
/* Return this iff the param() call failed in your handler. */
|
|
|
|
struct command_result *command_param_failed(void);
|
|
|
|
|
|
|
|
/* Call this on fatal error. */
|
2020-01-26 15:44:16 +01:00
|
|
|
void NORETURN plugin_err(struct plugin *p, const char *fmt, ...);
|
2019-01-15 05:13:27 +01:00
|
|
|
|
2019-05-21 09:32:31 +02:00
|
|
|
/* This command is finished, here's a detailed error; @cmd cannot be
|
2019-06-12 02:38:54 +02:00
|
|
|
* NULL, data can be NULL; otherwise it must be a JSON object. */
|
2019-01-15 05:13:27 +01:00
|
|
|
struct command_result *WARN_UNUSED_RESULT
|
|
|
|
command_done_err(struct command *cmd,
|
2020-01-26 13:52:29 +01:00
|
|
|
errcode_t code,
|
2019-01-15 05:13:27 +01:00
|
|
|
const char *errmsg,
|
2019-06-12 02:38:54 +02:00
|
|
|
const struct json_out *data);
|
|
|
|
|
2019-08-28 05:38:12 +02:00
|
|
|
/* Send a raw error response. Useful for forwarding a previous
|
|
|
|
* error after cleanup */
|
|
|
|
struct command_result *command_err_raw(struct command *cmd,
|
|
|
|
const char *json_str);
|
|
|
|
|
2019-06-12 02:38:54 +02:00
|
|
|
/* This command is finished, here's the result object; @cmd cannot be NULL. */
|
|
|
|
struct command_result *WARN_UNUSED_RESULT
|
|
|
|
command_success(struct command *cmd, const struct json_out *result);
|
2019-01-15 05:13:27 +01:00
|
|
|
|
2019-06-12 02:38:54 +02:00
|
|
|
/* Simple version where we just want to send a string, or NULL means an empty
|
|
|
|
* result object. @cmd cannot be NULL. */
|
2019-01-15 05:13:27 +01:00
|
|
|
struct command_result *WARN_UNUSED_RESULT
|
2019-06-12 02:38:54 +02:00
|
|
|
command_success_str(struct command *cmd, const char *str);
|
2019-01-15 05:13:27 +01:00
|
|
|
|
|
|
|
/* Synchronous helper to send command and extract single field from
|
|
|
|
* response; can only be used in init callback. */
|
|
|
|
const char *rpc_delve(const tal_t *ctx,
|
2020-01-27 00:42:00 +01:00
|
|
|
struct plugin *plugin,
|
2019-06-12 02:38:54 +02:00
|
|
|
const char *method,
|
|
|
|
const struct json_out *params TAKES,
|
2020-01-27 00:42:00 +01:00
|
|
|
const char *guide);
|
2019-01-15 05:13:27 +01:00
|
|
|
|
2019-06-12 02:38:54 +02:00
|
|
|
/* Async rpc request.
|
2019-05-20 13:10:54 +02:00
|
|
|
* @cmd can be NULL if we're coming from a timer callback.
|
2019-06-12 02:38:54 +02:00
|
|
|
* @params can be NULL, otherwise it's an array or object.
|
2019-05-20 13:10:54 +02:00
|
|
|
*/
|
2019-06-12 02:38:54 +02:00
|
|
|
struct command_result *
|
2020-01-27 13:06:02 +01:00
|
|
|
send_outreq_(struct plugin *plugin,
|
|
|
|
struct command *cmd,
|
2019-01-15 05:13:27 +01:00
|
|
|
const char *method,
|
|
|
|
struct command_result *(*cb)(struct command *command,
|
|
|
|
const char *buf,
|
|
|
|
const jsmntok_t *result,
|
|
|
|
void *arg),
|
|
|
|
struct command_result *(*errcb)(struct command *command,
|
|
|
|
const char *buf,
|
|
|
|
const jsmntok_t *result,
|
|
|
|
void *arg),
|
|
|
|
void *arg,
|
2019-06-12 02:38:54 +02:00
|
|
|
const struct json_out *params TAKES);
|
2019-01-15 05:13:27 +01:00
|
|
|
|
2020-01-27 13:06:02 +01:00
|
|
|
#define send_outreq(plugin, cmd, method, cb, errcb, arg, params) \
|
|
|
|
send_outreq_((plugin), (cmd), (method), \
|
2019-01-15 05:13:27 +01:00
|
|
|
typesafe_cb_preargs(struct command_result *, void *, \
|
|
|
|
(cb), (arg), \
|
|
|
|
struct command *command, \
|
|
|
|
const char *buf, \
|
|
|
|
const jsmntok_t *result), \
|
|
|
|
typesafe_cb_preargs(struct command_result *, void *, \
|
|
|
|
(errcb), (arg), \
|
|
|
|
struct command *command, \
|
|
|
|
const char *buf, \
|
|
|
|
const jsmntok_t *result), \
|
2019-06-12 02:38:54 +02:00
|
|
|
(arg), (params))
|
2019-01-15 05:13:27 +01:00
|
|
|
|
2019-05-21 09:32:31 +02:00
|
|
|
/* Callback to just forward error and close request; @cmd cannot be NULL */
|
2019-01-15 05:13:27 +01:00
|
|
|
struct command_result *forward_error(struct command *cmd,
|
|
|
|
const char *buf,
|
|
|
|
const jsmntok_t *error,
|
|
|
|
void *arg);
|
|
|
|
|
2019-05-21 09:32:31 +02:00
|
|
|
/* Callback to just forward result and close request; @cmd cannot be NULL */
|
2019-01-15 05:13:27 +01:00
|
|
|
struct command_result *forward_result(struct command *cmd,
|
|
|
|
const char *buf,
|
|
|
|
const jsmntok_t *result,
|
|
|
|
void *arg);
|
|
|
|
|
2019-05-21 09:32:31 +02:00
|
|
|
/* Callback for timer where we expect a 'command_result'. All timers
|
|
|
|
* must return this eventually, though they may do so via a convoluted
|
|
|
|
* send_req() path. */
|
2020-01-24 14:57:12 +01:00
|
|
|
struct command_result *timer_complete(struct plugin *p);
|
2019-05-20 13:10:54 +02:00
|
|
|
|
|
|
|
/* Access timer infrastructure to add a timer.
|
|
|
|
*
|
2019-05-21 09:32:31 +02:00
|
|
|
* Freeing this releases the timer, otherwise it's freed after @cb
|
|
|
|
* if it hasn't been freed already.
|
2019-05-20 13:10:54 +02:00
|
|
|
*/
|
2020-01-24 14:57:12 +01:00
|
|
|
struct plugin_timer *plugin_timer(struct plugin *p,
|
2019-05-20 13:10:54 +02:00
|
|
|
struct timerel t,
|
2020-01-24 14:57:12 +01:00
|
|
|
struct command_result *(*cb)(struct plugin *p));
|
2019-05-20 13:10:54 +02:00
|
|
|
|
2019-05-21 09:32:37 +02:00
|
|
|
/* Log something */
|
2020-01-26 15:44:16 +01:00
|
|
|
void plugin_log(struct plugin *p, enum log_level l, const char *fmt, ...) PRINTF_FMT(3, 4);
|
2019-05-21 09:32:37 +02:00
|
|
|
|
2019-05-20 13:09:45 +02:00
|
|
|
/* Macro to define arguments */
|
2019-05-26 23:19:00 +02:00
|
|
|
#define plugin_option(name, type, description, set, arg) \
|
2019-05-20 13:09:45 +02:00
|
|
|
(name), \
|
2019-05-26 23:19:00 +02:00
|
|
|
(type), \
|
2019-05-20 13:09:45 +02:00
|
|
|
(description), \
|
|
|
|
typesafe_cb_preargs(char *, void *, (set), (arg), const char *), \
|
|
|
|
(arg)
|
|
|
|
|
|
|
|
/* Standard helpers */
|
|
|
|
char *u64_option(const char *arg, u64 *i);
|
|
|
|
char *charp_option(const char *arg, char **p);
|
|
|
|
|
|
|
|
/* The main plugin runner: append with 0 or more plugin_option(), then NULL. */
|
|
|
|
void NORETURN LAST_ARG_NULL plugin_main(char *argv[],
|
2020-01-27 00:42:00 +01:00
|
|
|
void (*init)(struct plugin *p,
|
2019-07-29 14:14:19 +02:00
|
|
|
const char *buf, const jsmntok_t *),
|
2019-07-29 13:46:48 +02:00
|
|
|
const enum plugin_restartability restartability,
|
2019-05-20 13:09:45 +02:00
|
|
|
const struct plugin_command *commands,
|
2019-12-04 18:19:14 +01:00
|
|
|
size_t num_commands,
|
|
|
|
const struct plugin_notification *notif_subs,
|
|
|
|
size_t num_notif_subs,
|
2019-12-05 11:28:32 +01:00
|
|
|
const struct plugin_hook *hook_subs,
|
|
|
|
size_t num_hook_subs,
|
2019-12-04 18:19:14 +01:00
|
|
|
...);
|
2019-01-15 05:13:27 +01:00
|
|
|
#endif /* LIGHTNING_PLUGINS_LIBPLUGIN_H */
|