Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MException: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Failed to set remote answer sdp: Called in wrong state: stable ( #917

Open
kikichen77 opened this issue Apr 27, 2023 · 1 comment

Comments

@kikichen77
Copy link

When I upgrade the latest version of react, react-dom, react-routers-dom, the normal previous code has the error of MException: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Failed to set remote answer sdp: Called in wrong state: stable
(
`client-side
import { useState,useRef,useEffect} from "react";
import io from "socket.io-client";
import SimplePeer from "simple-peer";
import { useParams } from "react-router-dom";

const Video = (props) => {
const ref = useRef();

useEffect(() => {
  props.peer.on('stream', (stream) => {
    ref.current.srcObject = stream;
  });
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return (
<video
style={{ width: "100%", transform: "rotateY(180deg)" }}
ref={ref}
autoPlay
muted
playsInline
>
);
};

const Room=()=>{
const username="wa"
const [peers, setPeers] = useState([]);
const socketRef = useRef();
const userVideo = useRef();
const peersRef = useRef([]);
const { id } = useParams();
const roomID = id;

useEffect(() => {
  socketRef.current = io.connect("http://localhost:8000/");
  navigator.mediaDevices.getUserMedia({ video: true, audio: false }).then(stream => {
    userVideo.current.srcObject = stream;
    socketRef.current.emit("join room", roomID);
    socketRef.current.on("all users", users => {
        const peers = [];
        users.forEach(userID => {
            const peer = createPeer(userID, socketRef.current.id, stream);
            peersRef.current.push({
                peerID: userID,
                peer,
            })
            peers.push(peer);
        })
        setPeers(peers);
    })

    socketRef.current.on("user joined", payload => {
        const peer = addPeer(payload.signal, payload.callerID, stream);
        peersRef.current.push({
            peerID: payload.callerID,
            peer,
        })

        setPeers(users => [...users, peer]);
    });

    socketRef.current.on("receiving returned signal", payload => {
      const item = peersRef.current.find(p => p.peerID === payload.id);
      if (!item.peer.destroyed) {
        item.peer.signal(payload.signal);
      }
    });
    
})

// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

function createPeer(userToSignal, callerID, stream) {
try {
const peer = new SimplePeer({
initiator: true,
trickle: false,
config: {
iceServers: [
{
urls: "stun:stun.l.google.com:19302",
},
],
},
stream: stream,
});

// Move error event listener to the beginning
peer.on("error", (error) => {
  console.error("Peer error:", error);
});

peer.on('signal', (signal) => {
  console.log("Peer signal:", signal);
  socketRef.current.emit('sending signal', { userToSignal, callerID, signal });
});

return peer;

} catch (error) {
console.log("Peer creation error:", error);
}
}

function addPeer(incomingSignal, callerID, stream) {
const peer = new SimplePeer({
initiator: false,
trickle: false,
config: {
iceServers: [
{
urls: "stun:stun.l.google.com:19302",
}],
},
stream: stream,
});
console.log(1)

// Move error event listener to the beginning
peer.on("error", (error) => {
console.error("Peer error:", error);
});

peer.on('signal', (signal) => {
console.log(2)
socketRef.current.emit('returning signal', { signal, callerID });
});

setTimeout(() => {
console.log(3)
// if (peer._pc.signalingState !== "stable") {
//console.log(4)
peer.signal(incomingSignal);
// }
}, 100);

return peer;
}

return (
  <div className="video-wrap">
    <span style={{ position: "absolute", top: "1px", left: "1px" }}>
      {username}
    </span>
    <video
      style={{ width: "100%", transform: "rotateY(180deg)" }}
      ref={userVideo}
      autoPlay
      muted
      playsInline
    ></video>
    {peers.map((peer, index) => {
      return <Video key={index} peer={peer} />;
    })}
  </div>
);

}
export default Room;
``server-side
require('dotenv').config();
const express = require("express");
const http = require("http");
const app = express();
const server = http.createServer(app);
const socket = require("socket.io");
const io = socket(server);

const users = {};

const socketToRoom = {};

io.on('connection', socket => {
socket.on("join room", roomID => {
// console.log("Join room event triggered for room:", roomID);
if (users[roomID]) {
const length = users[roomID].length;
// console.log(length);
if (length === 8) {
socket.emit("room full");
return;
}
// Check if socket.id is not already in the users[roomID] array before pushing it
if (!users[roomID].includes(socket.id)) {
users[roomID].push(socket.id);
}
} else {
users[roomID] = [socket.id];
}
socketToRoom[socket.id] = roomID;
const usersInThisRoom = users[roomID].filter(id => id !== socket.id);
console.log(usersInThisRoom)
socket.emit("all users", usersInThisRoom);
});

socket.on("sending signal", payload => {
    io.to(payload.userToSignal).emit('user joined', { signal: payload.signal, callerID: payload.callerID });    
  });

socket.on("returning signal", payload => {
    io.to(payload.callerID).emit('receiving returned signal', { signal: payload.signal, id: socket.id });
});

socket.on('disconnect', () => {
    const roomID = socketToRoom[socket.id];
    let room = users[roomID];
    if (room) {
        room = room.filter(id => id !== socket.id);
        users[roomID] = room;
    }
});

});

server.listen(8000, () => console.log('server is running on port 8000'));
version:
{
"name": "client",
"version": "0.1.0",
"private": true,
"proxy": "http://localhost:8000",
"dependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-router-dom": "^6.10.0",
"react-scripts": "3.4.1",
"simple-peer": "^9.11.1",
"socket.io-client": "^2.3.0",
"styled-components": "^5.1.0",
"uuid": "^7.0.3",
"vite": "^4.3.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
`

@szcuipeng
Copy link

i got the same error, i found i made a mistake:

correct:
create peer1 (initiator) and peer2 -->
send peer1's signal data to peer2 -->
send peer2's signal data to peer1

wrong:
create peer1 (initiator) and peer2 -->
send peer1's signal data to peer2 -->
send peer2's signal data to peer3, then peer3 output a console error:

Failed to execute 'setRemoteDescription' on 'RTCPeerConnection':
Failed to set remote answer sdp: Called in wrong state: stable

to avoid this, i add an uuid property to peer object.
everytime i send/recv/call signal data, i check if peer1(initiator) and peerx has the same uuid.
if not same, restart all.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants