xref: /openbmc/qemu/io/channel-websock.c (revision 0b1183e3)
1 /*
2  * QEMU I/O channels driver websockets
3  *
4  * Copyright (c) 2015 Red Hat, Inc.
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  *
19  */
20 
21 #include "qemu/osdep.h"
22 #include "qapi/error.h"
23 #include "qemu/bswap.h"
24 #include "io/channel-websock.h"
25 #include "crypto/hash.h"
26 #include "trace.h"
27 
28 
29 /* Max amount to allow in rawinput/rawoutput buffers */
30 #define QIO_CHANNEL_WEBSOCK_MAX_BUFFER 8192
31 
32 #define QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN 24
33 #define QIO_CHANNEL_WEBSOCK_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
34 #define QIO_CHANNEL_WEBSOCK_GUID_LEN strlen(QIO_CHANNEL_WEBSOCK_GUID)
35 
36 #define QIO_CHANNEL_WEBSOCK_HEADER_PROTOCOL "sec-websocket-protocol"
37 #define QIO_CHANNEL_WEBSOCK_HEADER_VERSION "sec-websocket-version"
38 #define QIO_CHANNEL_WEBSOCK_HEADER_KEY "sec-websocket-key"
39 #define QIO_CHANNEL_WEBSOCK_HEADER_UPGRADE "upgrade"
40 #define QIO_CHANNEL_WEBSOCK_HEADER_HOST "host"
41 #define QIO_CHANNEL_WEBSOCK_HEADER_CONNECTION "connection"
42 
43 #define QIO_CHANNEL_WEBSOCK_PROTOCOL_BINARY "binary"
44 #define QIO_CHANNEL_WEBSOCK_CONNECTION_UPGRADE "Upgrade"
45 #define QIO_CHANNEL_WEBSOCK_UPGRADE_WEBSOCKET "websocket"
46 
47 #define QIO_CHANNEL_WEBSOCK_HANDSHAKE_RESPONSE  \
48     "HTTP/1.1 101 Switching Protocols\r\n"      \
49     "Upgrade: websocket\r\n"                    \
50     "Connection: Upgrade\r\n"                   \
51     "Sec-WebSocket-Accept: %s\r\n"              \
52     "Sec-WebSocket-Protocol: binary\r\n"        \
53     "\r\n"
54 #define QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM "\r\n"
55 #define QIO_CHANNEL_WEBSOCK_HANDSHAKE_END "\r\n\r\n"
56 #define QIO_CHANNEL_WEBSOCK_SUPPORTED_VERSION "13"
57 #define QIO_CHANNEL_WEBSOCK_HTTP_METHOD "GET"
58 #define QIO_CHANNEL_WEBSOCK_HTTP_PATH "/"
59 #define QIO_CHANNEL_WEBSOCK_HTTP_VERSION "HTTP/1.1"
60 
61 /* The websockets packet header is variable length
62  * depending on the size of the payload... */
63 
64 /* ...length when using 7-bit payload length */
65 #define QIO_CHANNEL_WEBSOCK_HEADER_LEN_7_BIT 6
66 /* ...length when using 16-bit payload length */
67 #define QIO_CHANNEL_WEBSOCK_HEADER_LEN_16_BIT 8
68 /* ...length when using 64-bit payload length */
69 #define QIO_CHANNEL_WEBSOCK_HEADER_LEN_64_BIT 14
70 
71 /* Length of the optional data mask field in header */
72 #define QIO_CHANNEL_WEBSOCK_HEADER_LEN_MASK 4
73 
74 /* Maximum length that can fit in 7-bit payload size */
75 #define QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_THRESHOLD_7_BIT 126
76 /* Maximum length that can fit in 16-bit payload size */
77 #define QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_THRESHOLD_16_BIT 65536
78 
79 /* Magic 7-bit length to indicate use of 16-bit payload length */
80 #define QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_16_BIT 126
81 /* Magic 7-bit length to indicate use of 64-bit payload length */
82 #define QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_64_BIT 127
83 
84 /* Bitmasks & shifts for accessing header fields */
85 #define QIO_CHANNEL_WEBSOCK_HEADER_FIELD_FIN 0x80
86 #define QIO_CHANNEL_WEBSOCK_HEADER_FIELD_OPCODE 0x0f
87 #define QIO_CHANNEL_WEBSOCK_HEADER_FIELD_HAS_MASK 0x80
88 #define QIO_CHANNEL_WEBSOCK_HEADER_FIELD_PAYLOAD_LEN 0x7f
89 #define QIO_CHANNEL_WEBSOCK_HEADER_SHIFT_FIN 7
90 #define QIO_CHANNEL_WEBSOCK_HEADER_SHIFT_HAS_MASK 7
91 
92 typedef struct QIOChannelWebsockHeader QIOChannelWebsockHeader;
93 
94 struct QEMU_PACKED QIOChannelWebsockHeader {
95     unsigned char b0;
96     unsigned char b1;
97     union {
98         struct QEMU_PACKED {
99             uint16_t l16;
100             QIOChannelWebsockMask m16;
101         } s16;
102         struct QEMU_PACKED {
103             uint64_t l64;
104             QIOChannelWebsockMask m64;
105         } s64;
106         QIOChannelWebsockMask m;
107     } u;
108 };
109 
110 typedef struct QIOChannelWebsockHTTPHeader QIOChannelWebsockHTTPHeader;
111 
112 struct QIOChannelWebsockHTTPHeader {
113     char *name;
114     char *value;
115 };
116 
117 enum {
118     QIO_CHANNEL_WEBSOCK_OPCODE_CONTINUATION = 0x0,
119     QIO_CHANNEL_WEBSOCK_OPCODE_TEXT_FRAME = 0x1,
120     QIO_CHANNEL_WEBSOCK_OPCODE_BINARY_FRAME = 0x2,
121     QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE = 0x8,
122     QIO_CHANNEL_WEBSOCK_OPCODE_PING = 0x9,
123     QIO_CHANNEL_WEBSOCK_OPCODE_PONG = 0xA
124 };
125 
126 static size_t
127 qio_channel_websock_extract_headers(char *buffer,
128                                     QIOChannelWebsockHTTPHeader *hdrs,
129                                     size_t nhdrsalloc,
130                                     Error **errp)
131 {
132     char *nl, *sep, *tmp;
133     size_t nhdrs = 0;
134 
135     /*
136      * First parse the HTTP protocol greeting of format:
137      *
138      *   $METHOD $PATH $VERSION
139      *
140      * e.g.
141      *
142      *   GET / HTTP/1.1
143      */
144 
145     nl = strstr(buffer, QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM);
146     if (!nl) {
147         error_setg(errp, "Missing HTTP header delimiter");
148         return 0;
149     }
150     *nl = '\0';
151 
152     tmp = strchr(buffer, ' ');
153     if (!tmp) {
154         error_setg(errp, "Missing HTTP path delimiter");
155         return 0;
156     }
157     *tmp = '\0';
158 
159     if (!g_str_equal(buffer, QIO_CHANNEL_WEBSOCK_HTTP_METHOD)) {
160         error_setg(errp, "Unsupported HTTP method %s", buffer);
161         return 0;
162     }
163 
164     buffer = tmp + 1;
165     tmp = strchr(buffer, ' ');
166     if (!tmp) {
167         error_setg(errp, "Missing HTTP version delimiter");
168         return 0;
169     }
170     *tmp = '\0';
171 
172     if (!g_str_equal(buffer, QIO_CHANNEL_WEBSOCK_HTTP_PATH)) {
173         error_setg(errp, "Unexpected HTTP path %s", buffer);
174         return 0;
175     }
176 
177     buffer = tmp + 1;
178 
179     if (!g_str_equal(buffer, QIO_CHANNEL_WEBSOCK_HTTP_VERSION)) {
180         error_setg(errp, "Unsupported HTTP version %s", buffer);
181         return 0;
182     }
183 
184     buffer = nl + strlen(QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM);
185 
186     /*
187      * Now parse all the header fields of format
188      *
189      *   $NAME: $VALUE
190      *
191      * e.g.
192      *
193      *   Cache-control: no-cache
194      */
195     do {
196         QIOChannelWebsockHTTPHeader *hdr;
197 
198         nl = strstr(buffer, QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM);
199         if (nl) {
200             *nl = '\0';
201         }
202 
203         sep = strchr(buffer, ':');
204         if (!sep) {
205             error_setg(errp, "Malformed HTTP header");
206             return 0;
207         }
208         *sep = '\0';
209         sep++;
210         while (*sep == ' ') {
211             sep++;
212         }
213 
214         if (nhdrs >= nhdrsalloc) {
215             error_setg(errp, "Too many HTTP headers");
216             return 0;
217         }
218 
219         hdr = &hdrs[nhdrs++];
220         hdr->name = buffer;
221         hdr->value = sep;
222 
223         /* Canonicalize header name for easier identification later */
224         for (tmp = hdr->name; *tmp; tmp++) {
225             *tmp = g_ascii_tolower(*tmp);
226         }
227 
228         if (nl) {
229             buffer = nl + strlen(QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM);
230         }
231     } while (nl != NULL);
232 
233     return nhdrs;
234 }
235 
236 static const char *
237 qio_channel_websock_find_header(QIOChannelWebsockHTTPHeader *hdrs,
238                                 size_t nhdrs,
239                                 const char *name)
240 {
241     size_t i;
242 
243     for (i = 0; i < nhdrs; i++) {
244         if (g_str_equal(hdrs[i].name, name)) {
245             return hdrs[i].value;
246         }
247     }
248 
249     return NULL;
250 }
251 
252 
253 static int qio_channel_websock_handshake_send_response(QIOChannelWebsock *ioc,
254                                                        const char *key,
255                                                        Error **errp)
256 {
257     char combined_key[QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN +
258                       QIO_CHANNEL_WEBSOCK_GUID_LEN + 1];
259     char *accept = NULL, *response = NULL;
260     size_t responselen;
261 
262     g_strlcpy(combined_key, key, QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN + 1);
263     g_strlcat(combined_key, QIO_CHANNEL_WEBSOCK_GUID,
264               QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN +
265               QIO_CHANNEL_WEBSOCK_GUID_LEN + 1);
266 
267     /* hash and encode it */
268     if (qcrypto_hash_base64(QCRYPTO_HASH_ALG_SHA1,
269                             combined_key,
270                             QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN +
271                             QIO_CHANNEL_WEBSOCK_GUID_LEN,
272                             &accept,
273                             errp) < 0) {
274         return -1;
275     }
276 
277     response = g_strdup_printf(QIO_CHANNEL_WEBSOCK_HANDSHAKE_RESPONSE, accept);
278     responselen = strlen(response);
279     buffer_reserve(&ioc->encoutput, responselen);
280     buffer_append(&ioc->encoutput, response, responselen);
281 
282     g_free(accept);
283     g_free(response);
284 
285     return 0;
286 }
287 
288 static int qio_channel_websock_handshake_process(QIOChannelWebsock *ioc,
289                                                  char *buffer,
290                                                  Error **errp)
291 {
292     QIOChannelWebsockHTTPHeader hdrs[32];
293     size_t nhdrs = G_N_ELEMENTS(hdrs);
294     const char *protocols = NULL, *version = NULL, *key = NULL,
295         *host = NULL, *connection = NULL, *upgrade = NULL;
296 
297     nhdrs = qio_channel_websock_extract_headers(buffer, hdrs, nhdrs, errp);
298     if (!nhdrs) {
299         return -1;
300     }
301 
302     protocols = qio_channel_websock_find_header(
303         hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_PROTOCOL);
304     if (!protocols) {
305         error_setg(errp, "Missing websocket protocol header data");
306         return -1;
307     }
308 
309     version = qio_channel_websock_find_header(
310         hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_VERSION);
311     if (!version) {
312         error_setg(errp, "Missing websocket version header data");
313         return -1;
314     }
315 
316     key = qio_channel_websock_find_header(
317         hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_KEY);
318     if (!key) {
319         error_setg(errp, "Missing websocket key header data");
320         return -1;
321     }
322 
323     host = qio_channel_websock_find_header(
324         hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_HOST);
325     if (!host) {
326         error_setg(errp, "Missing websocket host header data");
327         return -1;
328     }
329 
330     connection = qio_channel_websock_find_header(
331         hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_CONNECTION);
332     if (!connection) {
333         error_setg(errp, "Missing websocket connection header data");
334         return -1;
335     }
336 
337     upgrade = qio_channel_websock_find_header(
338         hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_UPGRADE);
339     if (!upgrade) {
340         error_setg(errp, "Missing websocket upgrade header data");
341         return -1;
342     }
343 
344     if (!g_strrstr(protocols, QIO_CHANNEL_WEBSOCK_PROTOCOL_BINARY)) {
345         error_setg(errp, "No '%s' protocol is supported by client '%s'",
346                    QIO_CHANNEL_WEBSOCK_PROTOCOL_BINARY, protocols);
347         return -1;
348     }
349 
350     if (!g_str_equal(version, QIO_CHANNEL_WEBSOCK_SUPPORTED_VERSION)) {
351         error_setg(errp, "Version '%s' is not supported by client '%s'",
352                    QIO_CHANNEL_WEBSOCK_SUPPORTED_VERSION, version);
353         return -1;
354     }
355 
356     if (strlen(key) != QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN) {
357         error_setg(errp, "Key length '%zu' was not as expected '%d'",
358                    strlen(key), QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN);
359         return -1;
360     }
361 
362     if (!g_strrstr(connection, QIO_CHANNEL_WEBSOCK_CONNECTION_UPGRADE)) {
363         error_setg(errp, "No connection upgrade requested '%s'", connection);
364         return -1;
365     }
366 
367     if (!g_str_equal(upgrade, QIO_CHANNEL_WEBSOCK_UPGRADE_WEBSOCKET)) {
368         error_setg(errp, "Incorrect upgrade method '%s'", upgrade);
369         return -1;
370     }
371 
372     return qio_channel_websock_handshake_send_response(ioc, key, errp);
373 }
374 
375 static int qio_channel_websock_handshake_read(QIOChannelWebsock *ioc,
376                                               Error **errp)
377 {
378     char *handshake_end;
379     ssize_t ret;
380     /* Typical HTTP headers from novnc are 512 bytes, so limiting
381      * total header size to 4096 is easily enough. */
382     size_t want = 4096 - ioc->encinput.offset;
383     buffer_reserve(&ioc->encinput, want);
384     ret = qio_channel_read(ioc->master,
385                            (char *)buffer_end(&ioc->encinput), want, errp);
386     if (ret < 0) {
387         return -1;
388     }
389     ioc->encinput.offset += ret;
390 
391     handshake_end = g_strstr_len((char *)ioc->encinput.buffer,
392                                  ioc->encinput.offset,
393                                  QIO_CHANNEL_WEBSOCK_HANDSHAKE_END);
394     if (!handshake_end) {
395         if (ioc->encinput.offset >= 4096) {
396             error_setg(errp,
397                        "End of headers not found in first 4096 bytes");
398             return -1;
399         } else {
400             return 0;
401         }
402     }
403     *handshake_end = '\0';
404 
405     if (qio_channel_websock_handshake_process(ioc,
406                                               (char *)ioc->encinput.buffer,
407                                               errp) < 0) {
408         return -1;
409     }
410 
411     buffer_advance(&ioc->encinput,
412                    handshake_end - (char *)ioc->encinput.buffer +
413                    strlen(QIO_CHANNEL_WEBSOCK_HANDSHAKE_END));
414     return 1;
415 }
416 
417 static gboolean qio_channel_websock_handshake_send(QIOChannel *ioc,
418                                                    GIOCondition condition,
419                                                    gpointer user_data)
420 {
421     QIOTask *task = user_data;
422     QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(
423         qio_task_get_source(task));
424     Error *err = NULL;
425     ssize_t ret;
426 
427     ret = qio_channel_write(wioc->master,
428                             (char *)wioc->encoutput.buffer,
429                             wioc->encoutput.offset,
430                             &err);
431 
432     if (ret < 0) {
433         trace_qio_channel_websock_handshake_fail(ioc);
434         qio_task_set_error(task, err);
435         qio_task_complete(task);
436         return FALSE;
437     }
438 
439     buffer_advance(&wioc->encoutput, ret);
440     if (wioc->encoutput.offset == 0) {
441         trace_qio_channel_websock_handshake_complete(ioc);
442         qio_task_complete(task);
443         return FALSE;
444     }
445     trace_qio_channel_websock_handshake_pending(ioc, G_IO_OUT);
446     return TRUE;
447 }
448 
449 static gboolean qio_channel_websock_handshake_io(QIOChannel *ioc,
450                                                  GIOCondition condition,
451                                                  gpointer user_data)
452 {
453     QIOTask *task = user_data;
454     QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(
455         qio_task_get_source(task));
456     Error *err = NULL;
457     int ret;
458 
459     ret = qio_channel_websock_handshake_read(wioc, &err);
460     if (ret < 0) {
461         trace_qio_channel_websock_handshake_fail(ioc);
462         qio_task_set_error(task, err);
463         qio_task_complete(task);
464         return FALSE;
465     }
466     if (ret == 0) {
467         trace_qio_channel_websock_handshake_pending(ioc, G_IO_IN);
468         /* need more data still */
469         return TRUE;
470     }
471 
472     trace_qio_channel_websock_handshake_reply(ioc);
473     qio_channel_add_watch(
474         wioc->master,
475         G_IO_OUT,
476         qio_channel_websock_handshake_send,
477         task,
478         NULL);
479     return FALSE;
480 }
481 
482 
483 static void qio_channel_websock_encode(QIOChannelWebsock *ioc)
484 {
485     size_t header_size;
486     union {
487         char buf[QIO_CHANNEL_WEBSOCK_HEADER_LEN_64_BIT];
488         QIOChannelWebsockHeader ws;
489     } header;
490 
491     if (!ioc->rawoutput.offset) {
492         return;
493     }
494 
495     header.ws.b0 = (1 << QIO_CHANNEL_WEBSOCK_HEADER_SHIFT_FIN) |
496         (QIO_CHANNEL_WEBSOCK_OPCODE_BINARY_FRAME &
497          QIO_CHANNEL_WEBSOCK_HEADER_FIELD_OPCODE);
498     if (ioc->rawoutput.offset <
499         QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_THRESHOLD_7_BIT) {
500         header.ws.b1 = (uint8_t)ioc->rawoutput.offset;
501         header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_7_BIT;
502     } else if (ioc->rawoutput.offset <
503                QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_THRESHOLD_16_BIT) {
504         header.ws.b1 = QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_16_BIT;
505         header.ws.u.s16.l16 = cpu_to_be16((uint16_t)ioc->rawoutput.offset);
506         header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_16_BIT;
507     } else {
508         header.ws.b1 = QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_64_BIT;
509         header.ws.u.s64.l64 = cpu_to_be64(ioc->rawoutput.offset);
510         header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_64_BIT;
511     }
512     header_size -= QIO_CHANNEL_WEBSOCK_HEADER_LEN_MASK;
513 
514     buffer_reserve(&ioc->encoutput, header_size + ioc->rawoutput.offset);
515     buffer_append(&ioc->encoutput, header.buf, header_size);
516     buffer_append(&ioc->encoutput, ioc->rawoutput.buffer,
517                   ioc->rawoutput.offset);
518     buffer_reset(&ioc->rawoutput);
519 }
520 
521 
522 static ssize_t qio_channel_websock_decode_header(QIOChannelWebsock *ioc,
523                                                  Error **errp)
524 {
525     unsigned char opcode, fin, has_mask;
526     size_t header_size;
527     size_t payload_len;
528     QIOChannelWebsockHeader *header =
529         (QIOChannelWebsockHeader *)ioc->encinput.buffer;
530 
531     if (ioc->payload_remain) {
532         error_setg(errp,
533                    "Decoding header but %zu bytes of payload remain",
534                    ioc->payload_remain);
535         return -1;
536     }
537     if (ioc->encinput.offset < QIO_CHANNEL_WEBSOCK_HEADER_LEN_7_BIT) {
538         /* header not complete */
539         return QIO_CHANNEL_ERR_BLOCK;
540     }
541 
542     fin = (header->b0 & QIO_CHANNEL_WEBSOCK_HEADER_FIELD_FIN) >>
543         QIO_CHANNEL_WEBSOCK_HEADER_SHIFT_FIN;
544     opcode = header->b0 & QIO_CHANNEL_WEBSOCK_HEADER_FIELD_OPCODE;
545     has_mask = (header->b1 & QIO_CHANNEL_WEBSOCK_HEADER_FIELD_HAS_MASK) >>
546         QIO_CHANNEL_WEBSOCK_HEADER_SHIFT_HAS_MASK;
547     payload_len = header->b1 & QIO_CHANNEL_WEBSOCK_HEADER_FIELD_PAYLOAD_LEN;
548 
549     if (opcode == QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE) {
550         /* disconnect */
551         return 0;
552     }
553 
554     /* Websocket frame sanity check:
555      * * Websocket fragmentation is not supported.
556      * * All  websockets frames sent by a client have to be masked.
557      * * Only binary encoding is supported.
558      */
559     if (!fin) {
560         error_setg(errp, "websocket fragmentation is not supported");
561         return -1;
562     }
563     if (!has_mask) {
564         error_setg(errp, "websocket frames must be masked");
565         return -1;
566     }
567     if (opcode != QIO_CHANNEL_WEBSOCK_OPCODE_BINARY_FRAME) {
568         error_setg(errp, "only binary websocket frames are supported");
569         return -1;
570     }
571 
572     if (payload_len < QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_16_BIT) {
573         ioc->payload_remain = payload_len;
574         header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_7_BIT;
575         ioc->mask = header->u.m;
576     } else if (payload_len == QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_16_BIT &&
577                ioc->encinput.offset >= QIO_CHANNEL_WEBSOCK_HEADER_LEN_16_BIT) {
578         ioc->payload_remain = be16_to_cpu(header->u.s16.l16);
579         header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_16_BIT;
580         ioc->mask = header->u.s16.m16;
581     } else if (payload_len == QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_64_BIT &&
582                ioc->encinput.offset >= QIO_CHANNEL_WEBSOCK_HEADER_LEN_64_BIT) {
583         ioc->payload_remain = be64_to_cpu(header->u.s64.l64);
584         header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_64_BIT;
585         ioc->mask = header->u.s64.m64;
586     } else {
587         /* header not complete */
588         return QIO_CHANNEL_ERR_BLOCK;
589     }
590 
591     buffer_advance(&ioc->encinput, header_size);
592     return 1;
593 }
594 
595 
596 static ssize_t qio_channel_websock_decode_payload(QIOChannelWebsock *ioc,
597                                                   Error **errp)
598 {
599     size_t i;
600     size_t payload_len;
601     uint32_t *payload32;
602 
603     if (!ioc->payload_remain) {
604         error_setg(errp,
605                    "Decoding payload but no bytes of payload remain");
606         return -1;
607     }
608 
609     /* If we aren't at the end of the payload, then drop
610      * off the last bytes, so we're always multiple of 4
611      * for purpose of unmasking, except at end of payload
612      */
613     if (ioc->encinput.offset < ioc->payload_remain) {
614         payload_len = ioc->encinput.offset - (ioc->encinput.offset % 4);
615     } else {
616         payload_len = ioc->payload_remain;
617     }
618     if (payload_len == 0) {
619         return QIO_CHANNEL_ERR_BLOCK;
620     }
621 
622     ioc->payload_remain -= payload_len;
623 
624     /* unmask frame */
625     /* process 1 frame (32 bit op) */
626     payload32 = (uint32_t *)ioc->encinput.buffer;
627     for (i = 0; i < payload_len / 4; i++) {
628         payload32[i] ^= ioc->mask.u;
629     }
630     /* process the remaining bytes (if any) */
631     for (i *= 4; i < payload_len; i++) {
632         ioc->encinput.buffer[i] ^= ioc->mask.c[i % 4];
633     }
634 
635     buffer_reserve(&ioc->rawinput, payload_len);
636     buffer_append(&ioc->rawinput, ioc->encinput.buffer, payload_len);
637     buffer_advance(&ioc->encinput, payload_len);
638     return payload_len;
639 }
640 
641 
642 QIOChannelWebsock *
643 qio_channel_websock_new_server(QIOChannel *master)
644 {
645     QIOChannelWebsock *wioc;
646     QIOChannel *ioc;
647 
648     wioc = QIO_CHANNEL_WEBSOCK(object_new(TYPE_QIO_CHANNEL_WEBSOCK));
649     ioc = QIO_CHANNEL(wioc);
650 
651     wioc->master = master;
652     if (qio_channel_has_feature(master, QIO_CHANNEL_FEATURE_SHUTDOWN)) {
653         qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_SHUTDOWN);
654     }
655     object_ref(OBJECT(master));
656 
657     trace_qio_channel_websock_new_server(wioc, master);
658     return wioc;
659 }
660 
661 void qio_channel_websock_handshake(QIOChannelWebsock *ioc,
662                                    QIOTaskFunc func,
663                                    gpointer opaque,
664                                    GDestroyNotify destroy)
665 {
666     QIOTask *task;
667 
668     task = qio_task_new(OBJECT(ioc),
669                         func,
670                         opaque,
671                         destroy);
672 
673     trace_qio_channel_websock_handshake_start(ioc);
674     trace_qio_channel_websock_handshake_pending(ioc, G_IO_IN);
675     qio_channel_add_watch(ioc->master,
676                           G_IO_IN,
677                           qio_channel_websock_handshake_io,
678                           task,
679                           NULL);
680 }
681 
682 
683 static void qio_channel_websock_finalize(Object *obj)
684 {
685     QIOChannelWebsock *ioc = QIO_CHANNEL_WEBSOCK(obj);
686 
687     buffer_free(&ioc->encinput);
688     buffer_free(&ioc->encoutput);
689     buffer_free(&ioc->rawinput);
690     buffer_free(&ioc->rawoutput);
691     object_unref(OBJECT(ioc->master));
692     if (ioc->io_tag) {
693         g_source_remove(ioc->io_tag);
694     }
695     if (ioc->io_err) {
696         error_free(ioc->io_err);
697     }
698 }
699 
700 
701 static ssize_t qio_channel_websock_read_wire(QIOChannelWebsock *ioc,
702                                              Error **errp)
703 {
704     ssize_t ret;
705 
706     if (ioc->encinput.offset < 4096) {
707         size_t want = 4096 - ioc->encinput.offset;
708 
709         buffer_reserve(&ioc->encinput, want);
710         ret = qio_channel_read(ioc->master,
711                                (char *)ioc->encinput.buffer +
712                                ioc->encinput.offset,
713                                want,
714                                errp);
715         if (ret < 0) {
716             return ret;
717         }
718         if (ret == 0 &&
719             ioc->encinput.offset == 0) {
720             return 0;
721         }
722         ioc->encinput.offset += ret;
723     }
724 
725     while (ioc->encinput.offset != 0) {
726         if (ioc->payload_remain == 0) {
727             ret = qio_channel_websock_decode_header(ioc, errp);
728             if (ret < 0) {
729                 return ret;
730             }
731             if (ret == 0) {
732                 ioc->io_eof = TRUE;
733                 break;
734             }
735         }
736 
737         ret = qio_channel_websock_decode_payload(ioc, errp);
738         if (ret < 0) {
739             return ret;
740         }
741     }
742     return 1;
743 }
744 
745 
746 static ssize_t qio_channel_websock_write_wire(QIOChannelWebsock *ioc,
747                                               Error **errp)
748 {
749     ssize_t ret;
750     ssize_t done = 0;
751     qio_channel_websock_encode(ioc);
752 
753     while (ioc->encoutput.offset > 0) {
754         ret = qio_channel_write(ioc->master,
755                                 (char *)ioc->encoutput.buffer,
756                                 ioc->encoutput.offset,
757                                 errp);
758         if (ret < 0) {
759             if (ret == QIO_CHANNEL_ERR_BLOCK &&
760                 done > 0) {
761                 return done;
762             } else {
763                 return ret;
764             }
765         }
766         buffer_advance(&ioc->encoutput, ret);
767         done += ret;
768     }
769     return done;
770 }
771 
772 
773 static void qio_channel_websock_flush_free(gpointer user_data)
774 {
775     QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(user_data);
776     object_unref(OBJECT(wioc));
777 }
778 
779 static void qio_channel_websock_set_watch(QIOChannelWebsock *ioc);
780 
781 static gboolean qio_channel_websock_flush(QIOChannel *ioc,
782                                           GIOCondition condition,
783                                           gpointer user_data)
784 {
785     QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(user_data);
786     ssize_t ret;
787 
788     if (condition & G_IO_OUT) {
789         ret = qio_channel_websock_write_wire(wioc, &wioc->io_err);
790         if (ret < 0) {
791             goto cleanup;
792         }
793     }
794 
795     if (condition & G_IO_IN) {
796         ret = qio_channel_websock_read_wire(wioc, &wioc->io_err);
797         if (ret < 0) {
798             goto cleanup;
799         }
800     }
801 
802  cleanup:
803     qio_channel_websock_set_watch(wioc);
804     return FALSE;
805 }
806 
807 
808 static void qio_channel_websock_unset_watch(QIOChannelWebsock *ioc)
809 {
810     if (ioc->io_tag) {
811         g_source_remove(ioc->io_tag);
812         ioc->io_tag = 0;
813     }
814 }
815 
816 static void qio_channel_websock_set_watch(QIOChannelWebsock *ioc)
817 {
818     GIOCondition cond = 0;
819 
820     qio_channel_websock_unset_watch(ioc);
821 
822     if (ioc->io_err) {
823         return;
824     }
825 
826     if (ioc->encoutput.offset) {
827         cond |= G_IO_OUT;
828     }
829     if (ioc->encinput.offset < QIO_CHANNEL_WEBSOCK_MAX_BUFFER &&
830         !ioc->io_eof) {
831         cond |= G_IO_IN;
832     }
833 
834     if (cond) {
835         object_ref(OBJECT(ioc));
836         ioc->io_tag =
837             qio_channel_add_watch(ioc->master,
838                                   cond,
839                                   qio_channel_websock_flush,
840                                   ioc,
841                                   qio_channel_websock_flush_free);
842     }
843 }
844 
845 
846 static ssize_t qio_channel_websock_readv(QIOChannel *ioc,
847                                          const struct iovec *iov,
848                                          size_t niov,
849                                          int **fds,
850                                          size_t *nfds,
851                                          Error **errp)
852 {
853     QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc);
854     size_t i;
855     ssize_t got = 0;
856     ssize_t ret;
857 
858     if (wioc->io_err) {
859         error_propagate(errp, error_copy(wioc->io_err));
860         return -1;
861     }
862 
863     if (!wioc->rawinput.offset) {
864         ret = qio_channel_websock_read_wire(QIO_CHANNEL_WEBSOCK(ioc), errp);
865         if (ret < 0) {
866             return ret;
867         }
868     }
869 
870     for (i = 0 ; i < niov ; i++) {
871         size_t want = iov[i].iov_len;
872         if (want > (wioc->rawinput.offset - got)) {
873             want = (wioc->rawinput.offset - got);
874         }
875 
876         memcpy(iov[i].iov_base,
877                wioc->rawinput.buffer + got,
878                want);
879         got += want;
880 
881         if (want < iov[i].iov_len) {
882             break;
883         }
884     }
885 
886     buffer_advance(&wioc->rawinput, got);
887     qio_channel_websock_set_watch(wioc);
888     return got;
889 }
890 
891 
892 static ssize_t qio_channel_websock_writev(QIOChannel *ioc,
893                                           const struct iovec *iov,
894                                           size_t niov,
895                                           int *fds,
896                                           size_t nfds,
897                                           Error **errp)
898 {
899     QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc);
900     size_t i;
901     ssize_t done = 0;
902     ssize_t ret;
903 
904     if (wioc->io_err) {
905         error_propagate(errp, error_copy(wioc->io_err));
906         return -1;
907     }
908 
909     if (wioc->io_eof) {
910         error_setg(errp, "%s", "Broken pipe");
911         return -1;
912     }
913 
914     for (i = 0; i < niov; i++) {
915         size_t want = iov[i].iov_len;
916         if ((want + wioc->rawoutput.offset) > QIO_CHANNEL_WEBSOCK_MAX_BUFFER) {
917             want = (QIO_CHANNEL_WEBSOCK_MAX_BUFFER - wioc->rawoutput.offset);
918         }
919         if (want == 0) {
920             goto done;
921         }
922 
923         buffer_reserve(&wioc->rawoutput, want);
924         buffer_append(&wioc->rawoutput, iov[i].iov_base, want);
925         done += want;
926         if (want < iov[i].iov_len) {
927             break;
928         }
929     }
930 
931  done:
932     ret = qio_channel_websock_write_wire(wioc, errp);
933     if (ret < 0 &&
934         ret != QIO_CHANNEL_ERR_BLOCK) {
935         qio_channel_websock_unset_watch(wioc);
936         return -1;
937     }
938 
939     qio_channel_websock_set_watch(wioc);
940 
941     if (done == 0) {
942         return QIO_CHANNEL_ERR_BLOCK;
943     }
944 
945     return done;
946 }
947 
948 static int qio_channel_websock_set_blocking(QIOChannel *ioc,
949                                             bool enabled,
950                                             Error **errp)
951 {
952     QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc);
953 
954     qio_channel_set_blocking(wioc->master, enabled, errp);
955     return 0;
956 }
957 
958 static void qio_channel_websock_set_delay(QIOChannel *ioc,
959                                           bool enabled)
960 {
961     QIOChannelWebsock *tioc = QIO_CHANNEL_WEBSOCK(ioc);
962 
963     qio_channel_set_delay(tioc->master, enabled);
964 }
965 
966 static void qio_channel_websock_set_cork(QIOChannel *ioc,
967                                          bool enabled)
968 {
969     QIOChannelWebsock *tioc = QIO_CHANNEL_WEBSOCK(ioc);
970 
971     qio_channel_set_cork(tioc->master, enabled);
972 }
973 
974 static int qio_channel_websock_shutdown(QIOChannel *ioc,
975                                         QIOChannelShutdown how,
976                                         Error **errp)
977 {
978     QIOChannelWebsock *tioc = QIO_CHANNEL_WEBSOCK(ioc);
979 
980     return qio_channel_shutdown(tioc->master, how, errp);
981 }
982 
983 static int qio_channel_websock_close(QIOChannel *ioc,
984                                      Error **errp)
985 {
986     QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc);
987 
988     return qio_channel_close(wioc->master, errp);
989 }
990 
991 typedef struct QIOChannelWebsockSource QIOChannelWebsockSource;
992 struct QIOChannelWebsockSource {
993     GSource parent;
994     QIOChannelWebsock *wioc;
995     GIOCondition condition;
996 };
997 
998 static gboolean
999 qio_channel_websock_source_prepare(GSource *source,
1000                                    gint *timeout)
1001 {
1002     QIOChannelWebsockSource *wsource = (QIOChannelWebsockSource *)source;
1003     GIOCondition cond = 0;
1004     *timeout = -1;
1005 
1006     if (wsource->wioc->rawinput.offset) {
1007         cond |= G_IO_IN;
1008     }
1009     if (wsource->wioc->rawoutput.offset < QIO_CHANNEL_WEBSOCK_MAX_BUFFER) {
1010         cond |= G_IO_OUT;
1011     }
1012 
1013     return cond & wsource->condition;
1014 }
1015 
1016 static gboolean
1017 qio_channel_websock_source_check(GSource *source)
1018 {
1019     QIOChannelWebsockSource *wsource = (QIOChannelWebsockSource *)source;
1020     GIOCondition cond = 0;
1021 
1022     if (wsource->wioc->rawinput.offset) {
1023         cond |= G_IO_IN;
1024     }
1025     if (wsource->wioc->rawoutput.offset < QIO_CHANNEL_WEBSOCK_MAX_BUFFER) {
1026         cond |= G_IO_OUT;
1027     }
1028 
1029     return cond & wsource->condition;
1030 }
1031 
1032 static gboolean
1033 qio_channel_websock_source_dispatch(GSource *source,
1034                                     GSourceFunc callback,
1035                                     gpointer user_data)
1036 {
1037     QIOChannelFunc func = (QIOChannelFunc)callback;
1038     QIOChannelWebsockSource *wsource = (QIOChannelWebsockSource *)source;
1039     GIOCondition cond = 0;
1040 
1041     if (wsource->wioc->rawinput.offset) {
1042         cond |= G_IO_IN;
1043     }
1044     if (wsource->wioc->rawoutput.offset < QIO_CHANNEL_WEBSOCK_MAX_BUFFER) {
1045         cond |= G_IO_OUT;
1046     }
1047 
1048     return (*func)(QIO_CHANNEL(wsource->wioc),
1049                    (cond & wsource->condition),
1050                    user_data);
1051 }
1052 
1053 static void
1054 qio_channel_websock_source_finalize(GSource *source)
1055 {
1056     QIOChannelWebsockSource *ssource = (QIOChannelWebsockSource *)source;
1057 
1058     object_unref(OBJECT(ssource->wioc));
1059 }
1060 
1061 GSourceFuncs qio_channel_websock_source_funcs = {
1062     qio_channel_websock_source_prepare,
1063     qio_channel_websock_source_check,
1064     qio_channel_websock_source_dispatch,
1065     qio_channel_websock_source_finalize
1066 };
1067 
1068 static GSource *qio_channel_websock_create_watch(QIOChannel *ioc,
1069                                                  GIOCondition condition)
1070 {
1071     QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc);
1072     QIOChannelWebsockSource *ssource;
1073     GSource *source;
1074 
1075     source = g_source_new(&qio_channel_websock_source_funcs,
1076                           sizeof(QIOChannelWebsockSource));
1077     ssource = (QIOChannelWebsockSource *)source;
1078 
1079     ssource->wioc = wioc;
1080     object_ref(OBJECT(wioc));
1081 
1082     ssource->condition = condition;
1083 
1084     qio_channel_websock_set_watch(wioc);
1085     return source;
1086 }
1087 
1088 static void qio_channel_websock_class_init(ObjectClass *klass,
1089                                            void *class_data G_GNUC_UNUSED)
1090 {
1091     QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass);
1092 
1093     ioc_klass->io_writev = qio_channel_websock_writev;
1094     ioc_klass->io_readv = qio_channel_websock_readv;
1095     ioc_klass->io_set_blocking = qio_channel_websock_set_blocking;
1096     ioc_klass->io_set_cork = qio_channel_websock_set_cork;
1097     ioc_klass->io_set_delay = qio_channel_websock_set_delay;
1098     ioc_klass->io_close = qio_channel_websock_close;
1099     ioc_klass->io_shutdown = qio_channel_websock_shutdown;
1100     ioc_klass->io_create_watch = qio_channel_websock_create_watch;
1101 }
1102 
1103 static const TypeInfo qio_channel_websock_info = {
1104     .parent = TYPE_QIO_CHANNEL,
1105     .name = TYPE_QIO_CHANNEL_WEBSOCK,
1106     .instance_size = sizeof(QIOChannelWebsock),
1107     .instance_finalize = qio_channel_websock_finalize,
1108     .class_init = qio_channel_websock_class_init,
1109 };
1110 
1111 static void qio_channel_websock_register_types(void)
1112 {
1113     type_register_static(&qio_channel_websock_info);
1114 }
1115 
1116 type_init(qio_channel_websock_register_types);
1117