NEW 278672
Regression: Creating peer connection fails on Safari 17.5+ with IPv6-only network
https://bugs.webkit.org/show_bug.cgi?id=278672
Summary Regression: Creating peer connection fails on Safari 17.5+ with IPv6-only net...
Virginia Farley
Reported 2024-08-26 12:29:19 PDT
Network: T-Mobile Safari version: 17.5+ Creating a peer connection fails on Safari 17.5+ when using the carrier T-mobile, an IPv6-only network. Repro steps: • Navigate to https://webrtc.github.io/samples/src/content/peerconnection/pc1/ • Click “Start” • Click “Call” • Observe black screen in right box indicating peer connection could not be established Repro on Safari 17.5 Repro on Safari 17.6 No repro Safari 16 Note that this could be related to bug 230552: https://bugs.webkit.org/show_bug.cgi?id=230552
Attachments
ice binding test (2.54 KB, text/html)
2024-08-26 21:07 PDT, Byungseon(Sun) Shin
no flags
ice binding test with gfn stun (2.55 KB, text/html)
2024-08-26 21:13 PDT, Byungseon(Sun) Shin
no flags
ice binding test (4.00 KB, text/html)
2024-08-26 22:13 PDT, Byungseon(Sun) Shin
no flags
ice binding test with gfn stun (4.01 KB, text/html)
2024-08-26 22:16 PDT, Byungseon(Sun) Shin
no flags
test result on iOS 18.0 (3.59 KB, text/plain)
2024-08-26 23:06 PDT, Byungseon(Sun) Shin
no flags
test result on macOS 14.6.1 (1.11 KB, text/plain)
2024-08-26 23:07 PDT, Byungseon(Sun) Shin
no flags
Radar WebKit Bug Importer
Comment 1 2024-08-26 13:42:07 PDT
Byungseon(Sun) Shin
Comment 2 2024-08-26 21:07:02 PDT
Created attachment 472308 [details] ice binding test
Byungseon(Sun) Shin
Comment 3 2024-08-26 21:13:18 PDT
Created attachment 472309 [details] ice binding test with gfn stun
Byungseon(Sun) Shin
Comment 4 2024-08-26 22:11:32 PDT
Comment on attachment 472308 [details] ice binding test <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ICE Connection Test</title> </head> <body> <h1>ICE Connection Test</h1> <video id="localVideo" playsinline autoplay muted></video> <video id="remoteVideo" playsinline autoplay></video> <p> <button id="startButton">Start ICE Test</button> <pre id="output"></pre> <script> const startButton = document.getElementById('startButton'); const output = document.getElementById('output'); const localVideo = document.getElementById('localVideo'); const remoteVideo = document.getElementById('remoteVideo'); startButton.addEventListener('click', startTest); async function startTest() { const configuration = { iceServers: [ { urls: 'stun:stun.l.google.com:19302' } // Example STUN server ] }; const localPeer = new RTCPeerConnection(configuration); const remotePeer = new RTCPeerConnection(configuration); localPeer.onicecandidate = (event) => { if (event.candidate) { remotePeer.addIceCandidate(event.candidate); log(`Local ICE candidate: ${event.candidate.candidate}`); } }; remotePeer.onicecandidate = (event) => { if (event.candidate) { localPeer.addIceCandidate(event.candidate); log(`Remote ICE candidate: ${event.candidate.candidate}`); } }; localPeer.oniceconnectionstatechange = () => { log(`Local ICE connection state: ${localPeer.iceConnectionState}`); }; remotePeer.oniceconnectionstatechange = () => { log(`Remote ICE connection state: ${remotePeer.iceConnectionState}`); }; remotePeer.addEventListener('track', (event) => { gotRemoteStream(event); }); try { let localStream; //localPeer.createDataChannel('testChannel'); const offerOptions = { offerToReceiveAudio: 1, offerToReceiveVideo: 1 }; const stream = await navigator.mediaDevices.getUserMedia({audio: true, video: true}); localVideo.srcObject = stream; localStream = stream; const videoTracks = localStream.getVideoTracks(); const audioTracks = localStream.getAudioTracks(); if (videoTracks.length > 0) { console.log(`Using video device: ${videoTracks[0].label}`); } if (audioTracks.length > 0) { console.log(`Using audio device: ${audioTracks[0].label}`); } localStream.getTracks().forEach(track => localPeer.addTrack(track, localStream)); const offer = await localPeer.createOffer(); await localPeer.setLocalDescription(offer); log('Local peer created and set local offer'); await remotePeer.setRemoteDescription(offer); log('Remote peer set remote offer'); const answer = await remotePeer.createAnswer(); await remotePeer.setLocalDescription(answer); log('Remote peer created and set local answer'); await localPeer.setRemoteDescription(answer); log('Local peer set remote answer'); } catch (error) { log(`Error: ${error}`); } } function gotRemoteStream(e) { if (remoteVideo.srcObject !== e.streams[0]) { remoteVideo.srcObject = e.streams[0]; console.log('remote peer received remote stream'); } } function log(message) { output.textContent += `${message}\n`; } </script> </body> </html>
Byungseon(Sun) Shin
Comment 5 2024-08-26 22:13:11 PDT
Comment on attachment 472308 [details] ice binding test <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ICE Connection Test</title> </head> <body> <h1>ICE Connection Test</h1> <video id="localVideo" playsinline autoplay muted></video> <video id="remoteVideo" playsinline autoplay></video> <p> <button id="startButton">Start ICE Test</button> <pre id="output"></pre> <script> const startButton = document.getElementById('startButton'); const output = document.getElementById('output'); const localVideo = document.getElementById('localVideo'); const remoteVideo = document.getElementById('remoteVideo'); startButton.addEventListener('click', startTest); async function startTest() { const configuration = { iceServers: [ { urls: 'stun:stun.l.google.com:19302' } // Example STUN server ] }; const localPeer = new RTCPeerConnection(configuration); const remotePeer = new RTCPeerConnection(configuration); localPeer.onicecandidate = (event) => { if (event.candidate) { remotePeer.addIceCandidate(event.candidate); log(`Local ICE candidate: ${event.candidate.candidate}`); } }; remotePeer.onicecandidate = (event) => { if (event.candidate) { localPeer.addIceCandidate(event.candidate); log(`Remote ICE candidate: ${event.candidate.candidate}`); } }; localPeer.oniceconnectionstatechange = () => { log(`Local ICE connection state: ${localPeer.iceConnectionState}`); }; remotePeer.oniceconnectionstatechange = () => { log(`Remote ICE connection state: ${remotePeer.iceConnectionState}`); }; remotePeer.addEventListener('track', (event) => { gotRemoteStream(event); }); try { let localStream; //localPeer.createDataChannel('testChannel'); const offerOptions = { offerToReceiveAudio: 1, offerToReceiveVideo: 1 }; const stream = await navigator.mediaDevices.getUserMedia({audio: true, video: true}); localVideo.srcObject = stream; localStream = stream; const videoTracks = localStream.getVideoTracks(); const audioTracks = localStream.getAudioTracks(); if (videoTracks.length > 0) { console.log(`Using video device: ${videoTracks[0].label}`); } if (audioTracks.length > 0) { console.log(`Using audio device: ${audioTracks[0].label}`); } localStream.getTracks().forEach(track => localPeer.addTrack(track, localStream)); const offer = await localPeer.createOffer(); await localPeer.setLocalDescription(offer); log('Local peer created and set local offer'); await remotePeer.setRemoteDescription(offer); log('Remote peer set remote offer'); const answer = await remotePeer.createAnswer(); await remotePeer.setLocalDescription(answer); log('Remote peer created and set local answer'); await localPeer.setRemoteDescription(answer); log('Local peer set remote answer'); } catch (error) { log(`Error: ${error}`); } } function gotRemoteStream(e) { if (remoteVideo.srcObject !== e.streams[0]) { remoteVideo.srcObject = e.streams[0]; console.log('remote peer received remote stream'); } } function log(message) { output.textContent += `${message}\n`; } </script> </body> </html>
Byungseon(Sun) Shin
Comment 6 2024-08-26 22:13:39 PDT
Created attachment 472310 [details] ice binding test
Byungseon(Sun) Shin
Comment 7 2024-08-26 22:16:24 PDT
Created attachment 472311 [details] ice binding test with gfn stun
Byungseon(Sun) Shin
Comment 8 2024-08-26 23:06:37 PDT
Created attachment 472312 [details] test result on iOS 18.0
Byungseon(Sun) Shin
Comment 9 2024-08-26 23:07:07 PDT
Created attachment 472313 [details] test result on macOS 14.6.1
Byungseon(Sun) Shin
Comment 10 2024-08-26 23:09:53 PDT
(In reply to Byungseon(Sun) Shin from comment #5) > Comment on attachment 472308 [details] > ice binding test > > <!DOCTYPE html> > <html lang="en"> > <head> > <meta charset="UTF-8"> > <meta name="viewport" content="width=device-width, initial-scale=1.0"> > <title>ICE Connection Test</title> > </head> > <body> > <h1>ICE Connection Test</h1> > <video id="localVideo" playsinline autoplay muted></video> > <video id="remoteVideo" playsinline autoplay></video> > > <p> > <button id="startButton">Start ICE Test</button> > <pre id="output"></pre> > > <script> > const startButton = document.getElementById('startButton'); > const output = document.getElementById('output'); > const localVideo = document.getElementById('localVideo'); > const remoteVideo = document.getElementById('remoteVideo'); > > startButton.addEventListener('click', startTest); > > async function startTest() { > const configuration = { > iceServers: [ > { urls: 'stun:stun.l.google.com:19302' } // Example STUN server > ] > }; > > const localPeer = new RTCPeerConnection(configuration); > const remotePeer = new RTCPeerConnection(configuration); > > localPeer.onicecandidate = (event) => { > if (event.candidate) { > remotePeer.addIceCandidate(event.candidate); > log(`Local ICE candidate: ${event.candidate.candidate}`); > } > }; > > remotePeer.onicecandidate = (event) => { > if (event.candidate) { > localPeer.addIceCandidate(event.candidate); > log(`Remote ICE candidate: > ${event.candidate.candidate}`); > } > }; > > localPeer.oniceconnectionstatechange = () => { > log(`Local ICE connection state: > ${localPeer.iceConnectionState}`); > }; > > remotePeer.oniceconnectionstatechange = () => { > log(`Remote ICE connection state: > ${remotePeer.iceConnectionState}`); > }; > > remotePeer.addEventListener('track', (event) => { > gotRemoteStream(event); > }); > > try { > let localStream; > //localPeer.createDataChannel('testChannel'); > const offerOptions = { > offerToReceiveAudio: 1, > offerToReceiveVideo: 1 > }; > > const stream = await > navigator.mediaDevices.getUserMedia({audio: true, video: true}); > localVideo.srcObject = stream; > localStream = stream; > > const videoTracks = localStream.getVideoTracks(); > const audioTracks = localStream.getAudioTracks(); > if (videoTracks.length > 0) { > console.log(`Using video device: ${videoTracks[0].label}`); > } > if (audioTracks.length > 0) { > console.log(`Using audio device: ${audioTracks[0].label}`); > } > localStream.getTracks().forEach(track => > localPeer.addTrack(track, localStream)); > > const offer = await localPeer.createOffer(); > await localPeer.setLocalDescription(offer); > log('Local peer created and set local offer'); > > await remotePeer.setRemoteDescription(offer); > log('Remote peer set remote offer'); > > const answer = await remotePeer.createAnswer(); > await remotePeer.setLocalDescription(answer); > log('Remote peer created and set local answer'); > > await localPeer.setRemoteDescription(answer); > log('Local peer set remote answer'); > } catch (error) { > log(`Error: ${error}`); > } > } > > function gotRemoteStream(e) { > if (remoteVideo.srcObject !== e.streams[0]) { > remoteVideo.srcObject = e.streams[0]; > console.log('remote peer received remote stream'); > } > } > > function log(message) { > output.textContent += `${message}\n`; > } > </script> > </body> > </html>
Byungseon(Sun) Shin
Comment 11 2024-08-26 23:14:06 PDT
Attached simplified test for ice binding and test results on iOS and macOS. We see the connection failure on iOS but not macOS.
Note You need to log in before you can comment on or make changes to this bug.