diff options
-rw-r--r-- | src/channel-usbredir.c | 15 | ||||
-rw-r--r-- | src/spice-channel-priv.h | 2 | ||||
-rw-r--r-- | src/spice-channel.c | 19 |
3 files changed, 35 insertions, 1 deletions
diff --git a/src/channel-usbredir.c b/src/channel-usbredir.c index c236ee7..0be72ba 100644 --- a/src/channel-usbredir.c +++ b/src/channel-usbredir.c @@ -91,6 +91,9 @@ static void usbredir_log(void *user_data, int level, const char *msg); static int usbredir_read_callback(void *user_data, uint8_t *data, int count); static int usbredir_write_callback(void *user_data, uint8_t *data, int count); static void usbredir_write_flush_callback(void *user_data); +#if USBREDIR_VERSION >= 0x000701 +static uint64_t usbredir_buffered_output_size_callback(void *user_data); +#endif static void *usbredir_alloc_lock(void); static void usbredir_lock_lock(void *user_data); @@ -224,6 +227,10 @@ void spice_usbredir_channel_set_context(SpiceUsbredirChannel *channel, usbredirhost_fl_write_cb_owns_buffer); if (!priv->host) g_error("Out of memory allocating usbredirhost"); + +#if USBREDIR_VERSION >= 0x000701 + usbredirhost_set_buffered_output_size_cb(priv->host, usbredir_buffered_output_size_callback); +#endif } static gboolean spice_usbredir_channel_open_device( @@ -461,6 +468,14 @@ void spice_usbredir_channel_get_guest_filter( /* ------------------------------------------------------------------ */ /* callbacks (any context) */ +#if USBREDIR_VERSION >= 0x000701 +static uint64_t usbredir_buffered_output_size_callback(void *user_data) +{ + g_return_val_if_fail(SPICE_IS_USBREDIR_CHANNEL(user_data), 0); + return spice_channel_get_queue_size(SPICE_CHANNEL(user_data)); +} +#endif + /* Note that this function must be re-entrant safe, as it can get called from both the main thread as well as from the usb event handling thread */ static void usbredir_write_flush_callback(void *user_data) diff --git a/src/spice-channel-priv.h b/src/spice-channel-priv.h index 436a521..4b2d1e6 100644 --- a/src/spice-channel-priv.h +++ b/src/spice-channel-priv.h @@ -111,6 +111,7 @@ struct _SpiceChannelPrivate { gboolean xmit_queue_blocked; STATIC_MUTEX xmit_queue_lock; guint xmit_queue_wakeup_id; + guint64 xmit_queue_size; char name[16]; enum spice_channel_state state; @@ -171,6 +172,7 @@ void spice_channel_wakeup(SpiceChannel *channel, gboolean cancel); SpiceSession* spice_channel_get_session(SpiceChannel *channel); enum spice_channel_state spice_channel_get_state(SpiceChannel *channel); +guint64 spice_channel_get_queue_size (SpiceChannel *channel); /* coroutine context */ typedef void (*handler_msg_in)(SpiceChannel *channel, SpiceMsgIn *msg, gpointer data); diff --git a/src/spice-channel.c b/src/spice-channel.c index d459ec4..1c96ded 100644 --- a/src/spice-channel.c +++ b/src/spice-channel.c @@ -697,10 +697,12 @@ void spice_msg_out_send(SpiceMsgOut *out) { SpiceChannelPrivate *c; gboolean was_empty; + guint32 size; g_return_if_fail(out != NULL); g_return_if_fail(out->channel != NULL); c = out->channel->priv; + size = spice_marshaller_get_total_size(out->marshaller); STATIC_MUTEX_LOCK(c->xmit_queue_lock); if (c->xmit_queue_blocked) { @@ -710,6 +712,7 @@ void spice_msg_out_send(SpiceMsgOut *out) was_empty = g_queue_is_empty(&c->xmit_queue); g_queue_push_tail(&c->xmit_queue, out); + c->xmit_queue_size = (was_empty) ? size : c->xmit_queue_size + size; /* One wakeup is enough to empty the entire queue -> only do a wakeup if the queue was empty, and there isn't one pending already. */ @@ -2104,8 +2107,11 @@ static void spice_channel_iterate_write(SpiceChannel *channel) STATIC_MUTEX_LOCK(c->xmit_queue_lock); out = g_queue_pop_head(&c->xmit_queue); STATIC_MUTEX_UNLOCK(c->xmit_queue_lock); - if (out) + if (out) { + guint32 size = spice_marshaller_get_total_size(out->marshaller); + c->xmit_queue_size = (c->xmit_queue_size < size) ? 0 : c->xmit_queue_size - size; spice_channel_write_msg(channel, out); + } } while (out); spice_channel_flushed(channel, TRUE); @@ -2814,6 +2820,17 @@ enum spice_channel_state spice_channel_get_state(SpiceChannel *channel) } G_GNUC_INTERNAL +guint64 spice_channel_get_queue_size (SpiceChannel *channel) +{ + guint64 size; + SpiceChannelPrivate *c = channel->priv; + STATIC_MUTEX_LOCK(c->xmit_queue_lock); + size = c->xmit_queue_size; + STATIC_MUTEX_UNLOCK(c->xmit_queue_lock); + return size; +} + +G_GNUC_INTERNAL void spice_channel_swap(SpiceChannel *channel, SpiceChannel *swap, gboolean swap_msgs) { SpiceChannelPrivate *c = channel->priv; |