comparison src/channel.c @ 7868:17e6ff1a74f1 v7.4.1231

commit https://github.com/vim/vim/commit/19d2f1589850d7db1ce77efec052929246f156e2 Author: Bram Moolenaar <Bram@vim.org> Date: Mon Feb 1 21:38:19 2016 +0100 patch 7.4.1231 Problem: JSON messages are not parsed properly. Solution: Queue received messages.
author Christian Brabandt <cb@256bit.org>
date Mon, 01 Feb 2016 21:45:06 +0100
parents 6b0891de44a9
children 4b9d4600166f
comparison
equal deleted inserted replaced
7867:3b79ecd05a51 7868:17e6ff1a74f1
72 { 72 {
73 char_u *buffer; 73 char_u *buffer;
74 struct readqueue *next; 74 struct readqueue *next;
75 struct readqueue *prev; 75 struct readqueue *prev;
76 }; 76 };
77 typedef struct readqueue queue_T; 77 typedef struct readqueue readq_T;
78
79 struct jsonqueue
80 {
81 typval_T *value;
82 struct jsonqueue *next;
83 struct jsonqueue *prev;
84 };
85 typedef struct jsonqueue jsonq_T;
78 86
79 typedef struct { 87 typedef struct {
80 sock_T ch_fd; /* the socket, -1 for a closed channel */ 88 sock_T ch_fd; /* the socket, -1 for a closed channel */
81 int ch_idx; /* used by channel_poll_setup() */ 89 int ch_idx; /* used by channel_poll_setup() */
82 queue_T ch_head; /* dummy node, header for circular queue */ 90 readq_T ch_head; /* dummy node, header for circular queue */
83 91
84 int ch_error; /* When TRUE an error was reported. Avoids giving 92 int ch_error; /* When TRUE an error was reported. Avoids giving
85 * pages full of error messages when the other side 93 * pages full of error messages when the other side
86 * has exited, only mention the first error until the 94 * has exited, only mention the first error until the
87 * connection works again. */ 95 * connection works again. */
98 void (*ch_close_cb)(void); /* callback for when channel is closed */ 106 void (*ch_close_cb)(void); /* callback for when channel is closed */
99 107
100 char_u *ch_callback; /* function to call when a msg is not handled */ 108 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 */ 109 char_u *ch_req_callback; /* function to call for current request */
102 110
103 int ch_json_mode; 111 int ch_json_mode; /* TRUE for a json channel */
112 jsonq_T ch_json_head; /* dummy node, header for circular queue */
104 } channel_T; 113 } channel_T;
105 114
106 /* 115 /*
107 * Information about all channels. 116 * Information about all channels.
108 * There can be gaps for closed channels, they will be reused later. 117 * There can be gaps for closed channels, they will be reused later.
123 static int 132 static int
124 add_channel(void) 133 add_channel(void)
125 { 134 {
126 int idx; 135 int idx;
127 channel_T *new_channels; 136 channel_T *new_channels;
137 channel_T *ch;
128 138
129 if (channels != NULL) 139 if (channels != NULL)
130 for (idx = 0; idx < channel_count; ++idx) 140 for (idx = 0; idx < channel_count; ++idx)
131 if (channels[idx].ch_fd < 0) 141 if (channels[idx].ch_fd < 0)
132 /* re-use a closed channel slot */ 142 /* re-use a closed channel slot */
137 if (new_channels == NULL) 147 if (new_channels == NULL)
138 return -1; 148 return -1;
139 if (channels != NULL) 149 if (channels != NULL)
140 mch_memmove(new_channels, channels, sizeof(channel_T) * channel_count); 150 mch_memmove(new_channels, channels, sizeof(channel_T) * channel_count);
141 channels = new_channels; 151 channels = new_channels;
142 (void)vim_memset(&channels[channel_count], 0, sizeof(channel_T)); 152 ch = &channels[channel_count];
143 153 (void)vim_memset(ch, 0, sizeof(channel_T));
144 channels[channel_count].ch_fd = (sock_T)-1; 154
155 ch->ch_fd = (sock_T)-1;
145 #ifdef FEAT_GUI_X11 156 #ifdef FEAT_GUI_X11
146 channels[channel_count].ch_inputHandler = (XtInputId)NULL; 157 ch->ch_inputHandler = (XtInputId)NULL;
147 #endif 158 #endif
148 #ifdef FEAT_GUI_GTK 159 #ifdef FEAT_GUI_GTK
149 channels[channel_count].ch_inputHandler = 0; 160 ch->ch_inputHandler = 0;
150 #endif 161 #endif
151 #ifdef FEAT_GUI_W32 162 #ifdef FEAT_GUI_W32
152 channels[channel_count].ch_inputHandler = -1; 163 ch->ch_inputHandler = -1;
153 #endif 164 #endif
165 /* initialize circular queues */
166 ch->ch_head.next = &ch->ch_head;
167 ch->ch_head.prev = &ch->ch_head;
168 ch->ch_json_head.next = &ch->ch_json_head;
169 ch->ch_json_head.prev = &ch->ch_json_head;
154 170
155 return channel_count++; 171 return channel_count++;
156 } 172 }
157 173
158 #if defined(FEAT_GUI) || defined(PROTO) 174 #if defined(FEAT_GUI) || defined(PROTO)
410 * Set the callback for channel "idx" for the next response. 426 * Set the callback for channel "idx" for the next response.
411 */ 427 */
412 void 428 void
413 channel_set_req_callback(int idx, char_u *callback) 429 channel_set_req_callback(int idx, char_u *callback)
414 { 430 {
431 /* TODO: make a list of callbacks */
415 vim_free(channels[idx].ch_req_callback); 432 vim_free(channels[idx].ch_req_callback);
416 channels[idx].ch_req_callback = callback == NULL 433 channels[idx].ch_req_callback = callback == NULL
417 ? NULL : vim_strsave(callback); 434 ? NULL : vim_strsave(callback);
418 }
419
420 /*
421 * Decode JSON "msg", which must have the form "[expr1, expr2, expr3]".
422 * Put "expr1" in "tv1".
423 * Put "expr2" in "tv2".
424 * Put "expr3" in "tv3". If "tv3" is NULL there is no "expr3".
425 *
426 * Return OK or FAIL.
427 */
428 int
429 channel_decode_json(char_u *msg, typval_T *tv1, typval_T *tv2, typval_T *tv3)
430 {
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);
438
439 if (listtv.v_type == VAR_LIST)
440 {
441 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 }
464 }
465
466 /* give error message? */
467 clear_tv(&listtv);
468 return FAIL;
469 } 435 }
470 436
471 /* 437 /*
472 * Invoke the "callback" on channel "idx". 438 * Invoke the "callback" on channel "idx".
473 */ 439 */
488 cursor_on(); 454 cursor_on();
489 out_flush(); 455 out_flush();
490 } 456 }
491 457
492 /* 458 /*
459 * Return the first buffer from the channel and remove it.
460 * The caller must free it.
461 * Returns NULL if there is nothing.
462 */
463 char_u *
464 channel_get(int idx)
465 {
466 readq_T *head = &channels[idx].ch_head;
467 readq_T *node;
468 char_u *p;
469
470 if (head->next == head || head->next == NULL)
471 return NULL;
472 node = head->next;
473 /* dispose of the node but keep the buffer */
474 p = node->buffer;
475 head->next = node->next;
476 node->next->prev = node->prev;
477 vim_free(node);
478 return p;
479 }
480
481 /*
482 * Returns the whole buffer contents concatenated.
483 */
484 static char_u *
485 channel_get_all(int idx)
486 {
487 /* Concatenate everything into one buffer.
488 * TODO: avoid multiple allocations. */
489 while (channel_collapse(idx) == OK)
490 ;
491 return channel_get(idx);
492 }
493
494 /*
495 * Collapses the first and second buffer in the channel "idx".
496 * Returns FAIL if that is not possible.
497 */
498 int
499 channel_collapse(int idx)
500 {
501 readq_T *head = &channels[idx].ch_head;
502 readq_T *node = head->next;
503 char_u *p;
504
505 if (node == head || node == NULL || node->next == head)
506 return FAIL;
507
508 p = alloc((unsigned)(STRLEN(node->buffer)
509 + STRLEN(node->next->buffer) + 1));
510 if (p == NULL)
511 return FAIL; /* out of memory */
512 STRCPY(p, node->buffer);
513 STRCAT(p, node->next->buffer);
514 vim_free(node->next->buffer);
515 node->next->buffer = p;
516
517 /* dispose of the node and buffer */
518 head->next = node->next;
519 node->next->prev = node->prev;
520 vim_free(node->buffer);
521 vim_free(node);
522 return OK;
523 }
524
525 /*
526 * Use the read buffer of channel "ch_idx" and parse JSON messages that are
527 * complete. The messages are added to the queue.
528 */
529 void
530 channel_read_json(int ch_idx)
531 {
532 js_read_T reader;
533 typval_T listtv;
534 jsonq_T *item;
535 jsonq_T *head = &channels[ch_idx].ch_json_head;
536
537 if (channel_peek(ch_idx) == NULL)
538 return;
539
540 /* TODO: make reader work properly */
541 /* reader.js_buf = channel_peek(ch_idx); */
542 reader.js_buf = channel_get_all(ch_idx);
543 reader.js_eof = TRUE;
544 /* reader.js_eof = FALSE; */
545 reader.js_used = 0;
546 /* reader.js_fill = channel_fill; */
547 reader.js_cookie = &ch_idx;
548 if (json_decode(&reader, &listtv) == OK)
549 {
550 item = (jsonq_T *)alloc((unsigned)sizeof(jsonq_T));
551 if (item == NULL)
552 clear_tv(&listtv);
553 else
554 {
555 item->value = alloc_tv();
556 if (item->value == NULL)
557 {
558 vim_free(item);
559 clear_tv(&listtv);
560 }
561 else
562 {
563 *item->value = listtv;
564 item->prev = head->prev;
565 head->prev = item;
566 item->next = head;
567 item->prev->next = item;
568 }
569 }
570 }
571 }
572
573 /*
574 * Remove "node" from the queue that it is in and free it.
575 * Caller should have freed or used node->value.
576 */
577 static void
578 remove_json_node(jsonq_T *node)
579 {
580 node->prev->next = node->next;
581 node->next->prev = node->prev;
582 vim_free(node);
583 }
584
585 /*
586 * Get a message from the JSON queue for channel "ch_idx".
587 * When "id" is positive it must match the first number in the list.
588 * When "id" is zero or negative jut get the first message.
589 * Return OK when found and return the value in "rettv".
590 * Return FAIL otherwise.
591 */
592 static int
593 channel_get_json(int ch_idx, int id, typval_T **rettv)
594 {
595 jsonq_T *head = &channels[ch_idx].ch_json_head;
596 jsonq_T *item = head->next;
597
598 while (item != head)
599 {
600 list_T *l = item->value->vval.v_list;
601 typval_T *tv = &l->lv_first->li_tv;
602
603 if ((id > 0 && tv->v_type == VAR_NUMBER && tv->vval.v_number == id)
604 || id <= 0)
605 {
606 *rettv = item->value;
607 remove_json_node(item);
608 return OK;
609 }
610 item = item->next;
611 }
612 return FAIL;
613 }
614
615 /*
493 * Execute a command received over channel "idx". 616 * Execute a command received over channel "idx".
494 * "cmd" is the command string, "arg2" the second argument. 617 * "cmd" is the command string, "arg2" the second argument.
495 * "arg3" is the third argument, NULL if missing. 618 * "arg3" is the third argument, NULL if missing.
496 */ 619 */
497 static void 620 static void
522 } 645 }
523 else if (STRCMP(cmd, "redraw") == 0) 646 else if (STRCMP(cmd, "redraw") == 0)
524 { 647 {
525 exarg_T ea; 648 exarg_T ea;
526 649
527 ea.forceit = *arg != NUL; 650 ea.forceit = arg != NULL && *arg != NUL;
528 ex_redraw(&ea); 651 ex_redraw(&ea);
529 showruler(FALSE); 652 showruler(FALSE);
530 setcursor(); 653 setcursor();
531 out_flush(); 654 out_flush();
532 #ifdef FEAT_GUI 655 #ifdef FEAT_GUI
575 * Invoke a callback for channel "idx" if needed. 698 * Invoke a callback for channel "idx" if needed.
576 */ 699 */
577 static void 700 static void
578 may_invoke_callback(int idx) 701 may_invoke_callback(int idx)
579 { 702 {
580 char_u *msg; 703 char_u *msg = NULL;
581 typval_T typetv; 704 typval_T *listtv = NULL;
705 list_T *list;
706 typval_T *typetv;
582 typval_T argv[3]; 707 typval_T argv[3];
583 typval_T arg3;
584 char_u *cmd = NULL;
585 int seq_nr = -1; 708 int seq_nr = -1;
586 int ret = OK; 709 int json_mode = channels[idx].ch_json_mode;
587 710
588 if (channel_peek(idx) == NULL) 711 if (channel_peek(idx) == NULL)
589 return; 712 return;
590 713 if (channels[idx].ch_close_cb != NULL)
591 /* Concatenate everything into one buffer. 714 /* this channel is handled elsewhere (netbeans) */
592 * TODO: only read what the callback will use. 715 return;
593 * TODO: avoid multiple allocations. */ 716
594 while (channel_collapse(idx) == OK) 717 if (json_mode)
595 ; 718 {
596 msg = channel_get(idx); 719 /* Get any json message. Return if there isn't one. */
597 720 channel_read_json(idx);
598 if (channels[idx].ch_json_mode) 721 if (channel_get_json(idx, -1, &listtv) == FAIL)
599 { 722 return;
600 ret = channel_decode_json(msg, &typetv, &argv[1], &arg3); 723 if (listtv->v_type != VAR_LIST)
601 if (ret == OK) 724 {
602 { 725 /* TODO: give error */
603 /* TODO: error if arg3 is set when it shouldn't? */ 726 clear_tv(listtv);
604 if (typetv.v_type == VAR_STRING) 727 return;
605 cmd = typetv.vval.v_string; 728 }
606 else if (typetv.v_type == VAR_NUMBER) 729
607 seq_nr = typetv.vval.v_number; 730 list = listtv->vval.v_list;
608 } 731 if (list->lv_len < 2)
732 {
733 /* TODO: give error */
734 clear_tv(listtv);
735 return;
736 }
737
738 argv[1] = list->lv_first->li_next->li_tv;
739 typetv = &list->lv_first->li_tv;
740 if (typetv->v_type == VAR_STRING)
741 {
742 typval_T *arg3 = NULL;
743 char_u *cmd = typetv->vval.v_string;
744
745 /* ["cmd", arg] */
746 if (list->lv_len == 3)
747 arg3 = &list->lv_last->li_tv;
748 channel_exe_cmd(idx, cmd, &argv[1], arg3);
749 clear_tv(listtv);
750 return;
751 }
752
753 if (typetv->v_type != VAR_NUMBER)
754 {
755 /* TODO: give error */
756 clear_tv(listtv);
757 return;
758 }
759 seq_nr = typetv->vval.v_number;
609 } 760 }
610 else 761 else
611 { 762 {
763 /* For a raw channel we don't know where the message ends, just get
764 * everything. */
765 msg = channel_get_all(idx);
612 argv[1].v_type = VAR_STRING; 766 argv[1].v_type = VAR_STRING;
613 argv[1].vval.v_string = msg; 767 argv[1].vval.v_string = msg;
614 } 768 }
615 769
616 if (ret == OK) 770 if (channels[idx].ch_req_callback != NULL && seq_nr != 0)
617 { 771 {
618 if (cmd != NULL) 772 /* TODO: check the sequence number */
619 { 773 /* invoke the one-time callback */
620 channel_exe_cmd(idx, cmd, &argv[1], &arg3); 774 invoke_callback(idx, channels[idx].ch_req_callback, argv);
621 } 775 channels[idx].ch_req_callback = NULL;
622 else if (channels[idx].ch_req_callback != NULL && seq_nr != 0) 776 }
623 { 777 else if (channels[idx].ch_callback != NULL)
624 /* TODO: check the sequence number */ 778 {
625 /* invoke the one-time callback */ 779 /* invoke the channel callback */
626 invoke_callback(idx, channels[idx].ch_req_callback, argv); 780 invoke_callback(idx, channels[idx].ch_callback, argv);
627 channels[idx].ch_req_callback = NULL; 781 }
628 } 782 /* else: drop the message TODO: give error */
629 else if (channels[idx].ch_callback != NULL) 783
630 { 784 if (listtv != NULL)
631 /* invoke the channel callback */ 785 clear_tv(listtv);
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]);
640 clear_tv(&arg3);
641 }
642 }
643
644 vim_free(msg); 786 vim_free(msg);
645 } 787 }
646 788
647 /* 789 /*
648 * Return TRUE when channel "idx" is open. 790 * Return TRUE when channel "idx" is open.
659 * This does not trigger the close callback. 801 * This does not trigger the close callback.
660 */ 802 */
661 void 803 void
662 channel_close(int idx) 804 channel_close(int idx)
663 { 805 {
664 channel_T *channel = &channels[idx]; 806 channel_T *channel = &channels[idx];
807 jsonq_T *jhead;
665 808
666 if (channel->ch_fd >= 0) 809 if (channel->ch_fd >= 0)
667 { 810 {
668 sock_close(channel->ch_fd); 811 sock_close(channel->ch_fd);
669 channel->ch_fd = -1; 812 channel->ch_fd = -1;
813 channel->ch_close_cb = NULL;
670 #ifdef FEAT_GUI 814 #ifdef FEAT_GUI
671 channel_gui_unregister(idx); 815 channel_gui_unregister(idx);
672 #endif 816 #endif
673 vim_free(channel->ch_callback); 817 vim_free(channel->ch_callback);
674 channel->ch_callback = NULL; 818 channel->ch_callback = NULL;
819
820 while (channel_peek(idx) != NULL)
821 vim_free(channel_get(idx));
822
823 jhead = &channel->ch_json_head;
824 while (jhead->next != jhead)
825 {
826 clear_tv(jhead->next->value);
827 remove_json_node(jhead->next);
828 }
675 } 829 }
676 } 830 }
677 831
678 /* 832 /*
679 * Store "buf[len]" on channel "idx". 833 * Store "buf[len]" on channel "idx".
680 * Returns OK or FAIL. 834 * Returns OK or FAIL.
681 */ 835 */
682 int 836 int
683 channel_save(int idx, char_u *buf, int len) 837 channel_save(int idx, char_u *buf, int len)
684 { 838 {
685 queue_T *node; 839 readq_T *node;
686 queue_T *head = &channels[idx].ch_head; 840 readq_T *head = &channels[idx].ch_head;
687 841
688 node = (queue_T *)alloc(sizeof(queue_T)); 842 node = (readq_T *)alloc(sizeof(readq_T));
689 if (node == NULL) 843 if (node == NULL)
690 return FAIL; /* out of memory */ 844 return FAIL; /* out of memory */
691 node->buffer = alloc(len + 1); 845 node->buffer = alloc(len + 1);
692 if (node->buffer == NULL) 846 if (node->buffer == NULL)
693 { 847 {
694 vim_free(node); 848 vim_free(node);
695 return FAIL; /* out of memory */ 849 return FAIL; /* out of memory */
696 } 850 }
697 mch_memmove(node->buffer, buf, (size_t)len); 851 mch_memmove(node->buffer, buf, (size_t)len);
698 node->buffer[len] = NUL; 852 node->buffer[len] = NUL;
699
700 if (head->next == NULL) /* initialize circular queue */
701 {
702 head->next = head;
703 head->prev = head;
704 }
705 853
706 /* insert node at tail of queue */ 854 /* insert node at tail of queue */
707 node->next = head; 855 node->next = head;
708 node->prev = head->prev; 856 node->prev = head->prev;
709 head->prev->next = node; 857 head->prev->next = node;
724 * Returns NULL if there is nothing. 872 * Returns NULL if there is nothing.
725 */ 873 */
726 char_u * 874 char_u *
727 channel_peek(int idx) 875 channel_peek(int idx)
728 { 876 {
729 queue_T *head = &channels[idx].ch_head; 877 readq_T *head = &channels[idx].ch_head;
730 878
731 if (head->next == head || head->next == NULL) 879 if (head->next == head || head->next == NULL)
732 return NULL; 880 return NULL;
733 return head->next->buffer; 881 return head->next->buffer;
734 } 882 }
735 883
736 /* 884 /*
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 *
742 channel_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
764 channel_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". 885 * Clear the read buffer on channel "idx".
792 */ 886 */
793 void 887 void
794 channel_clear(int idx) 888 channel_clear(int idx)
795 { 889 {
796 queue_T *head = &channels[idx].ch_head; 890 readq_T *head = &channels[idx].ch_head;
797 queue_T *node = head->next; 891 readq_T *node = head->next;
798 queue_T *next; 892 readq_T *next;
799 893
800 while (node != NULL && node != head) 894 while (node != NULL && node != head)
801 { 895 {
802 next = node->next; 896 next = node->next;
803 vim_free(node->buffer); 897 vim_free(node->buffer);
945 gtk_main_quit(); 1039 gtk_main_quit();
946 #endif 1040 #endif
947 } 1041 }
948 1042
949 /* 1043 /*
950 * Read from channel "idx". Blocks until there is something to read or the 1044 * Read from raw channel "idx". Blocks until there is something to read or
951 * timeout expires. 1045 * the timeout expires.
952 * Returns what was read in allocated memory. 1046 * Returns what was read in allocated memory.
953 * Returns NULL in case of error or timeout. 1047 * Returns NULL in case of error or timeout.
954 */ 1048 */
955 char_u * 1049 char_u *
956 channel_read_block(int idx) 1050 channel_read_block(int idx)
962 if (channel_wait(channels[idx].ch_fd, 2000) == FAIL) 1056 if (channel_wait(channels[idx].ch_fd, 2000) == FAIL)
963 return NULL; 1057 return NULL;
964 channel_read(idx); 1058 channel_read(idx);
965 } 1059 }
966 1060
967 /* Concatenate everything into one buffer. 1061 return channel_get_all(idx);
968 * TODO: avoid multiple allocations. */ 1062 }
969 while (channel_collapse(idx) == OK) 1063
970 ; 1064 /*
971 1065 * Read one JSON message from channel "ch_idx" with ID "id" and store the
972 return channel_get(idx); 1066 * result in "rettv".
1067 * Blocks until the message is received.
1068 */
1069 int
1070 channel_read_json_block(int ch_idx, int id, typval_T **rettv)
1071 {
1072 for (;;)
1073 {
1074 channel_read_json(ch_idx);
1075
1076 /* search for messsage "id" */
1077 if (channel_get_json(ch_idx, id, rettv) == OK)
1078 return OK;
1079
1080 /* Wait for up to 2 seconds.
1081 * TODO: use timeout set on the channel. */
1082 if (channel_wait(channels[ch_idx].ch_fd, 2000) == FAIL)
1083 break;
1084 channel_read(ch_idx);
1085 }
1086 return FAIL;
973 } 1087 }
974 1088
975 # if defined(WIN32) || defined(PROTO) 1089 # if defined(WIN32) || defined(PROTO)
976 /* 1090 /*
977 * Lookup the channel index from the socket. 1091 * Lookup the channel index from the socket.