<br><br><div class="gmail_quote">On Tue, Jul 28, 2009 at 4:40 PM, Ian Hickson <span dir="ltr"><<a href="mailto:ian@hixie.ch">ian@hixie.ch</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div class="im">On Tue, 14 Jul 2009, Jeremy Orlow wrote:<br>
> > ><br>
> > > I think 'readyState' should just go away since an application will<br>
> > > have to keep track of state updates through the fired events and use<br>
> > > try/catch blocks around all API calls anyway.<br>
> ><br>
> > The attribute is mostly present for debugging purposes. I wouldn't<br>
> > expect anyone to actually use it for production work.<br>
><br>
</div><div class="im">> Is there precedent for other portions of the API that are mostly for<br>
> debugging purposes?  (I can't think of anything off the top of my head.)<br>
<br>
</div>readyState on Document and <video> aren't realy useful for anything but<br>
debugging either, as far as I can tell.<br>
<div class="im"><br>
<br>
> Also, maybe it should be noted as such in the spec?<br>
<br>
</div>I don't really see much benefit to including such a statement; if someone<br>
wants to use it for a non-debugging reason, why not do so?<br>
<div class="im"><br>
<br>
> If it's only for debugging purposes, maybe a cleaner way to define it is<br>
</div>> to simply be the last event fired on a given WebSocket?<br>
<br>
I don't really understand what problem we would be trying to solve by<br>
changing that.<br>
<div class="im"><br>
<br>
> One other random question:  in the IDL for WebSockets, the three<br>
> constants for ready state are all defined as shorts but the value of<br>
> ready state is a long.  Is this an oversight?<br>
<br>
</div>Fixed.<br>
<div class="im"><br>
<br>
On Mon, 27 Jul 2009, Alexey Proskuryakov wrote:<br>
><br>
> I agree with Michael that send() should not silently drop data that<br>
> could not be sent. It is very easy to fill send buffers, and if bytes<br>
> get silently dropped, implementing app-level acks becomes quite<br>
> difficult.<br>
<br>
</div>I've made it clear that if bytes can't be sent, the connection must be<br>
closed.<br>
<div class="im"><br>
<br>
> However, I do not think that raising an exception is an appropriate<br>
> answer. Often, the TCP implementation takes a part of data given to it,<br>
> and asks to resubmit the rest later. So, just returning an integer<br>
> result from send() would be best in my opinion.<br>
<br>
</div>I think we are best off abstracting away this level of complexity from<br>
authors, especially since we'd need to make sure that data was not sent<br>
half-way through a UTF-8 sequence, and since the framing is under the<br>
control of the UA, not the application. There's no way to retry a<br>
partially-successful send() from the API here.<br>
<div class="im"><br>
<br>
> 1) Web Sockets is specified to send whatever authentication credentials<br>
> the client has for the resource. However, there is no challenge-response<br>
> sequence specified, which seems to prevent using common auth schemes.<br>
> HTTP Basic needs to know an authentication realm for the credentials,<br>
> and other schemes need a cryptographic challenge (e.g. nonce for Digest<br>
> auth).<br>
<br>
</div>I expect to address this in more detail in a future version. For now, use<br>
in-band authentication in the WebSocket once you are connected. We may<br>
find that that is actually enough.<br>
<div class="im"><br>
<br>
> 2) It is not specified what the server does when credentials are<br>
> incorrect, so I assume that the intended behavior is to close the<br>
> connection. Unlike HTTP 401 response, this doesn't give the client a<br>
> chance to ask the user again. Also, if the server is on a different<br>
> host, especially one that's not shared with an HTTP server, there isn't<br>
> a way to obtain credentials, in the first place.<br>
<br>
</div>How we address this will likely depend on how we address the earlier<br>
point.<br>
<div class="im"><br>
<br>
> 3) A Web Sockets server cannot respond with a redirect to another URL.<br>
> I'm not sure if the intention is to leave this to implementations, or to<br>
> add in Web Sockets v2, but it definitely looks like an important feature<br>
> to me, maybe something that needs to be in v1.<br>
<br>
</div>What's the use case? Why does this need to be at the connection layer<br>
rather than the application layer? (Why would we need this, when TCP<br>
doesn't have it? Would you also need "redirect"-like functonality in IRC,<br>
IMAP, SSH, and other such protocols?)<br>
<div class="im"><br>
<br>
> 4) "If the user agent already has a Web Socket connection to the remote<br>
> host identified by /host/ (even if known by another name), wait until<br>
> that connection has been established or for that connection to have<br>
> failed."<br>
><br>
> It doesn't look like "host identified by /host/" is defined anywhere.<br>
> Does this requirement say that IP addresses should be compared, instead<br>
> of host names?<br>
<br>
</div>Right. I've tried to clarify this.<br>
<div class="im"><br>
<br>
> I'm not sure if this is significant for preventing DoS attacks, and<br>
> anyway, the IP address may not be known before a request is sent. This<br>
> puts an unusual burden on the implementation.<br>
<br>
</div>Without this requirement, you can just have a DNS server return the victim<br>
IP for a wildcard DNS entry, and then just have attackers open connections<br>
to thousands of "hosts".<br>
<div class="im"><br>
<br>
> 5) We probably need to specify a keep-alive feature to avoid proxy<br>
> connection timeout. I do not have factual data on whether common proxies<br>
> implement connection timeout, but I'd expect them to often do.<br>
<br>
</div>This seems like something that would be easy to deal with at the<br>
application layer, if desired.<br>
<div class="im"><br>
<br>
> 6) The spec should probably explicitly permit blocking some ports from<br>
> use with Web Sockets at UA's discretion. In practice, the list would<br>
> likely be the same as for HTTP, see e.g.<br>
> <<a href="http://www.mozilla.org/projects/netlib/PortBanning.html" target="_blank">http://www.mozilla.org/projects/netlib/PortBanning.html</a>>.<br>
<br>
</div>Done.<br>
<div class="im"><br>
<br>
> 7) "use a SOCKS proxy for WebSocket connections, if available, or failing<br>
> that, to prefer an HTTPS proxy over an HTTP proxy"<br>
><br>
> It is not clear what definition of proxy types is used here. To me, an HTTPS<br>
> proxy is one that supports CONNECT to port 443, and an HTTP proxy (if we're<br>
> making a distinction from HTTPS) is one that intercepts and forwards GET<br>
> requests. However, this understanding contradicts an example in paragraph<br>
> 3.1.3, and also, it's not clear how a GET proxy could be used for Web Sockets.<br>
<br>
</div>Clarified, I hope.<br>
<div class="im"><br>
<br>
> 8) Many HTTPS proxies only allow connecting to port 443. Do you have the<br>
> data on whether relying on existing proxies to establish connections to<br>
> arbitrary ports is practical?<br>
<br>
</div>I do not. I expect most people to use direct connections over port 81 or<br>
TLS over port 443, as discussed in the introduction.<br>
<div class="im"><br>
<br>
> 9) "There is no limit to the number of established Web Socket<br>
> connections a user agent can have with a single remote host".<br>
><br>
> Does this mean that Web Socket connections are exempt from the normal<br>
> 4-connection (or so) limit? Why is it OK?<br>
<br>
</div>That limit is an HTTP limit. WebSocket is not an HTTP protocol, so the<br>
limit has no bearing on WebSocket.<br>
<br>
As I understand it, the limit in HTTP is intended to deal with the problem<br>
of multiple short-lived connections being needed to render a page, e.g.<br>
going to a Web page with thousands of <img>s. There would be no way for<br>
the author to ensure the page didn't DOS the server in such a case. This<br>
is not a concern with WebSocket, where the author controls when the<br>
connections are made.<br>
<div class="im"><br>
<br>
> 10) Web Socket handshake uses CRLF line endings strictly. Does this add<br>
> much to security? It prevents using telnet/netcat for debugging, which<br>
> is something I personally use often when working on networking issues.<br>
><br>
> If there is no practical reason for this, I'd suggest relaxing this<br>
> aspect of parsing.<br>
<br>
</div>Do you mean client->server or server->client?<br>
<div class="im"><br>
<br>
> 11) There is no way for the client to know that the connection has been<br>
> closed. For example:<br>
> - socket.close() is called from JavaScript;<br>
> - onclose handler is invoked;<br>
> - more data arrives from the server, and onmessage is dispatched (which I<br>
> think is correct, and it matches what TCP does);<br>
> - finally, a TCP FIN arrives, indicating that there will be no more data from<br>
> the server (the underlying TCP connection is in TIME_WAIT state after that);<br>
> - the client never learns that the server is done sending data.<br>
<br>
</div>The onclose only fires once the connection has closed, which is after the<br>
TCP FIN, so it happens after the last 'message' event.<br>
<div class="im"><br>
<br>
> As Web Sockets are basically at the same level as TCP, and TCP provides<br>
> complete info about socket state, I don't think that delegating<br>
> connection closing to app-level protocols would be appropriate.<br>
<br>
</div>I'm not sure what you mean.<br>
<div class="im"><br>
<br>
On Mon, 27 Jul 2009, Maciej Stachowiak wrote:<br>
><br>
> With WebSocket, another possibility is for the implementation to buffer<br>
> pending data that could not yet be sent to the TCP layer, so that the<br>
> client of WebSocket doesn't have to be exposed to system limitations. At<br>
> that point, an exception is only needed if the implementation runs out<br>
> of memory for buffering. With a system TCP implementation, the buffering<br>
> would be in kernel space, which is a scarce resource, but user space<br>
> memory inside the implementation is no more scarce than user space<br>
> memory held by the Web application waiting to send to the WebSocket.<br>
<br>
</div>Indeed.<br>
<div class="im"><br>
<br>
On Mon, 27 Jul 2009, Alexey Proskuryakov wrote:<br>
><br>
> I agree that this will help if the application sends data in burst mode,<br>
> but what if it just constantly sends more than the network can transmit?<br>
> It will never learn that it's misbehaving, and will just take more and<br>
> more memory.<br>
<br>
</div>I've added an attribute that says how much data has been buffered, so an<br>
application can tell if this number is rising unexpectedly.<br>
<div class="im"><br>
<br>
> An example where adapting to network bandwidth is needed is of course<br>
> file uploading, but even if we dismiss it as a special case that can be<br>
> served with custom code, there's also e.g. captured video or audio that<br>
> can be downgraded in quality for slow connections.<br>
<br>
</div>We may have to do more complex things when we introduce files and streams,<br>
but in practice I expect those to be a non-issue since the UA would take<br>
care of them completely with just one send() call.<br>
<br>
   function upload(file) {<br>
     websocket.send(file);<br>
   }<br>
<br>
   websocket.startSendingStream(camera.stream);<br>
   ...<br>
   websocket.stopSendingStream(camera.stream);<br>
<br>
...or something. Those are in fact far easier to deal with than just<br>
continuous updates of the user's progress in a game or some such.<br>
<div class="im"><br>
<br>
On Mon, 27 Jul 2009, Jeremy Orlow wrote:<br>
><br>
> Maybe the right behavior is to buffer in user-space (like Maciej<br>
> explained) up until a limit (left up to the UA) and then anything beyond<br>
> that results in an exception.  This seems like it'd handle bursty<br>
> communication and would keep the failure model simple.<br>
<br>
</div>Running out of space is hitting a hardware limitation, at which point you<br>
can do whatever you like (the spec doesn't require any particular<br>
behaviour in such scenarios, since what is possible depends on the UA).<br>
<br>
I have, however, made the spec clear that if the send() fails somehow, the<br>
connection must be closed.<br>
<div class="im"><br>
<br>
On Mon, 27 Jul 2009, Alexey Proskuryakov wrote:<br>
><br>
> Having a send() that doesn't return anything and doesn't raise<br>
> exceptions would be a clear signal that send() just blocks until it's<br>
> possible to send data to me, and I'm sure to many others, as well. There<br>
> is no reason to silently drop data sent over a TCP connection - after<br>
> all, we could as well base the protocol on UDP if we did, and lose<br>
> nothing.<br>
<br>
</div>I think returning a boolean is more or less the same as "silently<br>
dropping" in practice.<br>
<div class="im"><br>
<br>
On Mon, 27 Jul 2009, Drew Wilson wrote:<br>
><br>
> There's another option besides blocking, raising an exception, and<br>
> dropping data: unlimited buffering in user space. So I'm saying we<br>
> should not put any limits on the amount of user-space buffering we're<br>
> willing to do, any more than we put any limits on the amount of other<br>
> types of user-space memory allocation a page can perform.<br>
<br>
</div>Agreed.<br>
<div class="im"><br>
<br>
On Mon, 27 Jul 2009, Jeremy Orlow wrote:<br>
><br>
> I agree with Alexey that applications need feedback when they're<br>
> consistentiently exceeding what your net connection can handle.  I think<br>
> an application getting an exception rather than filling up its buffer<br>
> until it OOMs is a much better experience for the user and the web<br>
> developer.<br>
<br>
</div>True. the .bufferedAmount attribute will now allow this.<br>
<div class="im"><br>
<br>
> If you have application level ACKs (which you probably<br>
> should--especially in high-throughput uses), you really shouldn't even<br>
> hit the buffer limits that a UA might have in place.  I don't really<br>
> think that having a limit on the buffer size is a problem and that, if<br>
> anything, it'll promote better application level flow control.<br>
<br>
</div>Probably true also.<br>
<div class="im"><br>
<br>
On Mon, 27 Jul 2009, Drew Wilson wrote:<br>
><br>
> I'm assuming that no actual limits would be specified in the<br>
> specification, so it would be entirely up to a given UserAgent to decide<br>
> how much buffering it is willing to provide. Doesn't that imply that a<br>
> well-behaved web application would be forced to check for exceptions<br>
> from all send() invocations, since there's no way to know a priori<br>
> whether limits imposed by an application via its app-level protocol<br>
> would be sufficient to stay under a given user-agent's internal limits?<br>
<br>
</div>Without the recent changes, yes.<br>
<div class="im"><br>
<br>
> Even worse, to be broadly deployable the app-level protocol would have<br>
> to enforce the lowest-common-denominator buffering limit, which would<br>
> inhibit throughput on platforms that support higher buffers. In<br>
> practice, I suspect most implementations would adopt a "just blast out<br>
> as much data as possible until the system throws an exception, then set<br>
> a timer to retry the send in 100ms" approach. But perhaps that's your<br>
> intention? If so, then I'd suggest changing the API to just have a<br>
> "canWrite" notification like other async socket APIs provide (or<br>
> something similar) to avoid the clunky catch-and-retry idiom.<br>
<br>
</div>The attribute now lets you just wait until the buffer is empty, which is<br>
more or less equivalent, I think.<br>
<div class="im"><br>
<br>
On Mon, 27 Jul 2009, Maciej Stachowiak wrote:<br>
><br>
> I think even unlimited buffering needs to be combined with at least a<br>
> hint to the WebSocket client to back off the send rate, because it's<br>
> possible to send so much data that it exceeds the available address<br>
> space, for example when uploading a very large file piece by piece, or<br>
> when sending a live media stream that requires more bandwidth than the<br>
> connection can deliver. In the first case, it is possible, though highly<br>
> undesirable, to spool the data to be sent to disk; in the latter case,<br>
> doing that would just inevitably fill the disk. Obviously we need more<br>
> web platform capabilities to make such use cases a reality, but they are<br>
> foreseeable and we should deal with them in some reasonable way.<br>
<br>
</div>Both the lice stream and the file case are actually far easier for us to<br>
deal with, as noted above, than just lots of generated text data.<br>
<div class="im"><br>
<br>
On Tue, 28 Jul 2009, Robert O'Callahan wrote:<br>
><br>
> Why not just allow unlimited buffering, but also provide an API to query<br>
> how much data is currently buffered (approximate only, so it would be OK<br>
> to just return the size of data buffered in user space)?<br>
><br>
> Then applications that care and can adapt can do so. But most<br>
> applications will not need to. The problem of partial writes being<br>
> incorrectly handled is pernicious and I definitely think partial writes<br>
> should not be exposed to applications.<br>
<br>
</div>That's what I've done.<br>
<div class="im"><br>
<br>
On Mon, 27 Jul 2009, Michael Nordman wrote:<br>
><br>
> The proposed websocket interface is too dumbed down. The caller doesn't<br>
> know what the impl is doing, and the impl doesn't know what the caller<br>
> is trying to do. As a consequence, there is no "reasonable" action that<br>
> either can take when buffers start overflowing. Typically, the network<br>
> layer provides sufficient status info to its caller that, allowing the<br>
> higher level code to do something reasonable in light of how the network<br>
> layer is performing. That kind of status info is simply missing from the<br>
> websocket interface. I think its possible to add to the interface<br>
> features that would facilitate more demanding uses cases without<br>
> complicating the simple use cases. I think that would be an excellent<br>
> goal for this API.<br>
<br>
</div>Do the minimal new additions address this to your satisfaction?</blockquote><div><br></div><div>The hints about future additions have, in particular support for 'streams'.</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
<div class="im"><br>
<br>
On Mon, 27 Jul 2009, Drew Wilson wrote:<br>
><br>
> I would suggest that the solution to this situation is an appropriate<br>
> application-level protocol (i.e. acks) to allow the application to have<br>
> no more than (say) 1MB of data outstanding.<br>
><br>
> I'm just afraid that we're burdening the API to handle degenerative<br>
> cases that the vast majority of users won't encounter. Specifying in the<br>
> API that any arbitrary send() invocation could throw some kind of "retry<br>
> exception" or return some kind of error code is really really<br>
> cumbersome.<br>
<br>
</div>I agree that we aren't talking about a particularly common case.<br>
<div><div></div><div class="h5"><br>
--<br>
Ian Hickson               U+1047E                )\._.,--....,'``.    fL<br>
<a href="http://ln.hixie.ch/" target="_blank">http://ln.hixie.ch/</a>       U+263A                /,   _.. \   _\  ;`._ ,.<br>
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'<br>
</div></div></blockquote></div><br>