Re: [hybi] Redesigning the Web Socket handshake

Vladimir Katardjiev <vladimir@d2dx.com> Tue, 02 February 2010 09:13 UTC

Return-Path: <vladimir@d2dx.com>
X-Original-To: hybi@core3.amsl.com
Delivered-To: hybi@core3.amsl.com
Received: from localhost (localhost [127.0.0.1]) by core3.amsl.com (Postfix) with ESMTP id 887C528C22B for <hybi@core3.amsl.com>; Tue, 2 Feb 2010 01:13:08 -0800 (PST)
X-Virus-Scanned: amavisd-new at amsl.com
X-Spam-Flag: NO
X-Spam-Score: -2.599
X-Spam-Level:
X-Spam-Status: No, score=-2.599 tagged_above=-999 required=5 tests=[BAYES_00=-2.599]
Received: from mail.ietf.org ([64.170.98.32]) by localhost (core3.amsl.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id TATknxSK9LEc for <hybi@core3.amsl.com>; Tue, 2 Feb 2010 01:13:07 -0800 (PST)
Received: from homiemail-a2.g.dreamhost.com (mailbigip.dreamhost.com [208.97.132.5]) by core3.amsl.com (Postfix) with ESMTP id 6976228C20D for <hybi@ietf.org>; Tue, 2 Feb 2010 01:13:07 -0800 (PST)
Received: from dhcp122.verkstad.net (dhcp122.verkstad.net [192.36.157.122]) (using TLSv1 with cipher AES128-SHA (128/128 bits)) (No client certificate requested) by homiemail-a2.g.dreamhost.com (Postfix) with ESMTP id 8AD07D26BE for <hybi@ietf.org>; Tue, 2 Feb 2010 01:13:44 -0800 (PST)
From: Vladimir Katardjiev <vladimir@d2dx.com>
Content-Type: text/plain; charset="us-ascii"
Content-Transfer-Encoding: quoted-printable
Date: Tue, 02 Feb 2010 10:13:41 +0100
Message-Id: <0F4875AA-06D6-4181-9019-12E2CDA45DD5@d2dx.com>
To: hybi@ietf.org
Mime-Version: 1.0 (Apple Message framework v1077)
X-Mailer: Apple Mail (2.1077)
Subject: Re: [hybi] Redesigning the Web Socket handshake
X-BeenThere: hybi@ietf.org
X-Mailman-Version: 2.1.9
Precedence: list
List-Id: Server-Initiated HTTP <hybi.ietf.org>
List-Unsubscribe: <https://www.ietf.org/mailman/listinfo/hybi>, <mailto:hybi-request@ietf.org?subject=unsubscribe>
List-Archive: <http://www.ietf.org/mail-archive/web/hybi>
List-Post: <mailto:hybi@ietf.org>
List-Help: <mailto:hybi-request@ietf.org?subject=help>
List-Subscribe: <https://www.ietf.org/mailman/listinfo/hybi>, <mailto:hybi-request@ietf.org?subject=subscribe>
X-List-Received-Date: Tue, 02 Feb 2010 09:14:08 -0000

With regards to the HTTP compatibility, my understanding is, at least with regards to what I've personally written, as well as what I've been told by those developing Ericsson's proxy offering, that by the time you can realise an incoming request is a WebSocket request, the code assumes the response will be an HTTP request. In other words, the actual socket is now held by a class designed around the assumption that headers may be sent in any order. At least our product developers stated that if the header ordering (specifically!) was relaxed it would be easier for them (and thus more probable) to implement WebSocket support.

Having said that, I'd like to join the "WebSocket handshake header ordering requirement is eliminated"-train. This would make the handshake HTTP compliant w.r.t. both parsing and response generation, but it's still a subset of HTTP. The problem caused by this is that WebSockets now might not break on proxies it would before [1]. This issue stems from the fact that the initial WS handshake would actually be a very specific HTTP Upgrade handshake, thus not handshaking WS at all. A possible solution is to introduce a WS-framed handshake. I was actually thinking of the nonce idea too, so...

For example, client sends:
0x7F Client [nonce] Req 0xFF  (spaces between frames and text only for legibility purposes; actual bytes would be 0x7F 0x43)

Server replies with
0x7F Server [nonce] Resp 0xFF

If this second WS-specific handshake is successful, that means that either there are no intermediaries or they are WebSocket aware, as this exchange breaks the HTTP protocol much more severely than header ordering (HTTP response already sent when client sends "body", and client sends a "body" on a GET request... this is not valid HTTP any way you slice it). [2]

The downsides are

- It would introduce another round-trip on the establishment of a WebSocket connection. Given that the first request is the HTTP handshake, effectively, I believe it's warranted to add a separate WS-specific handshake that establishes the connection given by the HTTP Upgrade actually conforms to the WS requirements. 

- It uses up a frame type. If this is a big concern, we could reuse the frame for the orderly close (it doesn't make sense to see handshake frame after you've established the connection), or even state that it's a control channel that can be used for more things (e.g. keep-alive).

- It introduces additional complexity. On the flip side, this additional processing comes on the WebSocket stage of things, where byte ordering is guaranteed. Your server can send back a standard dump of HTTP headers in the simplest case, without parsing whatever the client sent. It still needs to parse the WS-specific part, but it's much simpler. In the example above, if we say nonce is 16 bytes, you can state "read 0x7F, skip 7 bytes, read 16 bytes, write 0x7F Server [same 16 bytes] Resp 0xFF". 

I believe the above suggestion lowers the barrier of entry for inclusion in existing HTTP stacks, without having to significantly modify the HTTP request/response handling code. In addition, it would still maintain the property of breaking on unaware intermediaries, and it shouldn't open up for anyone faking a websocket aware endpoint using a crafty set of headers.

Apologies if I'm repeating something on the list; there were quite a bit of messages so I might have missed one.

Cheers,
Vladimir

[1] I hold that the exact header ordering is a _probability_ but not _guarantee_ that WebSockets breaks on HTTP proxies. The rationale is that for any sorting algorithm on headers there must be a set of input values that ensures the output happens to come in the correct order. I, unfortunately, have no proof of this statement, hence footnote status.

[2] At the very least this will break the above mentioned proxy offering (in transparent mode) while it does not support WebSockets.