Annotation of src/usr.bin/ssh/nchan.c, Revision 1.3
1.1 markus 1: #include "includes.h"
1.3 ! markus 2: RCSID("$Id: nchan.c,v 1.2 1999/10/16 22:29:01 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: /*
! 18: * EVENTS: update channel input/ouput states
! 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:
! 26: debug("channel %d: INPUT_WAIT_CLOSE -> INPUT_CLOSED [rcvd OCLOSE]", c->self);
! 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:
! 64: debug("channel %d: INPUT_WAIT_DRAIN -> INPUT_WAIT_OCLOSE [inbuf empty, send OCLOSE]", c->self);
! 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:
! 170: debug("internal error: channel %d: cannot send IEOF for istate %d",c->self,c->istate);
! 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.3 ! markus 179: error("chan_shutdown_write failed for %d/%d %.100s",
! 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.3 ! markus 186: error("chan_shutdown_read failed for %d/%d %.100s",
! 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: }