[{"id":1765485,"web_url":"http://patchwork.ozlabs.org/comment/1765485/","msgid":"<788c7aad-fab1-a6da-3d63-bedc270de023@amsat.org>","list_archive_url":null,"date":"2017-09-08T16:14:06","subject":"Re: [Qemu-devel] [PATCH v3 1/3] io: send proper HTTP response for\n\twebsocket errors","submitter":{"id":70924,"url":"http://patchwork.ozlabs.org/api/people/70924/","name":"Philippe Mathieu-Daudé","email":"f4bug@amsat.org"},"content":"On 09/08/2017 10:58 AM, Daniel P. Berrange wrote:\n> When any error occurs while processing the websockets handshake,\n> QEMU just terminates the connection abruptly. This is in violation\n> of the HTTP specs and does not help the client understand what they\n> did wrong. This is particularly bad when the client gives the wrong\n> path, as a \"404 Not Found\" would be very helpful.\n> \n> Refactor the handshake code so that it always sends a response to\n> the client unless there was an I/O error.\n> \n> Fixes bug: #1715186\n> \n> Signed-off-by: Daniel P. Berrange <berrange@redhat.com>\n\nReviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>\n\n> ---\n>   io/channel-websock.c | 186 ++++++++++++++++++++++++++++++++++++++-------------\n>   1 file changed, 140 insertions(+), 46 deletions(-)\n> \n> diff --git a/io/channel-websock.c b/io/channel-websock.c\n> index 5a3badbec2..cc93a23f8b 100644\n> --- a/io/channel-websock.c\n> +++ b/io/channel-websock.c\n> @@ -25,6 +25,8 @@\n>   #include \"crypto/hash.h\"\n>   #include \"trace.h\"\n>   \n> +#include <time.h>\n> +\n>   \n>   /* Max amount to allow in rawinput/rawoutput buffers */\n>   #define QIO_CHANNEL_WEBSOCK_MAX_BUFFER 8192\n> @@ -44,13 +46,40 @@\n>   #define QIO_CHANNEL_WEBSOCK_CONNECTION_UPGRADE \"Upgrade\"\n>   #define QIO_CHANNEL_WEBSOCK_UPGRADE_WEBSOCKET \"websocket\"\n>   \n> -#define QIO_CHANNEL_WEBSOCK_HANDSHAKE_RESPONSE  \\\n> +#define QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_COMMON \\\n> +    \"Server: QEMU VNC\\r\\n\"                       \\\n> +    \"Date: %s\\r\\n\"\n> +\n> +#define QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_OK    \\\n>       \"HTTP/1.1 101 Switching Protocols\\r\\n\"      \\\n> +    QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_COMMON    \\\n>       \"Upgrade: websocket\\r\\n\"                    \\\n>       \"Connection: Upgrade\\r\\n\"                   \\\n>       \"Sec-WebSocket-Accept: %s\\r\\n\"              \\\n>       \"Sec-WebSocket-Protocol: binary\\r\\n\"        \\\n>       \"\\r\\n\"\n> +#define QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_NOT_FOUND \\\n> +    \"HTTP/1.1 404 Not Found\\r\\n\"                    \\\n> +    QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_COMMON        \\\n> +    \"Connection: close\\r\\n\"                         \\\n> +    \"\\r\\n\"\n> +#define QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_BAD_REQUEST \\\n> +    \"HTTP/1.1 400 Bad Request\\r\\n\"                    \\\n> +    QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_COMMON          \\\n> +    \"Connection: close\\r\\n\"                           \\\n> +    \"Sec-WebSocket-Version: \"                         \\\n> +    QIO_CHANNEL_WEBSOCK_SUPPORTED_VERSION             \\\n> +    \"\\r\\n\"\n> +#define QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_SERVER_ERR \\\n> +    \"HTTP/1.1 500 Internal Server Error\\r\\n\"         \\\n> +    QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_COMMON         \\\n> +    \"Connection: close\\r\\n\"                          \\\n> +    \"\\r\\n\"\n> +#define QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_TOO_LARGE  \\\n> +    \"HTTP/1.1 403 Request Entity Too Large\\r\\n\"      \\\n> +    QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_COMMON         \\\n> +    \"Connection: close\\r\\n\"                          \\\n> +    \"\\r\\n\"\n>   #define QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM \"\\r\\n\"\n>   #define QIO_CHANNEL_WEBSOCK_HANDSHAKE_END \"\\r\\n\\r\\n\"\n>   #define QIO_CHANNEL_WEBSOCK_SUPPORTED_VERSION \"13\"\n> @@ -123,8 +152,47 @@ enum {\n>       QIO_CHANNEL_WEBSOCK_OPCODE_PONG = 0xA\n>   };\n>   \n> +static void qio_channel_websock_handshake_send_res(QIOChannelWebsock *ioc,\n> +                                                   const char *resmsg,\n> +                                                   ...)\n> +{\n> +    va_list vargs;\n> +    char *response;\n> +    size_t responselen;\n> +\n> +    va_start(vargs, resmsg);\n> +    response = g_strdup_vprintf(resmsg, vargs);\n> +    responselen = strlen(response);\n> +    buffer_reserve(&ioc->encoutput, responselen);\n> +    buffer_append(&ioc->encoutput, response, responselen);\n> +    va_end(vargs);\n> +}\n> +\n> +static gchar *qio_channel_websock_date_str(void)\n> +{\n> +    struct tm tm;\n> +    struct timeval tv;\n> +    char datebuf[128];\n> +\n> +    gettimeofday(&tv, NULL);\n> +    gmtime_r(&tv.tv_sec, &tm);\n> +\n> +    strftime(datebuf, sizeof(datebuf), \"%a, %d %b %Y %H:%M:%S GMT\", &tm);\n> +\n> +    return g_strdup(datebuf);\n> +}\n> +\n> +static void qio_channel_websock_handshake_send_res_err(QIOChannelWebsock *ioc,\n> +                                                       const char *resdata)\n> +{\n> +    char *date = qio_channel_websock_date_str();\n> +    qio_channel_websock_handshake_send_res(ioc, resdata, date);\n> +    g_free(date);\n> +}\n> +\n>   static size_t\n> -qio_channel_websock_extract_headers(char *buffer,\n> +qio_channel_websock_extract_headers(QIOChannelWebsock *ioc,\n> +                                    char *buffer,\n>                                       QIOChannelWebsockHTTPHeader *hdrs,\n>                                       size_t nhdrsalloc,\n>                                       Error **errp)\n> @@ -145,7 +213,7 @@ qio_channel_websock_extract_headers(char *buffer,\n>       nl = strstr(buffer, QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM);\n>       if (!nl) {\n>           error_setg(errp, \"Missing HTTP header delimiter\");\n> -        return 0;\n> +        goto bad_request;\n>       }\n>       *nl = '\\0';\n>   \n> @@ -158,18 +226,20 @@ qio_channel_websock_extract_headers(char *buffer,\n>   \n>       if (!g_str_equal(buffer, QIO_CHANNEL_WEBSOCK_HTTP_METHOD)) {\n>           error_setg(errp, \"Unsupported HTTP method %s\", buffer);\n> -        return 0;\n> +        goto bad_request;\n>       }\n>   \n>       buffer = tmp + 1;\n>       tmp = strchr(buffer, ' ');\n>       if (!tmp) {\n>           error_setg(errp, \"Missing HTTP version delimiter\");\n> -        return 0;\n> +        goto bad_request;\n>       }\n>       *tmp = '\\0';\n>   \n>       if (!g_str_equal(buffer, QIO_CHANNEL_WEBSOCK_HTTP_PATH)) {\n> +        qio_channel_websock_handshake_send_res_err(\n> +            ioc, QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_NOT_FOUND);\n>           error_setg(errp, \"Unexpected HTTP path %s\", buffer);\n>           return 0;\n>       }\n> @@ -178,7 +248,7 @@ qio_channel_websock_extract_headers(char *buffer,\n>   \n>       if (!g_str_equal(buffer, QIO_CHANNEL_WEBSOCK_HTTP_VERSION)) {\n>           error_setg(errp, \"Unsupported HTTP version %s\", buffer);\n> -        return 0;\n> +        goto bad_request;\n>       }\n>   \n>       buffer = nl + strlen(QIO_CHANNEL_WEBSOCK_HANDSHAKE_DELIM);\n> @@ -203,7 +273,7 @@ qio_channel_websock_extract_headers(char *buffer,\n>           sep = strchr(buffer, ':');\n>           if (!sep) {\n>               error_setg(errp, \"Malformed HTTP header\");\n> -            return 0;\n> +            goto bad_request;\n>           }\n>           *sep = '\\0';\n>           sep++;\n> @@ -213,7 +283,7 @@ qio_channel_websock_extract_headers(char *buffer,\n>   \n>           if (nhdrs >= nhdrsalloc) {\n>               error_setg(errp, \"Too many HTTP headers\");\n> -            return 0;\n> +            goto bad_request;\n>           }\n>   \n>           hdr = &hdrs[nhdrs++];\n> @@ -231,6 +301,11 @@ qio_channel_websock_extract_headers(char *buffer,\n>       } while (nl != NULL);\n>   \n>       return nhdrs;\n> +\n> + bad_request:\n> +    qio_channel_websock_handshake_send_res_err(\n> +        ioc, QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_BAD_REQUEST);\n> +    return 0;\n>   }\n>   \n>   static const char *\n> @@ -250,14 +325,14 @@ qio_channel_websock_find_header(QIOChannelWebsockHTTPHeader *hdrs,\n>   }\n>   \n>   \n> -static int qio_channel_websock_handshake_send_response(QIOChannelWebsock *ioc,\n> -                                                       const char *key,\n> -                                                       Error **errp)\n> +static void qio_channel_websock_handshake_send_res_ok(QIOChannelWebsock *ioc,\n> +                                                      const char *key,\n> +                                                      Error **errp)\n>   {\n>       char combined_key[QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN +\n>                         QIO_CHANNEL_WEBSOCK_GUID_LEN + 1];\n> -    char *accept = NULL, *response = NULL;\n> -    size_t responselen;\n> +    char *accept = NULL;\n> +    char *date = qio_channel_websock_date_str();\n>   \n>       g_strlcpy(combined_key, key, QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN + 1);\n>       g_strlcat(combined_key, QIO_CHANNEL_WEBSOCK_GUID,\n> @@ -271,105 +346,108 @@ static int qio_channel_websock_handshake_send_response(QIOChannelWebsock *ioc,\n>                               QIO_CHANNEL_WEBSOCK_GUID_LEN,\n>                               &accept,\n>                               errp) < 0) {\n> -        return -1;\n> +        qio_channel_websock_handshake_send_res_err(\n> +            ioc, QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_SERVER_ERR);\n> +        return;\n>       }\n>   \n> -    response = g_strdup_printf(QIO_CHANNEL_WEBSOCK_HANDSHAKE_RESPONSE, accept);\n> -    responselen = strlen(response);\n> -    buffer_reserve(&ioc->encoutput, responselen);\n> -    buffer_append(&ioc->encoutput, response, responselen);\n> +    qio_channel_websock_handshake_send_res(\n> +        ioc, QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_OK, date, accept);\n>   \n> +    g_free(date);\n>       g_free(accept);\n> -    g_free(response);\n> -\n> -    return 0;\n>   }\n>   \n> -static int qio_channel_websock_handshake_process(QIOChannelWebsock *ioc,\n> -                                                 char *buffer,\n> -                                                 Error **errp)\n> +static void qio_channel_websock_handshake_process(QIOChannelWebsock *ioc,\n> +                                                  char *buffer,\n> +                                                  Error **errp)\n>   {\n>       QIOChannelWebsockHTTPHeader hdrs[32];\n>       size_t nhdrs = G_N_ELEMENTS(hdrs);\n>       const char *protocols = NULL, *version = NULL, *key = NULL,\n>           *host = NULL, *connection = NULL, *upgrade = NULL;\n>   \n> -    nhdrs = qio_channel_websock_extract_headers(buffer, hdrs, nhdrs, errp);\n> +    nhdrs = qio_channel_websock_extract_headers(ioc, buffer, hdrs, nhdrs, errp);\n>       if (!nhdrs) {\n> -        return -1;\n> +        return;\n>       }\n>   \n>       protocols = qio_channel_websock_find_header(\n>           hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_PROTOCOL);\n>       if (!protocols) {\n>           error_setg(errp, \"Missing websocket protocol header data\");\n> -        return -1;\n> +        goto bad_request;\n>       }\n>   \n>       version = qio_channel_websock_find_header(\n>           hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_VERSION);\n>       if (!version) {\n>           error_setg(errp, \"Missing websocket version header data\");\n> -        return -1;\n> +        goto bad_request;\n>       }\n>   \n>       key = qio_channel_websock_find_header(\n>           hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_KEY);\n>       if (!key) {\n>           error_setg(errp, \"Missing websocket key header data\");\n> -        return -1;\n> +        goto bad_request;\n>       }\n>   \n>       host = qio_channel_websock_find_header(\n>           hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_HOST);\n>       if (!host) {\n>           error_setg(errp, \"Missing websocket host header data\");\n> -        return -1;\n> +        goto bad_request;\n>       }\n>   \n>       connection = qio_channel_websock_find_header(\n>           hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_CONNECTION);\n>       if (!connection) {\n>           error_setg(errp, \"Missing websocket connection header data\");\n> -        return -1;\n> +        goto bad_request;\n>       }\n>   \n>       upgrade = qio_channel_websock_find_header(\n>           hdrs, nhdrs, QIO_CHANNEL_WEBSOCK_HEADER_UPGRADE);\n>       if (!upgrade) {\n>           error_setg(errp, \"Missing websocket upgrade header data\");\n> -        return -1;\n> +        goto bad_request;\n>       }\n>   \n>       if (!g_strrstr(protocols, QIO_CHANNEL_WEBSOCK_PROTOCOL_BINARY)) {\n>           error_setg(errp, \"No '%s' protocol is supported by client '%s'\",\n>                      QIO_CHANNEL_WEBSOCK_PROTOCOL_BINARY, protocols);\n> -        return -1;\n> +        goto bad_request;\n>       }\n>   \n>       if (!g_str_equal(version, QIO_CHANNEL_WEBSOCK_SUPPORTED_VERSION)) {\n>           error_setg(errp, \"Version '%s' is not supported by client '%s'\",\n>                      QIO_CHANNEL_WEBSOCK_SUPPORTED_VERSION, version);\n> -        return -1;\n> +        goto bad_request;\n>       }\n>   \n>       if (strlen(key) != QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN) {\n>           error_setg(errp, \"Key length '%zu' was not as expected '%d'\",\n>                      strlen(key), QIO_CHANNEL_WEBSOCK_CLIENT_KEY_LEN);\n> -        return -1;\n> +        goto bad_request;\n>       }\n>   \n>       if (!g_strrstr(connection, QIO_CHANNEL_WEBSOCK_CONNECTION_UPGRADE)) {\n>           error_setg(errp, \"No connection upgrade requested '%s'\", connection);\n> -        return -1;\n> +        goto bad_request;\n>       }\n>   \n>       if (!g_str_equal(upgrade, QIO_CHANNEL_WEBSOCK_UPGRADE_WEBSOCKET)) {\n>           error_setg(errp, \"Incorrect upgrade method '%s'\", upgrade);\n> -        return -1;\n> +        goto bad_request;\n>       }\n>   \n> -    return qio_channel_websock_handshake_send_response(ioc, key, errp);\n> +    qio_channel_websock_handshake_send_res_ok(ioc, key, errp);\n> +    return;\n> +\n> + bad_request:\n> +    qio_channel_websock_handshake_send_res_err(\n> +        ioc, QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_BAD_REQUEST);\n>   }\n>   \n>   static int qio_channel_websock_handshake_read(QIOChannelWebsock *ioc,\n> @@ -393,20 +471,20 @@ static int qio_channel_websock_handshake_read(QIOChannelWebsock *ioc,\n>                                    QIO_CHANNEL_WEBSOCK_HANDSHAKE_END);\n>       if (!handshake_end) {\n>           if (ioc->encinput.offset >= 4096) {\n> +            qio_channel_websock_handshake_send_res_err(\n> +                ioc, QIO_CHANNEL_WEBSOCK_HANDSHAKE_RES_TOO_LARGE);\n>               error_setg(errp,\n>                          \"End of headers not found in first 4096 bytes\");\n> -            return -1;\n> +            return 1;\n>           } else {\n>               return 0;\n>           }\n>       }\n>       *handshake_end = '\\0';\n>   \n> -    if (qio_channel_websock_handshake_process(ioc,\n> -                                              (char *)ioc->encinput.buffer,\n> -                                              errp) < 0) {\n> -        return -1;\n> -    }\n> +    qio_channel_websock_handshake_process(ioc,\n> +                                          (char *)ioc->encinput.buffer,\n> +                                          errp);\n>   \n>       buffer_advance(&ioc->encinput,\n>                      handshake_end - (char *)ioc->encinput.buffer +\n> @@ -438,8 +516,15 @@ static gboolean qio_channel_websock_handshake_send(QIOChannel *ioc,\n>   \n>       buffer_advance(&wioc->encoutput, ret);\n>       if (wioc->encoutput.offset == 0) {\n> -        trace_qio_channel_websock_handshake_complete(ioc);\n> -        qio_task_complete(task);\n> +        if (wioc->io_err) {\n> +            trace_qio_channel_websock_handshake_fail(ioc);\n> +            qio_task_set_error(task, wioc->io_err);\n> +            wioc->io_err = NULL;\n> +            qio_task_complete(task);\n> +        } else {\n> +            trace_qio_channel_websock_handshake_complete(ioc);\n> +            qio_task_complete(task);\n> +        }\n>           return FALSE;\n>       }\n>       trace_qio_channel_websock_handshake_pending(ioc, G_IO_OUT);\n> @@ -458,6 +543,11 @@ static gboolean qio_channel_websock_handshake_io(QIOChannel *ioc,\n>   \n>       ret = qio_channel_websock_handshake_read(wioc, &err);\n>       if (ret < 0) {\n> +        /*\n> +         * We only take this path on a fatal I/O error reading from\n> +         * client connection, as most of the time we have an\n> +         * HTTP 4xx err response to send instead\n> +         */\n>           trace_qio_channel_websock_handshake_fail(ioc);\n>           qio_task_set_error(task, err);\n>           qio_task_complete(task);\n> @@ -469,6 +559,10 @@ static gboolean qio_channel_websock_handshake_io(QIOChannel *ioc,\n>           return TRUE;\n>       }\n>   \n> +    if (err) {\n> +        error_propagate(&wioc->io_err, err);\n> +    }\n> +\n>       trace_qio_channel_websock_handshake_reply(ioc);\n>       qio_channel_add_watch(\n>           wioc->master,\n>","headers":{"Return-Path":"<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>","X-Original-To":"incoming@patchwork.ozlabs.org","Delivered-To":"patchwork-incoming@bilbo.ozlabs.org","Authentication-Results":["ozlabs.org;\n\tspf=pass (mailfrom) smtp.mailfrom=nongnu.org\n\t(client-ip=2001:4830:134:3::11; helo=lists.gnu.org;\n\tenvelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org;\n\treceiver=<UNKNOWN>)","ozlabs.org;\n\tdkim=fail reason=\"signature verification failed\" (2048-bit key;\n\tunprotected) header.d=gmail.com header.i=@gmail.com\n\theader.b=\"NJT/thVD\"; dkim-atps=neutral"],"Received":["from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11])\n\t(using TLSv1 with cipher AES256-SHA (256/256 bits))\n\t(No client certificate requested)\n\tby ozlabs.org (Postfix) with ESMTPS id 3xpj8110rmz9s7p\n\tfor <incoming@patchwork.ozlabs.org>;\n\tSat,  9 Sep 2017 02:14:41 +1000 (AEST)","from localhost ([::1]:46329 helo=lists.gnu.org)\n\tby lists.gnu.org with esmtp (Exim 4.71) (envelope-from\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>)\n\tid 1dqLvT-00029s-7b\n\tfor incoming@patchwork.ozlabs.org; Fri, 08 Sep 2017 12:14:39 -0400","from eggs.gnu.org ([2001:4830:134:3::10]:33609)\n\tby lists.gnu.org with esmtp (Exim 4.71)\n\t(envelope-from <philippe.mathieu.daude@gmail.com>)\n\tid 1dqLv6-00029P-A0\n\tfor qemu-devel@nongnu.org; Fri, 08 Sep 2017 12:14:18 -0400","from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71)\n\t(envelope-from <philippe.mathieu.daude@gmail.com>)\n\tid 1dqLv2-000710-UW\n\tfor qemu-devel@nongnu.org; Fri, 08 Sep 2017 12:14:16 -0400","from mail-qk0-x243.google.com ([2607:f8b0:400d:c09::243]:37498)\n\tby eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16)\n\t(Exim 4.71) (envelope-from <philippe.mathieu.daude@gmail.com>)\n\tid 1dqLv2-0006zh-OL\n\tfor qemu-devel@nongnu.org; Fri, 08 Sep 2017 12:14:12 -0400","by mail-qk0-x243.google.com with SMTP id r66so1633326qke.4\n\tfor <qemu-devel@nongnu.org>; Fri, 08 Sep 2017 09:14:12 -0700 (PDT)","from [192.168.1.10] ([181.93.89.178])\n\tby smtp.gmail.com with ESMTPSA id\n\to38sm1539083qko.33.2017.09.08.09.14.08\n\t(version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128);\n\tFri, 08 Sep 2017 09:14:10 -0700 (PDT)"],"DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025;\n\th=sender:subject:to:cc:references:from:message-id:date:user-agent\n\t:mime-version:in-reply-to:content-language:content-transfer-encoding; \n\tbh=H1DST5pbhdEe9JQ4GXVfCJ2Pt2p+6eKVPsHAZtJCZDY=;\n\tb=NJT/thVDs+WUMFdBW3Me43ULKqUpCxO5bniKiONr2dE3gExDsnwwO/4pXARPn730ld\n\tisOB3lQv2U3MrwG+yQIAB2C8XfUbzxGWTJjVI3j3Ur48LBlYYPzcQgIAa0MXlUrULNRN\n\tEIL/R7CikiMRb0xET/NzwO2qY545mI7dUUfqJUqcQ9Y29bYxp2IoaZeaeN/Q1TMFwmkE\n\tgvKTNc7W4VV+qoF93hWKjkdHdkermEdExVArepx4VlBLVxESgONcKj8E4NBe1ONJYeyw\n\tWUjx0IY4Fp9oreCkC1nod85bknpPfEN6eo+bVccRDQ9krkHxDe/m/8KZjA0rcFiC7hYa\n\tYP7g==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n\td=1e100.net; s=20161025;\n\th=x-gm-message-state:sender:subject:to:cc:references:from:message-id\n\t:date:user-agent:mime-version:in-reply-to:content-language\n\t:content-transfer-encoding;\n\tbh=H1DST5pbhdEe9JQ4GXVfCJ2Pt2p+6eKVPsHAZtJCZDY=;\n\tb=Oct6MNCLx05l4atT7sN9XI500xKPJwiteL7Xh6TJt61KAv/IbxqLXFf4vTKVk3m6ci\n\ty4VSxtMD2Y9gwycwxBcSPo9gtkGED/v1cua0p2qrZR0yg4+6GCoALmHYt2aAjAN+dbiL\n\tY6W6i1NA0B0jupMwyNKo7nY3eFml3BywkSYz08F3E3xmLD+l+1yeGpMz20AgD1IlqzsO\n\txzu8kcwc4FI+c9HkNATDRddD/fZGOl4V0Ck/tbwWbJaCDY/0Eki/FhCigglC2C43Nx+O\n\tEnUPU8tQQ6FNE2z7TTZAFbJy9kUJkc2C7+XEVhcPBFewXGS4FdcTPwQ299n//aHQt5eG\n\tVUkA==","X-Gm-Message-State":"AHPjjUj671GHY9C9AZZiGkutadgzE8o7wBAwR8epuZLP+0I4fOkepKPL\n\tn8JQML8zkp+R2g==","X-Google-Smtp-Source":"AOwi7QDdQAIxOO7yy0mVkSVQe2ChgbzNmjqFvK370fPqFvn0Nb81TFGjNfFBUsK6yKNzXA/NphiStg==","X-Received":"by 10.55.116.134 with SMTP id p128mr4374890qkc.50.1504887251953; \n\tFri, 08 Sep 2017 09:14:11 -0700 (PDT)","To":"\"Daniel P. Berrange\" <berrange@redhat.com>, qemu-devel@nongnu.org","References":"<20170908135831.10556-1-berrange@redhat.com>\n\t<20170908135831.10556-2-berrange@redhat.com>","From":"=?utf-8?q?Philippe_Mathieu-Daud=C3=A9?= <f4bug@amsat.org>","Message-ID":"<788c7aad-fab1-a6da-3d63-bedc270de023@amsat.org>","Date":"Fri, 8 Sep 2017 13:14:06 -0300","User-Agent":"Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101\n\tThunderbird/52.3.0","MIME-Version":"1.0","In-Reply-To":"<20170908135831.10556-2-berrange@redhat.com>","Content-Type":"text/plain; charset=utf-8; format=flowed","Content-Language":"en-US","Content-Transfer-Encoding":"8bit","X-detected-operating-system":"by eggs.gnu.org: Genre and OS details not\n\trecognized.","X-Received-From":"2607:f8b0:400d:c09::243","Subject":"Re: [Qemu-devel] [PATCH v3 1/3] io: send proper HTTP response for\n\twebsocket errors","X-BeenThere":"qemu-devel@nongnu.org","X-Mailman-Version":"2.1.21","Precedence":"list","List-Id":"<qemu-devel.nongnu.org>","List-Unsubscribe":"<https://lists.nongnu.org/mailman/options/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=unsubscribe>","List-Archive":"<http://lists.nongnu.org/archive/html/qemu-devel/>","List-Post":"<mailto:qemu-devel@nongnu.org>","List-Help":"<mailto:qemu-devel-request@nongnu.org?subject=help>","List-Subscribe":"<https://lists.nongnu.org/mailman/listinfo/qemu-devel>,\n\t<mailto:qemu-devel-request@nongnu.org?subject=subscribe>","Cc":"Brian Rak <brak@vultr.com>","Errors-To":"qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org","Sender":"\"Qemu-devel\"\n\t<qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org>"}}]