From 164c6e9fc5addad59dd2a93441cb59a8b7c59223 Mon Sep 17 00:00:00 2001 From: Dan Fandrich Date: Thu, 12 Apr 2007 21:24:36 +0000 Subject: [PATCH] libssh2_channel_close now waits for a SSH_MSG_CHANNEL_CLOSE message from the server as mandated by the RFC. Not doing so causes an OpenSSH server to occasionally corrupt (truncate) short files uploaded by scp (which manifests itself as a failure of test603 in the curl regression test suite). --- NEWS | 3 +++ src/channel.c | 18 ++++++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/NEWS b/NEWS index 3bb090c0..a7e16d00 100644 --- a/NEWS +++ b/NEWS @@ -39,6 +39,9 @@ Version Improve debugging code. Avoids many #ifdef's. + Improved session closing to avoid potentially truncated files on + OpenSSH servers (Dan Fandrich) + Version 0.14 ------------ diff --git a/src/channel.c b/src/channel.c index 153e126e..77b2dc90 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1381,6 +1381,7 @@ LIBSSH2_API int libssh2_channel_close(LIBSSH2_CHANNEL *channel) { LIBSSH2_SESSION *session = channel->session; unsigned char packet[5]; + int rc = 0; if (channel->local.close) { /* Already closed, act like we sent another close, even though we didn't... shhhhhh */ @@ -1401,9 +1402,22 @@ LIBSSH2_API int libssh2_channel_close(LIBSSH2_CHANNEL *channel) return -1; } - /* TODO: Wait up to a timeout value for a CHANNEL_CLOSE to come back, to avoid the problem alluded to in channel_nextid */ + /* We must wait for the remote SSH_MSG_CHANNEL_CLOSE message */ + if (!channel->remote.close) { + libssh2pack_t ret; + /* set blocking mode */ + int bl = _libssh2_channel_set_blocking(channel, 1); + do { + ret = libssh2_packet_read(session); + if ((ret < 0) && (ret != PACKET_EAGAIN)) { + rc = -1; + } + } while (ret != SSH_MSG_CHANNEL_CLOSE && rc == 0); - return 0; + _libssh2_channel_set_blocking(channel, bl); + } + + return rc; } /* }}} */