MException: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Failed to set remote answer sdp: Called in wrong state: stable (
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"
]
}
}
`
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.