1 #ifndef NVIM_CHANNEL_H
2 #define NVIM_CHANNEL_H
3 
4 #include "nvim/eval/typval.h"
5 #include "nvim/event/libuv_process.h"
6 #include "nvim/event/process.h"
7 #include "nvim/event/socket.h"
8 #include "nvim/main.h"
9 #include "nvim/msgpack_rpc/channel_defs.h"
10 #include "nvim/os/pty_process.h"
11 
12 #define CHAN_STDIO 1
13 #define CHAN_STDERR 2
14 
15 typedef enum {
16   kChannelStreamProc,
17   kChannelStreamSocket,
18   kChannelStreamStdio,
19   kChannelStreamStderr,
20   kChannelStreamInternal,
21 } ChannelStreamType;
22 
23 typedef enum {
24   kChannelPartStdin,
25   kChannelPartStdout,
26   kChannelPartStderr,
27   kChannelPartRpc,
28   kChannelPartAll,
29 } ChannelPart;
30 
31 typedef enum {
32   kChannelStdinPipe,
33   kChannelStdinNull,
34 } ChannelStdinMode;
35 
36 typedef struct {
37   Stream in;
38   Stream out;
39 } StdioPair;
40 
41 typedef struct {
42   bool closed;
43 } StderrState;
44 
45 typedef struct {
46   LuaRef cb;
47 } InternalState;
48 
49 typedef struct {
50   Callback cb;
51   dict_T *self;
52   garray_T buffer;
53   bool eof;
54   bool buffered;
55   const char *type;
56 } CallbackReader;
57 
58 #define CALLBACK_READER_INIT ((CallbackReader){ .cb = CALLBACK_NONE, \
59                                                 .self = NULL, \
60                                                 .buffer = GA_EMPTY_INIT_VALUE, \
61                                                 .buffered = false, \
62                                                 .type = NULL })
callback_reader_set(CallbackReader reader)63 static inline bool callback_reader_set(CallbackReader reader)
64 {
65   return reader.cb.type != kCallbackNone || reader.self;
66 }
67 
68 struct Channel {
69   uint64_t id;
70   size_t refcount;
71   MultiQueue *events;
72 
73   ChannelStreamType streamtype;
74   union {
75     Process proc;
76     LibuvProcess uv;
77     PtyProcess pty;
78     Stream socket;
79     StdioPair stdio;
80     StderrState err;
81     InternalState internal;
82   } stream;
83 
84   bool is_rpc;
85   RpcState rpc;
86   Terminal *term;
87 
88   CallbackReader on_data;
89   CallbackReader on_stderr;
90   Callback on_exit;
91   int exit_status;
92 
93   bool callback_busy;
94   bool callback_scheduled;
95 };
96 
97 EXTERN PMap(uint64_t) channels INIT(= MAP_INIT);
98 
99 #ifdef INCLUDE_GENERATED_DECLARATIONS
100 # include "channel.h.generated.h"
101 #endif
102 
103 /// @returns Channel with the id or NULL if not found
find_channel(uint64_t id)104 static inline Channel *find_channel(uint64_t id)
105 {
106   return pmap_get(uint64_t)(&channels, id);
107 }
108 
channel_instream(Channel * chan)109 static inline Stream *channel_instream(Channel *chan)
110   FUNC_ATTR_NONNULL_ALL
111 {
112   switch (chan->streamtype) {
113   case kChannelStreamProc:
114     return &chan->stream.proc.in;
115 
116   case kChannelStreamSocket:
117     return &chan->stream.socket;
118 
119   case kChannelStreamStdio:
120     return &chan->stream.stdio.out;
121 
122   case kChannelStreamInternal:
123   case kChannelStreamStderr:
124     abort();
125   }
126   abort();
127 }
128 
channel_outstream(Channel * chan)129 static inline Stream *channel_outstream(Channel *chan)
130   FUNC_ATTR_NONNULL_ALL
131 {
132   switch (chan->streamtype) {
133   case kChannelStreamProc:
134     return &chan->stream.proc.out;
135 
136   case kChannelStreamSocket:
137     return &chan->stream.socket;
138 
139   case kChannelStreamStdio:
140     return &chan->stream.stdio.in;
141 
142   case kChannelStreamInternal:
143   case kChannelStreamStderr:
144     abort();
145   }
146   abort();
147 }
148 
149 
150 #endif  // NVIM_CHANNEL_H
151