@@ -79,14 +79,47 @@ function collectMessages(channel, count, timeout = 10000) {
7979 } ) ;
8080}
8181
82+ async function addIceCandidateBestEffort ( peerConnection , candidate ) {
83+ try {
84+ await peerConnection . addIceCandidate ( candidate ) ;
85+ } catch {
86+ // ICE restart can leave older gathered candidates in flight. Unit helpers
87+ // mirror browser-style candidate exchange and keep those races non-fatal.
88+ }
89+ }
90+
91+ function exchangeIceCandidates ( offerer , answerer ) {
92+ offerer . addEventListener ( "icecandidate" , ( event ) => {
93+ if ( event . candidate && answerer . signalingState !== "closed" ) {
94+ addIceCandidateBestEffort ( answerer , event . candidate ) ;
95+ }
96+ } ) ;
97+
98+ answerer . addEventListener ( "icecandidate" , ( event ) => {
99+ if ( event . candidate && offerer . signalingState !== "closed" ) {
100+ addIceCandidateBestEffort ( offerer , event . candidate ) ;
101+ }
102+ } ) ;
103+ }
104+
105+ async function exchangeSessionDescriptions ( offerer , answerer ) {
106+ const offer = await offerer . createOffer ( ) ;
107+ await offerer . setLocalDescription ( offer ) ;
108+ await answerer . setRemoteDescription ( offerer . localDescription ) ;
109+
110+ const answer = await answerer . createAnswer ( ) ;
111+ await answerer . setLocalDescription ( answer ) ;
112+ await offerer . setRemoteDescription ( answerer . localDescription ) ;
113+ }
114+
82115async function exchangeOfferAnswer ( offerer , answerer ) {
83116 const offererCandidates = [ ] ;
84117 const answererCandidates = [ ] ;
85118
86119 offerer . onicecandidate = ( event ) => {
87120 if ( ! event . candidate ) return ;
88121 if ( answerer . remoteDescription ) {
89- answerer . addIceCandidate ( event . candidate ) ;
122+ addIceCandidateBestEffort ( answerer , event . candidate ) ;
90123 } else {
91124 offererCandidates . push ( event . candidate ) ;
92125 }
@@ -95,7 +128,7 @@ async function exchangeOfferAnswer(offerer, answerer) {
95128 answerer . onicecandidate = ( event ) => {
96129 if ( ! event . candidate ) return ;
97130 if ( offerer . remoteDescription ) {
98- offerer . addIceCandidate ( event . candidate ) ;
131+ addIceCandidateBestEffort ( offerer , event . candidate ) ;
99132 } else {
100133 answererCandidates . push ( event . candidate ) ;
101134 }
@@ -104,12 +137,16 @@ async function exchangeOfferAnswer(offerer, answerer) {
104137 const offer = await offerer . createOffer ( ) ;
105138 await offerer . setLocalDescription ( offer ) ;
106139 await answerer . setRemoteDescription ( offerer . localDescription ) ;
107- for ( const candidate of offererCandidates . splice ( 0 ) ) await answerer . addIceCandidate ( candidate ) ;
140+ for ( const candidate of offererCandidates . splice ( 0 ) ) {
141+ await addIceCandidateBestEffort ( answerer , candidate ) ;
142+ }
108143
109144 const answer = await answerer . createAnswer ( ) ;
110145 await answerer . setLocalDescription ( answer ) ;
111146 await offerer . setRemoteDescription ( answerer . localDescription ) ;
112- for ( const candidate of answererCandidates . splice ( 0 ) ) await offerer . addIceCandidate ( candidate ) ;
147+ for ( const candidate of answererCandidates . splice ( 0 ) ) {
148+ await addIceCandidateBestEffort ( offerer , candidate ) ;
149+ }
113150}
114151
115152function closeAll ( ...peers ) {
@@ -293,14 +330,17 @@ test("restartIce renegotiates without closing data channels", async (t) => {
293330 t . after ( ( ) => closeAllAndWait ( offerer , answerer ) ) ;
294331 const local = offerer . createDataChannel ( "restart" ) ;
295332 const remotePromise = waitFor ( answerer , "datachannel" ) ;
333+ exchangeIceCandidates ( offerer , answerer ) ;
296334
297- await exchangeOfferAnswer ( offerer , answerer ) ;
335+ await exchangeSessionDescriptions ( offerer , answerer ) ;
298336 const remote = ( await remotePromise ) . channel ;
299337 await waitForOpen ( local ) ;
300338 await waitForOpen ( remote ) ;
301339
302340 offerer . restartIce ( ) ;
303- await exchangeOfferAnswer ( offerer , answerer ) ;
341+ await exchangeSessionDescriptions ( offerer , answerer ) ;
342+ await waitForOpen ( local ) ;
343+ await waitForOpen ( remote ) ;
304344
305345 const messagePromise = waitFor ( remote , "message" ) ;
306346 local . send ( "after-restart" ) ;
0 commit comments