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);
18 * EVENTS update channel input/output states execute ACTIONS
21 /* events concerning the INPUT from socket for channel (istate) */
23 chan_rcvd_oclose(Channel *c)
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);
32 debug("channel %d: INPUT_OPEN -> INPUT_CLOSED [rvcd OCLOSE, send IEOF]", c->self);
33 chan_shutdown_read(c);
35 c->istate = CHAN_INPUT_CLOSED;
36 chan_delele_if_full_closed(c);
39 debug("protocol error: chan_rcvd_oclose %d for istate %d", c->self, c->istate);
44 chan_read_failed(Channel *c)
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;
53 debug("internal error: we do not read, but chan_read_failed %d for istate %d",
59 chan_ibuf_empty(Channel *c)
61 if (buffer_len(&c->input)) {
62 debug("internal error: chan_ibuf_empty %d for non empty buffer", c->self);
66 case CHAN_INPUT_WAIT_DRAIN:
67 debug("channel %d: INPUT_WAIT_DRAIN -> INPUT_WAIT_OCLOSE [inbuf empty, send IEOF]", c->self);
69 c->istate = CHAN_INPUT_WAIT_OCLOSE;
72 debug("internal error: chan_ibuf_empty %d for istate %d", c->self, c->istate);
77 /* events concerning the OUTPUT from channel for socket (ostate) */
79 chan_rcvd_ieof(Channel *c)
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;
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);
92 debug("protocol error: chan_rcvd_ieof %d for ostate %d", c->self, c->ostate);
97 chan_write_failed(Channel *c)
100 case CHAN_OUTPUT_OPEN:
101 debug("channel %d: OUTPUT_OPEN -> OUTPUT_WAIT_IEOF [write failed]", c->self);
103 c->ostate = CHAN_OUTPUT_WAIT_IEOF;
105 case CHAN_OUTPUT_WAIT_DRAIN:
106 debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [write failed]", c->self);
108 c->ostate = CHAN_OUTPUT_CLOSED;
109 chan_delele_if_full_closed(c);
112 debug("internal error: chan_write_failed %d for ostate %d", c->self, c->ostate);
117 chan_obuf_empty(Channel *c)
119 if (buffer_len(&c->output)) {
120 debug("internal error: chan_obuf_empty %d for non empty buffer", c->self);
124 case CHAN_OUTPUT_WAIT_DRAIN:
125 debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [obuf empty, send OCLOSE]", c->self);
127 c->ostate = CHAN_OUTPUT_CLOSED;
128 chan_delele_if_full_closed(c);
131 debug("internal error: chan_obuf_empty %d for ostate %d", c->self, c->ostate);
137 * ACTIONS: should never update the channel states: c->istate or c->ostate
140 chan_send_ieof(Channel *c)
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);
150 debug("internal error: channel %d: cannot send IEOF for istate %d", c->self, c->istate);
155 chan_send_oclose(Channel *c)
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);
167 debug("internal error: channel %d: cannot send OCLOSE for ostate %d", c->self, c->istate);
174 chan_shutdown_write(Channel *c)
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));
182 chan_shutdown_read(Channel *c)
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));
190 chan_delele_if_full_closed(Channel *c)
192 if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
193 debug("channel %d: closing", c->self);
194 channel_free(c->self);
198 chan_init_iostates(Channel *c)
200 c->ostate = CHAN_OUTPUT_OPEN;
201 c->istate = CHAN_INPUT_OPEN;