diff --git a/common/json_parse_simple.c b/common/json_parse_simple.c index 9fe94229c..236c89bef 100644 --- a/common/json_parse_simple.c +++ b/common/json_parse_simple.c @@ -206,7 +206,9 @@ const char *json_get_id(const tal_t *ctx, const jsmntok_t *idtok = json_get_member(buffer, obj, "id"); if (!idtok) return NULL; - return json_strdup(ctx, buffer, idtok); + return tal_strndup(ctx, + json_tok_full(buffer, idtok), + json_tok_full_len(idtok)); } /*----------------------------------------------------------------------------- diff --git a/common/json_parse_simple.h b/common/json_parse_simple.h index 4092dad75..697dd4bad 100644 --- a/common/json_parse_simple.h +++ b/common/json_parse_simple.h @@ -66,7 +66,7 @@ const jsmntok_t *json_get_member(const char *buffer, const jsmntok_t tok[], /* Get index'th array member. */ const jsmntok_t *json_get_arr(const jsmntok_t tok[], size_t index); -/* Helper to get "id" field from object. */ +/* Helper to get "id" field from object (including any quotes!). */ const char *json_get_id(const tal_t *ctx, const char *buffer, const jsmntok_t *obj); diff --git a/common/json_stream.c b/common/json_stream.c index 59a21d280..59c80fbaf 100644 --- a/common/json_stream.c +++ b/common/json_stream.c @@ -239,9 +239,6 @@ void json_add_jsonstr(struct json_stream *js, { char *p; - if (!json_filter_ok(js->filter, fieldname)) - return; - /* NOTE: Filtering doesn't really work here! */ if (!json_filter_ok(js->filter, fieldname)) return; @@ -690,3 +687,11 @@ void json_add_lease_rates(struct json_stream *result, rates->channel_fee_max_proportional_thousandths); } +void json_add_id(struct json_stream *result, const char *id) +{ + char *p; + + /* Bypass escape-required assertion in json_out_add */ + p = json_member_direct(result, "id", strlen(id)); + memcpy(p, id, strlen(id)); +} diff --git a/common/json_stream.h b/common/json_stream.h index afcd29a57..31c73c1ef 100644 --- a/common/json_stream.h +++ b/common/json_stream.h @@ -390,4 +390,7 @@ void json_add_psbt(struct json_stream *stream, * Note that field names are set */ void json_add_lease_rates(struct json_stream *result, const struct lease_rates *rates); + +/* Add an id field literally (i.e. it's already a JSON primitive or string!) */ +void json_add_id(struct json_stream *result, const char *id); #endif /* LIGHTNING_COMMON_JSON_STREAM_H */ diff --git a/plugins/libplugin.c b/plugins/libplugin.c index ee813acc6..9d78ccc85 100644 --- a/plugins/libplugin.c +++ b/plugins/libplugin.c @@ -177,14 +177,22 @@ static const char *get_json_id(const tal_t *ctx, const char *cmd_id, const char *method) { - if (cmd_id) - return tal_fmt(ctx, "%s/%s:%s#%"PRIu64, - cmd_id, - plugin->id, method, - plugin->next_outreq_id++); - return tal_fmt(ctx, "%s:%s#%"PRIu64, - plugin->id, method, - plugin->next_outreq_id++); + const char *prefix; + + if (cmd_id) { + /* Strip quotes! */ + if (strstarts(cmd_id, "\"")) { + assert(strlen(cmd_id) >= 2); + assert(strends(cmd_id, "\"")); + prefix = tal_fmt(tmpctx, "%.*s/", + (int)strlen(cmd_id) - 2, cmd_id + 1); + } else + prefix = tal_fmt(tmpctx, "%s/", cmd_id); + } else + prefix = ""; + + return tal_fmt(ctx, "\"%s%s:%s#%"PRIu64"\"", + prefix, plugin->id, method, plugin->next_outreq_id++); } static void destroy_out_req(struct out_req *out_req, struct plugin *plugin) @@ -225,7 +233,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_string(out->js, "id", out->id); + json_add_id(out->js, out->id); json_add_string(out->js, "method", method); if (out->errcb) json_object_start(out->js, "params"); @@ -251,7 +259,7 @@ static struct json_stream *jsonrpc_stream_start(struct command *cmd) json_object_start(js, NULL); json_add_string(js, "jsonrpc", "2.0"); - json_add_string(js, "id", cmd->id); + json_add_id(js, cmd->id); return js; } @@ -548,10 +556,12 @@ static const jsmntok_t *sync_req(const tal_t *ctx, const jsmntok_t *contents; int reqlen; struct json_out *jout = json_out_new(tmpctx); + const char *id = get_json_id(tmpctx, plugin, "init", method); json_out_start(jout, NULL, '{'); json_out_addstr(jout, "jsonrpc", "2.0"); - json_out_addstr(jout, "id", get_json_id(tmpctx, plugin, "init", method)); + /* Copy in id *literally* */ + memcpy(json_out_member_direct(jout, "id", strlen(id)), id, strlen(id)); json_out_addstr(jout, "method", method); json_out_add_splice(jout, "params", params); if (taken(params)) @@ -810,8 +820,8 @@ static void handle_rpc_reply(struct plugin *plugin, const jsmntok_t *toks) return; out = strmap_getn(&plugin->out_reqs, - buf + idtok->start, - idtok->end - idtok->start); + json_tok_full(buf, idtok), + json_tok_full_len(idtok)); if (!out) { /* This can actually happen, if they free req! */ plugin_log(plugin, LOG_DBG, "JSON reply with unknown id '%.*s'", @@ -1376,7 +1386,7 @@ struct json_stream *plugin_notify_start(struct command *cmd, const char *method) json_add_string(js, "method", method); json_object_start(js, "params"); - json_add_string(js, "id", cmd->id); + json_add_id(js, cmd->id); return js; }