MException: Failed to execute 'setRemoteDescription' on 'RTCPeerConnection': Failed to set remote answer sdp: Called in wrong state: stable (
kikichen77 opened this issue · comments
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.