| 1039 | } |
| 1040 | |
| 1041 | static void handle_rpc_reply(const tal_t *working_ctx, |
| 1042 | struct plugin *plugin, const char *buf, const jsmntok_t *toks) |
| 1043 | { |
| 1044 | const jsmntok_t *idtok, *contenttok; |
| 1045 | struct out_req *out; |
| 1046 | struct command_result *res; |
| 1047 | bool cmd_freed; |
| 1048 | |
| 1049 | idtok = json_get_member(buf, toks, "id"); |
| 1050 | if (!idtok) |
| 1051 | /* FIXME: Don't simply ignore notifications! */ |
| 1052 | return; |
| 1053 | |
| 1054 | out = strmap_getn(&plugin->out_reqs, |
| 1055 | json_tok_full(buf, idtok), |
| 1056 | json_tok_full_len(idtok)); |
| 1057 | if (!out) { |
| 1058 | /* This can actually happen, if they free req! */ |
| 1059 | plugin_log(plugin, LOG_DBG, "JSON reply with unknown id '%.*s'", |
| 1060 | json_tok_full_len(toks), |
| 1061 | json_tok_full(buf, toks)); |
| 1062 | return; |
| 1063 | } |
| 1064 | |
| 1065 | /* We want to free this if callback doesn't. */ |
| 1066 | tal_steal(working_ctx, out); |
| 1067 | |
| 1068 | /* If they return complete, cmd should have been freed! */ |
| 1069 | cmd_freed = false; |
| 1070 | tal_add_destructor2(out->cmd, destroy_cmd_mark_freed, &cmd_freed); |
| 1071 | |
| 1072 | trace_span_resume(out); |
| 1073 | contenttok = json_get_member(buf, toks, "error"); |
| 1074 | |
| 1075 | /* Annotate the JSON-RPC span whether it succeeded or failed, |
| 1076 | * and then emit it. */ |
| 1077 | trace_span_tag(out, "error", contenttok ? "true" : "false"); |
| 1078 | trace_span_end(out); |
| 1079 | |
| 1080 | if (contenttok) { |
| 1081 | if (out->errcb) |
| 1082 | res = out->errcb(out->cmd, out->method, buf, contenttok, out->arg); |
| 1083 | else |
| 1084 | res = out->cb(out->cmd, out->method, buf, toks, out->arg); |
| 1085 | } else { |
| 1086 | contenttok = json_get_member(buf, toks, "result"); |
| 1087 | if (!contenttok) |
| 1088 | plugin_err(plugin, "Bad JSONRPC, no 'error' nor 'result': '%.*s'", |
| 1089 | json_tok_full_len(toks), |
| 1090 | json_tok_full(buf, toks)); |
| 1091 | /* errcb is NULL if it's a single whole-object callback */ |
| 1092 | if (out->errcb) |
| 1093 | res = out->cb(out->cmd, out->method, buf, contenttok, out->arg); |
| 1094 | else |
| 1095 | res = out->cb(out->cmd, out->method, buf, toks, out->arg); |
| 1096 | } |
| 1097 | |
| 1098 | if (res == &complete) { |
no test coverage detected