| 708 | } |
| 709 | |
| 710 | static struct io_plan *plugin_read_json(struct io_conn *conn, |
| 711 | struct plugin *plugin) |
| 712 | { |
| 713 | bool success; |
| 714 | bool have_full; |
| 715 | |
| 716 | log_io(plugin->log, LOG_IO_IN, NULL, "", |
| 717 | plugin->buffer + plugin->used, plugin->len_read); |
| 718 | |
| 719 | /* Our JSON parser is pretty good at incremental parsing, but |
| 720 | * `getrawblock` gives a giant 2MB token, which forces it to re-parse |
| 721 | * every time until we have all of it. However, we can't complete a |
| 722 | * JSON object without a '}', so we do a cheaper check here. |
| 723 | */ |
| 724 | have_full = memchr(plugin->buffer + plugin->used, '}', |
| 725 | plugin->len_read); |
| 726 | |
| 727 | plugin->used += plugin->len_read; |
| 728 | if (plugin->used == tal_count(plugin->buffer)) |
| 729 | tal_resize(&plugin->buffer, plugin->used * 2); |
| 730 | |
| 731 | /* Read and process all messages from the connection */ |
| 732 | if (have_full) { |
| 733 | do { |
| 734 | bool destroyed; |
| 735 | const char *err; |
| 736 | err = |
| 737 | plugin_read_json_one(plugin, &success, &destroyed); |
| 738 | |
| 739 | /* If it's destroyed, conn is already freed! */ |
| 740 | if (destroyed) |
| 741 | return io_close(NULL); |
| 742 | |
| 743 | if (err) { |
| 744 | plugin_kill(plugin, LOG_UNUSUAL, |
| 745 | "%s", err); |
| 746 | /* plugin_kill frees plugin */ |
| 747 | return io_close(NULL); |
| 748 | } |
| 749 | } while (success); |
| 750 | } |
| 751 | |
| 752 | /* Now read more from the connection */ |
| 753 | return io_read_partial(plugin->stdout_conn, |
| 754 | plugin->buffer + plugin->used, |
| 755 | tal_count(plugin->buffer) - plugin->used, |
| 756 | &plugin->len_read, plugin_read_json, plugin); |
| 757 | } |
| 758 | |
| 759 | /* Mutual recursion */ |
| 760 | static struct io_plan *plugin_write_json(struct io_conn *conn, |
nothing calls this directly
no test coverage detected