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