From 25aff8166d493ab1e3bc06423418e9879c5ce85d Mon Sep 17 00:00:00 2001 From: Christian Decker Date: Mon, 20 Jul 2020 14:39:32 +0200 Subject: [PATCH] plugin: Do not automatically initialize the RPC connection in bcli Changelog-Fixed: plugin: `bcli` no longer logs a harmless warning about being unable to connect to the JSON-RPC interface. Changelog-Added: plugin: Plugins can opt out of having an RPC connection automatically initialized on startup. --- plugins/autoclean.c | 2 +- plugins/bcli.c | 3 +- plugins/fundchannel.c | 2 +- plugins/keysend.c | 2 +- plugins/libplugin.c | 71 +++++++++++++++++++++------------- plugins/libplugin.h | 1 + plugins/pay.c | 2 +- tests/plugins/test_libplugin.c | 3 +- 8 files changed, 54 insertions(+), 32 deletions(-) diff --git a/plugins/autoclean.c b/plugins/autoclean.c index acdab496e..eecdd52f7 100644 --- a/plugins/autoclean.c +++ b/plugins/autoclean.c @@ -88,7 +88,7 @@ static const struct plugin_command commands[] = { { int main(int argc, char *argv[]) { setup_locale(); - plugin_main(argv, init, PLUGIN_STATIC, NULL, commands, ARRAY_SIZE(commands), + plugin_main(argv, init, PLUGIN_STATIC, true, NULL, commands, ARRAY_SIZE(commands), NULL, 0, NULL, 0, plugin_option("autocleaninvoice-cycle", "string", diff --git a/plugins/bcli.c b/plugins/bcli.c index e3936a359..2aae8acc2 100644 --- a/plugins/bcli.c +++ b/plugins/bcli.c @@ -961,7 +961,8 @@ int main(int argc, char *argv[]) /* Initialize our global context object here to handle startup options. */ bitcoind = new_bitcoind(NULL); - plugin_main(argv, init, PLUGIN_STATIC, NULL, commands, ARRAY_SIZE(commands), + plugin_main(argv, init, PLUGIN_STATIC, false /* Do not init RPC on startup*/, + NULL, commands, ARRAY_SIZE(commands), NULL, 0, NULL, 0, plugin_option("bitcoin-datadir", "string", diff --git a/plugins/fundchannel.c b/plugins/fundchannel.c index 7caf70388..06b733088 100644 --- a/plugins/fundchannel.c +++ b/plugins/fundchannel.c @@ -446,6 +446,6 @@ static const struct plugin_command commands[] = { { int main(int argc, char *argv[]) { setup_locale(); - plugin_main(argv, init, PLUGIN_RESTARTABLE, NULL, commands, + plugin_main(argv, init, PLUGIN_RESTARTABLE, true, NULL, commands, ARRAY_SIZE(commands), NULL, 0, NULL, 0, NULL); } diff --git a/plugins/keysend.c b/plugins/keysend.c index 8d664caab..8dc5a419b 100644 --- a/plugins/keysend.c +++ b/plugins/keysend.c @@ -358,7 +358,7 @@ int main(int argc, char *argv[]) features.bits[i] = tal_arr(NULL, u8, 0); set_feature_bit(&features.bits[NODE_ANNOUNCE_FEATURE], KEYSEND_FEATUREBIT); - plugin_main(argv, init, PLUGIN_STATIC, &features, commands, + plugin_main(argv, init, PLUGIN_STATIC, true, &features, commands, ARRAY_SIZE(commands), NULL, 0, hooks, ARRAY_SIZE(hooks), NULL); } diff --git a/plugins/libplugin.c b/plugins/libplugin.c index c5c5500a6..e9c9cd124 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -83,6 +83,10 @@ struct plugin { /* Feature set for lightningd */ struct feature_set *our_features; + + /* Location of the RPC filename in case we need to defer RPC + * initialization or need to recover from a disconnect. */ + const char *rpc_location; }; /* command_result is mainly used as a compile-time check to encourage you @@ -763,7 +767,7 @@ static struct command_result *handle_init(struct command *cmd, char *dir, *network; struct json_out *param_obj; struct plugin *p = cmd->plugin; - bool with_rpc = true; + bool with_rpc = p->rpc_conn != NULL; configtok = json_delve(buf, params, ".configuration"); @@ -780,27 +784,39 @@ static struct command_result *handle_init(struct command *cmd, fsettok = json_delve(buf, configtok, ".feature_set"); p->our_features = json_to_feature_set(p, buf, fsettok); + /* Only attempt to connect if the plugin has configured the rpc_conn + * already, if that's not the case we were told to run without an RPC + * connection, so don't even log an error. */ rpctok = json_delve(buf, configtok, ".rpc-file"); - p->rpc_conn->fd = socket(AF_UNIX, SOCK_STREAM, 0); - if (rpctok->end - rpctok->start + 1 > sizeof(addr.sun_path)) - plugin_err(p, "rpc filename '%.*s' too long", - rpctok->end - rpctok->start, - buf + rpctok->start); - memcpy(addr.sun_path, buf + rpctok->start, rpctok->end - rpctok->start); - addr.sun_path[rpctok->end - rpctok->start] = '\0'; - addr.sun_family = AF_UNIX; - - if (connect(p->rpc_conn->fd, (struct sockaddr *)&addr, sizeof(addr)) != 0) { - with_rpc = false; - plugin_log(p, LOG_UNUSUAL, "Could not connect to '%.*s': %s", - rpctok->end - rpctok->start, buf + rpctok->start, - strerror(errno)); - } else { + p->rpc_location = json_strdup(p, buf, rpctok); + /* FIXME: Move this to its own function so we can initialize at a + * later point in time. */ + if (p->rpc_conn != NULL) { + p->rpc_conn->fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (strlen(p->rpc_location) + 1 > sizeof(addr.sun_path)) + plugin_err(p, "rpc filename '%s' too long", + p->rpc_location); + memcpy(addr.sun_path, buf + rpctok->start, + rpctok->end - rpctok->start); + addr.sun_path[rpctok->end - rpctok->start] = '\0'; + addr.sun_family = AF_UNIX; + + if (connect(p->rpc_conn->fd, (struct sockaddr *)&addr, + sizeof(addr)) != 0) { + with_rpc = false; + plugin_log(p, LOG_UNUSUAL, + "Could not connect to '%s': %s", + p->rpc_location, strerror(errno)); + } + + membuf_init(&p->rpc_conn->mb, tal_arr(p, char, READ_CHUNKSIZE), + READ_CHUNKSIZE, membuf_tal_realloc); + param_obj = json_out_obj(NULL, "config", "allow-deprecated-apis"); - deprecated_apis = streq(rpc_delve(tmpctx, p, "listconfigs", - take(param_obj), - ".allow-deprecated-apis"), - "true"); + deprecated_apis = + streq(rpc_delve(tmpctx, p, "listconfigs", take(param_obj), + ".allow-deprecated-apis"), + "true"); } opttok = json_get_member(buf, params, "options"); @@ -1182,6 +1198,7 @@ static struct plugin *new_plugin(const tal_t *ctx, void (*init)(struct plugin *p, const char *buf, const jsmntok_t *), const enum plugin_restartability restartability, + bool init_rpc, struct feature_set *features, const struct plugin_command *commands, size_t num_commands, @@ -1207,11 +1224,12 @@ static struct plugin *new_plugin(const tal_t *ctx, uintmap_init(&p->out_reqs); p->our_features = features; - /* Sync RPC FIXME: maybe go full async ? */ - p->rpc_conn = tal(p, struct rpc_conn); - membuf_init(&p->rpc_conn->mb, - tal_arr(p, char, READ_CHUNKSIZE), READ_CHUNKSIZE, - membuf_tal_realloc); + if (init_rpc) { + /* Sync RPC FIXME: maybe go full async ? */ + p->rpc_conn = tal(p, struct rpc_conn); + } else { + p->rpc_conn = NULL; + } p->init = init; p->manifested = p->initialized = false; @@ -1244,6 +1262,7 @@ void plugin_main(char *argv[], void (*init)(struct plugin *p, const char *buf, const jsmntok_t *), const enum plugin_restartability restartability, + bool init_rpc, struct feature_set *features, const struct plugin_command *commands, size_t num_commands, @@ -1264,7 +1283,7 @@ void plugin_main(char *argv[], daemon_setup(argv[0], NULL, NULL); va_start(ap, num_hook_subs); - plugin = new_plugin(NULL, init, restartability, features, commands, + plugin = new_plugin(NULL, init, restartability, init_rpc, features, commands, num_commands, notif_subs, num_notif_subs, hook_subs, num_hook_subs, ap); va_end(ap); diff --git a/plugins/libplugin.h b/plugins/libplugin.h index bc1e2ac21..87ec13e1c 100644 --- a/plugins/libplugin.h +++ b/plugins/libplugin.h @@ -248,6 +248,7 @@ void NORETURN LAST_ARG_NULL plugin_main(char *argv[], void (*init)(struct plugin *p, const char *buf, const jsmntok_t *), const enum plugin_restartability restartability, + bool init_rpc, struct feature_set *features, const struct plugin_command *commands, size_t num_commands, diff --git a/plugins/pay.c b/plugins/pay.c index 423816c4c..77e817037 100644 --- a/plugins/pay.c +++ b/plugins/pay.c @@ -2007,7 +2007,7 @@ static const struct plugin_command commands[] = { int main(int argc, char *argv[]) { setup_locale(); - plugin_main(argv, init, PLUGIN_RESTARTABLE, NULL, commands, + plugin_main(argv, init, PLUGIN_RESTARTABLE, true, NULL, commands, ARRAY_SIZE(commands), NULL, 0, NULL, 0, plugin_option("disable-mpp", "flag", "Disable multi-part payments.", diff --git a/tests/plugins/test_libplugin.c b/tests/plugins/test_libplugin.c index bff60e89b..66dcb7c18 100644 --- a/tests/plugins/test_libplugin.c +++ b/tests/plugins/test_libplugin.c @@ -124,7 +124,8 @@ static const struct plugin_notification notifs[] = { { int main(int argc, char *argv[]) { setup_locale(); - plugin_main(argv, init, PLUGIN_RESTARTABLE, NULL, commands, ARRAY_SIZE(commands), + plugin_main(argv, init, PLUGIN_RESTARTABLE, true, NULL, + commands, ARRAY_SIZE(commands), notifs, ARRAY_SIZE(notifs), hooks, ARRAY_SIZE(hooks), plugin_option("name", "string",