cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

channel-websock.c (43193B)


      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 strlen(QIO_CHANNEL_WEBSOCK_GUID)
     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
    126typedef struct QIOChannelWebsockHeader QIOChannelWebsockHeader;
    127
    128struct 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
    144typedef struct QIOChannelWebsockHTTPHeader QIOChannelWebsockHTTPHeader;
    145
    146struct QIOChannelWebsockHTTPHeader {
    147    char *name;
    148    char *value;
    149};
    150
    151enum {
    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
    160static void GCC_FMT_ATTR(2, 3)
    161qio_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
    178static 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
    185static 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
    193enum {
    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
    202static size_t
    203qio_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
    321static const char *
    322qio_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
    338static 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_ALG_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
    379static 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
    484static 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
    529static 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        return FALSE;
    549    }
    550
    551    buffer_advance(&wioc->encoutput, ret);
    552    if (wioc->encoutput.offset == 0) {
    553        if (wioc->io_err) {
    554            trace_qio_channel_websock_handshake_fail(
    555                ioc, error_get_pretty(wioc->io_err));
    556            qio_task_set_error(task, wioc->io_err);
    557            wioc->io_err = NULL;
    558            qio_task_complete(task);
    559        } else {
    560            trace_qio_channel_websock_handshake_complete(ioc);
    561            qio_task_complete(task);
    562        }
    563        return FALSE;
    564    }
    565    trace_qio_channel_websock_handshake_pending(ioc, G_IO_OUT);
    566    return TRUE;
    567}
    568
    569static gboolean qio_channel_websock_handshake_io(QIOChannel *ioc,
    570                                                 GIOCondition condition,
    571                                                 gpointer user_data)
    572{
    573    QIOTask *task = user_data;
    574    QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(
    575        qio_task_get_source(task));
    576    Error *err = NULL;
    577    int ret;
    578
    579    ret = qio_channel_websock_handshake_read(wioc, &err);
    580    if (ret < 0) {
    581        /*
    582         * We only take this path on a fatal I/O error reading from
    583         * client connection, as most of the time we have an
    584         * HTTP 4xx err response to send instead
    585         */
    586        trace_qio_channel_websock_handshake_fail(ioc, error_get_pretty(err));
    587        qio_task_set_error(task, err);
    588        qio_task_complete(task);
    589        return FALSE;
    590    }
    591    if (ret == 0) {
    592        trace_qio_channel_websock_handshake_pending(ioc, G_IO_IN);
    593        /* need more data still */
    594        return TRUE;
    595    }
    596
    597    error_propagate(&wioc->io_err, err);
    598
    599    trace_qio_channel_websock_handshake_reply(ioc);
    600    qio_channel_add_watch(
    601        wioc->master,
    602        G_IO_OUT,
    603        qio_channel_websock_handshake_send,
    604        task,
    605        NULL);
    606    return FALSE;
    607}
    608
    609
    610static void qio_channel_websock_encode(QIOChannelWebsock *ioc,
    611                                       uint8_t opcode,
    612                                       const struct iovec *iov,
    613                                       size_t niov,
    614                                       size_t size)
    615{
    616    size_t header_size;
    617    size_t i;
    618    union {
    619        char buf[QIO_CHANNEL_WEBSOCK_HEADER_LEN_64_BIT];
    620        QIOChannelWebsockHeader ws;
    621    } header;
    622
    623    assert(size <= iov_size(iov, niov));
    624
    625    header.ws.b0 = QIO_CHANNEL_WEBSOCK_HEADER_FIELD_FIN |
    626        (opcode & QIO_CHANNEL_WEBSOCK_HEADER_FIELD_OPCODE);
    627    if (size < QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_THRESHOLD_7_BIT) {
    628        header.ws.b1 = (uint8_t)size;
    629        header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_7_BIT;
    630    } else if (size < QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_THRESHOLD_16_BIT) {
    631        header.ws.b1 = QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_16_BIT;
    632        header.ws.u.s16.l16 = cpu_to_be16((uint16_t)size);
    633        header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_16_BIT;
    634    } else {
    635        header.ws.b1 = QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_64_BIT;
    636        header.ws.u.s64.l64 = cpu_to_be64(size);
    637        header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_64_BIT;
    638    }
    639    header_size -= QIO_CHANNEL_WEBSOCK_HEADER_LEN_MASK;
    640
    641    trace_qio_channel_websock_encode(ioc, opcode, header_size, size);
    642    buffer_reserve(&ioc->encoutput, header_size + size);
    643    buffer_append(&ioc->encoutput, header.buf, header_size);
    644    for (i = 0; i < niov && size != 0; i++) {
    645        size_t want = iov[i].iov_len;
    646        if (want > size) {
    647            want = size;
    648        }
    649        buffer_append(&ioc->encoutput, iov[i].iov_base, want);
    650        size -= want;
    651    }
    652}
    653
    654
    655static ssize_t qio_channel_websock_write_wire(QIOChannelWebsock *, Error **);
    656
    657
    658static void qio_channel_websock_write_close(QIOChannelWebsock *ioc,
    659                                            uint16_t code, const char *reason)
    660{
    661    struct iovec iov[2] = {
    662        { .iov_base = &code, .iov_len = sizeof(code) },
    663    };
    664    size_t niov = 1;
    665    size_t size = iov[0].iov_len;
    666
    667    cpu_to_be16s(&code);
    668
    669    if (reason) {
    670        iov[1].iov_base = (void *)reason;
    671        iov[1].iov_len = strlen(reason);
    672        size += iov[1].iov_len;
    673        niov++;
    674    }
    675    qio_channel_websock_encode(ioc, QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE,
    676                               iov, niov, size);
    677    qio_channel_websock_write_wire(ioc, NULL);
    678    qio_channel_shutdown(ioc->master, QIO_CHANNEL_SHUTDOWN_BOTH, NULL);
    679}
    680
    681
    682static int qio_channel_websock_decode_header(QIOChannelWebsock *ioc,
    683                                             Error **errp)
    684{
    685    unsigned char opcode, fin, has_mask;
    686    size_t header_size;
    687    size_t payload_len;
    688    QIOChannelWebsockHeader *header =
    689        (QIOChannelWebsockHeader *)ioc->encinput.buffer;
    690
    691    if (ioc->payload_remain) {
    692        error_setg(errp,
    693                   "Decoding header but %zu bytes of payload remain",
    694                   ioc->payload_remain);
    695        qio_channel_websock_write_close(
    696            ioc, QIO_CHANNEL_WEBSOCK_STATUS_SERVER_ERR,
    697            "internal server error");
    698        return -1;
    699    }
    700    if (ioc->encinput.offset < QIO_CHANNEL_WEBSOCK_HEADER_LEN_7_BIT) {
    701        /* header not complete */
    702        return QIO_CHANNEL_ERR_BLOCK;
    703    }
    704
    705    fin = header->b0 & QIO_CHANNEL_WEBSOCK_HEADER_FIELD_FIN;
    706    opcode = header->b0 & QIO_CHANNEL_WEBSOCK_HEADER_FIELD_OPCODE;
    707    has_mask = header->b1 & QIO_CHANNEL_WEBSOCK_HEADER_FIELD_HAS_MASK;
    708    payload_len = header->b1 & QIO_CHANNEL_WEBSOCK_HEADER_FIELD_PAYLOAD_LEN;
    709
    710    /* Save or restore opcode. */
    711    if (opcode) {
    712        ioc->opcode = opcode;
    713    } else {
    714        opcode = ioc->opcode;
    715    }
    716
    717    trace_qio_channel_websock_header_partial_decode(ioc, payload_len,
    718                                                    fin, opcode, (int)has_mask);
    719
    720    if (opcode == QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE) {
    721        /* disconnect */
    722        return 0;
    723    }
    724
    725    /* Websocket frame sanity check:
    726     * * Fragmentation is only supported for binary frames.
    727     * * All frames sent by a client MUST be masked.
    728     * * Only binary and ping/pong encoding is supported.
    729     */
    730    if (!fin) {
    731        if (opcode != QIO_CHANNEL_WEBSOCK_OPCODE_BINARY_FRAME) {
    732            error_setg(errp, "only binary websocket frames may be fragmented");
    733            qio_channel_websock_write_close(
    734                ioc, QIO_CHANNEL_WEBSOCK_STATUS_POLICY ,
    735                "only binary frames may be fragmented");
    736            return -1;
    737        }
    738    } else {
    739        if (opcode != QIO_CHANNEL_WEBSOCK_OPCODE_BINARY_FRAME &&
    740            opcode != QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE &&
    741            opcode != QIO_CHANNEL_WEBSOCK_OPCODE_PING &&
    742            opcode != QIO_CHANNEL_WEBSOCK_OPCODE_PONG) {
    743            error_setg(errp, "unsupported opcode: 0x%04x; only binary, close, "
    744                       "ping, and pong websocket frames are supported", opcode);
    745            qio_channel_websock_write_close(
    746                ioc, QIO_CHANNEL_WEBSOCK_STATUS_INVALID_DATA ,
    747                "only binary, close, ping, and pong frames are supported");
    748            return -1;
    749        }
    750    }
    751    if (!has_mask) {
    752        error_setg(errp, "client websocket frames must be masked");
    753        qio_channel_websock_write_close(
    754            ioc, QIO_CHANNEL_WEBSOCK_STATUS_PROTOCOL_ERR,
    755            "client frames must be masked");
    756        return -1;
    757    }
    758
    759    if (payload_len < QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_16_BIT) {
    760        ioc->payload_remain = payload_len;
    761        header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_7_BIT;
    762        ioc->mask = header->u.m;
    763    } else if (opcode & QIO_CHANNEL_WEBSOCK_CONTROL_OPCODE_MASK) {
    764        error_setg(errp, "websocket control frame is too large");
    765        qio_channel_websock_write_close(
    766            ioc, QIO_CHANNEL_WEBSOCK_STATUS_PROTOCOL_ERR,
    767            "control frame is too large");
    768        return -1;
    769    } else if (payload_len == QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_16_BIT &&
    770               ioc->encinput.offset >= QIO_CHANNEL_WEBSOCK_HEADER_LEN_16_BIT) {
    771        ioc->payload_remain = be16_to_cpu(header->u.s16.l16);
    772        header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_16_BIT;
    773        ioc->mask = header->u.s16.m16;
    774    } else if (payload_len == QIO_CHANNEL_WEBSOCK_PAYLOAD_LEN_MAGIC_64_BIT &&
    775               ioc->encinput.offset >= QIO_CHANNEL_WEBSOCK_HEADER_LEN_64_BIT) {
    776        ioc->payload_remain = be64_to_cpu(header->u.s64.l64);
    777        header_size = QIO_CHANNEL_WEBSOCK_HEADER_LEN_64_BIT;
    778        ioc->mask = header->u.s64.m64;
    779    } else {
    780        /* header not complete */
    781        return QIO_CHANNEL_ERR_BLOCK;
    782    }
    783
    784    trace_qio_channel_websock_header_full_decode(
    785        ioc, header_size, ioc->payload_remain, ioc->mask.u);
    786    buffer_advance(&ioc->encinput, header_size);
    787    return 0;
    788}
    789
    790
    791static int qio_channel_websock_decode_payload(QIOChannelWebsock *ioc,
    792                                              Error **errp)
    793{
    794    size_t i;
    795    size_t payload_len = 0;
    796    uint32_t *payload32;
    797
    798    if (ioc->payload_remain) {
    799        /* If we aren't at the end of the payload, then drop
    800         * off the last bytes, so we're always multiple of 4
    801         * for purpose of unmasking, except at end of payload
    802         */
    803        if (ioc->encinput.offset < ioc->payload_remain) {
    804            /* Wait for the entire payload before processing control frames
    805             * because the payload will most likely be echoed back. */
    806            if (ioc->opcode & QIO_CHANNEL_WEBSOCK_CONTROL_OPCODE_MASK) {
    807                return QIO_CHANNEL_ERR_BLOCK;
    808            }
    809            payload_len = ioc->encinput.offset - (ioc->encinput.offset % 4);
    810        } else {
    811            payload_len = ioc->payload_remain;
    812        }
    813        if (payload_len == 0) {
    814            return QIO_CHANNEL_ERR_BLOCK;
    815        }
    816
    817        ioc->payload_remain -= payload_len;
    818
    819        /* unmask frame */
    820        /* process 1 frame (32 bit op) */
    821        payload32 = (uint32_t *)ioc->encinput.buffer;
    822        for (i = 0; i < payload_len / 4; i++) {
    823            payload32[i] ^= ioc->mask.u;
    824        }
    825        /* process the remaining bytes (if any) */
    826        for (i *= 4; i < payload_len; i++) {
    827            ioc->encinput.buffer[i] ^= ioc->mask.c[i % 4];
    828        }
    829    }
    830
    831    trace_qio_channel_websock_payload_decode(
    832        ioc, ioc->opcode, ioc->payload_remain);
    833
    834    if (ioc->opcode == QIO_CHANNEL_WEBSOCK_OPCODE_BINARY_FRAME) {
    835        if (payload_len) {
    836            /* binary frames are passed on */
    837            buffer_reserve(&ioc->rawinput, payload_len);
    838            buffer_append(&ioc->rawinput, ioc->encinput.buffer, payload_len);
    839        }
    840    } else if (ioc->opcode == QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE) {
    841        /* close frames are echoed back */
    842        error_setg(errp, "websocket closed by peer");
    843        if (payload_len) {
    844            /* echo client status */
    845            struct iovec iov = { .iov_base = ioc->encinput.buffer,
    846                                 .iov_len = ioc->encinput.offset };
    847            qio_channel_websock_encode(ioc, QIO_CHANNEL_WEBSOCK_OPCODE_CLOSE,
    848                                       &iov, 1, iov.iov_len);
    849            qio_channel_websock_write_wire(ioc, NULL);
    850            qio_channel_shutdown(ioc->master, QIO_CHANNEL_SHUTDOWN_BOTH, NULL);
    851        } else {
    852            /* send our own status */
    853            qio_channel_websock_write_close(
    854                ioc, QIO_CHANNEL_WEBSOCK_STATUS_NORMAL, "peer requested close");
    855        }
    856        return -1;
    857    } else if (ioc->opcode == QIO_CHANNEL_WEBSOCK_OPCODE_PING) {
    858        /* ping frames produce an immediate reply, as long as we've not still
    859         * got a previous pong queued, in which case we drop the new pong */
    860        if (ioc->pong_remain == 0) {
    861            struct iovec iov = { .iov_base = ioc->encinput.buffer,
    862                                 .iov_len = ioc->encinput.offset };
    863            qio_channel_websock_encode(ioc, QIO_CHANNEL_WEBSOCK_OPCODE_PONG,
    864                                       &iov, 1, iov.iov_len);
    865            ioc->pong_remain = ioc->encoutput.offset;
    866        }
    867    }   /* pong frames are ignored */
    868
    869    if (payload_len) {
    870        buffer_advance(&ioc->encinput, payload_len);
    871    }
    872    return 0;
    873}
    874
    875
    876QIOChannelWebsock *
    877qio_channel_websock_new_server(QIOChannel *master)
    878{
    879    QIOChannelWebsock *wioc;
    880    QIOChannel *ioc;
    881
    882    wioc = QIO_CHANNEL_WEBSOCK(object_new(TYPE_QIO_CHANNEL_WEBSOCK));
    883    ioc = QIO_CHANNEL(wioc);
    884
    885    wioc->master = master;
    886    if (qio_channel_has_feature(master, QIO_CHANNEL_FEATURE_SHUTDOWN)) {
    887        qio_channel_set_feature(ioc, QIO_CHANNEL_FEATURE_SHUTDOWN);
    888    }
    889    object_ref(OBJECT(master));
    890
    891    trace_qio_channel_websock_new_server(wioc, master);
    892    return wioc;
    893}
    894
    895void qio_channel_websock_handshake(QIOChannelWebsock *ioc,
    896                                   QIOTaskFunc func,
    897                                   gpointer opaque,
    898                                   GDestroyNotify destroy)
    899{
    900    QIOTask *task;
    901
    902    task = qio_task_new(OBJECT(ioc),
    903                        func,
    904                        opaque,
    905                        destroy);
    906
    907    trace_qio_channel_websock_handshake_start(ioc);
    908    trace_qio_channel_websock_handshake_pending(ioc, G_IO_IN);
    909    qio_channel_add_watch(ioc->master,
    910                          G_IO_IN,
    911                          qio_channel_websock_handshake_io,
    912                          task,
    913                          NULL);
    914}
    915
    916
    917static void qio_channel_websock_finalize(Object *obj)
    918{
    919    QIOChannelWebsock *ioc = QIO_CHANNEL_WEBSOCK(obj);
    920
    921    buffer_free(&ioc->encinput);
    922    buffer_free(&ioc->encoutput);
    923    buffer_free(&ioc->rawinput);
    924    object_unref(OBJECT(ioc->master));
    925    if (ioc->io_tag) {
    926        g_source_remove(ioc->io_tag);
    927    }
    928    if (ioc->io_err) {
    929        error_free(ioc->io_err);
    930    }
    931}
    932
    933
    934static ssize_t qio_channel_websock_read_wire(QIOChannelWebsock *ioc,
    935                                             Error **errp)
    936{
    937    ssize_t ret;
    938
    939    if (ioc->encinput.offset < 4096) {
    940        size_t want = 4096 - ioc->encinput.offset;
    941
    942        buffer_reserve(&ioc->encinput, want);
    943        ret = qio_channel_read(ioc->master,
    944                               (char *)ioc->encinput.buffer +
    945                               ioc->encinput.offset,
    946                               want,
    947                               errp);
    948        if (ret < 0) {
    949            return ret;
    950        }
    951        if (ret == 0 && ioc->encinput.offset == 0) {
    952            ioc->io_eof = TRUE;
    953            return 0;
    954        }
    955        ioc->encinput.offset += ret;
    956    }
    957
    958    while (ioc->encinput.offset != 0) {
    959        if (ioc->payload_remain == 0) {
    960            ret = qio_channel_websock_decode_header(ioc, errp);
    961            if (ret < 0) {
    962                return ret;
    963            }
    964        }
    965
    966        ret = qio_channel_websock_decode_payload(ioc, errp);
    967        if (ret < 0) {
    968            return ret;
    969        }
    970    }
    971    return 1;
    972}
    973
    974
    975static ssize_t qio_channel_websock_write_wire(QIOChannelWebsock *ioc,
    976                                              Error **errp)
    977{
    978    ssize_t ret;
    979    ssize_t done = 0;
    980
    981    while (ioc->encoutput.offset > 0) {
    982        ret = qio_channel_write(ioc->master,
    983                                (char *)ioc->encoutput.buffer,
    984                                ioc->encoutput.offset,
    985                                errp);
    986        if (ret < 0) {
    987            if (ret == QIO_CHANNEL_ERR_BLOCK &&
    988                done > 0) {
    989                return done;
    990            } else {
    991                return ret;
    992            }
    993        }
    994        buffer_advance(&ioc->encoutput, ret);
    995        done += ret;
    996        if (ioc->pong_remain < ret) {
    997            ioc->pong_remain = 0;
    998        } else {
    999            ioc->pong_remain -= ret;
   1000        }
   1001    }
   1002    return done;
   1003}
   1004
   1005
   1006static void qio_channel_websock_flush_free(gpointer user_data)
   1007{
   1008    QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(user_data);
   1009    object_unref(OBJECT(wioc));
   1010}
   1011
   1012static void qio_channel_websock_set_watch(QIOChannelWebsock *ioc);
   1013
   1014static gboolean qio_channel_websock_flush(QIOChannel *ioc,
   1015                                          GIOCondition condition,
   1016                                          gpointer user_data)
   1017{
   1018    QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(user_data);
   1019    ssize_t ret;
   1020
   1021    if (condition & G_IO_OUT) {
   1022        ret = qio_channel_websock_write_wire(wioc, &wioc->io_err);
   1023        if (ret < 0) {
   1024            goto cleanup;
   1025        }
   1026    }
   1027
   1028    if (condition & G_IO_IN) {
   1029        ret = qio_channel_websock_read_wire(wioc, &wioc->io_err);
   1030        if (ret < 0) {
   1031            goto cleanup;
   1032        }
   1033    }
   1034
   1035 cleanup:
   1036    qio_channel_websock_set_watch(wioc);
   1037    return FALSE;
   1038}
   1039
   1040
   1041static void qio_channel_websock_unset_watch(QIOChannelWebsock *ioc)
   1042{
   1043    if (ioc->io_tag) {
   1044        g_source_remove(ioc->io_tag);
   1045        ioc->io_tag = 0;
   1046    }
   1047}
   1048
   1049static void qio_channel_websock_set_watch(QIOChannelWebsock *ioc)
   1050{
   1051    GIOCondition cond = 0;
   1052
   1053    qio_channel_websock_unset_watch(ioc);
   1054
   1055    if (ioc->io_err) {
   1056        return;
   1057    }
   1058
   1059    if (ioc->encoutput.offset) {
   1060        cond |= G_IO_OUT;
   1061    }
   1062    if (ioc->encinput.offset < QIO_CHANNEL_WEBSOCK_MAX_BUFFER &&
   1063        !ioc->io_eof) {
   1064        cond |= G_IO_IN;
   1065    }
   1066
   1067    if (cond) {
   1068        object_ref(OBJECT(ioc));
   1069        ioc->io_tag =
   1070            qio_channel_add_watch(ioc->master,
   1071                                  cond,
   1072                                  qio_channel_websock_flush,
   1073                                  ioc,
   1074                                  qio_channel_websock_flush_free);
   1075    }
   1076}
   1077
   1078
   1079static ssize_t qio_channel_websock_readv(QIOChannel *ioc,
   1080                                         const struct iovec *iov,
   1081                                         size_t niov,
   1082                                         int **fds,
   1083                                         size_t *nfds,
   1084                                         Error **errp)
   1085{
   1086    QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc);
   1087    size_t i;
   1088    ssize_t got = 0;
   1089    ssize_t ret;
   1090
   1091    if (wioc->io_err) {
   1092        error_propagate(errp, error_copy(wioc->io_err));
   1093        return -1;
   1094    }
   1095
   1096    if (!wioc->rawinput.offset) {
   1097        ret = qio_channel_websock_read_wire(QIO_CHANNEL_WEBSOCK(ioc), errp);
   1098        if (ret < 0) {
   1099            return ret;
   1100        }
   1101    }
   1102
   1103    for (i = 0 ; i < niov ; i++) {
   1104        size_t want = iov[i].iov_len;
   1105        if (want > (wioc->rawinput.offset - got)) {
   1106            want = (wioc->rawinput.offset - got);
   1107        }
   1108
   1109        memcpy(iov[i].iov_base,
   1110               wioc->rawinput.buffer + got,
   1111               want);
   1112        got += want;
   1113
   1114        if (want < iov[i].iov_len) {
   1115            break;
   1116        }
   1117    }
   1118
   1119    buffer_advance(&wioc->rawinput, got);
   1120    qio_channel_websock_set_watch(wioc);
   1121    return got;
   1122}
   1123
   1124
   1125static ssize_t qio_channel_websock_writev(QIOChannel *ioc,
   1126                                          const struct iovec *iov,
   1127                                          size_t niov,
   1128                                          int *fds,
   1129                                          size_t nfds,
   1130                                          Error **errp)
   1131{
   1132    QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc);
   1133    ssize_t want = iov_size(iov, niov);
   1134    ssize_t avail;
   1135    ssize_t ret;
   1136
   1137    if (wioc->io_err) {
   1138        error_propagate(errp, error_copy(wioc->io_err));
   1139        return -1;
   1140    }
   1141
   1142    if (wioc->io_eof) {
   1143        error_setg(errp, "%s", "Broken pipe");
   1144        return -1;
   1145    }
   1146
   1147    avail = wioc->encoutput.offset >= QIO_CHANNEL_WEBSOCK_MAX_BUFFER ?
   1148        0 : (QIO_CHANNEL_WEBSOCK_MAX_BUFFER - wioc->encoutput.offset);
   1149    if (want > avail) {
   1150        want = avail;
   1151    }
   1152
   1153    if (want) {
   1154        qio_channel_websock_encode(wioc,
   1155                                   QIO_CHANNEL_WEBSOCK_OPCODE_BINARY_FRAME,
   1156                                   iov, niov, want);
   1157    }
   1158
   1159    /* Even if want == 0, we'll try write_wire in case there's
   1160     * pending data we could usefully flush out
   1161     */
   1162    ret = qio_channel_websock_write_wire(wioc, errp);
   1163    if (ret < 0 &&
   1164        ret != QIO_CHANNEL_ERR_BLOCK) {
   1165        qio_channel_websock_unset_watch(wioc);
   1166        return -1;
   1167    }
   1168
   1169    qio_channel_websock_set_watch(wioc);
   1170
   1171    if (want == 0) {
   1172        return QIO_CHANNEL_ERR_BLOCK;
   1173    }
   1174
   1175    return want;
   1176}
   1177
   1178static int qio_channel_websock_set_blocking(QIOChannel *ioc,
   1179                                            bool enabled,
   1180                                            Error **errp)
   1181{
   1182    QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc);
   1183
   1184    qio_channel_set_blocking(wioc->master, enabled, errp);
   1185    return 0;
   1186}
   1187
   1188static void qio_channel_websock_set_delay(QIOChannel *ioc,
   1189                                          bool enabled)
   1190{
   1191    QIOChannelWebsock *tioc = QIO_CHANNEL_WEBSOCK(ioc);
   1192
   1193    qio_channel_set_delay(tioc->master, enabled);
   1194}
   1195
   1196static void qio_channel_websock_set_cork(QIOChannel *ioc,
   1197                                         bool enabled)
   1198{
   1199    QIOChannelWebsock *tioc = QIO_CHANNEL_WEBSOCK(ioc);
   1200
   1201    qio_channel_set_cork(tioc->master, enabled);
   1202}
   1203
   1204static int qio_channel_websock_shutdown(QIOChannel *ioc,
   1205                                        QIOChannelShutdown how,
   1206                                        Error **errp)
   1207{
   1208    QIOChannelWebsock *tioc = QIO_CHANNEL_WEBSOCK(ioc);
   1209
   1210    return qio_channel_shutdown(tioc->master, how, errp);
   1211}
   1212
   1213static int qio_channel_websock_close(QIOChannel *ioc,
   1214                                     Error **errp)
   1215{
   1216    QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc);
   1217
   1218    trace_qio_channel_websock_close(ioc);
   1219    return qio_channel_close(wioc->master, errp);
   1220}
   1221
   1222typedef struct QIOChannelWebsockSource QIOChannelWebsockSource;
   1223struct QIOChannelWebsockSource {
   1224    GSource parent;
   1225    QIOChannelWebsock *wioc;
   1226    GIOCondition condition;
   1227};
   1228
   1229static gboolean
   1230qio_channel_websock_source_check(GSource *source)
   1231{
   1232    QIOChannelWebsockSource *wsource = (QIOChannelWebsockSource *)source;
   1233    GIOCondition cond = 0;
   1234
   1235    if (wsource->wioc->rawinput.offset) {
   1236        cond |= G_IO_IN;
   1237    }
   1238    if (wsource->wioc->encoutput.offset < QIO_CHANNEL_WEBSOCK_MAX_BUFFER) {
   1239        cond |= G_IO_OUT;
   1240    }
   1241    if (wsource->wioc->io_eof) {
   1242        cond |= G_IO_HUP;
   1243    }
   1244    if (wsource->wioc->io_err) {
   1245        cond |= G_IO_ERR;
   1246    }
   1247
   1248    return cond & wsource->condition;
   1249}
   1250
   1251static gboolean
   1252qio_channel_websock_source_prepare(GSource *source,
   1253                                   gint *timeout)
   1254{
   1255    *timeout = -1;
   1256    return qio_channel_websock_source_check(source);
   1257}
   1258
   1259static gboolean
   1260qio_channel_websock_source_dispatch(GSource *source,
   1261                                    GSourceFunc callback,
   1262                                    gpointer user_data)
   1263{
   1264    QIOChannelFunc func = (QIOChannelFunc)callback;
   1265    QIOChannelWebsockSource *wsource = (QIOChannelWebsockSource *)source;
   1266
   1267    return (*func)(QIO_CHANNEL(wsource->wioc),
   1268                   qio_channel_websock_source_check(source),
   1269                   user_data);
   1270}
   1271
   1272static void
   1273qio_channel_websock_source_finalize(GSource *source)
   1274{
   1275    QIOChannelWebsockSource *ssource = (QIOChannelWebsockSource *)source;
   1276
   1277    object_unref(OBJECT(ssource->wioc));
   1278}
   1279
   1280GSourceFuncs qio_channel_websock_source_funcs = {
   1281    qio_channel_websock_source_prepare,
   1282    qio_channel_websock_source_check,
   1283    qio_channel_websock_source_dispatch,
   1284    qio_channel_websock_source_finalize
   1285};
   1286
   1287static GSource *qio_channel_websock_create_watch(QIOChannel *ioc,
   1288                                                 GIOCondition condition)
   1289{
   1290    QIOChannelWebsock *wioc = QIO_CHANNEL_WEBSOCK(ioc);
   1291    QIOChannelWebsockSource *ssource;
   1292    GSource *source;
   1293
   1294    source = g_source_new(&qio_channel_websock_source_funcs,
   1295                          sizeof(QIOChannelWebsockSource));
   1296    ssource = (QIOChannelWebsockSource *)source;
   1297
   1298    ssource->wioc = wioc;
   1299    object_ref(OBJECT(wioc));
   1300
   1301    ssource->condition = condition;
   1302
   1303    qio_channel_websock_set_watch(wioc);
   1304    return source;
   1305}
   1306
   1307static void qio_channel_websock_class_init(ObjectClass *klass,
   1308                                           void *class_data G_GNUC_UNUSED)
   1309{
   1310    QIOChannelClass *ioc_klass = QIO_CHANNEL_CLASS(klass);
   1311
   1312    ioc_klass->io_writev = qio_channel_websock_writev;
   1313    ioc_klass->io_readv = qio_channel_websock_readv;
   1314    ioc_klass->io_set_blocking = qio_channel_websock_set_blocking;
   1315    ioc_klass->io_set_cork = qio_channel_websock_set_cork;
   1316    ioc_klass->io_set_delay = qio_channel_websock_set_delay;
   1317    ioc_klass->io_close = qio_channel_websock_close;
   1318    ioc_klass->io_shutdown = qio_channel_websock_shutdown;
   1319    ioc_klass->io_create_watch = qio_channel_websock_create_watch;
   1320}
   1321
   1322static const TypeInfo qio_channel_websock_info = {
   1323    .parent = TYPE_QIO_CHANNEL,
   1324    .name = TYPE_QIO_CHANNEL_WEBSOCK,
   1325    .instance_size = sizeof(QIOChannelWebsock),
   1326    .instance_finalize = qio_channel_websock_finalize,
   1327    .class_init = qio_channel_websock_class_init,
   1328};
   1329
   1330static void qio_channel_websock_register_types(void)
   1331{
   1332    type_register_static(&qio_channel_websock_info);
   1333}
   1334
   1335type_init(qio_channel_websock_register_types);