Subject: Re: [hybi] WebSocket protocol as it stands

From: Willy Tarreau <[email-masked]>
Date: Sat, 6 Nov 2010 17:45:09 +0100

Hi Ryan,

On Sat, Nov 06, 2010 at 03:44:09PM +0000, Ryan Worsley wrote:
> Hi Willy et al,
> 
> I've been doing a lot of digging to get to the bottom of this behaviour in
> asp.net.  I've had some excellent conversations with the guys at Microsoft
> after Scott Guthrie hooked me up with the people in the know.  I'll copy
> Stefan Shackow's response below as I believe he explains the problem
> excellently;
> 
> *The current technical issue for our stack is that the low-level Windows
> HTTP driver that handles incoming HTTP request (http.sys) does not recognize
> the current websockets format as having a valid entity body.  As you have
> noted, the lack of a content length header means that http.sys does not make
> the nonce bytes in the entity available to any upstack callers.  That's part
> of the work we will need to do to build websockets support into http.sys.
>  Basically we need to tweak http.sys to recognize what is really a non-HTTP
> request, as an HTTP request.

Stefan is right in that his server must not consider the nonce as a valid
body. If the server returns the 101 when it reads all the headers without
yet knowing about the nonde, then the tunnel should be established and the
nonce should automatically flow to the server-side code. The point is that
as the current spec is worded, it looks like the server should wait for those
bytes before responding with 101, and since those bytes are not supposed to
be a body, the server code can't get them.

The right thing to do in my opinion would be to respond 101 before reading
the nonce, and then wait for the nonce to come in. Several implementers had
to do that already to fix the issue.

Regards,
Willy

---

From: Ryan Worsley <[email-masked]>
Date: Sat, 6 Nov 2010 15:44:09 +0000

Hi Willy et al,

Implementation-wise this boils down to how strictly a server-side HTTP
listener interprets incoming requests as HTTP.  For example a server stack
that instead treats port 80 as a TCP/IP socket as opposed to an HTTP
endpoint can readily do whatever it wants with the websockets initiation
request.  We have some client samples, and sample websockets endpoint that
the WCF team is working on that use this approach (details here:
http://tomasz.janczuk.org/2010/07/silverlight-html5-websocket-client-with.html).
 However that work is in flux right now, and I don't what the timelines are
for releasing any prototypes on codeplex.com.

For our server-side HTTP stack we do plan to make the necessary changes to
support websockets since we want IIS and ASP.NET <http://asp.net/> to handle
websockets workloads in the future.  We have folks keeping an eye on the
websockets spec as it progresses and we do plan to make whatever changes are
necessary in the future.*
*
*
---

I personally hope that the next WebSocket draft doesn't require this
somewhat awkward behaviour as it'll necessitate a rewrite of the http stack
in asp.net, which means those of us working with those technologies could be
left out in the cold for a time.

Thanks for all your help, I hope this summary is of use to someone.

Regards,

Ryan Worsley.

On 30 October 2010 17:08, Willy Tarreau <[email-masked]> wrote:

> Hi Ryan,
>
> On Sat, Oct 30, 2010 at 04:39:44PM +0100, Ryan Worsley wrote:
> > Hi Willy,
> >
> > Thanks for your considered reply, I actually confirmed this behaviour by
> > using a Microsoft application called wfetch.  if I insert a
> content-length
> > header into the message the body gets through just fine.
>
> I'm not surprized.
>
> > I understand your approach to be to send the response headers immediately
> > and then attempting to read the message body as we're now in a different
> > mode.
>
> It's not a body, it's the beginning of the tunnelled data. The difference
> is precisely that if it were a body, it would be covered by a
> content-length.
> When I first reported this issue a few months ago, I was told that we don't
> want to put a content-length because the goal was precisely to ensure that
> only completely compliant intermediaries would let this pass through.
>
> > Unfortunately this didn't work in IIS and I think I can explain why.
> >
> > At the point at which my application runs, the incoming http message has
> > been processed and packaged into a data structure that is handed to it.
>  No
> > further processing can be done at this point on the inbound message.  I
> can
> > listen on the incoming stream for further data from the client, but the
> body
> > has already been sent and disregarded.
>
> But if you use this data as the incoming stream, are you able to read it ?
> I certainly agree that you can't get it as a body since it's not advertised
> as such.
>
> > It might be possible in my case to hook in at a much lower level of the
> > request processing pipeline.  I'm not sure, so I've posted a request for
> > information on the IIS community forums.
> >
> > Is there any chance that you'll include content-length in the next draft?
>
> Apparently no due to the explanation above. Also, it's possible that a
> next draft will rely again on a completely different handshake.
>
> > What is the ETA of your next draft?
>
> I have no idea.
>
> > Does this aforementioned behaviour make IIS compliant or non compliant?
>
> If IIS does not pass you those 8 bytes as a body, then it's right not to
> do so. However, once you respond the 101 and the headers, it should let
> the data flow between both sides, resulting in the pending 8 bytes to
> reach your application. If you can't get those bytes, it would be nice
> to find out why.
>
> Regards,
> Willy
>
>