version 1.432, 2023/07/04 03:59:21 |
version 1.433, 2023/09/04 00:01:46 |
|
|
|
|
/* |
/* |
* Enqueue data for channels with open or draining c->input. |
* Enqueue data for channels with open or draining c->input. |
|
* Returns non-zero if a packet was enqueued. |
*/ |
*/ |
static void |
static int |
channel_output_poll_input_open(struct ssh *ssh, Channel *c) |
channel_output_poll_input_open(struct ssh *ssh, Channel *c) |
{ |
{ |
size_t len, plen; |
size_t len, plen; |
|
|
else |
else |
chan_ibuf_empty(ssh, c); |
chan_ibuf_empty(ssh, c); |
} |
} |
return; |
return 0; |
} |
} |
|
|
if (!c->have_remote_id) |
if (!c->have_remote_id) |
|
|
*/ |
*/ |
if (plen > c->remote_window || plen > c->remote_maxpacket) { |
if (plen > c->remote_window || plen > c->remote_maxpacket) { |
debug("channel %d: datagram too big", c->self); |
debug("channel %d: datagram too big", c->self); |
return; |
return 0; |
} |
} |
/* Enqueue it */ |
/* Enqueue it */ |
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 || |
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 || |
|
|
(r = sshpkt_send(ssh)) != 0) |
(r = sshpkt_send(ssh)) != 0) |
fatal_fr(r, "channel %i: send datagram", c->self); |
fatal_fr(r, "channel %i: send datagram", c->self); |
c->remote_window -= plen; |
c->remote_window -= plen; |
return; |
return 1; |
} |
} |
|
|
/* Enqueue packet for buffered data. */ |
/* Enqueue packet for buffered data. */ |
|
|
if (len > c->remote_maxpacket) |
if (len > c->remote_maxpacket) |
len = c->remote_maxpacket; |
len = c->remote_maxpacket; |
if (len == 0) |
if (len == 0) |
return; |
return 0; |
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 || |
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_DATA)) != 0 || |
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
(r = sshpkt_put_u32(ssh, c->remote_id)) != 0 || |
(r = sshpkt_put_string(ssh, sshbuf_ptr(c->input), len)) != 0 || |
(r = sshpkt_put_string(ssh, sshbuf_ptr(c->input), len)) != 0 || |
|
|
if ((r = sshbuf_consume(c->input, len)) != 0) |
if ((r = sshbuf_consume(c->input, len)) != 0) |
fatal_fr(r, "channel %i: consume", c->self); |
fatal_fr(r, "channel %i: consume", c->self); |
c->remote_window -= len; |
c->remote_window -= len; |
|
return 1; |
} |
} |
|
|
/* |
/* |
* Enqueue data for channels with open c->extended in read mode. |
* Enqueue data for channels with open c->extended in read mode. |
|
* Returns non-zero if a packet was enqueued. |
*/ |
*/ |
static void |
static int |
channel_output_poll_extended_read(struct ssh *ssh, Channel *c) |
channel_output_poll_extended_read(struct ssh *ssh, Channel *c) |
{ |
{ |
size_t len; |
size_t len; |
int r; |
int r; |
|
|
if ((len = sshbuf_len(c->extended)) == 0) |
if ((len = sshbuf_len(c->extended)) == 0) |
return; |
return 0; |
|
|
debug2("channel %d: rwin %u elen %zu euse %d", c->self, |
debug2("channel %d: rwin %u elen %zu euse %d", c->self, |
c->remote_window, sshbuf_len(c->extended), c->extended_usage); |
c->remote_window, sshbuf_len(c->extended), c->extended_usage); |
|
|
if (len > c->remote_maxpacket) |
if (len > c->remote_maxpacket) |
len = c->remote_maxpacket; |
len = c->remote_maxpacket; |
if (len == 0) |
if (len == 0) |
return; |
return 0; |
if (!c->have_remote_id) |
if (!c->have_remote_id) |
fatal_f("channel %d: no remote id", c->self); |
fatal_f("channel %d: no remote id", c->self); |
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA)) != 0 || |
if ((r = sshpkt_start(ssh, SSH2_MSG_CHANNEL_EXTENDED_DATA)) != 0 || |
|
|
fatal_fr(r, "channel %i: consume", c->self); |
fatal_fr(r, "channel %i: consume", c->self); |
c->remote_window -= len; |
c->remote_window -= len; |
debug2("channel %d: sent ext data %zu", c->self, len); |
debug2("channel %d: sent ext data %zu", c->self, len); |
|
return 1; |
} |
} |
|
|
/* If there is data to send to the connection, enqueue some of it now. */ |
/* |
void |
* If there is data to send to the connection, enqueue some of it now. |
|
* Returns non-zero if data was enqueued. |
|
*/ |
|
int |
channel_output_poll(struct ssh *ssh) |
channel_output_poll(struct ssh *ssh) |
{ |
{ |
struct ssh_channels *sc = ssh->chanctxt; |
struct ssh_channels *sc = ssh->chanctxt; |
Channel *c; |
Channel *c; |
u_int i; |
u_int i; |
|
int ret = 0; |
|
|
for (i = 0; i < sc->channels_alloc; i++) { |
for (i = 0; i < sc->channels_alloc; i++) { |
c = sc->channels[i]; |
c = sc->channels[i]; |
|
|
/* Get the amount of buffered data for this channel. */ |
/* Get the amount of buffered data for this channel. */ |
if (c->istate == CHAN_INPUT_OPEN || |
if (c->istate == CHAN_INPUT_OPEN || |
c->istate == CHAN_INPUT_WAIT_DRAIN) |
c->istate == CHAN_INPUT_WAIT_DRAIN) |
channel_output_poll_input_open(ssh, c); |
ret |= channel_output_poll_input_open(ssh, c); |
/* Send extended data, i.e. stderr */ |
/* Send extended data, i.e. stderr */ |
if (!(c->flags & CHAN_EOF_SENT) && |
if (!(c->flags & CHAN_EOF_SENT) && |
c->extended_usage == CHAN_EXTENDED_READ) |
c->extended_usage == CHAN_EXTENDED_READ) |
channel_output_poll_extended_read(ssh, c); |
ret |= channel_output_poll_extended_read(ssh, c); |
} |
} |
|
return ret; |
} |
} |
|
|
/* -- mux proxy support */ |
/* -- mux proxy support */ |