UNPKG

@virusonic/react-native-sdk

Version:

234 lines (204 loc) 7.3 kB
var Constants = require('../util/datatype'); const RTCPeerConnection = require('../dependencies').RTCPeerConnection; const RTCSessionDescription = require('../dependencies').RTCSessionDescription; const RTCIceCandidate = require('../dependencies').RTCIceCandidate; function WebRTCWorker(options, isVideo, isAudio) { EventBus.apply(this, arguments); var me = this; me._options = options; me._connectionState = Constants.ConnectionState.new; me._waitAnswer = false; me._remoteNewSDPInfo = false; me.pcConfig = { iceServers: _prepareIceServers([...options.STUN_SERVERS, ...options.TURN_SERVERS]) }; me._iceCandidates = []; me._destroyed = false; console.log("PC CONFIG", me.pcConfig); me._pc = new RTCPeerConnection(me.pcConfig); me._pc.addEventListener('icecandidate', event => { if (me._destroyed) { return; } if (event.candidate) { me.post(Constants.WorkerEvent.iceCandidate, [event.candidate]); } }); me._pc.addEventListener("track", (event) => { if (me._destroyed) { return; } me.post(Constants.WorkerEvent.onTrack, [event]); }); me._pc.addEventListener("iceconnectionstatechange", (ev) => { if (me._destroyed) { return; } switch (me._pc.iceConnectionState) { case 'checking': me._connectionState = Constants.ConnectionState.connecting; break; case 'connected': me._connectionState = Constants.ConnectionState.connected; break; case 'completed': me._connectionState = Constants.ConnectionState.completed; break; case 'failed': me._connectionState = Constants.ConnectionState.failed; break; case 'disconnected': me._connectionState = Constants.ConnectionState.disconnected; break; default: break; } me.post(Constants.WorkerEvent.connectionState, [me._connectionState]); }); me._pc.addEventListener("signalingstatechange", (ev) => { if (me._destroyed) { return; } if (me._pc.signalingState === 'stable' && me._iceCandidates.length > 0) { me._iceCandidates.forEach(ic => { me.addIceCandidate(ic); }) me._iceCandidates = []; } }); me._localSessionInfo = null; me._remoteSessionInfo = null; } WebRTCWorker.prototype = Object.create(EventBus.prototype); WebRTCWorker.prototype.constructor = WebRTCWorker; WebRTCWorker.prototype.startConnectivity = function (stream) { var me = this; if (stream) { //todo warning if stream already exist me._stream = stream; } if (me._remoteNewSDPInfo) { me._remoteNewSDPInfo = false; // change connectionState for waitConnectivity return false me._connectionState = Constants.ConnectionState.connecting; if (Constants.SessionInfoType.offer === me._remoteSessionInfo.sdpInfo.type) { return me.createAnswer(me._stream); } else { //todo add check if wee receive answer, but offer does not created - create offer return Promise.resolve(); } } else if (!me._waitAnswer) { return me.createOffer(me._stream); } }; WebRTCWorker.prototype.waitConnectivity = function() { var me = this; console.log("AAAA", me._remoteNewSDPInfo, me._connectionState === Constants.ConnectionState.new, !me._waitAnswer); return me._remoteNewSDPInfo || (me._connectionState === Constants.ConnectionState.new && !me._waitAnswer); }; WebRTCWorker.prototype.setRemoteSessionInfo = function (sessionInfo) { var me = this; me._remoteSessionInfo = sessionInfo; me._remoteNewSDPInfo = true; me._waitAnswer = false; if (me._remoteSessionInfo.tracksInfo) { me.post(Constants.WorkerEvent.trackInfo, [me._remoteSessionInfo.tracksInfo]); } return me._pc.setRemoteDescription(new RTCSessionDescription(me._remoteSessionInfo.sdpInfo)).then(() => { if (sessionInfo.extraSDPInfo) { me.addExtraSdpInfo(sessionInfo.extraSDPInfo); } }); }; WebRTCWorker.prototype.addExtraSdpInfo = function (extraSDPInfo) { var me = this; extraSDPInfo.iceCandidates.forEach(ic => { if (me._pc.signalingState === 'stable') { me.addIceCandidate(ic); } else { me._iceCandidates.push(ic); } }) }; WebRTCWorker.prototype.destroy = function (msg) { var me = this; if (me._pc) { me._pc.close(); } me._destroyed = true; }; WebRTCWorker.prototype.createOffer = function (stream) { var me = this; if (me._pc !== null) { stream.getTracks().forEach(track => { me._pc.addTrack(track); }); return me._pc.createOffer({ optional: [], mandatory: {OfferToReceiveAudio: true, OfferToReceiveVideo: true} }) .then(sdpInfo => { let localSessionInfo = me.gotLocalDescription(sdpInfo); me._waitAnswer = true; return localSessionInfo; }); } }; WebRTCWorker.prototype.createAnswer = function (stream) { var me = this; if (me._pc !== null) { stream.getTracks().forEach(track => { me._pc.addTrack(track, stream); }); return me._pc.createAnswer({mandatory: {OfferToReceiveAudio: true, OfferToReceiveVideo: true}}) .then(sdpInfo => { let localSessionInfo = me.gotLocalDescription(sdpInfo); return localSessionInfo; }); } }; WebRTCWorker.prototype.gotLocalDescription = function (sdpInfo) { var me = this; me._pc.setLocalDescription(sdpInfo); me._localSessionInfo = {sdpInfo: sdpInfo}; if (me._stream) { me._localSessionInfo.tracksInfo = []; me._stream.getTracks().forEach(track => { const trackInfo = {id: track.id, type: track.kind, enabled: track.enabled}; me._localSessionInfo.tracksInfo.push(trackInfo); }); } return me._localSessionInfo; }; WebRTCWorker.prototype.addIceCandidate = function (iceCandidate) { var me = this; me._pc.addIceCandidate(new RTCIceCandidate(iceCandidate), () => { }, error => { console.log("Error on 'addIceCandidate': " + error); }); } function _prepareIceServers(iceServers) { const iceServersCopy = cloneObject(iceServers); Object.keys(iceServersCopy).forEach((c, i, a) => { if (iceServersCopy[i].hasOwnProperty('url')) { iceServersCopy[i].urls = iceServersCopy[i].url; } else { iceServersCopy[i].url = iceServersCopy[i].urls; } }); return iceServersCopy; } function cloneObject(obj = {}, escapeNull = false) { try { const json = JSON.stringify(obj) const jsonObject = escapeNull ? json.replace(/null/g, "\"\"") : json return JSON.parse(jsonObject) } catch (error) { return obj } } module.exports = WebRTCWorker;