From 03cca297df5210f94be2246cfdb1ee9a30454bea Mon Sep 17 00:00:00 2001 From: Yegappan Lakshmanan Date: Mon, 18 Apr 2022 14:07:46 +0100 Subject: patch 8.2.4780: parsing an LSP message fails when it is split Problem: Parsing an LSP message fails when it is split. Solution: Collapse the received data before parsing. (Yegappan Lakshmanan, closes #10215) --- src/channel.c | 33 ++++++++++++++++++++++++--------- 1 file changed, 24 insertions(+), 9 deletions(-) (limited to 'src/channel.c') diff --git a/src/channel.c b/src/channel.c index 79f4dbc29b..b981af4006 100644 --- a/src/channel.c +++ b/src/channel.c @@ -2035,22 +2035,24 @@ channel_consume(channel_T *channel, ch_part_T part, int len) int channel_collapse(channel_T *channel, ch_part_T part, int want_nl) { - readq_T *head = &channel->ch_part[part].ch_head; - readq_T *node = head->rq_next; - readq_T *last_node; - readq_T *n; - char_u *newbuf; - char_u *p; - long_u len; + ch_mode_T mode = channel->ch_part[part].ch_mode; + readq_T *head = &channel->ch_part[part].ch_head; + readq_T *node = head->rq_next; + readq_T *last_node; + readq_T *n; + char_u *newbuf; + char_u *p; + long_u len; if (node == NULL || node->rq_next == NULL) return FAIL; last_node = node->rq_next; len = node->rq_buflen + last_node->rq_buflen; - if (want_nl) + if (want_nl || mode == MODE_LSP) while (last_node->rq_next != NULL - && channel_first_nl(last_node) == NULL) + && (mode == MODE_LSP + || channel_first_nl(last_node) == NULL)) { last_node = last_node->rq_next; len += last_node->rq_buflen; @@ -3006,6 +3008,12 @@ may_invoke_callback(channel_T *channel, ch_part_T part) // Get any json message in the queue. if (channel_get_json(channel, part, -1, FALSE, &listtv) == FAIL) { + if (ch_mode == MODE_LSP) + // In the "lsp" mode, the http header and the json payload may + // be received in multiple messages. So concatenate all the + // received messages. + (void)channel_collapse(channel, part, FALSE); + // Parse readahead, return when there is still no message. channel_parse_json(channel, part); if (channel_get_json(channel, part, -1, FALSE, &listtv) == FAIL) @@ -3974,6 +3982,7 @@ channel_read_json_block( sock_T fd; int timeout; chanpart_T *chanpart = &channel->ch_part[part]; + ch_mode_T mode = channel->ch_part[part].ch_mode; int retval = FAIL; ch_log(channel, "Blocking read JSON for id %d", id); @@ -3984,6 +3993,12 @@ channel_read_json_block( for (;;) { + if (mode == MODE_LSP) + // In the "lsp" mode, the http header and the json payload may be + // received in multiple messages. So concatenate all the received + // messages. + (void)channel_collapse(channel, part, FALSE); + more = channel_parse_json(channel, part); // search for message "id" -- cgit v1.2.3