Fix _libssh2_channel_write(): fixed the write loop to also read from the
transport layer better, to avoid draining the window size when sending large packets. I also fixed the return code for it to return the number of bytes handled in this single invoke (and not the cumulative amount).
This commit is contained in:
parent
b755f3eb10
commit
ad13de92d4
@ -1997,7 +1997,9 @@ _libssh2_channel_packet_data_len(LIBSSH2_CHANNEL * channel, int stream_id)
|
|||||||
/*
|
/*
|
||||||
* _libssh2_channel_write
|
* _libssh2_channel_write
|
||||||
*
|
*
|
||||||
* Send data to a channel
|
* Send data to a channel. Note that if this returns EAGAIN or simply didn't
|
||||||
|
* send the entire packet, the caller must call this function again with the
|
||||||
|
* SAME input arguments.
|
||||||
*/
|
*/
|
||||||
ssize_t
|
ssize_t
|
||||||
_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
|
_libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
|
||||||
@ -2005,6 +2007,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
|
|||||||
{
|
{
|
||||||
LIBSSH2_SESSION *session = channel->session;
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
libssh2pack_t rc;
|
libssh2pack_t rc;
|
||||||
|
ssize_t wrote = 0; /* counter for this specific this call */
|
||||||
|
|
||||||
if (channel->write_state == libssh2_NB_state_idle) {
|
if (channel->write_state == libssh2_NB_state_idle) {
|
||||||
channel->write_bufwrote = 0;
|
channel->write_bufwrote = 0;
|
||||||
@ -2060,29 +2063,19 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
|
|||||||
channel->write_s += 4;
|
channel->write_s += 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* twiddle our thumbs until there's window space available */
|
/* drain the incoming flow first */
|
||||||
while (channel->local.window_size <= 0) {
|
do
|
||||||
/* Don't worry -- This is never hit unless it's a
|
|
||||||
blocking channel anyway */
|
|
||||||
rc = _libssh2_transport_read(session);
|
rc = _libssh2_transport_read(session);
|
||||||
|
while (rc > 0);
|
||||||
|
|
||||||
if (rc < 0) {
|
if(channel->local.window_size <= 0) {
|
||||||
/* Error or EAGAIN occurred, disconnect? */
|
/* there's no more room for data so we stop sending now */
|
||||||
if (rc != PACKET_EAGAIN) {
|
if(!wrote) {
|
||||||
LIBSSH2_FREE(session, channel->write_packet);
|
/* if nothing has been written at this point we're at an
|
||||||
channel->write_state = libssh2_NB_state_idle;
|
EAGAIN point */
|
||||||
}
|
|
||||||
return rc;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rc == 0) {
|
|
||||||
/*
|
|
||||||
* if rc == 0, then fake EAGAIN to prevent busyloops until
|
|
||||||
* data arriaves on the network which seemed like a very
|
|
||||||
* bad idea
|
|
||||||
*/
|
|
||||||
return PACKET_EAGAIN;
|
return PACKET_EAGAIN;
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Don't exceed the remote end's limits */
|
/* Don't exceed the remote end's limits */
|
||||||
@ -2140,15 +2133,9 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
|
|||||||
buflen -= channel->write_bufwrite;
|
buflen -= channel->write_bufwrite;
|
||||||
buf += channel->write_bufwrite;
|
buf += channel->write_bufwrite;
|
||||||
channel->write_bufwrote += channel->write_bufwrite;
|
channel->write_bufwrote += channel->write_bufwrite;
|
||||||
|
wrote += channel->write_bufwrite;
|
||||||
|
|
||||||
channel->write_state = libssh2_NB_state_allocated;
|
channel->write_state = libssh2_NB_state_allocated;
|
||||||
|
|
||||||
/*
|
|
||||||
* Not sure this is still wanted
|
|
||||||
if (!channel->session->socket_block) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2157,7 +2144,7 @@ _libssh2_channel_write(LIBSSH2_CHANNEL *channel, int stream_id,
|
|||||||
|
|
||||||
channel->write_state = libssh2_NB_state_idle;
|
channel->write_state = libssh2_NB_state_idle;
|
||||||
|
|
||||||
return channel->write_bufwrote;
|
return wrote;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user