Block means block
This commit is contained in:
2
README
2
README
@@ -12,6 +12,8 @@ Version 0.9
|
|||||||
|
|
||||||
Fixed libssh2_poll() to recognized closed sessions/channels.
|
Fixed libssh2_poll() to recognized closed sessions/channels.
|
||||||
|
|
||||||
|
Fixed libssh2_channel_write_ex() to fully block when set to blocking mode. Return actual bytes written as well. (Thanks deadem)
|
||||||
|
|
||||||
Added libssh2_channel_window_read_ex() and libssh2_channel_window_write_ex()
|
Added libssh2_channel_window_read_ex() and libssh2_channel_window_write_ex()
|
||||||
for examining the ssh transport windowing states.
|
for examining the ssh transport windowing states.
|
||||||
|
|
||||||
|
@@ -849,8 +849,8 @@ LIBSSH2_API int libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id,
|
|||||||
LIBSSH2_API int libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id, const char *buf, size_t buflen)
|
LIBSSH2_API int libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id, const char *buf, size_t buflen)
|
||||||
{
|
{
|
||||||
LIBSSH2_SESSION *session = channel->session;
|
LIBSSH2_SESSION *session = channel->session;
|
||||||
unsigned char *packet, *s;
|
unsigned char *packet;
|
||||||
unsigned long packet_len;
|
unsigned long packet_len, bufwrote = 0;
|
||||||
|
|
||||||
if (channel->local.close) {
|
if (channel->local.close) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_CLOSED, "We've already closed this channel", 0);
|
libssh2_error(session, LIBSSH2_ERROR_CHANNEL_CLOSED, "We've already closed this channel", 0);
|
||||||
@@ -870,39 +870,54 @@ LIBSSH2_API int libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id
|
|||||||
}
|
}
|
||||||
|
|
||||||
packet_len = buflen + (stream_id ? 13 : 9); /* packet_type(1) + channelno(4) [ + streamid(4) ] + buflen(4) */
|
packet_len = buflen + (stream_id ? 13 : 9); /* packet_type(1) + channelno(4) [ + streamid(4) ] + buflen(4) */
|
||||||
s = packet = LIBSSH2_ALLOC(session, packet_len);
|
packet = LIBSSH2_ALLOC(session, packet_len);
|
||||||
if (!packet) {
|
if (!packet) {
|
||||||
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocte space for data transmission packet", 0);
|
libssh2_error(session, LIBSSH2_ERROR_ALLOC, "Unable to allocte space for data transmission packet", 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
*(s++) = stream_id ? SSH_MSG_CHANNEL_EXTENDED_DATA : SSH_MSG_CHANNEL_DATA;
|
while (buflen > 0) {
|
||||||
libssh2_htonu32(s, channel->remote.id); s += 4;
|
size_t bufwrite = buflen;
|
||||||
if (stream_id) {
|
unsigned char *s = packet;
|
||||||
libssh2_htonu32(s, stream_id); s += 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Don't exceed the remote end's limits */
|
*(s++) = stream_id ? SSH_MSG_CHANNEL_EXTENDED_DATA : SSH_MSG_CHANNEL_DATA;
|
||||||
/* REMEMBER local means local as the SOURCE of the data */
|
libssh2_htonu32(s, channel->remote.id); s += 4;
|
||||||
if (buflen > channel->local.window_size) {
|
if (stream_id) {
|
||||||
buflen = channel->local.window_size;
|
libssh2_htonu32(s, stream_id); s += 4;
|
||||||
}
|
}
|
||||||
if (buflen > channel->local.packet_size) {
|
|
||||||
buflen = channel->local.packet_size;
|
|
||||||
}
|
|
||||||
libssh2_htonu32(s, buflen); s += 4;
|
|
||||||
memcpy(s, buf, buflen); s += buflen;
|
|
||||||
|
|
||||||
if (libssh2_packet_write(session, packet, s - packet)) {
|
/* Don't exceed the remote end's limits */
|
||||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send channel data", 0);
|
/* REMEMBER local means local as the SOURCE of the data */
|
||||||
return -1;
|
if (bufwrite > channel->local.window_size) {
|
||||||
|
bufwrite = channel->local.window_size;
|
||||||
|
}
|
||||||
|
if (bufwrite > channel->local.packet_size) {
|
||||||
|
bufwrite = channel->local.packet_size;
|
||||||
|
}
|
||||||
|
libssh2_htonu32(s, bufwrite); s += 4;
|
||||||
|
memcpy(s, buf, bufwrite); s += bufwrite;
|
||||||
|
|
||||||
|
if (libssh2_packet_write(session, packet, s - packet)) {
|
||||||
|
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send channel data", 0);
|
||||||
|
LIBSSH2_FREE(session, packet);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
/* Shrink local window size */
|
||||||
|
channel->local.window_size -= bufwrite;
|
||||||
|
|
||||||
|
/* Adjust buf for next iteration */
|
||||||
|
buflen -= bufwrite;
|
||||||
|
buf += bufwrite;
|
||||||
|
bufwrote += bufwrite;
|
||||||
|
|
||||||
|
if (!channel->blocking) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* Shrink local window size */
|
|
||||||
channel->local.window_size -= buflen;
|
|
||||||
|
|
||||||
LIBSSH2_FREE(session, packet);
|
LIBSSH2_FREE(session, packet);
|
||||||
|
|
||||||
return buflen;
|
return bufwrote;
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user