Blame SOURCES/kvm-io-pass-a-struct-iovec-into-qio_channel_websock_enco.patch

4a2fec
From 33c5c11a12bba1c60e75f716d7ddf09b99dc372a Mon Sep 17 00:00:00 2001
4a2fec
From: "Daniel P. Berrange" <berrange@redhat.com>
4a2fec
Date: Wed, 20 Dec 2017 17:56:57 +0100
4a2fec
Subject: [PATCH 17/42] io: pass a struct iovec into qio_channel_websock_encode
4a2fec
4a2fec
RH-Author: Daniel P. Berrange <berrange@redhat.com>
4a2fec
Message-id: <20171220175702.29663-16-berrange@redhat.com>
4a2fec
Patchwork-id: 78468
4a2fec
O-Subject: [RHV-7.5 qemu-kvm-rhev PATCH v2 15/20] io: pass a struct iovec into qio_channel_websock_encode
4a2fec
Bugzilla: 1518649
4a2fec
RH-Acked-by: John Snow <jsnow@redhat.com>
4a2fec
RH-Acked-by: Jeffrey Cody <jcody@redhat.com>
4a2fec
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
4a2fec
4a2fec
Instead of requiring use of another Buffer, pass a struct iovec
4a2fec
into qio_channel_websock_encode, which gives callers more
4a2fec
flexibility in how they process data.
4a2fec
4a2fec
Reviewed-by: Eric Blake <eblake@redhat.com>
4a2fec
Signed-off-by: Daniel P. Berrange <berrange@redhat.com>
4a2fec
(cherry picked from commit fb74e5903914b9ec8c80b6f7a35da000f9f92ae7)
4a2fec
4a2fec
NB, slight context difference due to typo fixup in previous
4a2fec
patch. Also pulled in iov.h include, again, to fix bisect build
4a2fec
4a2fec
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
4a2fec
---
4a2fec
 io/channel-websock.c | 68 +++++++++++++++++++++++++++++++++-------------------
4a2fec
 1 file changed, 43 insertions(+), 25 deletions(-)
4a2fec
4a2fec
diff --git a/io/channel-websock.c b/io/channel-websock.c
4a2fec
index 403b72b..11b6039 100644
4a2fec
--- a/io/channel-websock.c
4a2fec
+++ b/io/channel-websock.c
4a2fec
@@ -24,6 +24,7 @@
4a2fec
 #include "io/channel-websock.h"
4a2fec
 #include "crypto/hash.h"
4a2fec
 #include "trace.h"
4a2fec
+#include "qemu/iov.h"
4a2fec
 
4a2fec
 #include <time.h>
4a2fec
 
4a2fec
@@ -582,37 +583,48 @@ static gboolean qio_channel_websock_handshake_io(QIOChannel *ioc,
4a2fec
 }
4a2fec
 
4a2fec
 
4a2fec
-static void qio_channel_websock_encode_buffer(QIOChannelWebsock *ioc,
4a2fec
-                                              Buffer *output,
4a2fec
-                                              uint8_t opcode, Buffer *buffer)
4a2fec
+static void qio_channel_websock_encode(QIOChannelWebsock *ioc,
4a2fec
+                                       uint8_t opcode,
4a2fec
+                                       const struct iovec *iov,
4a2fec
+                                       size_t niov,
4a2fec
+                                       size_t size)
4a2fec
 {
4a2fec
     size_t header_size;
4a2fec
+    size_t i;
4a2fec
     union {
4a2fec
         char buf[QIO_CHANNEL_WEBSOCK_HEADER_LEN_64_BIT];
4a2fec
         QIOChannelWebsockHeader ws;
4a2fec
     } header;
4a2fec
 
4a2fec
+    assert(size <= iov_size(iov, niov));
4a2fec
+
4a2fec
     header.ws.b0 = QIO_CHANNEL_WEBSOCK_HEADER_FIELD_FIN |
4a2fec
         (opcode & QIO_CHANNEL_WEBSOCK_HEADER_FIELD_OPCODE);
4a2fec
-    if (buffer->offset < QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_THRESHOLD_7_BIT) {
4a2fec
-        header.ws.b1 = (uint8_t)buffer->offset;
4a2fec
+    if (size < QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_THRESHOLD_7_BIT) {
4a2fec
+        header.ws.b1 = (uint8_t)size;
4a2fec
         header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_7_BIT;
4a2fec
-    } else if (buffer->offset <
4a2fec
-               QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_THRESHOLD_16_BIT) {
4a2fec
+    } else if (size < QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_THRESHOLD_16_BIT) {
4a2fec
         header.ws.b1 = QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_16_BIT;
4a2fec
-        header.ws.u.s16.l16 = cpu_to_be16((uint16_t)buffer->offset);
4a2fec
+        header.ws.u.s16.l16 = cpu_to_be16((uint16_t)size);
4a2fec
         header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_16_BIT;
4a2fec
     } else {
4a2fec
         header.ws.b1 = QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_64_BIT;
4a2fec
-        header.ws.u.s64.l64 = cpu_to_be64(buffer->offset);
4a2fec
+        header.ws.u.s64.l64 = cpu_to_be64(size);
4a2fec
         header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_64_BIT;
4a2fec
     }
4a2fec
     header_size -= QIO_CHANNEL_WEBSOCK_HEADER_LEN_MASK;
4a2fec
 
4a2fec
-    trace_qio_channel_websock_encode(ioc, opcode, header_size, buffer->offset);
4a2fec
-    buffer_reserve(output, header_size + buffer->offset);
4a2fec
-    buffer_append(output, header.buf, header_size);
4a2fec
-    buffer_append(output, buffer->buffer, buffer->offset);
4a2fec
+    trace_qio_channel_websock_encode(ioc, opcode, header_size, size);
4a2fec
+    buffer_reserve(&ioc->encoutput, header_size + size);
4a2fec
+    buffer_append(&ioc->encoutput, header.buf, header_size);
4a2fec
+    for (i = 0; i < niov && size != 0; i++) {
4a2fec
+        size_t want = iov[i].iov_len;
4a2fec
+        if (want > size) {
4a2fec
+            want = size;
4a2fec
+        }
4a2fec
+        buffer_append(&ioc->encoutput, iov[i].iov_base, want);
4a2fec
+        size -= want;
4a2fec
+    }
4a2fec
 }
4a2fec
 
4a2fec
 
4a2fec
@@ -622,6 +634,7 @@ static ssize_t qio_channel_websock_write_wire(QIOChannelWebsock *, Error **);
4a2fec
 static void qio_channel_websock_write_close(QIOChannelWebsock *ioc,
4a2fec
                                             uint16_t code, const char *reason)
4a2fec
 {
4a2fec
+    struct iovec iov;
4a2fec
     buffer_reserve(&ioc->rawoutput, 2 + (reason ? strlen(reason) : 0));
4a2fec
     *(uint16_t *)(ioc->rawoutput.buffer + ioc->rawoutput.offset) =
4a2fec
         cpu_to_be16(code);
4a2fec
@@ -629,9 +642,10 @@ static void qio_channel_websock_write_close(QIOChannelWebsock *ioc,
4a2fec
     if (reason) {
4a2fec
         buffer_append(&ioc->rawoutput, reason, strlen(reason));
4a2fec
     }
4a2fec
-    qio_channel_websock_encode_buffer(
4a2fec
-        ioc, &ioc->encoutput, QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE,
4a2fec
-        &ioc->rawoutput);
4a2fec
+    iov.iov_base = ioc->rawoutput.buffer;
4a2fec
+    iov.iov_len = ioc->rawoutput.offset;
4a2fec
+    qio_channel_websock_encode(ioc, QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE,
4a2fec
+                               &iov, 1, iov.iov_len);
4a2fec
     buffer_reset(&ioc->rawoutput);
4a2fec
     qio_channel_websock_write_wire(ioc, NULL);
4a2fec
     qio_channel_shutdown(ioc->master, QIO_CHANNEL_SHUTDOWN_BOTH, NULL);
4a2fec
@@ -801,9 +815,10 @@ static int qio_channel_websock_decode_payload(QIOChannelWebsock *ioc,
4a2fec
         error_setg(errp, "websocket closed by peer");
4a2fec
         if (payload_len) {
4a2fec
             /* echo client status */
4a2fec
-            qio_channel_websock_encode_buffer(
4a2fec
-                ioc, &ioc->encoutput, QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE,
4a2fec
-                &ioc->encinput);
4a2fec
+            struct iovec iov = { .iov_base = ioc->encinput.buffer,
4a2fec
+                                 .iov_len = ioc->encinput.offset };
4a2fec
+            qio_channel_websock_encode(ioc, QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE,
4a2fec
+                                       &iov, 1, iov.iov_len);
4a2fec
             qio_channel_websock_write_wire(ioc, NULL);
4a2fec
             qio_channel_shutdown(ioc->master, QIO_CHANNEL_SHUTDOWN_BOTH, NULL);
4a2fec
         } else {
4a2fec
@@ -816,9 +831,10 @@ static int qio_channel_websock_decode_payload(QIOChannelWebsock *ioc,
4a2fec
         /* ping frames produce an immediate reply, as long as we've not still
4a2fec
          * got a previous pong queued, in which case we drop the new pong */
4a2fec
         if (ioc->pong_remain == 0) {
4a2fec
-            qio_channel_websock_encode_buffer(
4a2fec
-                ioc, &ioc->encoutput, QIO_CHANNEL_WEBSOCK_OPCODE_PONG,
4a2fec
-                &ioc->encinput);
4a2fec
+            struct iovec iov = { .iov_base = ioc->encinput.buffer,
4a2fec
+                                 .iov_len = ioc->encinput.offset };
4a2fec
+            qio_channel_websock_encode(ioc, QIO_CHANNEL_WEBSOCK_OPCODE_PONG,
4a2fec
+                                       &iov, 1, iov.iov_len);
4a2fec
             ioc->pong_remain = ioc->encoutput.offset;
4a2fec
         }
4a2fec
     }   /* pong frames are ignored */
4a2fec
@@ -1121,9 +1137,11 @@ static ssize_t qio_channel_websock_writev(QIOChannel *ioc,
4a2fec
 
4a2fec
  done:
4a2fec
     if (wioc->rawoutput.offset) {
4a2fec
-        qio_channel_websock_encode_buffer(
4a2fec
-            wioc, &wioc->encoutput, QIO_CHANNEL_WEBSOCK_OPCODE_BINARY_FRAME,
4a2fec
-            &wioc->rawoutput);
4a2fec
+        struct iovec iov = { .iov_base = wioc->rawoutput.buffer,
4a2fec
+                             .iov_len = wioc->rawoutput.offset };
4a2fec
+        qio_channel_websock_encode(wioc,
4a2fec
+                                   QIO_CHANNEL_WEBSOCK_OPCODE_BINARY_FRAME,
4a2fec
+                                   &iov, 1, iov.iov_len);
4a2fec
         buffer_reset(&wioc->rawoutput);
4a2fec
     }
4a2fec
     ret = qio_channel_websock_write_wire(wioc, errp);
4a2fec
-- 
4a2fec
1.8.3.1
4a2fec