0

I am new to WebRTC and was making a video conferencing feature for my app using React, Socket.io, and WebRTC. I don't know why but I am having a lot of trouble with connecting the peer objects for my app. I can make and end a call between 2 peers fine for the first call but if I try to make subsequent calls, the peer connection gets closed and it does not get through to the other peer. I tried to cleanup the peer object and event listeners but that still does not seem to work. I am just not sure why it works perfectly fine on the first call but stops working after that. Appreciate any help, thank you!

import axios from "axios";
import { useRef, useEffect, useState } from "react";
import { useDispatch } from "react-redux";
import { useSelector } from "react-redux";
import { useLocation, useParams } from "react-router-dom";
import Peer from "simple-peer"
import SimplePeer from "simple-peer";

const ClientVideoConferenceDetail = ({socket}) => {
    
    const myVideo = useRef()
    const connectionRef= useRef()
    const SimplePeer = window.SimplePeer;

    const { roomid } = useParams()
    const location = useLocation()


    const userObj = useSelector(state => state.user)
    const [stream, setStream ] = useState()
    const userVideo = useRef()
    const [ callAccepted, setCallAccepted ] = useState(false)
    const [ callEnded, setCallEnded] = useState(false)
    const [ caller, setCaller ] = useState("")
    const [ name, setName ] = useState("")

    const [ callerSignal, setCallerSignal ] = useState()
    const [ receivingCall, setReceivingCall ] = useState(false)

    const [me, setMe] = useState('')
    const [sender, setSender] = useState()
    const [receiver, setReceiver] = useState()
    const [room, setRoom] = useState(roomid)

    const [userType, setUserType] = useState()

    const resetCallState = () => {
        setCallAccepted(false);
        setCallEnded(false);
        setCaller("");
        setReceivingCall(false)
        setName("");
    };


    useEffect(() => {
        if(room){
            socket.emit("join_room", {room})
        }
    },[room, socket])

    useEffect(() => {
        setMe(userObj.id)

        const getDeviceMedia = async () => {
            try {
                    const stream = await navigator.mediaDevices.getUserMedia({video: true});
                    setStream(stream)
                    myVideo.current.srcObject = stream;
            }
            catch(err){
                console.log(`Error here is ${err}`)
            }
            
            }
            getDeviceMedia()

        const getInfo = async () => {
            setSender(userObj.id)
            setReceiver(userObj.receiver) 

        }
        getInfo()
        
        socket.on("callUser", (data) => {
            console.log(`got into call user`)
            setReceivingCall(true)
            setCaller(data.from)
            setName(data.name)
            setCallerSignal(data.signal)
        })

        socket.on("endCall", (data) => {
            leaveCall()
        })

        return () => {
            if (connectionRef.current) {
              connectionRef.current.destroy();
            }
            socket.off("callUser");
            socket.off("endCall");
          };

    }, [sender, receiver])

    const callUser = (roomNumber) => {
        console.log('clicked call btn')
        const peer = new SimplePeer({
            initiator: true,
            trickle: false,
            stream: stream
        })
        

        connectionRef.current = peer;

        peer.on("signal", (data) => {
            console.log(`got in signal: ${roomNumber}`)
            socket.emit("callUser", {
                userToCall: roomNumber,
                signalData: data,
                from: me,
                name: receiver
            })
        })

        

        peer.on("stream", (stream_num) => { 
            console.log(`got in stream peer`)
            userVideo.current.srcObject = stream_num
        })

        peer.on('close', () => { 
            console.log(`why is it here`)
            console.log('peer closed'); 
            socket.off("callAccepted");
        });

        socket.on("callAccepted", (signal) => {
            setCallAccepted(true)
            peer.signal(signal)
        })

        // connectionRef.current = peer
        if (connectionRef.current) {
            connectionRef.current.destroy();
          }
          connectionRef.current = peer;
    }

    const answerCall =() =>  {
        setCallAccepted(true)
        const peer = new SimplePeer({
            initiator: false,
            trickle: false,
            stream: stream
        })
        

        peer.on("signal", (data) => {
            socket.emit("answerCall", { signal: data, to: room })
        })
        
        // connectionRef.current = peer;

        peer.on("stream", (stream) => {
            userVideo.current.srcObject = stream
        })

        peer.on('close', () => { console.log('peer closed'); socket.off("callAccepted"); });

        peer.signal(callerSignal)
        // connectionRef.current = peer
        if (connectionRef.current) {
            connectionRef.current.destroy();
          }
          connectionRef.current = peer;
    }

    const leaveCall = () => {
        setCallEnded(true)
        if (connectionRef.current) {
            connectionRef.current.destroy(); // Check if connectionRef.current is defined
        }
        resetCallState()
        socket.emit("hangUpCall", {room})
    }



    return ( 
        <div>
            <h2>Video Conferencing - Client</h2>
            <div className="video-container">
                <div className="video">
                    {stream && 
                    <>
                    <h3>You are {me}</h3>
                    <video playsInline muted ref={myVideo} autoPlay style={{ width: "500px", borderRadius:"15px" }} />
                    </>}
                </div>
                <div className="video">
                    {callAccepted && !callEnded ?
                    <>
                    <h3>Talking with {receiver}</h3>
                    <video playsInline ref={userVideo} autoPlay style={{ width: "500px", borderRadius:"15px"}} />
                    </>
                    :
                    null}
                </div>
            </div>
            <div className="call-button">
                    {callAccepted && !callEnded ? (
                        <button variant="contained" color="secondary" onClick={leaveCall}>End Call</button>
                    ) : (
                        <button onClick={() => callUser(roomid)}>Call</button>
                    )}
                </div>
                <div>
                {receivingCall && caller !== userObj.id && !callAccepted ? (
                        <div className="caller">
                        <h1 >{caller} is calling...</h1>
                        <button onClick={answerCall}> Answer</button>
                    </div>
                ) : null}
            </div>
        </div>
     );
}
 
export default ClientVideoConferenceDetail;

0 Answers0