blob: 14841e7bbca636b89990c75a7690f6fc31cb11b9 [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/*
18 * Change the zero to 1 to enable debugging.
19 * This will write a file "channel_debug.log".
20 */
21#if 0
22# define CHERROR(fmt, arg) cherror(fmt, arg)
23# define CHLOG(idx, send, buf) chlog(idx, send, buf)
24# define CHFILE "channel_debug.log"
25
26static void cherror(char *fmt, char *arg);
27static void chlog(int send, char_u *buf);
28#else
29# define CHERROR(fmt, arg)
30# define CHLOG(idx, send, buf)
31#endif
32
33/* TRUE when netbeans is running with a GUI. */
34#ifdef FEAT_GUI
35# define CH_HAS_GUI (gui.in_use || gui.starting)
36#endif
37
38/* Note: when making changes here also adjust configure.in. */
39#ifdef WIN32
40/* WinSock API is separated from C API, thus we can't use read(), write(),
41 * errno... */
42# define SOCK_ERRNO errno = WSAGetLastError()
43# undef ECONNREFUSED
44# define ECONNREFUSED WSAECONNREFUSED
45# ifdef EINTR
46# undef EINTR
47# endif
48# define EINTR WSAEINTR
49# define sock_write(sd, buf, len) send(sd, buf, len, 0)
50# define sock_read(sd, buf, len) recv(sd, buf, len, 0)
51# define sock_close(sd) closesocket(sd)
52# define sleep(t) Sleep(t*1000) /* WinAPI Sleep() accepts milliseconds */
53#else
54# include <netdb.h>
55# include <netinet/in.h>
56
57# include <sys/socket.h>
58# ifdef HAVE_LIBGEN_H
59# include <libgen.h>
60# endif
61# define SOCK_ERRNO
62# define sock_write(sd, buf, len) write(sd, buf, len)
63# define sock_read(sd, buf, len) read(sd, buf, len)
64# define sock_close(sd) close(sd)
65#endif
66
67#ifdef FEAT_GUI_W32
68extern HWND s_hwnd; /* Gvim's Window handle */
69#endif
70
71struct readqueue
72{
73 char_u *buffer;
74 struct readqueue *next;
75 struct readqueue *prev;
76};
77typedef struct readqueue queue_T;
78
Bram Moolenaare0874f82016-01-24 20:36:41 +010079typedef struct {
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010080 sock_T ch_fd; /* the socket, -1 for a closed channel */
81 int ch_idx; /* used by channel_poll_setup() */
82 queue_T ch_head; /* dummy node, header for circular queue */
Bram Moolenaard04a0202016-01-26 23:30:18 +010083
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010084 int ch_error; /* When TRUE an error was reported. Avoids giving
Bram Moolenaard04a0202016-01-26 23:30:18 +010085 * pages full of error messages when the other side
86 * has exited, only mention the first error until the
87 * connection works again. */
88#ifdef FEAT_GUI_X11
89 XtInputId ch_inputHandler; /* Cookie for input */
90#endif
91#ifdef FEAT_GUI_GTK
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010092 gint ch_inputHandler; /* Cookie for input */
Bram Moolenaard04a0202016-01-26 23:30:18 +010093#endif
Bram Moolenaarf12d9832016-01-29 21:11:25 +010094#ifdef WIN32
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010095 int ch_inputHandler; /* simply ret.value of WSAAsyncSelect() */
Bram Moolenaard04a0202016-01-26 23:30:18 +010096#endif
97
Bram Moolenaar3b5f9292016-01-28 22:37:01 +010098 void (*ch_close_cb)(void); /* callback for when channel is closed */
99
100 char_u *ch_callback; /* function to call when a msg is not handled */
101 char_u *ch_req_callback; /* function to call for current request */
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100102
103 int ch_json_mode;
Bram Moolenaare0874f82016-01-24 20:36:41 +0100104} channel_T;
105
Bram Moolenaard04a0202016-01-26 23:30:18 +0100106/*
107 * Information about all channels.
108 * There can be gaps for closed channels, they will be reused later.
109 */
Bram Moolenaare0874f82016-01-24 20:36:41 +0100110static channel_T *channels = NULL;
111static int channel_count = 0;
112
113/*
Bram Moolenaard04a0202016-01-26 23:30:18 +0100114 * TODO: open debug file when desired.
115 */
116FILE *debugfd = NULL;
117
118/*
Bram Moolenaare0874f82016-01-24 20:36:41 +0100119 * Add a new channel slot, return the index.
Bram Moolenaard04a0202016-01-26 23:30:18 +0100120 * The channel isn't actually used into ch_fd is set >= 0;
121 * Returns -1 if all channels are in use.
Bram Moolenaare0874f82016-01-24 20:36:41 +0100122 */
123 static int
124add_channel(void)
125{
126 int idx;
127 channel_T *new_channels;
128
129 if (channels != NULL)
130 for (idx = 0; idx < channel_count; ++idx)
131 if (channels[idx].ch_fd < 0)
132 /* re-use a closed channel slot */
133 return idx;
134 if (channel_count == MAX_OPEN_CHANNELS)
135 return -1;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100136 new_channels = (channel_T *)alloc(sizeof(channel_T) * (channel_count + 1));
Bram Moolenaare0874f82016-01-24 20:36:41 +0100137 if (new_channels == NULL)
138 return -1;
139 if (channels != NULL)
140 mch_memmove(new_channels, channels, sizeof(channel_T) * channel_count);
141 channels = new_channels;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100142 (void)vim_memset(&channels[channel_count], 0, sizeof(channel_T));
143
Bram Moolenaare0874f82016-01-24 20:36:41 +0100144 channels[channel_count].ch_fd = (sock_T)-1;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100145#ifdef FEAT_GUI_X11
146 channels[channel_count].ch_inputHandler = (XtInputId)NULL;
147#endif
148#ifdef FEAT_GUI_GTK
149 channels[channel_count].ch_inputHandler = 0;
150#endif
151#ifdef FEAT_GUI_W32
152 channels[channel_count].ch_inputHandler = -1;
153#endif
Bram Moolenaare0874f82016-01-24 20:36:41 +0100154
155 return channel_count++;
156}
157
Bram Moolenaard04a0202016-01-26 23:30:18 +0100158#if defined(FEAT_GUI) || defined(PROTO)
Bram Moolenaare0874f82016-01-24 20:36:41 +0100159/*
Bram Moolenaard04a0202016-01-26 23:30:18 +0100160 * Read a command from netbeans.
Bram Moolenaare0874f82016-01-24 20:36:41 +0100161 */
Bram Moolenaard04a0202016-01-26 23:30:18 +0100162#ifdef FEAT_GUI_X11
163 static void
164messageFromNetbeans(XtPointer clientData,
165 int *unused1 UNUSED,
166 XtInputId *unused2 UNUSED)
Bram Moolenaare0874f82016-01-24 20:36:41 +0100167{
Bram Moolenaard04a0202016-01-26 23:30:18 +0100168 channel_read((int)(long)clientData);
Bram Moolenaare0874f82016-01-24 20:36:41 +0100169}
Bram Moolenaard04a0202016-01-26 23:30:18 +0100170#endif
Bram Moolenaare0874f82016-01-24 20:36:41 +0100171
Bram Moolenaard04a0202016-01-26 23:30:18 +0100172#ifdef FEAT_GUI_GTK
173 static void
174messageFromNetbeans(gpointer clientData,
175 gint unused1 UNUSED,
176 GdkInputCondition unused2 UNUSED)
Bram Moolenaare0874f82016-01-24 20:36:41 +0100177{
Bram Moolenaard04a0202016-01-26 23:30:18 +0100178 channel_read((int)(long)clientData);
Bram Moolenaare0874f82016-01-24 20:36:41 +0100179}
180#endif
181
182 static void
Bram Moolenaard04a0202016-01-26 23:30:18 +0100183channel_gui_register(int idx)
Bram Moolenaare0874f82016-01-24 20:36:41 +0100184{
Bram Moolenaard04a0202016-01-26 23:30:18 +0100185 channel_T *channel = &channels[idx];
186
187 if (!CH_HAS_GUI)
188 return;
189
190# ifdef FEAT_GUI_X11
191 /* tell notifier we are interested in being called
192 * when there is input on the editor connection socket
193 */
194 if (channel->ch_inputHandler == (XtInputId)NULL)
195 channel->ch_inputHandler =
196 XtAppAddInput((XtAppContext)app_context, channel->ch_fd,
197 (XtPointer)(XtInputReadMask + XtInputExceptMask),
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100198 messageFromNetbeans, (XtPointer)(long)idx);
Bram Moolenaard04a0202016-01-26 23:30:18 +0100199# else
200# ifdef FEAT_GUI_GTK
201 /*
202 * Tell gdk we are interested in being called when there
203 * is input on the editor connection socket
204 */
205 if (channel->ch_inputHandler == 0)
206 channel->ch_inputHandler =
207 gdk_input_add((gint)channel->ch_fd, (GdkInputCondition)
208 ((int)GDK_INPUT_READ + (int)GDK_INPUT_EXCEPTION),
209 messageFromNetbeans, (gpointer)(long)idx);
210# else
211# ifdef FEAT_GUI_W32
212 /*
213 * Tell Windows we are interested in receiving message when there
214 * is input on the editor connection socket.
Bram Moolenaard04a0202016-01-26 23:30:18 +0100215 */
216 if (channel->ch_inputHandler == -1)
217 channel->ch_inputHandler =
218 WSAAsyncSelect(channel->ch_fd, s_hwnd, WM_NETBEANS, FD_READ);
219# endif
220# endif
Bram Moolenaare0874f82016-01-24 20:36:41 +0100221# endif
Bram Moolenaard04a0202016-01-26 23:30:18 +0100222}
223
224/*
225 * Register any of our file descriptors with the GUI event handling system.
226 * Called when the GUI has started.
227 */
228 void
229channel_gui_register_all(void)
230{
231 int i;
232
233 for (i = 0; i < channel_count; ++i)
234 if (channels[i].ch_fd >= 0)
235 channel_gui_register(i);
236}
237
238 static void
239channel_gui_unregister(int idx)
240{
241 channel_T *channel = &channels[idx];
242
243# ifdef FEAT_GUI_X11
244 if (channel->ch_inputHandler != (XtInputId)NULL)
Bram Moolenaare0874f82016-01-24 20:36:41 +0100245 {
Bram Moolenaard04a0202016-01-26 23:30:18 +0100246 XtRemoveInput(channel->ch_inputHandler);
247 channel->ch_inputHandler = (XtInputId)NULL;
248 }
249# else
250# ifdef FEAT_GUI_GTK
251 if (channel->ch_inputHandler != 0)
252 {
253 gdk_input_remove(channel->ch_inputHandler);
254 channel->ch_inputHandler = 0;
255 }
256# else
257# ifdef FEAT_GUI_W32
258 if (channel->ch_inputHandler == 0)
259 {
Bram Moolenaar54e09e72016-01-26 23:49:31 +0100260 WSAAsyncSelect(channel->ch_fd, s_hwnd, 0, 0);
Bram Moolenaard04a0202016-01-26 23:30:18 +0100261 channel->ch_inputHandler = -1;
262 }
263# endif
264# endif
265# endif
266}
267
268#endif
269
270/*
271 * Open a channel to "hostname":"port".
272 * Returns the channel number for success.
273 * Returns a negative number for failure.
274 */
275 int
276channel_open(char *hostname, int port_in, void (*close_cb)(void))
277{
278 int sd;
279 struct sockaddr_in server;
280 struct hostent * host;
Bram Moolenaarf12d9832016-01-29 21:11:25 +0100281#ifdef WIN32
Bram Moolenaard04a0202016-01-26 23:30:18 +0100282 u_short port = port_in;
283#else
284 int port = port_in;
285#endif
286 int idx;
287
Bram Moolenaarf12d9832016-01-29 21:11:25 +0100288#ifdef WIN32
Bram Moolenaard04a0202016-01-26 23:30:18 +0100289 channel_init_winsock();
290#endif
291
292 idx = add_channel();
293 if (idx < 0)
294 {
295 CHERROR("All channels are in use\n", "");
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100296 EMSG(_("E897: All channels are in use"));
Bram Moolenaard04a0202016-01-26 23:30:18 +0100297 return -1;
298 }
299
300 if ((sd = (sock_T)socket(AF_INET, SOCK_STREAM, 0)) == (sock_T)-1)
301 {
302 CHERROR("error in socket() in channel_open()\n", "");
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100303 PERROR("E898: socket() in channel_open()");
Bram Moolenaard04a0202016-01-26 23:30:18 +0100304 return -1;
305 }
306
307 /* Get the server internet address and put into addr structure */
308 /* fill in the socket address structure and connect to server */
309 vim_memset((char *)&server, 0, sizeof(server));
310 server.sin_family = AF_INET;
311 server.sin_port = htons(port);
312 if ((host = gethostbyname(hostname)) == NULL)
313 {
314 CHERROR("error in gethostbyname() in channel_open()\n", "");
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100315 PERROR("E901: gethostbyname() in channel_open()");
Bram Moolenaard04a0202016-01-26 23:30:18 +0100316 sock_close(sd);
317 return -1;
318 }
319 memcpy((char *)&server.sin_addr, host->h_addr, host->h_length);
320
321 /* Connect to server */
322 if (connect(sd, (struct sockaddr *)&server, sizeof(server)))
323 {
324 SOCK_ERRNO;
325 CHERROR("channel_open: Connect failed with errno %d\n", errno);
326 if (errno == ECONNREFUSED)
327 {
328 sock_close(sd);
329 if ((sd = (sock_T)socket(AF_INET, SOCK_STREAM, 0)) == (sock_T)-1)
330 {
331 SOCK_ERRNO;
332 CHERROR("socket() retry in channel_open()\n", "");
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100333 PERROR("E900: socket() retry in channel_open()");
Bram Moolenaard04a0202016-01-26 23:30:18 +0100334 return -1;
335 }
336 if (connect(sd, (struct sockaddr *)&server, sizeof(server)))
337 {
338 int retries = 36;
339 int success = FALSE;
340
341 SOCK_ERRNO;
342 while (retries-- && ((errno == ECONNREFUSED)
343 || (errno == EINTR)))
344 {
345 CHERROR("retrying...\n", "");
346 mch_delay(3000L, TRUE);
347 ui_breakcheck();
348 if (got_int)
349 {
350 errno = EINTR;
351 break;
352 }
353 if (connect(sd, (struct sockaddr *)&server,
354 sizeof(server)) == 0)
355 {
356 success = TRUE;
357 break;
358 }
359 SOCK_ERRNO;
360 }
361 if (!success)
362 {
363 /* Get here when the server can't be found. */
364 CHERROR("Cannot connect to port after retry\n", "");
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100365 PERROR(_("E899: Cannot connect to port after retry2"));
Bram Moolenaard04a0202016-01-26 23:30:18 +0100366 sock_close(sd);
367 return -1;
368 }
369 }
370 }
371 else
372 {
373 CHERROR("Cannot connect to port\n", "");
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100374 PERROR(_("E902: Cannot connect to port"));
Bram Moolenaard04a0202016-01-26 23:30:18 +0100375 sock_close(sd);
376 return -1;
377 }
378 }
379
380 channels[idx].ch_fd = sd;
381 channels[idx].ch_close_cb = close_cb;
382
383#ifdef FEAT_GUI
384 channel_gui_register(idx);
385#endif
386
387 return idx;
388}
389
390/*
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100391 * Set the json mode of channel "idx" to TRUE or FALSE.
392 */
393 void
394channel_set_json_mode(int idx, int json_mode)
395{
396 channels[idx].ch_json_mode = json_mode;
397}
398
399/*
400 * Set the callback for channel "idx".
401 */
402 void
403channel_set_callback(int idx, char_u *callback)
404{
405 vim_free(channels[idx].ch_callback);
406 channels[idx].ch_callback = vim_strsave(callback);
407}
408
409/*
410 * Set the callback for channel "idx" for the next response.
411 */
412 void
413channel_set_req_callback(int idx, char_u *callback)
414{
415 vim_free(channels[idx].ch_req_callback);
416 channels[idx].ch_req_callback = callback == NULL
417 ? NULL : vim_strsave(callback);
418}
419
420/*
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100421 * Decode JSON "msg", which must have the form "[expr1, expr2, expr3]".
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100422 * Put "expr1" in "tv1".
423 * Put "expr2" in "tv2".
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100424 * Put "expr3" in "tv3". If "tv3" is NULL there is no "expr3".
425 *
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100426 * Return OK or FAIL.
427 */
428 int
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100429channel_decode_json(char_u *msg, typval_T *tv1, typval_T *tv2, typval_T *tv3)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100430{
431 js_read_T reader;
432 typval_T listtv;
433
434 reader.js_buf = msg;
435 reader.js_eof = TRUE;
436 reader.js_used = 0;
437 json_decode(&reader, &listtv);
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100438
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100439 if (listtv.v_type == VAR_LIST)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100440 {
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100441 list_T *list = listtv.vval.v_list;
442
443 if (list->lv_len == 2 || (tv3 != NULL && list->lv_len == 3))
444 {
445 /* Move the item from the list and then change the type to avoid the
446 * item being freed. */
447 *tv1 = list->lv_first->li_tv;
448 list->lv_first->li_tv.v_type = VAR_NUMBER;
449 *tv2 = list->lv_first->li_next->li_tv;
450 list->lv_first->li_next->li_tv.v_type = VAR_NUMBER;
451 if (tv3 != NULL)
452 {
453 if (list->lv_len == 3)
454 {
455 *tv3 = list->lv_last->li_tv;
456 list->lv_last->li_tv.v_type = VAR_NUMBER;
457 }
458 else
459 tv3->v_type = VAR_UNKNOWN;
460 }
461 list_unref(list);
462 return OK;
463 }
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100464 }
465
466 /* give error message? */
467 clear_tv(&listtv);
468 return FAIL;
469}
470
471/*
472 * Invoke the "callback" on channel "idx".
473 */
474 static void
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100475invoke_callback(int idx, char_u *callback, typval_T *argv)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100476{
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100477 typval_T rettv;
478 int dummy;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100479
480 argv[0].v_type = VAR_NUMBER;
481 argv[0].vval.v_number = idx;
482
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100483 call_func(callback, (int)STRLEN(callback),
484 &rettv, 2, argv, 0L, 0L, &dummy, TRUE, NULL);
485 /* If an echo command was used the cursor needs to be put back where
486 * it belongs. */
487 setcursor();
488 cursor_on();
489 out_flush();
490}
491
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100492/*
493 * Execute a command received over channel "idx".
494 * "cmd" is the command string, "arg2" the second argument.
495 * "arg3" is the third argument, NULL if missing.
496 */
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100497 static void
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100498channel_exe_cmd(int idx, char_u *cmd, typval_T *arg2, typval_T *arg3)
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100499{
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100500 char_u *arg;
501
502 if (arg2->v_type != VAR_STRING)
503 {
504 if (p_verbose > 2)
505 EMSG("E903: received ex command with non-string argument");
506 return;
507 }
508 arg = arg2->vval.v_string;
509
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100510 if (STRCMP(cmd, "ex") == 0)
511 {
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100512 do_cmdline_cmd(arg);
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100513 }
514 else if (STRCMP(cmd, "normal") == 0)
515 {
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100516 exarg_T ea;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100517
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100518 ea.arg = arg;
519 ea.addr_count = 0;
520 ea.forceit = TRUE; /* no mapping */
521 ex_normal(&ea);
522 }
523 else if (STRCMP(cmd, "redraw") == 0)
524 {
525 exarg_T ea;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100526
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100527 ea.forceit = *arg != NUL;
528 ex_redraw(&ea);
529 showruler(FALSE);
530 setcursor();
531 out_flush();
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100532#ifdef FEAT_GUI
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100533 if (gui.in_use)
534 {
535 gui_update_cursor(FALSE, FALSE);
536 gui_mch_flush();
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100537 }
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100538#endif
539 }
540 else if (STRCMP(cmd, "expr") == 0 || STRCMP(cmd, "eval") == 0)
541 {
542 int is_eval = cmd[1] == 'v';
543
544 if (is_eval && arg3->v_type != VAR_NUMBER)
545 {
546 if (p_verbose > 2)
547 EMSG("E904: third argument for eval must be a number");
548 }
549 else
550 {
551 typval_T *tv = eval_expr(arg, NULL);
552 typval_T err_tv;
553 char_u *json;
554
555 if (is_eval)
556 {
557 if (tv == NULL)
558 {
559 err_tv.v_type = VAR_STRING;
560 err_tv.vval.v_string = (char_u *)"ERROR";
561 tv = &err_tv;
562 }
563 json = json_encode_nr_expr(arg3->vval.v_number, tv);
564 channel_send(idx, json, "eval");
565 vim_free(json);
566 }
567 free_tv(tv);
568 }
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100569 }
570 else if (p_verbose > 2)
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100571 EMSG2("E905: received unknown command: %s", cmd);
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100572}
573
574/*
575 * Invoke a callback for channel "idx" if needed.
576 */
577 static void
578may_invoke_callback(int idx)
579{
580 char_u *msg;
581 typval_T typetv;
582 typval_T argv[3];
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100583 typval_T arg3;
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100584 char_u *cmd = NULL;
585 int seq_nr = -1;
586 int ret = OK;
587
588 if (channel_peek(idx) == NULL)
589 return;
590
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100591 /* Concatenate everything into one buffer.
592 * TODO: only read what the callback will use.
593 * TODO: avoid multiple allocations. */
594 while (channel_collapse(idx) == OK)
595 ;
596 msg = channel_get(idx);
597
598 if (channels[idx].ch_json_mode)
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100599 {
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100600 ret = channel_decode_json(msg, &typetv, &argv[1], &arg3);
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100601 if (ret == OK)
602 {
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100603 /* TODO: error if arg3 is set when it shouldn't? */
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100604 if (typetv.v_type == VAR_STRING)
605 cmd = typetv.vval.v_string;
606 else if (typetv.v_type == VAR_NUMBER)
607 seq_nr = typetv.vval.v_number;
608 }
609 }
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100610 else
611 {
612 argv[1].v_type = VAR_STRING;
613 argv[1].vval.v_string = msg;
614 }
615
616 if (ret == OK)
617 {
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100618 if (cmd != NULL)
619 {
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100620 channel_exe_cmd(idx, cmd, &argv[1], &arg3);
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100621 }
622 else if (channels[idx].ch_req_callback != NULL && seq_nr != 0)
623 {
624 /* TODO: check the sequence number */
625 /* invoke the one-time callback */
626 invoke_callback(idx, channels[idx].ch_req_callback, argv);
627 channels[idx].ch_req_callback = NULL;
628 }
629 else if (channels[idx].ch_callback != NULL)
630 {
631 /* invoke the channel callback */
632 invoke_callback(idx, channels[idx].ch_callback, argv);
633 }
634 /* else: drop the message */
635
636 if (channels[idx].ch_json_mode)
637 {
638 clear_tv(&typetv);
639 clear_tv(&argv[1]);
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100640 clear_tv(&arg3);
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100641 }
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100642 }
Bram Moolenaar20fb9f32016-01-30 23:20:33 +0100643
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100644 vim_free(msg);
645}
646
647/*
Bram Moolenaard04a0202016-01-26 23:30:18 +0100648 * Return TRUE when channel "idx" is open.
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100649 * Also returns FALSE or invalid "idx".
Bram Moolenaard04a0202016-01-26 23:30:18 +0100650 */
651 int
652channel_is_open(int idx)
653{
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100654 return idx >= 0 && idx < channel_count && channels[idx].ch_fd >= 0;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100655}
656
657/*
658 * Close channel "idx".
659 * This does not trigger the close callback.
660 */
661 void
662channel_close(int idx)
663{
664 channel_T *channel = &channels[idx];
665
666 if (channel->ch_fd >= 0)
667 {
668 sock_close(channel->ch_fd);
669 channel->ch_fd = -1;
670#ifdef FEAT_GUI
671 channel_gui_unregister(idx);
672#endif
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100673 vim_free(channel->ch_callback);
674 channel->ch_callback = NULL;
Bram Moolenaare0874f82016-01-24 20:36:41 +0100675 }
676}
677
Bram Moolenaard04a0202016-01-26 23:30:18 +0100678/*
679 * Store "buf[len]" on channel "idx".
Bram Moolenaar83162462016-01-28 23:10:07 +0100680 * Returns OK or FAIL.
Bram Moolenaard04a0202016-01-26 23:30:18 +0100681 */
Bram Moolenaar83162462016-01-28 23:10:07 +0100682 int
Bram Moolenaard04a0202016-01-26 23:30:18 +0100683channel_save(int idx, char_u *buf, int len)
684{
685 queue_T *node;
686 queue_T *head = &channels[idx].ch_head;
687
688 node = (queue_T *)alloc(sizeof(queue_T));
689 if (node == NULL)
Bram Moolenaar83162462016-01-28 23:10:07 +0100690 return FAIL; /* out of memory */
Bram Moolenaard04a0202016-01-26 23:30:18 +0100691 node->buffer = alloc(len + 1);
692 if (node->buffer == NULL)
693 {
694 vim_free(node);
Bram Moolenaar83162462016-01-28 23:10:07 +0100695 return FAIL; /* out of memory */
Bram Moolenaard04a0202016-01-26 23:30:18 +0100696 }
697 mch_memmove(node->buffer, buf, (size_t)len);
698 node->buffer[len] = NUL;
699
700 if (head->next == NULL) /* initialize circular queue */
701 {
702 head->next = head;
703 head->prev = head;
704 }
705
706 /* insert node at tail of queue */
707 node->next = head;
708 node->prev = head->prev;
709 head->prev->next = node;
710 head->prev = node;
711
712 if (debugfd != NULL)
713 {
714 fprintf(debugfd, "RECV on %d: ", idx);
Bram Moolenaar83162462016-01-28 23:10:07 +0100715 if (fwrite(buf, len, 1, debugfd) != 1)
716 return FAIL;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100717 fprintf(debugfd, "\n");
718 }
Bram Moolenaar83162462016-01-28 23:10:07 +0100719 return OK;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100720}
721
722/*
723 * Return the first buffer from the channel without removing it.
724 * Returns NULL if there is nothing.
725 */
726 char_u *
727channel_peek(int idx)
728{
729 queue_T *head = &channels[idx].ch_head;
730
731 if (head->next == head || head->next == NULL)
732 return NULL;
733 return head->next->buffer;
734}
735
736/*
737 * Return the first buffer from the channel and remove it.
738 * The caller must free it.
739 * Returns NULL if there is nothing.
740 */
741 char_u *
742channel_get(int idx)
743{
744 queue_T *head = &channels[idx].ch_head;
745 queue_T *node;
746 char_u *p;
747
748 if (head->next == head || head->next == NULL)
749 return NULL;
750 node = head->next;
751 /* dispose of the node but keep the buffer */
752 p = node->buffer;
753 head->next = node->next;
754 node->next->prev = node->prev;
755 vim_free(node);
756 return p;
757}
758
759/*
760 * Collapses the first and second buffer in the channel "idx".
761 * Returns FAIL if that is not possible.
762 */
763 int
764channel_collapse(int idx)
765{
766 queue_T *head = &channels[idx].ch_head;
767 queue_T *node = head->next;
768 char_u *p;
769
770 if (node == head || node == NULL || node->next == head)
771 return FAIL;
772
773 p = alloc((unsigned)(STRLEN(node->buffer)
774 + STRLEN(node->next->buffer) + 1));
775 if (p == NULL)
776 return FAIL; /* out of memory */
777 STRCPY(p, node->buffer);
778 STRCAT(p, node->next->buffer);
779 vim_free(node->next->buffer);
780 node->next->buffer = p;
781
782 /* dispose of the node and buffer */
783 head->next = node->next;
784 node->next->prev = node->prev;
785 vim_free(node->buffer);
786 vim_free(node);
787 return OK;
788}
789
790/*
791 * Clear the read buffer on channel "idx".
792 */
793 void
794channel_clear(int idx)
795{
796 queue_T *head = &channels[idx].ch_head;
797 queue_T *node = head->next;
798 queue_T *next;
799
800 while (node != NULL && node != head)
801 {
802 next = node->next;
803 vim_free(node->buffer);
804 vim_free(node);
805 if (next == head)
806 {
807 head->next = head;
808 head->prev = head;
809 break;
810 }
811 node = next;
812 }
813}
814
815/* Sent when the channel is found closed when reading. */
816#define DETACH_MSG "\"DETACH\"\n"
817
818/* Buffer size for reading incoming messages. */
819#define MAXMSGSIZE 4096
820
821/*
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100822 * Check for reading from "fd" with "timeout" msec.
823 * Return FAIL when there is nothing to read.
824 */
825 static int
826channel_wait(int fd, int timeout)
827{
828#ifdef HAVE_SELECT
829 struct timeval tval;
830 fd_set rfds;
831 int ret;
832
833 FD_ZERO(&rfds);
834 FD_SET(fd, &rfds);
835 tval.tv_sec = timeout / 1000;
836 tval.tv_usec = (timeout % 1000) * 1000;
837 for (;;)
838 {
839 ret = select(fd + 1, &rfds, NULL, NULL, &tval);
840# ifdef EINTR
841 if (ret == -1 && errno == EINTR)
842 continue;
843# endif
844 if (ret <= 0)
845 return FAIL;
846 break;
847 }
848#else
Bram Moolenaarb8b65112016-01-28 23:01:49 +0100849# ifdef HAVE_POLL
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100850 struct pollfd fds;
851
852 fds.fd = fd;
853 fds.events = POLLIN;
854 if (poll(&fds, 1, timeout) <= 0)
855 return FAIL;
Bram Moolenaarb8b65112016-01-28 23:01:49 +0100856# endif
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100857#endif
858 return OK;
859}
860
861/*
862 * Return a unique ID to be used in a message.
863 */
864 int
Bram Moolenaar7454a062016-01-30 15:14:10 +0100865channel_get_id(void)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100866{
867 static int next_id = 1;
868
869 return next_id++;
870}
871
872/*
873 * Read from channel "idx" for as long as there is something to read.
874 * The data is put in the read queue.
Bram Moolenaard04a0202016-01-26 23:30:18 +0100875 */
876 void
877channel_read(int idx)
878{
879 static char_u *buf = NULL;
880 int len = 0;
881 int readlen = 0;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100882 channel_T *channel = &channels[idx];
883
884 if (channel->ch_fd < 0)
885 {
886 CHLOG(idx, FALSE, "channel_read() called while socket is closed\n");
887 return;
888 }
889
890 /* Allocate a buffer to read into. */
891 if (buf == NULL)
892 {
893 buf = alloc(MAXMSGSIZE);
894 if (buf == NULL)
895 return; /* out of memory! */
896 }
897
898 /* Keep on reading for as long as there is something to read.
899 * Use select() or poll() to avoid blocking on a message that is exactly
900 * MAXMSGSIZE long. */
901 for (;;)
902 {
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100903 if (channel_wait(channel->ch_fd, 0) == FAIL)
Bram Moolenaard04a0202016-01-26 23:30:18 +0100904 break;
Bram Moolenaard04a0202016-01-26 23:30:18 +0100905 len = sock_read(channel->ch_fd, buf, MAXMSGSIZE);
906 if (len <= 0)
907 break; /* error or nothing more to read */
908
909 /* Store the read message in the queue. */
910 channel_save(idx, buf, len);
911 readlen += len;
912 if (len < MAXMSGSIZE)
913 break; /* did read everything that's available */
914 }
915
916 /* Reading a socket disconnection (readlen == 0), or a socket error. */
917 if (readlen <= 0)
918 {
919 /* Queue a "DETACH" netbeans message in the command queue in order to
920 * terminate the netbeans session later. Do not end the session here
921 * directly as we may be running in the context of a call to
922 * netbeans_parse_messages():
923 * netbeans_parse_messages
924 * -> autocmd triggered while processing the netbeans cmd
925 * -> ui_breakcheck
926 * -> gui event loop or select loop
927 * -> channel_read()
928 */
929 channel_save(idx, (char_u *)DETACH_MSG, (int)STRLEN(DETACH_MSG));
930
931 channel_close(idx);
932 if (channel->ch_close_cb != NULL)
933 (*channel->ch_close_cb)();
934
935 if (len < 0)
936 {
937 /* Todo: which channel? */
938 CHERROR("%s(): cannot from channel\n", "channel_read");
Bram Moolenaarfb1f6262016-01-31 20:24:32 +0100939 PERROR(_("E896: read from channel"));
Bram Moolenaard04a0202016-01-26 23:30:18 +0100940 }
941 }
942
943#if defined(CH_HAS_GUI) && defined(FEAT_GUI_GTK)
944 if (CH_HAS_GUI && gtk_main_level() > 0)
945 gtk_main_quit();
946#endif
947}
948
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100949/*
950 * Read from channel "idx". Blocks until there is something to read or the
951 * timeout expires.
952 * Returns what was read in allocated memory.
953 * Returns NULL in case of error or timeout.
954 */
955 char_u *
956channel_read_block(int idx)
957{
958 if (channel_peek(idx) == NULL)
959 {
960 /* Wait for up to 2 seconds.
961 * TODO: use timeout set on the channel. */
962 if (channel_wait(channels[idx].ch_fd, 2000) == FAIL)
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100963 return NULL;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100964 channel_read(idx);
965 }
966
967 /* Concatenate everything into one buffer.
968 * TODO: avoid multiple allocations. */
969 while (channel_collapse(idx) == OK)
970 ;
971
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100972 return channel_get(idx);
973}
974
Bram Moolenaarf12d9832016-01-29 21:11:25 +0100975# if defined(WIN32) || defined(PROTO)
Bram Moolenaar85be35f2016-01-27 21:08:18 +0100976/*
977 * Lookup the channel index from the socket.
978 * Returns -1 when the socket isn't found.
979 */
980 int
981channel_socket2idx(sock_T fd)
982{
983 int i;
984
985 if (fd >= 0)
986 for (i = 0; i < channel_count; ++i)
987 if (channels[i].ch_fd == fd)
988 return i;
989 return -1;
990}
991# endif
992
Bram Moolenaard04a0202016-01-26 23:30:18 +0100993/*
994 * Write "buf" (NUL terminated string) to channel "idx".
995 * When "fun" is not NULL an error message might be given.
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100996 * Return FAIL or OK.
Bram Moolenaard04a0202016-01-26 23:30:18 +0100997 */
Bram Moolenaar3b5f9292016-01-28 22:37:01 +0100998 int
Bram Moolenaard04a0202016-01-26 23:30:18 +0100999channel_send(int idx, char_u *buf, char *fun)
1000{
1001 channel_T *channel = &channels[idx];
1002 int len = (int)STRLEN(buf);
1003
1004 if (channel->ch_fd < 0)
1005 {
1006 if (!channel->ch_error && fun != NULL)
1007 {
1008 CHERROR(" %s(): write while not connected\n", fun);
1009 EMSG2("E630: %s(): write while not connected", fun);
1010 }
1011 channel->ch_error = TRUE;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001012 return FAIL;
Bram Moolenaard04a0202016-01-26 23:30:18 +01001013 }
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001014
1015 if (sock_write(channel->ch_fd, buf, len) != len)
Bram Moolenaard04a0202016-01-26 23:30:18 +01001016 {
1017 if (!channel->ch_error && fun != NULL)
1018 {
1019 CHERROR(" %s(): write failed\n", fun);
1020 EMSG2("E631: %s(): write failed", fun);
1021 }
1022 channel->ch_error = TRUE;
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001023 return FAIL;
Bram Moolenaard04a0202016-01-26 23:30:18 +01001024 }
Bram Moolenaar3b5f9292016-01-28 22:37:01 +01001025
1026 channel->ch_error = FALSE;
1027 return OK;
Bram Moolenaard04a0202016-01-26 23:30:18 +01001028}
1029
1030# if (defined(UNIX) && !defined(HAVE_SELECT)) || defined(PROTO)
Bram Moolenaare0874f82016-01-24 20:36:41 +01001031/*
1032 * Add open channels to the poll struct.
1033 * Return the adjusted struct index.
1034 * The type of "fds" is hidden to avoid problems with the function proto.
1035 */
1036 int
1037channel_poll_setup(int nfd_in, void *fds_in)
1038{
1039 int nfd = nfd_in;
1040 int i;
1041 struct pollfd *fds = fds_in;
1042
1043 for (i = 0; i < channel_count; ++i)
1044 if (channels[i].ch_fd >= 0)
1045 {
1046 channels[i].ch_idx = nfd;
1047 fds[nfd].fd = channels[i].ch_fd;
1048 fds[nfd].events = POLLIN;
1049 nfd++;
1050 }
1051 else
1052 channels[i].ch_idx = -1;
1053
1054 return nfd;
1055}
1056
1057/*
1058 * The type of "fds" is hidden to avoid problems with the function proto.
1059 */
1060 int
1061channel_poll_check(int ret_in, void *fds_in)
1062{
1063 int ret = ret_in;
1064 int i;
1065 struct pollfd *fds = fds_in;
1066
1067 for (i = 0; i < channel_count; ++i)
1068 if (ret > 0 && channels[i].ch_idx != -1
1069 && fds[channels[i].ch_idx].revents & POLLIN)
1070 {
1071 channel_read(i);
1072 --ret;
1073 }
1074
1075 return ret;
1076}
Bram Moolenaard04a0202016-01-26 23:30:18 +01001077# endif /* UNIX && !HAVE_SELECT */
Bram Moolenaare0874f82016-01-24 20:36:41 +01001078
Bram Moolenaarf12d9832016-01-29 21:11:25 +01001079# if (!defined(FEAT_GUI_W32) && defined(HAVE_SELECT)) || defined(PROTO)
Bram Moolenaare0874f82016-01-24 20:36:41 +01001080/*
1081 * The type of "rfds" is hidden to avoid problems with the function proto.
1082 */
1083 int
1084channel_select_setup(int maxfd_in, void *rfds_in)
1085{
1086 int maxfd = maxfd_in;
1087 int i;
1088 fd_set *rfds = rfds_in;
1089
1090 for (i = 0; i < channel_count; ++i)
1091 if (channels[i].ch_fd >= 0)
1092 {
1093 FD_SET(channels[i].ch_fd, rfds);
1094 if (maxfd < channels[i].ch_fd)
1095 maxfd = channels[i].ch_fd;
1096 }
1097
1098 return maxfd;
1099}
1100
1101/*
1102 * The type of "rfds" is hidden to avoid problems with the function proto.
1103 */
1104 int
1105channel_select_check(int ret_in, void *rfds_in)
1106{
1107 int ret = ret_in;
1108 int i;
1109 fd_set *rfds = rfds_in;
1110
1111 for (i = 0; i < channel_count; ++i)
1112 if (ret > 0 && channels[i].ch_fd >= 0
1113 && FD_ISSET(channels[i].ch_fd, rfds))
1114 {
1115 channel_read(i);
1116 --ret;
1117 }
1118
1119 return ret;
1120}
Bram Moolenaarf12d9832016-01-29 21:11:25 +01001121# endif /* !FEAT_GUI_W32 && HAVE_SELECT */
Bram Moolenaare0874f82016-01-24 20:36:41 +01001122
Bram Moolenaar20fb9f32016-01-30 23:20:33 +01001123/*
1124 * Invoked from the main loop when it's save to execute received commands.
1125 */
1126 void
1127channel_parse_messages(void)
1128{
1129 int i;
1130
1131 for (i = 0; i < channel_count; ++i)
1132 may_invoke_callback(i);
1133}
1134
Bram Moolenaare0874f82016-01-24 20:36:41 +01001135#endif /* FEAT_CHANNEL */