From 0138e36352d210b6074dbbf507d198fcbf003d9e Mon Sep 17 00:00:00 2001 From: Sara Golemon Date: Mon, 28 Mar 2005 22:59:35 +0000 Subject: [PATCH] Add libssh2_channel_window_(read|write)_ex() --- README | 3 +++ include/libssh2.h | 8 +++++++- src/channel.c | 50 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) diff --git a/README b/README index a2874ab..b1149c7 100644 --- a/README +++ b/README @@ -6,6 +6,9 @@ Version 0.9 Fixed libssh2_poll() to recognized closed sessions/channels. + Added libssh2_channel_window_read_ex() and libssh2_channel_window_write_ex() + for examining the ssh transport windowing states. + Version 0.8 ----------- diff --git a/include/libssh2.h b/include/libssh2.h index 807c011..645af9b 100644 --- a/include/libssh2.h +++ b/include/libssh2.h @@ -68,7 +68,7 @@ typedef long long libssh2_int64_t; #endif #define LIBSSH2_VERSION "0.8" -#define LIBSSH2_APINO 200503221619 +#define LIBSSH2_APINO 200503281457 /* Part of every banner, user specified or not */ #define LIBSSH2_SSH_BANNER "SSH-2.0-libssh2_" LIBSSH2_VERSION @@ -318,10 +318,16 @@ LIBSSH2_API int libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id, #define libssh2_channel_read(channel, buf, buflen) libssh2_channel_read_ex((channel), 0, (buf), (buflen)) #define libssh2_channel_read_stderr(channel, buf, buflen) libssh2_channel_read_ex((channel), SSH_EXTENDED_DATA_STDERR, (buf), (buflen)) +LIBSSH2_API unsigned long libssh2_channel_window_read_ex(LIBSSH2_CHANNEL *channel, unsigned long *read_avail, unsigned long *window_size_initial); +#define libssh2_channel_window_read(channel) libssh2_channel_window_read_ex((channel), NULL, NULL) + LIBSSH2_API int libssh2_channel_write_ex(LIBSSH2_CHANNEL *channel, int stream_id, const char *buf, size_t buflen); #define libssh2_channel_write(channel, buf, buflen) libssh2_channel_write_ex((channel), 0, (buf), (buflen)) #define libssh2_channel_write_stderr(channel, buf, buflen) libssh2_channel_write_ex((channel), SSH_EXTENDED_DATA_STDERR, (buf), (buflen)) +LIBSSH2_API unsigned long libssh2_channel_window_write_ex(LIBSSH2_CHANNEL *channel, unsigned long *window_size_initial); +#define libssh2_channel_window_write(channel) libssh2_channel_window_write_ex((channel), NULL) + LIBSSH2_API void libssh2_channel_set_blocking(LIBSSH2_CHANNEL *channel, int blocking); LIBSSH2_API void libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode); /* libssh2_channel_ignore_extended_data() is defined below for BC with version 0.1 diff --git a/src/channel.c b/src/channel.c index 5a48d99..292210d 100644 --- a/src/channel.c +++ b/src/channel.c @@ -1069,3 +1069,53 @@ LIBSSH2_API int libssh2_channel_free(LIBSSH2_CHANNEL *channel) return 0; } /* }}} */ + +/* {{{ libssh2_channel_window_read_ex + * Check the status of the read window + * Returns the number of bytes which the remote end may send without overflowing the window limit + * read_avail (if passed) will be populated with the number of bytes actually available to be read + * window_size_initial (if passed) will be populated with the window_size_initial as defined by the channel_open request + */ +LIBSSH2_API unsigned long libssh2_channel_window_read_ex(LIBSSH2_CHANNEL *channel, unsigned long *read_avail, unsigned long *window_size_initial) +{ + if (window_size_initial) { + *window_size_initial = channel->remote.window_size_initial; + } + + if (read_avail) { + unsigned long bytes_queued = 0; + LIBSSH2_PACKET *packet = channel->session->packets.head; + + while (packet) { + unsigned char packet_type = packet->data[0]; + + if (((packet_type == SSH_MSG_CHANNEL_DATA) || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA)) && + (libssh2_ntohu32(packet->data + 1) == channel->local.id)) { + bytes_queued += packet->data_len - packet->data_head; + } + + packet = packet->next; + } + + *read_avail = bytes_queued; + } + + return channel->remote.window_size; +} +/* }}} */ + +/* {{{ libssh2_channel_window_write_ex + * Check the status of the write window + * Returns the number of bytes which may be safely writen on the channel without blocking + * window_size_initial (if passed) will be populated with the size of the initial window as defined by the channel_open request + */ +LIBSSH2_API unsigned long libssh2_channel_window_write_ex(LIBSSH2_CHANNEL *channel, unsigned long *window_size_initial) +{ + if (window_size_initial) { + /* For locally initiated channels this is very often 0, so it's not *that* useful as information goes */ + *window_size_initial = channel->local.window_size_initial; + } + + return channel->local.window_size; +} +/* }}} */