RFC 8864

Negotiation Data Channels Using the Session Description Protocol (SDP)

πŸ“… published January 2021, from ietf

RFC 8864: Negotiation Data Channels Using SDP πŸ¦‹

okay bestie, this one is RFC 8864, titled Negotiation Data Channels Using the Session Description Protocol (SDP) ✨. It's a Standards Track document from the IETF, which means it's an actual Internet standard and not just a suggestion. It was published in January 2021 and has ISSN 2070-1721. The authors are K. Drage, M. Makaraju, R. Ejzak, J. Marcon (listed as Unaffiliated), and R. Even, who is the editor (Ed.). The title block doesn't list any RFCs that it obsoletes or updates, so this one is standing on its own πŸ’….

Abstract ✨

okay so, data channel setup can happen in two ways: in-band with DCEP (Data Channel Establishment Protocol), or out-of-band with some non-DCEP protocol 🫢. This document explains how the SDP offer/answer exchange can be used to do that out-of-band non-DCEP negotiation for setting up a data channel. it's giving "pick your own vibe" energy 🌈

Status of This Memo

this part is the official paperwork πŸ“‹. The document is an Internet Standards Track document and a product of the IETF. It represents the consensus of the IETF community, got public review, and was approved by the Internet Engineering Steering Group (IESG). If you want more on Internet Standards, check Section 2 of RFC 7841. For the current status, any errata, and how to give feedback, go to https://www.rfc-editor.org/info/rfc8864 πŸ”—.

Copyright (c) 2021 IETF Trust and the persons identified as the document authors. All rights reserved πŸŽ€. This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents, which are at https://trustee.ietf.org/license-info and were in effect on the publication date. Please actually read these, because they describe your rights and restrictions. Code components pulled out of this document must include Simplified BSD License text as described in Section 4.e of the Trust Legal Provisions, and they come without warranty, as the Simplified BSD License describes.

Table of Contents πŸ“š

1.  Introduction
2.  Conventions
3.  Terminology
4.  Applicability Statement
5.  SDP Data Channel Attributes
  5.1.  SDP DCMAP Attribute
    5.1.1.  DCMAP Attribute Syntax
    5.1.2.  'dcmap-stream-id' Parameter
    5.1.3.  'label' Parameter
    5.1.4.  'subprotocol' Parameter
    5.1.5.  'max-retr' Parameter
    5.1.6.  'max-time' Parameter
    5.1.7.  'ordered' Parameter
    5.1.8.  'priority' Parameter
    5.1.9.  DCMAP Multiplexing Category
  5.2.  SDP DCSA Attribute
    5.2.1.  DCSA Attribute Syntax
    5.2.2.  DCSA Multiplexing Category
6.  SDP Offer/Answer Procedures
  6.1.  Managing Stream Identifiers
  6.2.  Negotiating Data Channel Parameters
  6.3.  Generating the Initial Offer for a Data Channel
  6.4.  Generating the SDP Answer
  6.5.  Offerer Processing of the SDP Answer
  6.6.  Modifying the Session
    6.6.1.  Closing a Data Channel
  6.7.  Various SDP Offer/Answer Considerations
7.  Examples
8.  Security Considerations
9.  IANA Considerations
  9.1.  Subprotocol Identifiers
  9.2.  New SDP Attributes
    9.2.1.  dcmap
    9.2.2.  dcsa
  9.3.  Registering Attributes for Use with Data Channels
10. References
  10.1.  Normative References
  10.2.  Informative References
Appendix A.  Generic Data Channel Negotiation Aspects when Not
        Using DCEP
  A.1.  Stream Identifier Numbering
  A.2.  Generic Data Channel Negotiation Not Using DCEP
    A.2.1.  Overview
    A.2.2.  Opening a Data Channel
    A.2.3.  Closing a Data Channel
Acknowledgements
Contributors
Authors' Addresses

1. Introduction 🌸

okay so, a bidirectional data channel that runs on top of SCTP (the Stream Control Transmission Protocol) is covered in [RFC8831], and that's what lets applications use data channels πŸ’–. The in-band DCEP is described in [RFC8832], but honestly other in-band or out-of-band protocols can also set up data channels πŸ™ˆ. Every data channel is a pair of SCTP streams that share the same SCTP Stream Identifier.

Apps create data channels in one of two ways: (1) the WebRTC API (Application Programming Interface) [WebRtcAPI], or (2) other protocols, like Controlling Multiple Streams for Telepresence (CLUE) [RFC8850] 🧚. The protocol gets signaled with the data channel 'subprotocol' parameter, which is kinda like a WebSocket subprotocol from [RFC6455] πŸ”₯. The main thing is that besides the "subprotocol" value that gets sent to the peer, the two endpoint applications can agree on how to start up a given subprotocol on a data channel. They can also agree on whether it gets signaled in-band with DCEP, out-of-band with a non-DCEP protocol, or both πŸ‘‘.

This document defines the SDP (Session Description Protocol) offer/answer procedures from [RFC3264] πŸ’…. These procedures make out-of-band negotiation possible for setting up data channels that carry well-defined subprotocols. They're based on the general SDP offer/answer rules for SCTP-based media transport in [RFC8841], for the SDP m= line proto values UDP/DTLS/SCTP and TCP/DTLS/SCTP ✨.

This document uses MSRP (the Message Session Relay Protocol) [RFC4975] and BFCP (the Binary Floor Control Protocol) [RFC8855] in a few examples πŸ¦‹. It does NOT give a complete spec for negotiating a data channel that carries MSRP, though. Each subprotocol's own procedures would need to be written up somewhere else. For MSRP, that's [RFC8873]. The MSRP examples are only there to show how the general procedures might apply to one specific subprotocol πŸ“.

2. Conventions πŸ“œ

The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174], but only when they show up in all capitals, exactly like that πŸ’œ. Anywhere else, they're just regular words, no special powers πŸ™ƒ.

3. Terminology πŸ”

okay, here are the terms this document uses, and I'm obsessed with how precise they are πŸ€“.

Data channel: A WebRTC data channel, as specified in [RFC8831].

Data channel stack: An entity that runs the data channel protocol when an application asks it to. It keeps track of states, plus sending and receiving data. If the application is a browser-based JavaScript app, the stack lives in the browser. If it's a native app, the stack lives in the app and you reach it through some kind of API or APIs 🌈.

Data channel properties: Fixed properties given to a data channel when it gets created. Some of them decide how the data channel stack sends data on that channel, like the stream identifier, reliability, and order of delivery ✨.

Data channel subprotocol: The application protocol carried over one data channel. Subprotocol messages get sent as data channel payload over an established data channel. An SDP offer/answer exchange, as specified in this document, can negotiate setting up data channels, their properties, the subprotocols attached to them, and the subprotocol properties πŸŽ€. When that happens, the data channel subprotocols can be identified by the values of the 'subprotocol' parameters of the SDP a=dcmap: attribute, described in Section 5.1.4. Inside this document, "data channel subprotocol" usually gets shortened to just "subprotocol" 🫢.

DCEP: Data Channel Establishment Protocol, as defined in [RFC8832] πŸ› οΈ.

In-band: Transmission through the peer-to-peer SCTP association πŸ”—.

Out-of-band: Transmission through the application signaling path πŸ“‘.

Peer: From the point of view of one agent in a session, its peer is the other agent. So from the SDP offerer's point of view, the peer is the SDP answerer. And from the SDP answerer's point of view, the peer is the SDP offerer πŸ‘―.

SCTP Stream Sequence Number (SSN): The SCTP Stream Sequence Number, as specified in [RFC4960] 🧾.

Stream identifier: The identifier of the outbound and inbound SCTP streams that make up a data channel πŸ’œ.

4. Applicability Statement 🚦

This mechanism only applies to SDP [RFC8866] when it's used together with the SDP offer/answer mechanism [RFC3264]. Declarative usage of SDP is out of scope for this document, so it's undefined here πŸ™…β€β™€οΈ.

5. SDP Data Channel Attributes πŸ’–

This section defines two new SDP media-level attributes. You can use them with the SDP Offer/Answer mechanism to negotiate data-channel-specific and subprotocol-specific parameters, and you don't need DCEP [RFC8832] for that πŸŽ‰. The first attribute (Section 5.1) negotiates channel-specific parameters. The second attribute (Section 5.2) negotiates subprotocol-specific parameters ✨.

Note: Appendix A explains how data channels work in general. It also sums up some key things to think about when negotiating data channels without DCEP, so go peek if that's you πŸ‘€.

5.1. SDP DCMAP Attribute πŸ—ΊοΈ

This section defines a new media-level attribute, a=dcmap:, which sets the data channel parameters for each data channel being negotiated 🧁.

This attribute is used to create bidirectional SCTP data channels that all have the same set of attributes. The data channel properties (reliable, partially reliable, ordered, or unordered) need to suit the subprotocol's transport requirements, so pick wisely, bestie πŸ’….


to be continued... part 2 is where the DCMAP syntax and its parameters show up, and it gets SO good πŸ¦‹πŸ’œ

5.1.1. DCMAP Attribute Syntax πŸŽ€

Okay bestie, so a=dcmap: is a media-level attribute, and its definition and ABNF syntax come from [RFC5234] (yes, the ABNF one πŸ’…). Here's the whole attribute at a glance:

                 +=================================+
                 |       "a=dcmap:" Attribute      |
                 +===================+=============+
                 | Name              | dcmap       |
                 +-------------------+-------------+
                 | Value             | dcmap-value |
                 +-------------------+-------------+
                 | Usage Level       | media       |
                 +-------------------+-------------+
                 | Charset Dependent | No          |
                 +-------------------+-------------+

                    Table 1: "a=dcmap:" Attribute
                              Definition

Now the formal syntax, which is giving precise and kind of iconic πŸ”₯:

dcmap-value     = dcmap-stream-id
                  [ SP dcmap-opt *(";" dcmap-opt) ]
dcmap-opt       = ordering-opt / subprotocol-opt / label-opt
                  / maxretr-opt / maxtime-opt / priority-opt
                  ; maxretr-opt and maxtime-opt are
                  ; mutually exclusive

dcmap-stream-id = 1*5DIGIT
ordering-opt    = "ordered=" ordering-value
ordering-value  = "true" / "false"
subprotocol-opt = "subprotocol=" quoted-string
label-opt       = "label=" quoted-string
maxretr-opt     = "max-retr=" maxretr-value
maxretr-value   = "0" / integer
                  ; number of retransmissions,
                  ; less than 2^32,
                  ; derived from 'Reliability Parameter' [RFC8832]
maxtime-opt     = "max-time=" maxtime-value
maxtime-value   = "0" / integer
                  ; milliseconds,
                  ; less than 2^32,
                  ; derived from 'Reliability Parameter' [RFC8832]
priority-opt    = "priority=" priority-value
priority-value  = "0" / integer
                  ; unsigned integer value indicating the priority of
                  ; the data channel,
                  ; less than 2^16,
                  ; derived from 'Priority' [RFC8832]

quoted-string   = DQUOTE *(quoted-char / escaped-char) DQUOTE
quoted-char     = SP / quoted-visible
quoted-visible  = %x21 / %x23-24 / %x26-7E ; VCHAR without " or %
escaped-char    = "%" HEXDIG HEXDIG
DQUOTE          = <from RFC 5234>
integer         = <from RFC 8866>

And some examples to vibe check 🧚:

a=dcmap:0
a=dcmap:1 subprotocol="bfcp";max-time=60000;priority=512
a=dcmap:2 subprotocol="msrp";ordered=true;label="msrp"
a=dcmap:3 label="Label 1";ordered=false;max-retr=5;priority=128
a=dcmap:4 label="foo%09bar";ordered=true;max-time=15000
Note: The last example (a=dcmap:4) has a label value with one nonprintable escaped-char in it, which is the tab character (%09). Slay the detail πŸ™ˆ

Okay, real talk on the rules: on a single a=dcmap: line, only one max-retr parameter or one max-time parameter can show up, not both. They MUST NOT be present together 🚫

5.1.2. 'dcmap-stream-id' Parameter πŸ¦‹

So dcmap-stream-id is the SCTP stream identifier inside the SCTP association that gets used to form the data channel. It's basically the channel's address in the SCTP association πŸ’œ

5.1.3. 'label' Parameter 🏷️

The label parameter is the name of the channel. In the context of the WebRTC API [WebRtcAPI], it's what lets you tell one RTCDataChannel object apart from another RTCDataChannel object. It maps to the 'Label' parameter defined in [RFC8832]. label is optional, and if it's not there, its value defaults to the empty string πŸ“

When it's time to talk to the WebRTC API, the label parameter should:

  • Serialize the WebRTC label as a UTF-8 string [RFC3629].
  • Treat the UTF-8 serialization as a series of bytes.
  • For each byte in the serialization,
    • If the byte can be expressed as a 'quoted-char', do so.
    • Otherwise, express the byte as an 'escaped-char'.
Note: The empty string can also be used on purpose as a label value, so label="" means the same thing as not including the label parameter at all. [RFC8832] lets the DATA_CHANNEL_OPEN message's 'Label' value be an empty string, so it's all valid πŸ™Œ

5.1.4. 'subprotocol' Parameter 🧁

The subprotocol parameter says which protocol the client expects to exchange over the channel. It maps to the 'Protocol' parameter defined in [RFC8832]. Section 9.1 explains how values for new subprotocol parameters get registered. subprotocol is optional, and if it's missing, its value defaults to an empty string ✨

Note: The empty string can also be used on purpose as a subprotocol value, so subprotocol="" means the same thing as not including the subprotocol parameter at all. [RFC8832] lets the DATA_CHANNEL_OPEN message's 'Protocol' value be an empty string.

5.1.5. 'max-retr' Parameter πŸ”

This parameter tells you the data channel is partially reliable 🫢 The max-retr parameter is the maximum number of times a user message gets retransmitted. It's optional. If max-retr and max-time are both absent, reliable transmission happens as specified in [RFC4960]. This parameter maps to the 'Number of RTX' parameter defined in [RFC8832].

5.1.6. 'max-time' Parameter ⏳

Also partially reliable, bestie πŸ¦‹ A user message stops being transmitted or retransmitted once its lifetime runs out. The lifetime is given in milliseconds in the max-time parameter, and it starts counting when the user message is handed to the protocol stack. max-time is optional. If max-retr and max-time are both absent, reliable transmission happens as specified in [RFC4960]. This parameter maps to the 'Lifetime in ms' parameter defined in [RFC8832].

5.1.7. 'ordered' Parameter πŸ“¬

When ordered has the value "true", the receiver passes DATA chunks in the data channel up to the upper layer while keeping their order 🧠 ordered is optional and has two values: "true" for ordered delivery and "false" for unordered delivery. The default is "true". Any other value gets ignored, and then "ordered=true" is assumed. If the parameter isn't there at all, "ordered=true" is also assumed. This parameter maps to the ordered or unordered data channel types defined in [RFC8832].

5.1.8. 'priority' Parameter πŸ‘‘

The priority parameter shows the data channel's priority compared to other data channels, which might also exist over the same SCTP association. It maps to the 'Priority' parameter defined in [RFC8832]. priority is optional. If it's not there, "priority=256" is assumed πŸ’…

5.1.9. DCMAP Multiplexing Category 🌈

The multiplexing category [RFC8859] of the a=dcmap: attribute is SPECIAL, which is a whole vibe 😭

Using multiple SCTP associations on top of a single DTLS association is outside the scope of [RFC8841]. Because of that, no a=dcmap: multiplexing rules are specified for the UDP/DTLS/SCTP and TCP/DTLS/SCTP proto values. If future extensions of [RFC8841] define how to negotiate multiplexing of multiple SCTP associations on top of a single DTLS association, or how to add multiple SCTP associations to one BUNDLE group, then multiplexing rules for the a=dcmap: attribute need to be defined as well. For instance, that could happen in an extension of this specification πŸŽ€

5.2. SDP DCSA Attribute πŸ§šβ€β™€οΈ

In the SDP media description, each data channel declaration MAY also be followed by other SDP attributes. These apply to the matching data channel and its subprotocol. Each one is represented by a new a=dcsa: attribute line that references another SDP attribute defined for use with this data channel's subprotocol. Instructions for registering attributes for use with a data channel are in Section 9.3 ✨

Any SDP attribute that's related to the subprotocol and would normally be used to negotiate it through the SDP offer/answer mechanism gets replaced with an attribute of the form a=dcsa:stream-id original-attribute. Here dcsa stands for "data channel subprotocol attribute", stream-id is the SCTP stream identifier assigned to this subprotocol instance, and original-attribute holds the contents of the subprotocol-related attribute being included.

The same syntax applies to any other SDP attribute needed to negotiate this instance of the subprotocol 🫧

The detailed offer/answer procedures for the dcsa attribute depend on the associated subprotocol. If no offer/answer procedures exist for the subprotocol when it's used outside of the dcsa attribute, nothing needs to be specified for use with dcsa. The IANA (Internet Assigned Numbers Authority) registration procedures for the "WebSocket Subprotocol Name Registry" (Section 9.1) don't strictly require a specification of the offer/answer procedures for the subprotocol when it's used with dcsa. If the subprotocol has defined offer/answer procedures when used outside of dcsa, such a specification is encouraged to keep things interoperable 🀝 If the subprotocol has defined offer/answer procedures outside of dcsa but there's no specification for them when used with dcsa, implementations SHOULD assume the default values for all otherwise-negotiable and applicable subprotocol parameters πŸ’–

5.2.1. DCSA Attribute Syntax ✨

okay so this is where the a=dcsa: attribute gets its grammar πŸŽ€ it's a media-level attribute, and the ABNF is defined using [RFC5234] πŸ’…

Here's the whole vibe in one table, bestie πŸ¦‹

                 +================================+
                 |      "a=dcsa:" Attribute       |
                 +===================+============+
                 | Name              | dcsa       |
                 +-------------------+------------+
                 | Value             | dcsa-value |
                 +-------------------+------------+
                 | Usage Level       | media      |
                 +-------------------+------------+
                 | Charset Dependent | No         |
                 +-------------------+------------+

                    Table 2: "a=dcsa:" Attribute
                             Definition

The formal syntax is literally just this 🌸

dcsa-value      = stream-id SP attribute
stream-id       = 1*5DIGIT
attribute       = <from RFC 8866>

and here's an example that makes it click πŸ“

a=dcmap:2 subprotocol="msrp";ordered=true;label="msrp"

a=dcsa:2 accept-types:text/plain

So the [RFC8866] reference just tells you where the attribute definition lives, it doesn't limit support for attributes defined in other documents that follow this format 🧚 BUT not every SDP attribute is suitable to go inside a dcsa 😭 The IANA SDP parameters registry has the lists of session-level and media-level (or media-level-only) attributes, so check there πŸ‘‘

In the example, the original a=accept-types:text/plain becomes a=dcsa:2 accept-types:text/plain, which says this instance of the MSRP subprotocol, carried over the SCTP association on the data channel with stream id 2, accepts plaintext files πŸ’œ

Here's the big difference from the a=dcmap: parameters: these ones are subject to offer/answer negotiation, following the procedures in the subprotocol-specific documents πŸ”₯

It's assumed that subprotocol-related media-level attributes are generally independent of the subprotocol's transport protocol 🫢 So those transport-independent attributes get used exactly the same way as in the original subprotocol spec, even when the subprotocol runs over a data channel and the attribute is wrapped in a dcsa 🌈

There may be cases where the usage does depend on the transport protocol πŸ™ˆ In that case, the data-channel usage is expected to be described for the data channel transport. A data-channel-specific usage is expected to be specified in the same document that registers the subprotocol's identifier for data channel usage, as described in Section 9.1 ✨

5.2.2. DCSA Multiplexing Category ⭐

The multiplexing category of the a=dcsa: attribute is SPECIAL πŸ¦‹

Since using multiple SCTP associations on top of a single DTLS association is outside the scope of [RFC8841], there are no a=dcsa: multiplexing rules for the UDP/DTLS/SCTP and TCP/DTLS/SCTP proto values πŸ’– If future extensions of [RFC8841] define how to negotiate multiplexing of multiple SCTP associations on one DTLS association, or how to add multiple SCTP associations to one BUNDLE group, then multiplexing rules for a=dcsa: will need to be defined too, for instance in an extension of this specification πŸŽ€

6. SDP Offer/Answer Procedures πŸ‘‘

okay this section is where the actual negotiation choreography happens πŸ’… A single media description can describe multiple data channels (each one gets its own SDP dcmap attribute), and they can be created, modified, and closed across different offer/answer exchanges πŸ¦‹ The procedures here apply to one given data channel at a time 🌸

The generic offer/answer procedures for negotiating the SCTP association are defined in [RFC8841], and this section only covers the data-channel-specific bits 🧚

"Initial offer" refers to the offer where a data channel gets opened. It can be either the initial offer or a subsequent offer of the associated SDP session πŸ’œ

The detailed offer/answer procedures for the dcsa attribute depend on the associated subprotocol, so see Section 5.2 🫢

6.1. Managing Stream Identifiers πŸ”₯

To avoid SCTP stream identifier collisions, in alignment with [RFC8832], the endpoint acting as a DTLS client (for the SCTP association used to realize data channels) MUST use even identifier values, and the endpoint acting as a DTLS server MUST use odd identifier values πŸ’–

SCTP stream identifiers tied to data channels negotiated using DCEP MUST NOT be included in SDP offers and answers 😭

6.2. Negotiating Data Channel Parameters 🌈

The data channel types defined in [RFC8832] map to the dcmap SDP attribute parameters like this, where ordered=true is the default and can be left out πŸ“

DATA_CHANNEL_RELIABLE
   ordered=true

DATA_CHANNEL_RELIABLE_UNORDERED
   ordered=false

DATA_CHANNEL_PARTIAL_RELIABLE_REXMIT
   ordered=true;max-retr=<number of retransmissions>

DATA_CHANNEL_PARTIAL_RELIABLE_REXMIT_UNORDERED
   ordered=false;max-retr=<number of retransmissions>

DATA_CHANNEL_PARTIAL_RELIABLE_TIMED
   ordered=true;max-time=<lifetime in milliseconds>

DATA_CHANNEL_PARTIAL_RELIABLE_TIMED_UNORDERED
   ordered=false;max-time=<lifetime in milliseconds>

By definition, max-retr and max-time are mutually exclusive, so both MUST NOT be present in the a=dcmap: attribute line πŸ™…β€β™€οΈ If an SDP offer contains both, the receiver MUST reject that offer. If an SDP answer contains both, the offerer MUST treat the associated offer/answer as failed πŸ’€

6.3. Generating the Initial Offer for a Data Channel πŸŽ€

When an offerer sends an initial offer to negotiate an SCTP stream for a data channel, the offerer:

  • SHALL include an SDP dcmap attribute (Sections 5.1 and 6.2) associated with the data channel in the m= section representing the SCTP association used to realize the data channel, and
  • MAY include one or more SDP dcsa attributes (Section 5.2) associated with the data channel. The value of the 'stream-id' part of each attribute SHALL match the 'dcmap-stream-id' value of the dcmap attribute 🧚

6.4. Generating the SDP Answer πŸ¦‹

When an answerer gets an offer with an m= section for an SCTP association, and the offer describes an SCTP stream for a data channel, and the answerer accepts that data channel, it:

  • SHALL include an SDP dcmap attribute (Sections 5.1 and 6.2) associated with the data channel in the m= section representing the SCTP association used to realize the data channel. The values of the 'dcmap-stream-id', 'max-retr', and 'max-time' in the dcmap attribute SHALL be identical to the values used for the data channel in the offer, and
  • MAY include one or more SDP dcsa attributes (Section 5.2) associated with the data channel πŸ’œ

6.5. Offerer Processing of the SDP Answer πŸ’…

An offerer receiving an SDP answer does the following:

  • It SHALL close any created data channels, as described in Section 6.6.1, for which the expected a=dcmap: attributes are not present in the SDP answer. If the SDP answer has no a=dcmap: attributes, then either the peer doesn't support them or it rejected all the data channels. Either way, the offerer closes all the data channels offered by SDP that were open at the time of the offer 😭 The DTLS association and SCTP association will still be set up. At this point, the offerer MAY use DCEP negotiation [RFC8832] to open data channels 🌸

Each agent application MUST wait to send data until it has confirmation that the data channel at the peer is instantiated. For WebRTC, that's when both data channel stacks have channel parameters instantiated, and it happens like this:

  • At both peers, when a data channel is created without a previously established SCTP association, as soon as the SCTP association is successfully established πŸ”₯
  • At the agent receiving an SDP offer for which there is an established SCTP association, as soon as it creates the negotiated data channel based on the information in the SDP offer 🫢
  • At the agent sending an SDP offer to create a new data channel for which there is an established SCTP association, when it receives the SDP answer confirming acceptance of the data channel, or when it starts receiving data on the data channel from the peer, whichever comes first πŸ“

6.6. Modifying the Session 🌈

When an offerer sends a subsequent offer that includes information for a previously negotiated data channel, unless the offerer intends to close that data channel (Section 6.6.1), the offerer SHALL include the previously negotiated SDP attributes and attribute values associated with the data channel. The answerer MAY reject the offer. How rejection works depends on the higher-layer protocol. The offer/answer exchange is atomic: if the answer is rejected, the session reverts to the state it was in before the offer [RFC3264] 🧚

6.6.1. Closing a Data Channel πŸ’–

To close a data channel, the endpoint that wants to close it SHALL send an SCTP SSN Reset message [RFC6525], following the procedure in Section 6.7 of [RFC8831]. On top of that, if the closed data channel was negotiated using the offer/answer mechanism (Section 6.3), the endpoint that closed it SHALL send a subsequent offer that does one of the following:

  • Removes the SDP dcmap attribute and SDP dcsa attributes associated with the closed data channel. Once the endpoint gets a successful answer, the SCTP stream identifier value can later be used for a new data channel (negotiated using either SCTP or the offer/answer mechanism), or
  • After a reset has been performed, reuses the SCTP stream used for the closed data channel for a new data channel, following the procedure in Section 6.3. The offerer SHALL use a different SDP dcmap attribute value for the data channel using the same SCTP stream πŸŽ€

6.7. Various SDP Offer/Answer Considerations πŸ‘‘

If an SDP offer or answer has no a=dcmap: attributes but does have a=dcsa: attributes, that's an error case πŸ™ˆ In this case, the receiver of such an offer or answer MUST discard the a=dcsa: attributes.

If an SDP offer or answer has an a=dcsa: attribute whose subprotocol attribute is unknown, the receiver of that offer or answer SHOULD ignore this entire a=dcsa: attribute line πŸ¦‹

If an SDP offer or answer has an a=dcsa: attribute whose subprotocol attribute is known, but whose subprotocol attribute semantic isn't known for the data channel transport case, the receiver of that offer or answer SHOULD ignore this entire a=dcsa: attribute line 🌸

7. Examples πŸŽ€

Okay bestie, Figure 1 is the one where the SDP answerer says "nope" to the data channel with stream id 0. Maybe it's a deliberate no, or maybe it just doesn't understand the a=dcmap: attribute πŸ™ˆ. Either way the offerer closes that channel. The SCTP association still gets set up over DTLS ✨, and after that the offerer or the answerer can use DCEP negotiation to open channels πŸ¦‹.

m=application 10001 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP6 2001:db8::3
a=max-message-size:100000
a=sctp-port:5000
a=setup:actpass
a=fingerprint:SHA-1 \
    4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB
a=tls-id:abc3de65cddef001be82
a=dcmap:0 subprotocol="bfcp";label="bfcp"
m=application 10002 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP6 2001:db8::1
a=max-message-size:100000
a=sctp-port:5002
a=setup:passive
a=fingerprint:SHA-1 \
    5B:AD:67:B1:3E:82:AC:3B:90:02:B1:DF:12:5D:CA:6B:3F:E5:54:FA
a=tls-id:dcb3ae65cddef0532d42

Figure 1: Example 1

Figure 2 is the one with a little drama πŸ’…. The offer has data channels for both BFCP and MSRP. The answer says no to BFCP and yes to MSRP. So the offerer closes the BFCP channel, and once the SCTP association is up, both sides can start using the MSRP channel πŸ’–. Stream id 0 is now free for future DCEP or SDP offer/answer negotiation.

m=application 10001 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 192.0.2.1
a=max-message-size:100000
a=sctp-port:5000
a=setup:actpass
a=fingerprint:SHA-1 \
    4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB
a=tls-id:abc3de65cddef001be82
a=dcmap:0 subprotocol="bfcp";label="bfcp"
a=dcmap:2 subprotocol="msrp";label="msrp"
a=dcsa:2 accept-types:message/cpim text/plain
a=dcsa:2 path:msrp://alice.example.com:10001/2s93i93idj;dc
m=application 10002 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 192.0.2.2
a=max-message-size:100000
a=sctp-port:5002
a=setup:passive
a=fingerprint:SHA-1 \
    5B:AD:67:B1:3E:82:AC:3B:90:02:B1:DF:12:5D:CA:6B:3F:E5:54:FA
a=tls-id:dcb3ae65cddef0532d42
a=dcmap:2 subprotocol="msrp";label="msrp"
a=dcsa:2 accept-types:message/cpim text/plain
a=dcsa:2 path:msrp://bob.example.com:10002/si438dsaodes;dc

Figure 2: Example 2

Figure 3 picks up right where Figure 2 left off ✨. The offerer drops the MSRP channel with stream id 2 and opens a brand new MSRP channel with stream id 4 🧚. The answerer accepts the whole offer, so the offerer closes the old MSRP channel, and both sides can start using the new one. Iconic glow-up πŸ‘‘.

m=application 10001 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 192.0.2.1
a=max-message-size:100000
a=sctp-port:5000
a=setup:actpass
a=fingerprint:SHA-1 \
    4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB
a=tls-id:abc3de65cddef001be82
a=dcmap:4 subprotocol="msrp";label="msrp"
a=dcsa:4 accept-types:message/cpim text/plain
a=dcsa:4 path:msrp://alice.example.com:10001/2s93i93idj;dc
m=application 10002 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 192.0.2.2
a=max-message-size:100000
a=sctp-port:5002
a=setup:passive
a=fingerprint:SHA-1 \
    5B:AD:67:B1:3E:82:AC:3B:90:02:B1:DF:12:5D:CA:6B:3F:E5:54:FA
a=tls-id:dcb3ae65cddef0532d42
a=dcmap:4 subprotocol="msrp";label="msrp"
a=dcsa:4 accept-types:message/cpim text/plain
a=dcsa:4 path:msrp://bob.example.com:10002/si438dsaodes;dc

Figure 3: Example 3


8. Security Considerations πŸ”’

Let's get serious for a sec 🫢. This document specifies new SDP attributes that are used to negotiate data channel parameters.

These parameters get negotiated as part of opening an SCTP channel over DTLS, as specified in [RFC8841]. Every subprotocol might come with its own security considerations, and those need to be written up as part of that subprotocol's definition. Other than that, this document doesn't add any security considerations on top of the ones in [RFC8841] πŸ’œ.

Error cases are a big deal 😭. Unknown parameter values, or breaking the odd/even rule in Section 6.1, MUST be handled by closing the corresponding data channel. No exceptions, bestie.

9. IANA Considerations πŸ“‹

9.1. Subprotocol Identifiers

New subprotocol identifiers get registered in the existing IANA "WebSocket Subprotocol Name Registry" table 🌈.

A line of text has been added under the title of that table, and it says:

"This table also includes subprotocol identifiers specified for usage within a WebRTC data channel."

This document (RFC 8864) has also been added to the "Reference" list for the registry.

This document doesn't assign any new values to that table, so nothing new is being added there πŸ“.

A subprotocol can be defined for data channel transport and for WebSocket transport at the same time. When that happens, the "Subprotocol Definition" and "Reference" cells in that subprotocol's row of the IANA "WebSocket Subprotocol Name Registry" table should contain two entries. One entry in each of those cells should point to the WebSocket-related subprotocol specification, and the other entry should point to the data-channel-related one ✨.

9.2. New SDP Attributes

9.2.1. dcmap

This document defines a brand new SDP media-level attribute, a=dcmap:, and here's how it's registered πŸ¦‹:

+==================================================================+
|                            "a=dcmap:"                            |
+=====================+============================================+
| Contact name        | IESG                                       |
+---------------------+--------------------------------------------+
| Contact email       | iesg@ietf.org                              |
+---------------------+--------------------------------------------+
| Attribute name      | dcmap                                      |
+---------------------+--------------------------------------------+
| Attribute syntax    | As per Section 5.1.1                       |
+---------------------+--------------------------------------------+
| Attribute semantics | As per Section 5.1.1                       |
+---------------------+--------------------------------------------+
| Usage level         | media                                      |
+---------------------+--------------------------------------------+
| Charset dependent   | No                                         |
+---------------------+--------------------------------------------+
| Purpose             | To define data-channel-specific parameters |
+---------------------+--------------------------------------------+
| Appropriate values  | As per Section 5.1.1                       |
+---------------------+--------------------------------------------+
| O/A procedures      | SDP offer/answer procedures as per         |
|                     | Section 6                                  |
+---------------------+--------------------------------------------+
| Mux category        | SPECIAL.  See Section 5.1.9                |
+---------------------+--------------------------------------------+
| Reference           | RFC 8864                                   |
+---------------------+--------------------------------------------+

Table 3: New "a=dcmap:" Attribute

9.2.2. dcsa

This document also defines a new SDP media-level attribute, a=dcsa: πŸŽ€. Check out the registration details:

   +=============================================================+
   |                          "a=dcsa:"                          |
   +=====================+=======================================+
   | Contact name        | IESG                                  |
   +---------------------+---------------------------------------+
   | Contact email       | iesg@ietf.org                         |
   +---------------------+---------------------------------------+
   | Attribute name      | dcsa                                  |
   +---------------------+---------------------------------------+
   | Attribute syntax    | As per Section 5.2.1                  |
   +---------------------+---------------------------------------+
   | Attribute semantics | As per Section 5.2.1                  |
   +---------------------+---------------------------------------+
   | Usage level         | media                                 |
   +---------------------+---------------------------------------+
   | Charset dependent   | No                                    |
   +---------------------+---------------------------------------+
   | Purpose             | To define attributes that are         |
   |                     | specific to data channel subprotocols |
   +---------------------+---------------------------------------+
   | Appropriate values  | As per Section 5.2.1                  |
   +---------------------+---------------------------------------+
   | O/A procedures      | SDP offer/answer procedures as per    |
   |                     | Section 6                             |
   +---------------------+---------------------------------------+
   | Mux category        | SPECIAL.  See Section 5.2.2           |
   +---------------------+---------------------------------------+
   | Reference           | RFC 8864                              |
   +---------------------+---------------------------------------+

Table 4: New "a=dcsa:" Attribute

9.3. Registering Attributes for Use with Data Channels

When a subprotocol gets defined for use over data channels with the SDP offer/answer mechanism, any SDP attributes that can be negotiated using a=dcsa: MUST be added to the IANA "attribute-name registry (formerly "att-field")", as specified in [RFC8866], Section 8.2.4 πŸ’…. This document also sets up new Usage Levels of the form "dcsa (foo)", where foo stands in for the subprotocol name. Documents that specify negotiation of particular subprotocols should register these Usage Levels.

IANA has updated the "attribute-name (formerly "att-field")" registry so that it points to this document 🌸.

10. References πŸ“š

The reference entries weren't included in the text I was given, so I can't rewrite them without guessing. Please send that part and I'll slay it in full ✨.

10.1. Normative References πŸ“š

These are the must-reads to actually understand this spec, bestie 🫢

10.2. Informative References πŸ¦‹

These ones are good background reading, but they're not required to implement this spec πŸ’œ


Appendix A. Generic Data Channel Negotiation Aspects when Not Using DCEP ✨

Okay so this appendix is basically a recap of how data channels work in general, plus the key stuff you should think about when you negotiate them out-of-band and skip DCEP πŸ’…

A WebRTC app makes a data channel by handing over a bunch of setup params: subprotocol, label, max number of retransmissions, max retransmission time, order of delivery, and priority πŸ’– The app also gets to pick whether it wants to use negotiation via DCEP [RFC8832] or negotiate data channels through the SDP offer/answer protocol.

Either way, the SDP offer the app generates follows [RFC8841]. Quick version: it has one "m=" line for the SCTP association that the data channels will run on top of 🌸

m=application 54111 UDP/DTLS/SCTP webrtc-datachannel
c=IN IP4 192.0.2.1
a=max-message-size:100000
a=sctp-port:5000
a=tls-id:abc3de65cddef001be82
a=setup:actpass
a=fingerprint:SHA-1 \
    4A:AD:B9:B1:3F:82:18:3B:54:02:12:DF:3E:5D:49:6B:19:E5:7C:AB
Note: A WebRTC application will only use the "m=" line format "webrtc-datachannel" and will not use other formats in the "m=" line for other protocols such as T.38 [T38]. [RFC8841] supports only one SCTP association to be established on top of a DTLS association.
Note: The above SDP media description does not contain any channel-specific information.

A.1. Stream Identifier Numbering πŸ”’

No matter what kind of negotiation is happening, the app creating a data channel can either (1) pass the stream identifier into the data channel stack so it gets assigned, or (2) let the data channel stack pick one of the unused ones πŸŽ€

Also, to avoid glare situations [RFC3264], each endpoint can own its own exclusive set of stream identifiers. If it does that, an endpoint can only create a data channel with a stream identifier it owns πŸ‘‘

Which endpoint owns which set is decided by convention or some other means.

Note: For data channels negotiated with DCEP, one endpoint owns by convention the even stream identifiers, whereas the other owns the odd stream identifiers, as defined in [RFC8832].
Note: For data channels negotiated via a protocol other than DCEP, no convention is defined by default.

A.2. Generic Data Channel Negotiation Not Using DCEP 🫧

A.2.1. Overview

Honestly, DCEP negotiation only covers the transport parameters of a data channel. It doesn't cover subprotocol-specific parameters at all πŸ™ˆ Non-DCEP negotiation can be defined to handle more than that, like parameters specific to the subprotocol running on a particular data channel.

The procedures below are shared by every non-DCEP method, whether it's in-band (done with proprietary means over a data channel that's already open) or out-of-band (using the SDP offer/answer mechanism or some other protocol tied to the signaling channel) πŸ¦‹

A.2.2. Opening a Data Channel

For non-DCEP negotiation, the endpoint application gets to fully control the stream identifier assignments. Those assignments still have to coexist with the ones the data channel stack controls for DCEP-negotiated channels (if there are any). It's the application's job to make sure stream identifiers are assigned consistently ✨

When the app asks for a new data channel through non-DCEP negotiation, the data channel stack creates it locally without sending any DATA_CHANNEL_OPEN messages in-band. Now, even if ICE (Interactive Connectivity Establishment), DTLS, and SCTP are all already done, the application can't send data on this channel until negotiation with the peer finishes 😭 The peer has to know about the channel and accept it first. Once the peer accepts the data channel offer, it can start sending data right away. That means the offerer might receive subprotocol messages before negotiation is complete, so the app should be ready to handle them πŸ’€

If the peer rejects the data channel part of the offer, it doesn't have to do anything, because the data channel was never created through the stack. The offerer, on the other hand, needs to close the data channel it opened, by calling the relevant data channel stack API procedures πŸ₯€

Also worth knowing: a data channel stack implementation might not give you any APIs to create and close data channels. Instead, the channels can just get used on the fly, by communicating through non-DCEP means or even through some local configuration or assumptions on both peers 🧚

Then the application negotiates the data channel properties and subprotocol properties with the peer's application, using a mechanism that isn't DCEP πŸ’…

The peer then symmetrically creates a data channel with these negotiated properties. This is the only way the peer's data channel stack knows which properties to apply when it transmits data on that channel. The data channel stack must allow data channel creation with any nonconflicting stream identifier, so both peers can create the data channel with the same stream identifier πŸ‘‘

A.2.3. Closing a Data Channel

When the app asks to close a data channel that was negotiated without DCEP, the data channel stack always does an SCTP SSN Reset for that channel πŸ”„

Depending on the non-DCEP negotiation method and the subprotocol tied to the data channel, closing the channel might also be signaled to the peer through SDP offer/answer negotiation 🌈


Acknowledgements 🫢

The authors want to give a shoutout to Salvatore Loreto, Gonzalo Camarillo, Peter Dunkley, and Gavin Llewellyn for the ideas they borrowed from their draft documents πŸ’– They also want to thank Flemming Andreasen, Christian Groves, Gunnar HellstrΓΆm, Paul Kyzivat, Jonathan Lennox, Uwe Rauschenbach, and Roman Shpount for their invaluable comments 🌸

Special thanks to Christer Holmberg for helping finish the document and cleaning up Section 6! πŸŽ€βœ¨

Contributors πŸ’œ

Juergen Stoetzer-Bradler made significant contributions to this document and should be considered a coauthor πŸ¦‹

Authors' Addresses 🌷

Keith Drage Unaffiliated Email: drageke@ntlworld.com

Maridi R. Makaraju (Raju) Unaffiliated Email: mmraju@gmail.com

Richard Ejzak Unaffiliated Email: richard.ejzak@gmail.com

Jerome Marcon Unaffiliated Email: jeromee.marcon@free.fr

Roni Even (editor) Email: ron.even.tlv@gmail.com

πŸ“¦ where this page comes from