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