comparison src/channel.c @ 10845:c31782d57569 v8.0.0312

patch 8.0.0312: failure when a channel receives a split json message commit https://github.com/vim/vim/commit/88989cc381c764978f7d7c8e387f3efc21333b4b Author: Bram Moolenaar <Bram@vim.org> Date: Mon Feb 6 21:56:09 2017 +0100 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.
author Christian Brabandt <cb@256bit.org>
date Mon, 06 Feb 2017 22:00:05 +0100
parents 98ee4f22da6e
children 2f041b367cd9
comparison
equal deleted inserted replaced
10844:1f16beccae3d 10845:c31782d57569
1838 fprintf(log_fd, "'\n"); 1838 fprintf(log_fd, "'\n");
1839 } 1839 }
1840 return OK; 1840 return OK;
1841 } 1841 }
1842 1842
1843 /*
1844 * Try to fill the buffer of "reader".
1845 * Returns FALSE when nothing was added.
1846 */
1843 static int 1847 static int
1844 channel_fill(js_read_T *reader) 1848 channel_fill(js_read_T *reader)
1845 { 1849 {
1846 channel_T *channel = (channel_T *)reader->js_cookie; 1850 channel_T *channel = (channel_T *)reader->js_cookie;
1847 ch_part_T part = reader->js_cookie_arg; 1851 ch_part_T part = reader->js_cookie_arg;
1848 char_u *next = channel_get(channel, part); 1852 char_u *next = channel_get(channel, part);
1849 int unused; 1853 int keeplen;
1850 int len; 1854 int addlen;
1851 char_u *p; 1855 char_u *p;
1852 1856
1853 if (next == NULL) 1857 if (next == NULL)
1854 return FALSE; 1858 return FALSE;
1855 1859
1856 unused = reader->js_end - reader->js_buf - reader->js_used; 1860 keeplen = reader->js_end - reader->js_buf;
1857 if (unused > 0) 1861 if (keeplen > 0)
1858 { 1862 {
1859 /* Prepend unused text. */ 1863 /* Prepend unused text. */
1860 len = (int)STRLEN(next); 1864 addlen = (int)STRLEN(next);
1861 p = alloc(unused + len + 1); 1865 p = alloc(keeplen + addlen + 1);
1862 if (p == NULL) 1866 if (p == NULL)
1863 { 1867 {
1864 vim_free(next); 1868 vim_free(next);
1865 return FALSE; 1869 return FALSE;
1866 } 1870 }
1867 mch_memmove(p, reader->js_buf + reader->js_used, unused); 1871 mch_memmove(p, reader->js_buf, keeplen);
1868 mch_memmove(p + unused, next, len + 1); 1872 mch_memmove(p + keeplen, next, addlen + 1);
1869 vim_free(next); 1873 vim_free(next);
1870 next = p; 1874 next = p;
1871 } 1875 }
1872 1876
1873 vim_free(reader->js_buf); 1877 vim_free(reader->js_buf);
1874 reader->js_buf = next; 1878 reader->js_buf = next;
1875 reader->js_used = 0;
1876 return TRUE; 1879 return TRUE;
1877 } 1880 }
1878 1881
1879 /* 1882 /*
1880 * Use the read buffer of "channel"/"part" and parse a JSON message that is 1883 * Use the read buffer of "channel"/"part" and parse a JSON message that is
1950 } 1953 }
1951 } 1954 }
1952 } 1955 }
1953 1956
1954 if (status == OK) 1957 if (status == OK)
1955 chanpart->ch_waiting = FALSE; 1958 chanpart->ch_wait_len = 0;
1956 else if (status == MAYBE) 1959 else if (status == MAYBE)
1957 { 1960 {
1958 if (!chanpart->ch_waiting) 1961 size_t buflen = STRLEN(reader.js_buf);
1959 { 1962
1960 /* First time encountering incomplete message, set a deadline of 1963 if (chanpart->ch_wait_len < buflen)
1961 * 100 msec. */ 1964 {
1962 ch_log(channel, "Incomplete message - wait for more"); 1965 /* First time encountering incomplete message or after receiving
1966 * more (but still incomplete): set a deadline of 100 msec. */
1967 ch_logn(channel,
1968 "Incomplete message (%d bytes) - wait 100 msec for more",
1969 buflen);
1963 reader.js_used = 0; 1970 reader.js_used = 0;
1964 chanpart->ch_waiting = TRUE; 1971 chanpart->ch_wait_len = buflen;
1965 #ifdef WIN32 1972 #ifdef WIN32
1966 chanpart->ch_deadline = GetTickCount() + 100L; 1973 chanpart->ch_deadline = GetTickCount() + 100L;
1967 #else 1974 #else
1968 gettimeofday(&chanpart->ch_deadline, NULL); 1975 gettimeofday(&chanpart->ch_deadline, NULL);
1969 chanpart->ch_deadline.tv_usec += 100 * 1000; 1976 chanpart->ch_deadline.tv_usec += 100 * 1000;
1990 } 1997 }
1991 #endif 1998 #endif
1992 if (timeout) 1999 if (timeout)
1993 { 2000 {
1994 status = FAIL; 2001 status = FAIL;
1995 chanpart->ch_waiting = FALSE; 2002 chanpart->ch_wait_len = 0;
2003 ch_log(channel, "timed out");
1996 } 2004 }
1997 else 2005 else
1998 { 2006 {
1999 reader.js_used = 0; 2007 reader.js_used = 0;
2000 ch_log(channel, "still waiting on incomplete message"); 2008 ch_log(channel, "still waiting on incomplete message");
2004 2012
2005 if (status == FAIL) 2013 if (status == FAIL)
2006 { 2014 {
2007 ch_error(channel, "Decoding failed - discarding input"); 2015 ch_error(channel, "Decoding failed - discarding input");
2008 ret = FALSE; 2016 ret = FALSE;
2009 chanpart->ch_waiting = FALSE; 2017 chanpart->ch_wait_len = 0;
2010 } 2018 }
2011 else if (reader.js_buf[reader.js_used] != NUL) 2019 else if (reader.js_buf[reader.js_used] != NUL)
2012 { 2020 {
2013 /* Put the unread part back into the channel. */ 2021 /* Put the unread part back into the channel. */
2014 channel_save(channel, part, reader.js_buf + reader.js_used, 2022 channel_save(channel, part, reader.js_buf + reader.js_used,
3367 continue; 3375 continue;
3368 3376
3369 /* Wait for up to the timeout. If there was an incomplete message 3377 /* Wait for up to the timeout. If there was an incomplete message
3370 * use the deadline for that. */ 3378 * use the deadline for that. */
3371 timeout = timeout_arg; 3379 timeout = timeout_arg;
3372 if (chanpart->ch_waiting) 3380 if (chanpart->ch_wait_len > 0)
3373 { 3381 {
3374 #ifdef WIN32 3382 #ifdef WIN32
3375 timeout = chanpart->ch_deadline - GetTickCount() + 1; 3383 timeout = chanpart->ch_deadline - GetTickCount() + 1;
3376 #else 3384 #else
3377 { 3385 {
3387 #endif 3395 #endif
3388 if (timeout < 0) 3396 if (timeout < 0)
3389 { 3397 {
3390 /* Something went wrong, channel_parse_json() didn't 3398 /* Something went wrong, channel_parse_json() didn't
3391 * discard message. Cancel waiting. */ 3399 * discard message. Cancel waiting. */
3392 chanpart->ch_waiting = FALSE; 3400 chanpart->ch_wait_len = 0;
3393 timeout = timeout_arg; 3401 timeout = timeout_arg;
3394 } 3402 }
3395 else if (timeout > timeout_arg) 3403 else if (timeout > timeout_arg)
3396 timeout = timeout_arg; 3404 timeout = timeout_arg;
3397 } 3405 }