From 46fc14c51dfc41ca4b9501059522b0491e6fc95c Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 11 Jul 2023 01:53:43 +0930 Subject: [PATCH] plugins: add support for wildcard subscription. Requested-by: Shahana Farooqui @Shahana Signed-off-by: Rusty Russell Changelog-Added: Plugins: plugins can subscribe to all notifications using "*". --- doc/PLUGINS.md | 7 +++++++ .../plugin-development/event-notifications.md | 7 +++++++ lightningd/plugin.c | 19 ++++++++++++------- 3 files changed, 26 insertions(+), 7 deletions(-) diff --git a/doc/PLUGINS.md b/doc/PLUGINS.md index ada4384a3..a2f7fb476 100644 --- a/doc/PLUGINS.md +++ b/doc/PLUGINS.md @@ -431,6 +431,13 @@ above for example subscribes to the two topics `connect` and corresponding payloads are listed below. +### `*` + +This is a way of specifying that you want to subscribe to all possible +event notifications. It is not recommended, but is useful for plugins +which want to provide generic infrastructure for others (in future, we +may add the ability to dynamically subscribe/unsubscribe). + ### `channel_opened` A notification for topic `channel_opened` is sent if a peer successfully diff --git a/doc/guides/Developer-s Guide/plugin-development/event-notifications.md b/doc/guides/Developer-s Guide/plugin-development/event-notifications.md index 3dbc62cd6..61d2fa343 100644 --- a/doc/guides/Developer-s Guide/plugin-development/event-notifications.md +++ b/doc/guides/Developer-s Guide/plugin-development/event-notifications.md @@ -13,6 +13,13 @@ Event notifications allow a plugin to subscribe to events in `lightningd`. `ligh Plugins subscribe by returning an array of subscriptions as part of the `getmanifest` response. The result for the `getmanifest` call above for example subscribes to the two topics `connect` and `disconnect`. The topics that are currently defined and the corresponding payloads are listed below. +### `*` + +This is a way of specifying that you want to subscribe to all possible +event notifications. It is not recommended, but is useful for plugins +which want to provide generic infrastructure for others (in future, we +may add the ability to dynamically subscribe/unsubscribe). + ### `channel_opened` A notification for topic `channel_opened` is sent if a peer successfully funded a channel with us. It contains the peer id, the funding amount (in millisatoshis), the funding transaction id, and a boolean indicating if the funding transaction has been included into a block. diff --git a/lightningd/plugin.c b/lightningd/plugin.c index fa7a3c91a..dbe7f6c35 100644 --- a/lightningd/plugin.c +++ b/lightningd/plugin.c @@ -101,7 +101,8 @@ static void plugin_check_subscriptions(struct plugins *plugins, { for (size_t i = 0; i < tal_count(plugin->subscriptions); i++) { const char *topic = plugin->subscriptions[i]; - if (!notifications_have_topic(plugins, topic)) + if (!streq(topic, "*") + && !notifications_have_topic(plugins, topic)) log_unusual( plugin->log, "topic '%s' is not a known notification topic", @@ -1306,7 +1307,8 @@ static const char *plugin_subscriptions_add(struct plugin *plugin, const char *buffer, const jsmntok_t *resulttok) { - const jsmntok_t *subscriptions = + size_t i; + const jsmntok_t *s, *subscriptions = json_get_member(buffer, resulttok, "subscriptions"); if (!subscriptions) { @@ -1318,12 +1320,11 @@ static const char *plugin_subscriptions_add(struct plugin *plugin, return tal_fmt(plugin, "\"result.subscriptions\" is not an array"); } - for (int i = 0; i < subscriptions->size; i++) { + json_for_each_arr(i, s, subscriptions) { char *topic; - const jsmntok_t *s = json_get_arr(subscriptions, i); if (s->type != JSMN_STRING) { return tal_fmt(plugin, - "result.subscriptions[%d] is not a string: '%.*s'", i, + "result.subscriptions[%zu] is not a string: '%.*s'", i, json_tok_full_len(s), json_tok_full(buffer, s)); } @@ -2236,9 +2237,13 @@ void json_add_opt_disable_plugins(struct json_stream *response, static bool plugin_subscriptions_contains(struct plugin *plugin, const char *method) { - for (size_t i = 0; i < tal_count(plugin->subscriptions); i++) - if (streq(method, plugin->subscriptions[i])) + for (size_t i = 0; i < tal_count(plugin->subscriptions); i++) { + if (streq(method, plugin->subscriptions[i]) + /* Asterisk is magic "all" */ + || streq(plugin->subscriptions[i], "*")) { return true; + } + } return false; }