Subject: [rtcweb] Data channel setup and signalling

From: Randell Jesup <[email-masked]>
Date: Tue, 15 Nov 2011 01:42:51 -0500

The signalling discussion and how it touched on data channels got me 
thinking.

One open issue is how we define data channels, both in the "internal" 
case (no interop) and the federated case (which may have the same JS app 
or different ones at either end).

One solution is that all data channels are defined as m= lines.  They 
could be generic "m=data", or they could specify the data to be passed 
in the m= line.  For "public" message structures that might be used by 
different applications (an IM protocol, for example), one would specify 
that in some manner in the media description (perhaps via a MIME type).  
This also implies that any addition or removal (or change to) a data 
channel requires a full replacement OFFER and ANSWER.  If we stick with 
the SDP requirement about never removing m= lines, then the OFFER size 
may become unbounded.

The other option is to have (some) data channels be separate from media, 
in particular app-specific anonymous data channels.  There's no 
requirement for describing the channels if they're private to the app, 
at least to the first approximation.  An app could pre-define data 
channel 3 as a private message structure for game map updates, so long 
as it knows its talking to itself.

This has advantages in setup time, especially if the data channels are 
dynamic and invoked via another data channel, since there doesn't have 
to be a full offer-answer including the media channels.  You just need 
to make sure the two sides agree on the data to be exchanged and that 
they listen before receiving data.  It has a minor advantage in reducing 
the amount of information leakage to the server about the creation and 
types of streams (and potentially significant metadata about them).

A use-case would be a background http proxy-server during chat.  If you 
have to re-OFFER for each data channel that comes and goes to transfer a 
resource, it will both swamp the server and be slow (due to the triangle 
signalling).  If instead the application can open a single control data 
channel, and invoke transfers over it, the application can efficiently 
transfer a high number of URIs.  Are there other ways to do this without 
re-OFFERing constantly?  yes.  But they generally involve building 
protocols on top of an array of long-lasting generic connections.

For example, the control data channel might pass messages (directly 
browser-to-browser) like
{
    id: 1,
    command: "GET",
    URI: "blah/foo/bar",
    channel: 5,
}
with an answer:
{
    id: 1,
    result: "ok",
    size: 1234,
}
followed by transfer of the URI on data channel 5.  (Note: in this I'm 
assuming an API that lets the app open a specific data channel of the 
peer connection.)

Now, this is contrived, though plausible.  You could pre-open a bunch of 
idle data connections and then re-use them as needed.  The 
counter-argument is that one could write a connection-server library 
that abstracts a bunch of pre-opened data channels into an API for the 
app that works like I described above, though it may require more 
housekeeping and larger fixed resource usage.

So.....

Is it worthwhile to consider interfaces/APIs whereby an application 
could directly open data channels with no re-OFFER and implement a 
control protocol similar to the one I described?  Are there other 
use-cases for high-volume data channel create/removal, or where data 
channel latency creation is critical? (my usecase is a little contrived 
since I'm falling asleep a the keyboard.)

-- 
Randell Jesup
[email-masked]

---

From: Saúl Ibarra Corretgé <[email-masked]>
Date: Tue, 15 Nov 2011 10:04:10 +0100

HI,

On Nov 15, 2011, at 7:42 AM, Randell Jesup wrote:

> The signalling discussion and how it touched on data channels got me thinking.
> 
> One open issue is how we define data channels, both in the "internal" case (no interop) and the federated case (which may have the same JS app or different ones at either end).
> 
> One solution is that all data channels are defined as m= lines.  They could be generic "m=data", or they could specify the data to be passed in the m= line.  For "public" message structures that might be used by different applications (an IM protocol, for example), one would specify that in some manner in the media description (perhaps via a MIME type).  This also implies that any addition or removal (or change to) a data channel requires a full replacement OFFER and ANSWER.  If we stick with the SDP requirement about never removing m= lines, then the OFFER size may become unbounded.
> 

Once a stream is removed apart from setting the port to 0 all attributes may be removed to save some space (sorry, can't find where I read that :-S). Yes, it could still grow infinitely, but I've doing this for quite some time now (adding and removing audio, MSRP chat and MSRP file transfer streams) and only cheap-hotel wifi networks choked on SDP size. ;-)

> The other option is to have (some) data channels be separate from media, in particular app-specific anonymous data channels.  There's no requirement for describing the channels if they're private to the app, at least to the first approximation.  An app could pre-define data channel 3 as a private message structure for game map updates, so long as it knows its talking to itself.
> 
> This has advantages in setup time, especially if the data channels are dynamic and invoked via another data channel, since there doesn't have to be a full offer-answer including the media channels.  You just need to make sure the two sides agree on the data to be exchanged and that they listen before receiving data.  It has a minor advantage in reducing the amount of information leakage to the server about the creation and types of streams (and potentially significant metadata about them).
> 
> 
> A use-case would be a background http proxy-server during chat.  If you have to re-OFFER for each data channel that comes and goes to transfer a resource, it will both swamp the server and be slow (due to the triangle signalling).  If instead the application can open a single control data channel, and invoke transfers over it, the application can efficiently transfer a high number of URIs.  Are there other ways to do this without re-OFFERing constantly?  yes.  But they generally involve building protocols on top of an array of long-lasting generic connections.
> 
> For example, the control data channel might pass messages (directly browser-to-browser) like
> {
>   id: 1,
>   command: "GET",
>   URI: "blah/foo/bar",
>   channel: 5,
> }
> with an answer:
> {
>   id: 1,
>   result: "ok",
>   size: 1234,
> }
> followed by transfer of the URI on data channel 5.  (Note: in this I'm assuming an API that lets the app open a specific data channel of the peer connection.)
> 
> Now, this is contrived, though plausible.  You could pre-open a bunch of idle data connections and then re-use them as needed.  The counter-argument is that one could write a connection-server library that abstracts a bunch of pre-opened data channels into an API for the app that works like I described above, though it may require more housekeeping and larger fixed resource usage.
> 
> 
> So.....
> 
> Is it worthwhile to consider interfaces/APIs whereby an application could directly open data channels with no re-OFFER and implement a control protocol similar to the one I described?  Are there other use-cases for high-volume data channel create/removal, or where data channel latency creation is critical? (my usecase is a little contrived since I'm falling asleep a the keyboard.)
> 

Your proposal seems fine to me. Some may want to negotiate the data channel, some may not. A use case that comes to mind for a high-volume data channel usage would be file transfer using MSRP for example (assuming it's a valid use case).

Regards,

--
Saúl Ibarra Corretgé
AG Projects

---

From: Harald Alvestrand <[email-masked]>
Date: Tue, 15 Nov 2011 17:25:39 +0800

On 11/15/2011 02:42 PM, Randell Jesup wrote:
> case (no interop) and the federated case (which may have the same JS 
> app or different ones at either end).
>
> different applications (an IM protocol, for example), one would 
> specify that in some manner in the media description (perhaps via a 
> MIME type).  This also implies that any addition or removal (or change 
> to) a data channel requires a full replacement OFFER and ANSWER.  If 
> we stick with the SDP requirement about never removing m= lines, then 
> the OFFER size may become unbounded.
Just to add to the confusion:
If one instead keeps the (each?) SCTP connection as one m= line, one 
could instead model the data channels as corresponding to SSRCs, and 
reuse the codec declaration mechanisms from RTP m= lines to assign 
specific data syntaxes to each SSRC....

this seems to me to be a model that adheres more closely to the RTP 
model, but that doesn't mean it's a good fit to SCTP, or a good fit to 
real applications' real requirements.

>
> The other option is to have (some) data channels be separate from 
> media, in particular app-specific anonymous data channels.  There's no 
> they listen before receiving data.  It has a minor advantage in 
> reducing the amount of information leakage to the server about the 
> creation and types of streams (and potentially significant metadata 
> about them).
>
>
> A use-case would be a background http proxy-server during chat.  If 
> you have to re-OFFER for each data channel that comes and goes to 
> transfer a resource, it will both swamp the server and be slow (due to 
> the triangle signalling).  If instead the application can open a 
> single control data channel, and invoke transfers over it, the 
> application can efficiently transfer a high number of URIs.  Are there 
> other ways to do this without re-OFFERing constantly?  yes.  But they 
> generally involve building protocols on top of an array of 
> long-lasting generic connections.
>
> Now, this is contrived, though plausible.  You could pre-open a bunch 
> of idle data connections and then re-use them as needed.  The 
This example in fact VERY closely resembling FTP..... make the commands 
one-line instead of JSON blobs, and the responses into numeric codes, 
and the resemblance is just about uncanny....
> channel latency creation is critical? (my usecase is a little 
> contrived since I'm falling asleep a the keyboard.)
>
I kind of like the idea of being able to open data channels with no 
re-offer; we could pattern the API of new incoming data channels on the 
handling of SSRCs that weren't mentioned at negotiation time .... not 
that we've worked that out at the API level, last time we discussed it, 
I think it was suggested that any new SSRC was signalled as a new 
MediaStream...

---

From: Justin Uberti <[email-masked]>
Date: Tue, 15 Nov 2011 09:05:51 -0500

On Tue, Nov 15, 2011 at 4:25 AM, Harald Alvestrand <[email-masked]>wrote:

>> case (no interop) and the federated case (which may have the same JS app or
>> different ones at either end).
>>
>> could be generic "m=data", or they could specify the data to be passed in
>> the m= line.  For "public" message structures that might be used by
>> channel requires a full replacement OFFER and ANSWER.  If we stick with the
>> SDP requirement about never removing m= lines, then the OFFER size may
>> become unbounded.
>>
> If one instead keeps the (each?) SCTP connection as one m= line, one could
> instead model the data channels as corresponding to SSRCs, and reuse the
> codec declaration mechanisms from RTP m= lines to assign specific data
> syntaxes to each SSRC....
>
> this seems to me to be a model that adheres more closely to the RTP model,
> but that doesn't mean it's a good fit to SCTP, or a good fit to real
> applications' real requirements.
>
>
>
>> in particular app-specific anonymous data channels.  There's no requirement
>> for describing the channels if they're private to the app, at least to the
>> first approximation.  An app could pre-define data channel 3 as a private
>> message structure for game map updates, so long as it knows its talking to
>> itself.
>>
>> dynamic and invoked via another data channel, since there doesn't have to
>> be a full offer-answer including the media channels.  You just need to make
>> sure the two sides agree on the data to be exchanged and that they listen
>> before receiving data.  It has a minor advantage in reducing the amount of
>> information leakage to the server about the creation and types of streams
>> (and potentially significant metadata about them).
>>
>>
>> assuming an API that lets the app open a specific data channel of the peer
>> connection.)
>>
>> idle data connections and then re-use them as needed.  The counter-argument
>> is that one could write a connection-server library that abstracts a bunch
>> of pre-opened data channels into an API for the app that works like I
>> described above, though it may require more housekeeping and larger fixed
>> resource usage.
>>
> one-line instead of JSON blobs, and the responses into numeric codes, and
> the resemblance is just about uncanny....
>
>
>> So.....
>>
>> Is it worthwhile to consider interfaces/APIs whereby an application could
>> directly open data channels with no re-OFFER and implement a control
>> protocol similar to the one I described?  Are there other use-cases for
>> high-volume data channel create/removal, or where data channel latency
>> creation is critical? (my usecase is a little contrived since I'm falling
>> asleep a the keyboard.)
>>
> handling of SSRCs that weren't mentioned at negotiation time .... not that
> we've worked that out at the API level, last time we discussed it, I think
> it was suggested that any new SSRC was signalled as a new MediaStream...
>
>
I'd prefer to have one way of doing things that's consistent, i.e. using
re-OFFER for adding datastreams or SSRCs. This wouldn't have to be slow; if
you already had a datastream, as you indicate in your example, the re-OFFER
could occur over this path. Doing it this way would also allow metadata
regarding the SSRC or datastream to be communicated to the other side prior
to using the stream.

>
> ______________________________**_________________
> rtcweb mailing list
> [email-masked]
> https://www.ietf.org/mailman/**listinfo/rtcweb<https://www.ietf.org/mailman/listinfo/rtcweb>
>

---

From: Randell Jesup <[email-masked]>
Date: Tue, 15 Nov 2011 14:19:19 -0500

On 11/15/2011 9:05 AM, Justin Uberti wrote:
>
>
> On Tue, Nov 15, 2011 at 4:25 AM, Harald Alvestrand <[email-masked]
> <mailto:[email-masked]>> wrote:
>
>         One open issue is how we define data channels, both in the
>         "internal" case (no interop) and the federated case (which may
>         have the same JS app or different ones at either end).
>
>         One solution is that all data channels are defined as m= lines.
>           They could be generic "m=data", or they could specify the data
>         to be passed in the m= line.  For "public" message structures
>         that might be used by different applications (an IM protocol,
>         for example), one would specify that in some manner in the media
>         description (perhaps via a MIME type).  This also implies that
>         any addition or removal (or change to) a data channel requires a
>         full replacement OFFER and ANSWER.  If we stick with the SDP
>         requirement about never removing m= lines, then the OFFER size
>         may become unbounded.
>
>     model, but that doesn't mean it's a good fit to SCTP, or a good fit
>     to real applications' real requirements.

That's interesting... something like

    m=data 1234 webrtc/data 1 2 3 4
    a=rtpmap:1 SCTP/8000/1
    a=ftmp:1 reliable
    a=rtpmap:2 SCTP/8000/2
    a=fmtp:2 partially-reliable;time-limit=500
    a=rtpmap:3 SCTP/8000/3
    a=ftmp:3 reliable;stream
    a=rtpmap:4 SCTP/8000/4
    a=ftmp:4 unreliable;out-of-order

etc.  The /1, /2 paramter to rtpmap would be the SCTP data channel 
number (or the "payload" value could also be that).  Or, as you say, 
they could be SSRCs, but you need to pre-define what type of data 
channel they correspond to as per above.  Plus remember we don't have an 
SSRC on each datagram; it comes into a channel, and something needs to 
know it's coming and service the stream.

>         The other option is to have (some) data channels be separate
>         from media, in particular app-specific anonymous data channels.
>           There's no requirement for describing the channels if they're
>         private to the app, at least to the first approximation.  An app
>         could pre-define data channel 3 as a private message structure
>         for game map updates, so long as it knows its talking to itself.
>
>         This has advantages in setup time, especially if the data
>         channels are dynamic and invoked via another data channel, since
>         there doesn't have to be a full offer-answer including the media
>         channels.  You just need to make sure the two sides agree on the
>         data to be exchanged and that they listen before receiving data.
>           It has a minor advantage in reducing the amount of information
>         leakage to the server about the creation and types of streams
>         A use-case would be a background http proxy-server during chat.
>           If you have to re-OFFER for each data channel that comes and
>         goes to transfer a resource, it will both swamp the server and
>         be slow (due to the triangle signalling).  If instead the
>         application can open a single control data channel, and invoke
>         transfers over it, the application can efficiently transfer a
>         high number of URIs.  Are there other ways to do this without
>         re-OFFERing constantly?  yes.  But they generally involve
>         building protocols on top of an array of long-lasting generic
>         connections.
>
>         followed by transfer of the URI on data channel 5.  (Note: in
>         this I'm assuming an API that lets the app open a specific data
>         channel of the peer connection.)
>
>         Now, this is contrived, though plausible.  You could pre-open a
>         bunch of idle data connections and then re-use them as needed.
>           The counter-argument is that one could write a
>         connection-server library that abstracts a bunch of pre-opened
>         data channels into an API for the app that works like I
>         described above, though it may require more housekeeping and
>         larger fixed resource usage.
>
>     This example in fact VERY closely resembling FTP..... make the
>     commands one-line instead of JSON blobs, and the responses into
>     numeric codes, and the resemblance is just about uncanny....

Yeah, that's not entirely unintentional.  Originally the example WAS 
effectively multi-channel FTP (background file transfer), but I thought 
this was more interesting.

>         So.....
>
>         Is it worthwhile to consider interfaces/APIs whereby an
>         application could directly open data channels with no re-OFFER
>         and implement a control protocol similar to the one I described?
>           Are there other use-cases for high-volume data channel
>         create/removal, or where data channel latency creation is
>         critical? (my usecase is a little contrived since I'm falling
>         asleep a the keyboard.)
>
>     re-offer; we could pattern the API of new incoming data channels on
>     the handling of SSRCs that weren't mentioned at negotiation time
>     .... not that we've worked that out at the API level, last time we
>     discussed it, I think it was suggested that any new SSRC was
>     signalled as a new MediaStream...
>
>
> re-OFFER for adding datastreams or SSRCs. This wouldn't have to be slow;
> if you already had a datastream, as you indicate in your example, the
> re-OFFER could occur over this path. Doing it this way would also allow
> metadata regarding the SSRC or datastream to be communicated to the
> other side prior to using the stream.

Well, we haven't talked directly about using a datastream to do 
re-OFFER.  Certainly possible, if we have a datastream defined for that 
(and since transport of the signalling is entirely up to the 
application, it could use a datastream for updated OFFER and ANSWERs). 
It is a bit chicken-and-egg like, but in practice that's not a problem 
if we're careful not to close the datastream used for this in the 
re-OFFER...

A big issue with re-offer on every data channel coming or going is that 
the overhead of offer-answer is significant (especially if we don't find 
a way to cull 'dead' m= lines in ROAP/SDP).  We probably need to make 
sure in any case that parts of the SDP that don't change never notice a 
re-OFFER/ANSWER however, not even to force an IDR or re-init a jitter 
buffer.

-- 
Randell Jesup
[email-masked]

---

From: Wolfgang Beck <[email-masked]>
Date: Wed, 16 Nov 2011 02:40:10 +0100

On Tue, Nov 15, 2011 at 7:42 AM, Randell Jesup <[email-masked]> wrote:
> The other option is to have (some) data channels be separate from media, in
> particular app-specific anonymous data channels.  There's no requirement for
> describing the channels if they're private to the app, at least to the first
> approximation.  An app could pre-define data channel 3 as a private message
> structure for game map updates, so long as it knows its talking to itself.
>
> dynamic and invoked via another data channel, since there doesn't have to be
> a full offer-answer including the media channels.  You just need to make
> before receiving data.
..Let the JS client code be the protocol standard for your data
channel. This is a good example
where the ROAP model leads to a clumsy solution.

> It has a minor advantage in reducing the amount of
The JS client code can inform to the server any time. You have to trust the
server when running its JS client code.

Wolfgang Beck

---

From: Hadriel Kaplan <[email-masked]>
Date: Wed, 16 Nov 2011 06:05:29 +0000

> One open issue is how we define data channels, both in the "internal" case (no interop) and the federated case (which may have the same JS app or different ones at either end).

Well one question is if there should be two different ways for doing it to begin with. :)
I think it's obvious that from a practical perspective there'll be tons of web-app data-channel usage which will only be in the same WebRTC domain. But I don't see how we can honestly create a SDP media attribute to mean "void".

Months ago when I was arguing against putting SDP in the browser, I pointed out that using SDP means using SDP and being stuck with actually following SDP, including IANA registries, having to be *real* SDP which can go anywhere, etc.

Maybe we do something like:
  m=application 1234 UDP/DTLS/SCTP/APP *
  a=app-type:www.mydomain.com

> One solution is that all data channels are defined as m= lines.  They could be generic "m=data", or they could specify the data to be passed in the m= line.  For "public" message structures that mi…

I'm not sure the above is a problem: you can re-use m-lines.

-hadriel

---

From: Wolfgang Beck <[email-masked]>
Date: Wed, 16 Nov 2011 14:14:09 +0800

>  a=app-type:www.mydomain.com
Hey, we could do this for audio, video as well!

Wolfgang Beck

---

From: Stefan Håkansson LK <[email-masked]>
Date: Thu, 17 Nov 2011 14:47:11 +0100

> as it knows its talking to itself.

I like this. Is there really a need to signal individual data channels 
at all (except for setting up data - one m-line saying "data")?

When data is available the allocation of channels can be handled by the 
app itself with no associated signaling. Either the app knows that 
channel 3 is always used for this and channel 5 for that; or the app 
signals using one predefined channel the contents of the other channels.

For the federated case, there could be a document describing what to use 
the channels for (if needed).