diff options
-rw-r--r-- | src/channels.c | 19 | ||||
-rw-r--r-- | src/poll.c | 76 |
2 files changed, 91 insertions, 4 deletions
diff --git a/src/channels.c b/src/channels.c index bc4d9bb..be12d0b 100644 --- a/src/channels.c +++ b/src/channels.c @@ -487,10 +487,13 @@ SSH_PACKET_CALLBACK(channel_rcv_change_window) { SSH_PACKET_CALLBACK(channel_rcv_data){ ssh_channel channel; ssh_string str; - ssh_buffer buf; size_t len; int is_stderr; +#ifdef WITH_SERVER +#else + ssh_buffer buf; int rest; +#endif (void)user; enter_function(); if(type==SSH2_MSG_CHANNEL_DATA) @@ -555,6 +558,8 @@ SSH_PACKET_CALLBACK(channel_rcv_data){ ssh_string_free(str); +#ifdef WITH_SERVER +#else if(ssh_callbacks_exists(channel->callbacks, channel_data_function)) { if(is_stderr) { buf = channel->stderr_buffer; @@ -571,12 +576,13 @@ SSH_PACKET_CALLBACK(channel_rcv_data){ buffer_pass_bytes(buf, rest); channel->local_window_buffer -= rest; } + } +#endif if (channel->local_window + channel->local_window_buffer < WINDOWLIMIT) { if (grow_window(session, channel, 0) < 0) { leave_function(); return -1; } - } } leave_function(); @@ -603,10 +609,13 @@ SSH_PACKET_CALLBACK(channel_rcv_eof) { /* channel->remote_window = 0; */ channel->remote_eof = 1; - if(ssh_callbacks_exists(channel->callbacks, channel_eof_function)) { - channel->callbacks->channel_eof_function(channel->session, + if(ssh_channel_is_eof(channel)) { + if(ssh_callbacks_exists(channel->callbacks, channel_eof_function)) { + channel->callbacks->channel_eof_function(channel->session, channel, channel->callbacks->userdata); + channel->remote_eof = 2; /* EOF callback has been called */ + } } leave_function(); @@ -649,11 +658,13 @@ SSH_PACKET_CALLBACK(channel_rcv_close) { * buffer because the eof is ignored until the buffer is empty. */ + if(ssh_channel_is_eof(channel)) { if(ssh_callbacks_exists(channel->callbacks, channel_close_function)) { channel->callbacks->channel_close_function(channel->session, channel, channel->callbacks->userdata); } + } channel->flags &= SSH_CHANNEL_FLAG_CLOSED_REMOTE; if(channel->flags & SSH_CHANNEL_FLAG_FREED_LOCAL) ssh_channel_do_free(channel); @@ -38,6 +38,7 @@ #ifdef WITH_SERVER #include "libssh/server.h" #include "libssh/misc.h" +#include "libssh/buffer.h" #endif @@ -807,11 +808,86 @@ int ssh_event_add_session(ssh_event event, ssh_session session) { */ int ssh_event_dopoll(ssh_event event, int timeout) { int rc; +#ifdef WITH_SERVER + ssh_session session; + struct ssh_iterator *iterator; + struct ssh_iterator *channels; + ssh_channel channel; + int rest; + static uint64_t count = 0; +#endif + count++; if(event == NULL || event->ctx == NULL) { return SSH_ERROR; } rc = ssh_poll_ctx_dopoll(event->ctx, timeout); +#ifdef WITH_SERVER + if(rc < 0 && rc != SSH_AGAIN) { + return rc; + } + iterator = ssh_list_get_iterator(event->sessions); + while(iterator != NULL) { + session = (ssh_session)iterator->data; + if(session->channels == NULL) { + iterator = iterator->next; + continue; + } + channels = ssh_list_get_iterator(session->channels); + while(channels != NULL) { + channel = (ssh_channel)channels->data; + if(channel->local_window_buffer > 0) { + if ((channel->stderr_buffer && + buffer_get_rest_len(channel->stderr_buffer) > 0)) { + rest = channel->callbacks->channel_data_function( + channel->session, + channel, + buffer_get_rest(channel->stderr_buffer), + buffer_get_rest_len(channel->stderr_buffer), + 1, + channel->callbacks->userdata); + if(rest > 0) { + buffer_pass_bytes(channel->stderr_buffer, rest); + channel->local_window_buffer -= rest; + } + } + if ((channel->stdout_buffer && + buffer_get_rest_len(channel->stdout_buffer) > 0)) { + rest = channel->callbacks->channel_data_function( + channel->session, + channel, + buffer_get_rest(channel->stdout_buffer), + buffer_get_rest_len(channel->stdout_buffer), + 0, + channel->callbacks->userdata); + if(rest > 0) { + buffer_pass_bytes(channel->stdout_buffer, rest); + channel->local_window_buffer -= rest; + } + } + } + if(ssh_channel_is_eof(channel)) { + if(channel->remote_eof != 2 && + ssh_callbacks_exists(channel->callbacks, + channel_eof_function)) { + channel->callbacks->channel_eof_function(channel->session, + channel, + channel->callbacks->userdata); + channel->remote_eof = 2; /* EOF callback has been called */ + } + if(ssh_callbacks_exists(channel->callbacks, + channel_close_function)) { + channel->callbacks->channel_close_function(channel->session, + channel, + channel->callbacks->userdata); + } + } + channels = channels->next; + } + iterator = iterator->next; + } +#endif + return rc; } |