| 471 | } |
| 472 | |
| 473 | static struct command_result *handle_reply(struct node_id *peer, |
| 474 | u64 idnum, |
| 475 | const u8 *msg, size_t msglen, |
| 476 | bool terminal) |
| 477 | { |
| 478 | struct commando *ocmd; |
| 479 | struct json_stream *res; |
| 480 | const jsmntok_t *toks, *result, *err, *id; |
| 481 | const char *replystr; |
| 482 | size_t i; |
| 483 | const jsmntok_t *t; |
| 484 | |
| 485 | ocmd = find_commando(outgoing_commands, peer, &idnum); |
| 486 | if (!ocmd) { |
| 487 | plugin_log(plugin, LOG_DBG, |
| 488 | "Ignoring unexpected %s reply from %s (id %"PRIu64")", |
| 489 | terminal ? "terminal" : "partial", |
| 490 | fmt_node_id(tmpctx, peer), |
| 491 | idnum); |
| 492 | return NULL; |
| 493 | } |
| 494 | |
| 495 | /* FIXME: We buffer, but ideally we would stream! */ |
| 496 | /* listchannels is 71MB, so we need to allow some headroom! */ |
| 497 | append_contents(ocmd, msg, msglen, 500*1024*1024); |
| 498 | |
| 499 | if (!terminal) |
| 500 | return NULL; |
| 501 | |
| 502 | if (!ocmd->contents) |
| 503 | return command_fail(ocmd->cmd, COMMANDO_ERROR_LOCAL, "Reply was oversize"); |
| 504 | |
| 505 | replystr = (const char *)ocmd->contents; |
| 506 | toks = json_parse_simple(ocmd, replystr, tal_bytelen(ocmd->contents)); |
| 507 | if (!toks || toks[0].type != JSMN_OBJECT) |
| 508 | return command_fail(ocmd->cmd, COMMANDO_ERROR_LOCAL, |
| 509 | "Reply was unparsable: '%.*s'", |
| 510 | (int)tal_bytelen(ocmd->contents), replystr); |
| 511 | |
| 512 | id = json_get_member(replystr, toks, "id"); |
| 513 | |
| 514 | /* Old commando didn't reply with id, but newer should get it right! */ |
| 515 | if (id && !memeq(json_tok_full(replystr, id), json_tok_full_len(id), |
| 516 | ocmd->json_id, strlen(ocmd->json_id))) { |
| 517 | plugin_log(plugin, LOG_BROKEN, "Commando reply with wrong id:" |
| 518 | " I sent %s, they replied with %.*s!", |
| 519 | ocmd->json_id, |
| 520 | json_tok_full_len(id), json_tok_full(replystr, id)); |
| 521 | } |
| 522 | |
| 523 | err = json_get_member(replystr, toks, "error"); |
| 524 | if (err) { |
| 525 | const jsmntok_t *code = json_get_member(replystr, err, "code"); |
| 526 | const jsmntok_t *message = json_get_member(replystr, err, "message"); |
| 527 | const jsmntok_t *datatok = json_get_member(replystr, err, "data"); |
| 528 | struct json_out *data; |
| 529 | int ecode; |
| 530 | if (!code || !json_to_int(replystr, code, &ecode)) { |
no test coverage detected