fix toggling input source and off in video calls

pull/1969/head
Audric Ackermann 4 years ago
parent fbd51c2974
commit a629985a4f
No known key found for this signature in database
GPG Key ID: 999F434D76324AD4

@ -18,25 +18,14 @@ export async function handleCallMessage(
const sentTimestamp = _.toNumber(envelope.timestamp); const sentTimestamp = _.toNumber(envelope.timestamp);
const { type } = callMessage; const { type } = callMessage;
switch (type) {
case SignalService.CallMessage.Type.END_CALL: if (type === SignalService.CallMessage.Type.PROVISIONAL_ANSWER) {
window.log.info('handling callMessage END_CALL'); await removeFromCache(envelope);
break;
case SignalService.CallMessage.Type.ANSWER: window.log.info('Skipping callMessage PROVISIONAL_ANSWER');
window.log.info('handling callMessage ANSWER'); return;
break;
case SignalService.CallMessage.Type.ICE_CANDIDATES:
window.log.info('handling callMessage ICE_CANDIDATES');
break;
case SignalService.CallMessage.Type.OFFER:
window.log.info('handling callMessage OFFER');
break;
case SignalService.CallMessage.Type.PROVISIONAL_ANSWER:
window.log.info('handling callMessage PROVISIONAL_ANSWER');
break;
default:
window.log.info('handling callMessage unknown');
} }
if (type === SignalService.CallMessage.Type.OFFER) { if (type === SignalService.CallMessage.Type.OFFER) {
if (Math.max(sentTimestamp - (Date.now() - currentOffset)) > TTL_DEFAULT.CALL_MESSAGE) { if (Math.max(sentTimestamp - (Date.now() - currentOffset)) > TTL_DEFAULT.CALL_MESSAGE) {
window?.log?.info('Dropping incoming OFFER callMessage sent a while ago: ', sentTimestamp); window?.log?.info('Dropping incoming OFFER callMessage sent a while ago: ', sentTimestamp);
@ -46,7 +35,7 @@ export async function handleCallMessage(
} }
await removeFromCache(envelope); await removeFromCache(envelope);
await CallManager.handleOfferCallMessage(sender, callMessage, sentTimestamp); await CallManager.handleCallTypeOffer(sender, callMessage, sentTimestamp);
return; return;
} }
@ -54,7 +43,7 @@ export async function handleCallMessage(
if (type === SignalService.CallMessage.Type.END_CALL) { if (type === SignalService.CallMessage.Type.END_CALL) {
await removeFromCache(envelope); await removeFromCache(envelope);
CallManager.handleEndCallMessage(sender); CallManager.handleCallTypeEndCall(sender);
return; return;
} }
@ -62,19 +51,19 @@ export async function handleCallMessage(
if (type === SignalService.CallMessage.Type.ANSWER) { if (type === SignalService.CallMessage.Type.ANSWER) {
await removeFromCache(envelope); await removeFromCache(envelope);
await CallManager.handleCallAnsweredMessage(sender, callMessage); await CallManager.handleCallTypeAnswer(sender, callMessage);
return; return;
} }
if (type === SignalService.CallMessage.Type.ICE_CANDIDATES) { if (type === SignalService.CallMessage.Type.ICE_CANDIDATES) {
await removeFromCache(envelope); await removeFromCache(envelope);
await CallManager.handleIceCandidatesMessage(sender, callMessage); await CallManager.handleCallTypeIceCandidates(sender, callMessage);
return; return;
} }
await removeFromCache(envelope); await removeFromCache(envelope);
// if this another type of call message, just add it to the manager // if this another type of call message, just add it to the manager
await CallManager.handleOtherCallMessage(sender, callMessage); await CallManager.handleOtherCallTypes(sender, callMessage);
} }

@ -32,7 +32,7 @@ export function removeMessagePadding(paddedData: ArrayBuffer): ArrayBuffer {
* @param messageBuffer The buffer to add padding to. * @param messageBuffer The buffer to add padding to.
*/ */
export function addMessagePadding(messageBuffer: Uint8Array): Uint8Array { export function addMessagePadding(messageBuffer: Uint8Array): Uint8Array {
window?.log?.info('Adding message padding...'); // window?.log?.info('Adding message padding...');
const plaintext = new Uint8Array(getPaddedMessageLength(messageBuffer.byteLength + 1) - 1); const plaintext = new Uint8Array(getPaddedMessageLength(messageBuffer.byteLength + 1) - 1);
plaintext.set(new Uint8Array(messageBuffer)); plaintext.set(new Uint8Array(messageBuffer));

@ -44,7 +44,7 @@ export function getLatestTimestampOffset() {
window.log.warn('latestTimestampOffset is not set yet'); window.log.warn('latestTimestampOffset is not set yet');
return 0; return 0;
} }
window.log.info('latestTimestampOffset is ', latestTimestampOffset); // window.log.info('latestTimestampOffset is ', latestTimestampOffset);
return latestTimestampOffset; return latestTimestampOffset;
} }

@ -19,6 +19,9 @@ import { getMessageQueue } from '../sending';
import { PubKey } from '../types'; import { PubKey } from '../types';
export type InputItem = { deviceId: string; label: string }; export type InputItem = { deviceId: string; label: string };
// const VIDEO_WIDTH = 640;
// const VIDEO_RATIO = 16 / 9;
type CallManagerListener = type CallManagerListener =
| (( | ((
localStream: MediaStream | null, localStream: MediaStream | null,
@ -48,6 +51,7 @@ const callCache = new Map<string, Array<SignalService.CallMessage>>();
let peerConnection: RTCPeerConnection | null; let peerConnection: RTCPeerConnection | null;
let remoteStream: MediaStream | null; let remoteStream: MediaStream | null;
let mediaDevices: MediaStream | null; let mediaDevices: MediaStream | null;
const INPUT_DISABLED_DEVICE_ID = 'off';
let makingOffer = false; let makingOffer = false;
let ignoreOffer = false; let ignoreOffer = false;
@ -87,61 +91,101 @@ navigator.mediaDevices.addEventListener('devicechange', async () => {
async function updateInputLists() { async function updateInputLists() {
// Get the set of cameras connected // Get the set of cameras connected
const videoCameras = await getConnectedDevices('videoinput'); const videoCameras = await getConnectedDevices('videoinput');
camerasList = videoCameras.map(m => ({
deviceId: m.deviceId, camerasList = [{ deviceId: INPUT_DISABLED_DEVICE_ID, label: 'Off' }].concat(
label: m.label, videoCameras.map(m => ({
})); deviceId: m.deviceId,
label: m.label,
}))
);
// Get the set of audio inputs connected // Get the set of audio inputs connected
const audiosInput = await getConnectedDevices('audioinput'); const audiosInput = await getConnectedDevices('audioinput');
audioInputsList = audiosInput.map(m => ({ audioInputsList = [{ deviceId: INPUT_DISABLED_DEVICE_ID, label: 'Off' }].concat(
deviceId: m.deviceId, audiosInput.map(m => ({
label: m.label, deviceId: m.deviceId,
})); label: m.label,
}))
);
} }
export async function selectCameraByDeviceId(cameraDeviceId: string) { export async function selectCameraByDeviceId(cameraDeviceId: string) {
console.warn('selecting cameraDeviceId ', cameraDeviceId);
if (camerasList.some(m => m.deviceId === cameraDeviceId)) { if (camerasList.some(m => m.deviceId === cameraDeviceId)) {
selectedCameraId = cameraDeviceId; selectedCameraId = cameraDeviceId;
try { if (selectedCameraId === INPUT_DISABLED_DEVICE_ID) {
mediaDevices = await openMediaDevices({ const sender = peerConnection?.getSenders().find(s => {
audioInputId: selectedAudioInputId, return s.track?.kind === 'video';
cameraId: selectedCameraId,
}); });
if (sender?.track) {
sender.track.enabled = false;
}
return;
}
const devicesConfig = {
video: {
deviceId: selectedCameraId ? { exact: selectedCameraId } : undefined,
// width: VIDEO_WIDTH,
// height: Math.floor(VIDEO_WIDTH * VIDEO_RATIO),
},
};
mediaDevices.getTracks().map((track: MediaStreamTrack) => { try {
window.log.info('selectCameraByDeviceId adding track: ', track); const newVideoStream = await navigator.mediaDevices.getUserMedia(devicesConfig);
if (mediaDevices) { const videoTrack = newVideoStream.getVideoTracks()[0];
peerConnection?.addTrack(track, mediaDevices); if (!peerConnection) {
} throw new Error('cannot selectCameraByDeviceId without a peer connection');
}
const sender = peerConnection.getSenders().find(s => {
return s.track?.kind === videoTrack.kind;
}); });
callVideoListener(); if (sender) {
} catch (err) { await sender.replaceTrack(videoTrack);
console.warn('err', err); videoTrack.enabled = true;
mediaDevices?.getVideoTracks().forEach(t => {
t.stop();
mediaDevices?.removeTrack(t);
});
mediaDevices?.addTrack(videoTrack);
} else {
throw new Error('Failed to get sender for selectCameraByDeviceId ');
}
} catch (e) {
window.log.warn('selectCameraByDeviceId failed with', e.message);
} }
} }
} }
export async function selectAudioInputByDeviceId(audioInputDeviceId: string) { export async function selectAudioInputByDeviceId(audioInputDeviceId: string) {
console.warn('selecting audioInputDeviceId', audioInputDeviceId);
if (audioInputsList.some(m => m.deviceId === audioInputDeviceId)) { if (audioInputsList.some(m => m.deviceId === audioInputDeviceId)) {
selectedAudioInputId = audioInputDeviceId; selectedAudioInputId = audioInputDeviceId;
const devicesConfig = {
audio: {
deviceId: selectedAudioInputId ? { exact: selectedAudioInputId } : undefined,
},
};
try { try {
mediaDevices = await openMediaDevices({ const newAudioStream = await navigator.mediaDevices.getUserMedia(devicesConfig);
audioInputId: selectedAudioInputId, const audioTrack = newAudioStream.getAudioTracks()[0];
cameraId: selectedCameraId, if (!peerConnection) {
throw new Error('cannot selectAudioInputByDeviceId without a peer connection');
}
const sender = peerConnection.getSenders().find(s => {
return s.track?.kind === audioTrack.kind;
}); });
mediaDevices.getTracks().map((track: MediaStreamTrack) => { if (sender) {
window.log.info('selectAudioInputByDeviceId adding track: ', track); await sender.replaceTrack(audioTrack);
if (mediaDevices) { mediaDevices?.getAudioTracks().forEach(t => {
peerConnection?.addTrack(track, mediaDevices); t.stop();
} mediaDevices?.removeTrack(t);
}); });
callVideoListener(); mediaDevices?.addTrack(audioTrack);
} catch (err) { } else {
console.warn('err', err); throw new Error('Failed to get sender for selectAudioInputByDeviceId ');
}
} catch (e) {
window.log.warn('selectAudioInputByDeviceId failed with', e.message);
} }
} }
} }
@ -151,14 +195,13 @@ async function handleNegotiationNeededEvent(event: Event, recipient: string) {
try { try {
makingOffer = true; makingOffer = true;
const offer = await peerConnection?.createOffer(); const offer = await peerConnection?.createOffer();
if (!offer) { if (!offer) {
throw new Error('Could not create offer in handleNegotiationNeededEvent'); throw new Error('Could not create offer in handleNegotiationNeededEvent');
} }
await peerConnection?.setLocalDescription(offer); await peerConnection?.setLocalDescription(offer);
if (offer && offer.sdp) { if (offer && offer.sdp) {
const negotationOfferMessage = new CallMessage({ const offerMessage = new CallMessage({
timestamp: Date.now(), timestamp: Date.now(),
type: SignalService.CallMessage.Type.OFFER, type: SignalService.CallMessage.Type.OFFER,
sdps: [offer.sdp], sdps: [offer.sdp],
@ -167,10 +210,10 @@ async function handleNegotiationNeededEvent(event: Event, recipient: string) {
window.log.info('sending OFFER MESSAGE'); window.log.info('sending OFFER MESSAGE');
const negotationOfferSendResult = await getMessageQueue().sendToPubKeyNonDurably( const negotationOfferSendResult = await getMessageQueue().sendToPubKeyNonDurably(
PubKey.cast(recipient), PubKey.cast(recipient),
negotationOfferMessage offerMessage
); );
if (typeof negotationOfferSendResult === 'number') { if (typeof negotationOfferSendResult === 'number') {
window.log?.warn('setting last sent timestamp'); // window.log?.warn('setting last sent timestamp');
lastOutgoingOfferTimestamp = negotationOfferSendResult; lastOutgoingOfferTimestamp = negotationOfferSendResult;
} }
} }
@ -188,25 +231,47 @@ function handleIceCandidates(event: RTCPeerConnectionIceEvent, pubkey: string) {
} }
} }
// tslint:disable-next-line: function-name async function openMediaDevicesAndAddTracks() {
export async function USER_callRecipient(recipient: string) {
await updateInputLists();
window?.log?.info(`starting call with ${ed25519Str(recipient)}..`);
window.inboxStore?.dispatch(startingCallWith({ pubkey: recipient }));
if (peerConnection) {
window.log.info('closing existing peerconnection');
peerConnection.close();
peerConnection = null;
}
peerConnection = new RTCPeerConnection(configuration);
try { try {
mediaDevices = await openMediaDevices({}); await updateInputLists();
if (!camerasList.length) {
ToastUtils.pushNoCameraFound();
return;
}
if (!audioInputsList.length) {
ToastUtils.pushNoAudioInputFound();
return;
}
mediaDevices.getTracks().map((track: any) => { const firstAudio = audioInputsList[0].deviceId;
window.log.info('USER_callRecipient adding track: ', track); const firstVideo = camerasList[0].deviceId;
window.log.info(`openMediaDevices video:${firstVideo} audio:${firstAudio}`);
const devicesConfig = {
audio: {
deviceId: firstAudio,
echoCancellation: true,
},
video: {
deviceId: firstVideo,
// width: VIDEO_WIDTH,
// height: Math.floor(VIDEO_WIDTH * VIDEO_RATIO),
},
};
mediaDevices = await navigator.mediaDevices.getUserMedia(devicesConfig);
mediaDevices.getTracks().map(track => {
if (track.kind === 'video') {
track.enabled = false;
}
if (mediaDevices) { if (mediaDevices) {
// FIXME audric why does this fails?
// track.onunmute = () => {
// if (mediaDevices) {
peerConnection?.addTrack(track, mediaDevices); peerConnection?.addTrack(track, mediaDevices);
// }
// };
} }
}); });
} catch (err) { } catch (err) {
@ -215,27 +280,19 @@ export async function USER_callRecipient(recipient: string) {
window.inboxStore?.dispatch(showSettingsSection(SessionSettingCategory.Privacy)); window.inboxStore?.dispatch(showSettingsSection(SessionSettingCategory.Privacy));
}); });
} }
peerConnection.addEventListener('connectionstatechange', () => {
handleConnectionStateChanged(recipient);
});
peerConnection.addEventListener('icecandidate', event => {
handleIceCandidates(event, recipient);
});
peerConnection.onnegotiationneeded = async (event: Event) => {
await handleNegotiationNeededEvent(event, recipient);
};
remoteStream = new MediaStream();
callVideoListener(); callVideoListener();
}
peerConnection.addEventListener('track', event => { // tslint:disable-next-line: function-name
callVideoListener(); export async function USER_callRecipient(recipient: string) {
if (remoteStream) { await updateInputLists();
remoteStream.addTrack(event.track); window?.log?.info(`starting call with ${ed25519Str(recipient)}..`);
} window.inboxStore?.dispatch(startingCallWith({ pubkey: recipient }));
}); if (peerConnection) {
throw new Error('USER_callRecipient peerConnection is already initialized ');
}
peerConnection = createOrGetPeerConnection(recipient);
await openMediaDevicesAndAddTracks();
} }
const iceCandidates: Array<RTCIceCandidate> = new Array(); const iceCandidates: Array<RTCIceCandidate> = new Array();
@ -272,32 +329,6 @@ const iceSenderDebouncer = _.debounce(async (recipient: string) => {
await getMessageQueue().sendToPubKeyNonDurably(PubKey.cast(recipient), callIceCandicates); await getMessageQueue().sendToPubKeyNonDurably(PubKey.cast(recipient), callIceCandicates);
}, 2000); }, 2000);
const openMediaDevices = async ({
audioInputId,
cameraId,
}: {
cameraId?: string;
audioInputId?: string;
}) => {
if (mediaDevices) {
window.log.info('stopping existing tracks in openMediaDevices');
mediaDevices.getTracks().forEach(track => {
track.stop();
});
}
window.log.info('openMediaDevices ', { audioInputId, cameraId });
return navigator.mediaDevices.getUserMedia({
audio: {
deviceId: audioInputId ? { exact: audioInputId } : undefined,
echoCancellation: true,
},
video: {
deviceId: cameraId ? { exact: cameraId } : undefined,
},
});
};
const findLastMessageTypeFromSender = (sender: string, msgType: SignalService.CallMessage.Type) => { const findLastMessageTypeFromSender = (sender: string, msgType: SignalService.CallMessage.Type) => {
const msgCacheFromSender = callCache.get(sender); const msgCacheFromSender = callCache.get(sender);
if (!msgCacheFromSender) { if (!msgCacheFromSender) {
@ -328,6 +359,7 @@ function handleConnectionStateChanged(pubkey: string) {
} }
function closeVideoCall() { function closeVideoCall() {
window.log.info('closingVideoCall ', peerConnection);
if (peerConnection) { if (peerConnection) {
peerConnection.ontrack = null; peerConnection.ontrack = null;
peerConnection.onicecandidate = null; peerConnection.onicecandidate = null;
@ -345,7 +377,7 @@ function closeVideoCall() {
if (remoteStream) { if (remoteStream) {
remoteStream.getTracks().forEach(track => { remoteStream.getTracks().forEach(track => {
track.stop(); remoteStream?.removeTrack(track);
}); });
} }
@ -353,11 +385,46 @@ function closeVideoCall() {
peerConnection = null; peerConnection = null;
} }
mediaDevices = null;
remoteStream = null;
if (videoEventsListener) { if (videoEventsListener) {
videoEventsListener(null, null, [], []); videoEventsListener(null, null, [], []);
} }
} }
function createOrGetPeerConnection(withPubkey: string) {
if (peerConnection) {
return peerConnection;
}
remoteStream = new MediaStream();
peerConnection = new RTCPeerConnection(configuration);
peerConnection.onnegotiationneeded = async (event: Event) => {
await handleNegotiationNeededEvent(event, withPubkey);
};
peerConnection.onsignalingstatechange = handleSignalingStateChangeEvent;
peerConnection.ontrack = event => {
event.track.onunmute = () => {
remoteStream?.addTrack(event.track);
callVideoListener();
};
event.track.onmute = () => {
remoteStream?.removeTrack(event.track);
callVideoListener();
};
};
peerConnection.onconnectionstatechange = () => {
handleConnectionStateChanged(withPubkey);
};
peerConnection.onicecandidate = event => {
handleIceCandidates(event, withPubkey);
};
return peerConnection;
}
// tslint:disable-next-line: function-name // tslint:disable-next-line: function-name
export async function USER_acceptIncomingCallRequest(fromSender: string) { export async function USER_acceptIncomingCallRequest(fromSender: string) {
const msgCacheFromSender = callCache.get(fromSender); const msgCacheFromSender = callCache.get(fromSender);
@ -382,38 +449,12 @@ export async function USER_acceptIncomingCallRequest(fromSender: string) {
window.inboxStore?.dispatch(answerCall({ pubkey: fromSender })); window.inboxStore?.dispatch(answerCall({ pubkey: fromSender }));
if (peerConnection) { if (peerConnection) {
window.log.info('closing existing peerconnection'); throw new Error('USER_acceptIncomingCallRequest: peerConnection is already set.');
peerConnection.close();
peerConnection = null;
} }
peerConnection = new RTCPeerConnection(configuration);
mediaDevices = await openMediaDevices({});
mediaDevices.getTracks().map(track => {
// window.log.info('USER_acceptIncomingCallRequest adding track ', track);
if (mediaDevices) {
peerConnection?.addTrack(track, mediaDevices);
}
});
remoteStream = new MediaStream();
peerConnection.addEventListener('icecandidate', event => { peerConnection = createOrGetPeerConnection(fromSender);
if (event.candidate) {
iceCandidates.push(event.candidate);
void iceSenderDebouncer(fromSender);
}
});
peerConnection.addEventListener('signalingstatechange', handleSignalingStateChangeEvent); await openMediaDevicesAndAddTracks();
callVideoListener();
peerConnection.addEventListener('track', event => {
callVideoListener();
remoteStream?.addTrack(event.track);
});
peerConnection.addEventListener('connectionstatechange', () => {
handleConnectionStateChanged(fromSender);
});
const { sdps } = lastOfferMessage; const { sdps } = lastOfferMessage;
if (!sdps || sdps.length === 0) { if (!sdps || sdps.length === 0) {
@ -430,22 +471,6 @@ export async function USER_acceptIncomingCallRequest(fromSender: string) {
window.log?.error(`Error setting RTC Session Description ${e}`); window.log?.error(`Error setting RTC Session Description ${e}`);
} }
const answer = await peerConnection.createAnswer({
offerToReceiveAudio: true,
offerToReceiveVideo: true,
});
if (!answer?.sdp || answer.sdp.length === 0) {
window.log.warn('failed to create answer');
return;
}
await peerConnection.setLocalDescription(answer);
const answerSdp = answer.sdp;
const callAnswerMessage = new CallMessage({
timestamp: Date.now(),
type: SignalService.CallMessage.Type.ANSWER,
sdps: [answerSdp],
});
const lastCandidatesFromSender = findLastMessageTypeFromSender( const lastCandidatesFromSender = findLastMessageTypeFromSender(
fromSender, fromSender,
SignalService.CallMessage.Type.ICE_CANDIDATES SignalService.CallMessage.Type.ICE_CANDIDATES
@ -461,9 +486,7 @@ export async function USER_acceptIncomingCallRequest(fromSender: string) {
await peerConnection.addIceCandidate(candicate); await peerConnection.addIceCandidate(candicate);
} }
} }
window.log.info('sending ANSWER MESSAGE'); await buildAnswerAndSendIt(fromSender);
await getMessageQueue().sendToPubKeyNonDurably(PubKey.cast(fromSender), callAnswerMessage);
} }
// tslint:disable-next-line: function-name // tslint:disable-next-line: function-name
@ -478,32 +501,80 @@ export async function USER_rejectIncomingCallRequest(fromSender: string) {
window.log.info('sending END_CALL MESSAGE'); window.log.info('sending END_CALL MESSAGE');
await getMessageQueue().sendToPubKeyNonDurably(PubKey.cast(fromSender), endCallMessage); await getMessageQueue().sendToPubKeyNonDurably(PubKey.cast(fromSender), endCallMessage);
const convos = getConversationController().getConversations();
const callingConvos = convos.filter(convo => convo.callState !== undefined);
if (callingConvos.length > 0) {
// we just got a new offer from someone we are already in a call with
if (callingConvos.length === 1 && callingConvos[0].id === fromSender) {
closeVideoCall();
}
}
} }
export function handleEndCallMessage(sender: string) { export function handleCallTypeEndCall(sender: string) {
callCache.delete(sender); callCache.delete(sender);
window.log.info('handling callMessage END_CALL');
if (videoEventsListener) { if (videoEventsListener) {
videoEventsListener(null, null, [], []); videoEventsListener(null, null, [], []);
} }
mediaDevices = null; closeVideoCall();
remoteStream = null;
// //
// FIXME audric trigger UI cleanup // FIXME audric trigger UI cleanup
window.inboxStore?.dispatch(endCall({ pubkey: sender })); window.inboxStore?.dispatch(endCall({ pubkey: sender }));
} }
export async function handleOfferCallMessage( async function buildAnswerAndSendIt(sender: string) {
if (peerConnection) {
const answer = await peerConnection.createAnswer({
offerToReceiveAudio: true,
offerToReceiveVideo: true,
});
if (!answer?.sdp || answer.sdp.length === 0) {
window.log.warn('failed to create answer');
return;
}
await peerConnection.setLocalDescription(answer);
const answerSdp = answer.sdp;
const callAnswerMessage = new CallMessage({
timestamp: Date.now(),
type: SignalService.CallMessage.Type.ANSWER,
sdps: [answerSdp],
});
window.log.info('sending ANSWER MESSAGE');
await getMessageQueue().sendToPubKeyNonDurably(PubKey.cast(sender), callAnswerMessage);
}
}
export async function handleCallTypeOffer(
sender: string, sender: string,
callMessage: SignalService.CallMessage, callMessage: SignalService.CallMessage,
incomingOfferTimestamp: number incomingOfferTimestamp: number
) { ) {
try { try {
window.log.info('handling callMessage OFFER');
const convos = getConversationController().getConversations(); const convos = getConversationController().getConversations();
const callingConvos = convos.filter(convo => convo.callState !== undefined); const callingConvos = convos.filter(convo => convo.callState !== undefined);
if (callingConvos.length > 0) { if (callingConvos.length > 0) {
// we just got a new offer from someone we are already in a call with // we just got a new offer from someone we are already in a call with
if (callingConvos.length === 1 && callingConvos[0].id === sender) { if (callingConvos.length === 1 && callingConvos[0].id === sender) {
window.log.info('Got a new offer message from our ongoing call'); window.log.info('Got a new offer message from our ongoing call');
const remoteDesc = new RTCSessionDescription({
type: 'offer',
sdp: callMessage.sdps[0],
});
if (peerConnection) {
await peerConnection.setRemoteDescription(remoteDesc);
remoteStream?.getTracks().forEach(t => {
remoteStream?.removeTrack(t);
});
await buildAnswerAndSendIt(sender);
}
} else { } else {
await handleMissedCall(sender, incomingOfferTimestamp); await handleMissedCall(sender, incomingOfferTimestamp);
return; return;
@ -549,14 +620,13 @@ async function handleMissedCall(sender: string, incomingOfferTimestamp: number)
return; return;
} }
export async function handleCallAnsweredMessage( export async function handleCallTypeAnswer(sender: string, callMessage: SignalService.CallMessage) {
sender: string,
callMessage: SignalService.CallMessage
) {
if (!callMessage.sdps || callMessage.sdps.length === 0) { if (!callMessage.sdps || callMessage.sdps.length === 0) {
window.log.warn('cannot handle answered message without signal description protols'); window.log.warn('cannot handle answered message without signal description protols');
return; return;
} }
window.log.info('handling callMessage ANSWER');
if (!callCache.has(sender)) { if (!callCache.has(sender)) {
callCache.set(sender, new Array()); callCache.set(sender, new Array());
} }
@ -565,7 +635,7 @@ export async function handleCallAnsweredMessage(
window.inboxStore?.dispatch(answerCall({ pubkey: sender })); window.inboxStore?.dispatch(answerCall({ pubkey: sender }));
const remoteDesc = new RTCSessionDescription({ type: 'answer', sdp: callMessage.sdps[0] }); const remoteDesc = new RTCSessionDescription({ type: 'answer', sdp: callMessage.sdps[0] });
if (peerConnection) { if (peerConnection) {
window.log?.warn('Setting remote answer pending'); // window.log?.info('Setting remote answer pending');
isSettingRemoteAnswerPending = true; isSettingRemoteAnswerPending = true;
await peerConnection.setRemoteDescription(remoteDesc); await peerConnection.setRemoteDescription(remoteDesc);
isSettingRemoteAnswerPending = false; isSettingRemoteAnswerPending = false;
@ -574,7 +644,7 @@ export async function handleCallAnsweredMessage(
} }
} }
export async function handleIceCandidatesMessage( export async function handleCallTypeIceCandidates(
sender: string, sender: string,
callMessage: SignalService.CallMessage callMessage: SignalService.CallMessage
) { ) {
@ -582,12 +652,17 @@ export async function handleIceCandidatesMessage(
window.log.warn('cannot handle iceCandicates message without candidates'); window.log.warn('cannot handle iceCandicates message without candidates');
return; return;
} }
window.log.info('handling callMessage ICE_CANDIDATES');
if (!callCache.has(sender)) { if (!callCache.has(sender)) {
callCache.set(sender, new Array()); callCache.set(sender, new Array());
} }
callCache.get(sender)?.push(callMessage); callCache.get(sender)?.push(callMessage);
// window.inboxStore?.dispatch(incomingCall({ pubkey: sender })); await addIceCandidateToExistingPeerConnection(callMessage);
}
async function addIceCandidateToExistingPeerConnection(callMessage: SignalService.CallMessage) {
if (peerConnection) { if (peerConnection) {
// tslint:disable-next-line: prefer-for-of // tslint:disable-next-line: prefer-for-of
for (let index = 0; index < callMessage.sdps.length; index++) { for (let index = 0; index < callMessage.sdps.length; index++) {
@ -609,9 +684,6 @@ export async function handleIceCandidatesMessage(
} }
// tslint:disable-next-line: no-async-without-await // tslint:disable-next-line: no-async-without-await
export async function handleOtherCallMessage( export async function handleOtherCallTypes(sender: string, callMessage: SignalService.CallMessage) {
sender: string,
callMessage: SignalService.CallMessage
) {
callCache.get(sender)?.push(callMessage); callCache.get(sender)?.push(callMessage);
} }

Loading…
Cancel
Save