log state changes in PeerCall

This commit is contained in:
Bruno Windels 2022-03-25 16:53:12 +01:00
parent 4bf171def9
commit 11a9177592

View file

@ -113,10 +113,10 @@ export class PeerCall implements IDisposable {
}, },
onDataChannelChanged(dataChannel: DataChannel | undefined) {}, onDataChannelChanged(dataChannel: DataChannel | undefined) {},
onNegotiationNeeded() { onNegotiationNeeded() {
const log = outer.logItem.child("onNegotiationNeeded"); const promiseCreator = () => {
const promiseCreator = async () => { return outer.logItem.wrap("onNegotiationNeeded", log => {
await outer.handleNegotiation(log); return outer.handleNegotiation(log);
log.finish(); });
}; };
outer.responsePromiseChain = outer.responsePromiseChain?.then(promiseCreator) ?? promiseCreator(); outer.responsePromiseChain = outer.responsePromiseChain?.then(promiseCreator) ?? promiseCreator();
}, },
@ -139,7 +139,7 @@ export class PeerCall implements IDisposable {
} }
this.localMedia = localMedia; this.localMedia = localMedia;
this.direction = CallDirection.Outbound; this.direction = CallDirection.Outbound;
this.setState(CallState.CreateOffer); this.setState(CallState.CreateOffer, log);
for (const t of this.localMedia.tracks) { for (const t of this.localMedia.tracks) {
this.peerConnection.addTrack(t); this.peerConnection.addTrack(t);
} }
@ -155,7 +155,7 @@ export class PeerCall implements IDisposable {
return; return;
} }
this.localMedia = localMedia; this.localMedia = localMedia;
this.setState(CallState.CreateAnswer); this.setState(CallState.CreateAnswer, log);
for (const t of this.localMedia.tracks) { for (const t of this.localMedia.tracks) {
this.peerConnection.addTrack(t); this.peerConnection.addTrack(t);
} }
@ -173,7 +173,7 @@ export class PeerCall implements IDisposable {
try { try {
await this.peerConnection.setLocalDescription(myAnswer); await this.peerConnection.setLocalDescription(myAnswer);
this.setState(CallState.Connecting); this.setState(CallState.Connecting, log);
} catch (err) { } catch (err) {
await log.wrap(`Error setting local description!`, log => { await log.wrap(`Error setting local description!`, log => {
log.catch(err); log.catch(err);
@ -305,7 +305,7 @@ export class PeerCall implements IDisposable {
}; };
if (this._state === CallState.CreateOffer) { if (this._state === CallState.CreateOffer) {
await this.sendSignallingMessage({type: EventType.Invite, content}, log); await this.sendSignallingMessage({type: EventType.Invite, content}, log);
this.setState(CallState.InviteSent); this.setState(CallState.InviteSent, log);
} else if (this._state === CallState.Connected || this._state === CallState.Connecting) { } else if (this._state === CallState.Connected || this._state === CallState.Connecting) {
// send Negotiate message // send Negotiate message
//await this.sendSignallingMessage({type: EventType.Invite, content}); //await this.sendSignallingMessage({type: EventType.Invite, content});
@ -317,14 +317,16 @@ export class PeerCall implements IDisposable {
this.sendCandidateQueue(log); this.sendCandidateQueue(log);
if (this._state === CallState.InviteSent) { await log.wrap("invite timeout", async log => {
try { await this.delay(CALL_TIMEOUT_MS); }
catch (err) { return; }
// @ts-ignore TS doesn't take the await above into account to know that the state could have changed in between
if (this._state === CallState.InviteSent) { if (this._state === CallState.InviteSent) {
this._hangup(CallErrorCode.InviteTimeout, log); try { await this.delay(CALL_TIMEOUT_MS); }
catch (err) { return; }
// @ts-ignore TS doesn't take the await above into account to know that the state could have changed in between
if (this._state === CallState.InviteSent) {
this._hangup(CallErrorCode.InviteTimeout, log);
}
} }
} });
}; };
private async handleInviteGlare(content: MCallInvite<MCallBase>, partyId: PartyId, log: ILogItem): Promise<void> { private async handleInviteGlare(content: MCallInvite<MCallBase>, partyId: PartyId, log: ILogItem): Promise<void> {
@ -398,7 +400,7 @@ export class PeerCall implements IDisposable {
return; return;
} }
this.setState(CallState.Ringing); this.setState(CallState.Ringing, log);
try { await this.delay(content.lifetime ?? CALL_TIMEOUT_MS); } try { await this.delay(content.lifetime ?? CALL_TIMEOUT_MS); }
catch (err) { return; } catch (err) { return; }
@ -406,7 +408,7 @@ export class PeerCall implements IDisposable {
if (this._state === CallState.Ringing) { if (this._state === CallState.Ringing) {
log.log(`Invite has expired. Hanging up.`); log.log(`Invite has expired. Hanging up.`);
this.hangupParty = CallParty.Remote; // effectively this.hangupParty = CallParty.Remote; // effectively
this.setState(CallState.Ended); this.setState(CallState.Ended, log);
this.stopAllMedia(); this.stopAllMedia();
if (this.peerConnection.signalingState != 'closed') { if (this.peerConnection.signalingState != 'closed') {
this.peerConnection.close(); this.peerConnection.close();
@ -428,7 +430,7 @@ export class PeerCall implements IDisposable {
this.opponentPartyId = partyId; this.opponentPartyId = partyId;
await this.addBufferedIceCandidates(log); await this.addBufferedIceCandidates(log);
this.setState(CallState.Connecting); this.setState(CallState.Connecting, log);
const sdpStreamMetadata = content[SDPStreamMetadataKey]; const sdpStreamMetadata = content[SDPStreamMetadataKey];
if (sdpStreamMetadata) { if (sdpStreamMetadata) {
@ -449,7 +451,6 @@ export class PeerCall implements IDisposable {
} }
private handleIceGatheringState(state: RTCIceGatheringState, log: ILogItem) { private handleIceGatheringState(state: RTCIceGatheringState, log: ILogItem) {
log.set("state", state);
if (state === 'complete' && !this.sentEndOfCandidates) { if (state === 'complete' && !this.sentEndOfCandidates) {
// If we didn't get an empty-string candidate to signal the end of candidates, // If we didn't get an empty-string candidate to signal the end of candidates,
// create one ourselves now gathering has finished. // create one ourselves now gathering has finished.
@ -712,15 +713,12 @@ export class PeerCall implements IDisposable {
if (this._state === CallState.Ended) { if (this._state === CallState.Ended) {
return; // because ICE can still complete as we're ending the call return; // because ICE can still complete as we're ending the call
} }
log.log(
"ICE connection state changed to: " + state,
);
// ideally we'd consider the call to be connected when we get media but // ideally we'd consider the call to be connected when we get media but
// chrome doesn't implement any of the 'onstarted' events yet // chrome doesn't implement any of the 'onstarted' events yet
if (state == 'connected') { if (state == 'connected') {
this.iceDisconnectedTimeout?.abort(); this.iceDisconnectedTimeout?.abort();
this.iceDisconnectedTimeout = undefined; this.iceDisconnectedTimeout = undefined;
this.setState(CallState.Connected); this.setState(CallState.Connected, log);
} else if (state == 'failed') { } else if (state == 'failed') {
this.iceDisconnectedTimeout?.abort(); this.iceDisconnectedTimeout?.abort();
this.iceDisconnectedTimeout = undefined; this.iceDisconnectedTimeout = undefined;
@ -733,15 +731,18 @@ export class PeerCall implements IDisposable {
} }
}; };
private setState(state: CallState): void { private setState(state: CallState, log: ILogItem): void {
const oldState = this._state; if (state !== this._state) {
this._state = state; log.log({l: "change state", status: state, oldState: this._state});
let deferred = this.statePromiseMap.get(state); const oldState = this._state;
if (deferred) { this._state = state;
deferred.resolve(); let deferred = this.statePromiseMap.get(state);
this.statePromiseMap.delete(state); if (deferred) {
deferred.resolve();
this.statePromiseMap.delete(state);
}
this.options.emitUpdate(this, undefined);
} }
this.options.emitUpdate(this, undefined);
} }
private waitForState(states: CallState[]): Promise<void> { private waitForState(states: CallState[]): Promise<void> {