Save up multiple small refunds in order to cut down on unnecessary WINDOW_ADJUST packets
Этот коммит содержится в:
родитель
7502920c7f
Коммит
cc7703092f
@ -67,7 +67,7 @@ typedef unsigned long long libssh2_uint64_t;
|
||||
typedef long long libssh2_int64_t;
|
||||
#endif
|
||||
|
||||
#define LIBSSH2_VERSION "0.9"
|
||||
#define LIBSSH2_VERSION "0.10"
|
||||
#define LIBSSH2_APINO 200503281457
|
||||
|
||||
/* Part of every banner, user specified or not */
|
||||
@ -279,6 +279,7 @@ LIBSSH2_API int libssh2_poll(LIBSSH2_POLLFD *fds, unsigned int nfds, long timeou
|
||||
/* Channel API */
|
||||
#define LIBSSH2_CHANNEL_WINDOW_DEFAULT 65536
|
||||
#define LIBSSH2_CHANNEL_PACKET_DEFAULT 16384
|
||||
#define LIBSSH2_CHANNEL_MINADJUST 1024
|
||||
|
||||
/* Extended Data Handling */
|
||||
#define LIBSSH2_CHANNEL_EXTENDED_DATA_NORMAL 0
|
||||
@ -321,6 +322,8 @@ LIBSSH2_API int libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id,
|
||||
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 unsigned long libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel, unsigned long adjustment, unsigned char force);
|
||||
|
||||
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))
|
||||
|
@ -113,6 +113,7 @@ struct _LIBSSH2_CHANNEL {
|
||||
int blocking;
|
||||
|
||||
libssh2_channel_data local, remote;
|
||||
unsigned long adjust_queue; /* Amount of bytes to be refunded to receive window (but not yet sent) */
|
||||
|
||||
LIBSSH2_SESSION *session;
|
||||
|
||||
|
@ -780,28 +780,59 @@ LIBSSH2_API int libssh2_channel_flush_ex(LIBSSH2_CHANNEL *channel, int streamid)
|
||||
}
|
||||
|
||||
if (refund_bytes && channel->remote.window_size_initial) {
|
||||
unsigned char adjust[9]; /* packet_type(1) + channel(4) + adjustment(4) */
|
||||
|
||||
/* 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);
|
||||
#ifdef LIBSSH2_DEBUG_CONNECTION
|
||||
_libssh2_debug(channel->session, LIBSSH2_DBG_CONN, "Adjusting window %lu bytes for data flushed from channel %lu/%lu", refund_bytes, channel->local.id, channel->remote.id);
|
||||
#endif
|
||||
|
||||
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;
|
||||
}
|
||||
libssh2_channel_receive_window_adjust(channel, refund_bytes, 0);
|
||||
}
|
||||
|
||||
return flush_bytes;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_channel_receive_window_adjust
|
||||
* Adjust the receive window for a channel by adjustment bytes
|
||||
* If the amount to be adjusted is less than LIBSSH2_CHANNEL_MINADJUST and force is 0
|
||||
* The adjustment amount will be queued for a later packet
|
||||
*
|
||||
* Returns the new size of the receive window (as understood by remote end)
|
||||
*/
|
||||
LIBSSH2_API unsigned long libssh2_channel_receive_window_adjust(LIBSSH2_CHANNEL *channel, unsigned long adjustment, unsigned char force)
|
||||
{
|
||||
unsigned char adjust[9]; /* packet_type(1) + channel(4) + adjustment(4) */
|
||||
|
||||
if (!force && (adjustment + channel->adjust_queue < LIBSSH2_CHANNEL_MINADJUST)) {
|
||||
#ifdef LIBSSH2_DEBUG_CONNECTION
|
||||
_libssh2_debug(channel->session, LIBSSH2_DBG_CONN, "Queing %lu bytes for receive window adjustment for channel %lu/%lu", adjustment, channel->local.id, channel->remote.id);
|
||||
#endif
|
||||
channel->adjust_queue += adjustment;
|
||||
return channel->remote.window_size;
|
||||
}
|
||||
|
||||
if (!adjustment && !channel->adjust_queue) {
|
||||
return channel->remote.window_size;
|
||||
}
|
||||
|
||||
adjustment += channel->adjust_queue;
|
||||
channel->adjust_queue = 0;
|
||||
|
||||
|
||||
/* 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, adjustment);
|
||||
#ifdef LIBSSH2_DEBUG_CONNECTION
|
||||
_libssh2_debug(channel->session, LIBSSH2_DBG_CONN, "Adjusting window %lu bytes for data flushed from channel %lu/%lu", adjustment, channel->local.id, channel->remote.id);
|
||||
#endif
|
||||
|
||||
if (libssh2_packet_write(channel->session, adjust, 9)) {
|
||||
libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send transfer-window adjustment packet, deferring", 0);
|
||||
channel->adjust_queue = adjustment;
|
||||
} else {
|
||||
channel->remote.window_size += adjustment;
|
||||
}
|
||||
|
||||
return channel->remote.window_size;
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
/* {{{ libssh2_channel_handle_extended_data
|
||||
* How should extended data look to the calling app?
|
||||
* Keep it in separate channels[_read() _read_stdder()]? (NORMAL)
|
||||
@ -866,8 +897,6 @@ LIBSSH2_API int libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id,
|
||||
bytes_read += want;
|
||||
|
||||
if (unlink_packet) {
|
||||
unsigned char adjust[9]; /* packet_type(1) + channel(4) + adjustment(4) */
|
||||
|
||||
if (packet->prev) {
|
||||
packet->prev->next = packet->next;
|
||||
} else {
|
||||
@ -881,20 +910,9 @@ LIBSSH2_API int libssh2_channel_read_ex(LIBSSH2_CHANNEL *channel, int stream_id,
|
||||
LIBSSH2_FREE(session, packet->data);
|
||||
|
||||
#ifdef LIBSSH2_DEBUG_CONNECTION
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN, "Unlinking empty packet buffer from channel %lu/%lu sending window adjust for %d bytes", channel->local.id, channel->remote.id, (int)(packet->data_len - (stream_id ? 13 : 9)));
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN, "Unlinking empty packet buffer from channel %lu/%lu", channel->local.id, channel->remote.id);
|
||||
#endif
|
||||
/* 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, packet->data_len - (stream_id ? 13 : 9));
|
||||
|
||||
if (libssh2_packet_write(session, adjust, 9)) {
|
||||
libssh2_error(session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send transfer-window adjustment packet", 0);
|
||||
} else {
|
||||
/* Don't forget to acknowledge the adjust on this end */
|
||||
channel->remote.window_size += (packet->data_len - (stream_id ? 13 : 9));
|
||||
}
|
||||
|
||||
libssh2_channel_receive_window_adjust(channel, packet->data_len - (stream_id ? 13 : 9), 0);
|
||||
LIBSSH2_FREE(session, packet);
|
||||
}
|
||||
}
|
||||
|
12
src/packet.c
12
src/packet.c
@ -446,19 +446,11 @@ static int libssh2_packet_add(LIBSSH2_SESSION *session, unsigned char *data, siz
|
||||
LIBSSH2_FREE(session, data);
|
||||
|
||||
if (channel->remote.window_size_initial) {
|
||||
/* Adjust the window based on the block we just freed */
|
||||
unsigned char adjust[9];
|
||||
|
||||
#ifdef LIBSSH2_DEBUG_CONNECTION
|
||||
_libssh2_debug(session, LIBSSH2_DBG_CONN, "Ignoring extended data and refunding %d bytes", (int)(datalen - 13));
|
||||
#endif
|
||||
adjust[0] = SSH_MSG_CHANNEL_WINDOW_ADJUST;
|
||||
libssh2_htonu32(adjust + 1, channel->remote.id);
|
||||
libssh2_htonu32(adjust + 5, datalen - 13);
|
||||
|
||||
if (libssh2_packet_write(channel->session, adjust, 9)) {
|
||||
libssh2_error(channel->session, LIBSSH2_ERROR_SOCKET_SEND, "Unable to send transfer-window adjustment packet", 0);
|
||||
}
|
||||
/* Adjust the window based on the block we just freed */
|
||||
libssh2_channel_receive_window_adjust(channel, datalen - 13, 0);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
Загрузка…
x
Ссылка в новой задаче
Block a user