How to fix the Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Failed to set remote answer sdp: Called in wrong state: kStable

Viewed 2610

I refer the below document to build using perfect negotiation pattern in my Peer Communicate web app.:

  1. This one from MDN
  2. This one from github

My web page content as below:

<html>
 <head>
  <meta charset="UTF-8">
  <title>WebRTC Caller</title>
  <script src="/socket.io/socket.io.js"></script>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
  <script>
   
   var peer=null;
   var socket = io.connect();
   var dc,pc,polite=false;
   var localVideo,remoteVideo;
   var makingOffer = false, ignoreOffer = false;
   var configuration = {iceServers: 
    [{urls: "stun:stun.stunprotocol.org"},
     {urls: "stun:stun.l.google.com:19302"},
     {urls: "turn:numb.viagenie.ca", credential: "***", username: "***"}  
    ]};
   $( document ).ready(function() {
    localVideo=document.getElementById("selfView");
    remoteVideo=document.getElementById("remoteView");
   });
   function call() {
    polite=true;
    createConnection();
   }
   function createConnection(){
    pc=new RTCPeerConnection(configuration);
    pc.onnegotiationneeded=negotiationEventHandler;
    pc.onicecandidate=iceCandidateEventHandler;
    dc= pc.createDataChannel('chat');
   }
   function hangUp() {
    dc.close();
    pc.close();
   }
   function iceCandidateEventHandler(event){
    if (event.candidate==null){
     writeLog("All ICE Candidates are sent");
    } else {
     writeLog("Send ICE Candidate");
     socket.emit('send',{candidate:event.candidate});
    }
   }
   async function negotiationEventHandler(){
    writeLog('Handle Negotitation');
    
    try {
     makingOffer = true;
     await pc.setLocalDescription();
     socket.emit("send",{ description: pc.localDescription });
    } catch(err) {
     writeLog(err);
    } finally {
     makingOffer = false;
    }
    
   }
   function clearLog() {
     chatelement = document.getElementById('logger');
     chatelement.innerHTML='';
   }  
   function writeLog(message) {
    var logger=document.getElementById("logger");
    logger.innerHTML=message+"<br>"+logger.innerHTML;
   } 
   socket.on("receive",async (req)=>{
    let ignoreOffer = false;
    clearLog();
    createConnection();
    if (req.description){
     const offerCollision = (req.description.type == "offer") &&
         (makingOffer || pc.signalingState != "stable");

     ignoreOffer = !polite && offerCollision;
     if (ignoreOffer) {
      return;
     }
     await pc.setRemoteDescription(req.description);
     if (req.description.type =="offer") {
      await pc.setLocalDescription();
      socket.emit("send",{description: pc.localDescription});
     }
    } else {
     if (req.candidate){
      try {
       if (pc.currentRemoteDescription){
        await pc.addIceCandidate(req.candidate);
       }
      } catch(err) {
       if (!ignoreOffer) {
         throw err;
       }
      }
     }
    }
   });   
  </script>
 </head>
 <body>
  <table border=1>
   <tr>
    <td>
     <h1> Self View </h1>
     <video id="selfView" width="320" height="240" autoplay muted></video>
    </td>
    <td>
     <h1> Remote View </h1>
     <video id="remoteView" width="320" height="240" autoplay muted></video>
    </td>
   </tr>
   <tr>
    <td><button onclick="call()">Make A Call</button><button onclick="addMedia()">Add Media</button></td>
    <td><button onclick="hangUp()">Hang Up</button></td>
   </tr> 
  </table>
  <div id="logger" style="border:1px solid black;width:100%;height:30%;overflow:scroll">
  </div>
 </body>
</html> 

My node.js server side code as below:

var fs = require('fs');
var https = require('https');

var express = require('express');
var app = express();

var options = {
  key: fs.readFileSync('private.key'),
  ca: [fs.readFileSync('ca_bundle.crt')],
  cert: fs.readFileSync('certificate.crt')
};
var serverPort = 443;

var server = https.createServer(options, app);
var io = require('socket.io')(server);
var userList=[];

app.use(express.static('public'));
io.on('connection', function(socket) {
  console.log('new connection');
  userList.push(socket.id); 
  socket.emit('message', 'This is a message from the dark side.');
});
io.on('connection', (socket) => {
    console.log('a user connected@'+(new Date()));
    socket.on("send",(req)=>{
        console.log("Receive send request");
        socket.broadcast.emit("receive", req);
    });
    socket.on('disconnect', () => {
        console.log('user disconnected@'+(new Date()));
    });
});

server.listen(serverPort, function() {
  console.log('server up and running at %s port', serverPort);
});

I open the web page with 2 browsers (1 is chrome,1 firefox). When I click on the "Make a call" button in chrome browser, the chrome prompt the following error message:

Uncaught (in promise) DOMException: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Failed to set remote answer sdp: Called in wrong state: kStable

When I click on the "Make a call" button in firefox browser, the firefox prompt the following error message:

InvalidStateError: Cannot set remote answer in state stable

What is the problem?How can I fix it?

0 Answers
Related