commit 3a389798d21f3fd713f071f51c96e763de35f461
parent 3a0afe444ec77d1554950f12a9e0694054c8c3c2
Author: Harald Alvestrand <hta@chromium.org>
Date: Thu, 25 Dec 2025 20:58:17 +0000
Bug 2007657 [wpt PR 56914] - Wait for SCTP to be connected before checking ID assignment, a=testonly
Automatic update from web-platform-tests
Wait for SCTP to be connected before checking ID assignment
This checks for conformance with a 2019 spec update:
https://github.com/w3c/webrtc-pc/pull/2222
Bug: webrtc:470478209
Change-Id: I00467cd16bc31b3c6eed7d34d9d3ab798259a68f
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/7280971
Commit-Queue: Tomas Gunnarsson <tommi@chromium.org>
Auto-Submit: Harald Alvestrand <hta@chromium.org>
Reviewed-by: Tomas Gunnarsson <tommi@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1562457}
--
wpt-commits: 48faf0f2b72d03405a96e3239670e0b34fbd1b0c
wpt-pr: 56914
Diffstat:
2 files changed, 34 insertions(+), 43 deletions(-)
diff --git a/testing/web-platform/tests/webrtc/RTCDataChannel-id.html b/testing/web-platform/tests/webrtc/RTCDataChannel-id.html
@@ -17,34 +17,37 @@
const nStreams = 65535;
/*
- 6.1.
- 21. If the [[DataChannelId]] slot is null (due to no ID being passed into
- createDataChannel, or [[Negotiated]] being false), and the DTLS role of the SCTP
- transport has already been negotiated, then initialize [[DataChannelId]] to a value
- generated by the user agent, according to [RTCWEB-DATA-PROTOCOL] [...]
+ The ID is assigned after SCTP connects, according to section 6.1.1.3
+ (RTCSctpTransport Connected procedure)
*/
promise_test(async (t) => {
- const pc = new RTCPeerConnection;
- t.add_cleanup(() => pc.close());
+ const pc1 = new RTCPeerConnection;
+ t.add_cleanup(() => pc1.close());
+ const pc2 = new RTCPeerConnection;
+ t.add_cleanup(() => pc2.close());
+ exchangeIceCandidates(pc1, pc2);
- const dc1 = pc.createDataChannel('client_ids');
+ const dc1 = pc1.createDataChannel('client_ids');
const ids = new UniqueSet();
- const offer = await pc.createOffer();
- await pc.setLocalDescription(offer);
- // Turn our own offer SDP into valid answer SDP by setting the DTLS role to
- // "active".
- const answer = {
- type: 'answer',
- sdp: pc.localDescription.sdp.replace('actpass', 'active')
- };
- await pc.setRemoteDescription(answer);
+ const initial_offer = await pc1.createOffer();
+ // Ensure that pc1 is "passive" and pc2 is "active"
+ const offer = {
+ type: 'offer',
+ sdp: initial_offer.sdp.replace('actpass', 'passive'),
+ }
+ await Promise.all([pc1.setLocalDescription(initial_offer),
+ pc2.setRemoteDescription(offer)]);
+ const answer = await pc2.createAnswer();
+ await Promise.all([pc1.setRemoteDescription(answer),
+ pc2.setLocalDescription(answer)]);
+ await waitForState(pc1.sctp, 'connected');
// Since the remote description had an 'active' DTLS role, we're the server
// and should use odd data channel IDs, according to rtcweb-data-channel.
assert_equals(dc1.id % 2, 1,
`Channel created by the DTLS server role must be odd (was ${dc1.id})`);
- const dc2 = pc.createDataChannel('another');
+ const dc2 = pc1.createDataChannel('another');
assert_equals(dc2.id % 2, 1,
`Channel created by the DTLS server role must be odd (was ${dc2.id})`);
@@ -171,7 +174,7 @@ promise_test(async (t) => {
return answer;
},
});
-
+ await waitForState(pc1.sctp, 'connected');
for (const dc of dcs) {
assert_equals(dc.id % 2, 1,
`Channel created by the DTLS server role must be odd (was ${dc.id})`);
diff --git a/testing/web-platform/tests/webrtc/RTCPeerConnection-createDataChannel.html b/testing/web-platform/tests/webrtc/RTCPeerConnection-createDataChannel.html
@@ -507,31 +507,15 @@ test(t => {
}, 'createDataChannel with negotiated true and id not defined should throw TypeError');
/*
- 4.4.1.6. Set the RTCSessionSessionDescription
- 2.2.6. If description is of type "answer" or "pranswer", then run the
- following steps:
- 3. If description negotiates the DTLS role of the SCTP transport, and there is an
- RTCDataChannel with a null id, then generate an ID according to
- [RTCWEB-DATA-PROTOCOL]. [...]
-
- 6.1. createDataChannel
- 21. If the [[DataChannelId]] slot is null (due to no ID being passed into
- createDataChannel, or [[Negotiated]] being false), and the DTLS role of the SCTP
- transport has already been negotiated, then initialize [[DataChannelId]] to a value
- generated by the user agent, according to [RTCWEB-DATA-PROTOCOL], and skip
- to the next step. If no available ID could be generated, or if the value of the
- [[DataChannelId]] slot is being used by an existing RTCDataChannel, throw an
- OperationError exception.
-
- Note
- If the [[DataChannelId]] slot is null after this step, it will be populated once
- the DTLS role is determined during the process of setting an RTCSessionDescription.
+ The ID is assigned after SCTP connects, according to section 6.1.1.3 (RTCSctpTransport
+ Connected procedure).
*/
promise_test(async t => {
const pc1 = new RTCPeerConnection();
const pc2 = new RTCPeerConnection();
t.add_cleanup(() => pc1.close());
t.add_cleanup(() => pc2.close());
+ exchangeIceCandidates(pc1, pc2);
const negotiatedDc = pc1.createDataChannel('negotiated-channel', {
negotiated: true,
@@ -545,7 +529,9 @@ promise_test(async t => {
const offer = await pc1.createOffer();
await Promise.all([pc1.setLocalDescription(offer), pc2.setRemoteDescription(offer)]);
const answer = await pc2.createAnswer();
- await pc1.setRemoteDescription(answer);
+ await Promise.all([pc1.setRemoteDescription(answer), pc2.setLocalDescription(answer)]);
+ await waitForState(pc1.sctp, 'connected');
+ await waitForState(pc2.sctp, 'connected');
assert_not_equals(dc1.id, null,
'Expect dc1.id to be assigned after remote description has been set');
@@ -578,7 +564,7 @@ promise_test(async t => {
assert_equals(negotiatedDc.id, 42,
'Expect negotiatedDc.id to be 42 after remote description has been set');
-}, 'Channels created (after setRemoteDescription) should have id assigned');
+}, 'Channels created (after SCTP connected) should have id assigned');
test(t => {
const pc = new RTCPeerConnection();
@@ -648,16 +634,18 @@ promise_test(async t => {
const pc2 = new RTCPeerConnection();
t.add_cleanup(() => pc1.close());
t.add_cleanup(() => pc2.close());
+ exchangeIceCandidates(pc1, pc2);
const dc1 = pc1.createDataChannel('channel-1');
const offer = await pc1.createOffer();
await Promise.all([pc1.setLocalDescription(offer), pc2.setRemoteDescription(offer)]);
const answer = await pc2.createAnswer();
- await pc1.setRemoteDescription(answer);
-
+ await Promise.all([pc1.setRemoteDescription(answer), pc2.setLocalDescription(answer)]);
+ await waitForState(pc1.sctp, 'connected');
+ await waitForState(pc2.sctp, 'connected');
assert_not_equals(dc1.id, null,
- 'Expect dc1.id to be assigned after remote description has been set');
+ 'Expect dc1.id to be assigned after SCTP has connected');
assert_throws_dom('OperationError', () =>
pc1.createDataChannel('channel-2', {