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