From 794f01acc14214938327399f86fc16c73f3b3618 Mon Sep 17 00:00:00 2001 From: Sara Golemon Date: Wed, 8 Dec 2004 18:54:25 +0000 Subject: [PATCH] Add flush mechanism to the channel API --- README | 5 +++ include/libssh2.h | 5 +++ src/channel.c | 77 ++++++++++++++++++++++++++++++----------------- 3 files changed, 60 insertions(+), 27 deletions(-) diff --git a/README b/README index b8b2ec3..2b3ac27 100644 --- a/README +++ b/README @@ -15,6 +15,11 @@ Version 0.2 LIBSSH2_CHANNEL_EXTENDED_DATA_MERGE Calls to channel_read() will check both the standard data stream and the extended data stream(s) for the first available packet + Added libssh2_channel_flush_ex() and basic macros: ..._flush() ..._flush_stderr() + flush_ex accepts either the streamid (0 for standard data, 1 for stderr) or one of the two following constants: + LIBSSH2_CHANNEL_FLUSH_ALL Flush all streams + LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA Flush all streams EXCEPT the standard data stream + Version 0.1 ----------- diff --git a/include/libssh2.h b/include/libssh2.h index d2e5840..392fb48 100644 --- a/include/libssh2.h +++ b/include/libssh2.h @@ -217,6 +217,11 @@ LIBSSH2_API void libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel, /* DEPRECATED */ #define libssh2_channel_ignore_extended_data(channel, ignore) libssh2_channel_handle_extended_data((channel), (ignore) ? LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE : LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL ) +#define LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA -1 +#define LIBSSH2_CHANNEL_FLUSH_ALL -2 +LIBSSH2_API int libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int streamid); +#define libssh2_channel_flush(channel) libssh2_channel_flush_ex((channel), 0) +#define libssh2_channel_flush_stderr(channel) libssh2_channel_flush_ex((channel), SSH_EXTENDED_DATA_STDERR) LIBSSH2_API int libssh2_channel_send_eof(LIBSSH2_CHANNEL *channel); LIBSSH2_API int libssh2_channel_eof(LIBSSH2_CHANNEL *channel); diff --git a/src/channel.c b/src/channel.c index d9caee3..c3cbaac 100644 --- a/src/channel.c +++ b/src/channel.c @@ -434,27 +434,30 @@ LIBSSH2_API void libssh2_channel_set_blocking(LIBSSH2_CHANNEL *channel, int bloc } /* }}} */ -/* {{{ libssh2_channel_handle_extended_data - * How should extended data look to the calling app? - * Keep it in separate channels[_read() _read_stdder()]? (NORMAL) - * Merge the extended data to the standard data? [everything via _read()]? (MERGE) - * -Ignore it entirely [toss out packets as they come in]? (IGNORE) +/* {{{ libssh2_channel_flush_ex + * Flush data from one (or all) stream + * Returns number of bytes flushed, or -1 on failure */ -LIBSSH2_API void libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode) +LIBSSH2_API int libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int streamid) { - channel->remote.extended_data_ignore_mode = ignore_mode; + LIBSSH2_PACKET *packet = channel->session->packets.head; + unsigned long refund_bytes = 0, flush_bytes = 0; - if (ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) { - /* Flush queued extended data */ - LIBSSH2_PACKET *packet = channel->session->packets.head; - unsigned long refund_bytes = 0; + while (packet) { + LIBSSH2_PACKET *next = packet->next; + unsigned char packet_type = packet->data[0]; - while (packet) { - LIBSSH2_PACKET *next = packet->next; + if (((packet_type == SSH_MSG_CHANNEL_DATA) || (packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA)) && + (libssh2_ntohu32(packet->data + 1) == channel->local.id)) { + /* It's our channel at least */ + if ((streamid == LIBSSH2_CHANNEL_FLUSH_ALL) || + ((packet_type == SSH_MSG_CHANNEL_EXTENDED_DATA) && ((streamid == LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA) || (streamid = libssh2_ntohu32(packet->data + 5)))) || + ((packet_type == SSH_MSG_CHANNEL_DATA) && (streamid == 0))) { - if ((packet->data[0] == SSH_MSG_CHANNEL_EXTENDED_DATA) && (libssh2_ntohu32(packet->data + 1) == channel->local.id)) { + /* It's one of the streams we wanted to flush */ refund_bytes += packet->data_len - 13; + flush_bytes += packet->data_len - packet->data_head; + LIBSSH2_FREE(channel->session, packet->data); if (packet->prev) { packet->prev->next = packet->next; @@ -468,23 +471,43 @@ LIBSSH2_API void libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel, } LIBSSH2_FREE(channel->session, packet); } - packet = next; } - if (refund_bytes && channel->remote.window_size_initial) { - unsigned char adjust[9]; /* packet_type(1) + channel(4) + adjustment(4) */ + packet = next; + } - /* Adjust the window based on the block we just freed */ - adjust[0] = SSH_MSG_CHANNEL_WINDOW_ADJUST; - libssh2_htonu32(adjust + 1, channel->remote.id); - libssh2_htonu32(adjust + 5, refund_bytes); + if (refund_bytes && channel->remote.window_size_initial) { + unsigned char adjust[9]; /* packet_type(1) + channel(4) + adjustment(4) */ - if (libssh2_packet_write(channel->session, adjust, 9)) { - libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send transfer-window adjustment packet", 0); - } else { - channel->remote.window_size += refund_bytes; - } + /* Adjust the window based on the block we just freed */ + adjust[0] = SSH_MSG_CHANNEL_WINDOW_ADJUST; + libssh2_htonu32(adjust + 1, channel->remote.id); + libssh2_htonu32(adjust + 5, refund_bytes); + + if (libssh2_packet_write(channel->session, adjust, 9)) { + libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send transfer-window adjustment packet", 0); + return -1; + } else { + channel->remote.window_size += refund_bytes; } } + + return flush_bytes; +} +/* }}} */ + +/* {{{ libssh2_channel_handle_extended_data + * How should extended data look to the calling app? + * Keep it in separate channels[_read() _read_stdder()]? (NORMAL) + * Merge the extended data to the standard data? [everything via _read()]? (MERGE) + * Ignore it entirely [toss out packets as they come in]? (IGNORE) + */ +LIBSSH2_API void libssh2_channel_handle_extended_data(LIBSSH2_CHANNEL *channel, int ignore_mode) +{ + channel->remote.extended_data_ignore_mode = ignore_mode; + + if (ignore_mode == LIBSSH2_CHANNEL_EXTENDED_DATA_IGNORE) { + libssh2_channel_flush_ex(channel, LIBSSH2_CHANNEL_FLUSH_EXTENDED_DATA); + } } /* }}} */