Annotation of src/usr.bin/ssh/nchan.c, Revision 1.4
1.1 markus 1: #include "includes.h"
1.4 ! markus 2: RCSID("$Id: nchan.c,v 1.3 1999/10/17 16:56:09 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:
77: /* X11: if we receive IEOF for X11, then we have to FORCE sending of IEOF,
78: * this is from ssh-1.2.27 debugging output.
79: */
80: if(c->x11){
81: debug("channel %d: OUTPUT_OPEN -> OUTPUT_CLOSED/INPUT_WAIT_OCLOSED [X11 FIX]", c->self);
82: chan_send_ieof(c);
83: c->istate=CHAN_INPUT_WAIT_OCLOSE;
84: chan_send_oclose(c);
85: c->ostate=CHAN_OUTPUT_CLOSED;
86: chan_delele_if_full_closed(c);
87: return;
88: }
89: switch(c->ostate){
90: case CHAN_OUTPUT_OPEN:
91: debug("channel %d: OUTPUT_OPEN -> OUTPUT_WAIT_DRAIN [rvcd IEOF]", c->self);
92: c->ostate=CHAN_OUTPUT_WAIT_DRAIN;
93: break;
94: case CHAN_OUTPUT_WAIT_IEOF:
95: debug("channel %d: OUTPUT_WAIT_IEOF -> OUTPUT_CLOSED [rvcd IEOF]", c->self);
96: c->ostate=CHAN_OUTPUT_CLOSED;
97: chan_delele_if_full_closed(c);
98: break;
99: default:
100: debug("protocol error: chan_rcvd_ieof %d for ostate %d", c->self,c->ostate);
101: break;
102: }
103: }
104: void
105: chan_write_failed(Channel *c){
106: switch(c->ostate){
107: case CHAN_OUTPUT_OPEN:
108: debug("channel %d: OUTPUT_OPEN -> OUTPUT_WAIT_IEOF [write failed]", c->self);
109: chan_send_oclose(c);
110: c->ostate=CHAN_OUTPUT_WAIT_IEOF;
111: break;
112: case CHAN_OUTPUT_WAIT_DRAIN:
113: debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [write failed]", c->self);
114: chan_send_oclose(c);
115: c->ostate=CHAN_OUTPUT_CLOSED;
116: chan_delele_if_full_closed(c);
117: break;
118: default:
119: debug("internal error: chan_write_failed %d for ostate %d",c->self,c->ostate);
120: break;
121: }
122: }
123: void
124: chan_obuf_empty(Channel *c){
125: if(buffer_len(&c->output)){
126: debug("internal error: chan_obuf_empty %d for non empty buffer",c->self);
127: return;
128: }
129: switch(c->ostate){
130: case CHAN_OUTPUT_WAIT_DRAIN:
131: debug("channel %d: OUTPUT_WAIT_DRAIN -> OUTPUT_CLOSED [obuf empty, send OCLOSE]", c->self);
132: chan_send_oclose(c);
133: c->ostate=CHAN_OUTPUT_CLOSED;
134: chan_delele_if_full_closed(c);
135: break;
136: default:
137: debug("internal error: chan_obuf_empty %d for ostate %d",c->self,c->ostate);
138: break;
139: }
140: }
141: /*
142: * ACTIONS: should never update c->istate or c->ostate
143: */
144: static void
1.1 markus 145: chan_send_ieof(Channel *c){
1.3 markus 146: switch(c->istate){
147: case CHAN_INPUT_OPEN:
148: case CHAN_INPUT_WAIT_DRAIN:
149: packet_start(SSH_MSG_CHANNEL_INPUT_EOF);
150: packet_put_int(c->remote_id);
151: packet_send();
152: break;
153: default:
154: debug("internal error: channel %d: cannot send IEOF for istate %d",c->self,c->istate);
155: break;
1.1 markus 156: }
157: }
1.3 markus 158: static void
1.1 markus 159: chan_send_oclose(Channel *c){
1.3 markus 160: switch(c->ostate){
161: case CHAN_OUTPUT_OPEN:
162: case CHAN_OUTPUT_WAIT_DRAIN:
163: chan_shutdown_write(c);
164: buffer_consume(&c->output, buffer_len(&c->output));
165: packet_start(SSH_MSG_CHANNEL_OUTPUT_CLOSE);
166: packet_put_int(c->remote_id);
167: packet_send();
168: break;
169: default:
1.4 ! markus 170: debug("internal error: channel %d: cannot send OCLOSE for ostate %d",c->self,c->istate);
1.3 markus 171: break;
1.1 markus 172: }
173: }
1.3 markus 174: /* helper */
175: static void
1.1 markus 176: chan_shutdown_write(Channel *c){
1.3 markus 177: debug("channel %d: shutdown_write", c->self);
1.1 markus 178: if(shutdown(c->sock, SHUT_WR)<0)
1.4 ! markus 179: error("chan_shutdown_write failed for #%d/fd%d: %.100s",
1.3 markus 180: c->self, c->sock, strerror(errno));
1.1 markus 181: }
1.3 markus 182: static void
1.1 markus 183: chan_shutdown_read(Channel *c){
1.3 markus 184: debug("channel %d: shutdown_read", c->self);
1.1 markus 185: if(shutdown(c->sock, SHUT_RD)<0)
1.4 ! markus 186: error("chan_shutdown_read failed for #%d/fd%d: %.100s",
1.3 markus 187: c->self, c->sock, strerror(errno));
1.1 markus 188: }
1.3 markus 189: static void
190: chan_delele_if_full_closed(Channel *c){
191: if(c->istate==CHAN_INPUT_CLOSED && c->ostate==CHAN_OUTPUT_CLOSED){
192: debug("channel %d: closing", c->self);
1.1 markus 193: channel_free(c->self);
194: }
1.3 markus 195: }
196: void
197: chan_init_iostates(Channel *c){
198: c->ostate=CHAN_OUTPUT_OPEN;
199: c->istate=CHAN_INPUT_OPEN;
1.1 markus 200: }