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