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