From d360075d2231865b7a20645cbd4ec07ed04a27fb Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 13 Sep 2022 06:49:12 +0930 Subject: [PATCH] libplugin: use string ids correctly. Build them from the command which caused them, and take plugin name as basename with extension stripped. Signed-off-by: Rusty Russell --- plugins/libplugin.c | 50 +++++++++++++++++++++++++++++--------------- plugins/libplugin.h | 2 +- tests/test_wallet.py | 2 +- 3 files changed, 35 insertions(+), 19 deletions(-) diff --git a/plugins/libplugin.c b/plugins/libplugin.c index 0aff78a7f..2de4b0de7 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -36,6 +37,9 @@ struct plugin { struct io_conn *stdin_conn; struct io_conn *stdout_conn; + /* to append to all our command ids */ + const char *id; + /* To read from lightningd */ char *buffer; size_t used, len_read; @@ -53,7 +57,7 @@ struct plugin { jsmn_parser rpc_parser; jsmntok_t *rpc_toks; /* Tracking async RPC requests */ - UINTMAP(struct out_req *) out_reqs; + STRMAP(struct out_req *) out_reqs; u64 next_outreq_id; /* Synchronous RPC interaction */ @@ -172,12 +176,20 @@ jsonrpc_request_start_(struct plugin *plugin, struct command *cmd, struct out_req *out; out = tal(plugin, struct out_req); - out->id = plugin->next_outreq_id++; + if (cmd) + out->id = tal_fmt(out, "%s/%s:%s#%"PRIu64, cmd->id, + plugin->id, method, + plugin->next_outreq_id); + else + out->id = tal_fmt(out, "%s:%s#%"PRIu64, + plugin->id, method, + plugin->next_outreq_id); + plugin->next_outreq_id++; out->cmd = cmd; out->cb = cb; out->errcb = errcb; out->arg = arg; - uintmap_add(&plugin->out_reqs, out->id, out); + strmap_add(&plugin->out_reqs, out->id, out); /* If command goes away, don't call callbacks! */ if (out->cmd) @@ -186,7 +198,7 @@ jsonrpc_request_start_(struct plugin *plugin, struct command *cmd, out->js = new_json_stream(NULL, cmd, NULL); json_object_start(out->js, NULL); json_add_string(out->js, "jsonrpc", "2.0"); - json_add_u64(out->js, "id", out->id); + json_add_string(out->js, "id", out->id); json_add_string(out->js, "method", method); if (out->errcb) json_object_start(out->js, "params"); @@ -667,22 +679,19 @@ static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks) const jsmntok_t *idtok, *contenttok; struct out_req *out; struct command_result *res; - u64 id; idtok = json_get_member(plugin->rpc_buffer, toks, "id"); if (!idtok) /* FIXME: Don't simply ignore notifications! */ return; - if (!json_to_u64(plugin->rpc_buffer, idtok, &id)) - plugin_err(plugin, "JSON reply without numeric id '%.*s'", + out = strmap_getn(&plugin->out_reqs, + plugin->rpc_buffer + idtok->start, + idtok->end - idtok->start); + if (!out) + plugin_err(plugin, "JSON reply with unknown id '%.*s'", json_tok_full_len(toks), json_tok_full(plugin->rpc_buffer, toks)); - out = uintmap_get(&plugin->out_reqs, id); - if (!out) - plugin_err(plugin, "JSON reply with unknown id '%.*s' (%"PRIu64")", - json_tok_full_len(toks), - json_tok_full(plugin->rpc_buffer, toks), id); /* Remove destructor if one existed */ if (out->cmd) @@ -690,7 +699,7 @@ static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks) /* We want to free this if callback doesn't. */ tal_steal(tmpctx, out); - uintmap_del(&plugin->out_reqs, out->id); + strmap_del(&plugin->out_reqs, out->id, NULL); contenttok = json_get_member(plugin->rpc_buffer, toks, "error"); if (contenttok) { @@ -1356,8 +1365,8 @@ static void memleak_check(struct plugin *plugin, struct command *cmd) /* Now delete plugin and anything it has pointers to. */ memleak_remove_region(memtable, plugin, sizeof(*plugin)); - /* Memleak needs some help to see into intmaps */ - memleak_remove_uintmap(memtable, &plugin->out_reqs); + /* Memleak needs some help to see into strmaps */ + memleak_remove_strmap(memtable, &plugin->out_reqs); /* We know usage strings are referred to. */ memleak_remove_strmap(memtable, &cmd->plugin->usagemap); @@ -1587,6 +1596,7 @@ static struct io_plan *stdout_conn_init(struct io_conn *conn, } static struct plugin *new_plugin(const tal_t *ctx, + const char *argv0, const char *(*init)(struct plugin *p, const char *buf, const jsmntok_t *), @@ -1605,7 +1615,12 @@ static struct plugin *new_plugin(const tal_t *ctx, { const char *optname; struct plugin *p = tal(ctx, struct plugin); + char *name; + /* id is our name, without extension (not that we expect any, in C!) */ + name = path_basename(p, argv0); + name[path_ext_off(name)] = '\0'; + p->id = name; p->buffer = tal_arr(p, char, 64); p->js_arr = tal_arr(p, struct json_stream *, 0); p->used = 0; @@ -1620,7 +1635,7 @@ static struct plugin *new_plugin(const tal_t *ctx, jsmn_init(&p->rpc_parser); p->rpc_toks = toks_alloc(p); p->next_outreq_id = 0; - uintmap_init(&p->out_reqs); + strmap_init(&p->out_reqs); p->desired_features = tal_steal(p, features); if (init_rpc) { @@ -1698,7 +1713,8 @@ void plugin_main(char *argv[], daemon_setup(argv[0], NULL, NULL); va_start(ap, num_notif_topics); - plugin = new_plugin(NULL, init, restartability, init_rpc, features, commands, + plugin = new_plugin(NULL, argv[0], + init, restartability, init_rpc, features, commands, num_commands, notif_subs, num_notif_subs, hook_subs, num_hook_subs, notif_topics, num_notif_topics, ap); va_end(ap); diff --git a/plugins/libplugin.h b/plugins/libplugin.h index 50c24da89..ba7c6b4ab 100644 --- a/plugins/libplugin.h +++ b/plugins/libplugin.h @@ -32,7 +32,7 @@ enum plugin_restartability { struct out_req { /* The unique id of this request. */ - u64 id; + const char *id; /* The command which is why we're calling this rpc. */ struct command *cmd; /* The request stream. */ diff --git a/tests/test_wallet.py b/tests/test_wallet.py index bed459f2a..5b25d5a4a 100644 --- a/tests/test_wallet.py +++ b/tests/test_wallet.py @@ -60,7 +60,7 @@ def test_withdraw(node_factory, bitcoind): out = l1.rpc.withdraw(waddr, 2 * amount) # Side note: sendrawtransaction will trace back to withdrawl - l1.daemon.wait_for_log(": OUT:id=[0-9]*/cln:sendrawtransaction#[0-9]*") + l1.daemon.wait_for_log(": OUT:id=[0-9]*/cln:withdraw#[0-9]*/txprepare:sendpsbt#[0-9]*/cln:sendrawtransaction#[0-9]*") # Make sure bitcoind received the withdrawal unspent = l1.bitcoin.rpc.listunspent(0)