]> andersk Git - openssh.git/blob - nchan.c
- Merged very large OpenBSD source code reformat
[openssh.git] / nchan.c
1 #include "includes.h"
2 RCSID("$Id$");
3
4 #include "ssh.h"
5
6 #include "buffer.h"
7 #include "packet.h"
8 #include "channels.h"
9 #include "nchan.h"
10
11 static void chan_send_ieof(Channel *c);
12 static void chan_send_oclose(Channel *c);
13 static void chan_shutdown_write(Channel *c);
14 static void chan_shutdown_read(Channel *c);
15 static void chan_delele_if_full_closed(Channel *c);
16
17 /*
18  * EVENTS update channel input/output states execute ACTIONS
19  */
20
21 /* events concerning the INPUT from socket for channel (istate) */
22 void
23 chan_rcvd_oclose(Channel *c)
24 {
25         switch (c->istate) {
26         case CHAN_INPUT_WAIT_OCLOSE:
27                 debug("channel %d: INPUT_WAIT_OCLOSE -> INPUT_CLOSED [rcvd OCLOSE]", c->self);
28                 c->istate = CHAN_INPUT_CLOSED;
29                 chan_delele_if_full_closed(c);
30                 break;
31         case CHAN_INPUT_OPEN:
32                 debug("channel %d: INPUT_OPEN -> INPUT_CLOSED [rvcd OCLOSE, send IEOF]", c->self);
33                 chan_shutdown_read(c);
34                 chan_send_ieof(c);
35                 c->istate = CHAN_INPUT_CLOSED;
36                 chan_delele_if_full_closed(c);
37                 break;
38         default:
39                 debug("protocol error: chan_rcvd_oclose %d for istate %d", c->self, c->istate);
40                 break;
41         }
42 }
43 void
44 chan_read_failed(Channel *c)
45 {
46         switch (c->istate) {
47         case CHAN_INPUT_OPEN:
48                 debug("channel %d: INPUT_OPEN -> INPUT_WAIT_DRAIN [read failed]", c->self);
49                 chan_shutdown_read(c);
50                 c->istate = CHAN_INPUT_WAIT_DRAIN;
51                 break;
52         default:
53                 debug("internal error: we do not read, but chan_read_failed %d for istate %d",
54                       c->self, c->istate);
55                 break;
56         }
57 }
58 void
59 chan_ibuf_empty(Channel *c)
60 {
61         if (buffer_len(&c->input)) {
62                 debug("internal error: chan_ibuf_empty %d for non empty buffer", c->self);
63                 return;
64         }
65         switch (c->istate) {
66         case CHAN_INPUT_WAIT_DRAIN:
67                 debug("channel %d: INPUT_WAIT_DRAIN -> INPUT_WAIT_OCLOSE [inbuf empty, send IEOF]", c->self);
68                 chan_send_ieof(c);
69                 c->istate = CHAN_INPUT_WAIT_OCLOSE;
70                 break;
71         default:
72                 debug("internal error: chan_ibuf_empty %d for istate %d", c->self, c->istate);
73                 break;
74         }
75 }
76
77 /* events concerning the OUTPUT from channel for socket (ostate) */
78 void
79 chan_rcvd_ieof(Channel *c)
80 {
81         switch (c->ostate) {
82         case CHAN_OUTPUT_OPEN:
83                 debug("channel %d: OUTPUT_OPEN -> OUTPUT_WAIT_DRAIN [rvcd IEOF]", c->self);
84                 c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
85                 break;
86         case CHAN_OUTPUT_WAIT_IEOF:
87                 debug("channel %d: OUTPUT_WAIT_IEOF -> OUTPUT_CLOSED [rvcd IEOF]", c->self);
88                 c->ostate = CHAN_OUTPUT_CLOSED;
89                 chan_delele_if_full_closed(c);
90                 break;
91         default:
92                 debug("protocol error: chan_rcvd_ieof %d for ostate %d", c->self, c->ostate);
93                 break;
94         }
95 }
96 void
97 chan_write_failed(Channel *c)
98 {
99         switch (c->ostate) {
100         case CHAN_OUTPUT_OPEN:
101                 debug("channel %d: OUTPUT_OPEN -> OUTPUT_WAIT_IEOF [write failed]", c->self);
102                 chan_send_oclose(c);
103                 c->ostate = CHAN_OUTPUT_WAIT_IEOF;
104                 break;
105         case CHAN_OUTPUT_WAIT_DRAIN:
106                 debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [write failed]", c->self);
107                 chan_send_oclose(c);
108                 c->ostate = CHAN_OUTPUT_CLOSED;
109                 chan_delele_if_full_closed(c);
110                 break;
111         default:
112                 debug("internal error: chan_write_failed %d for ostate %d", c->self, c->ostate);
113                 break;
114         }
115 }
116 void
117 chan_obuf_empty(Channel *c)
118 {
119         if (buffer_len(&c->output)) {
120                 debug("internal error: chan_obuf_empty %d for non empty buffer", c->self);
121                 return;
122         }
123         switch (c->ostate) {
124         case CHAN_OUTPUT_WAIT_DRAIN:
125                 debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [obuf empty, send OCLOSE]", c->self);
126                 chan_send_oclose(c);
127                 c->ostate = CHAN_OUTPUT_CLOSED;
128                 chan_delele_if_full_closed(c);
129                 break;
130         default:
131                 debug("internal error: chan_obuf_empty %d for ostate %d", c->self, c->ostate);
132                 break;
133         }
134 }
135
136 /*
137  * ACTIONS: should never update the channel states: c->istate or c->ostate
138  */
139 static void
140 chan_send_ieof(Channel *c)
141 {
142         switch (c->istate) {
143         case CHAN_INPUT_OPEN:
144         case CHAN_INPUT_WAIT_DRAIN:
145                 packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
146                 packet_put_int(c->remote_id);
147                 packet_send();
148                 break;
149         default:
150                 debug("internal error: channel %d: cannot send IEOF for istate %d", c->self, c->istate);
151                 break;
152         }
153 }
154 static void
155 chan_send_oclose(Channel *c)
156 {
157         switch (c->ostate) {
158         case CHAN_OUTPUT_OPEN:
159         case CHAN_OUTPUT_WAIT_DRAIN:
160                 chan_shutdown_write(c);
161                 buffer_consume(&c->output, buffer_len(&c->output));
162                 packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
163                 packet_put_int(c->remote_id);
164                 packet_send();
165                 break;
166         default:
167                 debug("internal error: channel %d: cannot send OCLOSE for ostate %d", c->self, c->istate);
168                 break;
169         }
170 }
171
172 /* helper */
173 static void
174 chan_shutdown_write(Channel *c)
175 {
176         debug("channel %d: shutdown_write", c->self);
177         if (shutdown(c->sock, SHUT_WR) < 0)
178                 error("chan_shutdown_write failed for #%d/fd%d: %.100s",
179                       c->self, c->sock, strerror(errno));
180 }
181 static void
182 chan_shutdown_read(Channel *c)
183 {
184         debug("channel %d: shutdown_read", c->self);
185         if (shutdown(c->sock, SHUT_RD) < 0)
186                 error("chan_shutdown_read failed for #%d/fd%d: %.100s",
187                       c->self, c->sock, strerror(errno));
188 }
189 static void
190 chan_delele_if_full_closed(Channel *c)
191 {
192         if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
193                 debug("channel %d: closing", c->self);
194                 channel_free(c->self);
195         }
196 }
197 void
198 chan_init_iostates(Channel *c)
199 {
200         c->ostate = CHAN_OUTPUT_OPEN;
201         c->istate = CHAN_INPUT_OPEN;
202 }
This page took 0.12029 seconds and 5 git commands to generate.