- From: Randell Jesup <randell-ietf@jesup.org>
- Date: Mon, 23 Apr 2012 12:01:05 -0400
- To: "public-webrtc@w3.org" <public-webrtc@w3.org>
- CC: Michael Tuexen <tuexen@fh-muenster.de>, Randall Stewart <rrs@lakerest.net>, Salvatore Loreto <salvatore.loreto@ericsson.com>
In going over the details for the DataChannel minor protocol and how it works over SCTP, we realized we'll need a 3-way handshake instead of a 2-way. The reason is that an OPEN_RESPONSE sent ordered followed by a data message sent unordered would allow the data message to come in at the other end before the open response, and since we don't know the input-stream -> output-stream mapping until we get the OPEN_RESPONSE, we might not know what to do with it. So we plan to add an ACK message to the protocol to provide the 3-way handshake. We now have to decide what to do about the JS-level API; which to recap currently requires waiting for onopen on the opener's side, and allows the answerer to send() immediately on getting ondatachannel. We've figured out that we can allow send() before onopen (in either direction) by forcing data to be in-order until the 3-way handshake is complete. Obviously, if you're using in-order (reliable or unreliable) this doesn't matter. It does cause and data sent to be buffered in the stack(s) until it can be delivered, which typically would be no real problem unless the OPEN (or OPEN_RESPONSE) was lost and had to be re-transmitted. There are two really "simple and clean" solutions: 1) both sides wait for onopen() 2) neither side waits for onopen() Note that in #2 we'd still have onopen() for ease of porting WebSockets code to it DataChannels. We could also keep the current API (onopen at the opener, immediate on the receiver). #1 requires the application maintain state in a number of cases where it would not otherwise need to, or buffer within the app. I.e. an application that wants to send data on a channel not yet open must open it and somehow defer the sending until it's open. This can be encapsulated in JS functions: temp = peer.createDataChannel(..) temp.data_to_send = "I want to send just this"; temp.onopen = function() { temp.send(temp.data_to_send); temp.close(); // don't wait for GC to close/reclaim stream! temp = null; // available for GC }; Of course, not as straightforward as: temp = peer.createDataChannel(..) temp.send("I want to send just this"); temp.close(); temp = null; but not a lot worse. It's more complex if you might want to send more data to the channel and need to buffer all of it in the app (think a log channel) while waiting for it to open. Commonly the answerer will wait for incoming data before sending anything, but not in all cases. It seems to me that forcing in-order delivery until the handshake is complete is simpler for the user, and only rarely has any impact on the application. The exception might be if you wanted to dump a bunch of sends that were reliable and out-of-order immediately on creation of the channel - and I don't see it being a major issue there - and you can still wait on onopen if you want. Recap: #2 is slightly closer to how WebSockets works (though anything coded for WebSockets' onopen behavior would still work in #1), and #2 avoids potential additional buffering in the stack if the OPEN/OPEN_RESPONSE is lost. (If it's not lost, there's really no extra buffering occurring, except maybe in the rare case where we need to increase the maximum number of simultaneous streams.) Opinions? -- Randell Jesup randell-ietf@jesup.org
Received on Monday, 23 April 2012 16:02:20 UTC