UNPKG

@securemeeting/secure-meeting-client

Version:
338 lines (294 loc) 10.1 kB
import openSocket from "socket.io-client"; class P2P { /** * Creates an instance of SecureMeeting's P2P API * @constructor * @param {String} socketUrl The address of the signalling server to establish a connection with */ constructor(socketUrl) { this.localStream = null; this.screenShareStream = null; this.socket = openSocket(socketUrl); this.configuration = { iceServers: [ { url: "stun:stun.l.google.com:19302" }, { url: "turn:numb.viagenie.ca", credential: "enter1234", username: "bethin.charles@yahoo.com", }, ], }; this.peerConnections = new Object(); this.init(); } /*Functions to do: turnOnScreenshare turnOffScreenshare onNeedNegotiation */ turnOffMic() { console.log("turn off mic"); let peers = Object.keys(this.peerConnections); for (let i = 0; i < peers.length; i++) { let currentSocketId = peers[i]; console.log("removing mic track from", currentSocketId); let senders = this.peerConnections[currentSocketId].getSenders(); let videoSenders = senders.filter((sender) => { return sender.track.kind === "audio"; }); for (let j = 0; j < videoSenders.length; j++) { videoSenders[j].track.enabled = false; } console.log(videoSenders); } } turnOnMic() { console.log("turn on mic"); let peers = Object.keys(this.peerConnections); for (let i = 0; i < peers.length; i++) { let currentSocketId = peers[i]; console.log("removing mic track from", currentSocketId); let senders = this.peerConnections[currentSocketId].getSenders(); let videoSenders = senders.filter((sender) => { return sender.track.kind === "audio"; }); for (let j = 0; j < videoSenders.length; j++) { videoSenders[j].track.enabled = true; } console.log(videoSenders); } } turnOnWebcam() { console.log("turn on webcam"); let peers = Object.keys(this.peerConnections); for (let i = 0; i < peers.length; i++) { let currentSocketId = peers[i]; console.log("removing webcam track from", currentSocketId); let senders = this.peerConnections[currentSocketId].getSenders(); let videoSenders = senders.filter((sender) => { return sender.track.kind === "video"; }); for (let j = 0; j < videoSenders.length; j++) { videoSenders[j].track.enabled = true; } console.log(videoSenders); } } turnOffWebcam() { console.log("turn off webcam"); let peers = Object.keys(this.peerConnections); for (let i = 0; i < peers.length; i++) { let currentSocketId = peers[i]; console.log("removing webcam track from", currentSocketId); let senders = this.peerConnections[currentSocketId].getSenders(); let videoSenders = senders.filter((sender) => { return sender.track.kind === "video"; }); for (let j = 0; j < videoSenders.length; j++) { videoSenders[j].track.enabled = false; } console.log(videoSenders); } } /** * Initializes the webcam and websocket connections * */ async init() { console.log("initilizing SM p2p...."); console.log("getting local streams"); await this.getMedia(); this.initSocket(); } /** * Sends the local Offer to the remote peer * @param {Object} offer the offer generated by the RTCPeerconnection * @param {String} socketId the socketId of the remote peer */ sendLocalOffer(offer, socketId) { this.socket.emit("send_local_offer", { offer: offer, socketId: socketId }); } /** * Sends the local Answer to the remote peer * @param {Object} answer the offer generated by the RTCPeerconnection * @param {String} socketId the socketId of the remote peer */ sendLocalAnswer(answer, socketId) { this.socket.emit("send_local_answer", { answer: answer, socketId: socketId, }); } /** * Removes a peer from the P2P connections * @param {String} socketId the socketId of the peer who disconnected */ removePeer(socketId) { console.log("removed peer:", socketId); //remove video element let vid = document.getElementById( this.peerConnections[socketId].connectionWith ); vid.remove(); //close peer connection this.peerConnections[socketId].close(); delete this.peerConnections[socketId]; } /** * Allows a peer to join a room * @param {String} roomName a unique roomName to join */ joinRoom(roomName) { this.socket.emit("join_room", { roomName: roomName }); } /** * Creates and sends an answer to the remote peer * @param {String} socketId the socketId of the remote peer */ async createAnswer(socketId) { const answer = await this.peerConnections[socketId].createAnswer(); await this.peerConnections[socketId].setLocalDescription(answer); console.log("created answer:", answer); this.sendLocalAnswer(answer, socketId); } /** * Creates and sends an offer to the remote peer * @param {String} socketId the socketId of the remote peer */ async getLocalOffer(socketId) { const offer = await this.peerConnections[socketId].createOffer(); await this.peerConnections[socketId].setLocalDescription(offer); console.log("created offer:", offer); this.sendLocalOffer(offer, socketId); } /** * Gets the webcam and microphone of the user */ async getMedia() { var video = document.getElementById("localStream"); let stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true, }); video.srcObject = stream; this.localStream = stream; } /** * Attaches tracks onto a peer connection * @param {String} socketId the socketId of the peerConnection to attach tracks to */ async attachTracks(socketId) { console.log("adding tracks.."); if (this.localStream == null) { await this.getMedia(); } this.localStream.getTracks().forEach((track) => { this.peerConnections[socketId].addTrack(track, this.localStream); }); } /** * Initializes the RTC Event Handlers for the specifiec peer connection * @param {String} socketId the socketId of the remote peer */ initRTCEvents(socketId) { console.log("init rtc events"); this.peerConnections[socketId].connectionWith = socketId; this.peerConnections[socketId].onicecandidate = (iceEvent) => { let candidate = iceEvent.candidate; let socketId = iceEvent.target.connectionWith; //console.log(candidate); //console.log(socketId); if (candidate) { this.socket.emit("send_ice_candidate", { candidate: candidate, socketId: socketId, }); } }; this.peerConnections[socketId].ontrack = (event) => { console.log("on track", event); //var video = document.getElementById("remoteStream"); //console.log("got track"); //video.srcObject = event.streams[0]; var videoElementForCurrentPeer = document.getElementById( this.peerConnections[socketId].connectionWith ); if (videoElementForCurrentPeer === null) { var vid = document.createElement("video"); vid.setAttribute("id", this.peerConnections[socketId].connectionWith); vid.autoplay = true; vid.srcObject = event.streams[0]; vid.setAttribute("width", "320"); vid.setAttribute("height", "320"); var x = document.getElementById("vids"); x.appendChild(vid); } }; this.peerConnections[socketId].onnegotiationneeded = (event) => { console.log("negotiation needed!!"); console.log("negotiation needed!!"); console.log("negotiation needed!!"); }; } /** * Starts the process establishing a peer connection with a remote peer (Peer A) * @param {String} socketId the socketId of the remote peer */ async initiateNewConnection(socketId) { console.log("initiating a new webRtc conection with ", socketId); this.peerConnections[socketId] = new RTCPeerConnection(this.configuration); this.attachTracks(socketId); this.initRTCEvents(socketId); await this.getLocalOffer(socketId); console.log(this.peerConnections[socketId]); } /** * Finishes the process establishing a peer connection with a remote peer (Peer B) * @param {String} socketId the socketId of the remote peer */ finishNewConnection(socketId, offer) { console.log("finishing a new webRtc conection with ", socketId); this.peerConnections[socketId] = new RTCPeerConnection(this.configuration); this.attachTracks(socketId); this.initRTCEvents(socketId); this.peerConnections[socketId] .setRemoteDescription(offer) .then(async () => { await this.createAnswer(socketId); console.log(this.peerConnections[socketId]); }); } /** * Initializes the websocket events */ initSocket() { console.log("init sockets"); this.socket.on("got_remote_offer", async (payload) => { var { socketId, offer } = payload; console.log("got remote offer from", socketId); this.finishNewConnection(socketId, offer); }); this.socket.on("got_remote_answer", async (payload) => { console.log("got a remote answer"); var { socketId, answer } = payload; console.log(socketId, answer); this.peerConnections[socketId].setRemoteDescription(answer); console.log(this.peerConnections[socketId]); }); this.socket.on("create_new_connection", async (payload) => { this.initiateNewConnection(payload.socketId); }); this.socket.on("peer_left_room", async (payload) => { this.removePeer(payload.socketId); }); this.socket.on("got_ice_candidate", async (payload) => { console.log("got ice"); var { candidate, socketId } = payload; if (candidate) { this.peerConnections[socketId].addIceCandidate(candidate); } }); } } export { P2P };