aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/libssh/channels.h1
-rw-r--r--src/channels.c19
2 files changed, 13 insertions, 7 deletions
diff --git a/include/libssh/channels.h b/include/libssh/channels.h
index c35daf1..2165602 100644
--- a/include/libssh/channels.h
+++ b/include/libssh/channels.h
@@ -59,6 +59,7 @@ struct ssh_channel_struct {
ssh_session session; /* SSH_SESSION pointer */
uint32_t local_channel;
uint32_t local_window;
+ uint32_t local_window_buffer;
int local_eof;
uint32_t local_maxpacket;
diff --git a/src/channels.c b/src/channels.c
index 8879b0f..3f65010 100644
--- a/src/channels.c
+++ b/src/channels.c
@@ -48,6 +48,7 @@
#define WINDOWBASE 1280000
#define WINDOWLIMIT (WINDOWBASE/2)
+#define WINDOWMAX (WINDOWBASE*2)
/*
* All implementations MUST be able to process packets with an
@@ -351,6 +352,10 @@ static int grow_window(ssh_session session, ssh_channel channel, int minimumsize
uint32_t new_window = minimumsize > WINDOWBASE ? minimumsize : WINDOWBASE;
enter_function();
+ if(new_window + channel->local_window_buffer > WINDOWMAX) {
+ /* limit memory consumption per channel */
+ new_window = WINDOWMAX - channel->local_window_buffer;
+ }
#ifdef WITH_SSH1
if (session->version == 1){
channel->remote_window = new_window;
@@ -557,8 +562,9 @@ SSH_PACKET_CALLBACK(channel_rcv_data){
channel->callbacks->userdata);
if(rest > 0) {
buffer_pass_bytes(buf, rest);
+ channel->local_window_buffer -= rest;
}
- if (channel->local_window + buffer_get_rest_len(buf) < WINDOWLIMIT) {
+ if (channel->local_window + channel->local_window_buffer < WINDOWLIMIT) {
if (grow_window(session, channel, 0) < 0) {
leave_function();
return -1;
@@ -890,6 +896,7 @@ int channel_default_bufferize(ssh_channel channel, void *data, int len,
return -1;
}
}
+ channel->local_window_buffer += len;
return 0;
}
@@ -1387,11 +1394,8 @@ int ssh_channel_is_eof(ssh_channel channel) {
if(channel == NULL) {
return SSH_ERROR;
}
- if ((channel->stdout_buffer &&
- buffer_get_rest_len(channel->stdout_buffer) > 0) ||
- (channel->stderr_buffer &&
- buffer_get_rest_len(channel->stderr_buffer) > 0)) {
- return 0;
+ if (channel->local_window_buffer > 0) {
+ return 0;
}
return (channel->remote_eof != 0);
@@ -2665,8 +2669,9 @@ int ssh_channel_read(ssh_channel channel, void *dest, uint32_t count, int is_std
len = (len > count ? count : len);
memcpy(dest, buffer_get_rest(stdbuf), len);
buffer_pass_bytes(stdbuf,len);
+ channel->local_window_buffer -= len;
/* Authorize some buffering while userapp is busy */
- if (channel->local_window < WINDOWLIMIT) {
+ if (channel->local_window + channel->local_window_buffer < WINDOWLIMIT) {
if (grow_window(session, channel, 0) < 0) {
leave_function();
return -1;