From 28b4110593de37e337068079c9ba074a921266a8 Mon Sep 17 00:00:00 2001 From: Tom Deseyn Date: Sat, 13 Aug 2022 16:02:44 +0200 Subject: [PATCH] Emit channel_write_wontblock when remote window becomes non-zero. Signed-off-by: Tom Deseyn --- src/channels.c | 18 +++++++++++++++++- src/packet.c | 25 ------------------------- 2 files changed, 17 insertions(+), 26 deletions(-) diff --git a/src/channels.c b/src/channels.c index 7405ea6e4..83b89c96e 100644 --- a/src/channels.c +++ b/src/channels.c @@ -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; diff --git a/src/packet.c b/src/packet.c index 8233d1b7a..eae8563d7 100644 --- a/src/packet.c +++ b/src/packet.c @@ -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); } -- GitLab