import { BUNDLE_POLICY, HANDSHAKE_PROGRESS, PEER_TYPE } from '../../../constants';
import Skylink from '../../../index';
import logger from '../../../logger';
import callbacks from './callbacks/index';
import { dispatchEvent } from '../../../utils/skylinkEventManager';
import { handshakeProgress } from '../../../skylink-events';
import { updateRemoveStream } from '../../../compatibility/index';
const createNativePeerConnection = (targetMid, constraints, optional, hasScreenShare, currentRoom) => {
const initOptions = Skylink.getInitOptions();
const state = Skylink.getSkylinkState(currentRoom.id);
const { AdapterJS } = window;
logger.log.DEBUG([targetMid, 'RTCPeerConnection', null, 'Creating peer connection ->'], {
constraints,
optional,
});
const { RTCPeerConnection, msRTCPeerConnection } = window;
const rtcPeerConnection = new (initOptions.useEdgeWebRTC && msRTCPeerConnection ? window.msRTCPeerConnection : RTCPeerConnection)(constraints, optional);
const callbackExtraParams = [rtcPeerConnection, targetMid, state];
// attributes (added on by Temasys)
rtcPeerConnection.setOffer = '';
rtcPeerConnection.setAnswer = '';
rtcPeerConnection.negotiating = false;
rtcPeerConnection.hasStream = false;
rtcPeerConnection.hasMainChannel = false;
rtcPeerConnection.firefoxStreamId = '';
rtcPeerConnection.processingLocalSDP = false;
rtcPeerConnection.processingRemoteSDP = false;
rtcPeerConnection.gathered = false;
rtcPeerConnection.gathering = false;
rtcPeerConnection.localStream = null;
rtcPeerConnection.localStreamId = null;
// Used for safari 11
rtcPeerConnection.iceConnectionStateClosed = false;
rtcPeerConnection.signalingStateClosed = false;
// candidates
state.gatheredCandidates[targetMid] = {
sending: { host: [], srflx: [], relay: [] },
receiving: { host: [], srflx: [], relay: [] },
};
// self._streamsSession[targetMid] = self._streamsSession[targetMid] || {}; from SkylinkJS
state.peerEndOfCandidatesCounter[targetMid] = state.peerEndOfCandidatesCounter[targetMid] || {};
state.sdpSessions[targetMid] = { local: {}, remote: {} };
state.peerBandwidth[targetMid] = {};
// state.peerStats[targetMid] = {}; // initialised only after peerConnationStatus === 'completed'
// FIXME: ESS-1620 - To check if still needed
if (targetMid === PEER_TYPE.MCU) {
logger.log.INFO('Creating an empty transceiver of kind video with MCU');
if (typeof rtcPeerConnection.addTransceiver === 'function') {
rtcPeerConnection.addTransceiver('video');
}
}
Skylink.setSkylinkState(state, currentRoom.id);
if (AdapterJS.webrtcDetectedBrowser === 'firefox') {
rtcPeerConnection.removeStream = updateRemoveStream(rtcPeerConnection);
}
/* CALLBACKS */
rtcPeerConnection.ontrack = callbacks.ontrack.bind(rtcPeerConnection, ...callbackExtraParams);
rtcPeerConnection.ondatachannel = callbacks.ondatachannel.bind(rtcPeerConnection, ...callbackExtraParams);
rtcPeerConnection.onicecandidate = callbacks.onicecandidate.bind(rtcPeerConnection, ...callbackExtraParams);
rtcPeerConnection.oniceconnectionstatechange = callbacks.oniceconnectionstatechange.bind(rtcPeerConnection, ...callbackExtraParams);
rtcPeerConnection.onsignalingstatechange = callbacks.onsignalingstatechange.bind(rtcPeerConnection, ...callbackExtraParams);
rtcPeerConnection.onicegatheringstatechange = callbacks.onicegatheringstatechange.bind(rtcPeerConnection, ...callbackExtraParams);
return rtcPeerConnection;
};
/**
* Function that creates the Peer Connection.
* @param {JSON} params
* @return {RTCPeerConnection} peerConnection
* @memberOf PeerConnection.PeerConnectionHelpers
* @fires handshakeProgress
*/
const createPeerConnection = (params) => {
let peerConnection = null;
const {
currentRoom,
targetMid,
cert,
hasScreenShare,
} = params;
const initOptions = Skylink.getInitOptions();
const { filterCandidatesType } = initOptions;
const state = Skylink.getSkylinkState(currentRoom.id);
const {
peerConnectionConfig,
room,
} = state;
const constraints = {
iceServers: state.room.connection.peerConfig.iceServers,
iceTransportPolicy: filterCandidatesType.host && filterCandidatesType.srflx && !filterCandidatesType.relay ? 'relay' : 'all',
bundlePolicy: peerConnectionConfig.bundlePolicy === BUNDLE_POLICY.NONE ? BUNDLE_POLICY.BALANCED : peerConnectionConfig.bundlePolicy,
rtcpMuxPolicy: peerConnectionConfig.rtcpMuxPolicy,
iceCandidatePoolSize: peerConnectionConfig.iceCandidatePoolSize,
};
const optional = {
optional: [
{ DtlsSrtpKeyAgreement: true },
{ googIPv6: true },
],
};
if (cert) {
constraints.certificates = [cert];
}
if (state.peerConnStatus[targetMid]) {
state.peerConnStatus[targetMid].constraints = constraints;
state.peerConnStatus[targetMid].optional = optional;
}
Skylink.setSkylinkState(state, currentRoom.id);
try {
peerConnection = createNativePeerConnection(targetMid, constraints, optional, hasScreenShare, currentRoom);
} catch (error) {
logger.log.ERROR([targetMid, null, null, 'Failed creating peer connection:'], error);
peerConnection = null;
dispatchEvent(handshakeProgress({
state: HANDSHAKE_PROGRESS.ERROR,
peerId: targetMid,
error,
room,
}));
}
return peerConnection;
};
export default createPeerConnection;