/* * the same for SSH2 */ static void chan_rcvd_close2(Channel *c) { debug("channel %d: rcvd close", c->self); if (c->flags & CHAN_CLOSE_RCVD) error("channel %d: protocol error: close rcvd twice", c->self); c->flags |= CHAN_CLOSE_RCVD; if (c->type == SSH_CHANNEL_LARVAL) { /* tear down larval channels immediately */ chan_set_ostate(c, CHAN_OUTPUT_CLOSED); chan_set_istate(c, CHAN_INPUT_CLOSED); return; } switch (c->ostate) { case CHAN_OUTPUT_OPEN: /* * wait until a data from the channel is consumed if a CLOSE * is received */ chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); break; } switch (c->istate) { case CHAN_INPUT_OPEN: chan_shutdown_read(c); chan_set_istate(c, CHAN_INPUT_CLOSED); break; case CHAN_INPUT_WAIT_DRAIN: chan_send_eof2(c); chan_set_istate(c, CHAN_INPUT_CLOSED); break; } }
void chan_rcvd_eow(Channel *c) { debug2("channel %d: rcvd eow", c->self); switch (c->istate) { case CHAN_INPUT_OPEN: chan_shutdown_read(c); chan_set_istate(c, CHAN_INPUT_CLOSED); break; } }
void chan_read_failed(Channel *c) { debug2("channel %d: read failed", c->self); switch (c->istate) { case CHAN_INPUT_OPEN: chan_shutdown_read(c); chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN); break; default: error("channel %d: chan_read_failed for istate %d", c->self, c->istate); break; } }
static void chan_rcvd_oclose1(Channel *c) { debug2("channel %d: rcvd oclose", c->self); /* * FIXME. This function forces stopping all socket threads * at next select. This workaround nivelate problem with * infinite hangs up in below scenario: * * a) read select start. * b) write select start. * c) read select ends: SSH2_MSG_CHANNEL_CLOSE received. * d) close input channel. * e) now write select may never ends. */ #ifdef WIN32_FIXME StopSocketThreads(); #endif switch (c->istate) { case CHAN_INPUT_WAIT_OCLOSE: chan_set_istate(c, CHAN_INPUT_CLOSED); break; case CHAN_INPUT_OPEN: chan_shutdown_read(c); chan_send_ieof1(c); chan_set_istate(c, CHAN_INPUT_CLOSED); break; case CHAN_INPUT_WAIT_DRAIN: /* both local read_failed and remote write_failed */ chan_send_ieof1(c); chan_set_istate(c, CHAN_INPUT_CLOSED); break; default: error("channel %d: protocol error: rcvd_oclose for istate %d", c->self, c->istate); return; } }
static void chan_rcvd_oclose1(Channel *c) { debug2("channel %d: rcvd oclose", c->self); switch (c->istate) { case CHAN_INPUT_WAIT_OCLOSE: chan_set_istate(c, CHAN_INPUT_CLOSED); break; case CHAN_INPUT_OPEN: chan_shutdown_read(c); chan_send_ieof1(c); chan_set_istate(c, CHAN_INPUT_CLOSED); break; case CHAN_INPUT_WAIT_DRAIN: /* both local read_failed and remote write_failed */ chan_send_ieof1(c); chan_set_istate(c, CHAN_INPUT_CLOSED); break; default: error("channel %d: protocol error: rcvd_oclose for istate %d", c->self, c->istate); return; } }