|
@@ -1521,8 +1521,37 @@ gboolean vnc_client_io(QIOChannel *ioc G_GNUC_UNUSED,
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
+/*
|
|
|
|
+ * Scale factor to apply to vs->throttle_output_offset when checking for
|
|
|
|
+ * hard limit. Worst case normal usage could be x2, if we have a complete
|
|
|
|
+ * incremental update and complete forced update in the output buffer.
|
|
|
|
+ * So x3 should be good enough, but we pick x5 to be conservative and thus
|
|
|
|
+ * (hopefully) never trigger incorrectly.
|
|
|
|
+ */
|
|
|
|
+#define VNC_THROTTLE_OUTPUT_LIMIT_SCALE 5
|
|
|
|
+
|
|
void vnc_write(VncState *vs, const void *data, size_t len)
|
|
void vnc_write(VncState *vs, const void *data, size_t len)
|
|
{
|
|
{
|
|
|
|
+ if (vs->disconnecting) {
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+ /* Protection against malicious client/guest to prevent our output
|
|
|
|
+ * buffer growing without bound if client stops reading data. This
|
|
|
|
+ * should rarely trigger, because we have earlier throttling code
|
|
|
|
+ * which stops issuing framebuffer updates and drops audio data
|
|
|
|
+ * if the throttle_output_offset value is exceeded. So we only reach
|
|
|
|
+ * this higher level if a huge number of pseudo-encodings get
|
|
|
|
+ * triggered while data can't be sent on the socket.
|
|
|
|
+ *
|
|
|
|
+ * NB throttle_output_offset can be zero during early protocol
|
|
|
|
+ * handshake, or from the job thread's VncState clone
|
|
|
|
+ */
|
|
|
|
+ if (vs->throttle_output_offset != 0 &&
|
|
|
|
+ vs->output.offset > (vs->throttle_output_offset *
|
|
|
|
+ VNC_THROTTLE_OUTPUT_LIMIT_SCALE)) {
|
|
|
|
+ vnc_disconnect_start(vs);
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
buffer_reserve(&vs->output, len);
|
|
buffer_reserve(&vs->output, len);
|
|
|
|
|
|
if (vs->ioc != NULL && buffer_empty(&vs->output)) {
|
|
if (vs->ioc != NULL && buffer_empty(&vs->output)) {
|