**************FLOW , CONNECTIONS AND DISPLAYING ID'S******************

 IN THE FRONTEND , CONNECT BUTTON IS CLICKED,

<Button variant="contained" onClick={connect}>
            Connect
          </Button>


  let connect = () => {
    setAskForUsername(false); // AFTER BUTTON IS CLICKED , THE USERNAME IS SET TO FALSE
    getMedia();
    getUserMedia();
  };


  let getMedia = () => {
    setVideo(videoAvailable);
    setAudio(audioAvailable);
    connectToSocketServer(); // CONNNECTING TO SERVER
  };

INITIALLY, IN THE CONNECT TO SOCKET SERVER, 

let connectToSocketServer = () => {
    socketRef.current = io(server_Url);
    socketRef.current.on("signal", gotMessageFromServer);

IN THE BACKEND, WHEN A signal IS SENT,

 socket.on("signal", (toId, message) => {
      // console.log(socket.id);
      // console.log(message);
      io.to(toId).emit("signal", socket.id, message);
    });

gotMessageFromServer

let gotMessageFromServer = (Id, Message) => {
    let signal = JSON.parse(Message);
    console.log(signal);
    console.log(Id, socketIdRef.current);
    if (Id !== socketIdRef.current) {
      console.log(signal.sdp);
      if (signal.sdp) {
        connections[Id].setRemoteDescription(
          new RTCSessionDescription(signal.sdp)
        )
          .then(() => {
            if (signal.sdp.type === "offer") {
              connections[Id].createAnswer()
                .then((description) => {
                  connections[Id].setLocalDescription(description)
                    .then(() => {
                      socketRef.current.emit(
                        "signal",
                        Id,
                        JSON.stringify({
                          sdp: connections[Id].localDescription,
                        })
                      );
                    })
                    .catch((e) => console.log(e));
                })
                .catch((e) => console.log(e));
            }
          })
          .catch((e) => console.log(e));
      }
      if (signal.ice) {
        console.log("iceeeeeeeeee");
        connections[Id].addIceCandidate(new RTCIceCandidate(signal.ice)).catch(
          (e) => console.log(e)
        );
      }
    }
  };

on the BACKEND SOCKETCONTROLLER.JS
  for (let i = 0; i < connections[path].length; i++) {
        io.to(connections[path][i]).emit(
          "user-joined",
          socket.id,
          connections[path]
        );
      }

  let connectToSocketServer = () => {
    socketRef.current = io(server_Url);
    socketRef.current.on("signal", gotMessageFromServer);
    socketRef.current.on("connect", () => {
      socketRef.current.emit("join-call", window.location.href);
      socketIdRef.current = socketRef.current.id;
      socketRef.current.on("chat-message", setMessage);
      socketRef.current.on("user-left", (id) => {
        setVideo((videos) => videos.filter((video) => video.socketId !== id));
      });
      socketRef.current.on("user-joined", (id, clients) => {
        clients.forEach((socketListId) => {
// NEW PEER CONNECTION IS ESTABLISHED
          connections[socketListId] = new RTCPeerConnection(
            peerConfigConnections
          );
//WHEN TWO USERS WANT TO DO A PEER TO PEER CONNECTION, THEY NEED TO KNOW HOW TO
CONTACT EACH OTHER BUT DUE TO FIREWALLS IT'S NOT STRAIGHT FORWARD. SO EACH PEER
GATHERS POSSIBLE WAYS ( CANDIDATES) TO CONNECT, THESE ARE CALLED ICE CANDIDATES.

          connections[socketListId].onicecandidate = (event) => {
            if (event.candidate !== null) {
              socketRef.current.emit(
                "signal",
                socketListId,
                JSON.stringify({ ice: event.candidate })
            // THIS LINE WRAPS UP THE EVENT CANDIDATE LIKE THIS
  {
"ice": { "candidate": "candidate:842163049 1 udp ...", "sdpMid": "0", "sdpMLineIndex": 0 } }
);
            }
          };
          console.log(connections[socketListId]);
          //ontrack
HERE, WHEN WE RECEIVE A MEDIA STREAM (AUDIO/VIDEO) FROM THE CONNECTION, WE UPDATE
THE REACT STATE. SO, IT CAN BE RENDERED ON SCREEN.

          connections[socketListId].ontrack = (event) => {

            setVideos((prevVideos) => {
WE CHECK, IF A VIDEO EXISTS FROM THAT SPECIFIC SOCKETLISTID, INORDER TO PREVENT
ADDING THE SAME VIDEOS.

              const videoExists = prevVideos.some(
                (video) => video.socketId === socketListId
              );
          IF STREAM EXISTS WE JUST UPDATE THE STREAM
              if (videoExists) {
                return prevVideos.map((video) =>
                  video.socketId === socketListId
                    ? { ...video, stream: event.streams[0] }
                    : video
                );
              }
          IF IT'S A NEW VIDEO, A NEW OBJECT IS CREATED

              const newVideo = {
                socketId: socketListId,
                stream: event.streams[0],
                autoPlay: true,
                playsinline: true,
              };
         
              const updatedVideos = [...prevVideos, newVideo];
              videoRef.current = updatedVideos;
              return updatedVideos;
            });
          };
         
          console.log(window.localStream);

// TO SEND LOCAL AUDIO/VIDEO TRACKS TO REMOTE PEERS
          if (window.localStream) {
            window.localStream.getTracks().forEach((track) => {
              connections[socketListId].addTrack(track, window.localStream);
            });
          }
else {
WHEN THERE'S NO WEBCAM/MIC A BLACK SILENT STREAM IS SENT.
            //BLACK SILENCE
            let blackSilence = (...args) =>
              new MediaStream([black(...args), silence()]);
            window.localStream = blackSilence();

            window.localStream.getTracks().forEach((track) => {
              connections[socketListId].addTrack(track, window.localStream);
            });
          }
        });

        if (id === socketIdRef.current) {
          for (let id2 in connections) {
            if (id2 === socketIdRef.current) {
              continue;
            }
     WHEN TWO PEERS NEED TO BE CONNECTED, AN OFFER IS CREATED. AN OFFER IS A PART
OF SDP (SESSION DESCRIPTION PROTOCOL) NEGOTIATION THAT HELPS TWO PEERS AGREE ON
HOW TO COMMUNICATE.

          1.AN OFFER IS CREATED BY PEER A
  connections[id2].createOffer().then((description) => {
2.THIS OFFER IS SET AS IT'S LOCAL DESCRIPTION
              connections[id2]
                .setLocalDescription(description)
                .then(() => {
3. THEN THIS IS SENT TO PEER B AS A SIGNAL.
                  socketRef.current.emit(
                    "signal",
                    id2,
                    JSON.stringify({
                      sdp: connections[id2].localDescription,
                    })
                  );
                })
                .catch((e) => {
                  console.log(e);
                });
            });
          }
        }
      });
    });
  };

getUserMedia() FUNCTION TO GET THE USER'S MEDIA

let getUserMedia = () => {
    console.log(video);
    if ((video && videoAvailable) || (audio && audioAvailable)) {
      navigator.mediaDevices
        .getUserMedia({ video: video, audio: audio })
        .then(getUserMediaSuccess)
        .then((stream) => {})
        .catch((e) => {
          console.log(e);
        });
    } else {
      try {
        let tracks = localVideoRef.current.srcObject.getTracks();
        tracks.forEach((track) => track.stop());
      } catch (e) {}
    }
  };


**************** getUserMediaSuccess ****************

 const getUserMediaSuccess = (stream) => {
    console.log(window.localStream.getTracks());
    try {
IF ANY PREVIOUS STREAM EXISTS WE STOP IT.
      window.localStream.getTracks().forEach((track) => {
        track.stop();
      });
    } catch (e) {
      console.log(e);
    }
    // console.log(stream);
    window.localStream = stream;
    // console.log(window.localStream);
    // console.log(localVideoRef.current.srcObject);
TO DISPLAY NEW STREAM
    localVideoRef.current.srcObject = stream;
    // console.log(localVideoRef.current.srcObject);
    // console.log(connections);
    for (let id in connections) {
      // console.log(id);
      if (id === socketIdRef.current) {
        continue;
      }

      connections[id].createOffer().then((description) => {
        // console.log(description);
        connections[id]
          .setLocalDescription(description)
          .then(() => {
            socketRef.current.emit(
              "signal",
              id,
              JSON.stringify({ sdp: connections[id].localDescription })
            );
          })
          .catch((e) => console.log(e));
      });
    }
WHEN THE USER TURNS OFF MIC/WEBCAM THE STREAM IS UPDATED.
    stream.getTracks().forEach(
      (track) =>
        (track.onended = () => {
          setAudio(false);
          setVideo(false);

          try {
            let tracks = localVideoRef.current.srcObject.getTracks();
            // console.log(tracks);
            tracks.forEach((track) => track.stop());
          } catch (e) {
            console.log(e);
          }

          let blackSilence = (...args) =>
            new MediaStream([black(...args), silence()]);
          window.localStream = blackSilence();
          localVideoRef.current.srcObject = window.localStream;

          for (let id in connections) {
            connections[id].createOffer().then((description) => {
              connections[id]
                .setLocalDescription(description)
                .then(() => {
                  socketRef.current.emit(
                    "signal",
                    id,
                    JSON.stringify({ sdp: connections[id].localDescription })
                  );
                })
                .catch((e) => console.log(e));
            });
          }
        })
    );
  };



TO DISPLAY ID'S
 <>
      {askForUsername === true ? (
        <div>
          <h2>Enter into lobby</h2>
          <TextField
            className="inputsRequired"
            id="outlined-basic"
            label="Username"
            value={username}
            variant="outlined"
            onChange={(e) => setUsername(e.target.value)}
          />
          <Button variant="contained" onClick={connect}>
            Connect
          </Button>
          <div>
            <video ref={localVideoRef} autoPlay muted></video>
          </div>
        </div>
      ) : (
        <div>
          <video ref={localVideoRef} autoPlay muted></video>
          {videos.map((video) => (
            <div key={video.socketId}>
              <h2>{video.socketId}</h2>
              <video
                data-socket={video.socketId}
                ref={(ref) => {
                  if (ref && video.stream) {
                    ref.srcObject = video.stream;
                  }
                }}
                autoPlay
                playsInline
              />
            </div>
          ))}
        </div>
      )}
    </>
  );





















Comments