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