summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel P. Berrange <berrange@redhat.com>2017-01-27 18:11:32 +0000
committerDaniel P. Berrange <berrange@redhat.com>2017-02-28 10:36:31 +0000
commitcd892a2efc47bf45d058578fb557ba6db235a3a8 (patch)
tree7a9a36c49ce6406b09f2bdcaf57ab44c6204bc59
parent8f2d7c341184a95d05476ea3c45dbae2b9ddbe51 (diff)
io: fix decoding when multiple websockets frames arrive at once
The qio_channel_websock_read_wire() method will read upto 4096 bytes off the socket and then decode the websockets header and payload. The code was only decoding a single websockets frame, even if the buffered data contained multiple frames. This meant that decoding of subsequent frames was delayed until further input arrived on the socket. This backlog of delayed frames gets worse & worse over time. Symptom was that when connecting to the VNC server via the built-in websockets server, mouse/keyboard interaction would start out fine, but slowly get more & more delayed until it was unusable. Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
-rw-r--r--io/channel-websock.c28
1 files changed, 14 insertions, 14 deletions
diff --git a/io/channel-websock.c b/io/channel-websock.c
index e47279a1ae..a06a4a85d1 100644
--- a/io/channel-websock.c
+++ b/io/channel-websock.c
@@ -570,21 +570,24 @@ static ssize_t qio_channel_websock_read_wire(QIOChannelWebsock *ioc,
ioc->encinput.offset += ret;
}
- if (ioc->payload_remain == 0) {
- ret = qio_channel_websock_decode_header(ioc, errp);
+ while (ioc->encinput.offset != 0) {
+ if (ioc->payload_remain == 0) {
+ ret = qio_channel_websock_decode_header(ioc, errp);
+ if (ret < 0) {
+ return ret;
+ }
+ if (ret == 0) {
+ ioc->io_eof = TRUE;
+ break;
+ }
+ }
+
+ ret = qio_channel_websock_decode_payload(ioc, errp);
if (ret < 0) {
return ret;
}
- if (ret == 0) {
- return 0;
- }
}
-
- ret = qio_channel_websock_decode_payload(ioc, errp);
- if (ret < 0) {
- return ret;
- }
- return ret;
+ return 1;
}
@@ -642,9 +645,6 @@ static gboolean qio_channel_websock_flush(QIOChannel *ioc,
if (ret < 0) {
goto cleanup;
}
- if (ret == 0) {
- wioc->io_eof = TRUE;
- }
}
cleanup: