version 1.36, 2002/01/10 12:47:59 |
version 1.37, 2002/01/13 21:31:20 |
|
|
static void chan_shutdown_write(Channel *); |
static void chan_shutdown_write(Channel *); |
static void chan_shutdown_read(Channel *); |
static void chan_shutdown_read(Channel *); |
|
|
|
static char *ostates[] = { "open", "drain", "wait_ieof", "closed" }; |
|
static char *istates[] = { "open", "drain", "wait_oclose", "closed" }; |
|
|
|
static void |
|
chan_set_istate(Channel *c, u_int next) |
|
{ |
|
if (c->istate > CHAN_INPUT_CLOSED || next > CHAN_INPUT_CLOSED) |
|
fatal("chan_set_istate: bad state %d -> %d", c->istate, next); |
|
debug("channel %d: input %s -> %s", c->self, istates[c->istate], |
|
istates[next]); |
|
c->istate = next; |
|
} |
|
static void |
|
chan_set_ostate(Channel *c, u_int next) |
|
{ |
|
if (c->ostate > CHAN_OUTPUT_CLOSED || next > CHAN_OUTPUT_CLOSED) |
|
fatal("chan_set_ostate: bad state %d -> %d", c->ostate, next); |
|
debug("channel %d: output %s -> %s", c->self, ostates[c->ostate], |
|
ostates[next]); |
|
c->ostate = next; |
|
} |
|
|
/* |
/* |
* SSH1 specific implementation of event functions |
* SSH1 specific implementation of event functions |
*/ |
*/ |
|
|
debug("channel %d: rcvd oclose", c->self); |
debug("channel %d: rcvd oclose", c->self); |
switch (c->istate) { |
switch (c->istate) { |
case CHAN_INPUT_WAIT_OCLOSE: |
case CHAN_INPUT_WAIT_OCLOSE: |
debug("channel %d: input wait_oclose -> closed", c->self); |
chan_set_istate(c, CHAN_INPUT_CLOSED); |
c->istate = CHAN_INPUT_CLOSED; |
|
break; |
break; |
case CHAN_INPUT_OPEN: |
case CHAN_INPUT_OPEN: |
debug("channel %d: input open -> closed", c->self); |
|
chan_shutdown_read(c); |
chan_shutdown_read(c); |
chan_send_ieof1(c); |
chan_send_ieof1(c); |
c->istate = CHAN_INPUT_CLOSED; |
chan_set_istate(c, CHAN_INPUT_CLOSED); |
break; |
break; |
case CHAN_INPUT_WAIT_DRAIN: |
case CHAN_INPUT_WAIT_DRAIN: |
/* both local read_failed and remote write_failed */ |
/* both local read_failed and remote write_failed */ |
log("channel %d: input drain -> closed", c->self); |
|
chan_send_ieof1(c); |
chan_send_ieof1(c); |
c->istate = CHAN_INPUT_CLOSED; |
chan_set_istate(c, CHAN_INPUT_CLOSED); |
break; |
break; |
default: |
default: |
error("channel %d: protocol error: rcvd_oclose for istate %d", |
error("channel %d: protocol error: rcvd_oclose for istate %d", |
|
|
debug("channel %d: read failed", c->self); |
debug("channel %d: read failed", c->self); |
switch (c->istate) { |
switch (c->istate) { |
case CHAN_INPUT_OPEN: |
case CHAN_INPUT_OPEN: |
debug("channel %d: input open -> drain", c->self); |
|
chan_shutdown_read(c); |
chan_shutdown_read(c); |
c->istate = CHAN_INPUT_WAIT_DRAIN; |
chan_set_istate(c, CHAN_INPUT_WAIT_DRAIN); |
break; |
break; |
default: |
default: |
error("channel %d: chan_read_failed for istate %d", |
error("channel %d: chan_read_failed for istate %d", |
|
|
} |
} |
switch (c->istate) { |
switch (c->istate) { |
case CHAN_INPUT_WAIT_DRAIN: |
case CHAN_INPUT_WAIT_DRAIN: |
debug("channel %d: input drain -> wait_oclose", c->self); |
|
chan_send_ieof1(c); |
chan_send_ieof1(c); |
c->istate = CHAN_INPUT_WAIT_OCLOSE; |
chan_set_istate(c, CHAN_INPUT_WAIT_OCLOSE); |
break; |
break; |
default: |
default: |
error("channel %d: chan_ibuf_empty for istate %d", |
error("channel %d: chan_ibuf_empty for istate %d", |
|
|
debug("channel %d: rcvd ieof", c->self); |
debug("channel %d: rcvd ieof", c->self); |
switch (c->ostate) { |
switch (c->ostate) { |
case CHAN_OUTPUT_OPEN: |
case CHAN_OUTPUT_OPEN: |
debug("channel %d: output open -> drain", c->self); |
chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); |
c->ostate = CHAN_OUTPUT_WAIT_DRAIN; |
|
break; |
break; |
case CHAN_OUTPUT_WAIT_IEOF: |
case CHAN_OUTPUT_WAIT_IEOF: |
debug("channel %d: output wait_ieof -> closed", c->self); |
chan_set_ostate(c, CHAN_OUTPUT_CLOSED); |
c->ostate = CHAN_OUTPUT_CLOSED; |
|
break; |
break; |
default: |
default: |
error("channel %d: protocol error: rcvd_ieof for ostate %d", |
error("channel %d: protocol error: rcvd_ieof for ostate %d", |
|
|
debug("channel %d: write failed", c->self); |
debug("channel %d: write failed", c->self); |
switch (c->ostate) { |
switch (c->ostate) { |
case CHAN_OUTPUT_OPEN: |
case CHAN_OUTPUT_OPEN: |
debug("channel %d: output open -> wait_ieof", c->self); |
|
chan_send_oclose1(c); |
chan_send_oclose1(c); |
c->ostate = CHAN_OUTPUT_WAIT_IEOF; |
chan_set_ostate(c, CHAN_OUTPUT_WAIT_IEOF); |
break; |
break; |
case CHAN_OUTPUT_WAIT_DRAIN: |
case CHAN_OUTPUT_WAIT_DRAIN: |
debug("channel %d: output wait_drain -> closed", c->self); |
|
chan_send_oclose1(c); |
chan_send_oclose1(c); |
c->ostate = CHAN_OUTPUT_CLOSED; |
chan_set_ostate(c, CHAN_OUTPUT_CLOSED); |
break; |
break; |
default: |
default: |
error("channel %d: chan_write_failed for ostate %d", |
error("channel %d: chan_write_failed for ostate %d", |
|
|
} |
} |
switch (c->ostate) { |
switch (c->ostate) { |
case CHAN_OUTPUT_WAIT_DRAIN: |
case CHAN_OUTPUT_WAIT_DRAIN: |
debug("channel %d: output drain -> closed", c->self); |
|
chan_send_oclose1(c); |
chan_send_oclose1(c); |
c->ostate = CHAN_OUTPUT_CLOSED; |
chan_set_ostate(c, CHAN_OUTPUT_CLOSED); |
break; |
break; |
default: |
default: |
error("channel %d: internal error: obuf_empty for ostate %d", |
error("channel %d: internal error: obuf_empty for ostate %d", |
|
|
c->flags |= CHAN_CLOSE_RCVD; |
c->flags |= CHAN_CLOSE_RCVD; |
if (c->type == SSH_CHANNEL_LARVAL) { |
if (c->type == SSH_CHANNEL_LARVAL) { |
/* tear down larval channels immediately */ |
/* tear down larval channels immediately */ |
c->ostate = CHAN_OUTPUT_CLOSED; |
chan_set_ostate(c, CHAN_OUTPUT_CLOSED); |
c->istate = CHAN_INPUT_CLOSED; |
chan_set_istate(c, CHAN_INPUT_CLOSED); |
return; |
return; |
} |
} |
switch (c->ostate) { |
switch (c->ostate) { |
|
|
* wait until a data from the channel is consumed if a CLOSE |
* wait until a data from the channel is consumed if a CLOSE |
* is received |
* is received |
*/ |
*/ |
debug("channel %d: output open -> drain", c->self); |
chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); |
c->ostate = CHAN_OUTPUT_WAIT_DRAIN; |
|
break; |
break; |
} |
} |
switch (c->istate) { |
switch (c->istate) { |
case CHAN_INPUT_OPEN: |
case CHAN_INPUT_OPEN: |
debug("channel %d: input open -> closed", c->self); |
|
chan_shutdown_read(c); |
chan_shutdown_read(c); |
break; |
break; |
case CHAN_INPUT_WAIT_DRAIN: |
case CHAN_INPUT_WAIT_DRAIN: |
debug("channel %d: input drain -> closed", c->self); |
|
chan_send_eof2(c); |
chan_send_eof2(c); |
break; |
break; |
} |
} |
c->istate = CHAN_INPUT_CLOSED; |
chan_set_istate(c, CHAN_INPUT_CLOSED); |
} |
} |
static void |
static void |
chan_ibuf_empty2(Channel *c) |
chan_ibuf_empty2(Channel *c) |
|
|
} |
} |
switch (c->istate) { |
switch (c->istate) { |
case CHAN_INPUT_WAIT_DRAIN: |
case CHAN_INPUT_WAIT_DRAIN: |
debug("channel %d: input drain -> closed", c->self); |
|
if (!(c->flags & CHAN_CLOSE_SENT)) |
if (!(c->flags & CHAN_CLOSE_SENT)) |
chan_send_eof2(c); |
chan_send_eof2(c); |
c->istate = CHAN_INPUT_CLOSED; |
chan_set_istate(c, CHAN_INPUT_CLOSED); |
break; |
break; |
default: |
default: |
error("channel %d: chan_ibuf_empty for istate %d", |
error("channel %d: chan_ibuf_empty for istate %d", |
|
|
chan_rcvd_ieof2(Channel *c) |
chan_rcvd_ieof2(Channel *c) |
{ |
{ |
debug("channel %d: rcvd eof", c->self); |
debug("channel %d: rcvd eof", c->self); |
if (c->ostate == CHAN_OUTPUT_OPEN) { |
if (c->ostate == CHAN_OUTPUT_OPEN) |
debug("channel %d: output open -> drain", c->self); |
chan_set_ostate(c, CHAN_OUTPUT_WAIT_DRAIN); |
c->ostate = CHAN_OUTPUT_WAIT_DRAIN; |
|
} |
|
} |
} |
static void |
static void |
chan_write_failed2(Channel *c) |
chan_write_failed2(Channel *c) |
|
|
debug("channel %d: write failed", c->self); |
debug("channel %d: write failed", c->self); |
switch (c->ostate) { |
switch (c->ostate) { |
case CHAN_OUTPUT_OPEN: |
case CHAN_OUTPUT_OPEN: |
debug("channel %d: output open -> closed", c->self); |
|
chan_shutdown_write(c); /* ?? */ |
chan_shutdown_write(c); /* ?? */ |
c->ostate = CHAN_OUTPUT_CLOSED; |
chan_set_ostate(c, CHAN_OUTPUT_CLOSED); |
break; |
break; |
case CHAN_OUTPUT_WAIT_DRAIN: |
case CHAN_OUTPUT_WAIT_DRAIN: |
debug("channel %d: output drain -> closed", c->self); |
|
chan_shutdown_write(c); |
chan_shutdown_write(c); |
c->ostate = CHAN_OUTPUT_CLOSED; |
chan_set_ostate(c, CHAN_OUTPUT_CLOSED); |
break; |
break; |
default: |
default: |
error("channel %d: chan_write_failed for ostate %d", |
error("channel %d: chan_write_failed for ostate %d", |
|
|
} |
} |
switch (c->ostate) { |
switch (c->ostate) { |
case CHAN_OUTPUT_WAIT_DRAIN: |
case CHAN_OUTPUT_WAIT_DRAIN: |
debug("channel %d: output drain -> closed", c->self); |
|
chan_shutdown_write(c); |
chan_shutdown_write(c); |
c->ostate = CHAN_OUTPUT_CLOSED; |
chan_set_ostate(c, CHAN_OUTPUT_CLOSED); |
break; |
break; |
default: |
default: |
error("channel %d: chan_obuf_empty for ostate %d", |
error("channel %d: chan_obuf_empty for ostate %d", |