blob: d810925f9e6937bda726854d28e7c56d0a6ce130 [file] [log] [blame]
Bram Moolenaare0874f82016-01-24 20:36:41 +01001/* vi:set ts=8 sts=4 sw=4:
2 *
3 * VIM - Vi IMproved by Bram Moolenaar
4 *
5 * Do ":help uganda" in Vim to read copying and usage conditions.
6 * Do ":help credits" in Vim to see a list of people who contributed.
7 */
8
9/*
10 * Implements communication through a socket or any file handle.
11 */
12
13#include "vim.h"
14
15#if defined(FEAT_CHANNEL) || defined(PROTO)
16
Bram Moolenaard04a0202016-01-26 23:30:18 +010017/* TRUE when netbeans is running with a GUI. */
18#ifdef FEAT_GUI
19# define CH_HAS_GUI (gui.in_use || gui.starting)
20#endif
21
22/* Note: when making changes here also adjust configure.in. */
23#ifdef WIN32
24/* WinSock API is separated from C API, thus we can't use read(), write(),
25 * errno... */
26# define SOCK_ERRNO errno = WSAGetLastError()
27# undef ECONNREFUSED
28# define ECONNREFUSED WSAECONNREFUSED
Bram Moolenaar4d919d72016-02-05 22:36:41 +010029# undef EWOULDBLOCK
30# define EWOULDBLOCK WSAEWOULDBLOCK
Bram Moolenaard04a0202016-01-26 23:30:18 +010031# ifdef EINTR
32# undef EINTR
33# endif
34# define EINTR WSAEINTR
35# define sock_write(sd, buf, len) send(sd, buf, len, 0)
36# define sock_read(sd, buf, len) recv(sd, buf, len, 0)
37# define sock_close(sd) closesocket(sd)
38# define sleep(t) Sleep(t*1000) /* WinAPI Sleep() accepts milliseconds */
39#else
40# include <netdb.h>
41# include <netinet/in.h>
42
43# include <sys/socket.h>
44# ifdef HAVE_LIBGEN_H
45# include <libgen.h>
46# endif
47# define SOCK_ERRNO
48# define sock_write(sd, buf, len) write(sd, buf, len)
49# define sock_read(sd, buf, len) read(sd, buf, len)
50# define sock_close(sd) close(sd)
51#endif
52
53#ifdef FEAT_GUI_W32
54extern HWND s_hwnd; /* Gvim's Window handle */
55#endif
56
Bram Moolenaard04a0202016-01-26 23:30:18 +010057/*
58 * Information about all channels.
59 * There can be gaps for closed channels, they will be reused later.
60 */
Bram Moolenaare0874f82016-01-24 20:36:41 +010061static channel_T *channels = NULL;
62static int channel_count = 0;
63
Bram Moolenaar6463ca22016-02-13 17:04:46 +010064/* Log file opened with ch_logfile(). */
65static FILE *log_fd = NULL;
66
67 void
68ch_logfile(FILE *file)
69{
70 if (log_fd != NULL)
71 fclose(log_fd);
72 log_fd = file;
73 if (log_fd != NULL)
74 fprintf(log_fd, "==== start log session ====\n");
75}
76
77 static void
78ch_log_lead(char *what, int ch_idx)
79{
80 if (log_fd != NULL)
81 {
82 if (ch_idx >= 0)
83 fprintf(log_fd, "%son %d: ", what, ch_idx);
84 else
85 fprintf(log_fd, "%s: ", what);
86 }
87}
88
89 static void
90ch_log(int ch_idx, char *msg)
91{
92 if (log_fd != NULL)
93 {
94 ch_log_lead("", ch_idx);
95 fputs(msg, log_fd);
96 fflush(log_fd);
97 }
98}
99
100 static void
101ch_logn(int ch_idx, char *msg, int nr)
102{
103 if (log_fd != NULL)
104 {
105 ch_log_lead("", ch_idx);
106 fprintf(log_fd, msg, nr);
107 fflush(log_fd);
108 }
109}
110
111 static void
112ch_logs(int ch_idx, char *msg, char *name)
113{
114 if (log_fd != NULL)
115 {
116 ch_log_lead("", ch_idx);
117 fprintf(log_fd, msg, name);
118 fflush(log_fd);
119 }
120}
121
122 static void
123ch_logsn(int ch_idx, char *msg, char *name, int nr)
124{
125 if (log_fd != NULL)
126 {
127 ch_log_lead("", ch_idx);
128 fprintf(log_fd, msg, name, nr);
129 fflush(log_fd);
130 }
131}
132
133 static void
134ch_error(int ch_idx, char *msg)
135{
136 if (log_fd != NULL)
137 {
138 ch_log_lead("ERR ", ch_idx);
139 fputs(msg, log_fd);
140 fflush(log_fd);
141 }
142}
143
144 static void
145ch_errorn(int ch_idx, char *msg, int nr)
146{
147 if (log_fd != NULL)
148 {
149 ch_log_lead("ERR ", ch_idx);
150 fprintf(log_fd, msg, nr);
151 fflush(log_fd);
152 }
153}
154
155 static void
156ch_errors(int ch_idx, char *msg, char *arg)
157{
158 if (log_fd != NULL)
159 {
160 ch_log_lead("ERR ", ch_idx);
161 fprintf(log_fd, msg, arg);
162 fflush(log_fd);
163 }
164}
Bram Moolenaard04a0202016-01-26 23:30:18 +0100165
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100166#ifdef _WIN32
167# undef PERROR
168# define PERROR(msg) (void)emsg3((char_u *)"%s: %s", \
169 (char_u *)msg, (char_u *)strerror_win32(errno))
170
171 static char *
172strerror_win32(int eno)
173{
174 static LPVOID msgbuf = NULL;
175 char_u *ptr;
176
177 if (msgbuf)
178 LocalFree(msgbuf);
179 FormatMessage(
180 FORMAT_MESSAGE_ALLOCATE_BUFFER |
181 FORMAT_MESSAGE_FROM_SYSTEM |
182 FORMAT_MESSAGE_IGNORE_INSERTS,
183 NULL,
184 eno,
185 MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
186 (LPTSTR) &msgbuf,
187 0,
188 NULL);
189 /* chomp \r or \n */
190 for (ptr = (char_u *)msgbuf; *ptr; ptr++)
191 switch (*ptr)
192 {
193 case '\r':
194 STRMOVE(ptr, ptr + 1);
195 ptr--;
196 break;
197 case '\n':
198 if (*(ptr + 1) == '\0')
199 *ptr = '\0';
200 else
201 *ptr = ' ';
202 break;
203 }
204 return msgbuf;
205}
206#endif
207
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100208 static void
209init_channel(int ch_idx)
Bram Moolenaare0874f82016-01-24 20:36:41 +0100210{
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100211 channel_T *ch;
Bram Moolenaare0874f82016-01-24 20:36:41 +0100212
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100213 ch = &channels[ch_idx];
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100214 (void)vim_memset(ch, 0, sizeof(channel_T));
Bram Moolenaard04a0202016-01-26 23:30:18 +0100215
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100216 ch->ch_sock = (sock_T)-1;
217#ifdef CHANNEL_PIPES
218 ch->ch_in = -1;
219 ch->ch_out = -1;
220 ch->ch_err = -1;
221#endif
Bram Moolenaard04a0202016-01-26 23:30:18 +0100222#ifdef FEAT_GUI_X11
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100223 ch->ch_inputHandler = (XtInputId)NULL;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100224#endif
225#ifdef FEAT_GUI_GTK
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100226 ch->ch_inputHandler = 0;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100227#endif
228#ifdef FEAT_GUI_W32
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100229 ch->ch_inputHandler = -1;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100230#endif
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100231 /* initialize circular queues */
232 ch->ch_head.next = &ch->ch_head;
233 ch->ch_head.prev = &ch->ch_head;
Bram Moolenaara07fec92016-02-05 21:04:08 +0100234 ch->ch_cb_head.next = &ch->ch_cb_head;
235 ch->ch_cb_head.prev = &ch->ch_cb_head;
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100236 ch->ch_json_head.next = &ch->ch_json_head;
237 ch->ch_json_head.prev = &ch->ch_json_head;
Bram Moolenaare0874f82016-01-24 20:36:41 +0100238
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100239 ch->ch_timeout = 2000;
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100240}
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100241
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100242/*
243 * Add a new channel slot, return the index.
244 * The channel isn't actually used into ch_sock is set >= 0;
245 * Returns -1 if all channels are in use.
246 */
247 int
248add_channel(void)
249{
250 int ch_idx;
251
252 if (channels != NULL)
253 {
254 for (ch_idx = 0; ch_idx < channel_count; ++ch_idx)
255 if (!channel_is_open(ch_idx))
256 {
257 /* re-use a closed channel slot */
258 init_channel(ch_idx);
259 ch_log(ch_idx, "Opening channel (used before)\n");
260 return ch_idx;
261 }
262 if (channel_count == MAX_OPEN_CHANNELS)
263 return -1;
264 }
265 else
266 {
267 channels = (channel_T *)alloc((int)sizeof(channel_T)
268 * MAX_OPEN_CHANNELS);
269 if (channels == NULL)
270 return -1;
271 }
272 init_channel(channel_count);
273 ch_log(channel_count, "Opening new channel\n");
Bram Moolenaare0874f82016-01-24 20:36:41 +0100274 return channel_count++;
275}
276
Bram Moolenaard04a0202016-01-26 23:30:18 +0100277#if defined(FEAT_GUI) || defined(PROTO)
Bram Moolenaare0874f82016-01-24 20:36:41 +0100278/*
Bram Moolenaard04a0202016-01-26 23:30:18 +0100279 * Read a command from netbeans.
Bram Moolenaare0874f82016-01-24 20:36:41 +0100280 */
Bram Moolenaard04a0202016-01-26 23:30:18 +0100281#ifdef FEAT_GUI_X11
282 static void
283messageFromNetbeans(XtPointer clientData,
284 int *unused1 UNUSED,
285 XtInputId *unused2 UNUSED)
Bram Moolenaare0874f82016-01-24 20:36:41 +0100286{
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100287 channel_read((int)(long)clientData, FALSE, "messageFromNetbeans");
Bram Moolenaare0874f82016-01-24 20:36:41 +0100288}
Bram Moolenaard04a0202016-01-26 23:30:18 +0100289#endif
Bram Moolenaare0874f82016-01-24 20:36:41 +0100290
Bram Moolenaard04a0202016-01-26 23:30:18 +0100291#ifdef FEAT_GUI_GTK
292 static void
293messageFromNetbeans(gpointer clientData,
294 gint unused1 UNUSED,
295 GdkInputCondition unused2 UNUSED)
Bram Moolenaare0874f82016-01-24 20:36:41 +0100296{
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100297 channel_read((int)(long)clientData, FALSE, "messageFromNetbeans");
Bram Moolenaare0874f82016-01-24 20:36:41 +0100298}
299#endif
300
301 static void
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100302channel_gui_register(int ch_idx)
Bram Moolenaare0874f82016-01-24 20:36:41 +0100303{
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100304 channel_T *channel = &channels[ch_idx];
Bram Moolenaard04a0202016-01-26 23:30:18 +0100305
306 if (!CH_HAS_GUI)
307 return;
308
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100309 /* TODO: pipes */
Bram Moolenaard04a0202016-01-26 23:30:18 +0100310# ifdef FEAT_GUI_X11
311 /* tell notifier we are interested in being called
312 * when there is input on the editor connection socket
313 */
314 if (channel->ch_inputHandler == (XtInputId)NULL)
315 channel->ch_inputHandler =
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100316 XtAppAddInput((XtAppContext)app_context, channel->ch_sock,
Bram Moolenaard04a0202016-01-26 23:30:18 +0100317 (XtPointer)(XtInputReadMask + XtInputExceptMask),
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100318 messageFromNetbeans, (XtPointer)(long)ch_idx);
Bram Moolenaard04a0202016-01-26 23:30:18 +0100319# else
320# ifdef FEAT_GUI_GTK
321 /*
322 * Tell gdk we are interested in being called when there
323 * is input on the editor connection socket
324 */
325 if (channel->ch_inputHandler == 0)
326 channel->ch_inputHandler =
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100327 gdk_input_add((gint)channel->ch_sock, (GdkInputCondition)
Bram Moolenaard04a0202016-01-26 23:30:18 +0100328 ((int)GDK_INPUT_READ + (int)GDK_INPUT_EXCEPTION),
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100329 messageFromNetbeans, (gpointer)(long)ch_idx);
Bram Moolenaard04a0202016-01-26 23:30:18 +0100330# else
331# ifdef FEAT_GUI_W32
332 /*
333 * Tell Windows we are interested in receiving message when there
334 * is input on the editor connection socket.
Bram Moolenaard04a0202016-01-26 23:30:18 +0100335 */
336 if (channel->ch_inputHandler == -1)
337 channel->ch_inputHandler =
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100338 WSAAsyncSelect(channel->ch_sock, s_hwnd, WM_NETBEANS, FD_READ);
Bram Moolenaard04a0202016-01-26 23:30:18 +0100339# endif
340# endif
Bram Moolenaare0874f82016-01-24 20:36:41 +0100341# endif
Bram Moolenaard04a0202016-01-26 23:30:18 +0100342}
343
344/*
345 * Register any of our file descriptors with the GUI event handling system.
346 * Called when the GUI has started.
347 */
348 void
349channel_gui_register_all(void)
350{
351 int i;
352
353 for (i = 0; i < channel_count; ++i)
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100354 /* TODO: pipes */
355 if (channels[i].ch_sock >= 0)
Bram Moolenaard04a0202016-01-26 23:30:18 +0100356 channel_gui_register(i);
357}
358
359 static void
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100360channel_gui_unregister(int ch_idx)
Bram Moolenaard04a0202016-01-26 23:30:18 +0100361{
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100362 channel_T *channel = &channels[ch_idx];
Bram Moolenaard04a0202016-01-26 23:30:18 +0100363
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100364 /* TODO: pipes */
Bram Moolenaard04a0202016-01-26 23:30:18 +0100365# ifdef FEAT_GUI_X11
366 if (channel->ch_inputHandler != (XtInputId)NULL)
Bram Moolenaare0874f82016-01-24 20:36:41 +0100367 {
Bram Moolenaard04a0202016-01-26 23:30:18 +0100368 XtRemoveInput(channel->ch_inputHandler);
369 channel->ch_inputHandler = (XtInputId)NULL;
370 }
371# else
372# ifdef FEAT_GUI_GTK
373 if (channel->ch_inputHandler != 0)
374 {
375 gdk_input_remove(channel->ch_inputHandler);
376 channel->ch_inputHandler = 0;
377 }
378# else
379# ifdef FEAT_GUI_W32
380 if (channel->ch_inputHandler == 0)
381 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100382 WSAAsyncSelect(channel->ch_sock, s_hwnd, 0, 0);
Bram Moolenaard04a0202016-01-26 23:30:18 +0100383 channel->ch_inputHandler = -1;
384 }
385# endif
386# endif
387# endif
388}
389
390#endif
391
392/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100393 * Open a socket channel to "hostname":"port".
Bram Moolenaard04a0202016-01-26 23:30:18 +0100394 * Returns the channel number for success.
395 * Returns a negative number for failure.
396 */
397 int
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100398channel_open(char *hostname, int port_in, int waittime, void (*close_cb)(void))
Bram Moolenaard04a0202016-01-26 23:30:18 +0100399{
400 int sd;
401 struct sockaddr_in server;
402 struct hostent * host;
Bram Moolenaarf12d9832016-01-29 21:11:25 +0100403#ifdef WIN32
Bram Moolenaard04a0202016-01-26 23:30:18 +0100404 u_short port = port_in;
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100405 u_long val = 1;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100406#else
407 int port = port_in;
408#endif
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100409 int ch_idx;
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100410 int ret;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100411
Bram Moolenaarf12d9832016-01-29 21:11:25 +0100412#ifdef WIN32
Bram Moolenaard04a0202016-01-26 23:30:18 +0100413 channel_init_winsock();
414#endif
415
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100416 ch_idx = add_channel();
417 if (ch_idx < 0)
Bram Moolenaard04a0202016-01-26 23:30:18 +0100418 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100419 ch_error(-1, "All channels are in use.\n");
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100420 EMSG(_("E897: All channels are in use"));
Bram Moolenaard04a0202016-01-26 23:30:18 +0100421 return -1;
422 }
423
424 if ((sd = (sock_T)socket(AF_INET, SOCK_STREAM, 0)) == (sock_T)-1)
425 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100426 ch_error(-1, "in socket() in channel_open().\n");
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100427 PERROR("E898: socket() in channel_open()");
Bram Moolenaard04a0202016-01-26 23:30:18 +0100428 return -1;
429 }
430
431 /* Get the server internet address and put into addr structure */
432 /* fill in the socket address structure and connect to server */
433 vim_memset((char *)&server, 0, sizeof(server));
434 server.sin_family = AF_INET;
435 server.sin_port = htons(port);
436 if ((host = gethostbyname(hostname)) == NULL)
437 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100438 ch_error(-1, "in gethostbyname() in channel_open()\n");
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100439 PERROR("E901: gethostbyname() in channel_open()");
Bram Moolenaard04a0202016-01-26 23:30:18 +0100440 sock_close(sd);
441 return -1;
442 }
443 memcpy((char *)&server.sin_addr, host->h_addr, host->h_length);
444
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100445 if (waittime >= 0)
Bram Moolenaard04a0202016-01-26 23:30:18 +0100446 {
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100447 /* Make connect non-blocking. */
448 if (
449#ifdef _WIN32
450 ioctlsocket(sd, FIONBIO, &val) < 0
451#else
452 fcntl(sd, F_SETFL, O_NONBLOCK) < 0
453#endif
454 )
Bram Moolenaard04a0202016-01-26 23:30:18 +0100455 {
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100456 SOCK_ERRNO;
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100457 ch_errorn(-1, "channel_open: Connect failed with errno %d\n",
458 errno);
Bram Moolenaard04a0202016-01-26 23:30:18 +0100459 sock_close(sd);
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100460 return -1;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100461 }
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100462 }
463
464 /* Try connecting to the server. */
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100465 ch_logsn(-1, "Connecting to %s port %d", hostname, port);
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100466 ret = connect(sd, (struct sockaddr *)&server, sizeof(server));
467 SOCK_ERRNO;
468 if (ret < 0)
469 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100470 if (errno != EWOULDBLOCK
471#ifdef EINPROGRESS
472 && errno != EINPROGRESS
473#endif
474 )
Bram Moolenaard04a0202016-01-26 23:30:18 +0100475 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100476 ch_errorn(-1, "channel_open: Connect failed with errno %d\n",
477 errno);
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100478 PERROR(_("E902: Cannot connect to port"));
Bram Moolenaard04a0202016-01-26 23:30:18 +0100479 sock_close(sd);
480 return -1;
481 }
482 }
483
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100484 if (waittime >= 0 && ret < 0)
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100485 {
486 struct timeval tv;
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100487 fd_set wfds;
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100488
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100489 FD_ZERO(&wfds);
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100490 FD_SET(sd, &wfds);
Bram Moolenaar26dfc412016-02-06 18:18:54 +0100491 tv.tv_sec = waittime / 1000;
492 tv.tv_usec = (waittime % 1000) * 1000;
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100493 ret = select((int)sd + 1, NULL, &wfds, NULL, &tv);
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100494 if (ret < 0)
495 {
496 SOCK_ERRNO;
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100497 ch_errorn(-1, "channel_open: Connect failed with errno %d\n",
498 errno);
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100499 PERROR(_("E902: Cannot connect to port"));
500 sock_close(sd);
501 return -1;
502 }
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100503 if (!FD_ISSET(sd, &wfds))
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100504 {
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100505 /* don't give an error, we just timed out. */
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100506 sock_close(sd);
507 return -1;
508 }
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100509 }
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100510
Bram Moolenaar7a84dbe2016-02-07 21:29:00 +0100511 if (waittime >= 0)
512 {
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100513#ifdef _WIN32
514 val = 0;
515 ioctlsocket(sd, FIONBIO, &val);
516#else
Bram Moolenaarfbc4b4d2016-02-07 15:14:01 +0100517 (void)fcntl(sd, F_SETFL, 0);
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100518#endif
519 }
520
Bram Moolenaar0fa98e72016-02-07 22:21:19 +0100521 /* Only retry for netbeans. TODO: can we use a waittime instead? */
522 if (errno == ECONNREFUSED && close_cb != NULL)
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100523 {
524 sock_close(sd);
525 if ((sd = (sock_T)socket(AF_INET, SOCK_STREAM, 0)) == (sock_T)-1)
526 {
527 SOCK_ERRNO;
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100528 ch_log(-1, "socket() retry in channel_open()\n");
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100529 PERROR("E900: socket() retry in channel_open()");
530 return -1;
531 }
532 if (connect(sd, (struct sockaddr *)&server, sizeof(server)))
533 {
534 int retries = 36;
535 int success = FALSE;
536
537 SOCK_ERRNO;
538 while (retries-- && ((errno == ECONNREFUSED)
539 || (errno == EINTR)))
540 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100541 ch_log(-1, "retrying...\n");
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100542 mch_delay(3000L, TRUE);
543 ui_breakcheck();
544 if (got_int)
545 {
546 errno = EINTR;
547 break;
548 }
549 if (connect(sd, (struct sockaddr *)&server,
550 sizeof(server)) == 0)
551 {
552 success = TRUE;
553 break;
554 }
555 SOCK_ERRNO;
556 }
557 if (!success)
558 {
559 /* Get here when the server can't be found. */
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100560 ch_error(-1, "Cannot connect to port after retry\n");
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100561 PERROR(_("E899: Cannot connect to port after retry2"));
562 sock_close(sd);
563 return -1;
564 }
565 }
566 }
567
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100568 channels[ch_idx].ch_sock = sd;
569 channels[ch_idx].ch_close_cb = close_cb;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100570
571#ifdef FEAT_GUI
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100572 channel_gui_register(ch_idx);
Bram Moolenaard04a0202016-01-26 23:30:18 +0100573#endif
574
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100575 return ch_idx;
576}
577
578#if defined(CHANNEL_PIPES) || defined(PROTO)
579 void
580channel_set_pipes(int ch_idx, int in, int out, int err)
581{
582 channel_T *channel = &channels[ch_idx];
583
584 channel->ch_in = in;
585 channel->ch_out = out;
586 channel->ch_err = err;
587}
588#endif
589
590 void
591channel_set_job(int ch_idx, job_T *job)
592{
593 channels[ch_idx].ch_job = job;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100594}
595
596/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100597 * Set the json mode of channel "ch_idx" to "ch_mode".
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100598 */
599 void
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100600channel_set_json_mode(int ch_idx, ch_mode_T ch_mode)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100601{
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100602 channels[ch_idx].ch_mode = ch_mode;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100603}
604
605/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100606 * Set the read timeout of channel "ch_idx".
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100607 */
608 void
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100609channel_set_timeout(int ch_idx, int timeout)
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100610{
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100611 channels[ch_idx].ch_timeout = timeout;
Bram Moolenaar4d919d72016-02-05 22:36:41 +0100612}
613
614/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100615 * Set the callback for channel "ch_idx".
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100616 */
617 void
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100618channel_set_callback(int ch_idx, char_u *callback)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100619{
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100620 vim_free(channels[ch_idx].ch_callback);
621 channels[ch_idx].ch_callback = vim_strsave(callback);
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100622}
623
624/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100625 * Set the callback for channel "ch_idx" for the response with "id".
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100626 */
627 void
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100628channel_set_req_callback(int ch_idx, char_u *callback, int id)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100629{
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100630 cbq_T *cbhead = &channels[ch_idx].ch_cb_head;
Bram Moolenaara07fec92016-02-05 21:04:08 +0100631 cbq_T *item = (cbq_T *)alloc((int)sizeof(cbq_T));
632
633 if (item != NULL)
634 {
635 item->callback = vim_strsave(callback);
636 item->seq_nr = id;
637 item->prev = cbhead->prev;
638 cbhead->prev = item;
639 item->next = cbhead;
640 item->prev->next = item;
641 }
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100642}
643
644/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100645 * Invoke the "callback" on channel "ch_idx".
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100646 */
647 static void
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100648invoke_callback(int ch_idx, char_u *callback, typval_T *argv)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100649{
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100650 typval_T rettv;
651 int dummy;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100652
653 argv[0].v_type = VAR_NUMBER;
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100654 argv[0].vval.v_number = ch_idx;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100655
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100656 call_func(callback, (int)STRLEN(callback),
657 &rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL);
658 /* If an echo command was used the cursor needs to be put back where
659 * it belongs. */
660 setcursor();
661 cursor_on();
662 out_flush();
663}
664
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100665/*
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100666 * Return the first buffer from the channel and remove it.
667 * The caller must free it.
668 * Returns NULL if there is nothing.
669 */
670 char_u *
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100671channel_get(int ch_idx)
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100672{
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100673 readq_T *head = &channels[ch_idx].ch_head;
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100674 readq_T *node;
675 char_u *p;
676
677 if (head->next == head || head->next == NULL)
678 return NULL;
679 node = head->next;
680 /* dispose of the node but keep the buffer */
681 p = node->buffer;
682 head->next = node->next;
683 node->next->prev = node->prev;
684 vim_free(node);
685 return p;
686}
687
688/*
689 * Returns the whole buffer contents concatenated.
690 */
691 static char_u *
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100692channel_get_all(int ch_idx)
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100693{
694 /* Concatenate everything into one buffer.
695 * TODO: avoid multiple allocations. */
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100696 while (channel_collapse(ch_idx) == OK)
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100697 ;
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100698 return channel_get(ch_idx);
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100699}
700
701/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100702 * Collapses the first and second buffer in the channel "ch_idx".
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100703 * Returns FAIL if that is not possible.
704 */
705 int
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100706channel_collapse(int ch_idx)
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100707{
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100708 readq_T *head = &channels[ch_idx].ch_head;
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100709 readq_T *node = head->next;
710 char_u *p;
711
712 if (node == head || node == NULL || node->next == head)
713 return FAIL;
714
715 p = alloc((unsigned)(STRLEN(node->buffer)
716 + STRLEN(node->next->buffer) + 1));
717 if (p == NULL)
718 return FAIL; /* out of memory */
719 STRCPY(p, node->buffer);
720 STRCAT(p, node->next->buffer);
721 vim_free(node->next->buffer);
722 node->next->buffer = p;
723
724 /* dispose of the node and buffer */
725 head->next = node->next;
726 node->next->prev = node->prev;
727 vim_free(node->buffer);
728 vim_free(node);
729 return OK;
730}
731
732/*
Bram Moolenaard7ece102016-02-02 23:23:02 +0100733 * Use the read buffer of channel "ch_idx" and parse a JSON messages that is
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100734 * complete. The messages are added to the queue.
Bram Moolenaard7ece102016-02-02 23:23:02 +0100735 * Return TRUE if there is more to read.
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100736 */
Bram Moolenaard7ece102016-02-02 23:23:02 +0100737 static int
738channel_parse_json(int ch_idx)
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100739{
740 js_read_T reader;
741 typval_T listtv;
742 jsonq_T *item;
Bram Moolenaar595e64e2016-02-07 19:19:53 +0100743 channel_T *channel = &channels[ch_idx];
744 jsonq_T *head = &channel->ch_json_head;
Bram Moolenaard7ece102016-02-02 23:23:02 +0100745 int ret;
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100746
747 if (channel_peek(ch_idx) == NULL)
Bram Moolenaard7ece102016-02-02 23:23:02 +0100748 return FALSE;
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100749
750 /* TODO: make reader work properly */
751 /* reader.js_buf = channel_peek(ch_idx); */
752 reader.js_buf = channel_get_all(ch_idx);
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100753 reader.js_used = 0;
Bram Moolenaar56ead342016-02-02 18:20:08 +0100754 reader.js_fill = NULL;
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100755 /* reader.js_fill = channel_fill; */
756 reader.js_cookie = &ch_idx;
Bram Moolenaar595e64e2016-02-07 19:19:53 +0100757 ret = json_decode(&reader, &listtv,
758 channel->ch_mode == MODE_JS ? JSON_JS : 0);
Bram Moolenaard7ece102016-02-02 23:23:02 +0100759 if (ret == OK)
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100760 {
Bram Moolenaar6076fe12016-02-05 22:49:56 +0100761 /* Only accept the response when it is a list with at least two
762 * items. */
763 if (listtv.v_type != VAR_LIST || listtv.vval.v_list->lv_len < 2)
Bram Moolenaard7ece102016-02-02 23:23:02 +0100764 {
765 /* TODO: give error */
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100766 clear_tv(&listtv);
Bram Moolenaard7ece102016-02-02 23:23:02 +0100767 }
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100768 else
769 {
Bram Moolenaard7ece102016-02-02 23:23:02 +0100770 item = (jsonq_T *)alloc((unsigned)sizeof(jsonq_T));
771 if (item == NULL)
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100772 clear_tv(&listtv);
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100773 else
774 {
Bram Moolenaard7ece102016-02-02 23:23:02 +0100775 item->value = alloc_tv();
776 if (item->value == NULL)
777 {
778 vim_free(item);
779 clear_tv(&listtv);
780 }
781 else
782 {
783 *item->value = listtv;
784 item->prev = head->prev;
785 head->prev = item;
786 item->next = head;
787 item->prev->next = item;
788 }
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100789 }
790 }
791 }
Bram Moolenaardf5b27b2016-02-02 18:43:17 +0100792
793 /* Put the unread part back into the channel.
794 * TODO: insert in front */
795 if (reader.js_buf[reader.js_used] != NUL)
Bram Moolenaard7ece102016-02-02 23:23:02 +0100796 {
Bram Moolenaardf5b27b2016-02-02 18:43:17 +0100797 channel_save(ch_idx, reader.js_buf + reader.js_used,
798 (int)(reader.js_end - reader.js_buf) - reader.js_used);
Bram Moolenaard7ece102016-02-02 23:23:02 +0100799 ret = TRUE;
800 }
801 else
802 ret = FALSE;
803
Bram Moolenaardf5b27b2016-02-02 18:43:17 +0100804 vim_free(reader.js_buf);
Bram Moolenaard7ece102016-02-02 23:23:02 +0100805 return ret;
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100806}
807
808/*
809 * Remove "node" from the queue that it is in and free it.
Bram Moolenaara07fec92016-02-05 21:04:08 +0100810 * Also frees the contained callback name.
811 */
812 static void
813remove_cb_node(cbq_T *node)
814{
815 node->prev->next = node->next;
816 node->next->prev = node->prev;
817 vim_free(node->callback);
818 vim_free(node);
819}
820
821/*
822 * Remove "node" from the queue that it is in and free it.
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100823 * Caller should have freed or used node->value.
824 */
825 static void
826remove_json_node(jsonq_T *node)
827{
828 node->prev->next = node->next;
829 node->next->prev = node->prev;
830 vim_free(node);
831}
832
833/*
834 * Get a message from the JSON queue for channel "ch_idx".
835 * When "id" is positive it must match the first number in the list.
Bram Moolenaare56bf152016-02-08 23:23:42 +0100836 * When "id" is zero or negative jut get the first message. But not the one
837 * with id ch_block_id.
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100838 * Return OK when found and return the value in "rettv".
839 * Return FAIL otherwise.
840 */
841 static int
842channel_get_json(int ch_idx, int id, typval_T **rettv)
843{
Bram Moolenaare56bf152016-02-08 23:23:42 +0100844 channel_T *channel = &channels[ch_idx];
845 jsonq_T *head = &channel->ch_json_head;
846 jsonq_T *item = head->next;
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100847
848 while (item != head)
849 {
850 list_T *l = item->value->vval.v_list;
851 typval_T *tv = &l->lv_first->li_tv;
852
853 if ((id > 0 && tv->v_type == VAR_NUMBER && tv->vval.v_number == id)
Bram Moolenaare56bf152016-02-08 23:23:42 +0100854 || (id <= 0 && (tv->v_type != VAR_NUMBER
Bram Moolenaarf6157282016-02-10 21:07:14 +0100855 || tv->vval.v_number == 0
Bram Moolenaare56bf152016-02-08 23:23:42 +0100856 || tv->vval.v_number != channel->ch_block_id)))
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100857 {
858 *rettv = item->value;
859 remove_json_node(item);
860 return OK;
861 }
862 item = item->next;
863 }
864 return FAIL;
865}
866
867/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100868 * Execute a command received over channel "ch_idx".
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100869 * "cmd" is the command string, "arg2" the second argument.
870 * "arg3" is the third argument, NULL if missing.
871 */
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100872 static void
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100873channel_exe_cmd(int ch_idx, char_u *cmd, typval_T *arg2, typval_T *arg3)
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100874{
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100875 char_u *arg;
876
877 if (arg2->v_type != VAR_STRING)
878 {
879 if (p_verbose > 2)
880 EMSG("E903: received ex command with non-string argument");
881 return;
882 }
883 arg = arg2->vval.v_string;
Bram Moolenaar14ad6112016-02-01 21:47:13 +0100884 if (arg == NULL)
885 arg = (char_u *)"";
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100886
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100887 if (STRCMP(cmd, "ex") == 0)
888 {
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100889 do_cmdline_cmd(arg);
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100890 }
891 else if (STRCMP(cmd, "normal") == 0)
892 {
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100893 exarg_T ea;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100894
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100895 ea.arg = arg;
896 ea.addr_count = 0;
897 ea.forceit = TRUE; /* no mapping */
898 ex_normal(&ea);
899 }
900 else if (STRCMP(cmd, "redraw") == 0)
901 {
902 exarg_T ea;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100903
Bram Moolenaar14ad6112016-02-01 21:47:13 +0100904 ea.forceit = *arg != NUL;
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100905 ex_redraw(&ea);
906 showruler(FALSE);
907 setcursor();
908 out_flush();
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100909#ifdef FEAT_GUI
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100910 if (gui.in_use)
911 {
912 gui_update_cursor(FALSE, FALSE);
913 gui_mch_flush();
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100914 }
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100915#endif
916 }
917 else if (STRCMP(cmd, "expr") == 0 || STRCMP(cmd, "eval") == 0)
918 {
919 int is_eval = cmd[1] == 'v';
920
Bram Moolenaar66624ff2016-02-03 23:59:43 +0100921 if (is_eval && (arg3 == NULL || arg3->v_type != VAR_NUMBER))
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100922 {
923 if (p_verbose > 2)
924 EMSG("E904: third argument for eval must be a number");
925 }
926 else
927 {
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100928 typval_T *tv;
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100929 typval_T err_tv;
Bram Moolenaar55fab432016-02-07 16:53:13 +0100930 char_u *json = NULL;
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100931 channel_T *channel = &channels[ch_idx];
Bram Moolenaar595e64e2016-02-07 19:19:53 +0100932 int options = channel->ch_mode == MODE_JS ? JSON_JS : 0;
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100933
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100934 /* Don't pollute the display with errors. */
935 ++emsg_skip;
936 tv = eval_expr(arg, NULL);
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100937 if (is_eval)
938 {
Bram Moolenaar55fab432016-02-07 16:53:13 +0100939 if (tv != NULL)
Bram Moolenaar595e64e2016-02-07 19:19:53 +0100940 json = json_encode_nr_expr(arg3->vval.v_number, tv,
941 options);
Bram Moolenaar55fab432016-02-07 16:53:13 +0100942 if (tv == NULL || (json != NULL && *json == NUL))
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100943 {
Bram Moolenaar55fab432016-02-07 16:53:13 +0100944 /* If evaluation failed or the result can't be encoded
945 * then return the string "ERROR". */
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100946 err_tv.v_type = VAR_STRING;
947 err_tv.vval.v_string = (char_u *)"ERROR";
948 tv = &err_tv;
Bram Moolenaar595e64e2016-02-07 19:19:53 +0100949 json = json_encode_nr_expr(arg3->vval.v_number, tv,
950 options);
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100951 }
Bram Moolenaar55fab432016-02-07 16:53:13 +0100952 if (json != NULL)
953 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100954 channel_send(ch_idx, json, "eval");
Bram Moolenaar55fab432016-02-07 16:53:13 +0100955 vim_free(json);
956 }
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100957 }
Bram Moolenaar55fab432016-02-07 16:53:13 +0100958 --emsg_skip;
Bram Moolenaarfcb1e3d2016-02-03 21:32:46 +0100959 if (tv != &err_tv)
960 free_tv(tv);
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100961 }
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100962 }
963 else if (p_verbose > 2)
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100964 EMSG2("E905: received unknown command: %s", cmd);
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100965}
966
967/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100968 * Invoke a callback for channel "ch_idx" if needed.
Bram Moolenaardf5b27b2016-02-02 18:43:17 +0100969 * Return OK when a message was handled, there might be another one.
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100970 */
Bram Moolenaardf5b27b2016-02-02 18:43:17 +0100971 static int
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100972may_invoke_callback(int ch_idx)
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100973{
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100974 char_u *msg = NULL;
975 typval_T *listtv = NULL;
976 list_T *list;
977 typval_T *typetv;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100978 typval_T argv[3];
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100979 int seq_nr = -1;
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100980 channel_T *channel = &channels[ch_idx];
Bram Moolenaar595e64e2016-02-07 19:19:53 +0100981 ch_mode_T ch_mode = channel->ch_mode;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100982
Bram Moolenaara07fec92016-02-05 21:04:08 +0100983 if (channel->ch_close_cb != NULL)
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100984 /* this channel is handled elsewhere (netbeans) */
Bram Moolenaardf5b27b2016-02-02 18:43:17 +0100985 return FALSE;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100986
Bram Moolenaar595e64e2016-02-07 19:19:53 +0100987 if (ch_mode != MODE_RAW)
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100988 {
Bram Moolenaard7ece102016-02-02 23:23:02 +0100989 /* Get any json message in the queue. */
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100990 if (channel_get_json(ch_idx, -1, &listtv) == FAIL)
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100991 {
Bram Moolenaard7ece102016-02-02 23:23:02 +0100992 /* Parse readahead, return when there is still no message. */
Bram Moolenaar6463ca22016-02-13 17:04:46 +0100993 channel_parse_json(ch_idx);
994 if (channel_get_json(ch_idx, -1, &listtv) == FAIL)
Bram Moolenaard7ece102016-02-02 23:23:02 +0100995 return FALSE;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100996 }
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100997
998 list = listtv->vval.v_list;
Bram Moolenaar19d2f152016-02-01 21:38:19 +0100999 argv[1] = list->lv_first->li_next->li_tv;
1000 typetv = &list->lv_first->li_tv;
1001 if (typetv->v_type == VAR_STRING)
1002 {
1003 typval_T *arg3 = NULL;
1004 char_u *cmd = typetv->vval.v_string;
1005
Bram Moolenaar66624ff2016-02-03 23:59:43 +01001006 /* ["cmd", arg] or ["cmd", arg, arg] */
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001007 if (list->lv_len == 3)
1008 arg3 = &list->lv_last->li_tv;
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001009 ch_logs(ch_idx, "Executing %s command", (char *)cmd);
1010 channel_exe_cmd(ch_idx, cmd, &argv[1], arg3);
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001011 clear_tv(listtv);
Bram Moolenaardf5b27b2016-02-02 18:43:17 +01001012 return TRUE;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001013 }
1014
1015 if (typetv->v_type != VAR_NUMBER)
1016 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001017 ch_error(ch_idx,
1018 "Dropping message with invalid sequence number type\n");
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001019 clear_tv(listtv);
Bram Moolenaardf5b27b2016-02-02 18:43:17 +01001020 return FALSE;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001021 }
1022 seq_nr = typetv->vval.v_number;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01001023 }
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001024 else if (channel_peek(ch_idx) == NULL)
Bram Moolenaard7ece102016-02-02 23:23:02 +01001025 {
1026 /* nothing to read on raw channel */
1027 return FALSE;
1028 }
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001029 else
1030 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001031 /* If there is no callback, don't do anything. */
1032 if (channel->ch_callback == NULL)
1033 return FALSE;
1034
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001035 /* For a raw channel we don't know where the message ends, just get
1036 * everything. */
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001037 msg = channel_get_all(ch_idx);
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001038 argv[1].v_type = VAR_STRING;
1039 argv[1].vval.v_string = msg;
1040 }
1041
Bram Moolenaara07fec92016-02-05 21:04:08 +01001042 if (seq_nr > 0)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001043 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001044 cbq_T *cbhead = &channel->ch_cb_head;
1045 cbq_T *cbitem = cbhead->next;
1046 int done = FALSE;
Bram Moolenaara07fec92016-02-05 21:04:08 +01001047
1048 /* invoke the one-time callback with the matching nr */
1049 while (cbitem != cbhead)
1050 {
1051 if (cbitem->seq_nr == seq_nr)
1052 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001053 ch_log(ch_idx, "Invoking one-time callback\n");
1054 invoke_callback(ch_idx, cbitem->callback, argv);
Bram Moolenaara07fec92016-02-05 21:04:08 +01001055 remove_cb_node(cbitem);
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001056 done = TRUE;
Bram Moolenaara07fec92016-02-05 21:04:08 +01001057 break;
1058 }
1059 cbitem = cbitem->next;
1060 }
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001061 if (!done)
1062 ch_log(ch_idx, "Dropping message without callback\n");
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001063 }
Bram Moolenaara07fec92016-02-05 21:04:08 +01001064 else if (channel->ch_callback != NULL)
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001065 {
1066 /* invoke the channel callback */
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001067 ch_log(ch_idx, "Invoking channel callback\n");
1068 invoke_callback(ch_idx, channel->ch_callback, argv);
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001069 }
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001070 else
1071 ch_log(ch_idx, "Dropping message\n");
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01001072
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001073 if (listtv != NULL)
1074 clear_tv(listtv);
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001075 vim_free(msg);
Bram Moolenaardf5b27b2016-02-02 18:43:17 +01001076
1077 return TRUE;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001078}
1079
1080/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001081 * Return TRUE when channel "ch_idx" is open for writing to.
1082 * Also returns FALSE or invalid "ch_idx".
Bram Moolenaard04a0202016-01-26 23:30:18 +01001083 */
1084 int
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001085channel_can_write_to(int ch_idx)
Bram Moolenaard04a0202016-01-26 23:30:18 +01001086{
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001087 return ch_idx >= 0 && ch_idx < channel_count
1088 && (channels[ch_idx].ch_sock >= 0
1089#ifdef CHANNEL_PIPES
1090 || channels[ch_idx].ch_in >= 0
1091#endif
1092 );
Bram Moolenaard04a0202016-01-26 23:30:18 +01001093}
1094
1095/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001096 * Return TRUE when channel "ch_idx" is open for reading or writing.
1097 * Also returns FALSE or invalid "ch_idx".
1098 */
1099 int
1100channel_is_open(int ch_idx)
1101{
1102 return ch_idx >= 0 && ch_idx < channel_count
1103 && (channels[ch_idx].ch_sock >= 0
1104#ifdef CHANNEL_PIPES
1105 || channels[ch_idx].ch_in >= 0
1106 || channels[ch_idx].ch_out >= 0
1107 || channels[ch_idx].ch_err >= 0
1108#endif
1109 );
1110}
1111
1112/*
1113 * Close channel "ch_idx".
Bram Moolenaard04a0202016-01-26 23:30:18 +01001114 * This does not trigger the close callback.
1115 */
1116 void
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001117channel_close(int ch_idx)
Bram Moolenaard04a0202016-01-26 23:30:18 +01001118{
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001119 channel_T *channel = &channels[ch_idx];
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001120 jsonq_T *jhead;
Bram Moolenaara07fec92016-02-05 21:04:08 +01001121 cbq_T *cbhead;
Bram Moolenaard04a0202016-01-26 23:30:18 +01001122
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001123 if (channel->ch_sock >= 0)
Bram Moolenaard04a0202016-01-26 23:30:18 +01001124 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001125 sock_close(channel->ch_sock);
1126 channel->ch_sock = -1;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001127 channel->ch_close_cb = NULL;
Bram Moolenaard04a0202016-01-26 23:30:18 +01001128#ifdef FEAT_GUI
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001129 channel_gui_unregister(ch_idx);
Bram Moolenaard04a0202016-01-26 23:30:18 +01001130#endif
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001131 vim_free(channel->ch_callback);
1132 channel->ch_callback = NULL;
Bram Moolenaar4d919d72016-02-05 22:36:41 +01001133 channel->ch_timeout = 2000;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001134
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001135 while (channel_peek(ch_idx) != NULL)
1136 vim_free(channel_get(ch_idx));
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001137
Bram Moolenaara07fec92016-02-05 21:04:08 +01001138 cbhead = &channel->ch_cb_head;
1139 while (cbhead->next != cbhead)
1140 remove_cb_node(cbhead->next);
1141
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001142 jhead = &channel->ch_json_head;
1143 while (jhead->next != jhead)
1144 {
1145 clear_tv(jhead->next->value);
1146 remove_json_node(jhead->next);
1147 }
Bram Moolenaare0874f82016-01-24 20:36:41 +01001148 }
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001149#if defined(CHANNEL_PIPES)
1150 if (channel->ch_in >= 0)
1151 {
1152 close(channel->ch_in);
1153 channel->ch_in = -1;
1154 }
1155 if (channel->ch_out >= 0)
1156 {
1157 close(channel->ch_out);
1158 channel->ch_out = -1;
1159 }
1160 if (channel->ch_err >= 0)
1161 {
1162 close(channel->ch_err);
1163 channel->ch_err = -1;
1164 }
1165#endif
Bram Moolenaare0874f82016-01-24 20:36:41 +01001166}
1167
Bram Moolenaard04a0202016-01-26 23:30:18 +01001168/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001169 * Store "buf[len]" on channel "ch_idx".
Bram Moolenaar83162462016-01-28 23:10:07 +01001170 * Returns OK or FAIL.
Bram Moolenaard04a0202016-01-26 23:30:18 +01001171 */
Bram Moolenaar83162462016-01-28 23:10:07 +01001172 int
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001173channel_save(int ch_idx, char_u *buf, int len)
Bram Moolenaard04a0202016-01-26 23:30:18 +01001174{
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001175 readq_T *node;
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001176 readq_T *head = &channels[ch_idx].ch_head;
Bram Moolenaard04a0202016-01-26 23:30:18 +01001177
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001178 node = (readq_T *)alloc(sizeof(readq_T));
Bram Moolenaard04a0202016-01-26 23:30:18 +01001179 if (node == NULL)
Bram Moolenaar83162462016-01-28 23:10:07 +01001180 return FAIL; /* out of memory */
Bram Moolenaard04a0202016-01-26 23:30:18 +01001181 node->buffer = alloc(len + 1);
1182 if (node->buffer == NULL)
1183 {
1184 vim_free(node);
Bram Moolenaar83162462016-01-28 23:10:07 +01001185 return FAIL; /* out of memory */
Bram Moolenaard04a0202016-01-26 23:30:18 +01001186 }
1187 mch_memmove(node->buffer, buf, (size_t)len);
1188 node->buffer[len] = NUL;
1189
Bram Moolenaard04a0202016-01-26 23:30:18 +01001190 /* insert node at tail of queue */
1191 node->next = head;
1192 node->prev = head->prev;
1193 head->prev->next = node;
1194 head->prev = node;
1195
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001196 if (log_fd != NULL)
Bram Moolenaard04a0202016-01-26 23:30:18 +01001197 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001198 ch_log_lead("RECV ", ch_idx);
1199 fprintf(log_fd, "'");
1200 if (fwrite(buf, len, 1, log_fd) != 1)
Bram Moolenaar83162462016-01-28 23:10:07 +01001201 return FAIL;
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001202 fprintf(log_fd, "'\n");
Bram Moolenaard04a0202016-01-26 23:30:18 +01001203 }
Bram Moolenaar83162462016-01-28 23:10:07 +01001204 return OK;
Bram Moolenaard04a0202016-01-26 23:30:18 +01001205}
1206
1207/*
1208 * Return the first buffer from the channel without removing it.
1209 * Returns NULL if there is nothing.
1210 */
1211 char_u *
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001212channel_peek(int ch_idx)
Bram Moolenaard04a0202016-01-26 23:30:18 +01001213{
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001214 readq_T *head = &channels[ch_idx].ch_head;
Bram Moolenaard04a0202016-01-26 23:30:18 +01001215
1216 if (head->next == head || head->next == NULL)
1217 return NULL;
1218 return head->next->buffer;
1219}
1220
1221/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001222 * Clear the read buffer on channel "ch_idx".
Bram Moolenaard04a0202016-01-26 23:30:18 +01001223 */
1224 void
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001225channel_clear(int ch_idx)
Bram Moolenaard04a0202016-01-26 23:30:18 +01001226{
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001227 readq_T *head = &channels[ch_idx].ch_head;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001228 readq_T *node = head->next;
1229 readq_T *next;
Bram Moolenaard04a0202016-01-26 23:30:18 +01001230
1231 while (node != NULL && node != head)
1232 {
1233 next = node->next;
1234 vim_free(node->buffer);
1235 vim_free(node);
1236 if (next == head)
1237 {
1238 head->next = head;
1239 head->prev = head;
1240 break;
1241 }
1242 node = next;
1243 }
1244}
1245
1246/* Sent when the channel is found closed when reading. */
1247#define DETACH_MSG "\"DETACH\"\n"
1248
1249/* Buffer size for reading incoming messages. */
1250#define MAXMSGSIZE 4096
1251
1252/*
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001253 * Check for reading from "fd" with "timeout" msec.
1254 * Return FAIL when there is nothing to read.
Bram Moolenaara8343c12016-02-04 22:09:48 +01001255 * Always returns OK for FEAT_GUI_W32.
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001256 */
1257 static int
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001258channel_wait(int ch_idx, int fd, int timeout)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001259{
Bram Moolenaara8343c12016-02-04 22:09:48 +01001260#if defined(HAVE_SELECT) && !defined(FEAT_GUI_W32)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001261 struct timeval tval;
1262 fd_set rfds;
1263 int ret;
1264
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001265 if (timeout > 0)
1266 ch_logn(ch_idx, "Waiting for %d msec\n", timeout);
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001267 FD_ZERO(&rfds);
1268 FD_SET(fd, &rfds);
1269 tval.tv_sec = timeout / 1000;
1270 tval.tv_usec = (timeout % 1000) * 1000;
1271 for (;;)
1272 {
1273 ret = select(fd + 1, &rfds, NULL, NULL, &tval);
1274# ifdef EINTR
1275 if (ret == -1 && errno == EINTR)
1276 continue;
1277# endif
1278 if (ret <= 0)
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001279 {
1280 ch_log(ch_idx, "Nothing to read\n");
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001281 return FAIL;
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001282 }
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001283 break;
1284 }
1285#else
Bram Moolenaarb8b65112016-01-28 23:01:49 +01001286# ifdef HAVE_POLL
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001287 struct pollfd fds;
1288
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001289 if (timeout > 0)
1290 ch_logn(ch_idx, "Waiting for %d msec\n", timeout);
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001291 fds.fd = fd;
1292 fds.events = POLLIN;
1293 if (poll(&fds, 1, timeout) <= 0)
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001294 {
1295 ch_log(ch_idx, "Nothing to read\n");
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001296 return FAIL;
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001297 }
Bram Moolenaarb8b65112016-01-28 23:01:49 +01001298# endif
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001299#endif
1300 return OK;
1301}
1302
1303/*
1304 * Return a unique ID to be used in a message.
1305 */
1306 int
Bram Moolenaar7454a062016-01-30 15:14:10 +01001307channel_get_id(void)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001308{
1309 static int next_id = 1;
1310
1311 return next_id++;
1312}
1313
1314/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001315 * Get the file descriptor to read from, either the socket or stdout.
1316 */
1317 static int
1318get_read_fd(int ch_idx, int use_stderr)
1319{
1320 channel_T *channel = &channels[ch_idx];
1321
1322 if (channel->ch_sock >= 0)
1323 return channel->ch_sock;
1324#if defined(CHANNEL_PIPES)
1325 if (!use_stderr && channel->ch_out >= 0)
1326 return channel->ch_out;
1327 if (use_stderr && channel->ch_err >= 0)
1328 return channel->ch_err;
1329#endif
1330 ch_error(ch_idx, "channel_read() called while socket is closed\n");
1331 return -1;
1332}
1333
1334/*
1335 * Read from channel "ch_idx" for as long as there is something to read.
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001336 * The data is put in the read queue.
Bram Moolenaard04a0202016-01-26 23:30:18 +01001337 */
1338 void
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001339channel_read(int ch_idx, int use_stderr, char *func)
Bram Moolenaard04a0202016-01-26 23:30:18 +01001340{
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001341 channel_T *channel = &channels[ch_idx];
Bram Moolenaard04a0202016-01-26 23:30:18 +01001342 static char_u *buf = NULL;
1343 int len = 0;
1344 int readlen = 0;
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001345 int fd;
1346 int use_socket = FALSE;
Bram Moolenaard04a0202016-01-26 23:30:18 +01001347
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001348 fd = get_read_fd(ch_idx, use_stderr);
1349 if (fd < 0)
Bram Moolenaard04a0202016-01-26 23:30:18 +01001350 return;
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001351 use_socket = channel->ch_sock >= 0;
Bram Moolenaard04a0202016-01-26 23:30:18 +01001352
1353 /* Allocate a buffer to read into. */
1354 if (buf == NULL)
1355 {
1356 buf = alloc(MAXMSGSIZE);
1357 if (buf == NULL)
1358 return; /* out of memory! */
1359 }
1360
1361 /* Keep on reading for as long as there is something to read.
1362 * Use select() or poll() to avoid blocking on a message that is exactly
1363 * MAXMSGSIZE long. */
1364 for (;;)
1365 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001366 if (channel_wait(ch_idx, fd, 0) == FAIL)
Bram Moolenaard04a0202016-01-26 23:30:18 +01001367 break;
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001368 if (use_socket)
1369 len = sock_read(fd, buf, MAXMSGSIZE);
1370 else
1371 len = read(fd, buf, MAXMSGSIZE);
Bram Moolenaard04a0202016-01-26 23:30:18 +01001372 if (len <= 0)
1373 break; /* error or nothing more to read */
1374
1375 /* Store the read message in the queue. */
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001376 channel_save(ch_idx, buf, len);
Bram Moolenaard04a0202016-01-26 23:30:18 +01001377 readlen += len;
1378 if (len < MAXMSGSIZE)
1379 break; /* did read everything that's available */
1380 }
Bram Moolenaara8343c12016-02-04 22:09:48 +01001381#ifdef FEAT_GUI_W32
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001382 if (use_socket && len == SOCKET_ERROR)
Bram Moolenaara8343c12016-02-04 22:09:48 +01001383 {
1384 /* For Win32 GUI channel_wait() always returns OK and we handle the
1385 * situation that there is nothing to read here.
1386 * TODO: how about a timeout? */
1387 if (WSAGetLastError() == WSAEWOULDBLOCK)
1388 return;
1389 }
1390#endif
Bram Moolenaard04a0202016-01-26 23:30:18 +01001391
1392 /* Reading a socket disconnection (readlen == 0), or a socket error. */
1393 if (readlen <= 0)
1394 {
1395 /* Queue a "DETACH" netbeans message in the command queue in order to
1396 * terminate the netbeans session later. Do not end the session here
1397 * directly as we may be running in the context of a call to
1398 * netbeans_parse_messages():
1399 * netbeans_parse_messages
1400 * -> autocmd triggered while processing the netbeans cmd
1401 * -> ui_breakcheck
1402 * -> gui event loop or select loop
1403 * -> channel_read()
1404 */
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001405 ch_errors(ch_idx, "%s(): Cannot read\n", func);
1406 channel_save(ch_idx, (char_u *)DETACH_MSG, (int)STRLEN(DETACH_MSG));
Bram Moolenaard04a0202016-01-26 23:30:18 +01001407
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001408 if (use_socket)
1409 {
1410 channel_close(ch_idx);
1411 if (channel->ch_close_cb != NULL)
1412 (*channel->ch_close_cb)();
1413 }
1414#if defined(CHANNEL_PIPES)
1415 else
1416 {
1417 close(fd);
1418 channel->ch_out = -1;
1419 }
1420#endif
Bram Moolenaard04a0202016-01-26 23:30:18 +01001421
1422 if (len < 0)
1423 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001424 ch_error(ch_idx, "channel_read(): cannot read from channel\n");
Bram Moolenaarfb1f6262016-01-31 20:24:32 +01001425 PERROR(_("E896: read from channel"));
Bram Moolenaard04a0202016-01-26 23:30:18 +01001426 }
1427 }
1428
1429#if defined(CH_HAS_GUI) && defined(FEAT_GUI_GTK)
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001430 /* signal the main loop that there is something to read */
Bram Moolenaard04a0202016-01-26 23:30:18 +01001431 if (CH_HAS_GUI && gtk_main_level() > 0)
1432 gtk_main_quit();
1433#endif
1434}
1435
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001436/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001437 * Read from raw channel "ch_idx". Blocks until there is something to read or
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001438 * the timeout expires.
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001439 * Returns what was read in allocated memory.
1440 * Returns NULL in case of error or timeout.
1441 */
1442 char_u *
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001443channel_read_block(int ch_idx)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001444{
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001445 ch_log(ch_idx, "Reading raw\n");
1446 if (channel_peek(ch_idx) == NULL)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001447 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001448 int fd = get_read_fd(ch_idx, FALSE);
1449
1450 ch_log(ch_idx, "No readahead\n");
Bram Moolenaar4d919d72016-02-05 22:36:41 +01001451 /* Wait for up to the channel timeout. */
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001452 if (fd < 0 || channel_wait(ch_idx, fd,
1453 channels[ch_idx].ch_timeout) == FAIL)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001454 return NULL;
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001455 channel_read(ch_idx, FALSE, "channel_read_block");
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001456 }
1457
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001458 /* TODO: only get the first message */
1459 ch_log(ch_idx, "Returning readahead\n");
1460 return channel_get_all(ch_idx);
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001461}
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001462
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001463/*
1464 * Read one JSON message from channel "ch_idx" with ID "id" and store the
1465 * result in "rettv".
Bram Moolenaar4d919d72016-02-05 22:36:41 +01001466 * Blocks until the message is received or the timeout is reached.
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001467 */
1468 int
1469channel_read_json_block(int ch_idx, int id, typval_T **rettv)
1470{
Bram Moolenaare56bf152016-02-08 23:23:42 +01001471 int more;
1472 channel_T *channel = &channels[ch_idx];
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001473 int fd;
Bram Moolenaard7ece102016-02-02 23:23:02 +01001474
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001475 ch_log(ch_idx, "Reading JSON\n");
Bram Moolenaare56bf152016-02-08 23:23:42 +01001476 channel->ch_block_id = id;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001477 for (;;)
1478 {
Bram Moolenaard7ece102016-02-02 23:23:02 +01001479 more = channel_parse_json(ch_idx);
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001480
1481 /* search for messsage "id" */
1482 if (channel_get_json(ch_idx, id, rettv) == OK)
Bram Moolenaare56bf152016-02-08 23:23:42 +01001483 {
1484 channel->ch_block_id = 0;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001485 return OK;
Bram Moolenaare56bf152016-02-08 23:23:42 +01001486 }
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001487
Bram Moolenaard7ece102016-02-02 23:23:02 +01001488 if (!more)
1489 {
1490 /* Handle any other messages in the queue. If done some more
1491 * messages may have arrived. */
1492 if (channel_parse_messages())
1493 continue;
1494
Bram Moolenaar4d919d72016-02-05 22:36:41 +01001495 /* Wait for up to the channel timeout. */
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001496 fd = get_read_fd(ch_idx, FALSE);
1497 if (fd < 0 || channel_wait(ch_idx, fd, channel->ch_timeout) == FAIL)
Bram Moolenaard7ece102016-02-02 23:23:02 +01001498 break;
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001499 channel_read(ch_idx, FALSE, "channel_read_json_block");
Bram Moolenaard7ece102016-02-02 23:23:02 +01001500 }
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001501 }
Bram Moolenaare56bf152016-02-08 23:23:42 +01001502 channel->ch_block_id = 0;
Bram Moolenaar19d2f152016-02-01 21:38:19 +01001503 return FAIL;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001504}
1505
Bram Moolenaarf12d9832016-01-29 21:11:25 +01001506# if defined(WIN32) || defined(PROTO)
Bram Moolenaar85be35f2016-01-27 21:08:18 +01001507/*
1508 * Lookup the channel index from the socket.
1509 * Returns -1 when the socket isn't found.
1510 */
1511 int
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001512channel_fd2idx(sock_T fd)
Bram Moolenaar85be35f2016-01-27 21:08:18 +01001513{
1514 int i;
1515
1516 if (fd >= 0)
1517 for (i = 0; i < channel_count; ++i)
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001518 if (channels[i].ch_sock == fd
1519# if defined(CHANNEL_PIPES)
1520 || channels[i].ch_out == fd
1521 || channels[i].ch_err == fd
1522# endif
1523 )
Bram Moolenaar85be35f2016-01-27 21:08:18 +01001524 return i;
1525 return -1;
1526}
1527# endif
1528
Bram Moolenaard04a0202016-01-26 23:30:18 +01001529/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001530 * Write "buf" (NUL terminated string) to channel "ch_idx".
Bram Moolenaard04a0202016-01-26 23:30:18 +01001531 * When "fun" is not NULL an error message might be given.
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001532 * Return FAIL or OK.
Bram Moolenaard04a0202016-01-26 23:30:18 +01001533 */
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001534 int
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001535channel_send(int ch_idx, char_u *buf, char *fun)
Bram Moolenaard04a0202016-01-26 23:30:18 +01001536{
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001537 channel_T *channel = &channels[ch_idx];
Bram Moolenaard04a0202016-01-26 23:30:18 +01001538 int len = (int)STRLEN(buf);
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001539 int res;
1540 int fd;
1541 int use_socket = FALSE;
Bram Moolenaard04a0202016-01-26 23:30:18 +01001542
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001543 if (channel->ch_sock >= 0)
1544 {
1545 fd = channel->ch_sock;
1546 use_socket = TRUE;
1547 }
1548#if defined(CHANNEL_PIPES)
1549 else if (channel->ch_in >= 0)
1550 fd = channel->ch_in;
1551#endif
1552 if (fd < 0)
Bram Moolenaard04a0202016-01-26 23:30:18 +01001553 {
1554 if (!channel->ch_error && fun != NULL)
1555 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001556 ch_errors(ch_idx, "%s(): write while not connected\n", fun);
Bram Moolenaard04a0202016-01-26 23:30:18 +01001557 EMSG2("E630: %s(): write while not connected", fun);
1558 }
1559 channel->ch_error = TRUE;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001560 return FAIL;
Bram Moolenaard04a0202016-01-26 23:30:18 +01001561 }
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001562
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001563 if (log_fd != NULL)
1564 {
1565 ch_log_lead("SEND ", ch_idx);
1566 fprintf(log_fd, "'");
1567 ignored = fwrite(buf, len, 1, log_fd);
1568 fprintf(log_fd, "'\n");
1569 fflush(log_fd);
1570 }
1571
1572 if (use_socket)
1573 res = sock_write(fd, buf, len);
1574 else
1575 res = write(fd, buf, len);
1576 if (res != len)
Bram Moolenaard04a0202016-01-26 23:30:18 +01001577 {
1578 if (!channel->ch_error && fun != NULL)
1579 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001580 ch_errors(ch_idx, "%s(): write failed\n", fun);
Bram Moolenaard04a0202016-01-26 23:30:18 +01001581 EMSG2("E631: %s(): write failed", fun);
1582 }
1583 channel->ch_error = TRUE;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001584 return FAIL;
Bram Moolenaard04a0202016-01-26 23:30:18 +01001585 }
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001586
1587 channel->ch_error = FALSE;
1588 return OK;
Bram Moolenaard04a0202016-01-26 23:30:18 +01001589}
1590
1591# if (defined(UNIX) && !defined(HAVE_SELECT)) || defined(PROTO)
Bram Moolenaare0874f82016-01-24 20:36:41 +01001592/*
1593 * Add open channels to the poll struct.
1594 * Return the adjusted struct index.
1595 * The type of "fds" is hidden to avoid problems with the function proto.
1596 */
1597 int
1598channel_poll_setup(int nfd_in, void *fds_in)
1599{
1600 int nfd = nfd_in;
1601 int i;
1602 struct pollfd *fds = fds_in;
1603
1604 for (i = 0; i < channel_count; ++i)
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001605 {
1606 if (channels[i].ch_sock >= 0)
Bram Moolenaare0874f82016-01-24 20:36:41 +01001607 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001608 channels[i].ch_sock_idx = nfd;
1609 fds[nfd].fd = channels[i].ch_sock;
Bram Moolenaare0874f82016-01-24 20:36:41 +01001610 fds[nfd].events = POLLIN;
1611 nfd++;
1612 }
1613 else
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001614 channels[i].ch_sock_idx = -1;
1615
1616# ifdef CHANNEL_PIPES
1617 if (channels[i].ch_out >= 0)
1618 {
1619 channels[i].ch_out_idx = nfd;
1620 fds[nfd].fd = channels[i].ch_out;
1621 fds[nfd].events = POLLIN;
1622 nfd++;
1623 }
1624 else
1625 channels[i].ch_out_idx = -1;
1626
1627 if (channels[i].ch_err >= 0)
1628 {
1629 channels[i].ch_err_idx = nfd;
1630 fds[nfd].fd = channels[i].ch_err;
1631 fds[nfd].events = POLLIN;
1632 nfd++;
1633 }
1634 else
1635 channels[i].ch_err_idx = -1;
1636# endif
1637 }
Bram Moolenaare0874f82016-01-24 20:36:41 +01001638
1639 return nfd;
1640}
1641
1642/*
1643 * The type of "fds" is hidden to avoid problems with the function proto.
1644 */
1645 int
1646channel_poll_check(int ret_in, void *fds_in)
1647{
1648 int ret = ret_in;
1649 int i;
1650 struct pollfd *fds = fds_in;
1651
1652 for (i = 0; i < channel_count; ++i)
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001653 {
1654 if (ret > 0 && channels[i].ch_sock_idx != -1
1655 && fds[channels[i].ch_sock_idx].revents & POLLIN)
Bram Moolenaare0874f82016-01-24 20:36:41 +01001656 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001657 channel_read(i, FALSE, "channel_poll_check");
Bram Moolenaare0874f82016-01-24 20:36:41 +01001658 --ret;
1659 }
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001660# ifdef CHANNEL_PIPES
1661 if (ret > 0 && channels[i].ch_out_idx != -1
1662 && fds[channels[i].ch_out_idx].revents & POLLIN)
1663 {
1664 channel_read(i, FALSE, "channel_poll_check");
1665 --ret;
1666 }
1667 if (ret > 0 && channels[i].ch_err_idx != -1
1668 && fds[channels[i].ch_err_idx].revents & POLLIN)
1669 {
1670 channel_read(i, TRUE, "channel_poll_check");
1671 --ret;
1672 }
1673# endif
1674 }
Bram Moolenaare0874f82016-01-24 20:36:41 +01001675
1676 return ret;
1677}
Bram Moolenaard04a0202016-01-26 23:30:18 +01001678# endif /* UNIX && !HAVE_SELECT */
Bram Moolenaare0874f82016-01-24 20:36:41 +01001679
Bram Moolenaarf12d9832016-01-29 21:11:25 +01001680# if (!defined(FEAT_GUI_W32) && defined(HAVE_SELECT)) || defined(PROTO)
Bram Moolenaare0874f82016-01-24 20:36:41 +01001681/*
1682 * The type of "rfds" is hidden to avoid problems with the function proto.
1683 */
1684 int
1685channel_select_setup(int maxfd_in, void *rfds_in)
1686{
1687 int maxfd = maxfd_in;
1688 int i;
1689 fd_set *rfds = rfds_in;
1690
1691 for (i = 0; i < channel_count; ++i)
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001692 {
1693 if (channels[i].ch_sock >= 0)
Bram Moolenaare0874f82016-01-24 20:36:41 +01001694 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001695 FD_SET(channels[i].ch_sock, rfds);
1696 if (maxfd < channels[i].ch_sock)
1697 maxfd = channels[i].ch_sock;
Bram Moolenaare0874f82016-01-24 20:36:41 +01001698 }
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001699# ifdef CHANNEL_PIPES
1700 if (channels[i].ch_out >= 0)
1701 {
1702 FD_SET(channels[i].ch_out, rfds);
1703 if (maxfd < channels[i].ch_out)
1704 maxfd = channels[i].ch_out;
1705 }
1706 if (channels[i].ch_err >= 0)
1707 {
1708 FD_SET(channels[i].ch_err, rfds);
1709 if (maxfd < channels[i].ch_err)
1710 maxfd = channels[i].ch_err;
1711 }
1712# endif
1713 }
Bram Moolenaare0874f82016-01-24 20:36:41 +01001714
1715 return maxfd;
1716}
1717
1718/*
1719 * The type of "rfds" is hidden to avoid problems with the function proto.
1720 */
1721 int
1722channel_select_check(int ret_in, void *rfds_in)
1723{
1724 int ret = ret_in;
1725 int i;
1726 fd_set *rfds = rfds_in;
1727
1728 for (i = 0; i < channel_count; ++i)
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001729 {
1730 if (ret > 0 && channels[i].ch_sock >= 0
1731 && FD_ISSET(channels[i].ch_sock, rfds))
Bram Moolenaare0874f82016-01-24 20:36:41 +01001732 {
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001733 channel_read(i, FALSE, "channel_select_check");
Bram Moolenaare0874f82016-01-24 20:36:41 +01001734 --ret;
1735 }
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001736# ifdef CHANNEL_PIPES
1737 if (ret > 0 && channels[i].ch_out >= 0
1738 && FD_ISSET(channels[i].ch_out, rfds))
1739 {
1740 channel_read(i, FALSE, "channel_select_check");
1741 --ret;
1742 }
1743 if (ret > 0 && channels[i].ch_err >= 0
1744 && FD_ISSET(channels[i].ch_err, rfds))
1745 {
1746 channel_read(i, TRUE, "channel_select_check");
1747 --ret;
1748 }
1749# endif
1750 }
Bram Moolenaare0874f82016-01-24 20:36:41 +01001751
1752 return ret;
1753}
Bram Moolenaarf12d9832016-01-29 21:11:25 +01001754# endif /* !FEAT_GUI_W32 && HAVE_SELECT */
Bram Moolenaare0874f82016-01-24 20:36:41 +01001755
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01001756/*
Bram Moolenaard7ece102016-02-02 23:23:02 +01001757 * Execute queued up commands.
1758 * Invoked from the main loop when it's safe to execute received commands.
1759 * Return TRUE when something was done.
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01001760 */
Bram Moolenaard7ece102016-02-02 23:23:02 +01001761 int
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01001762channel_parse_messages(void)
1763{
1764 int i;
Bram Moolenaard7ece102016-02-02 23:23:02 +01001765 int ret = FALSE;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01001766
1767 for (i = 0; i < channel_count; ++i)
Bram Moolenaardf5b27b2016-02-02 18:43:17 +01001768 while (may_invoke_callback(i) == OK)
Bram Moolenaard7ece102016-02-02 23:23:02 +01001769 {
1770 i = 0; /* start over */
1771 ret = TRUE;
1772 }
1773 return ret;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01001774}
1775
Bram Moolenaarfbc4b4d2016-02-07 15:14:01 +01001776/*
1777 * Mark references to lists used in channels.
1778 */
Bram Moolenaar4b6a6dc2016-02-04 22:49:49 +01001779 int
1780set_ref_in_channel(int copyID)
1781{
1782 int i;
1783 int abort = FALSE;
1784
1785 for (i = 0; i < channel_count; ++i)
1786 {
1787 jsonq_T *head = &channels[i].ch_json_head;
1788 jsonq_T *item = head->next;
1789
1790 while (item != head)
1791 {
1792 list_T *l = item->value->vval.v_list;
1793
1794 if (l->lv_copyID != copyID)
1795 {
1796 l->lv_copyID = copyID;
1797 abort = abort || set_ref_in_list(l, copyID, NULL);
1798 }
1799 item = item->next;
1800 }
1801 }
1802 return abort;
1803}
Bram Moolenaarae8eb3c2016-02-07 21:59:26 +01001804
1805/*
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001806 * Return the mode of channel "ch_idx".
1807 * If "ch_idx" is invalid returns MODE_JSON.
Bram Moolenaarae8eb3c2016-02-07 21:59:26 +01001808 */
1809 ch_mode_T
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001810channel_get_mode(int ch_idx)
Bram Moolenaarae8eb3c2016-02-07 21:59:26 +01001811{
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001812 if (ch_idx < 0 || ch_idx >= channel_count)
Bram Moolenaarae8eb3c2016-02-07 21:59:26 +01001813 return MODE_JSON;
Bram Moolenaar6463ca22016-02-13 17:04:46 +01001814 return channels[ch_idx].ch_mode;
Bram Moolenaarae8eb3c2016-02-07 21:59:26 +01001815}
1816
Bram Moolenaare0874f82016-01-24 20:36:41 +01001817#endif /* FEAT_CHANNEL */