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

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