@securemeeting/secure-meeting-client
Version:
The client side apis for secure meeting
338 lines (294 loc) • 10.1 kB
JavaScript
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 };