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