Improve channel_write().

git-svn-id: svn+ssh://svn.berlios.de/svnroot/repos/libssh/trunk@689 7dcaeef0-15fb-0310-b436-a5af3365683c
This commit is contained in:
Andreas Schneider
2009-05-04 06:30:12 +00:00
parent 17c146391c
commit 9345ba7030

View File

@@ -847,62 +847,72 @@ error:
return rc; return rc;
} }
/** \brief blocking write on channel /**
* \param channel channel * @brief Blocking write on channel.
* \param data pointer to data to write *
* \param len length of data * @param channel The channel to write to.
* \return number of bytes written on success\n *
* SSH_ERROR on error * @param data A pointer to the data to write.
* \see channel_read() *
* @param len The length of the buffer to write to.
*
* @return The number of bytes written, SSH_ERROR on error.
*
* @see channel_read()
*/ */
int channel_write(CHANNEL *channel, const void *data, u32 len) { int channel_write(CHANNEL *channel, const void *data, u32 len) {
SSH_SESSION *session = channel->session; SSH_SESSION *session = channel->session;
int effectivelen;
int origlen = len; int origlen = len;
int effectivelen;
enter_function(); enter_function();
if (channel->local_eof) { if (channel->local_eof) {
ssh_set_error(session,SSH_REQUEST_DENIED,"Can't write to channel %d:%d" ssh_set_error(session, SSH_REQUEST_DENIED,
" after EOF was sent",channel->local_channel,channel->remote_channel); "Can't write to channel %d:%d after EOF was sent",
channel->local_channel,
channel->remote_channel);
leave_function(); leave_function();
return -1; return -1;
} }
if(!channel->open || channel->delayed_close){
if (channel->open == 0 || channel->delayed_close != 0) {
ssh_set_error(session, SSH_REQUEST_DENIED, "Remote channel is closed"); ssh_set_error(session, SSH_REQUEST_DENIED, "Remote channel is closed");
leave_function(); leave_function();
return -1; return -1;
} }
#ifdef HAVE_SSH1 #ifdef HAVE_SSH1
if (channel->version == 1) { if (channel->version == 1) {
int err = channel_write1(channel,data,len); int rc = channel_write1(channel, data, len);
leave_function(); leave_function();
return err; return rc;
} }
#endif #endif
while (len > 0) { while (len > 0) {
if (channel->remote_window < len) { if (channel->remote_window < len) {
ssh_log(session, SSH_LOG_PROTOCOL, ssh_log(session, SSH_LOG_PROTOCOL,
"Remote window is %d bytes. going to write %d bytes", "Remote window is %d bytes. going to write %d bytes",
channel->remote_window,len); channel->remote_window,
len);
ssh_log(session, SSH_LOG_PROTOCOL, ssh_log(session, SSH_LOG_PROTOCOL,
"Waiting for a growing window message..."); "Waiting for a growing window message...");
// wonder what happens when the channel window is zero /* What happens when the channel window is zero? */
while(channel->remote_window == 0) { while(channel->remote_window == 0) {
// parse every incoming packet /* parse every incoming packet */
packet_wait(channel->session, 0, 0); packet_wait(channel->session, 0, 0);
} }
effectivelen = len > channel->remote_window ? channel->remote_window : len; effectivelen = len > channel->remote_window ? channel->remote_window : len;
} else } else {
effectivelen = len; effectivelen = len;
if (buffer_add_u8(session->out_buffer,SSH2_MSG_CHANNEL_DATA) < 0) {
goto error;
} }
if (buffer_add_u32(session->out_buffer,htonl(channel->remote_channel)) < 0) {
goto error; if (buffer_add_u8(session->out_buffer, SSH2_MSG_CHANNEL_DATA) < 0 ||
} buffer_add_u32(session->out_buffer,
if (buffer_add_u32(session->out_buffer,htonl(effectivelen)) < 0) { htonl(channel->remote_channel)) < 0 ||
goto error; buffer_add_u32(session->out_buffer, htonl(effectivelen)) < 0 ||
} buffer_add_data(session->out_buffer, data, effectivelen) < 0) {
if (buffer_add_data(session->out_buffer,data,effectivelen) < 0) {
goto error; goto error;
} }
@@ -910,12 +920,15 @@ int channel_write(CHANNEL *channel, const void *data, u32 len) {
leave_function(); leave_function();
return SSH_ERROR; return SSH_ERROR;
} }
ssh_log(session, SSH_LOG_RARE, ssh_log(session, SSH_LOG_RARE,
"channel_write wrote %d bytes", effectivelen); "channel_write wrote %d bytes", effectivelen);
channel->remote_window -= effectivelen; channel->remote_window -= effectivelen;
len -= effectivelen; len -= effectivelen;
data += effectivelen; data += effectivelen;
} }
leave_function(); leave_function();
return origlen; return origlen;
error: error: