[Spice-devel] [PATCH spice-server 3/4] red-channel-client: Allows to block receiving data
Frediano Ziglio
fziglio at redhat.com
Mon Jun 17 15:40:10 UTC 2019
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 at redhat.com>
---
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
More information about the Spice-devel
mailing list