Browse Source

plugins/libplugin: notifications support

Changelog-Added: plugins: libplugin now supports writing plugin which registers to notifications
travis-debug
darosior 5 years ago
committed by Christian Decker
parent
commit
3371f0cf78
  1. 1
      plugins/autoclean.c
  2. 2
      plugins/fundchannel.c
  3. 60
      plugins/libplugin.c
  4. 13
      plugins/libplugin.h
  5. 2
      plugins/pay.c

1
plugins/autoclean.c

@ -92,6 +92,7 @@ int main(int argc, char *argv[])
{ {
setup_locale(); setup_locale();
plugin_main(argv, init, PLUGIN_RESTARTABLE, commands, ARRAY_SIZE(commands), plugin_main(argv, init, PLUGIN_RESTARTABLE, commands, ARRAY_SIZE(commands),
NULL, 0,
plugin_option("autocleaninvoice-cycle", plugin_option("autocleaninvoice-cycle",
"string", "string",
"Perform cleanup of expired invoices every" "Perform cleanup of expired invoices every"

2
plugins/fundchannel.c

@ -512,5 +512,5 @@ static const struct plugin_command commands[] = { {
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
setup_locale(); setup_locale();
plugin_main(argv, init, PLUGIN_RESTARTABLE, commands, ARRAY_SIZE(commands), NULL); plugin_main(argv, init, PLUGIN_RESTARTABLE, commands, ARRAY_SIZE(commands), NULL, 0, NULL);
} }

60
plugins/libplugin.c

@ -51,7 +51,7 @@ struct plugin_conn {
static struct plugin_conn rpc_conn; static struct plugin_conn rpc_conn;
struct command { struct command {
u64 id; u64 *id;
const char *methodname; const char *methodname;
bool usage_only; bool usage_only;
}; };
@ -159,12 +159,15 @@ static struct command *read_json_request(const tal_t *ctx,
method = json_get_member(membuf_elems(&conn->mb), toks, "method"); method = json_get_member(membuf_elems(&conn->mb), toks, "method");
*params = json_get_member(membuf_elems(&conn->mb), toks, "params"); *params = json_get_member(membuf_elems(&conn->mb), toks, "params");
/* FIXME: Notifications don't have id! */
id = json_get_member(membuf_elems(&conn->mb), toks, "id"); id = json_get_member(membuf_elems(&conn->mb), toks, "id");
if (!json_to_u64(membuf_elems(&conn->mb), id, &cmd->id)) if (id) {
plugin_err("JSON id '%*.s' is not a number", cmd->id = tal(cmd, u64);
id->end - id->start, if(!json_to_u64(membuf_elems(&conn->mb), id, cmd->id))
membuf_elems(&conn->mb) + id->start); plugin_err("JSON id '%*.s' is not a number",
id->end - id->start,
membuf_elems(&conn->mb) + id->start);
} else
cmd->id = NULL;
cmd->usage_only = false; cmd->usage_only = false;
cmd->methodname = json_strdup(cmd, membuf_elems(&conn->mb), method); cmd->methodname = json_strdup(cmd, membuf_elems(&conn->mb), method);
@ -213,7 +216,7 @@ command_done_raw(struct command *cmd,
const char *label, const char *label,
const char *str, int size) const char *str, int size)
{ {
struct json_out *jout = start_json_rpc(cmd, cmd->id); struct json_out *jout = start_json_rpc(cmd, *cmd->id);
memcpy(json_out_member_direct(jout, label, size), str, size); memcpy(json_out_member_direct(jout, label, size), str, size);
@ -224,7 +227,7 @@ command_done_raw(struct command *cmd,
struct command_result *WARN_UNUSED_RESULT struct command_result *WARN_UNUSED_RESULT
command_success(struct command *cmd, const struct json_out *result) command_success(struct command *cmd, const struct json_out *result)
{ {
struct json_out *jout = start_json_rpc(cmd, cmd->id); struct json_out *jout = start_json_rpc(cmd, *cmd->id);
json_out_add_splice(jout, "result", result); json_out_add_splice(jout, "result", result);
finish_and_send_json(STDOUT_FILENO, jout); finish_and_send_json(STDOUT_FILENO, jout);
@ -234,7 +237,7 @@ command_success(struct command *cmd, const struct json_out *result)
struct command_result *WARN_UNUSED_RESULT struct command_result *WARN_UNUSED_RESULT
command_success_str(struct command *cmd, const char *str) command_success_str(struct command *cmd, const char *str)
{ {
struct json_out *jout = start_json_rpc(cmd, cmd->id); struct json_out *jout = start_json_rpc(cmd, *cmd->id);
if (str) if (str)
json_out_addstr(jout, "result", str); json_out_addstr(jout, "result", str);
@ -252,7 +255,7 @@ struct command_result *command_done_err(struct command *cmd,
const char *errmsg, const char *errmsg,
const struct json_out *data) const struct json_out *data)
{ {
struct json_out *jout = start_json_rpc(cmd, cmd->id); struct json_out *jout = start_json_rpc(cmd, *cmd->id);
json_out_start(jout, "error", '{'); json_out_start(jout, "error", '{');
json_out_add(jout, "code", false, "%d", code); json_out_add(jout, "code", false, "%d", code);
@ -483,6 +486,8 @@ static struct command_result *
handle_getmanifest(struct command *getmanifest_cmd, handle_getmanifest(struct command *getmanifest_cmd,
const struct plugin_command *commands, const struct plugin_command *commands,
size_t num_commands, size_t num_commands,
const struct plugin_notification *notif_subs,
size_t num_notif_subs,
const struct plugin_option *opts, const struct plugin_option *opts,
const enum plugin_restartability restartability) const enum plugin_restartability restartability)
{ {
@ -512,6 +517,12 @@ handle_getmanifest(struct command *getmanifest_cmd,
json_out_end(params, '}'); json_out_end(params, '}');
} }
json_out_end(params, ']'); json_out_end(params, ']');
json_out_start(params, "subscriptions", '[');
for (size_t i = 0; i < num_notif_subs; i++)
json_out_addstr(params, NULL, notif_subs[i].name);
json_out_end(params, ']');
json_out_addstr(params, "dynamic", restartability == PLUGIN_RESTARTABLE ? "true" : "false"); json_out_addstr(params, "dynamic", restartability == PLUGIN_RESTARTABLE ? "true" : "false");
json_out_end(params, '}'); json_out_end(params, '}');
json_out_finished(params); json_out_finished(params);
@ -612,13 +623,26 @@ static void handle_new_command(const tal_t *ctx,
struct plugin_conn *request_conn, struct plugin_conn *request_conn,
struct plugin_conn *rpc_conn, struct plugin_conn *rpc_conn,
const struct plugin_command *commands, const struct plugin_command *commands,
size_t num_commands) size_t num_commands,
const struct plugin_notification *notif_subs,
size_t num_notif_subs)
{ {
struct command *cmd; struct command *cmd;
const jsmntok_t *params; const jsmntok_t *params;
int reqlen; int reqlen;
cmd = read_json_request(ctx, request_conn, rpc_conn, &params, &reqlen); cmd = read_json_request(ctx, request_conn, rpc_conn, &params, &reqlen);
/* If this is a notification. */
if (!cmd->id) {
for (size_t i = 0; i < num_notif_subs; i++) {
if (streq(cmd->methodname, notif_subs[i].name)) {
notif_subs[i].handle(cmd, membuf_elems(&request_conn->mb),
params);
membuf_consume(&request_conn->mb, reqlen);
}
}
return;
}
for (size_t i = 0; i < num_commands; i++) { for (size_t i = 0; i < num_commands; i++) {
if (streq(cmd->methodname, commands[i].name)) { if (streq(cmd->methodname, commands[i].name)) {
commands[i].handle(cmd, membuf_elems(&request_conn->mb), commands[i].handle(cmd, membuf_elems(&request_conn->mb),
@ -721,7 +745,10 @@ void plugin_main(char *argv[],
const char *buf, const jsmntok_t *), const char *buf, const jsmntok_t *),
const enum plugin_restartability restartability, const enum plugin_restartability restartability,
const struct plugin_command *commands, const struct plugin_command *commands,
size_t num_commands, ...) size_t num_commands,
const struct plugin_notification *notif_subs,
size_t num_notif_subs,
...)
{ {
struct plugin_conn request_conn; struct plugin_conn request_conn;
const tal_t *ctx = tal(NULL, char); const tal_t *ctx = tal(NULL, char);
@ -752,7 +779,7 @@ void plugin_main(char *argv[],
membuf_tal_realloc); membuf_tal_realloc);
uintmap_init(&out_reqs); uintmap_init(&out_reqs);
va_start(ap, num_commands); va_start(ap, num_notif_subs);
while ((optname = va_arg(ap, const char *)) != NULL) { while ((optname = va_arg(ap, const char *)) != NULL) {
struct plugin_option o; struct plugin_option o;
o.name = optname; o.name = optname;
@ -770,7 +797,8 @@ void plugin_main(char *argv[],
plugin_err("Expected getmanifest not %s", cmd->methodname); plugin_err("Expected getmanifest not %s", cmd->methodname);
membuf_consume(&request_conn.mb, reqlen); membuf_consume(&request_conn.mb, reqlen);
handle_getmanifest(cmd, commands, num_commands, opts, restartability); handle_getmanifest(cmd, commands, num_commands, notif_subs, num_notif_subs,
opts, restartability);
cmd = read_json_request(tmpctx, &request_conn, &rpc_conn, cmd = read_json_request(tmpctx, &request_conn, &rpc_conn,
&params, &reqlen); &params, &reqlen);
@ -797,7 +825,7 @@ void plugin_main(char *argv[],
/* If we already have some input, process now. */ /* If we already have some input, process now. */
if (membuf_num_elems(&request_conn.mb) != 0) { if (membuf_num_elems(&request_conn.mb) != 0) {
handle_new_command(ctx, &request_conn, &rpc_conn, handle_new_command(ctx, &request_conn, &rpc_conn,
commands, num_commands); commands, num_commands, notif_subs, num_notif_subs);
continue; continue;
} }
if (membuf_num_elems(&rpc_conn.mb) != 0) { if (membuf_num_elems(&rpc_conn.mb) != 0) {
@ -824,7 +852,7 @@ void plugin_main(char *argv[],
if (fds[0].revents & POLLIN) if (fds[0].revents & POLLIN)
handle_new_command(ctx, &request_conn, &rpc_conn, handle_new_command(ctx, &request_conn, &rpc_conn,
commands, num_commands); commands, num_commands, notif_subs, num_notif_subs);
if (fds[1].revents & POLLIN) if (fds[1].revents & POLLIN)
handle_rpc_reply(&rpc_conn); handle_rpc_reply(&rpc_conn);
} }

13
plugins/libplugin.h

@ -42,6 +42,14 @@ struct plugin_option {
void *arg; void *arg;
}; };
/* 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);
};
/* Helper to create a zero or single-value JSON object; if @str is NULL, /* Helper to create a zero or single-value JSON object; if @str is NULL,
* object is empty. */ * object is empty. */
struct json_out *json_out_obj(const tal_t *ctx, struct json_out *json_out_obj(const tal_t *ctx,
@ -162,5 +170,8 @@ void NORETURN LAST_ARG_NULL plugin_main(char *argv[],
const char *buf, const jsmntok_t *), const char *buf, const jsmntok_t *),
const enum plugin_restartability restartability, const enum plugin_restartability restartability,
const struct plugin_command *commands, const struct plugin_command *commands,
size_t num_commands, ...); size_t num_commands,
const struct plugin_notification *notif_subs,
size_t num_notif_subs,
...);
#endif /* LIGHTNING_PLUGINS_LIBPLUGIN_H */ #endif /* LIGHTNING_PLUGINS_LIBPLUGIN_H */

2
plugins/pay.c

@ -1395,5 +1395,5 @@ static const struct plugin_command commands[] = { {
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
setup_locale(); setup_locale();
plugin_main(argv, init, PLUGIN_RESTARTABLE, commands, ARRAY_SIZE(commands), NULL); plugin_main(argv, init, PLUGIN_RESTARTABLE, commands, ARRAY_SIZE(commands), NULL, 0, NULL);
} }

Loading…
Cancel
Save