diff options
-rw-r--r-- | ui/vnc-auth-sasl.c | 5 | ||||
-rw-r--r-- | ui/vnc-jobs.c | 5 | ||||
-rw-r--r-- | ui/vnc.c | 28 | ||||
-rw-r--r-- | ui/vnc.h | 7 |
4 files changed, 41 insertions, 4 deletions
diff --git a/ui/vnc-auth-sasl.c b/ui/vnc-auth-sasl.c index 761493b9b2..8c1cdde3db 100644 --- a/ui/vnc-auth-sasl.c +++ b/ui/vnc-auth-sasl.c @@ -79,6 +79,11 @@ long vnc_client_write_sasl(VncState *vs) vs->sasl.encodedOffset += ret; if (vs->sasl.encodedOffset == vs->sasl.encodedLength) { + if (vs->sasl.encodedRawLength >= vs->force_update_offset) { + vs->force_update_offset = 0; + } else { + vs->force_update_offset -= vs->sasl.encodedRawLength; + } vs->output.offset -= vs->sasl.encodedRawLength; vs->sasl.encoded = NULL; vs->sasl.encodedOffset = vs->sasl.encodedLength = 0; diff --git a/ui/vnc-jobs.c b/ui/vnc-jobs.c index f7867771ae..e326679dd0 100644 --- a/ui/vnc-jobs.c +++ b/ui/vnc-jobs.c @@ -152,6 +152,11 @@ void vnc_jobs_consume_buffer(VncState *vs) vs->ioc, G_IO_IN | G_IO_OUT, vnc_client_io, vs, NULL); } buffer_move(&vs->output, &vs->jobs_buffer); + + if (vs->job_update == VNC_STATE_UPDATE_FORCE) { + vs->force_update_offset = vs->output.offset; + } + vs->job_update = VNC_STATE_UPDATE_NONE; } flush = vs->ioc != NULL && vs->abort != true; vnc_unlock_output(vs); @@ -1021,14 +1021,28 @@ static bool vnc_should_update(VncState *vs) break; case VNC_STATE_UPDATE_INCREMENTAL: /* Only allow incremental updates if the pending send queue - * is less than the permitted threshold + * is less than the permitted threshold, and the job worker + * is completely idle. */ - if (vs->output.offset < vs->throttle_output_offset) { + if (vs->output.offset < vs->throttle_output_offset && + vs->job_update == VNC_STATE_UPDATE_NONE) { return true; } break; case VNC_STATE_UPDATE_FORCE: - return true; + /* Only allow forced updates if the pending send queue + * does not contain a previous forced update, and the + * job worker is completely idle. + * + * Note this means we'll queue a forced update, even if + * the output buffer size is otherwise over the throttle + * output limit. + */ + if (vs->force_update_offset == 0 && + vs->job_update == VNC_STATE_UPDATE_NONE) { + return true; + } + break; } return false; } @@ -1096,8 +1110,9 @@ static int vnc_update_client(VncState *vs, int has_dirty) } } - vnc_job_push(job); + vs->job_update = vs->update; vs->update = VNC_STATE_UPDATE_NONE; + vnc_job_push(job); vs->has_dirty = 0; return n; } @@ -1332,6 +1347,11 @@ static ssize_t vnc_client_write_plain(VncState *vs) if (!ret) return 0; + if (ret >= vs->force_update_offset) { + vs->force_update_offset = 0; + } else { + vs->force_update_offset -= ret; + } buffer_advance(&vs->output, ret); if (vs->output.offset == 0) { @@ -271,6 +271,7 @@ struct VncState VncDisplay *vd; VncStateUpdate update; /* Most recent pending request from client */ + VncStateUpdate job_update; /* Currently processed by job thread */ int has_dirty; uint32_t features; int absolute; @@ -298,6 +299,12 @@ struct VncState VncClientInfo *info; + /* Job thread bottom half has put data for a forced update + * into the output buffer. This offset points to the end of + * the update data in the output buffer. This lets us determine + * when a force update is fully sent to the client, allowing + * us to process further forced updates. */ + size_t force_update_offset; /* We allow multiple incremental updates or audio capture * samples to be queued in output buffer, provided the * buffer size doesn't exceed this threshold. The value |