WebRTC STUN/TURN allocate request timed out

Viewed 3147

I'm testing the WebRTC video calling API. For signaling Firestore is being used. Offer is being created in caller web browser A and sent to callee B, which then returns the answer to A. Then icecandidates are being shared where I'm facing the problem described below -

  1. Chrome not showing any error in console. But when I head over to chrome://webrtc-internals/, I see multiple icecandidateerror error logs -

// replaced real IP with x.x.x.x
// following errors from 
icecandidateerror{
  url: turn:numb.viagenie.ca:3478?transport=udp
  address: x.x.x.x
  port: 55791
  host_candidate: x.x.x.x:55791
  error_text: TURN allocate request timed out.
  error_code: 701
}
icecandidateerror{
  url: stun:stun2.l.google.com:19302
  address: x.x.x.x
  port: 55791
  host_candidate: x.x.x.x:55791
  error_text: STUN allocate request timed out.
  error_code: 701
}
.....total of 8 such errors

// following logs are from webrtc-internals_dump.txt
{
     "time": "7/28/2020, 9:14:57 PM",
     "type": "icecandidateerror",
     "value": "url: turn:numb.viagenie.ca:3478?transport=udp\naddress: x.x.x.x\nport: 55787\nhost_candidate: x.x.x.x:55787\nerror_text: TURN allocate request timed out.\nerror_code: 701"
    },
    {
     "time": "7/28/2020, 9:14:57 PM",
     "type": "icecandidateerror",
     "value": "url: turn:numb.viagenie.ca:3478?transport=udp\naddress: x.x.x.x\nport: 55791\nhost_candidate: x.x.x.x:55791\nerror_text: TURN allocate request timed out.\nerror_code: 701"
    },
    {
     "time": "7/28/2020, 9:14:57 PM",
     "type": "icecandidateerror",
     "value": "url: stun:numb.viagenie.ca:3478\naddress: x.x.x.x\nport: 55787\nhost_candidate: x.x.x.x:55787\nerror_text: STUN allocate request timed out.\nerror_code: 701"
    },
    {
     "time": "7/28/2020, 9:14:57 PM",
     "type": "icecandidateerror",
     "value": "url: stun:numb.viagenie.ca:3478\naddress: x.x.x.x\nport: 55791\nhost_candidate: x.x.x.x:55791\nerror_text: STUN allocate request timed out.\nerror_code: 701"
    },
    {
     "time": "7/28/2020, 9:14:57 PM",
     "type": "icecandidateerror",
     "value": "url: stun:stun1.l.google.com:19302\naddress: x.x.x.x\nport: 55787\nhost_candidate: x.x.x.x:55787\nerror_text: STUN allocate request timed out.\nerror_code: 701"
    },
    {
     "time": "7/28/2020, 9:14:57 PM",
     "type": "icecandidateerror",
     "value": "url: stun:stun1.l.google.com:19302\naddress: x.x.x.x\nport: 55791\nhost_candidate: x.x.x.x:55791\nerror_text: STUN allocate request timed out.\nerror_code: 701"
    },
    {
     "time": "7/28/2020, 9:14:57 PM",
     "type": "icecandidateerror",
     "value": "url: stun:stun2.l.google.com:19302\naddress: x.x.x.x\nport: 55787\nhost_candidate: x.x.x.x:55787\nerror_text: STUN allocate request timed out.\nerror_code: 701"
    },
    {
     "time": "7/28/2020, 9:14:57 PM",
     "type": "icecandidateerror",
     "value": "url: stun:stun2.l.google.com:19302\naddress: x.x.x.x\nport: 55791\nhost_candidate: x.x.x.x:55791\nerror_text: STUN allocate request timed out.\nerror_code: 701"
    },

Here one thing to notice is that the IP address x.x.x.x is IP address of my ethernet but I'm connected to internet via wifi. Is this be the actual problem?

enter image description here

  1. Firefox console error -

    WebRTC: ICE failed, see about:webrtc for more details
    

Code Sample:

// TODO: Replace the following with your app's Firebase project configuration
    var firebaseConfig = {
        apiKey: "xx-xx",
        authDomain: "xx",
        databaseURL: "https://txx.firebaseio.com",
        projectId: "xx-xx-xx",
        storageBucket: "xx",
        messagingSenderId: "xx",
        appId: "xx",
        measurementId: "xx"
    };

    const servers = {
        iceServers: [
            {
                urls: [
                    'stun:stun1.l.google.com:19302',
                    'stun:stun2.l.google.com:19302'
                ],
            },
            {   'urls': 'turn:numb.viagenie.ca','credential': 'xzx','username': 'xx'}
        ],
        iceCandidatePoolSize: 10,
    };
    // Initialize Firebase
    var app = firebase.initializeApp(firebaseConfig);
    var localStream;
    var remoteStream;
    var peerConnection;

    var localVideo = document.querySelector('#localVideo')
    var remoteVideo = document.querySelector('#remoteVideo')

    const db = firebase.firestore();
    const userID = Math.round(Math.random()*1000)
    const collection = db.collection('rooms')
    var roomRef = null
    var roomID = null

    var pc = new RTCPeerConnection(servers)
    pc.onicecandidate = event => {
        console.log('ice candidate')
        if(event.candidate) {
            roomRef.update({ iceCandidates: firebase.firestore.FieldValue.arrayUnion({ ice: event.candidate.toJSON(), id: userID}) })
        } 
        else console.log('Sent all ice candidates!')
    }
    // this is deprecated
    // pc.onaddstream = (event => remoteVideo.srcObject = event.stream);

    async function createRoom(){
        await getLocalStream()
       
        pc.createOffer()
        .then(async (offer) => {
            roomRef = await collection.add({ id: userID, offer: { sdp: offer.sdp, type: 'offer' }})
            console.log(`New room created with ID ${roomRef.id}`)
            document.querySelector('#room-id').value = roomRef.id
            return offer
        })
        .then(offer => pc.setLocalDescription(offer))
        .then(() => attachRoomUpdateHandler())
    }

    async function joinRoom(){
        roomID = window.prompt('Enter room id', null)
        if(roomID){
            await getLocalStream()
            console.log(roomID)
            roomRef = collection.doc(roomID)
            const roomSnapshot = await roomRef.get()
            console.log(roomSnapshot,roomSnapshot.exits)
            
            var roomData = roomSnapshot.data()
            console.log(roomData.offer)
            pc.setRemoteDescription(roomData.offer)

            pc.createAnswer()
            .then(answer => pc.setLocalDescription(answer))
            .then(() => roomRef.update({ answers: firebase.firestore.FieldValue.arrayUnion({ sdp: pc.localDescription.sdp, id: userID}) }))
            .then(() => attachRoomUpdateHandler())
      }
    }

    async function attachRoomUpdateHandler(){
        roomRef.onSnapshot(async snapshot => {
            var updatedRoomData = snapshot.data()
            if(updatedRoomData){
                if(updatedRoomData.iceCandidates){
                    var remoteIceCandidates = updatedRoomData.iceCandidates.filter( ic => ic.id!=userID)
                    if(remoteIceCandidates.length>0) {
                        remoteIceCandidates.forEach(({ice}) => pc.addIceCandidate = new RTCIceCandidate(ice))
                    } else {
                        console.log('No remote ice candidates')
                    }
                } else if(updatedRoomData.id!=userID){
                    console.log('callee remote set')
                    pc.setRemoteDescription(updatedRoomData.offer)
                } else if(updatedRoomData.id==userID){
                    if(updatedRoomData.answers && updatedRoomData.answers.length){
                        pc.setRemoteDescription({ type: 'answer', sdp: updatedRoomData.answers[0].sdp})
                        console.log('answer remote set')
                    }
                }
            }
        })
    }
    var getLocalStream = async function(){
        return navigator.mediaDevices.getUserMedia({video: true, audio: true})
        .then(stream => { localStream = stream; localVideo.srcObject = stream ; return stream })
        .then(stream => stream.getTracks().forEach(track => pc.addTrack(track, localStream)))
        .then(() => {
            pc.ontrack = (event => remoteVideo.srcObject = event.streams[0])
        })
    }

    pc.addEventListener("connectionstatechange", ev => {
        console.log(pc.connectionState, ev)
   });
video{  max-width: 100%;  }
<h1>Realtime communication with WebRTC</h1>

<video id="localVideo" autoplay playsinline></video>
<video id="remoteVideo" autoplay playsinline></video>
<div>
   <input type="text" id="room-id">
    <button id="createBtn" onclick="createRoom()">Create Room</button>
    <button id="joinBtn" onclick="joinRoom()">Join Room</button>
    <p id="currentRoom"></p>
</div>    
    
<script src="https://www.gstatic.com/firebasejs/7.17.1/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.17.1/firebase-firestore.js"></script>

This much I could debug currently, but could not confirm whether the problem is in my code or STUN/TURN server.

Browser versions:

  1. Chrome version: Version 84.0.4147.89 (Official Build) (64-bit)
  2. Firefox version: 79.0 (64-bit)
0 Answers
Related