Annotation of src/usr.bin/ssh/nchan.c, Revision 1.6
1.1 markus 1: #include "includes.h"
1.6 ! markus 2: RCSID("$Id: nchan.c,v 1.5 1999/10/25 21:04:28 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.6 ! markus 18: * EVENTS update channel input/output states execute ACTIONS
1.3 markus 19: */
1.6 ! markus 20:
1.3 markus 21: /* events concerning the INPUT from socket for channel (istate) */
1.1 markus 22: void
1.6 ! markus 23: chan_rcvd_oclose(Channel *c)
! 24: {
! 25: switch (c->istate) {
1.3 markus 26: case CHAN_INPUT_WAIT_OCLOSE:
1.4 markus 27: debug("channel %d: INPUT_WAIT_OCLOSE -> INPUT_CLOSED [rcvd OCLOSE]", c->self);
1.6 ! markus 28: c->istate = CHAN_INPUT_CLOSED;
1.3 markus 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);
1.6 ! markus 35: c->istate = CHAN_INPUT_CLOSED;
1.3 markus 36: chan_delele_if_full_closed(c);
37: break;
38: default:
1.6 ! markus 39: debug("protocol error: chan_rcvd_oclose %d for istate %d", c->self, c->istate);
1.3 markus 40: break;
41: }
1.1 markus 42: }
43: void
1.6 ! markus 44: chan_read_failed(Channel *c)
! 45: {
! 46: switch (c->istate) {
1.3 markus 47: case CHAN_INPUT_OPEN:
48: debug("channel %d: INPUT_OPEN -> INPUT_WAIT_DRAIN [read failed]", c->self);
49: chan_shutdown_read(c);
1.6 ! markus 50: c->istate = CHAN_INPUT_WAIT_DRAIN;
1.3 markus 51: break;
52: default:
53: debug("internal error: we do not read, but chan_read_failed %d for istate %d",
1.6 ! markus 54: c->self, c->istate);
1.3 markus 55: break;
1.1 markus 56: }
57: }
58: void
1.6 ! markus 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);
1.3 markus 63: return;
64: }
1.6 ! markus 65: switch (c->istate) {
1.3 markus 66: case CHAN_INPUT_WAIT_DRAIN:
1.4 markus 67: debug("channel %d: INPUT_WAIT_DRAIN -> INPUT_WAIT_OCLOSE [inbuf empty, send IEOF]", c->self);
1.3 markus 68: chan_send_ieof(c);
1.6 ! markus 69: c->istate = CHAN_INPUT_WAIT_OCLOSE;
1.3 markus 70: break;
71: default:
1.6 ! markus 72: debug("internal error: chan_ibuf_empty %d for istate %d", c->self, c->istate);
1.3 markus 73: break;
1.1 markus 74: }
75: }
1.6 ! markus 76:
1.3 markus 77: /* events concerning the OUTPUT from channel for socket (ostate) */
1.1 markus 78: void
1.6 ! markus 79: chan_rcvd_ieof(Channel *c)
! 80: {
! 81: switch (c->ostate) {
1.3 markus 82: case CHAN_OUTPUT_OPEN:
83: debug("channel %d: OUTPUT_OPEN -> OUTPUT_WAIT_DRAIN [rvcd IEOF]", c->self);
1.6 ! markus 84: c->ostate = CHAN_OUTPUT_WAIT_DRAIN;
1.3 markus 85: break;
86: case CHAN_OUTPUT_WAIT_IEOF:
87: debug("channel %d: OUTPUT_WAIT_IEOF -> OUTPUT_CLOSED [rvcd IEOF]", c->self);
1.6 ! markus 88: c->ostate = CHAN_OUTPUT_CLOSED;
1.3 markus 89: chan_delele_if_full_closed(c);
90: break;
91: default:
1.6 ! markus 92: debug("protocol error: chan_rcvd_ieof %d for ostate %d", c->self, c->ostate);
1.3 markus 93: break;
94: }
95: }
96: void
1.6 ! markus 97: chan_write_failed(Channel *c)
! 98: {
! 99: switch (c->ostate) {
1.3 markus 100: case CHAN_OUTPUT_OPEN:
101: debug("channel %d: OUTPUT_OPEN -> OUTPUT_WAIT_IEOF [write failed]", c->self);
102: chan_send_oclose(c);
1.6 ! markus 103: c->ostate = CHAN_OUTPUT_WAIT_IEOF;
1.3 markus 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);
1.6 ! markus 108: c->ostate = CHAN_OUTPUT_CLOSED;
1.3 markus 109: chan_delele_if_full_closed(c);
110: break;
111: default:
1.6 ! markus 112: debug("internal error: chan_write_failed %d for ostate %d", c->self, c->ostate);
1.3 markus 113: break;
114: }
115: }
116: void
1.6 ! markus 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);
1.3 markus 121: return;
122: }
1.6 ! markus 123: switch (c->ostate) {
1.3 markus 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);
1.6 ! markus 127: c->ostate = CHAN_OUTPUT_CLOSED;
1.3 markus 128: chan_delele_if_full_closed(c);
129: break;
130: default:
1.6 ! markus 131: debug("internal error: chan_obuf_empty %d for ostate %d", c->self, c->ostate);
1.3 markus 132: break;
133: }
134: }
1.6 ! markus 135:
1.3 markus 136: /*
1.6 ! markus 137: * ACTIONS: should never update the channel states: c->istate or c->ostate
1.3 markus 138: */
139: static void
1.6 ! markus 140: chan_send_ieof(Channel *c)
! 141: {
! 142: switch (c->istate) {
1.3 markus 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:
1.6 ! markus 150: debug("internal error: channel %d: cannot send IEOF for istate %d", c->self, c->istate);
1.3 markus 151: break;
1.1 markus 152: }
153: }
1.3 markus 154: static void
1.6 ! markus 155: chan_send_oclose(Channel *c)
! 156: {
! 157: switch (c->ostate) {
1.3 markus 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:
1.6 ! markus 167: debug("internal error: channel %d: cannot send OCLOSE for ostate %d", c->self, c->istate);
1.3 markus 168: break;
1.1 markus 169: }
170: }
1.6 ! markus 171:
1.3 markus 172: /* helper */
173: static void
1.6 ! markus 174: chan_shutdown_write(Channel *c)
! 175: {
1.3 markus 176: debug("channel %d: shutdown_write", c->self);
1.6 ! markus 177: if (shutdown(c->sock, SHUT_WR) < 0)
1.4 markus 178: error("chan_shutdown_write failed for #%d/fd%d: %.100s",
1.6 ! markus 179: c->self, c->sock, strerror(errno));
1.1 markus 180: }
1.3 markus 181: static void
1.6 ! markus 182: chan_shutdown_read(Channel *c)
! 183: {
1.3 markus 184: debug("channel %d: shutdown_read", c->self);
1.6 ! markus 185: if (shutdown(c->sock, SHUT_RD) < 0)
1.4 markus 186: error("chan_shutdown_read failed for #%d/fd%d: %.100s",
1.6 ! markus 187: c->self, c->sock, strerror(errno));
1.1 markus 188: }
1.3 markus 189: static void
1.6 ! markus 190: chan_delele_if_full_closed(Channel *c)
! 191: {
! 192: if (c->istate == CHAN_INPUT_CLOSED && c->ostate == CHAN_OUTPUT_CLOSED) {
1.3 markus 193: debug("channel %d: closing", c->self);
1.1 markus 194: channel_free(c->self);
195: }
1.3 markus 196: }
197: void
1.6 ! markus 198: chan_init_iostates(Channel *c)
! 199: {
! 200: c->ostate = CHAN_OUTPUT_OPEN;
! 201: c->istate = CHAN_INPUT_OPEN;
1.1 markus 202: }