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