aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Deseyn <tom.deseyn@gmail.com>2021-01-05 16:15:24 +0100
committerAnderson Toshiyuki Sasaki <ansasaki@redhat.com>2021-01-11 20:38:24 +0100
commit44dfee778fb042d0d13a64c4d42ea0cb285ca2ae (patch)
treedd5009d33412e175902517401621453d39b8ab68 /src
parent710815674a907116c1864dd29c804039cd392616 (diff)
downloadlibssh-44dfee778fb042d0d13a64c4d42ea0cb285ca2ae.tar.gz
libssh-44dfee778fb042d0d13a64c4d42ea0cb285ca2ae.tar.xz
libssh-44dfee778fb042d0d13a64c4d42ea0cb285ca2ae.zip
channesl: Fix delayed close
If the SSH2_MSG_CHANNEL_CLOSE was previously received, change the channel state to SSH_STATE_CHANNEL_CLOSED in ssh_channel_read_timeout() after reading all data available. Fixes T31 Signed-off-by: Tom Deseyn <tom.deseyn@gmail.com> Reviewed-by: Anderson Toshiyuki Sasaki <ansasaki@redhat.com>
Diffstat (limited to 'src')
-rw-r--r--src/channels.c41
1 files changed, 28 insertions, 13 deletions
diff --git a/src/channels.c b/src/channels.c
index 6747a841..262ff64a 100644
--- a/src/channels.c
+++ b/src/channels.c
@@ -648,6 +648,23 @@ SSH_PACKET_CALLBACK(channel_rcv_eof) {
return SSH_PACKET_USED;
}
+static bool ssh_channel_has_unread_data(ssh_channel channel)
+{
+ if (channel == NULL) {
+ return false;
+ }
+
+ if ((channel->stdout_buffer &&
+ ssh_buffer_get_len(channel->stdout_buffer) > 0) ||
+ (channel->stderr_buffer &&
+ ssh_buffer_get_len(channel->stderr_buffer) > 0))
+ {
+ return true;
+ }
+
+ return false;
+}
+
SSH_PACKET_CALLBACK(channel_rcv_close) {
ssh_channel channel;
(void)user;
@@ -665,14 +682,12 @@ SSH_PACKET_CALLBACK(channel_rcv_close) {
channel->local_channel,
channel->remote_channel);
- if ((channel->stdout_buffer &&
- ssh_buffer_get_len(channel->stdout_buffer) > 0) ||
- (channel->stderr_buffer &&
- ssh_buffer_get_len(channel->stderr_buffer) > 0)) {
- channel->delayed_close = 1;
- } else {
+ if (!ssh_channel_has_unread_data(channel)) {
channel->state = SSH_CHANNEL_STATE_CLOSED;
- }
+ } else {
+ channel->delayed_close = 1;
+ }
+
if (channel->remote_eof == 0) {
SSH_LOG(SSH_LOG_PACKET,
"Remote host not polite enough to send an eof before close");
@@ -1604,11 +1619,8 @@ int ssh_channel_is_eof(ssh_channel channel) {
if(channel == NULL) {
return SSH_ERROR;
}
- if ((channel->stdout_buffer &&
- ssh_buffer_get_len(channel->stdout_buffer) > 0) ||
- (channel->stderr_buffer &&
- ssh_buffer_get_len(channel->stderr_buffer) > 0)) {
- return 0;
+ if (ssh_channel_has_unread_data(channel)) {
+ return 0;
}
return (channel->remote_eof != 0);
@@ -2812,7 +2824,6 @@ static int ssh_channel_read_termination(void *s){
return 0;
}
-/* TODO FIXME Fix the delayed close thing */
/* TODO FIXME Fix the blocking behaviours */
/**
@@ -2957,6 +2968,10 @@ int ssh_channel_read_timeout(ssh_channel channel,
if (channel->counter != NULL) {
channel->counter->in_bytes += len;
}
+ /* Try completing the delayed_close */
+ if (channel->delayed_close && !ssh_channel_has_unread_data(channel)) {
+ channel->state = SSH_CHANNEL_STATE_CLOSED;
+ }
/* Authorize some buffering while userapp is busy */
if (channel->local_window < WINDOWLIMIT) {
if (grow_window(session, channel, 0) < 0) {