Skip to content

Instantly share code, notes, and snippets.

@SanskarSans
Created March 14, 2019 12:04
Show Gist options
  • Save SanskarSans/76aee1ab4ccab7c02dc812019f1329e9 to your computer and use it in GitHub Desktop.
Save SanskarSans/76aee1ab4ccab7c02dc812019f1329e9 to your computer and use it in GitHub Desktop.
const sessionHandler = session({
secret : 'none',
rolling : true,
resave : true,
saveUninitialized : true
});
app.use(sessionHandler);
/*
* Definition of global variables.
*/
const users = {};
const sessions = {};
const candidatesQueue = {};
let kurentoClient = null;
io.of('/sockets').on('connection', socket => {
socket.on("room:addUser", async ({ interviewId: room, userEmail }) => {
console.log('room join socket listened');
socket.join(room);
socket.room = room;
let session = sessions[room];
if(!session) {
session = new CallHandler(await getKurentoClient(kurentoUrl), room, ()=>delete sessions[socket.room]);
await session.init();
sessions[socket.room] = session;
}
let addSuccess = session.addClient(socket.id, room, (message) => {
if(message.every){
io.of('sockets').in(socket.room).emit(message.action, message.data);
}else {
socket.emit(message.action, message.data);
}
});
if(!addSuccess){
//todo handle this case by showing the user some specific message
}
});
socket.on("iceCandidate", (candidate) => {
console.log("Ice Candidate");
let session = sessions[socket.room];
if(session){
console.log("serrion")
session.addIceCandidate(socket.id, candidate);
}
});
socket.on("offer", (offer) => {
console.log("offer>>>>>");
let session = sessions[socket.room];
if(session){
session.receiveOffer(socket.id, offer);
}
});
// OFFER_CREATE
socket.on('OFFER_CREATE', offer => {
const { room } = offer;
console.log(`creating offer to ${room}`);
start(sessionId, socket, offer, function(error, sdpAnswer) {
if (error) {
return socket.emit('ERROR', error);
}
const answer = {
room: room || socket.room,
sdpAnswer
}
socket.broadcast.to(room).emit('OFFER_RESPONSE', answer);
})
})
// leaving session
socket.on('STOP', () => stop(sessionId))
//
socket.on('CANDIDATE_NEW', response => onIceCandidate(socket.id, response.candidate));
socket.on("end", () => {
console.log(`closing socket in room:: ${socket.room}`);
// console.log(`socket end: room: ${room ? room : socket.room}`)
socket.disconnect(0);
});
socket.on('disconnect', () => {
console.log("Client disconnected from", socket.room);
let session = sessions[socket.room];
if(session){
session.removeClient(socket.id);
}
socket.broadcast.to(socket.room).emit('remote:leave', socket.id);
});
})
async function getKurentoClient() {
if(kurentoClient === null) {
kurentoClient = await Kurento(kurentoUrl);
console.log('Connected to Kurento');
}
return kurentoClient;
}
function start(socketId, socket, offer, callback) {
console.log('start function', offer, callback);
if (!socketId) {
return callback('Cannot use undefined socketId');
}
getKurentoClient(function(error, kurentoClient) {
if (error) {
return callback(error);
}
kurentoClient.create('MediaPipeline', function(error, pipeline) {
console.log('pipeline', pipeline);
if (error) {
return callback(error);
}
createMediaElements(pipeline, socket, function(error, webRtcEndpoint) {
if (error) {
pipeline.release();
return callback(error);
}
if (candidatesQueue[socketId]) {
while(candidatesQueue[socketId].length) {
const candidate = candidatesQueue[socketId].shift();
webRtcEndpoint.addIceCandidate(candidate);
}
}
connectMediaElements(webRtcEndpoint, function(error) {
if (error) {
pipeline.release();
return callback(error);
}
webRtcEndpoint.on('OnIceCandidate', function(event) {
var candidate = kurento.getComplexType('IceCandidate')(event.candidate);
// console.log('candidate', candidate);
socket.emit('ICE_CANDIDATE', candidate);
});
webRtcEndpoint.processOffer(offer, function(error, sdpAnswer) {
if (error) {
pipeline.release();
return callback(error);
}
sessions[socketId] = {
'pipeline' : pipeline,
'webRtcEndpoint' : webRtcEndpoint
}
console.log('sessions', sessions);
return callback(null, sdpAnswer);
});
webRtcEndpoint.gatherCandidates(function(error) {
if (error) {
return callback(error);
}
});
});
});
});
});
}
function createMediaElements(pipeline, socket, callback) {
pipeline.create('WebRtcEndpoint', function(error, webRtcEndpoint) {
if (error) {
return callback(error);
}
return callback(null, webRtcEndpoint);
});
}
function connectMediaElements(webRtcEndpoint, callback) {
webRtcEndpoint.connect(webRtcEndpoint, function(error) {
if (error) {
return callback(error);
}
return callback(null);
});
}
function stop(sessionId) {
if (sessions[sessionId]) {
var pipeline = sessions[sessionId].pipeline;
console.info('Releasing pipeline');
pipeline.release();
delete sessions[sessionId];
delete candidatesQueue[sessionId];
}
}
function onIceCandidate(sessionId, _candidate) {
var candidate = kurento.getComplexType('IceCandidate')(_candidate);
if (sessions[sessionId]) {
console.info('Sending candidate');
const webRtcEndpoint = sessions[sessionId].webRtcEndpoint;
webRtcEndpoint.addIceCandidate(candidate);
}
else {
console.info('Queueing candidate');
if (!candidatesQueue[sessionId]) {
candidatesQueue[sessionId] = [];
}
candidatesQueue[sessionId].push(candidate);
}
}
import kurentoUtils from "kurento-utils";
import socketIOClient from "socket.io-client";
import {
createWebRTCPeer,
sendMessage,
createWebRTCScreenPeer
} from "./common";
const CONSTRAINTS = {
audio: true,
video: {
width: 640,
framerate: 15
}
};
class VideoRoom extends Component {
constructor(props) {
super(props);
this.state = {
startCall: false,
room: "",
clientJoined: false,
email: "",
isLoggedIn: false,
open: false,
screenshare: false,
mute: false
};
this.localStreamRef = React.createRef();
this.remoteStreamRef = React.createRef();
this.handleScreenShare = this.handleScreenShare.bind(this);
this.onIceCandidates = this.onIceCandidates.bind(this);
this.screenOnIceCandidate = this.screenOnIceCandidate.bind(this);
this.handleStartSharing = this.handleStartSharing.bind(this);
this.handleError = this.handleError.bind(this);
this.socket = null;
this.webRTC = null;
this.loginName = null;
}
handleError = (e)=> {
console.log(e);
}
onIceCandidates(candidate) {
console.log("candidateeeeeeeee", this.socket);
sendMessage(
{
event: "iceCandidate",
data: candidate
},
this.socket
);
}
componentDidMount() {
this.socket = new socketIOClient("http://localhost:8443/sockets");
this.webRtcPeer = null;
this.webRtcScreenPeer = null;
const { state } = this.props.location;
if (state && state.interviewId) {
this.initiateSocket();
}
}
initiateSocket() {
const { interviewId } = this.props.location.state;
this.socket.emit("room:addUser", { interviewId, userEmail: this.state.email });
this.socket.on("ICE_CANDIDATE", async candidate => {
console.log("candidate in listener", candidate);
await this.webRTC.addIceCandidate(candidate);
});
this.socket.on("RTC:PEER", room => {
console.log("RTC:PEER", room, this.localStreamRef);
this.webRtcPeer = createWebRTCPeer(
{
localVideo: this.localStreamRef.current,
remoteVideo: this.remoteStreamRef.current,
onicecandidate: this.onIceCandidates
},
this.socket,
room
);
});
this.socket.on("client:joined", () => {
this.setState({ clientJoined: true });
});
this.socket.on("iceCandidate", (candidate) => {
console.log("GOT Candidate....");
this.webRtcPeer.addIceCandidate(candidate);
});
this.socket.on("answer", answer => {
console.log("GOT ANSWER....");
this.webRtcPeer.processAnswer(answer);
});
this.socket.on("remote:leave", () => {
console.log("LEAVE FROM REMOTE");
this.handleLeaveRoom(true);
this.setState({ clientJoined: false });
});
this.socket.on("ERROR", error => this.onError(error));
}
componentWillUnmount() {
this.socket.emit('end');
this.socket = null;
this.webRtcPeer && this.webRtcPeer.dispose();
this.webRtcPeer = null;
}
onError = error => console.error(error);
handleLeaveRoom = (remote = false) => {
if (remote) {
this.remoteStreamRef.current.srcObject = null;
} else if (
this.webRtcPeer !== null &&
this.webRtcPeer !== undefined &&
this.socket !== null
) {
this.localStreamRef.current.srcObject = null;
this.props.history.push("/interivew-id");
} else {
return ;
}
};
render() {
return (
<React.Fragment>
<Wrapper>
<Studio
{...this.state}
interviewer={this.localStreamRef}
interviewee={this.remoteStreamRef}
/>
<Controls
handleLeaveRoom={() => this.handleLeaveRoom()}
handleMute={() => this.handleMute()}
mute={this.state.mute}
handleScreenShare={this.handleScreenShare}
/>
</Wrapper>
</React.Fragment>
);
}
}
export default withRouter(VideoRoom);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment