static void qio_channel_websock_handshake_process(QIOChannelWebsock *ioc,

                                                  char *buffer,

                                                  Error **errp)

{

    QIOChannelWebsockHTTPHeader hdrs[32];

    size_t nhdrs = G_N_ELEMENTS(hdrs);

    const char *protocols = NULL, *version = NULL, *key = NULL,

        *host = NULL, *connection = NULL, *upgrade = NULL;



    nhdrs = qio_channel_websock_extract_headers(ioc, buffer, hdrs, nhdrs, errp);

    if (!nhdrs) {

        return;

    }



    protocols = qio_channel_websock_find_header(

        hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_PROTOCOL);

    if (!protocols) {

        error_setg(errp, "Missing websocket protocol header data");

        goto bad_request;

    }



    version = qio_channel_websock_find_header(

        hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_VERSION);

    if (!version) {

        error_setg(errp, "Missing websocket version header data");

        goto bad_request;

    }



    key = qio_channel_websock_find_header(

        hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_KEY);

    if (!key) {

        error_setg(errp, "Missing websocket key header data");

        goto bad_request;

    }



    host = qio_channel_websock_find_header(

        hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_HOST);

    if (!host) {

        error_setg(errp, "Missing websocket host header data");

        goto bad_request;

    }



    connection = qio_channel_websock_find_header(

        hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_CONNECTION);

    if (!connection) {

        error_setg(errp, "Missing websocket connection header data");

        goto bad_request;

    }



    upgrade = qio_channel_websock_find_header(

        hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_UPGRADE);

    if (!upgrade) {

        error_setg(errp, "Missing websocket upgrade header data");

        goto bad_request;

    }



    if (!g_strrstr(protocols, QIO_CHANNEL_WEBSOCK_PROTOCOL_BINARY)) {

        error_setg(errp, "No '%s' protocol is supported by client '%s'",

                   QIO_CHANNEL_WEBSOCK_PROTOCOL_BINARY, protocols);

        goto bad_request;

    }



    if (!g_str_equal(version, QIO_CHANNEL_WEBSOCK_SUPPORTED_VERSION)) {

        error_setg(errp, "Version '%s' is not supported by client '%s'",

                   QIO_CHANNEL_WEBSOCK_SUPPORTED_VERSION, version);

        goto bad_request;

    }



    if (strlen(key) != QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN) {

        error_setg(errp, "Key length '%zu' was not as expected '%d'",

                   strlen(key), QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN);

        goto bad_request;

    }



    if (strcasecmp(connection, QIO_CHANNEL_WEBSOCK_CONNECTION_UPGRADE) != 0) {

        error_setg(errp, "No connection upgrade requested '%s'", connection);

        goto bad_request;

    }



    if (strcasecmp(upgrade, QIO_CHANNEL_WEBSOCK_UPGRADE_WEBSOCKET) != 0) {

        error_setg(errp, "Incorrect upgrade method '%s'", upgrade);

        goto bad_request;

    }



    qio_channel_websock_handshake_send_res_ok(ioc, key, errp);

    return;



 bad_request:

    qio_channel_websock_handshake_send_res_err(

        ioc, QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_BAD_REQUEST);

}
