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