'PeerJs and Socket IO signal not recived by the existing user

I am making and group call platform for my final year project. I used this code from GitHub and modified a little bit. Back end code is almost same.

I am facing an issue while joining. Whenever a new user join the room it's video is not visible to the existing user's but the new user is able to see the video of the existing user.

[Front-end]

layout.jsx

import React, { useEffect, useRef, useState } from 'react';
import { io } from "socket.io-client";
import ChatSection from '../components/ChatSection';
import { EndCall, FullVolumeIcon, MessageIcon, MicrophoneOffIcon, MicrophoneOnIcon, UsersIcon, VideoOffIcon, VideoOnIcon } from '../components/Icon';
import queryString from 'query-string';
import Peer from 'simple-peer';
import { SnackBar } from '../components/SnackBar';
import useSound from "use-sound";


const Video = (props) => {
    const videoRef = useRef(null);

    useEffect(() => {

        props.peer.on("stream", stream => {
            videoRef.current.srcObject = stream;
        })

    }, [])

    return (
        <video className="meeting_video_video" ref={videoRef} autoPlay playsInline />
    )
}


export default function CenturyLayout() {


    const [showUserLeftSnackbar, setShowUserLeftSnackbar] = useState({
        open: false,
        message: 'test message'
    });

    const [showSnackBar, setShowSnackBar] = useState({
        open: false,
        message: 'test message'
    });

    const [roomName, setRoomName] = useState('');
    const [roomID, setRoomID] = useState('');
    const [userName, setUserName] = useState('');
    const [userSocketID, setUserSocketID] = useState('');
    const [time, setTime] = useState(0);


    const [isAudio, setIsAudio] = useState(true);
    const [isVideo, setIsVideo] = useState(true);



    const [showChat, setShowChat] = React.useState(false);

    // variables for different functionalities of video call
    const [peers, setPeers] = useState([]);
    const socketRef = useRef();
    const userVideo = useRef();
    const peersRef = useRef([]);
    const userStream = useRef();
    const [message, setMessage] = useState([]);

    const updateMessages = (message) => {
        setMessage((prev) => [...prev, { ...message }]);
    }

    useEffect(() => {
        const roomID = queryString.parse(window.location.search).room;
        const userName = queryString.parse(window.location.search).user;


        setRoomID(roomID);
        setUserName(userName);


        function formatAMPM(date) {
            var hours = date.getHours();
            var minutes = date.getMinutes();
            var ampm = hours >= 12 ? 'PM' : 'AM';
            hours = hours % 12;
            hours = hours ? hours : 12; // the hour '0' should be '12'
            minutes = minutes < 10 ? '0' + minutes : minutes;
            var strTime = hours + ':' + minutes + ' ' + ampm;
            return strTime;
        }


        setTime(formatAMPM(new Date()));

        // const socket = io.connect("https://centaur-meet.herokuapp.com/");
        const socket = io.connect("http://localhost:5000");

        setUserSocketID(socket.id);

        socketRef.current = socket;


        socket.on("chat-message", data => {
            alert(data.message);
            updateMessages(data);
        })


        // asking for audio and video access
        navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then(stream => {

            // streaming the audio and video
            userVideo.current.srcObject = stream;
            userStream.current = stream;


            socket.emit("join room group", { roomID, userName });



            // getting all user for the new user joining in
            socket.on("all users", users => {

                console.log("User currently in the room >>>", users);

                const tempPeers = [];

                // adding the new user to the group
                users.forEach(user => {

                    console.log("🙂User ID >>>", user);


                    const peer = createPeer(user.id, socket.id, stream, socket, user.userName);


                    peersRef.current.push({
                        peerID: user.id,
                        peer,
                    })
                    tempPeers.push({
                        peerID: user.id,
                        peer,
                    });
                })
                setPeers(tempPeers);
            })

            // sending signal to existing user's after new user joined
            socket.on("user joined", payload => {
                console.log(">>>A new user joined ", { payload });
                displaySnackBar(payload.userName + " joined the room");

                const peer = addPeer(payload.signal, payload.callerID, stream, socket);

                peersRef.current.push({
                    peerID: payload.callerID,
                    peer,
                })

                const peerObj = {
                    peer,
                    peerID: payload.callerID
                }

                setPeers((prev) => [...prev, peerObj]);
            });



            // existing users receiving the signal
            socket.on("receiving returned signal", payload => {
                console.log("Receiving returned signal ", payload.id);
                const item = peersRef.current.find(p => p.peerID === payload.id);

                console.log("item >>>", item);

                item.peer.signal(payload.signal);
            });



            // handling user disconnecting
            socket.on("user left", id => {
                // finding the id of the peer who just left
                const peerObj = peersRef.current.find(p => p.peerID === id);
                if (peerObj) {
                    peerObj.peer.destroy();
                    displaySnackBar(`${id} left the room`);
                }

                // removing the peer from the arrays and storing remaining peers in new array
                const peers = peersRef.current.filter(p => p.peerID !== id);
                peersRef.current = peers;
                setPeers(peers);
            })
        })



        return () => {
            socket.disconnect();

        }
    }, []);


    const displaySnackBar = (message) => {
        setShowSnackBar((prev) => {
            return {
                ...prev,
                open: true,
                message: message
            }
        })

        setTimeout(() => {
            setShowSnackBar((prev) => {
                return {
                    ...prev,
                    open: false,
                }
            })
        }, 3000);
    }


    // creating a peer object for newly joined user
    function createPeer(userToSignal, callerID, stream, socket, userName) {
        const peer = new Peer({
            initiator: true,
            trickle: false,
            stream,
            config: {
                'iceServers': [{ 'urls': 'stun:stun.l.google.com:19302' }]
            }
        });


        peer.on("signal", signal => {
            console.log("🙂Sending signal to callerID >>>", callerID);
            socket.emit("sending signal", { userToSignal, callerID, signal, userName })
        })

        return peer;
    }

    // adding the newly joined peer to the room
    function addPeer(incomingSignal, callerID, stream, socket) {
        const peer = new Peer({
            initiator: false,
            trickle: false,
            stream: stream,
        })



        peer.on("signal", signal => {
            console.log("Socket ID:  ", socket.id);
            console.log("🙂Sending signal to callerID >>>", callerID);
            socket.emit("returning signal", { signal, callerID })
        })


        peer.signal(incomingSignal);

        return peer;
    }

    // Toggle Video

    function toggleVideo() {
        setIsVideo(!isVideo);
        userStream.current.getVideoTracks()[0].enabled = isVideo;
    }

    // Toggle Audio

    function toggleAudio() {
        setIsAudio(!isAudio);
        userStream.current.getAudioTracks()[0].enabled = isAudio;
    }

    // Hanging up the call
    function hangUp() {
        userStream.current.getVideoTracks()[0].enabled = false;
        // callEndSound();
        window.location.replace("/");
    }


    // Chat functionality
    function sendChat(message) {

        const messageData = {
            message,
            userID: socketRef.current.id,
            roomID
        }

        updateMessages(messageData);

        socketRef.current.emit("message", messageData);
    }

    return (
        <div className='meeting_lyt_wrapper'>

            <ChatSection
                sendMessage={sendChat}
                userID={userSocketID}
                messages={message}
                showChat={showChat}
                setShowChat={setShowChat} />


            {
                showSnackBar.open && <SnackBar msg={showSnackBar.message} />}

            <div className='meeting_header_lyt'>
                <img src='./svg/centaurLogo.svg' className='meeting_header_logo' width={50} alt='logo' />

                <p className='meeting_header_time'>{time}</p>
                <hr />
                <p className='meeting_header_name'>{roomID}</p>
            </div>

            <div className='meeting_video_lyt'>
                <ul className='meeting_video_lists'>
                    <li className='meeting_video_item'>
                        <video ref={userVideo} className="meeting_video_video" autoPlay playsInline muted />
                    </li>
                    {peers && peers.map((peer, index) => (
                        <li key={index} className='meeting_video_item'>
                            <Video stream={peer.peer} key={peer.peerID} peer={peer.peer} />
                        </li>
                    ))}


                </ul>
            </div>

            <div className='meeting_controls_lyt'>
                <ul className='meeting_controls_list'>
                    <li className='meeting_control_item'>
                        <button className='meeting_control_button' onClick={() => console.log(peers)}>
                            <FullVolumeIcon color={'white'} />
                        </button>
                    </li>
                    <li className='meeting_control_item'>
                        <button className='meeting_control_button' onClick={toggleVideo}>
                            {
                                isVideo ? <VideoOnIcon color={'white'} /> : <VideoOffIcon color={'white'} />
                            }
                        </button>
                    </li>
                    <li className='meeting_control_item'>
                        <button className='meeting_control_button' onClick={toggleAudio}>
                            {
                                isAudio ?
                                    <MicrophoneOnIcon color={'white'} />
                                    :
                                    <MicrophoneOffIcon color={'white'} />
                            }
                        </button>
                    </li>
                    <li className='meeting_control_item'>
                        <button className='meeting_control_button' onClick={hangUp}>
                            <EndCall color={'white'} />
                        </button>
                    </li>
                    <li className='meeting_control_item'>
                        <button className='meeting_control_button'>
                            <UsersIcon color={'white'} />
                        </button>
                    </li>
                    <li className='meeting_control_item'>
                        <button
                            onClick={() => setShowChat(!showChat)}
                            className='meeting_control_button'>
                            <MessageIcon color={'white'} />
                        </button>
                    </li>

                </ul>
            </div>
        </div>
    )
}

[Back-end]

server.js

const express = require('express');
const cors = require('cors');
const bodyParser = require('body-parser');

const app = express();

bodyParser.urlencoded({ extended: false });
app.use(bodyParser.json());
app.use(cors());

app.get('/', (req, res) => {
    res.send('Hello World!');
});

const server = require('http').createServer(app);
const socketio = require('socket.io');
const e = require('express');
const io = socketio(server, {
    cors: {
        origin: '*',
        methods: ['GET', 'POST'],
        allowedHeaders: ['Access-Control-Allow-Headers'],
    }
});

const rooms = {};
const users = {};
const socketToRoom = {};

// when the user is forming a connection with socket.io
io.on("connection", socket => {

    console.log("user connected");
    // handling Group Video Call
    socket.on("join room group", ({ roomID, userName }) => {
        // getting the room with the room ID and adding the user to the room
        if (users[roomID]) {

            users[roomID].push({ id: socket.id, userName });
            // socket.join(roomID);
        } else {
            users[roomID] = [{ id: socket.id, userName }];
        }

        // returning new room with all the attendees after new attendee joined
        socketToRoom[socket.id] = roomID;
        const usersInThisRoom = users[roomID].filter(id => id.id !== socket.id);
        socket.emit("all users", usersInThisRoom);
    });

    // sending signal to existing members when user join
    socket.on("sending signal", payload => {
        const user = users[socketToRoom[socket.id]].find(user => user.id === payload.callerID);

        console.log({ callerID: payload.callerID })
        console.log({ socketID: socket.id })

        io.to(payload.userToSignal).emit('user joined', { signal: payload.signal, callerID: payload.callerID, userName: user.userName });
    });

    // signal recieved by the user who joined
    socket.on("returning signal", payload => {
        io.to(payload.callerID).emit('receiving returned signal', { signal: payload.signal, id: socket.id });
    });

    // Chat message
    socket.on("message", payload => {
        console.log("Chat message triggered", payload);
        io.to(payload.roomID).emit('chat-message', { message: payload.message, userID: payload.userID });
    });

    // handling user disconnect in group call
    socket.on('disconnect', () => {
        console.log('user disconnected');
        // getting the room array with all the participants
        const roomID = socketToRoom[socket.id];
        let room = users[roomID];

        if (room) {
            // finding the person who left the room
            // creating a new array with the remaining people
            room = room.filter(id => id.id !== socket.id);
            users[roomID] = room;
        }

        // emiting a signal and sending it to everyone that a user left
        socket.broadcast.emit('user left', socket.id);
    });
});

const port = process.env.PORT || 5000;

server.listen(port, () => {
    console.log('listening on port ', port);
});



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source