mirror of
https://github.com/vim/vim.git
synced 2025-11-15 23:14:06 -05:00
patch 8.0.0312: failure when a channel receives a split json message
Problem: When a json message arrives in pieces, the start is dropped and
the decoding fails.
Solution: Do not drop the start when it is still needed. (Kay Zheng) Add a
test. Reset the timeout when something is received.
This commit is contained in:
@@ -1840,39 +1840,42 @@ channel_save(channel_T *channel, ch_part_T part, char_u *buf, int len,
|
||||
return OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Try to fill the buffer of "reader".
|
||||
* Returns FALSE when nothing was added.
|
||||
*/
|
||||
static int
|
||||
channel_fill(js_read_T *reader)
|
||||
{
|
||||
channel_T *channel = (channel_T *)reader->js_cookie;
|
||||
ch_part_T part = reader->js_cookie_arg;
|
||||
char_u *next = channel_get(channel, part);
|
||||
int unused;
|
||||
int len;
|
||||
int keeplen;
|
||||
int addlen;
|
||||
char_u *p;
|
||||
|
||||
if (next == NULL)
|
||||
return FALSE;
|
||||
|
||||
unused = reader->js_end - reader->js_buf - reader->js_used;
|
||||
if (unused > 0)
|
||||
keeplen = reader->js_end - reader->js_buf;
|
||||
if (keeplen > 0)
|
||||
{
|
||||
/* Prepend unused text. */
|
||||
len = (int)STRLEN(next);
|
||||
p = alloc(unused + len + 1);
|
||||
addlen = (int)STRLEN(next);
|
||||
p = alloc(keeplen + addlen + 1);
|
||||
if (p == NULL)
|
||||
{
|
||||
vim_free(next);
|
||||
return FALSE;
|
||||
}
|
||||
mch_memmove(p, reader->js_buf + reader->js_used, unused);
|
||||
mch_memmove(p + unused, next, len + 1);
|
||||
mch_memmove(p, reader->js_buf, keeplen);
|
||||
mch_memmove(p + keeplen, next, addlen + 1);
|
||||
vim_free(next);
|
||||
next = p;
|
||||
}
|
||||
|
||||
vim_free(reader->js_buf);
|
||||
reader->js_buf = next;
|
||||
reader->js_used = 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -1952,16 +1955,20 @@ channel_parse_json(channel_T *channel, ch_part_T part)
|
||||
}
|
||||
|
||||
if (status == OK)
|
||||
chanpart->ch_waiting = FALSE;
|
||||
chanpart->ch_wait_len = 0;
|
||||
else if (status == MAYBE)
|
||||
{
|
||||
if (!chanpart->ch_waiting)
|
||||
size_t buflen = STRLEN(reader.js_buf);
|
||||
|
||||
if (chanpart->ch_wait_len < buflen)
|
||||
{
|
||||
/* First time encountering incomplete message, set a deadline of
|
||||
* 100 msec. */
|
||||
ch_log(channel, "Incomplete message - wait for more");
|
||||
/* First time encountering incomplete message or after receiving
|
||||
* more (but still incomplete): set a deadline of 100 msec. */
|
||||
ch_logn(channel,
|
||||
"Incomplete message (%d bytes) - wait 100 msec for more",
|
||||
buflen);
|
||||
reader.js_used = 0;
|
||||
chanpart->ch_waiting = TRUE;
|
||||
chanpart->ch_wait_len = buflen;
|
||||
#ifdef WIN32
|
||||
chanpart->ch_deadline = GetTickCount() + 100L;
|
||||
#else
|
||||
@@ -1992,7 +1999,8 @@ channel_parse_json(channel_T *channel, ch_part_T part)
|
||||
if (timeout)
|
||||
{
|
||||
status = FAIL;
|
||||
chanpart->ch_waiting = FALSE;
|
||||
chanpart->ch_wait_len = 0;
|
||||
ch_log(channel, "timed out");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2006,7 +2014,7 @@ channel_parse_json(channel_T *channel, ch_part_T part)
|
||||
{
|
||||
ch_error(channel, "Decoding failed - discarding input");
|
||||
ret = FALSE;
|
||||
chanpart->ch_waiting = FALSE;
|
||||
chanpart->ch_wait_len = 0;
|
||||
}
|
||||
else if (reader.js_buf[reader.js_used] != NUL)
|
||||
{
|
||||
@@ -3369,7 +3377,7 @@ channel_read_json_block(
|
||||
/* Wait for up to the timeout. If there was an incomplete message
|
||||
* use the deadline for that. */
|
||||
timeout = timeout_arg;
|
||||
if (chanpart->ch_waiting)
|
||||
if (chanpart->ch_wait_len > 0)
|
||||
{
|
||||
#ifdef WIN32
|
||||
timeout = chanpart->ch_deadline - GetTickCount() + 1;
|
||||
@@ -3389,7 +3397,7 @@ channel_read_json_block(
|
||||
{
|
||||
/* Something went wrong, channel_parse_json() didn't
|
||||
* discard message. Cancel waiting. */
|
||||
chanpart->ch_waiting = FALSE;
|
||||
chanpart->ch_wait_len = 0;
|
||||
timeout = timeout_arg;
|
||||
}
|
||||
else if (timeout > timeout_arg)
|
||||
|
||||
Reference in New Issue
Block a user