Emit channel_write_wontblock when remote window becomes non-zero.

Signed-off-by: Tom Deseyn <tom.deseyn@gmail.com>
Reviewed-by: Jakub Jelen <jjelen@redhat.com>
This commit is contained in:
Tom Deseyn
2022-08-13 16:02:44 +02:00
committed by Jakub Jelen
parent 49490ac06d
commit 6f029598c7
2 changed files with 17 additions and 26 deletions

View File

@@ -512,6 +512,8 @@ SSH_PACKET_CALLBACK(channel_rcv_change_window) {
ssh_channel channel;
uint32_t bytes;
int rc;
bool was_empty;
(void)user;
(void)type;
@@ -535,8 +537,21 @@ SSH_PACKET_CALLBACK(channel_rcv_change_window) {
channel->remote_channel,
channel->remote_window);
was_empty = channel->remote_window == 0;
channel->remote_window += bytes;
/* Writing to the channel is non-blocking until the receive window is empty.
When the receive window becomes non-zero again, call channel_write_wontblock_function. */
if (was_empty && bytes > 0) {
ssh_callbacks_execute_list(channel->callbacks,
ssh_channel_callbacks,
channel_write_wontblock_function,
session,
channel,
channel->remote_window);
}
return SSH_PACKET_USED;
}
@@ -1510,7 +1525,7 @@ static int channel_write_common(ssh_channel channel,
"Remote window is %" PRIu32 " bytes. going to write %" PRIu32 " bytes",
channel->remote_window,
len);
/* What happens when the channel window is zero? */
/* When the window is zero, wait for it to grow */
if(channel->remote_window == 0) {
/* nothing can be written */
SSH_LOG(SSH_LOG_DEBUG,
@@ -1524,6 +1539,7 @@ static int channel_write_common(ssh_channel channel,
goto out;
continue;
}
/* When the window is non-zero, accept data up to the window size */
effectivelen = MIN(len, channel->remote_window);
} else {
effectivelen = len;

View File

@@ -1394,34 +1394,9 @@ error:
return processed;
}
static void ssh_packet_socket_controlflow_callback(int code, void *userdata)
{
ssh_session session = userdata;
struct ssh_iterator *it;
ssh_channel channel;
if (code == SSH_SOCKET_FLOW_WRITEWONTBLOCK) {
SSH_LOG(SSH_LOG_TRACE, "sending channel_write_wontblock callback");
/* the out pipe is empty so we can forward this to channels */
it = ssh_list_get_iterator(session->channels);
while (it != NULL) {
channel = ssh_iterator_value(ssh_channel, it);
ssh_callbacks_execute_list(channel->callbacks,
ssh_channel_callbacks,
channel_write_wontblock_function,
session,
channel,
channel->remote_window);
it = it->next;
}
}
}
void ssh_packet_register_socket_callback(ssh_session session, ssh_socket s){
session->socket_callbacks.data=ssh_packet_socket_callback;
session->socket_callbacks.connected=NULL;
session->socket_callbacks.controlflow = ssh_packet_socket_controlflow_callback;
session->socket_callbacks.userdata=session;
ssh_socket_set_callbacks(s,&session->socket_callbacks);
}