red-channel-client: Allows to block receiving data

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@redhat.com>
Acked-by: Victor Toso <victortoso@redhat.com>
This commit is contained in:
Frediano Ziglio 2019-06-15 18:31:11 +01:00
parent 1157588cc1
commit 726b1824e3
2 changed files with 32 additions and 0 deletions

View File

@ -145,6 +145,7 @@ struct RedChannelClientPrivate
} urgent;
} send_data;
bool block_read;
bool during_send;
GQueue pipe;
@ -969,10 +970,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;
@ -1213,6 +1236,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);

View File

@ -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;