From a94886f157ece8328aa75d1ea5c189a6eab33337 Mon Sep 17 00:00:00 2001 From: Daniel Stenberg Date: Sat, 23 Oct 2010 01:16:12 +0200 Subject: [PATCH] _libssh2_channel_write: removed 32500 size limit Neither _libssh2_channel_write nor sftp_write now have the 32500 size limit anymore and instead the channel writing function now has its own logic to send data in multiple calls until everything is sent. --- src/channel.c | 75 +++++++++++++++++++++++++++++++++++++++++++--- src/libssh2_priv.h | 5 ++++ src/sftp.c | 4 --- 3 files changed, 76 insertions(+), 8 deletions(-) diff --git a/src/channel.c b/src/channel.c index 656ad43..bdc6c59 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1969,7 +1969,7 @@ _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id) } /* - * _libssh2_channel_write + * channel_write * * Send data to a channel. Note that if this returns EAGAIN, the caller must * call this function again with the SAME input arguments. @@ -1977,9 +1977,9 @@ _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id) * Returns: number of bytes sent, or if it returns a negative number, that is * the error code! */ -ssize_t -_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, - const unsigned char *buf, size_t buflen) +static ssize_t +channel_write(LIBSSH2_CHANNEL *channel, int stream_id, + const unsigned char *buf, size_t buflen) { LIBSSH2_SESSION *session = channel->session; int rc; @@ -2103,6 +2103,73 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, return LIBSSH2_ERROR_INVAL; /* reaching this point is really bad */ } +/* + * _libssh2_channel_write + * + * Send data to a channel. Note that if this returns EAGAIN, the caller must + * call this function again with the SAME input arguments. + * + * Returns: number of bytes sent, or if it returns a negative number, that is + * the error code! + */ +ssize_t +_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id, + const unsigned char *buf, size_t buflen) +{ + LIBSSH2_SESSION *session = channel->session; + int rc = 0; + ssize_t wrote = 0; + + if(channel->transport_buf) { + /* previous EAGAIN situation, take care of this first */ + rc = channel_write(channel, + channel->transport_streamid, + channel->transport_buf, + channel->transport_buflen); + if(rc == LIBSSH2_ERROR_EAGAIN) + /* still EAGAIN, get out */ + return rc; + else if(rc < 0) + return rc; + + if(rc != channel->transport_buflen) { + /* previous buffer not drained yet */ + channel->transport_buf += rc; + channel->transport_buflen -= rc; + return LIBSSH2_ERROR_EAGAIN; + } + + /* all is sent, clear the buf pointer */ + channel->transport_buf = NULL; + } + + do { + rc = channel_write(channel, stream_id, buf, buflen); + + if(rc < 0) { + if(rc == LIBSSH2_ERROR_EAGAIN) { + /* store the buf/buflen pair and use that in the next call + again to flush the transport layer */ + channel->transport_streamid = stream_id; + channel->transport_buf = buf; + channel->transport_buflen = buflen; + if(wrote) + return wrote; + + /* nothing written, return EAGAIN */ + return rc; + } + return rc; + } + wrote += rc; + buf += rc; + buflen -= rc; + + } while(buflen); + + return wrote; +} + /* * libssh2_channel_write_ex * diff --git a/src/libssh2_priv.h b/src/libssh2_priv.h index 7e4a092..0dde3fe 100644 --- a/src/libssh2_priv.h +++ b/src/libssh2_priv.h @@ -401,6 +401,10 @@ struct _LIBSSH2_CHANNEL size_t write_packet_len; size_t write_bufwrite; + int transport_streamid; + const unsigned char *transport_buf; + size_t transport_buflen; + /* State variables used in libssh2_channel_close() */ libssh2_nonblocking_states close_state; unsigned char close_packet[5]; @@ -416,6 +420,7 @@ struct _LIBSSH2_CHANNEL /* State variables used in libssh2_channel_handle_extended_data2() */ libssh2_nonblocking_states extData2_state; + }; struct _LIBSSH2_LISTENER diff --git a/src/sftp.c b/src/sftp.c index b9a0e83..e7726d8 100644 --- a/src/sftp.c +++ b/src/sftp.c @@ -1400,10 +1400,6 @@ static ssize_t sftp_write(LIBSSH2_SFTP_HANDLE *handle, const char *buffer, unsigned char *s, *data; int rc; - /* we limit this to just send a single SSH packet at a time */ - if(count > 32500) - count = 32500; - packet_len = handle->handle_len + count + 25; if (sftp->write_state == libssh2_NB_state_idle) {