Skip to content

Conversation

@fippo
Copy link
Contributor

@fippo fippo commented Sep 17, 2025

extending JSEP rules to negotiate datachannels before createDataChannel and negotiate them as the first m-line in the SDP.

const pc = new RTCPeerConnection({alwaysNegotiateDataChannels: true});
pc.addTransceiver('audio');
await offer = pc.createOffer();
// assert that the first m= line is m=application

JSEP issue: rtcweb-wg/jsep#1039

Fixes #241


Preview | Diff

@fippo fippo force-pushed the always-negotiate-datachannels branch from 1fc5bf4 to 9f4960d Compare September 17, 2025 07:48
</section>
<section id="always-negotiating-datachannels-interface-extensions">
<h3>
JSEP modifications
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@docfaraday what can we expect wrt rtcweb-wg/jsep#1039 here? What's next steps?

Comment on lines +1540 to +1546
<p>
In the algorithms for generating initial offers in [[RTCWEB-JSEP]] section 5.2.1,
replace
"Lastly, if a data channel has been created, a m= section MUST be generated for data"
with
"Lastly, if a data channel has been created and no m=section has been generated for data, a m= section MUST be generated for data".
</p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we add a note somewhere to clarify this changes the m-line order? As presented, this effect and its benefit wrt BUNDLE seems important to include as a reason why someone may want to use this API

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added, don't forget to squash (or I can squash)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we're going to note the "bundle-tag rejection trap avoidance" benefit, we might also want to mention that this benefit only applies with bundlePolicy=="max-bundle" (for "max-compat" the problem does not exist in the first place, and for "balanced" it won't help).

Copy link
Contributor Author

@fippo fippo Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

for balanced it would help since (surprise!) if you reject the bundle-tagged m-line you can still not move to the next per https://datatracker.ietf.org/doc/html/rfc8843#section-7.3.3 ?

(and it looks like Firefox and Chrome disagree what max-compat means... Firefox does not bundle, Chrome bundles)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure I understand. If it is in a group all by itself, (which is what "balanced" says to do, sort of, it's worded poorly), rejecting it destroys that transport, but since nothing else is in there it's fine. On the other side, if you have multiple m=audio, those will share a transport, but rejecting that bundle tag still messes things up; it's not the first m-section overall, but it still can destroy a transport and bring down everything bundled with it.

Copy link
Contributor Author

@fippo fippo Sep 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://jsfiddle.net/fippo/5y6ag2Lw/1/-- I don't see separate bundle groups with balanced? (nor do I see the second audio m-line marked as bundle-only)

Either way, do we agree this is cheap and solves a (max-bundle) headache without overpromising?

extending JSEP rules to negotiate datachannels before createDataChannel
and negotiate them as the first m-line in the SDP.

```
const pc = new RTCPeerConnection({alwaysNegotiateDataChannels: true});
pc.addTransceiver('audio');
await offer = pc.createOffer();
// assert that the first m= line is m=application
```

JSEP issue: rtcweb-wg/jsep#1039

Fixes w3c#241
@fippo fippo force-pushed the always-negotiate-datachannels branch from 9f4960d to bda5b11 Compare September 25, 2025 15:15
@docfaraday
Copy link

This is strikingly similar to the offerToReceiveX options on createOffer. Hypothetically, if we followed those as an example, we would get something pretty similar to what this proposal does. I think we would need to do some extra work to ensure that the m=application section was up top though. One potential benefit would be to allow this to be used after the initial negotiation; there's no way to ensure that this m=application is up top, but it still would allow the creation of one without forcing the offerer to create a channel. Something to consider.

@fippo
Copy link
Contributor Author

fippo commented Sep 25, 2025

offerTo* is dubbed "legacy" (ignoring that a significant percentage of Chrome usage does this) and (more importantly) does not work with setLocalDescription()

@fippo
Copy link
Contributor Author

fippo commented Sep 29, 2025

https://w3c.github.io/webrtc-pc/#webidl-862292147 also needs a slight tweak, changing

  1. If channel is the first RTCDataChannel created on connection and no m=section exists for data, update the negotiation-needed flag for connection.

I think the condition for that can be expressed using [[SctpTransport]] not being null.

Expected behavior:
Creating with alwaysNegotiateDataChannels should not fire ONN immediately.
Creating with alwaysNegotiateDataChannels and creating a data channel should fire ONN.
Creating with alwaysNegotiateDataChannels and adding a audio transceiver should result in two m-lines but fire ONN as result of adding audio. Calling createDataChannel way after that should not fire ONN.

Drive-by:

  • Step 19 should check if transport is not null before checkings its connected state?
  • Step 20 should check if this is the first datachannel on the transport, not the connection or alternatively if a transport needs to be created? SCTP getting rejected and recreated might be rare but...

@youennf
Copy link
Contributor

youennf commented Oct 9, 2025

@fippo, are you planning to update the PR according your latest comment?

@fippo
Copy link
Contributor Author

fippo commented Oct 9, 2025

@youennf this requires a PR against webrtc-pc

@alvestrand
Copy link
Contributor

we have multiple places in webrtc-extensions that contain what's effectively instructions to edit webrtc-pc when it gets merged.

@fippo
Copy link
Contributor Author

fippo commented Oct 10, 2025

Done. [[SctpTransport]] is missing an export in the dfn on line 1311. Should I file issues for the drive-by questions?

fippo added a commit to fippo/aiortc that referenced this pull request Oct 13, 2025
which always negotiates datachannels and puts them first in the SDP.
Spec:
  w3c/webrtc-extensions#242
fippo added a commit to fippo/aiortc that referenced this pull request Oct 13, 2025
which always negotiates datachannels and puts them first in the SDP.
Spec:
  w3c/webrtc-extensions#242
fippo added a commit to fippo/webrtc-pc that referenced this pull request Oct 16, 2025
@fippo fippo force-pushed the always-negotiate-datachannels branch from d812995 to 7f5bdb5 Compare October 19, 2025 09:29
@alvestrand alvestrand merged commit 7c1351b into w3c:main Oct 21, 2025
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Extend RTCConfiguration with a boolean to always negotiate datachannels

6 participants