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