If the client is keeping sending data while we can't handle them (for instance because we need to forward to a device but the device is not fast enough to receive that amount of data) allows to stop RedChannelClient to read data. This after a bit will stop the client sending data as its output buffer will become full. Signed-off-by: Frediano Ziglio <fziglio@xxxxxxxxxx> --- server/red-channel-client.c | 28 ++++++++++++++++++++++++++++ server/red-channel-client.h | 4 ++++ 2 files changed, 32 insertions(+) diff --git a/server/red-channel-client.c b/server/red-channel-client.c index 4978f3567..03d565be8 100644 --- a/server/red-channel-client.c +++ b/server/red-channel-client.c @@ -145,6 +145,7 @@ struct RedChannelClientPrivate } urgent; } send_data; + bool block_read; bool during_send; GQueue pipe; @@ -974,10 +975,32 @@ red_channel_client_watch_update_mask(RedChannelClient *rcc, int event_mask) return; } + if (rcc->priv->block_read) { + event_mask &= ~SPICE_WATCH_EVENT_READ; + } + core = red_channel_get_core_interface(rcc->priv->channel); core->watch_update_mask(core, rcc->priv->stream->watch, event_mask); } +void red_channel_client_block_read(RedChannelClient *rcc) +{ + if (rcc->priv->block_read) { + return; + } + rcc->priv->block_read = true; + red_channel_client_watch_update_mask(rcc, SPICE_WATCH_EVENT_WRITE); +} + +void red_channel_client_unblock_read(RedChannelClient *rcc) +{ + if (!rcc->priv->block_read) { + return; + } + rcc->priv->block_read = false; + red_channel_client_watch_update_mask(rcc, SPICE_WATCH_EVENT_READ|SPICE_WATCH_EVENT_WRITE); +} + static void red_channel_client_seamless_migration_done(RedChannelClient *rcc) { rcc->priv->wait_migrate_data = FALSE; @@ -1221,6 +1244,11 @@ static void red_channel_client_handle_incoming(RedChannelClient *rcc) if (buffer->msg_pos < msg_size) { if (!buffer->msg) { buffer->msg = red_channel_client_alloc_msg_buf(rcc, msg_type, msg_size); + if (buffer->msg == NULL && rcc->priv->block_read) { + // if we are blocked by flow control just return, message will be read + // when data will be available + return; + } if (buffer->msg == NULL) { red_channel_warning(channel, "ERROR: channel refused to allocate buffer."); red_channel_client_disconnect(rcc); diff --git a/server/red-channel-client.h b/server/red-channel-client.h index 1ca0ad717..56e006ec5 100644 --- a/server/red-channel-client.h +++ b/server/red-channel-client.h @@ -137,6 +137,10 @@ gboolean red_channel_client_set_migration_seamless(RedChannelClient *rcc); void red_channel_client_set_destroying(RedChannelClient *rcc); bool red_channel_client_is_destroying(RedChannelClient *rcc); +/* allow to block or unblock reading */ +void red_channel_client_block_read(RedChannelClient *rcc); +void red_channel_client_unblock_read(RedChannelClient *rcc); + struct RedChannelClient { GObject parent; -- 2.20.1 _______________________________________________ Spice-devel mailing list Spice-devel@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/spice-devel