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.1 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 #include "qemu/iov.h" 28 #include "qemu/module.h" 29 30 /* Max amount to allow in rawinput/encoutput buffers */ 31 #define QIO_CHANNEL_WEBSOCK_MAX_BUFFER 8192 32 33 #define QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN 24 34 #define QIO_CHANNEL_WEBSOCK_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" 35 #define QIO_CHANNEL_WEBSOCK_GUID_LEN (sizeof(QIO_CHANNEL_WEBSOCK_GUID) - 1) 36 37 #define QIO_CHANNEL_WEBSOCK_HEADER_PROTOCOL "sec-websocket-protocol" 38 #define QIO_CHANNEL_WEBSOCK_HEADER_VERSION "sec-websocket-version" 39 #define QIO_CHANNEL_WEBSOCK_HEADER_KEY "sec-websocket-key" 40 #define QIO_CHANNEL_WEBSOCK_HEADER_UPGRADE "upgrade" 41 #define QIO_CHANNEL_WEBSOCK_HEADER_HOST "host" 42 #define QIO_CHANNEL_WEBSOCK_HEADER_CONNECTION "connection" 43 44 #define QIO_CHANNEL_WEBSOCK_PROTOCOL_BINARY "binary" 45 #define QIO_CHANNEL_WEBSOCK_CONNECTION_UPGRADE "Upgrade" 46 #define QIO_CHANNEL_WEBSOCK_UPGRADE_WEBSOCKET "websocket" 47 48 #define QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_COMMON \ 49 "Server: QEMU VNC\r\n" \ 50 "Date: %s\r\n" 51 52 #define QIO_CHANNEL_WEBSOCK_HANDSHAKE_WITH_PROTO_RES_OK \ 53 "HTTP/1.1 101 Switching Protocols\r\n" \ 54 QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_COMMON \ 55 "Upgrade: websocket\r\n" \ 56 "Connection: Upgrade\r\n" \ 57 "Sec-WebSocket-Accept: %s\r\n" \ 58 "Sec-WebSocket-Protocol: binary\r\n" \ 59 "\r\n" 60 #define QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_OK \ 61 "HTTP/1.1 101 Switching Protocols\r\n" \ 62 QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_COMMON \ 63 "Upgrade: websocket\r\n" \ 64 "Connection: Upgrade\r\n" \ 65 "Sec-WebSocket-Accept: %s\r\n" \ 66 "\r\n" 67 #define QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_NOT_FOUND \ 68 "HTTP/1.1 404 Not Found\r\n" \ 69 QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_COMMON \ 70 "Connection: close\r\n" \ 71 "\r\n" 72 #define QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_BAD_REQUEST \ 73 "HTTP/1.1 400 Bad Request\r\n" \ 74 QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_COMMON \ 75 "Connection: close\r\n" \ 76 "Sec-WebSocket-Version: " \ 77 QIO_CHANNEL_WEBSOCK_SUPPORTED_VERSION \ 78 "\r\n" 79 #define QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_SERVER_ERR \ 80 "HTTP/1.1 500 Internal Server Error\r\n" \ 81 QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_COMMON \ 82 "Connection: close\r\n" \ 83 "\r\n" 84 #define QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_TOO_LARGE \ 85 "HTTP/1.1 403 Request Entity Too Large\r\n" \ 86 QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_COMMON \ 87 "Connection: close\r\n" \ 88 "\r\n" 89 #define QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM "\r\n" 90 #define QIO_CHANNEL_WEBSOCK_HANDSHAKE_END "\r\n\r\n" 91 #define QIO_CHANNEL_WEBSOCK_SUPPORTED_VERSION "13" 92 #define QIO_CHANNEL_WEBSOCK_HTTP_METHOD "GET" 93 #define QIO_CHANNEL_WEBSOCK_HTTP_PATH "/" 94 #define QIO_CHANNEL_WEBSOCK_HTTP_VERSION "HTTP/1.1" 95 96 /* The websockets packet header is variable length 97 * depending on the size of the payload... */ 98 99 /* ...length when using 7-bit payload length */ 100 #define QIO_CHANNEL_WEBSOCK_HEADER_LEN_7_BIT 6 101 /* ...length when using 16-bit payload length */ 102 #define QIO_CHANNEL_WEBSOCK_HEADER_LEN_16_BIT 8 103 /* ...length when using 64-bit payload length */ 104 #define QIO_CHANNEL_WEBSOCK_HEADER_LEN_64_BIT 14 105 106 /* Length of the optional data mask field in header */ 107 #define QIO_CHANNEL_WEBSOCK_HEADER_LEN_MASK 4 108 109 /* Maximum length that can fit in 7-bit payload size */ 110 #define QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_THRESHOLD_7_BIT 126 111 /* Maximum length that can fit in 16-bit payload size */ 112 #define QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_THRESHOLD_16_BIT 65536 113 114 /* Magic 7-bit length to indicate use of 16-bit payload length */ 115 #define QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_16_BIT 126 116 /* Magic 7-bit length to indicate use of 64-bit payload length */ 117 #define QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_64_BIT 127 118 119 /* Bitmasks for accessing header fields */ 120 #define QIO_CHANNEL_WEBSOCK_HEADER_FIELD_FIN 0x80 121 #define QIO_CHANNEL_WEBSOCK_HEADER_FIELD_OPCODE 0x0f 122 #define QIO_CHANNEL_WEBSOCK_HEADER_FIELD_HAS_MASK 0x80 123 #define QIO_CHANNEL_WEBSOCK_HEADER_FIELD_PAYLOAD_LEN 0x7f 124 #define QIO_CHANNEL_WEBSOCK_CONTROL_OPCODE_MASK 0x8 125 126 typedef struct QIOChannelWebsockHeader QIOChannelWebsockHeader; 127 128 struct QEMU_PACKED QIOChannelWebsockHeader { 129 unsigned char b0; 130 unsigned char b1; 131 union { 132 struct QEMU_PACKED { 133 uint16_t l16; 134 QIOChannelWebsockMask m16; 135 } s16; 136 struct QEMU_PACKED { 137 uint64_t l64; 138 QIOChannelWebsockMask m64; 139 } s64; 140 QIOChannelWebsockMask m; 141 } u; 142 }; 143 144 typedef struct QIOChannelWebsockHTTPHeader QIOChannelWebsockHTTPHeader; 145 146 struct QIOChannelWebsockHTTPHeader { 147 char *name; 148 char *value; 149 }; 150 151 enum { 152 QIO_CHANNEL_WEBSOCK_OPCODE_CONTINUATION = 0x0, 153 QIO_CHANNEL_WEBSOCK_OPCODE_TEXT_FRAME = 0x1, 154 QIO_CHANNEL_WEBSOCK_OPCODE_BINARY_FRAME = 0x2, 155 QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE = 0x8, 156 QIO_CHANNEL_WEBSOCK_OPCODE_PING = 0x9, 157 QIO_CHANNEL_WEBSOCK_OPCODE_PONG = 0xA 158 }; 159 160 static void G_GNUC_PRINTF(2, 3) 161 qio_channel_websock_handshake_send_res(QIOChannelWebsock *ioc, 162 const char *resmsg, 163 ...) 164 { 165 va_list vargs; 166 char *response; 167 size_t responselen; 168 169 va_start(vargs, resmsg); 170 response = g_strdup_vprintf(resmsg, vargs); 171 responselen = strlen(response); 172 buffer_reserve(&ioc->encoutput, responselen); 173 buffer_append(&ioc->encoutput, response, responselen); 174 g_free(response); 175 va_end(vargs); 176 } 177 178 static gchar *qio_channel_websock_date_str(void) 179 { 180 g_autoptr(GDateTime) now = g_date_time_new_now_utc(); 181 182 return g_date_time_format(now, "%a, %d %b %Y %H:%M:%S GMT"); 183 } 184 185 static void qio_channel_websock_handshake_send_res_err(QIOChannelWebsock *ioc, 186 const char *resdata) 187 { 188 char *date = qio_channel_websock_date_str(); 189 qio_channel_websock_handshake_send_res(ioc, resdata, date); 190 g_free(date); 191 } 192 193 enum { 194 QIO_CHANNEL_WEBSOCK_STATUS_NORMAL = 1000, 195 QIO_CHANNEL_WEBSOCK_STATUS_PROTOCOL_ERR = 1002, 196 QIO_CHANNEL_WEBSOCK_STATUS_INVALID_DATA = 1003, 197 QIO_CHANNEL_WEBSOCK_STATUS_POLICY = 1008, 198 QIO_CHANNEL_WEBSOCK_STATUS_TOO_LARGE = 1009, 199 QIO_CHANNEL_WEBSOCK_STATUS_SERVER_ERR = 1011, 200 }; 201 202 static size_t 203 qio_channel_websock_extract_headers(QIOChannelWebsock *ioc, 204 char *buffer, 205 QIOChannelWebsockHTTPHeader *hdrs, 206 size_t nhdrsalloc, 207 Error **errp) 208 { 209 char *nl, *sep, *tmp; 210 size_t nhdrs = 0; 211 212 /* 213 * First parse the HTTP protocol greeting of format: 214 * 215 * $METHOD $PATH $VERSION 216 * 217 * e.g. 218 * 219 * GET / HTTP/1.1 220 */ 221 222 nl = strstr(buffer, QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM); 223 if (!nl) { 224 error_setg(errp, "Missing HTTP header delimiter"); 225 goto bad_request; 226 } 227 *nl = '\0'; 228 trace_qio_channel_websock_http_greeting(ioc, buffer); 229 230 tmp = strchr(buffer, ' '); 231 if (!tmp) { 232 error_setg(errp, "Missing HTTP path delimiter"); 233 return 0; 234 } 235 *tmp = '\0'; 236 237 if (!g_str_equal(buffer, QIO_CHANNEL_WEBSOCK_HTTP_METHOD)) { 238 error_setg(errp, "Unsupported HTTP method %s", buffer); 239 goto bad_request; 240 } 241 242 buffer = tmp + 1; 243 tmp = strchr(buffer, ' '); 244 if (!tmp) { 245 error_setg(errp, "Missing HTTP version delimiter"); 246 goto bad_request; 247 } 248 *tmp = '\0'; 249 250 if (!g_str_equal(buffer, QIO_CHANNEL_WEBSOCK_HTTP_PATH)) { 251 qio_channel_websock_handshake_send_res_err( 252 ioc, QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_NOT_FOUND); 253 error_setg(errp, "Unexpected HTTP path %s", buffer); 254 return 0; 255 } 256 257 buffer = tmp + 1; 258 259 if (!g_str_equal(buffer, QIO_CHANNEL_WEBSOCK_HTTP_VERSION)) { 260 error_setg(errp, "Unsupported HTTP version %s", buffer); 261 goto bad_request; 262 } 263 264 buffer = nl + strlen(QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM); 265 266 /* 267 * Now parse all the header fields of format 268 * 269 * $NAME: $VALUE 270 * 271 * e.g. 272 * 273 * Cache-control: no-cache 274 */ 275 do { 276 QIOChannelWebsockHTTPHeader *hdr; 277 278 nl = strstr(buffer, QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM); 279 if (nl) { 280 *nl = '\0'; 281 } 282 283 sep = strchr(buffer, ':'); 284 if (!sep) { 285 error_setg(errp, "Malformed HTTP header"); 286 goto bad_request; 287 } 288 *sep = '\0'; 289 sep++; 290 while (*sep == ' ') { 291 sep++; 292 } 293 294 if (nhdrs >= nhdrsalloc) { 295 error_setg(errp, "Too many HTTP headers"); 296 goto bad_request; 297 } 298 299 hdr = &hdrs[nhdrs++]; 300 hdr->name = buffer; 301 hdr->value = sep; 302 303 /* Canonicalize header name for easier identification later */ 304 for (tmp = hdr->name; *tmp; tmp++) { 305 *tmp = g_ascii_tolower(*tmp); 306 } 307 308 if (nl) { 309 buffer = nl + strlen(QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM); 310 } 311 } while (nl != NULL); 312 313 return nhdrs; 314 315 bad_request: 316 qio_channel_websock_handshake_send_res_err( 317 ioc, QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_BAD_REQUEST); 318 return 0; 319 } 320 321 static const char * 322 qio_channel_websock_find_header(QIOChannelWebsockHTTPHeader *hdrs, 323 size_t nhdrs, 324 const char *name) 325 { 326 size_t i; 327 328 for (i = 0; i < nhdrs; i++) { 329 if (g_str_equal(hdrs[i].name, name)) { 330 return hdrs[i].value; 331 } 332 } 333 334 return NULL; 335 } 336 337 338 static void qio_channel_websock_handshake_send_res_ok(QIOChannelWebsock *ioc, 339 const char *key, 340 const bool use_protocols, 341 Error **errp) 342 { 343 char combined_key[QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN + 344 QIO_CHANNEL_WEBSOCK_GUID_LEN + 1]; 345 char *accept = NULL; 346 char *date = NULL; 347 348 g_strlcpy(combined_key, key, QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN + 1); 349 g_strlcat(combined_key, QIO_CHANNEL_WEBSOCK_GUID, 350 QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN + 351 QIO_CHANNEL_WEBSOCK_GUID_LEN + 1); 352 353 /* hash and encode it */ 354 if (qcrypto_hash_base64(QCRYPTO_HASH_ALGO_SHA1, 355 combined_key, 356 QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN + 357 QIO_CHANNEL_WEBSOCK_GUID_LEN, 358 &accept, 359 errp) < 0) { 360 qio_channel_websock_handshake_send_res_err( 361 ioc, QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_SERVER_ERR); 362 return; 363 } 364 365 date = qio_channel_websock_date_str(); 366 if (use_protocols) { 367 qio_channel_websock_handshake_send_res( 368 ioc, QIO_CHANNEL_WEBSOCK_HANDSHAKE_WITH_PROTO_RES_OK, 369 date, accept); 370 } else { 371 qio_channel_websock_handshake_send_res( 372 ioc, QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_OK, date, accept); 373 } 374 375 g_free(date); 376 g_free(accept); 377 } 378 379 static void qio_channel_websock_handshake_process(QIOChannelWebsock *ioc, 380 char *buffer, 381 Error **errp) 382 { 383 QIOChannelWebsockHTTPHeader hdrs[32]; 384 size_t nhdrs = G_N_ELEMENTS(hdrs); 385 const char *protocols = NULL, *version = NULL, *key = NULL, 386 *host = NULL, *connection = NULL, *upgrade = NULL; 387 char **connectionv; 388 bool upgraded = false; 389 size_t i; 390 391 nhdrs = qio_channel_websock_extract_headers(ioc, buffer, hdrs, nhdrs, errp); 392 if (!nhdrs) { 393 return; 394 } 395 396 protocols = qio_channel_websock_find_header( 397 hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_PROTOCOL); 398 399 version = qio_channel_websock_find_header( 400 hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_VERSION); 401 if (!version) { 402 error_setg(errp, "Missing websocket version header data"); 403 goto bad_request; 404 } 405 406 key = qio_channel_websock_find_header( 407 hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_KEY); 408 if (!key) { 409 error_setg(errp, "Missing websocket key header data"); 410 goto bad_request; 411 } 412 413 host = qio_channel_websock_find_header( 414 hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_HOST); 415 if (!host) { 416 error_setg(errp, "Missing websocket host header data"); 417 goto bad_request; 418 } 419 420 connection = qio_channel_websock_find_header( 421 hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_CONNECTION); 422 if (!connection) { 423 error_setg(errp, "Missing websocket connection header data"); 424 goto bad_request; 425 } 426 427 upgrade = qio_channel_websock_find_header( 428 hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_UPGRADE); 429 if (!upgrade) { 430 error_setg(errp, "Missing websocket upgrade header data"); 431 goto bad_request; 432 } 433 434 trace_qio_channel_websock_http_request(ioc, protocols, version, 435 host, connection, upgrade, key); 436 437 if (protocols) { 438 if (!g_strrstr(protocols, QIO_CHANNEL_WEBSOCK_PROTOCOL_BINARY)) { 439 error_setg(errp, "No '%s' protocol is supported by client '%s'", 440 QIO_CHANNEL_WEBSOCK_PROTOCOL_BINARY, protocols); 441 goto bad_request; 442 } 443 } 444 445 if (!g_str_equal(version, QIO_CHANNEL_WEBSOCK_SUPPORTED_VERSION)) { 446 error_setg(errp, "Version '%s' is not supported by client '%s'", 447 QIO_CHANNEL_WEBSOCK_SUPPORTED_VERSION, version); 448 goto bad_request; 449 } 450 451 if (strlen(key) != QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN) { 452 error_setg(errp, "Key length '%zu' was not as expected '%d'", 453 strlen(key), QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN); 454 goto bad_request; 455 } 456 457 connectionv = g_strsplit(connection, ",", 0); 458 for (i = 0; connectionv != NULL && connectionv[i] != NULL; i++) { 459 g_strstrip(connectionv[i]); 460 if (strcasecmp(connectionv[i], 461 QIO_CHANNEL_WEBSOCK_CONNECTION_UPGRADE) == 0) { 462 upgraded = true; 463 } 464 } 465 g_strfreev(connectionv); 466 if (!upgraded) { 467 error_setg(errp, "No connection upgrade requested '%s'", connection); 468 goto bad_request; 469 } 470 471 if (strcasecmp(upgrade, QIO_CHANNEL_WEBSOCK_UPGRADE_WEBSOCKET) != 0) { 472 error_setg(errp, "Incorrect upgrade method '%s'", upgrade); 473 goto bad_request; 474 } 475 476 qio_channel_websock_handshake_send_res_ok(ioc, key, !!protocols, errp); 477 return; 478 479 bad_request: 480 qio_channel_websock_handshake_send_res_err( 481 ioc, QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_BAD_REQUEST); 482 } 483 484 static int qio_channel_websock_handshake_read(QIOChannelWebsock *ioc, 485 Error **errp) 486 { 487 char *handshake_end; 488 ssize_t ret; 489 /* Typical HTTP headers from novnc are 512 bytes, so limiting 490 * total header size to 4096 is easily enough. */ 491 size_t want = 4096 - ioc->encinput.offset; 492 buffer_reserve(&ioc->encinput, want); 493 ret = qio_channel_read(ioc->master, 494 (char *)buffer_end(&ioc->encinput), want, errp); 495 if (ret < 0) { 496 return -1; 497 } 498 ioc->encinput.offset += ret; 499 500 handshake_end = g_strstr_len((char *)ioc->encinput.buffer, 501 ioc->encinput.offset, 502 QIO_CHANNEL_WEBSOCK_HANDSHAKE_END); 503 if (!handshake_end) { 504 if (ioc->encinput.offset >= 4096) { 505 qio_channel_websock_handshake_send_res_err( 506 ioc, QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_TOO_LARGE); 507 error_setg(errp, 508 "End of headers not found in first 4096 bytes"); 509 return 1; 510 } else if (ret == 0) { 511 error_setg(errp, 512 "End of headers not found before connection closed"); 513 return -1; 514 } 515 return 0; 516 } 517 *handshake_end = '\0'; 518 519 qio_channel_websock_handshake_process(ioc, 520 (char *)ioc->encinput.buffer, 521 errp); 522 523 buffer_advance(&ioc->encinput, 524 handshake_end - (char *)ioc->encinput.buffer + 525 strlen(QIO_CHANNEL_WEBSOCK_HANDSHAKE_END)); 526 return 1; 527 } 528 529 static gboolean qio_channel_websock_handshake_send(QIOChannel *ioc, 530 GIOCondition condition, 531 gpointer user_data) 532 { 533 QIOTask *task = user_data; 534 QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK( 535 qio_task_get_source(task)); 536 Error *err = NULL; 537 ssize_t ret; 538 539 ret = qio_channel_write(wioc->master, 540 (char *)wioc->encoutput.buffer, 541 wioc->encoutput.offset, 542 &err); 543 544 if (ret < 0) { 545 trace_qio_channel_websock_handshake_fail(ioc, error_get_pretty(err)); 546 qio_task_set_error(task, err); 547 qio_task_complete(task); 548 wioc->hs_io_tag = 0; 549 return FALSE; 550 } 551 552 buffer_advance(&wioc->encoutput, ret); 553 if (wioc->encoutput.offset == 0) { 554 if (wioc->io_err) { 555 trace_qio_channel_websock_handshake_fail( 556 ioc, error_get_pretty(wioc->io_err)); 557 qio_task_set_error(task, wioc->io_err); 558 wioc->io_err = NULL; 559 qio_task_complete(task); 560 } else { 561 trace_qio_channel_websock_handshake_complete(ioc); 562 qio_task_complete(task); 563 } 564 wioc->hs_io_tag = 0; 565 return FALSE; 566 } 567 trace_qio_channel_websock_handshake_pending(ioc, G_IO_OUT); 568 return TRUE; 569 } 570 571 static gboolean qio_channel_websock_handshake_io(QIOChannel *ioc, 572 GIOCondition condition, 573 gpointer user_data) 574 { 575 QIOTask *task = user_data; 576 QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK( 577 qio_task_get_source(task)); 578 Error *err = NULL; 579 int ret; 580 581 ret = qio_channel_websock_handshake_read(wioc, &err); 582 if (ret < 0) { 583 /* 584 * We only take this path on a fatal I/O error reading from 585 * client connection, as most of the time we have an 586 * HTTP 4xx err response to send instead 587 */ 588 trace_qio_channel_websock_handshake_fail(ioc, error_get_pretty(err)); 589 qio_task_set_error(task, err); 590 qio_task_complete(task); 591 wioc->hs_io_tag = 0; 592 return FALSE; 593 } 594 if (ret == 0) { 595 trace_qio_channel_websock_handshake_pending(ioc, G_IO_IN); 596 /* need more data still */ 597 return TRUE; 598 } 599 600 error_propagate(&wioc->io_err, err); 601 602 trace_qio_channel_websock_handshake_reply(ioc); 603 wioc->hs_io_tag = qio_channel_add_watch( 604 wioc->master, 605 G_IO_OUT, 606 qio_channel_websock_handshake_send, 607 task, 608 NULL); 609 return FALSE; 610 } 611 612 613 static void qio_channel_websock_encode(QIOChannelWebsock *ioc, 614 uint8_t opcode, 615 const struct iovec *iov, 616 size_t niov, 617 size_t size) 618 { 619 size_t header_size; 620 size_t i; 621 union { 622 char buf[QIO_CHANNEL_WEBSOCK_HEADER_LEN_64_BIT]; 623 QIOChannelWebsockHeader ws; 624 } header; 625 626 assert(size <= iov_size(iov, niov)); 627 628 header.ws.b0 = QIO_CHANNEL_WEBSOCK_HEADER_FIELD_FIN | 629 (opcode & QIO_CHANNEL_WEBSOCK_HEADER_FIELD_OPCODE); 630 if (size < QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_THRESHOLD_7_BIT) { 631 header.ws.b1 = (uint8_t)size; 632 header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_7_BIT; 633 } else if (size < QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_THRESHOLD_16_BIT) { 634 header.ws.b1 = QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_16_BIT; 635 header.ws.u.s16.l16 = cpu_to_be16((uint16_t)size); 636 header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_16_BIT; 637 } else { 638 header.ws.b1 = QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_64_BIT; 639 header.ws.u.s64.l64 = cpu_to_be64(size); 640 header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_64_BIT; 641 } 642 header_size -= QIO_CHANNEL_WEBSOCK_HEADER_LEN_MASK; 643 644 trace_qio_channel_websock_encode(ioc, opcode, header_size, size); 645 buffer_reserve(&ioc->encoutput, header_size + size); 646 buffer_append(&ioc->encoutput, header.buf, header_size); 647 for (i = 0; i < niov && size != 0; i++) { 648 size_t want = iov[i].iov_len; 649 if (want > size) { 650 want = size; 651 } 652 buffer_append(&ioc->encoutput, iov[i].iov_base, want); 653 size -= want; 654 } 655 } 656 657 658 static ssize_t qio_channel_websock_write_wire(QIOChannelWebsock *, Error **); 659 660 661 static void qio_channel_websock_write_close(QIOChannelWebsock *ioc, 662 uint16_t code, const char *reason) 663 { 664 struct iovec iov[2] = { 665 { .iov_base = &code, .iov_len = sizeof(code) }, 666 }; 667 size_t niov = 1; 668 size_t size = iov[0].iov_len; 669 670 cpu_to_be16s(&code); 671 672 if (reason) { 673 iov[1].iov_base = (void *)reason; 674 iov[1].iov_len = strlen(reason); 675 size += iov[1].iov_len; 676 niov++; 677 } 678 qio_channel_websock_encode(ioc, QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE, 679 iov, niov, size); 680 qio_channel_websock_write_wire(ioc, NULL); 681 qio_channel_shutdown(ioc->master, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); 682 } 683 684 685 static int qio_channel_websock_decode_header(QIOChannelWebsock *ioc, 686 Error **errp) 687 { 688 unsigned char opcode, fin, has_mask; 689 size_t header_size; 690 size_t payload_len; 691 QIOChannelWebsockHeader *header = 692 (QIOChannelWebsockHeader *)ioc->encinput.buffer; 693 694 if (ioc->payload_remain) { 695 error_setg(errp, 696 "Decoding header but %zu bytes of payload remain", 697 ioc->payload_remain); 698 qio_channel_websock_write_close( 699 ioc, QIO_CHANNEL_WEBSOCK_STATUS_SERVER_ERR, 700 "internal server error"); 701 return -1; 702 } 703 if (ioc->encinput.offset < QIO_CHANNEL_WEBSOCK_HEADER_LEN_7_BIT) { 704 /* header not complete */ 705 return QIO_CHANNEL_ERR_BLOCK; 706 } 707 708 fin = header->b0 & QIO_CHANNEL_WEBSOCK_HEADER_FIELD_FIN; 709 opcode = header->b0 & QIO_CHANNEL_WEBSOCK_HEADER_FIELD_OPCODE; 710 has_mask = header->b1 & QIO_CHANNEL_WEBSOCK_HEADER_FIELD_HAS_MASK; 711 payload_len = header->b1 & QIO_CHANNEL_WEBSOCK_HEADER_FIELD_PAYLOAD_LEN; 712 713 /* Save or restore opcode. */ 714 if (opcode) { 715 ioc->opcode = opcode; 716 } else { 717 opcode = ioc->opcode; 718 } 719 720 trace_qio_channel_websock_header_partial_decode(ioc, payload_len, 721 fin, opcode, (int)has_mask); 722 723 if (opcode == QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE) { 724 /* disconnect */ 725 return 0; 726 } 727 728 /* Websocket frame sanity check: 729 * * Fragmentation is only supported for binary frames. 730 * * All frames sent by a client MUST be masked. 731 * * Only binary and ping/pong encoding is supported. 732 */ 733 if (!fin) { 734 if (opcode != QIO_CHANNEL_WEBSOCK_OPCODE_BINARY_FRAME) { 735 error_setg(errp, "only binary websocket frames may be fragmented"); 736 qio_channel_websock_write_close( 737 ioc, QIO_CHANNEL_WEBSOCK_STATUS_POLICY , 738 "only binary frames may be fragmented"); 739 return -1; 740 } 741 } else { 742 if (opcode != QIO_CHANNEL_WEBSOCK_OPCODE_BINARY_FRAME && 743 opcode != QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE && 744 opcode != QIO_CHANNEL_WEBSOCK_OPCODE_PING && 745 opcode != QIO_CHANNEL_WEBSOCK_OPCODE_PONG) { 746 error_setg(errp, "unsupported opcode: 0x%04x; only binary, close, " 747 "ping, and pong websocket frames are supported", opcode); 748 qio_channel_websock_write_close( 749 ioc, QIO_CHANNEL_WEBSOCK_STATUS_INVALID_DATA , 750 "only binary, close, ping, and pong frames are supported"); 751 return -1; 752 } 753 } 754 if (!has_mask) { 755 error_setg(errp, "client websocket frames must be masked"); 756 qio_channel_websock_write_close( 757 ioc, QIO_CHANNEL_WEBSOCK_STATUS_PROTOCOL_ERR, 758 "client frames must be masked"); 759 return -1; 760 } 761 762 if (payload_len < QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_16_BIT) { 763 ioc->payload_remain = payload_len; 764 header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_7_BIT; 765 ioc->mask = header->u.m; 766 } else if (opcode & QIO_CHANNEL_WEBSOCK_CONTROL_OPCODE_MASK) { 767 error_setg(errp, "websocket control frame is too large"); 768 qio_channel_websock_write_close( 769 ioc, QIO_CHANNEL_WEBSOCK_STATUS_PROTOCOL_ERR, 770 "control frame is too large"); 771 return -1; 772 } else if (payload_len == QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_16_BIT && 773 ioc->encinput.offset >= QIO_CHANNEL_WEBSOCK_HEADER_LEN_16_BIT) { 774 ioc->payload_remain = be16_to_cpu(header->u.s16.l16); 775 header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_16_BIT; 776 ioc->mask = header->u.s16.m16; 777 } else if (payload_len == QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_64_BIT && 778 ioc->encinput.offset >= QIO_CHANNEL_WEBSOCK_HEADER_LEN_64_BIT) { 779 ioc->payload_remain = be64_to_cpu(header->u.s64.l64); 780 header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_64_BIT; 781 ioc->mask = header->u.s64.m64; 782 } else { 783 /* header not complete */ 784 return QIO_CHANNEL_ERR_BLOCK; 785 } 786 787 trace_qio_channel_websock_header_full_decode( 788 ioc, header_size, ioc->payload_remain, ioc->mask.u); 789 buffer_advance(&ioc->encinput, header_size); 790 return 0; 791 } 792 793 794 static int qio_channel_websock_decode_payload(QIOChannelWebsock *ioc, 795 Error **errp) 796 { 797 size_t i; 798 size_t payload_len = 0; 799 uint32_t *payload32; 800 801 if (ioc->payload_remain) { 802 /* If we aren't at the end of the payload, then drop 803 * off the last bytes, so we're always multiple of 4 804 * for purpose of unmasking, except at end of payload 805 */ 806 if (ioc->encinput.offset < ioc->payload_remain) { 807 /* Wait for the entire payload before processing control frames 808 * because the payload will most likely be echoed back. */ 809 if (ioc->opcode & QIO_CHANNEL_WEBSOCK_CONTROL_OPCODE_MASK) { 810 return QIO_CHANNEL_ERR_BLOCK; 811 } 812 payload_len = ioc->encinput.offset - (ioc->encinput.offset % 4); 813 } else { 814 payload_len = ioc->payload_remain; 815 } 816 if (payload_len == 0) { 817 return QIO_CHANNEL_ERR_BLOCK; 818 } 819 820 ioc->payload_remain -= payload_len; 821 822 /* unmask frame */ 823 /* process 1 frame (32 bit op) */ 824 payload32 = (uint32_t *)ioc->encinput.buffer; 825 for (i = 0; i < payload_len / 4; i++) { 826 payload32[i] ^= ioc->mask.u; 827 } 828 /* process the remaining bytes (if any) */ 829 for (i *= 4; i < payload_len; i++) { 830 ioc->encinput.buffer[i] ^= ioc->mask.c[i % 4]; 831 } 832 } 833 834 trace_qio_channel_websock_payload_decode( 835 ioc, ioc->opcode, ioc->payload_remain); 836 837 if (ioc->opcode == QIO_CHANNEL_WEBSOCK_OPCODE_BINARY_FRAME) { 838 if (payload_len) { 839 /* binary frames are passed on */ 840 buffer_reserve(&ioc->rawinput, payload_len); 841 buffer_append(&ioc->rawinput, ioc->encinput.buffer, payload_len); 842 } 843 } else if (ioc->opcode == QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE) { 844 /* close frames are echoed back */ 845 error_setg(errp, "websocket closed by peer"); 846 if (payload_len) { 847 /* echo client status */ 848 struct iovec iov = { .iov_base = ioc->encinput.buffer, 849 .iov_len = ioc->encinput.offset }; 850 qio_channel_websock_encode(ioc, QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE, 851 &iov, 1, iov.iov_len); 852 qio_channel_websock_write_wire(ioc, NULL); 853 qio_channel_shutdown(ioc->master, QIO_CHANNEL_SHUTDOWN_BOTH, NULL); 854 } else { 855 /* send our own status */ 856 qio_channel_websock_write_close( 857 ioc, QIO_CHANNEL_WEBSOCK_STATUS_NORMAL, "peer requested close"); 858 } 859 return -1; 860 } else if (ioc->opcode == QIO_CHANNEL_WEBSOCK_OPCODE_PING) { 861 /* ping frames produce an immediate reply, as long as we've not still 862 * got a previous pong queued, in which case we drop the new pong */ 863 if (ioc->pong_remain == 0) { 864 struct iovec iov = { .iov_base = ioc->encinput.buffer, 865 .iov_len = ioc->encinput.offset }; 866 qio_channel_websock_encode(ioc, QIO_CHANNEL_WEBSOCK_OPCODE_PONG, 867 &iov, 1, iov.iov_len); 868 ioc->pong_remain = ioc->encoutput.offset; 869 } 870 } /* pong frames are ignored */ 871 872 if (payload_len) { 873 buffer_advance(&ioc->encinput, payload_len); 874 } 875 return 0; 876 } 877 878 879 QIOChannelWebsock * 880 qio_channel_websock_new_server(QIOChannel *master) 881 { 882 QIOChannelWebsock *wioc; 883 QIOChannel *ioc; 884 885 wioc = QIO_CHANNEL_WEBSOCK(object_new(TYPE_QIO_CHANNEL_WEBSOCK)); 886 ioc = QIO_CHANNEL(wioc); 887 888 wioc->master = master; 889 ioc->follow_coroutine_ctx = master->follow_coroutine_ctx; 890 if (qio_channel_has_feature(master, QIO_CHANNEL_FEATURE_SHUTDOWN)) { 891 qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_SHUTDOWN); 892 } 893 object_ref(OBJECT(master)); 894 895 trace_qio_channel_websock_new_server(wioc, master); 896 return wioc; 897 } 898 899 void qio_channel_websock_handshake(QIOChannelWebsock *ioc, 900 QIOTaskFunc func, 901 gpointer opaque, 902 GDestroyNotify destroy) 903 { 904 QIOTask *task; 905 906 task = qio_task_new(OBJECT(ioc), 907 func, 908 opaque, 909 destroy); 910 911 trace_qio_channel_websock_handshake_start(ioc); 912 trace_qio_channel_websock_handshake_pending(ioc, G_IO_IN); 913 ioc->hs_io_tag = qio_channel_add_watch( 914 ioc->master, 915 G_IO_IN, 916 qio_channel_websock_handshake_io, 917 task, 918 NULL); 919 } 920 921 922 static void qio_channel_websock_finalize(Object *obj) 923 { 924 QIOChannelWebsock *ioc = QIO_CHANNEL_WEBSOCK(obj); 925 926 buffer_free(&ioc->encinput); 927 buffer_free(&ioc->encoutput); 928 buffer_free(&ioc->rawinput); 929 if (ioc->hs_io_tag) { 930 g_source_remove(ioc->hs_io_tag); 931 } 932 if (ioc->io_tag) { 933 g_source_remove(ioc->io_tag); 934 } 935 if (ioc->io_err) { 936 error_free(ioc->io_err); 937 } 938 object_unref(OBJECT(ioc->master)); 939 } 940 941 942 static ssize_t qio_channel_websock_read_wire(QIOChannelWebsock *ioc, 943 Error **errp) 944 { 945 ssize_t ret; 946 947 if (ioc->encinput.offset < 4096) { 948 size_t want = 4096 - ioc->encinput.offset; 949 950 buffer_reserve(&ioc->encinput, want); 951 ret = qio_channel_read(ioc->master, 952 (char *)ioc->encinput.buffer + 953 ioc->encinput.offset, 954 want, 955 errp); 956 if (ret < 0) { 957 return ret; 958 } 959 if (ret == 0 && ioc->encinput.offset == 0) { 960 ioc->io_eof = TRUE; 961 return 0; 962 } 963 ioc->encinput.offset += ret; 964 } 965 966 while (ioc->encinput.offset != 0) { 967 if (ioc->payload_remain == 0) { 968 ret = qio_channel_websock_decode_header(ioc, errp); 969 if (ret < 0) { 970 return ret; 971 } 972 } 973 974 ret = qio_channel_websock_decode_payload(ioc, errp); 975 if (ret < 0) { 976 return ret; 977 } 978 } 979 return 1; 980 } 981 982 983 static ssize_t qio_channel_websock_write_wire(QIOChannelWebsock *ioc, 984 Error **errp) 985 { 986 ssize_t ret; 987 ssize_t done = 0; 988 989 while (ioc->encoutput.offset > 0) { 990 ret = qio_channel_write(ioc->master, 991 (char *)ioc->encoutput.buffer, 992 ioc->encoutput.offset, 993 errp); 994 if (ret < 0) { 995 if (ret == QIO_CHANNEL_ERR_BLOCK && 996 done > 0) { 997 return done; 998 } else { 999 return ret; 1000 } 1001 } 1002 buffer_advance(&ioc->encoutput, ret); 1003 done += ret; 1004 if (ioc->pong_remain < ret) { 1005 ioc->pong_remain = 0; 1006 } else { 1007 ioc->pong_remain -= ret; 1008 } 1009 } 1010 return done; 1011 } 1012 1013 1014 static void qio_channel_websock_flush_free(gpointer user_data) 1015 { 1016 QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(user_data); 1017 object_unref(OBJECT(wioc)); 1018 } 1019 1020 static void qio_channel_websock_set_watch(QIOChannelWebsock *ioc); 1021 1022 static gboolean qio_channel_websock_flush(QIOChannel *ioc, 1023 GIOCondition condition, 1024 gpointer user_data) 1025 { 1026 QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(user_data); 1027 ssize_t ret; 1028 1029 if (condition & G_IO_OUT) { 1030 ret = qio_channel_websock_write_wire(wioc, &wioc->io_err); 1031 if (ret < 0) { 1032 goto cleanup; 1033 } 1034 } 1035 1036 if (condition & G_IO_IN) { 1037 ret = qio_channel_websock_read_wire(wioc, &wioc->io_err); 1038 if (ret < 0) { 1039 goto cleanup; 1040 } 1041 } 1042 1043 cleanup: 1044 qio_channel_websock_set_watch(wioc); 1045 return FALSE; 1046 } 1047 1048 1049 static void qio_channel_websock_unset_watch(QIOChannelWebsock *ioc) 1050 { 1051 if (ioc->io_tag) { 1052 g_source_remove(ioc->io_tag); 1053 ioc->io_tag = 0; 1054 } 1055 } 1056 1057 static void qio_channel_websock_set_watch(QIOChannelWebsock *ioc) 1058 { 1059 GIOCondition cond = 0; 1060 1061 qio_channel_websock_unset_watch(ioc); 1062 1063 if (ioc->io_err) { 1064 return; 1065 } 1066 1067 if (ioc->encoutput.offset) { 1068 cond |= G_IO_OUT; 1069 } 1070 if (ioc->encinput.offset < QIO_CHANNEL_WEBSOCK_MAX_BUFFER && 1071 !ioc->io_eof) { 1072 cond |= G_IO_IN; 1073 } 1074 1075 if (cond) { 1076 object_ref(OBJECT(ioc)); 1077 ioc->io_tag = 1078 qio_channel_add_watch(ioc->master, 1079 cond, 1080 qio_channel_websock_flush, 1081 ioc, 1082 qio_channel_websock_flush_free); 1083 } 1084 } 1085 1086 1087 static ssize_t qio_channel_websock_readv(QIOChannel *ioc, 1088 const struct iovec *iov, 1089 size_t niov, 1090 int **fds, 1091 size_t *nfds, 1092 int flags, 1093 Error **errp) 1094 { 1095 QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc); 1096 size_t i; 1097 ssize_t got = 0; 1098 ssize_t ret; 1099 1100 if (wioc->io_err) { 1101 error_propagate(errp, error_copy(wioc->io_err)); 1102 return -1; 1103 } 1104 1105 if (!wioc->rawinput.offset) { 1106 ret = qio_channel_websock_read_wire(QIO_CHANNEL_WEBSOCK(ioc), errp); 1107 if (ret < 0) { 1108 return ret; 1109 } 1110 } 1111 1112 for (i = 0 ; i < niov ; i++) { 1113 size_t want = iov[i].iov_len; 1114 if (want > (wioc->rawinput.offset - got)) { 1115 want = (wioc->rawinput.offset - got); 1116 } 1117 1118 memcpy(iov[i].iov_base, 1119 wioc->rawinput.buffer + got, 1120 want); 1121 got += want; 1122 1123 if (want < iov[i].iov_len) { 1124 break; 1125 } 1126 } 1127 1128 buffer_advance(&wioc->rawinput, got); 1129 qio_channel_websock_set_watch(wioc); 1130 return got; 1131 } 1132 1133 1134 static ssize_t qio_channel_websock_writev(QIOChannel *ioc, 1135 const struct iovec *iov, 1136 size_t niov, 1137 int *fds, 1138 size_t nfds, 1139 int flags, 1140 Error **errp) 1141 { 1142 QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc); 1143 ssize_t want = iov_size(iov, niov); 1144 ssize_t avail; 1145 ssize_t ret; 1146 1147 if (wioc->io_err) { 1148 error_propagate(errp, error_copy(wioc->io_err)); 1149 return -1; 1150 } 1151 1152 if (wioc->io_eof) { 1153 error_setg(errp, "%s", "Broken pipe"); 1154 return -1; 1155 } 1156 1157 avail = wioc->encoutput.offset >= QIO_CHANNEL_WEBSOCK_MAX_BUFFER ? 1158 0 : (QIO_CHANNEL_WEBSOCK_MAX_BUFFER - wioc->encoutput.offset); 1159 if (want > avail) { 1160 want = avail; 1161 } 1162 1163 if (want) { 1164 qio_channel_websock_encode(wioc, 1165 QIO_CHANNEL_WEBSOCK_OPCODE_BINARY_FRAME, 1166 iov, niov, want); 1167 } 1168 1169 /* Even if want == 0, we'll try write_wire in case there's 1170 * pending data we could usefully flush out 1171 */ 1172 ret = qio_channel_websock_write_wire(wioc, errp); 1173 if (ret < 0 && 1174 ret != QIO_CHANNEL_ERR_BLOCK) { 1175 qio_channel_websock_unset_watch(wioc); 1176 return -1; 1177 } 1178 1179 qio_channel_websock_set_watch(wioc); 1180 1181 if (want == 0) { 1182 return QIO_CHANNEL_ERR_BLOCK; 1183 } 1184 1185 return want; 1186 } 1187 1188 static int qio_channel_websock_set_blocking(QIOChannel *ioc, 1189 bool enabled, 1190 Error **errp) 1191 { 1192 QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc); 1193 1194 qio_channel_set_blocking(wioc->master, enabled, errp); 1195 return 0; 1196 } 1197 1198 static void qio_channel_websock_set_delay(QIOChannel *ioc, 1199 bool enabled) 1200 { 1201 QIOChannelWebsock *tioc = QIO_CHANNEL_WEBSOCK(ioc); 1202 1203 qio_channel_set_delay(tioc->master, enabled); 1204 } 1205 1206 static void qio_channel_websock_set_cork(QIOChannel *ioc, 1207 bool enabled) 1208 { 1209 QIOChannelWebsock *tioc = QIO_CHANNEL_WEBSOCK(ioc); 1210 1211 qio_channel_set_cork(tioc->master, enabled); 1212 } 1213 1214 static int qio_channel_websock_shutdown(QIOChannel *ioc, 1215 QIOChannelShutdown how, 1216 Error **errp) 1217 { 1218 QIOChannelWebsock *tioc = QIO_CHANNEL_WEBSOCK(ioc); 1219 1220 return qio_channel_shutdown(tioc->master, how, errp); 1221 } 1222 1223 static int qio_channel_websock_close(QIOChannel *ioc, 1224 Error **errp) 1225 { 1226 QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc); 1227 1228 trace_qio_channel_websock_close(ioc); 1229 buffer_free(&wioc->encinput); 1230 buffer_free(&wioc->encoutput); 1231 buffer_free(&wioc->rawinput); 1232 if (wioc->hs_io_tag) { 1233 g_clear_handle_id(&wioc->hs_io_tag, g_source_remove); 1234 } 1235 if (wioc->io_tag) { 1236 g_clear_handle_id(&wioc->io_tag, g_source_remove); 1237 } 1238 if (wioc->io_err) { 1239 g_clear_pointer(&wioc->io_err, error_free); 1240 } 1241 return qio_channel_close(wioc->master, errp); 1242 } 1243 1244 typedef struct QIOChannelWebsockSource QIOChannelWebsockSource; 1245 struct QIOChannelWebsockSource { 1246 GSource parent; 1247 QIOChannelWebsock *wioc; 1248 GIOCondition condition; 1249 }; 1250 1251 static gboolean 1252 qio_channel_websock_source_check(GSource *source) 1253 { 1254 QIOChannelWebsockSource *wsource = (QIOChannelWebsockSource *)source; 1255 GIOCondition cond = 0; 1256 1257 if (wsource->wioc->rawinput.offset) { 1258 cond |= G_IO_IN; 1259 } 1260 if (wsource->wioc->encoutput.offset < QIO_CHANNEL_WEBSOCK_MAX_BUFFER) { 1261 cond |= G_IO_OUT; 1262 } 1263 if (wsource->wioc->io_eof) { 1264 cond |= G_IO_HUP; 1265 } 1266 if (wsource->wioc->io_err) { 1267 cond |= G_IO_ERR; 1268 } 1269 1270 return cond & wsource->condition; 1271 } 1272 1273 static gboolean 1274 qio_channel_websock_source_prepare(GSource *source, 1275 gint *timeout) 1276 { 1277 *timeout = -1; 1278 return qio_channel_websock_source_check(source); 1279 } 1280 1281 static gboolean 1282 qio_channel_websock_source_dispatch(GSource *source, 1283 GSourceFunc callback, 1284 gpointer user_data) 1285 { 1286 QIOChannelFunc func = (QIOChannelFunc)callback; 1287 QIOChannelWebsockSource *wsource = (QIOChannelWebsockSource *)source; 1288 1289 return (*func)(QIO_CHANNEL(wsource->wioc), 1290 qio_channel_websock_source_check(source), 1291 user_data); 1292 } 1293 1294 static void 1295 qio_channel_websock_source_finalize(GSource *source) 1296 { 1297 QIOChannelWebsockSource *ssource = (QIOChannelWebsockSource *)source; 1298 1299 object_unref(OBJECT(ssource->wioc)); 1300 } 1301 1302 GSourceFuncs qio_channel_websock_source_funcs = { 1303 qio_channel_websock_source_prepare, 1304 qio_channel_websock_source_check, 1305 qio_channel_websock_source_dispatch, 1306 qio_channel_websock_source_finalize 1307 }; 1308 1309 static GSource *qio_channel_websock_create_watch(QIOChannel *ioc, 1310 GIOCondition condition) 1311 { 1312 QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc); 1313 QIOChannelWebsockSource *ssource; 1314 GSource *source; 1315 1316 source = g_source_new(&qio_channel_websock_source_funcs, 1317 sizeof(QIOChannelWebsockSource)); 1318 ssource = (QIOChannelWebsockSource *)source; 1319 1320 ssource->wioc = wioc; 1321 object_ref(OBJECT(wioc)); 1322 1323 ssource->condition = condition; 1324 1325 qio_channel_websock_set_watch(wioc); 1326 return source; 1327 } 1328 1329 static void qio_channel_websock_class_init(ObjectClass *klass, 1330 const void *class_data G_GNUC_UNUSED) 1331 { 1332 QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass); 1333 1334 ioc_klass->io_writev = qio_channel_websock_writev; 1335 ioc_klass->io_readv = qio_channel_websock_readv; 1336 ioc_klass->io_set_blocking = qio_channel_websock_set_blocking; 1337 ioc_klass->io_set_cork = qio_channel_websock_set_cork; 1338 ioc_klass->io_set_delay = qio_channel_websock_set_delay; 1339 ioc_klass->io_close = qio_channel_websock_close; 1340 ioc_klass->io_shutdown = qio_channel_websock_shutdown; 1341 ioc_klass->io_create_watch = qio_channel_websock_create_watch; 1342 } 1343 1344 static const TypeInfo qio_channel_websock_info = { 1345 .parent = TYPE_QIO_CHANNEL, 1346 .name = TYPE_QIO_CHANNEL_WEBSOCK, 1347 .instance_size = sizeof(QIOChannelWebsock), 1348 .instance_finalize = qio_channel_websock_finalize, 1349 .class_init = qio_channel_websock_class_init, 1350 }; 1351 1352 static void qio_channel_websock_register_types(void) 1353 { 1354 type_register_static(&qio_channel_websock_info); 1355 } 1356 1357 type_init(qio_channel_websock_register_types); 1358