[BACK]Return to nchan.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / ssh

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: }