Skip to contentSkip to conversation

io: fix decoding when multiple websockets frames arrive at once

PATCH In review Daniel P. Berrange 2 participants 2 messages Jan 30, 2017

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 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.

---
 io/channel-websock.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)
io/channel-websock.c +14 -14
index e47279a..a06a4a8 100644
@@ -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:
Signature · 1 line
2.9.3
Reviewed-by on v1 1/1
#1 lore raw
Quoted 1 line · Daniel P. Berrange

The qio_channel_websock_read_wire() method will read upto 4096

s/upto/up to/

Quoted 12 lines

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.

Quoted 5 lines
---
 io/channel-websock.c | 28 ++++++++++++++--------------
 1 file changed, 14 insertions(+), 14 deletions(-)
Signature · 2 lines
Eric Blake   eblake redhat com    +1-919-301-3266
Libvirt virtualization library http://libvirt.org