From 9a2a09efd64aec614e6d74fa7b68ac5c96a940fd Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Tue, 4 Feb 2020 12:52:54 +0100 Subject: [PATCH] plugin: Introduce plugin type to allow singleton and chaining The newly introduced type is used to determine what the call semantics of the hook are. We have `single` corresponding to the old behavior, as well as `chain` which allows multiple plugins to register for the hook, and they are then called sequentially (if all plugins return `{"result": "continue"}`) or exit the chain if the hook event was handled. --- lightningd/invoice.c | 1 + lightningd/jsonrpc.c | 3 ++- lightningd/opening_control.c | 1 + lightningd/peer_control.c | 8 +++++--- lightningd/peer_htlcs.c | 3 ++- lightningd/plugin_hook.c | 3 ++- lightningd/plugin_hook.h | 22 +++++++++++++++++----- 7 files changed, 30 insertions(+), 11 deletions(-) diff --git a/lightningd/invoice.c b/lightningd/invoice.c index 7a0e6e578..5f27ff886 100644 --- a/lightningd/invoice.c +++ b/lightningd/invoice.c @@ -269,6 +269,7 @@ invoice_payment_hook_cb(struct invoice_payment_hook_payload *payload, } REGISTER_PLUGIN_HOOK(invoice_payment, + PLUGIN_HOOK_SINGLE, invoice_payment_hook_cb, struct invoice_payment_hook_payload *, invoice_payment_serialize, diff --git a/lightningd/jsonrpc.c b/lightningd/jsonrpc.c index d2f896904..fae55e6ac 100644 --- a/lightningd/jsonrpc.c +++ b/lightningd/jsonrpc.c @@ -753,7 +753,8 @@ rpc_command_hook_callback(struct rpc_command_hook_payload *p, "Bad response to 'rpc_command' hook.")); } -REGISTER_PLUGIN_HOOK(rpc_command, rpc_command_hook_callback, +REGISTER_PLUGIN_HOOK(rpc_command, PLUGIN_HOOK_SINGLE, + rpc_command_hook_callback, struct rpc_command_hook_payload *, rpc_command_hook_serialize, struct rpc_command_hook_payload *); diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index 810a45fe5..4654b0b63 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -821,6 +821,7 @@ static void openchannel_hook_cb(struct openchannel_hook_payload *payload, } REGISTER_PLUGIN_HOOK(openchannel, + PLUGIN_HOOK_SINGLE, openchannel_hook_cb, struct openchannel_hook_payload *, openchannel_hook_serialize, diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index bda3ff474..3ccc8dec5 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -908,7 +908,8 @@ send_error: tal_free(payload); } -REGISTER_PLUGIN_HOOK(peer_connected, peer_connected_hook_cb, +REGISTER_PLUGIN_HOOK(peer_connected, PLUGIN_HOOK_SINGLE, + peer_connected_hook_cb, struct peer_connected_hook_payload *, peer_connected_serialize, struct peer_connected_hook_payload *); @@ -2393,8 +2394,9 @@ static void custommsg_payload_serialize(struct custommsg_payload *payload, json_add_node_id(stream, "peer_id", &payload->peer_id); } -REGISTER_PLUGIN_HOOK(custommsg, custommsg_callback, struct custommsg_payload *, - custommsg_payload_serialize, struct custommsg_payload *); +REGISTER_PLUGIN_HOOK(custommsg, PLUGIN_HOOK_SINGLE, custommsg_callback, + struct custommsg_payload *, custommsg_payload_serialize, + struct custommsg_payload *); void handle_custommsg_in(struct lightningd *ld, const struct node_id *peer_id, const u8 *msg) diff --git a/lightningd/peer_htlcs.c b/lightningd/peer_htlcs.c index fa1340663..9635475c5 100644 --- a/lightningd/peer_htlcs.c +++ b/lightningd/peer_htlcs.c @@ -873,7 +873,8 @@ htlc_accepted_hook_callback(struct htlc_accepted_hook_payload *request, tal_free(request); } -REGISTER_PLUGIN_HOOK(htlc_accepted, htlc_accepted_hook_callback, +REGISTER_PLUGIN_HOOK(htlc_accepted, PLUGIN_HOOK_SINGLE, + htlc_accepted_hook_callback, struct htlc_accepted_hook_payload *, htlc_accepted_hook_serialize, struct htlc_accepted_hook_payload *); diff --git a/lightningd/plugin_hook.c b/lightningd/plugin_hook.c index 064735e28..dd2c00b76 100644 --- a/lightningd/plugin_hook.c +++ b/lightningd/plugin_hook.c @@ -130,7 +130,8 @@ void plugin_hook_call_(struct lightningd *ld, const struct plugin_hook *hook, * annoying, and to make it clear that it's totally synchronous. */ /* Special synchronous hook for db */ -static struct plugin_hook db_write_hook = { "db_write", NULL, NULL, NULL }; +static struct plugin_hook db_write_hook = {"db_write", PLUGIN_HOOK_SINGLE, NULL, + NULL, NULL}; AUTODATA(hooks, &db_write_hook); static void db_hook_response(const char *buffer, const jsmntok_t *toks, diff --git a/lightningd/plugin_hook.h b/lightningd/plugin_hook.h index 2c4876625..d803b14cf 100644 --- a/lightningd/plugin_hook.h +++ b/lightningd/plugin_hook.h @@ -44,8 +44,18 @@ * and callback have the correct type. */ +enum plugin_hook_type { + PLUGIN_HOOK_SINGLE, + PLUGIN_HOOK_CHAIN, +}; + struct plugin_hook { const char *name; + + /* Which type of plugin is this? It'll determine how many plugins can + * register this hook, and how the hooks are called. */ + enum plugin_hook_type type; + void (*response_cb)(void *arg, const char *buffer, const jsmntok_t *toks); void (*serialize_payload)(void *src, struct json_stream *dest); @@ -84,14 +94,16 @@ void plugin_hook_call_(struct lightningd *ld, const struct plugin_hook *hook, * response_cb function accepts the deserialized response format and * an arbitrary extra argument used to maintain context. */ -#define REGISTER_PLUGIN_HOOK(name, response_cb, response_cb_arg_type, \ +#define REGISTER_PLUGIN_HOOK(name, type, response_cb, response_cb_arg_type, \ serialize_payload, payload_type) \ struct plugin_hook name##_hook_gen = { \ stringify(name), \ - typesafe_cb_cast(void (*)(void *, const char *, const jsmntok_t *),\ - void (*)(response_cb_arg_type, \ - const char *, const jsmntok_t *), \ - response_cb), \ + type, \ + typesafe_cb_cast( \ + void (*)(void *, const char *, const jsmntok_t *), \ + void (*)(response_cb_arg_type, const char *, \ + const jsmntok_t *), \ + response_cb), \ typesafe_cb_cast(void (*)(void *, struct json_stream *), \ void (*)(payload_type, struct json_stream *), \ serialize_payload), \