Skip to content

Commit

Permalink
Refactor state handling
Browse files Browse the repository at this point in the history
Signed-off-by: Šimon Brandner <simon.bra.ag@gmail.com>
  • Loading branch information
SimonBrandner committed Dec 4, 2022
1 parent 7799804 commit 0af2f79
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 25 deletions.
4 changes: 2 additions & 2 deletions spec/unit/webrtc/call.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1392,7 +1392,7 @@ describe('Call', function() {
it("ends call on onHangupReceived() if state is ringing", async () => {
expect(call.callHasEnded()).toBe(false);

call.state = CallState.Ringing;
(call as any).state = CallState.Ringing;
call.onHangupReceived({} as MCallHangupReject);

expect(call.callHasEnded()).toBe(true);
Expand Down Expand Up @@ -1424,7 +1424,7 @@ describe('Call', function() {
)("ends call on onRejectReceived() if in correct state (state=%s)", async (state: CallState) => {
expect(call.callHasEnded()).toBe(false);

call.state = state;
(call as any).state = state;
call.onRejectReceived({} as MCallHangupReject);

expect(call.callHasEnded()).toBe(
Expand Down
50 changes: 27 additions & 23 deletions src/webrtc/call.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,6 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
public roomId?: string;
public callId: string;
public invitee?: string;
public state = CallState.Fledgling;
public hangupParty?: CallParty;
public hangupReason?: string;
public direction?: CallDirection;
Expand All @@ -346,6 +345,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
// This should be set by the consumer on incoming & outgoing calls.
public isPtt = false;

private _state = CallState.Fledgling;
private readonly client: MatrixClient;
private readonly forceTURN?: boolean;
private readonly turnServers: Array<TurnServer>;
Expand Down Expand Up @@ -482,6 +482,16 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
return this.remoteAssertedIdentity;
}

public get state(): CallState {
return this._state;
}

private set state(state: CallState) {
const oldState = this._state;
this._state = state;
this.emit(CallEvent.State, state, oldState);
}

public get type(): CallType {
return (this.hasLocalUserMediaVideoTrack || this.hasRemoteUserMediaVideoTrack)
? CallType.Video
Expand Down Expand Up @@ -928,15 +938,15 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
return;
}

this.setState(CallState.Ringing);
this.state = CallState.Ringing;

if (event.getLocalAge()) {
// Time out the call if it's ringing for too long
const ringingTimer = setTimeout(() => {
if (this.state == CallState.Ringing) {
logger.debug(`Call ${this.callId} invite has expired. Hanging up.`);
this.hangupParty = CallParty.Remote; // effectively
this.setState(CallState.Ended);
this.state = CallState.Ended;
this.stopAllMedia();
if (this.peerConn!.signalingState != 'closed') {
this.peerConn!.close();
Expand All @@ -963,7 +973,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
// perverse as it may seem, sometimes we want to instantiate a call with a
// hangup message (because when getting the state of the room on load, events
// come in reverse order and we want to remember that a call has been hung up)
this.setState(CallState.Ended);
this.state = CallState.Ended;
}

private shouldAnswerWithMediaType(
Expand Down Expand Up @@ -1004,7 +1014,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
const answerWithAudio = this.shouldAnswerWithMediaType(audio, this.hasRemoteUserMediaAudioTrack, "audio");
const answerWithVideo = this.shouldAnswerWithMediaType(video, this.hasRemoteUserMediaVideoTrack, "video");

this.setState(CallState.WaitLocalMedia);
this.state = CallState.WaitLocalMedia;
this.waitForLocalAVStream = true;

try {
Expand Down Expand Up @@ -1034,7 +1044,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
if (answerWithVideo) {
// Try to answer without video
logger.warn(`Call ${this.callId} Failed to getUserMedia(), trying to getUserMedia() without video`);
this.setState(prevState);
this.state = prevState;
this.waitForLocalAVStream = false;
await this.answer(answerWithAudio, false);
} else {
Expand All @@ -1043,7 +1053,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
}
}
} else if (this.waitForLocalAVStream) {
this.setState(CallState.WaitLocalMedia);
this.state = CallState.WaitLocalMedia;
}
}

Expand Down Expand Up @@ -1495,7 +1505,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
});
}

this.setState(CallState.CreateOffer);
this.state = CallState.CreateOffer;

logger.debug(`Call ${this.callId} gotUserMediaForInvite`);
// Now we wait for the negotiationneeded event
Expand Down Expand Up @@ -1530,7 +1540,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
this.inviteOrAnswerSent = true;
} catch (error) {
// We've failed to answer: back to the ringing state
this.setState(CallState.Ringing);
this.state = CallState.Ringing;
if (error instanceof MatrixError && error.event) this.client.cancelPendingEvent(error.event);

let code = CallErrorCode.SendAnswer;
Expand Down Expand Up @@ -1627,7 +1637,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
this.pushLocalFeed(feed);
}

this.setState(CallState.CreateAnswer);
this.state = CallState.CreateAnswer;

let answer: RTCSessionDescriptionInit;
try {
Expand All @@ -1645,7 +1655,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
// make sure we're still going
if (this.callHasEnded()) return;

this.setState(CallState.Connecting);
this.state = CallState.Connecting;

// Allow a short time for initial candidates to be gathered
await new Promise(resolve => {
Expand Down Expand Up @@ -1762,7 +1772,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
this.chooseOpponent(event);
await this.addBufferedIceCandidates();

this.setState(CallState.Connecting);
this.state = CallState.Connecting;

const sdpStreamMetadata = content[SDPStreamMetadataKey];
if (sdpStreamMetadata) {
Expand Down Expand Up @@ -2034,7 +2044,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
this.sendCandidateQueue();
if (this.state === CallState.CreateOffer) {
this.inviteOrAnswerSent = true;
this.setState(CallState.InviteSent);
this.state = CallState.InviteSent;
this.inviteTimeout = setTimeout(() => {
this.inviteTimeout = undefined;
if (this.state === CallState.InviteSent) {
Expand Down Expand Up @@ -2088,7 +2098,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
// chrome doesn't implement any of the 'onstarted' events yet
if (["connected", "completed"].includes(this.peerConn?.iceConnectionState ?? '')) {
clearTimeout(this.iceDisconnectedTimeout);
this.setState(CallState.Connected);
this.state = CallState.Connected;

if (!this.callLengthInterval) {
this.callLengthInterval = setInterval(() => {
Expand All @@ -2112,7 +2122,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
logger.info(`Hanging up call ${this.callId} (ICE disconnected for too long)`);
this.hangup(CallErrorCode.IceFailed, false);
}, 30 * 1000);
this.setState(CallState.Connecting);
this.state = CallState.Connecting;
}

// In PTT mode, override feed status to muted when we lose connection to
Expand Down Expand Up @@ -2244,12 +2254,6 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
this.terminate(CallParty.Remote, CallErrorCode.AnsweredElsewhere, true);
};

private setState(state: CallState): void {
const oldState = this.state;
this.state = state;
this.emit(CallEvent.State, state, oldState);
}

/**
* Internal
* @param {string} eventType
Expand Down Expand Up @@ -2444,7 +2448,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap

this.hangupParty = hangupParty;
this.hangupReason = hangupReason;
this.setState(CallState.Ended);
this.state = CallState.Ended;

if (this.inviteTimeout) {
clearTimeout(this.inviteTimeout);
Expand Down Expand Up @@ -2578,7 +2582,7 @@ export class MatrixCall extends TypedEventEmitter<CallEvent, CallEventHandlerMap
if (!audio) {
throw new Error("You CANNOT start a call without audio");
}
this.setState(CallState.WaitLocalMedia);
this.state = CallState.WaitLocalMedia;

try {
const stream = await this.client.getMediaHandler().getUserMediaStream(audio, video);
Expand Down

0 comments on commit 0af2f79

Please sign in to comment.