SCTP mapping to data channels

On 2/3/2012 12:49 PM, Stefan Hakansson LK wrote:
> On 02/03/2012 06:41 PM, Harald Alvestrand wrote:

>> An advantage of bidirectional streams is that it doesn't matter which
>> end creates the data stream; with unidirectional, there either has to be
>> a flag stating the direction or a convention that the data sender (or
>> receiver) always creates them.
>
> Or different objects; the one creating the dataStream has a "sink" and
> the the receiver a "source". But I think it is simpler if they are
> bi-directional.

I believe I agree - it's simpler for the application developer; I see no 
real advantage to their being unidirectional.  (RTP is (normally - 
symmetric RTP) bidirectional as well).


I should note that SCTP per-se considers streams unidirectional, but 
typically applications tie a pair of streams together, one in each 
direction.

Internally we could handle this by creating the reverse channel 
automatically when we hear the forward channel is "created".  Which 
brings the next big thing that people may not be realizing:

*** SCTP streams (within an association) have no "open" or "close" ***

The number of streams in each direction is negotiated at association 
creation; and they're all available from that point (and the number 
cannot be changed during the association).  The application decides what 
to do with data arriving on a stream.

In terms of number of data channels, that could be specified in the peer 
connection before it's connected to the far end.  (An application should 
be able to do this, since all the data on those channels is specific to 
the application.)  If the application will use a dynamic number, it 
should specify the max in use at one time.  [OPEN ISSUE: what's the 
overhead for specifying extra channels you don't really need?]

In our case, the WebRTC implementation will be sctp_recvmsg()ing the 
data, which will come with a stream value for each chunk.  We'll use 
that to de-multiplex the data to the correct JS data channel.

Just as an FYI, the linux SCTP api:
int sctp_sendmsg(int sd,
                  const void * msg,
                  size_t len,
                  struct sockaddr *to,
                  socklen_t tolen,
                  uint32_t ppid,
                  uint32_t flags, // UNORDERED, etc
                  uint16_t stream_no,
                  uint32_t timetolive,
                  uint32_t context);

We have some options:

1) use an API that preserves that behavior up to the JS app.  This is a 
lower-level, handle-all-the-options-yourself interface between SCTP and 
the JS app.  Powerful but ugly and prone to misuse; requires more app code.

2) use an API that's closer to the current "define a channel and use it" 
behavior.  This is closer to typical JS idioms, using a hints object to 
set the default behavior of each channel.  These channels could be made 
to be bidirectional within our layering.  Internally, each would map to 
a stream in each direction.

Note that we need to be careful about this - if we just blindly use an 
"unused" stream and we expect bidirectionality, it may race (glare) with 
an attempt to do the same from the other end.  So, it may be better to 
signal that usage over some sort of control channel or via some type of 
signaling.

Typically, protocols using SCTP use stream 0 as a "control" stream, much 
as I'd laid out in my "FTP-like" example a while ago.  ("I'm sending 
file X on stream Y now", etc).  This is not required and is totally up 
to the application.

We *could* define that stream 0 is our control channel for handling the 
mapping of pc.createDataChannel() calls; used to inform the other end 
about them and any meta-data like labels (though I don't think in this 
usage they're needed) and type of stream (though SCTP itself doesn't 
require streams in opposite directions be correlated).  We also could 
use the PPID field for control info (see below).  In either case, we 
don't need to signal dataChannel creation/removal through the server 
(and SDP and JSEP), and I'd strongly recommend avoiding SDP/JSEP here.


We can either (again) expose the details to the JS app, or we can hide 
them behind dataChannel abstractions.

I propose we retain most of the current proposed JS API, which is a 
dataChannel abstraction layered on top of the SCTP channels.  Unlike raw 
SCTP, the application would specify the mode of transport for the 
dataChannel (raw SCTP allows you to set the reliable, unreliable, etc 
bits on each individual datagram at sctp_sendmsg() time, so a stream can 
be a mix of reliable and unreliable datagrams - powerful, but not used 
often and confusing).

At createDataChannel() (or what-have-you) time, we would (via hints) 
specify the type of data channel (reliable, unreliable, etc).  We would 
use that to notify the other side of the creation (over SCTP stream 0), 
and (if we choose bidirectional) the other side would set up the reverse 
stream.  The stream used for the dataChannel would be picked by the two 
ends via some mechanism.

Note that if we only support unidirectional channels, this is simplified 
- it's just a notification.  Unidirectional would imply we have 
dataChannelOutgoing objects and dataChannelIncoming objects (both can 
inherit if we want from dataChannel).

Removing a data channel would throw the stream "back into the pool" to 
use for createDataChannel/etc.

We also have the PPID field we can use (Payload Protocol Identifier); 
it's an opaque value (to SCTP) that can be attached to each DATA chunk. 
  That presents on option to use that to put the "signaling" data for 
each stream in the stream itself (for unidirectional streams at least), 
by using a specific PPID value saying basically "this is metadata about 
the stream".  These metadata messages would also specify reliable 
in-order delivery.

Even if we want to do bidirectional the in-stream metadata messages 
could be used to handle that; we'd need a handshake and "glare" 
resolution mechanism to decide which attempt to open the stream would 
get punted to another stream number.  That would avoid us needing a 
control channel (I believe; this is based on reading examples and APIs).

Randall, how does all this sound to you?  Did I misunderstand the 
API/protocol in some way, or do I have the gist of it correct? 
(Randall, if you're not a member of the W3 list and want to respond to 
everyone you should subscribe first - it's lower volume than rctweb.) ;-)

I'm quite open to alternative ideas, and someone could make a case for 
providing a transparent interface to the full set of SCTP functionality.

Note that if we want a dataChannel-ish API on top of SCTP, we'll need to 
have the IETF decide how they will provide it (control channel, or PPID 
meta-data messages, etc).

-- 
Randell Jesup
randell-ietf@jesup.org

Received on Friday, 3 February 2012 21:52:11 UTC