121 lines
3.9 KiB
JavaScript
121 lines
3.9 KiB
JavaScript
'use strict'
|
|
const User = use('App/Models/User');
|
|
const UserChildUtils = use('App/Utils/UserChildUtils');
|
|
const Call = use('App/Models/Call');
|
|
const IceServer = use('App/Models/IceServer');
|
|
const calls = {};
|
|
|
|
class SignalingController {
|
|
constructor({socket, request, auth, call}) {
|
|
this.callId = socket.topic.split(':')[1];
|
|
this.user = auth.user;
|
|
this.socket = socket;
|
|
this.request = request;
|
|
this.register(call);
|
|
console.log(`User #${this.user.id} connected to call ${this.callId}`);
|
|
}
|
|
register(callModel) {
|
|
if (!calls[this.callId])
|
|
calls[this.callId] = new CallSession(callModel);
|
|
else
|
|
console.log(`Call #${this.callId} Already Found`);
|
|
const callSession = calls[this.callId];
|
|
callSession.registerUser(this.user, this.socket)
|
|
.then(
|
|
success => {
|
|
|
|
})
|
|
.catch(
|
|
error => {
|
|
|
|
});
|
|
}
|
|
|
|
onClose() {
|
|
console.log(`User #${this.user.id} left call ${this.callId}`);
|
|
}
|
|
}
|
|
|
|
class CallSession {
|
|
// states: NEW -> STARTED -> IN_PROGRESS -> ENDED
|
|
constructor(callModel) {
|
|
this.callId = callModel.id;
|
|
this.callModel = callModel;
|
|
this.state = callModel.state;
|
|
this.user_1 = {id: callModel.user_1, socket: null, userModel: null};
|
|
this.user_2 = {id: callModel.user_2, socket: null, userModel: null};
|
|
this.startTime = Date.now();
|
|
this.heartbeat = setInterval(this.onHeartbeat.bind(this), 5000);
|
|
}
|
|
onHeartbeat() {
|
|
console.log(`We have ${Object.keys(calls).length} ongoing calls. Ids=${
|
|
Object.keys(calls)}`)
|
|
console.log(`Heartbeat for call #${this.callId} State: ${this.state}`);
|
|
}
|
|
async registerUser(user, socket) {
|
|
let userIndex = -1;
|
|
if (this.user_1.id === user.id)
|
|
userIndex = 1;
|
|
else if (this.user_2.id === user.id)
|
|
userIndex = 2;
|
|
if (userIndex < 0) return false;
|
|
this[`user_${userIndex}`].userModel = user;
|
|
this[`user_${userIndex}`].socket = socket;
|
|
socket.on('wrtc:sdp:offer', this.onSdpOffer.bind(this));
|
|
socket.on('wrtc:sdp:answer', this.onSdpAnswer.bind(this));
|
|
socket.on('wrtc:ice', this.onIceCandidate.bind(this));
|
|
await this.updateState();
|
|
if (this.state === 'STARTED') await this.sendStandby(socket, userIndex);
|
|
if (this.state === 'IN_PROGRESS') await this.sendStart(socket, userIndex);
|
|
return true;
|
|
}
|
|
async sendStandby(socket, userIndex) {
|
|
const iceServers = (await IceServer.all()).rows.map(i => i.toJSON());
|
|
socket.emit('call:standby', {iceServers, id: userIndex});
|
|
}
|
|
async sendStart(socket, userIndex) {
|
|
const iceServers = (await IceServer.all()).rows.map(i => i.toJSON());
|
|
socket.emit('call:start', {iceServers, id: userIndex});
|
|
}
|
|
async updateState() {
|
|
console.log(`Call #${this.callId} state=${this.state}`);
|
|
switch (this.state) {
|
|
case 'NEW':
|
|
if (this.areAllPartnersConnected())
|
|
this.state = 'IN_PROGRESS';
|
|
else
|
|
this.state = 'STARTED';
|
|
case 'STARTED':
|
|
if (this.areAllPartnersConnected()) this.state = 'IN_PROGRESS';
|
|
}
|
|
console.log(`Call #${this.callId} state=${this.state}`);
|
|
}
|
|
areAllPartnersConnected() {
|
|
return !!this.user_1.socket && !!this.user_2.socket;
|
|
}
|
|
async onIceCandidate(payload) {
|
|
const {from = id, ice} = payload;
|
|
const to = from === 1 ? 2 : 1;
|
|
this[`user_${to}`].socket.emit('wrtc:ice', {sdp});
|
|
console.log(`[Signal] [onIceCandidate] ${from} -> ${to}`)
|
|
return true;
|
|
}
|
|
async onSdpOffer(payload) {
|
|
const {from = payload.id, sdp} = payload;
|
|
const to = from === 1 ? 2 : 1;
|
|
this[`user_${to}`].socket.emit('wrtc:sdp:offer', {sdp});
|
|
console.log(`[Signal] [onSdpOffer] ${from} -> ${to}`)
|
|
return true;
|
|
}
|
|
|
|
async onSdpAnswer(payload) {
|
|
const {from = payload.id, sdp} = payload;
|
|
const to = from === 1 ? 2 : 1;
|
|
this[`user_${to}`].socket.emit('wrtc:sdp:answer', {sdp});
|
|
console.log(`[Signal] [onSdpAnswer] ${from} -> ${to}`)
|
|
return true;
|
|
}
|
|
}
|
|
|
|
module.exports = SignalingController
|