Subject: Re: [hybi] #1: HTTP Compliance

From: Ian Hickson <[email-masked]>
Date: Wed, 21 Jul 2010 06:47:54 +0000 (UTC)

On Wed, 19 May 2010, Jamie Lokier wrote:
> >
> > If we want to support multiple subprotocols at once, we can do so 
> > quite easily by just making the subprotocol list be comma-separated. 
> > Would this be a good idea?
> 
> I think it is a good idea, although there is a risk of low-quality 
> server but significant implementations matching a literal string, 
> breaking when other values are added to the comma-separate list, and 
> therefore making it impossible for clients to actually use the 
> capability.

Yeah, though since that bug would be specific to implementations of 
particular subprotocols, it would be pretty localised to individual 
communities. That's probably an acceptable problem.

I've added this to the spec for now.

   http://html5.org/tools/web-apps-tracker?from=5172&to=5173

> But assuming the comma-separated list did catch on, a consequence of 
> that would be the "below the API" part of WebSocket would have a place 
> to add its own distinct entries to the comma-separated list, for 
> recognition by the other side as transport option requests (such as 
> compression, etc.), safe in the knowledge it wouldn't break negotiation.
> 
> (Separate headers would be much cleaner for that, though).

I don't see why we wouldn't just use separate fields for that. No need to 
overload the subprotocol field.

> > >    - Trying a HTTP-based protocol if WebSocket is unavailable (ditto)
> > 
> > That wouldn't work anyway because the WebSocket object isn't the same 
> > object as the XMLHttpRequest object and they therefore create entirely 
> > different connections.
> 
> Just being different objects is not technical reason for different 
> connections. Separate XMLHttpRequest objects have no problem sharing 
> connections. There is no technical reason why a WebSocket object could 
> not do the same, just as easily.  Especially in browsers which routinely 
> do this!

I guess. I'm not convinced it's a good idea though.

> > In any case, why wouldn't you know that Web Socket is available? I 
> > don't understand why you would guess that it is and then find it 
> > isn't. You need a URL to connect to a Web Socket, why would you make 
> > up a URL without knowing whether it'll work?
> 
> Earlier in this thread, in a reply to you, we already gave an example. 
> It was the social networking client that talks to numerous de facto 
> standardised but different WebSocket protocols that the user shouldn't 
> have to know about.
> 
> Basically because autonegotiation is more user-friendly, both in terms 
> of users having to be given and enter fewer details, and in terms of 
> telling the user what went wrong if things didn't work out.
> 
> As you noted, people don't always pass around URLs - they often pass 
> around just a domain name, or a truncated URL that doesn't include the 
> "http:" prefix.
> 
> I would agree if it were _complicated_ to do, but we are talking about 
> really trivial stuff here.  Trying one thing, then trying another, is 
> already handled by the handshake, and it is utterly trivial to do from a 
> script.  It's so easy that it's hard to see why any random web developer 
> wouldn't use it whenever it seemed like a good idea.
> 
> It seems obvious to me that countless Javascripts will do exactly that.

I could see trying multiple WebSocket protocols over one connection, but 
trying to try both HTTP or WebSocket connections, not to mention any other 
protocols the servers might provide, seems like massive complexity for 
negligible gain overall.

> > This can be supported entirely in Web Socket if we want to do that. 
> > Currently, it's not clear that supporting this is even desireable, due 
> > to the UI issues with doing so.
> 
> (On that topic, how do you propose to get through a proxy on port 443 
> that needs proxy authentication before it passes a CONNECT request?)

I guess the UA would have to use the existing (suboptimal) UI for proxy 
auth. It's not a good situation to be in; I wouldn't recommend it.

> > WebSocket and HTTP are different protocols. Reusing the connection 
> > makes as much sense as reusing the connection of an FTP connection 
> > attempt to do an HTTP connection attempt.
> 
> This is different.  Both WebSockets and HTTP requests are transient in 
> many cases.

FTP is more transient than WebSockets. WebSockets is intended for 
connections that just stay open. It's not intended for transient use. It's 
not at all designed for transient use. It will do poorly when used for 
transient use.

> If FTP was also transient, and it shared the same port with 
> HTTP, and many servers especially those designed for high performance 
> implemented both together, and many clients implemented both, then of 
> course it would make sense to _permit_ connection reuse between them, 
> without _requiring_ any implementation to do so.

I think it would be pretty silly even in those cases, personally. Reusing 
connections amongst multiple protocols is simply asking for bugs. The 
benefits are minimal and the costs are high. If you want to do multiple 
things on a connection, use a protocol that supports all those things, 
don't try to switch back and forth between protocols.

(By extension, I think the Upgrade mechanism in HTTP isn't a particularly 
good idea. The number of times the mechanism has been used to great 
success on the Web somewhat supports my position on this, I think.)

> There is a much stronger case for reusing a WebSocket connection after a 
> gracefully close that puts it into some kind of idle state.  That's 
> because users follow links every few seconds - and therefore WebSocket 
> scripts in ordinary pages will connect and disconnect from the same 
> server and port every few seconds in the current model.

What use cases are you imagining that have Web Sockets used in such 
scenarios? None of the intended use cases even remotely resemble this. Web 
Sockets is intended for use on pages that are long-lived. It's quite 
possible that there are use cases on short-lived pages also, but they 
probably need their own protocol, optimised for those cases (e.g. HTTP and 
the text/event-stream EventSource mechanism). WebSockets isn't trying to 
be everything for everyone, it's just trying to address the specific use 
case of trivially-implementable long-lived TCP-like connections for Web 
browsers.

> Making it optional for both sides adds *zero* complexity for authors who 
> don't do it. I am not seeing how you can think it makes any difference 
> to them.

Clients have to support it. This means implementation cost, testing cost, 
and bug-fixing cost. It then propagates to documentation, which means 
reference costs, tutorial costs, etc. This further means that authors will 
see the feature in documentation. This leads to cognition costs when 
learning the material, information retrieval costs when distinguishing 
whether something is relevant or not when debugging, and communication 
costs when discussing the feature with others, e.g. when determining 
whether the feature is relevant to the question someone is asking. Then 
there's the cost of maintaining code that someone else has written that 
_does_ use the feature, there's the cost of debugging browser bugs when 
the feature is misimplemented and interacts even with code that doesn't 
use the feature, and finally there's the cost of implementing the feature 
on the server side once it makes its way onto check-mark lists of features 
that every web developer customer wants to support.

> Seriously, how do you imagine it affects them?

Optional features are a lie. Nothing is really optional in a platform like 
the Web's -- the only way a feature can be "free" is if it doesn't exist. 
This is why we have to justify everything we add, and make sure it's on 
the right side of the 80/20 line.

> > who would have no idea why their WebSocket servers were suddenly 
> > receiving random HTTP requests and vice versa.
> 
> That's a function of connecting to the wrong type of server already, and 
> it's already dealt with by the spec'd negotation, which the wrong type 
> of server handles already by design.  Nothing new there.

If we supported connection reuse and there was misconfiguration, then the 
kinds of failure scenarios would be much more varied than they are now.

-- 
Ian Hickson               U+1047E                )\._.,--....,'``.    fL
http://ln.hixie.ch/       U+263A                /,   _.. \   _\  ;`._ ,.
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'

---

From: John Tamplin <[email-masked]>
Date: Wed, 21 Jul 2010 10:15:42 -0400

On Mon, May 17, 2010 at 5:29 AM, Maciej Stachowiak <[email-masked]> wrote:

> Ian has claimed that the extra bytes after the request help WebSocket fail
> early in the face of unaware proxies, though we do not yet have data showing
> this to be the case. We do know that without this, often the handshake will
> appear to succeed but transmitting messages will fail, for the network
> setups of many users.
>
> I don't think anyone has indicated a practical problem caused by the extra
> bytes.
>

I believe we have already had a real-world practical case where they did
cause a problem:

   - client sends WebSocket request that goes through a proxy, random bytes
   are not advertised in the Content-length
   - proxy doesn't know WebSocket, passes along connection to real server
   which does implement WebSocket
   - server waits reading random bytes which were not forwarded
   - server drops the connection after a timeout

Thus the random bytes did succeed in preventing a WebSocket connection
across a non-WS compliant proxy, but:

   1. the proxy was actually capable of forwarding the connection if the
   server had completed the request
   2. we had to wait for a timeout, so this was not a fast-fail situation
   3. the same thing could have been more easily accomplished by having a WS
   control frame exchanged at startup with similar results without
   non-compliant random bytes on the wire

-- 
John A. Tamplin
Software Engineer (GWT), Google

---

From: John Tamplin <[email-masked]>
Date: Wed, 21 Jul 2010 10:27:37 -0400

On Tue, May 18, 2010 at 5:16 PM, Ian Hickson <[email-masked]> wrote:

> On Tue, 18 May 2010, Greg Wilkins wrote:
> >
> > If the handshake is HTTP compliant, then the connection for a websocket
> > handshake could be taken from the existing pool of idle connections to a
> > host.  That would save the time needed to establish the connection.
>
> The resemblence to HTTP is nothing more than a hack to alolow us to share
> ports in certain advanced scenarios. Most Web Socket servers will know
> nothing about HTTP.

I disagree completely -- there is going to be a web server involved in
delivering the web application, and I think the more usual scenario is that
web server also implements the WebSocket server.  Why would someone prefer
to deploy two servers rather than one, except in the case where their web
server doesn't yet support WebSocket?  If this protocol is successful, over
time that will drop to 0.

> Reusing connections is a level of complexity that is
> completely unwarranted and that would only be useful in the rarest of
> cases. It's a proposal that lies on completely the wrong side of the 80/20
> line and would introduce _massive_ complexity for authors, who would have
> no idea why their WebSocket servers were suddenly receiving random HTTP
> requests and vice versa.

I'm not sold on connection reuse, but I am not sure where these random HTTP
requests would be coming from.  If a connection was to ws://foo.org/socket,
the connection was closed, and then another connection was needed for
http://foo.org/image.gif, presumably the server at foo.org:80 is capable of
answering either request since it would have had to handle either request on
a new connection.  If instead it was ws://socket.foo.org/socket, then
obviously that connection would not be used to reach www.foo.org.

I'm not sure that adding connection keep-alive and/or restarting the
handshake is justified by the benefits, but I don't see where your argument
comes from.

---

From: Willy Tarreau <[email-masked]>
Date: Wed, 21 Jul 2010 16:34:44 +0200

>    - server drops the connection after a timeout

Confirmed. And it will fail with any HTTP reverse-proxy. And if you manage
to make an HTTP reverse-proxy work with the current scheme, then this
rev-proxy can be tricked by the client into sending uncontrolled requests
to the server (by just setting the "Upgrade" option that the server will
ignore).

>    non-compliant random bytes on the wire

And it would have worked without requiring any change to deployed components.

Regards,
Willy

---

From: Roberto Peon <[email-masked]>
Date: Wed, 21 Jul 2010 07:43:03 -0700

> protocols the servers might provide, seems like massive complexity for
I fully expect that we'll end up with multiple websocket "sockets" per tab,
and we typically end up with many tabs.
This is true even if going to only one large site. For instance, it is
fairly normal to have both corporate and personal email and calendering open
at all times.
If each websocket is its own TCP socket, we'll face a drastic increase in
the number of connections from everyone.
Worse, these connections won't go away, they'll send junk bytes all the time
(keep alives), they'll be unable to go to the same server if one is using
loadbalancing, they'll have more than an order of magnitude greater chance
to overload NAT tables, they'll make DST caches in the kernel less effective
due to dilution (for smaller servers), etc.

Each and every of these is a good reason that the complexity is warranted.
I have some "small" experience with ensuring that things can serve at-scale.
There are very good reasons that I'm concerned about websocket scalability.

As for complexity! At worst, you have flow control and multiplexing.
 Multiplexing involves a unique ID per channel. Flow control involves
sending periodic updates telling the other side how much it can send safely.
Of course you also need to have a table in which you do a lookup to see that
there is already a connection for that domain, including a reference to
that connection. None of this is difficult, even in concert.

-=R

> _______________________________________________
> hybi mailing list
> [email-masked]
> https://www.ietf.org/mailman/listinfo/hybi
>

---

From: John Tamplin <[email-masked]>
Date: Wed, 21 Jul 2010 10:47:37 -0400

On Wed, Jul 21, 2010 at 10:43 AM, Roberto Peon <[email-masked]> wrote:

> Worse, these connections won't go away, they'll send junk bytes all the
> time (keep alives), they'll be unable to go to the same server if one is
> using loadbalancing, they'll have more than an order of magnitude greater
> chance to overload NAT tables, they'll make DST caches in the kernel less
> effective due to dilution (for smaller servers), etc.
>
> I have some "small" experience with ensuring that things can serve
> at-scale. There are very good reasons that I'm concerned about websocket
> scalability.
>

Another benefit of muxing multiple WS connections over a single TCP
connection is you can have only one keep-alive for all of them.  And I think
WS really needs to have some keep-alive frame -- if not, then you are just
pushing the requirement off to the client code using the WS, and then it
won't be done consistently or in a way that can be aggregated.

---

From: Roberto Peon <[email-masked]>
Date: Wed, 21 Jul 2010 07:54:14 -0700

> success on the Web somewhat supports my position on this, I think.)

The UPGRADE mechanism was a fine idea. Poor transparent proxy
implementations have killed its effectiveness.
-=R

---

From: Willy Tarreau <[email-masked]>
Date: Wed, 21 Jul 2010 17:15:31 +0200

> implementations have killed its effectiveness.

Do we have reports of failures due to transparent proxies ? As of now,
the only failure I'm aware of is due to the unadvertised bytes which
is not compatible with HTTP.

Willy

---

From: Roberto Peon <[email-masked]>
Date: Wed, 21 Jul 2010 08:22:11 -0700

I believe Mike quoted numbers in an earlier thread.

Just to be sure we're talking about the same thing, I'm talking about the
UPGRADE feature of HTTP generically, and not as it applies to the current
draft Websocket spec.
-=R

---

From: Willy Tarreau <[email-masked]>
Date: Wed, 21 Jul 2010 17:45:19 +0200

> UPGRADE feature of HTTP generically, and not as it applies to the current

I thought they were related to the current version since it also uses
Upgrade. Anyway, even if some don't support it yet, it will be easy
to detect bypass them based on simple rules.

Willy

---

From: Ian Hickson <[email-masked]>
Date: Wed, 21 Jul 2010 22:54:47 +0000 (UTC)

On Wed, 21 Jul 2010, John Tamplin wrote:
> > Ian has claimed that the extra bytes after the request help WebSocket 
> > fail early in the face of unaware proxies, though we do not yet have 
> > data showing this to be the case. We do know that without this, often 
> > the handshake will appear to succeed but transmitting messages will 
> > fail, for the network setups of many users.
> >
> > I don't think anyone has indicated a practical problem caused by the 
> > extra bytes.
> 

Success! :-)

>    server had completed the request

That's easy to resolve. The simplest solution that comes to mind is having 
the server send back the 101 straight away, and having the proxy send the 
bytes on as soon as it sees the 101.

(Note: from a conformance standpoint, the "server" includes the proxy.)

>    2. we had to wait for a timeout, so this was not a fast-fail situation

Fast-fail is ideal, but not really necessary (there's plenty of other 
situations that fail very slowly). We just don't want false positives. If 
there's a way of tweaking the protocol so we don't get false positives, 
and still fulfills our other requirements, but that fails faster, that 
would be great.

>    non-compliant random bytes on the wire

Wouldn't that increase the startup latency by another round-trip?

---

From: Willy Tarreau <[email-masked]>
Date: Thu, 22 Jul 2010 01:03:50 +0200

> >    - server drops the connection after a timeout

I fail to see how failing through perfectly valid components can be qualified
as a success. It really seems that your goal is to ensure a general failure :-(

> bytes on as soon as it sees the 101.

Ah goodness, it sounds like you finally got that one !

> (Note: from a conformance standpoint, the "server" includes the proxy.)

as seen from the client, yes. As seen from the proxy or the server or any
intermediate between them, no :-)

> and still fulfills our other requirements, but that fails faster, that 

Please check my proposal in a separate mail. I should detect more unreliable
components, work through more reliable ones and avoid one round-trip.

Willy

---

From: Greg Wilkins <[email-masked]>
Date: Thu, 22 Jul 2010 09:09:45 +1000

On 22 July 2010 00:27, John Tamplin <[email-masked]> wrote:

>
> I'm not sold on connection reuse
>

Just to clearly (re)state a good use-case for connection reuse.

Currently the WS handshake can only be rejected by closing the connection
and discarding any potential HTTP response.  Thus a webapp that wishes to
fall back to a non-ws transport will have to establish a new connection,
maybe negotiate TLS, then handshake the new transport.   Thus there will be
an extra 2 or 3 round trips to establish the fall-back transport.

This is already a problem for cometd-2, as it will try WS and then fallback
to long polling.  I can visibly tell when establishing a chat room if I have
the WS transport enabled  in the client or not, because I can see the extra
delays as WS is tried and fails.

This will be a barrier to frameworks like cometd-2 including WS in their
transport negotiations.

---

From: Jamie Lokier <[email-masked]>
Date: Thu, 22 Jul 2010 00:37:06 +0100

Roberto Peon wrote:
> 
>    On Tue, Jul 20, 2010 at 11:47 PM, Ian Hickson <[1][email-masked]> wrote:
> 

Fwiw, this has happened before in generic HTTP clients, including some
major browsers, so it wasn't localised to particular communities.  I
guess requiring "Connection: close" to be literally that without
anything else on the line has gone away now :-) But I'm still not sure
if there are HTTP clients/servers in use which would match
",somekeyword," inside a quoted string in a HTTP header where such
things aren't meant to be matched...

>      I don't see why we wouldn't just use separate fields for that. No
>      need to overload the subprotocol field.

It cannot use the subprotocol field if the *current* spec gets
significantly deployed, because the client Javascript sets the
subprotocol field, and the server is entitled to expect to get
*exactly* what the client Javascript sets.

That means WebSocket client implementations cannot transparently
append comma-separated keywords to the subprotocol field without
breaking expectations.

I really hope we sort out feature negotation before there's any
significant deployment.

We should also keep in mind that "below the API" isn't always going to
be a clear line.  Some protocol features may be implementable above or
below the Javascript API, according to client capabilities, and some
might be implemented in a WS-aware proxy away from the browser (for
example keepalive modifications when crossing between different
network types).

-- Jamie

---

From: Jamie Lokier <[email-masked]>
Date: Thu, 22 Jul 2010 00:38:34 +0100

> to detect bypass them based on simple rules.

Um, will it?  How would that work?

-- Jamie

---

From: Willy Tarreau <[email-masked]>
Date: Thu, 22 Jul 2010 02:08:09 +0200

Hi Jamie,

> Um, will it?  How would that work?

Basically at some (many?) ISPs, you can find such an architecture :

  [ ISP's clients ]
      \  |  /
        POP
         |
         |
      routers
         |               / cache
    L7 load balancer ---<- cache
         |               \ cache
         |
      routers
         |
     (internet)

The clients connect to somesite.com:80. At least they believe they do
so. The first layer of routers see "port 80" and decide to forward to
the load balancers, otherwise they forward everything to the internet.
Obviously there are variants, it is possible that everything is sent
to the LBs too, that's just an example. The LBs have to support 3 main
features :

  - check if the URL has to be handled by the cache farm or not. If
    not, let's simply route it to the internet.

  - bypass the caches if too many are dead so that the remaining ones
    can't handle the load.

  - apply a load balancing algorithm on the request (eg: URL hash)
    to select a working cache, and forward the request to that cache.
    The request is sent unmodified and the cache receives the packets
    with the original destination IP address (sometimes they just rely
    on the Host header though).

The first point is crucial. If the LB sends everything to caches, it
costs a lot in terms of hardware, especially if the hardware is not
suited to the type of application (imagine streaming video over a
classical cache for instance, it would eat long-lived connections
and CPU for zero added value). Also, there are always some cases
where a bug or incompatibility will be discovered on the caches and
they will have to be bypassed for some sites or request types. Last,
they can degrade quality of service without bringing anything (eg:
when dealing with XMLHttpRequest or interactive applications).

This is the reason why the LBs in front of the cache are said to be
Layer7, they're HTTP-aware. Alteon was already doing a lot of business
with their products 10 years ago on this precise feature. Thus, the
ISP has the ability to add rules which check the HTTP requests and
decide whether or not it makes sense to send it to the cache farm
or if it's easier to forward it to the server.

The only prerequisite is that the L7 LB is HTTP-compliant, or at
least understands HTTP enough so that everything that it decides
to forward without passing through the caches will be unmodified.

The goal of the ISP is not to *control* what passes there, but to
*save bandwidth*. That means that rules can be very coarse. Some
will simply decide that any URL containing a question mark will
bypass the caches. Others will decide that youtube has too much
data to store locally and that it's better to bypass the cache
than thrashing it with youtube-only contents.

And others will simply say that any connection containing
"Upgrade: WebSocket" will bypass the caches. But for that to work,
the HTTP-like protocol has to be HTTP-compatible ;-)

Hoping this clarifies the things a bit,
Willy

---

From: Jamie Lokier <[email-masked]>
Date: Thu, 22 Jul 2010 01:11:05 +0100

Greg Wilkins wrote:
>    I can visibly tell when establishing a
>    chat room if I have the WS transport enabled in the client or not,
>    because I can see the extra delays as WS is tried and fails.
>    This will be a barrier to frameworks like cometd-2 including WS in
>    their transport negotiations.

(Aside: I think Ian's past responses suggest the following resolution:
When you're establishing a chat room connection, you *ought* to know
if you're connecting to a WS-aware chat service, in the same way that
you already must know in advance which WS subprotocol to request
if you do get a WS connection.)

As noted some time ago, even when WS negotation *succeeds*, it can be
slower than comet-style HTTP, both slower in sending the first
messages, and slower in receiving the first responses.

That situation is ridiculous.

It means latency-optimised apps may open *two* connections in
parallel: One comet-style HTTP, and one WebSocket.  They will
communicate initial messages over the HTTP connection, and switch to
the WebSocket connection when that is ready.  That's not kind on
low bandwidth links, nor easy to program, so it's an ugly compromise.

We can greatly improve the situation by avoiding some delays in the
negotiation sequence.

Unfortunately it seems each "waiting point" needs a different method
of avoidance, so TLS negotation round trip delay is reduced only by
using an ignorable TLS extension to carry initial messages; HTTP
handshake round trip delay is reduced only by encoding initial
messages in a HTTP-compatible manner, post-HTTP confirmation round
trip delay is removed only by encoding initial messages in a way that
is harmless to non-WS servers, and delays to messages originating
between those stages are reduced only by rather fiddly inter-stage
encodings.

(Ideally we'd avoid the TCP 3-way handshake round trip too by
including some data in the SYN, finally outperforming HTTP :-), but I
have the uncertain impression that's considered inadvisable.)

Fortunately there is a systematic approach possible, even though the
details are annoyingly technical, and fortunately each step could be
optionally implemented or not according to the implementer's
preference.  Simple implementations could ignore them entirely.

-- Jamie

---

From: Jamie Lokier <[email-masked]>
Date: Thu, 22 Jul 2010 01:22:07 +0100

> > Um, will it?  How would that work?

[Good description of transparent proxies at ISPs with configurable
HTTP-aware rules on the routers.]

Ah, I thought you meant "It will be easy to bypass *broken transparent
proxies* based on simple rules *in the WebSocket clients and/or servers*".

I.e. how to cope when the request hits a transparent proxy that
doesn't work and you're *not* the ISP.

Failing as fast as possible, and recognising it as a failure, is
highly desirable if we can manage that.  I don't know if we can.  It
would need actual experiments on a broad cross-section of the net.

-- Jamie

---

From: Willy Tarreau <[email-masked]>
Date: Thu, 22 Jul 2010 02:23:08 +0200

> low bandwidth links, nor easy to program, so it's an ugly compromise.

And it's reliance on random numbers in userspace and MD5 to hash
minuscule messages does not help at all keeping latency low !

> between those stages are reduced only by rather fiddly inter-stage

Agreed. You're defining a well-stacked model where each layer informs
the upper one about some information that may be needed for its handshake
to complete without having to wait.

> have the uncertain impression that's considered inadvisable.)

I think it was the principle of TTCP, but with TCP it's not possible
because you don't know how large the other side's buffers before you
receive the SYN-ACK which contains the MSS. However if you're interested,
I can explain to you a system-dependant way to save one ACK from the
client to the server by sending the data with the first ACK ;-)

> preference.  Simple implementations could ignore them entirely.

That's what is nice with declarative protocols such as HTTP where
you announce what you're doing. At least we should find a clean way
to be able to decide whether we want an HTTP medium or just a TCP
medium. I thought that the port was a good thing, but maybe the
protocol scheme itself speaks better (ws/wss). After all, browsers
currently use http/https for this. We could even have variants such
as :

  - WS = plain TCP, no initial handshake
  - WSS = plain TLS, no initial handshake beyond TLS
  - WSTP = WS over HTTP = HTTP initial handshake

Just a few ideas, hoping they will help others find better ones.

Regards,
Willy

---

From: Willy Tarreau <[email-masked]>
Date: Thu, 22 Jul 2010 02:29:28 +0200

> proxies* based on simple rules *in the WebSocket clients and/or servers*".

OK.

> doesn't work and you're *not* the ISP.

This happens all the time for such ISPs with simple HTTP sites that don't
display a video or something. They know about that very fast through their
forums from complaining customers, and they fix the issue using one of the
bypass rules above. And sometimes they ask the cache editor to fix their
product because they're fed up with feeding the L7 switch with bypass rules ;-)

There are not that many ISPs in each country, I mean there are far less ISPs
than there are web sites or potential WebSocket implementers. There's a high
pressure on them to work as expected by customers.

> highly desirable if we can manage that.  I don't know if we can.

That's my precise intent : fail ASAP if we know for sure it cannot work,
and don't fail for no reason when we have no proof it cannot work when
it would most likely have. Please see my proposal in another mail about
that, I think it can improve on the current handshake for that.

> It would need actual experiments on a broad cross-section of the net.

I wholeheartly agree with that. It's the first time I read about testing
before specifying on this list ! Doing so from the beginning would have
saved a lot of man-hours !

Regards,
Willy

---

From: Greg Wilkins <[email-masked]>
Date: Thu, 22 Jul 2010 10:43:46 +1000

> if you do get a WS connection.)
Jamie,

I'm afraid that the "knowledge" based resolution does not work in practise.

The server side of a webapplication can know if websocket is support on the
server, but it cannot know if is supported in the network infrastructure for
a particular deployment and/or client.

Even if the server side does know, it is the client that needs that
knowledge.   So the initial javascript loaded by the client could be
dynamically generated to indicate if websocket is supported or not - but
that would mean the js could not be cacheable (which has it's own
problems).   Alternately an Ajax request could be made by the client to the
server to ask if websocket is supported... but that is another round trip
and is essentially "handshaking" to see if it is permissible to handshake,
which then still might fail because of an intermediary unknown to both
client and server.

The simplest solution is for the client side frame work to check if
websocket is supported in the browser, and if so attempt to establish a
websocket connection to the server, which will test the infrastructure, the
server and the current server side application configuration in a single
request.  If that fails, it would be ideal if the TCP/IP and TLS session
negotiated could then be reused for subsequent HTTP based transports.

cheers

---

From: Ian Hickson <[email-masked]>
Date: Thu, 22 Jul 2010 06:32:02 +0000 (UTC)

On Wed, 21 Jul 2010, John Tamplin wrote:
> > > If the handshake is HTTP compliant, then the connection for a 
> > > websocket handshake could be taken from the existing pool of idle 
> > > connections to a host.  That would save the time needed to establish 
> > > the connection.
> >
> > The resemblence to HTTP is nothing more than a hack to alolow us to 
> > share ports in certain advanced scenarios. Most Web Socket servers 
> > will know nothing about HTTP.
> 
> delivering the web application, and I think the more usual scenario is 
> that web server also implements the WebSocket server.  Why would someone 
> prefer to deploy two servers rather than one, except in the case where 
> their web server doesn't yet support WebSocket?  If this protocol is 
> successful, over time that will drop to 0.

I see no advantage in the common case to using the same software for both. 
It's far easier to just host them separately.

Why don't people use the same software for HTTP and DNS? Or IMAP and SMTP?  
Or IRC and FTP? Why would they act differently for HTTP and WebSocket?

> > Reusing connections is a level of complexity that is completely 
> > unwarranted and that would only be useful in the rarest of cases. It's 
> > a proposal that lies on completely the wrong side of the 80/20 line 
> > and would introduce _massive_ complexity for authors, who would have 
> > no idea why their WebSocket servers were suddenly receiving random 
> > HTTP requests and vice versa.
> 
> I'm not sold on connection reuse, but I am not sure where these random 
> HTTP requests would be coming from.  If a connection was to 
> ws://foo.org/socket, the connection was closed, and then another 
> connection was needed for http://foo.org/image.gif, presumably the 
> server at foo.org:80 is capable of answering either request since it 
> would have had to handle either request on a new connection.

In this scenario, we are assuming that the server _can't_ answer the Web 
Socket request (otherwise the connection wouldn't be reused). So we are 
talking about cases where people are attempting to connect to servers that 
don't exist. If we're talking about that, then I don't see why it's any 
more of a stretch to imagine trying to connect to a Web Socket server, 
having it succeed from the server's point of view but fail from the 
client's point of view, and then having the client reuse the connection 
for some bogus HTTP request.

In any case, reusing connections when the server fails to return a valid 
Web Socket response but does return a valid HTTP response is an 
optimisation that will help in only the rarest of cases, all of which are 
indicating failurel and thus likely to be cases where the user doesn't 
really care about the milliseconds saved.

On Thu, 22 Jul 2010, Greg Wilkins wrote:
> 
> Currently the WS handshake can only be rejected by closing the 
> connection and discarding any potential HTTP response.  Thus a webapp 
> that wishes to fall back to a non-ws transport will have to establish a 
> new connection, maybe negotiate TLS, then handshake the new transport.  
> Thus there will be an extra 2 or 3 round trips to establish the 
> fall-back transport.

The only time this would be useful is when the script doesn't know ahead 
of time which host it will be connecting to, and doesn't know ahead of 
time what protocols that host will support, but where it does know that it 
will support either a Web Socket server or an HTTP-based mechanism. This 
will only occur during the transition period where some sites provide an 
HTTP-based protocol but not a Web Socket version, but where other sites 
provide Web Socket equivalents.

This is such an edge case that optimising for it should only be done if it 
can be essentially done for free. This is not the case here. Debugging 
connection reuse will be a huge pain. It's not worth it.

If you really truly want to handle this case, just invoke the 
XMLHttpRequest constructor at the same time as the WebSocket constructor, 
and then drop whichever one fails.

On Thu, 22 Jul 2010, Jamie Lokier wrote:
> slower than comet-style HTTP, both slower in sending the first messages, 
> and slower in receiving the first responses.
> 
> It means latency-optimised apps may open *two* connections in parallel: 
> One comet-style HTTP, and one WebSocket.  They will communicate initial 
> messages over the HTTP connection, and switch to the WebSocket 
> connection when that is ready.  That's not kind on low bandwidth links, 
> nor easy to program, so it's an ugly compromise.

Could you give an example of an app where the speed in which the Web 
Socket connection is established matters? I can't think of any case where 
the client needs to send information that quickly -- after all, the user 
won't have started doing anything within one RTT of the page loading. (The 
server can easily include any data it wants in the original HTTP request, 
so this is presumably not to _get_ information.)

On Wed, 21 Jul 2010, Roberto Peon wrote:
> >
> > I could see trying multiple WebSocket protocols over one connection, 
> > but trying to try both HTTP or WebSocket connections, not to mention 
> > any other protocols the servers might provide, seems like massive 
> > complexity for negligible gain overall.
>
> I fully expect that we'll end up with multiple websocket "sockets" per 
> tab

Presumably to different hosts.

> and we typically end up with many tabs.

Tabs can share a single WebSocket to a single host using shared workers.

> [...] As for complexity! At worst, you have flow control and 
> multiplexing. Multiplexing involves a unique ID per channel. Flow 
> control involves sending periodic updates telling the other side how 
> much it can send safely. Of course you also need to have a table in 
> which you do a lookup to see that there is already a connection for that 
> domain, including a reference to that connection. None of this is 
> difficult, even in concert.

Over the past couple of months, we've had several Web developers come into 
the #whatwg channel and ask for help implementing the current Web Socket 
draft. We've seen all kinds of difficulties implementing just the current 
spec! People using regular expressions over the buffer to parse the 
handshake [1], people not considering that the handshake might be split 
into two packets, people writing code that reads straight off the end of 
their buffer if the data sent to their server isn't wellformed per the 
handshake... none of what's in the current draft is "difficult", but it's 
still difficult enough, as far as I can tell.

[1] (Which I incidentally expected; that's why there are two keys, so you 
can't trick such naive implementations by smuggling a key in the resource 
name. I didn't expect to see code saved by this so soon.)

> > HTTP-aware rules on the routers.]

What Willy wrote was not a description of transparent proxies but of 
man-in-the-middle proxies. Transparent proxies are a different beast 
altogether. Please see the HTTP spec for details. Man-in-the-middle 
proxies are not legitimate per the HTTP spec as far as I can tell, and are 
the cause of many problems on the Web (such as the lack of our ability to 
deploy pipelining).

On Thu, 22 Jul 2010, Willy Tarreau wrote:
> 
> There are not that many ISPs in each country, I mean there are far less 
> ISPs than there are web sites or potential WebSocket implementers. 
> There's a high pressure on them to work as expected by customers.

Not high enough, clearly, or we'd be able to deploy pipelining.

On Thu, 22 Jul 2010, Willy Tarreau wrote:
> as seen from the client, yes. As seen from the proxy or the server or 
> any intermediate between them, no :-)

I mean as seen from the point of view of conformance to the specification.

---

From: John Tamplin <[email-masked]>
Date: Thu, 22 Jul 2010 02:50:34 -0400

> Or IRC and FTP? Why would they act differently for HTTP and WebSocket?

Few people serve their web apps from a DNS server.  Initially, virtually all
WebSocket clients are going to be JS applications downloaded via HTTP.  If I
am writing a JS game to be run in the browser, why would I want to maintain
two servers instead of one?  Using Jetty (and I would expect most other
servers to add support once the protocol is standardized), I can just add
another method on my servlet and presto, I have WebSocket support.  This is
especially important if the fallback is going to be hanging gets or polling
via HTTP -- I can have common code for either solution, rather than
duplicating code that runs in two separate servers, and it gets me the
ability to more easily share state between HTTP requests and WebSocket
messages, such as authentication credentials.

> provide Web Socket equivalents.

Or if it doesn't know that it can actually speak WebSocket all the way to
the server because of potentially interfering intermediaries.

---

From: Julian Reschke <[email-masked]>
Date: Thu, 22 Jul 2010 08:53:31 +0200

On 22.07.2010 08:32, Ian Hickson wrote:
> ...
> ...

Because the Websocket connection is usually launched from a browser, 
thus bootstrapped from an HTML/Web application, and very likely wants to 
share data with that web app?

Best regards, Julian

---

From: Greg Wilkins <[email-masked]>
Date: Thu, 22 Jul 2010 16:58:03 +1000

> It's far easier to just host them separately.

The evidence in this WG is that many server side developers see great
benefit in using a single server for both HTTP and Websocket.

The reason is that a websocket based application is a WEB application that
will be combination of HTTP served resources (markup, images, css,
javascript) interacting with websocket received/served resources
(messages).  Many of these applications will have fallback transports that
will use HTTP when websocket is not available.

It is highly desirable to avoid multiple instances of business logic for a
single client, thus it is highly desirable to have a single application
context handle both HTTP and websocket transactions for the same client.
Having multiple servers is just a recipe for complex applications suffering
from race conditions or needing the extra expense of putting more operations
through a transactional mechanism (DB, JMX etc.).

> Or IRC and FTP? Why would they act differently for HTTP and WebSocket?

Applications that combine mail and web applications often do run protocols
like SMTP in the same process as the web server.   Ditto for IRC, XMPP etc.

cheers

---

From: Willy Tarreau <[email-masked]>
Date: Thu, 22 Jul 2010 08:58:52 +0200

> Or IRC and FTP? Why would they act differently for HTTP and WebSocket?

Ian, you forget one thing : "applications".
HTTP + WebSocket will be combined in the same use to for applications,
with WebSocket being the interactive part, and HTTP carrying all the
transactional parts. For this reason, they will be intimately bound,
there will be a need for shared context, for persistence between the
two protocols from the same user on the same server, for passing
credentials, etc... None of the other examples you've proposed above
need that. And in fact there's one case where IMAP+SMTP are used
together, it's when you require a user to first log into the POP or
IMAP server so that he's allowed to relay through the SMTP server.
And in this case, both are bound ;-)

(...)
> proxies are not legitimate per the HTTP spec as far as I can tell,
> and are the cause of many problems on the Web (such as the lack of
> our ability to deploy pipelining).

Sorry ? what you call man-in-the-middle is what HTTP calls "gateways"
or what are commonly called "reverse-proxies". Not only they don't
cause lots of imaginary problems, they're deployed everywhere and you
don't ever notice them, reason why you believe they don't work. Try
to spot one large site which does not make use of an HTTP gateway in
front of servers. Hint: they're at least in every layer 7 load
balancers. So please stop thinking about your perl-written server
running on your laptop for your own tests and think about the real
world.

> Not high enough, clearly, or we'd be able to deploy pipelining.

We'd be able to *enable* pipelining, not deploy it for the other reason
I explained before (high cost and risks on intermediates for little added
value). However, if there are some remaining places where it still does
not work, well it may very well be because it's disabled by default in
browsers so that nobody has to complain.

> I mean as seen from the point of view of conformance to the specification.

Then it's a gateway, not a server.

Willy

---

From: Willy Tarreau <[email-masked]>
Date: Thu, 22 Jul 2010 09:01:46 +0200

> messages, such as authentication credentials.

In fact, it seems clear that everyone understands how WS is going to be
used, except one person. Unfortunately, that person is the editor :-(

Willy

---

From: Roberto Peon <[email-masked]>
Date: Thu, 22 Jul 2010 01:09:02 -0700

> It's far easier to just host them separately.

It is advisable to believe that you/we/anybody don't have all the answers
and build a protocol that allows people to adjust to the realities of their
time instead of rigidly adhering to something that covers only today's
use-cases.

> Or IRC and FTP? Why would they act differently for HTTP and WebSocket?

Is this a rhetorical question? I suppose I'll assume not.

Well, lets see. HTTP and DNS don't share transport protocols in the common
case.
IMAP and SMTP sometimes are collocated on the same server.
IRC and FTP serve completely different feature sets.
Many of these were not developed by the same parties, nor at the same time.
That is often a very good reason that they don't reside in the same
binary/server.

HTTP and WebSocket share the same transport protocol, and are used by the
same clients and servers to do the same tasks, and it is extremely likely
that they'll be written/maintained by the same people at the same time.
There is a strong desire to put this into the same binary/server.

> really care about the milliseconds saved.

Failure to upgrade to websocket doesn't imply a cessation of utility.
Idle connections have had their CWND expanded. This is a big latency win for
further uses of the channel.
This assumes that we're willing to take idle connections from the pool of
HTTP connections and upgrade to WS. This seems very reasonable to me.
We may find that it isn't-- there may be more demand for HTTP connections
than WS connections, in which case leaving WS to open its own connection may
result in a net latency win.

> provide Web Socket equivalents.

How are clients to know, a priori to contact, that the server speaks HTTP or
WS or some future protocol?
Keep in mind that the fact that the server speaks WS doesn't imply that the
channel between the client and server allows it to happen, and that neither
the client nor server may control any of this.

> connection reuse will be a huge pain. It's not worth it.

I'm hearing:
I don't think that saving the billions of users in the world any of their
time is worth any of mine.
If you can prove that reuse cannot happen, or that it offers no latency
benefit, then I'd agree. You've not proven that, you're just stating an
opinion that doesn't seem to have basis in experience.

> and then drop whichever one fails.

That seems likely to cause problems for clients on slow links, is much more
likely to cause congestion, is much more likely to needlessly waste server
resources, and needlessly increases complexity for the client in the form of
wonderful races.

> so this is presumably not to _get_ information.)

Chat. Games. Web browsing. Protocol discussions. Just about anything,
actually.
"The user" here is a user-agent. It is fully capable of taking action on
time horizons that the user cannot perceive directly.
RTTs can be fairly large, especially for devices using wireless links.
Starting off with an assumption that latency doesn't matter in the beginning
is just... amazingly, surprisingly silly.

> Presumably to different hosts.

Why would you presume that?

> Tabs can share a single WebSocket to a single host using shared workers.

Or they can just open a websocket and have it multiplex to the server
without any additional complexity at all for application writers while
maintaining no degradation at all in security model, and requiring no trust
of anything on any other tab.

> still difficult enough, as far as I can tell.

... so?
People using regular expressions over a buffer to parse a handshake, not
understanding the basics of TCP, or unable to handle other bits of IO
shouldn't be our target audience.
The target audience should be the consumers of the effects of the protocol--
the billions of people using web browsers, etc.

People making these kinds of mistakes are very unlikely to be writing the
next successful and widely used server (at least, not until they learn to do
these things properly, which some certainly may).
There is nothing wrong with tinkering on the network. I'm sure a lot of
people on this list did that in the past, and I'm certain that the lessons
learned have made those who did so much more effective. If we want a
protocol for learning, we should build one for that. That is not my intended
audience. I have my eye on the audience of billions.

This is the current list rathole, though. Targeting "amateur programmers"
shouldn't be a requirement.
-=R

> the cause of many problems on the Web (such as the lack of our ability to
Legitimate or not, they did exist, do exist, and likely will continue to
exist.