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