Browse Source

libplugin: make init return a string.

Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
Changelog-Added: libplugin: init can return a non-NULL string to disable the plugin.
ppa
Rusty Russell 4 years ago
committed by Christian Decker
parent
commit
27c006f7aa
  1. 6
      plugins/autoclean.c
  2. 6
      plugins/bcli.c
  3. 6
      plugins/fetchinvoice.c
  4. 6
      plugins/keysend.c
  5. 21
      plugins/libplugin.c
  6. 5
      plugins/libplugin.h
  7. 8
      plugins/offers.c
  8. 6
      plugins/pay.c
  9. 3
      plugins/spender/main.c
  10. 15
      tests/plugins/test_libplugin.c
  11. 21
      tests/test_plugin.py

6
plugins/autoclean.c

@ -64,8 +64,8 @@ static struct command_result *json_autocleaninvoice(struct command *cmd,
expired_by, cycle_seconds)); expired_by, cycle_seconds));
} }
static void init(struct plugin *p, static const char *init(struct plugin *p,
const char *buf UNUSED, const jsmntok_t *config UNUSED) const char *buf UNUSED, const jsmntok_t *config UNUSED)
{ {
if (cycle_seconds) { if (cycle_seconds) {
plugin_log(p, LOG_INFORM, "autocleaning every %"PRIu64" seconds", cycle_seconds); plugin_log(p, LOG_INFORM, "autocleaning every %"PRIu64" seconds", cycle_seconds);
@ -73,6 +73,8 @@ static void init(struct plugin *p,
do_clean, p); do_clean, p);
} else } else
plugin_log(p, LOG_DBG, "autocleaning not active"); plugin_log(p, LOG_DBG, "autocleaning not active");
return NULL;
} }
static const struct plugin_command commands[] = { { static const struct plugin_command commands[] = { {

6
plugins/bcli.c

@ -870,12 +870,14 @@ static void wait_and_check_bitcoind(struct plugin *p)
tal_free(cmd); tal_free(cmd);
} }
static void init(struct plugin *p, const char *buffer UNUSED, static const char *init(struct plugin *p, const char *buffer UNUSED,
const jsmntok_t *config UNUSED) const jsmntok_t *config UNUSED)
{ {
wait_and_check_bitcoind(p); wait_and_check_bitcoind(p);
plugin_log(p, LOG_INFORM, plugin_log(p, LOG_INFORM,
"bitcoin-cli initialized and connected to bitcoind."); "bitcoin-cli initialized and connected to bitcoind.");
return NULL;
} }
static const struct plugin_command commands[] = { static const struct plugin_command commands[] = {

6
plugins/fetchinvoice.c

@ -1346,12 +1346,14 @@ static const struct plugin_command commands[] = {
}, },
}; };
static void init(struct plugin *p, const char *buf UNUSED, static const char *init(struct plugin *p, const char *buf UNUSED,
const jsmntok_t *config UNUSED) const jsmntok_t *config UNUSED)
{ {
rpc_scan(p, "getinfo", rpc_scan(p, "getinfo",
take(json_out_obj(NULL, NULL, NULL)), take(json_out_obj(NULL, NULL, NULL)),
"{id:%}", JSON_SCAN(json_to_node_id, &local_id)); "{id:%}", JSON_SCAN(json_to_node_id, &local_id));
return NULL;
} }
static const struct plugin_hook hooks[] = { static const struct plugin_hook hooks[] = {

6
plugins/keysend.c

@ -92,8 +92,8 @@ REGISTER_PAYMENT_MODIFIER(keysend, struct keysend_data *, keysend_init,
* End of keysend modifier * End of keysend modifier
*****************************************************************************/ *****************************************************************************/
static void init(struct plugin *p, const char *buf UNUSED, static const char *init(struct plugin *p, const char *buf UNUSED,
const jsmntok_t *config UNUSED) const jsmntok_t *config UNUSED)
{ {
rpc_scan(p, "getinfo", take(json_out_obj(NULL, NULL, NULL)), rpc_scan(p, "getinfo", take(json_out_obj(NULL, NULL, NULL)),
"{id:%}", JSON_SCAN(json_to_node_id, &my_id)); "{id:%}", JSON_SCAN(json_to_node_id, &my_id));
@ -102,6 +102,8 @@ static void init(struct plugin *p, const char *buf UNUSED,
take(json_out_obj(NULL, "config", "max-locktime-blocks")), take(json_out_obj(NULL, "config", "max-locktime-blocks")),
"{max-locktime-blocks:%}", "{max-locktime-blocks:%}",
JSON_SCAN(json_to_number, &maxdelay_default)); JSON_SCAN(json_to_number, &maxdelay_default));
return NULL;
} }
struct payment_modifier *pay_mods[8] = { struct payment_modifier *pay_mods[8] = {

21
plugins/libplugin.c

@ -71,8 +71,8 @@ struct plugin {
struct plugin_option *opts; struct plugin_option *opts;
/* Anything special to do at init ? */ /* Anything special to do at init ? */
void (*init)(struct plugin *p, const char *(*init)(struct plugin *p,
const char *buf, const jsmntok_t *); const char *buf, const jsmntok_t *);
/* Has the manifest been sent already ? */ /* Has the manifest been sent already ? */
bool manifested; bool manifested;
/* Has init been received ? */ /* Has init been received ? */
@ -878,8 +878,12 @@ static struct command_result *handle_init(struct command *cmd,
tal_free(opt); tal_free(opt);
} }
if (p->init) if (p->init) {
p->init(p, buf, configtok); const char *disable = p->init(p, buf, configtok);
if (disable)
return command_success(cmd, json_out_obj(cmd, "disable",
disable));
}
if (with_rpc) if (with_rpc)
io_new_conn(p, p->rpc_conn->fd, rpc_conn_init, p); io_new_conn(p, p->rpc_conn->fd, rpc_conn_init, p);
@ -1296,8 +1300,9 @@ static struct io_plan *stdout_conn_init(struct io_conn *conn,
} }
static struct plugin *new_plugin(const tal_t *ctx, static struct plugin *new_plugin(const tal_t *ctx,
void (*init)(struct plugin *p, const char *(*init)(struct plugin *p,
const char *buf, const jsmntok_t *), const char *buf,
const jsmntok_t *),
const enum plugin_restartability restartability, const enum plugin_restartability restartability,
bool init_rpc, bool init_rpc,
struct feature_set *features, struct feature_set *features,
@ -1365,8 +1370,8 @@ static struct plugin *new_plugin(const tal_t *ctx,
} }
void plugin_main(char *argv[], void plugin_main(char *argv[],
void (*init)(struct plugin *p, const char *(*init)(struct plugin *p,
const char *buf, const jsmntok_t *), const char *buf, const jsmntok_t *),
const enum plugin_restartability restartability, const enum plugin_restartability restartability,
bool init_rpc, bool init_rpc,
struct feature_set *features, struct feature_set *features,

5
plugins/libplugin.h

@ -277,8 +277,9 @@ char *flag_option(const char *arg, bool *i);
/* The main plugin runner: append with 0 or more plugin_option(), then NULL. */ /* The main plugin runner: append with 0 or more plugin_option(), then NULL. */
void NORETURN LAST_ARG_NULL plugin_main(char *argv[], void NORETURN LAST_ARG_NULL plugin_main(char *argv[],
void (*init)(struct plugin *p, const char *(*init)(struct plugin *p,
const char *buf, const jsmntok_t *), const char *buf,
const jsmntok_t *),
const enum plugin_restartability restartability, const enum plugin_restartability restartability,
bool init_rpc, bool init_rpc,
struct feature_set *features, struct feature_set *features,

8
plugins/offers.c

@ -665,9 +665,9 @@ static struct command_result *json_decode(struct command *cmd,
return command_finished(cmd, response); return command_finished(cmd, response);
} }
static void init(struct plugin *p, static const char *init(struct plugin *p,
const char *buf UNUSED, const char *buf UNUSED,
const jsmntok_t *config UNUSED) const jsmntok_t *config UNUSED)
{ {
struct pubkey k; struct pubkey k;
@ -681,6 +681,8 @@ static void init(struct plugin *p,
rpc_scan(p, "listconfigs", rpc_scan(p, "listconfigs",
take(json_out_obj(NULL, "config", "cltv-final")), take(json_out_obj(NULL, "config", "cltv-final")),
"{cltv-final:%}", JSON_SCAN(json_to_number, &cltv_final)); "{cltv-final:%}", JSON_SCAN(json_to_number, &cltv_final));
return NULL;
} }
static const struct plugin_command commands[] = { static const struct plugin_command commands[] = {

6
plugins/pay.c

@ -1902,8 +1902,8 @@ static struct command_result *json_listpays(struct command *cmd,
return send_outreq(cmd->plugin, req); return send_outreq(cmd->plugin, req);
} }
static void init(struct plugin *p, static const char *init(struct plugin *p,
const char *buf UNUSED, const jsmntok_t *config UNUSED) const char *buf UNUSED, const jsmntok_t *config UNUSED)
{ {
rpc_scan(p, "getinfo", take(json_out_obj(NULL, NULL, NULL)), rpc_scan(p, "getinfo", take(json_out_obj(NULL, NULL, NULL)),
"{id:%}", JSON_SCAN(json_to_node_id, &my_id)); "{id:%}", JSON_SCAN(json_to_node_id, &my_id));
@ -1912,6 +1912,8 @@ static void init(struct plugin *p,
take(json_out_obj(NULL, "config", "max-locktime-blocks")), take(json_out_obj(NULL, "config", "max-locktime-blocks")),
"{max-locktime-blocks:%}", "{max-locktime-blocks:%}",
JSON_SCAN(json_to_number, &maxdelay_default)); JSON_SCAN(json_to_number, &maxdelay_default));
return NULL;
} }
struct payment_modifier *paymod_mods[] = { struct payment_modifier *paymod_mods[] = {

3
plugins/spender/main.c

@ -9,10 +9,11 @@
* spending from the onchain wallet. */ * spending from the onchain wallet. */
static static
void spender_init(struct plugin *p, const char *b, const jsmntok_t *t) const char *spender_init(struct plugin *p, const char *b, const jsmntok_t *t)
{ {
openchannel_init(p, b, t); openchannel_init(p, b, t);
/* whatever_init(p, b, t); */ /* whatever_init(p, b, t); */
return NULL;
} }
int main(int argc, char **argv) int main(int argc, char **argv)

15
tests/plugins/test_libplugin.c

@ -5,7 +5,7 @@
const char *name_option; const char *name_option;
static bool self_disable = false;
static struct command_result *json_helloworld(struct command *cmd, static struct command_result *json_helloworld(struct command *cmd,
const char *buf, const char *buf,
@ -86,10 +86,15 @@ static struct command_result *json_testrpc(struct command *cmd,
return send_outreq(cmd->plugin, req); return send_outreq(cmd->plugin, req);
} }
static void init(struct plugin *p, static const char *init(struct plugin *p,
const char *buf UNUSED, const jsmntok_t *config UNUSED) const char *buf UNUSED,
const jsmntok_t *config UNUSED)
{ {
plugin_log(p, LOG_DBG, "test_libplugin initialised!"); plugin_log(p, LOG_DBG, "test_libplugin initialised!");
if (self_disable)
return "Disabled via selfdisable option";
return NULL;
} }
static const struct plugin_command commands[] = { { static const struct plugin_command commands[] = { {
@ -149,5 +154,9 @@ int main(int argc, char *argv[])
"string", "string",
"Who to say hello to.", "Who to say hello to.",
charp_option, &name_option), charp_option, &name_option),
plugin_option("selfdisable",
"flag",
"Whether to disable.",
flag_option, &self_disable),
NULL); NULL);
} }

21
tests/test_plugin.py

@ -2326,19 +2326,26 @@ def test_pyln_request_notify(node_factory):
def test_self_disable(node_factory): def test_self_disable(node_factory):
"""Test that plugin can disable itself without penalty. """Test that plugin can disable itself without penalty.
""" """
plugin_path = os.path.join( # This disables in response to getmanifest.
os.path.dirname(__file__), 'plugins/test_selfdisable' p1 = os.path.join(
os.path.dirname(__file__), 'plugins/test_selfdisable_after_getmanifest'
) )
l1 = node_factory.get_node(options={'important-plugin': plugin_path}) # This disables in response to init.
p2 = os.path.join(os.getcwd(), "tests/plugins/test_libplugin")
l1 = node_factory.get_node(options={'important-plugin': [p1, p2], 'selfdisable': None})
# Could happen before it gets set up. # Could happen before it gets set up.
l1.daemon.logsearch_start = 0 l1.daemon.logsearch_start = 0
l1.daemon.wait_for_log('test_selfdisable: disabled itself: "Self-disable test after getmanifest"') l1.daemon.wait_for_logs(['test_selfdisable_after_getmanifest: disabled itself: "Self-disable test after getmanifest"',
'test_libplugin: disabled itself at init: Disabled via selfdisable option'])
assert plugin_path not in [p['name'] for p in l1.rpc.plugin_list()['plugins']] assert p1 not in [p['name'] for p in l1.rpc.plugin_list()['plugins']]
assert p2 not in [p['name'] for p in l1.rpc.plugin_list()['plugins']]
# Also works with dynamic load attempts # Also works with dynamic load attempts
with pytest.raises(RpcError, match="Self-disable test after getmanifest"): with pytest.raises(RpcError, match="Self-disable test after getmanifest"):
l1.rpc.plugin_start(plugin_path) l1.rpc.plugin_start(p1)
# Now test the disable-in-init-response. # Also works with dynamic load attempts
with pytest.raises(RpcError, match="Disabled via selfdisable option"):
l1.rpc.plugin_start(p2, selfdisable=True)

Loading…
Cancel
Save