version 1.230, 2005/12/28 22:46:06 |
version 1.231, 2005/12/30 15:56:36 |
|
|
|
|
/* -- channel core */ |
/* -- channel core */ |
|
|
#define CHAN_RBUF 16*1024 |
|
|
|
/* |
/* |
* Pointer to an array containing all allocated channels. The array is |
* Pointer to an array containing all allocated channels. The array is |
* dynamically extended as needed. |
* dynamically extended as needed. |
|
|
c->confirm = NULL; |
c->confirm = NULL; |
c->confirm_ctx = NULL; |
c->confirm_ctx = NULL; |
c->input_filter = NULL; |
c->input_filter = NULL; |
|
c->output_filter = NULL; |
debug("channel %d: new [%s]", found, remote_name); |
debug("channel %d: new [%s]", found, remote_name); |
return c; |
return c; |
} |
} |
|
|
c->detach_close = 0; |
c->detach_close = 0; |
} |
} |
void |
void |
channel_register_filter(int id, channel_filter_fn *fn) |
channel_register_filter(int id, channel_infilter_fn *ifn, |
|
channel_outfilter_fn *ofn) |
{ |
{ |
Channel *c = channel_lookup(id); |
Channel *c = channel_lookup(id); |
|
|
|
|
logit("channel_register_filter: %d: bad id", id); |
logit("channel_register_filter: %d: bad id", id); |
return; |
return; |
} |
} |
c->input_filter = fn; |
c->input_filter = ifn; |
|
c->output_filter = ofn; |
} |
} |
|
|
void |
void |
|
|
channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset) |
channel_handle_wfd(Channel *c, fd_set * readset, fd_set * writeset) |
{ |
{ |
struct termios tio; |
struct termios tio; |
u_char *data; |
u_char *data = NULL, *buf; |
u_int dlen; |
u_int dlen; |
int len; |
int len; |
|
|
|
|
if (c->wfd != -1 && |
if (c->wfd != -1 && |
FD_ISSET(c->wfd, writeset) && |
FD_ISSET(c->wfd, writeset) && |
buffer_len(&c->output) > 0) { |
buffer_len(&c->output) > 0) { |
|
if (c->output_filter != NULL) { |
|
if ((buf = c->output_filter(c, &data, &dlen)) == NULL) { |
|
debug2("channel %d: filter stops", c->self); |
|
chan_read_failed(c); |
|
} |
|
} else if (c->datagram) { |
|
buf = data = buffer_get_string(&c->output, &dlen); |
|
} else { |
|
buf = data = buffer_ptr(&c->output); |
|
dlen = buffer_len(&c->output); |
|
} |
|
|
if (c->datagram) { |
if (c->datagram) { |
data = buffer_get_string(&c->output, &dlen); |
|
/* ignore truncated writes, datagrams might get lost */ |
/* ignore truncated writes, datagrams might get lost */ |
c->local_consumed += dlen + 4; |
c->local_consumed += dlen + 4; |
len = write(c->wfd, data, dlen); |
len = write(c->wfd, buf, dlen); |
xfree(data); |
xfree(data); |
if (len < 0 && (errno == EINTR || errno == EAGAIN)) |
if (len < 0 && (errno == EINTR || errno == EAGAIN)) |
return 1; |
return 1; |
|
|
} |
} |
return 1; |
return 1; |
} |
} |
data = buffer_ptr(&c->output); |
|
dlen = buffer_len(&c->output); |
len = write(c->wfd, buf, dlen); |
len = write(c->wfd, data, dlen); |
|
if (len < 0 && (errno == EINTR || errno == EAGAIN)) |
if (len < 0 && (errno == EINTR || errno == EAGAIN)) |
return 1; |
return 1; |
if (len <= 0) { |
if (len <= 0) { |
|
|
} |
} |
return -1; |
return -1; |
} |
} |
if (compat20 && c->isatty && dlen >= 1 && data[0] != '\r') { |
if (compat20 && c->isatty && dlen >= 1 && buf[0] != '\r') { |
if (tcgetattr(c->wfd, &tio) == 0 && |
if (tcgetattr(c->wfd, &tio) == 0 && |
!(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { |
!(tio.c_lflag & ECHO) && (tio.c_lflag & ICANON)) { |
/* |
/* |
* Simulate echo to reduce the impact of |
* Simulate echo to reduce the impact of |
* traffic analysis. We need to match the |
* traffic analysis. We need to match the |
* size of a SSH2_MSG_CHANNEL_DATA message |
* size of a SSH2_MSG_CHANNEL_DATA message |
* (4 byte channel id + data) |
* (4 byte channel id + buf) |
*/ |
*/ |
packet_send_ignore(4 + len); |
packet_send_ignore(4 + len); |
packet_send(); |
packet_send(); |