Skip to content

Commit 4cc4b28

Browse files
authored
Merge pull request #1503 from matrix-org/dbkr/call_state_machine
Fixes for call state machine
2 parents fad9b4c + b28bad6 commit 4cc4b28

File tree

1 file changed

+30
-16
lines changed

1 file changed

+30
-16
lines changed

src/webrtc/call.ts

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -85,13 +85,23 @@ export enum CallParty {
8585
Remote = 'remote',
8686
}
8787

88+
export enum CallEvent {
89+
Hangup = 'hangup',
90+
State = 'state',
91+
Error = 'error',
92+
Replaced = 'replaced',
93+
}
94+
8895
enum MediaQueueId {
8996
RemoteVideo = 'remote_video',
9097
RemoteAudio = 'remote_audio',
9198
LocalVideo = 'local_video',
9299
}
93100

94101
export enum CallErrorCode {
102+
/** The user chose to end the call */
103+
UserHangup = 'user_hangup',
104+
95105
/** An error code when the local client failed to create an offer. */
96106
LocalOfferFailed = 'local_offer_failed',
97107
/**
@@ -297,7 +307,7 @@ export class MatrixCall extends EventEmitter {
297307
const audioConstraints = getUserMediaVideoContraints(CallType.Voice);
298308
this.placeCallWithConstraints(audioConstraints);
299309
} catch (err) {
300-
this.emit("error",
310+
this.emit(CallEvent.Error,
301311
new CallError(
302312
CallErrorCode.NoUserMedia,
303313
"Failed to get screen-sharing stream: ", err,
@@ -440,7 +450,7 @@ export class MatrixCall extends EventEmitter {
440450
if (this.peerConn.signalingState != 'closed') {
441451
this.peerConn.close();
442452
}
443-
this.emit("hangup");
453+
this.emit(CallEvent.Hangup);
444454
}
445455
}, this.msg.lifetime - event.getLocalAge());
446456
}
@@ -511,7 +521,7 @@ export class MatrixCall extends EventEmitter {
511521
newCall.remoteVideoElement = this.remoteVideoElement;
512522
newCall.remoteAudioElement = this.remoteAudioElement;
513523
this.successor = newCall;
514-
this.emit("replaced", newCall);
524+
this.emit(CallEvent.Replaced, newCall);
515525
this.hangup(CallErrorCode.Replaced, true);
516526
}
517527

@@ -528,8 +538,10 @@ export class MatrixCall extends EventEmitter {
528538
const content = {
529539
version: 0,
530540
call_id: this.callId,
531-
reason: reason,
532541
};
542+
// Continue to send no reason for user hangups temporarily, until
543+
// clients understand the user_hangup reason (voip v1)
544+
if (reason !== CallErrorCode.UserHangup) content['reason'] = reason;
533545
this.sendEvent('m.call.hangup', content);
534546
}
535547

@@ -642,8 +654,8 @@ export class MatrixCall extends EventEmitter {
642654
};
643655

644656
private sendAnswer() {
657+
this.setState(CallState.Connecting);
645658
this.sendEvent('m.call.answer', this.answerContent).then(() => {
646-
this.setState(CallState.Connecting);
647659
// If this isn't the first time we've tried to send the answer,
648660
// we may have candidates queued up, so send them now.
649661
this.sendCandidateQueue();
@@ -658,7 +670,7 @@ export class MatrixCall extends EventEmitter {
658670
code = CallErrorCode.UnknownDevices;
659671
message = "Unknown devices present in the room";
660672
}
661-
this.emit("error", new CallError(code, message, error));
673+
this.emit(CallEvent.Error, new CallError(code, message, error));
662674
throw error;
663675
});
664676
}
@@ -854,7 +866,7 @@ export class MatrixCall extends EventEmitter {
854866

855867
this.client.cancelPendingEvent(error.event);
856868
this.terminate(CallParty.Local, code, false);
857-
this.emit("error", new CallError(code, message, error));
869+
this.emit(CallEvent.Error, new CallError(code, message, error));
858870
}
859871
};
860872

@@ -863,7 +875,7 @@ export class MatrixCall extends EventEmitter {
863875

864876
this.terminate(CallParty.Local, CallErrorCode.LocalOfferFailed, false);
865877
this.emit(
866-
"error",
878+
CallEvent.Error,
867879
new CallError(
868880
CallErrorCode.LocalOfferFailed,
869881
"Failed to get local offer!", err,
@@ -879,7 +891,7 @@ export class MatrixCall extends EventEmitter {
879891

880892
this.terminate(CallParty.Local, CallErrorCode.NoUserMedia, false);
881893
this.emit(
882-
"error",
894+
CallEvent.Error,
883895
new CallError(
884896
CallErrorCode.NoUserMedia,
885897
"Couldn't start capturing media! Is your microphone set up and " +
@@ -893,12 +905,11 @@ export class MatrixCall extends EventEmitter {
893905
return; // because ICE can still complete as we're ending the call
894906
}
895907
logger.debug(
896-
"Ice connection state changed to: " + this.peerConn.iceConnectionState,
908+
"ICE connection state changed to: " + this.peerConn.iceConnectionState,
897909
);
898910
// ideally we'd consider the call to be connected when we get media but
899911
// chrome doesn't implement any of the 'onstarted' events yet
900-
if (this.peerConn.iceConnectionState == 'completed' ||
901-
this.peerConn.iceConnectionState == 'connected') {
912+
if (this.peerConn.iceConnectionState == 'connected') {
902913
this.setState(CallState.Connected);
903914
} else if (this.peerConn.iceConnectionState == 'failed') {
904915
this.hangup(CallErrorCode.IceFailed, false);
@@ -1004,7 +1015,7 @@ export class MatrixCall extends EventEmitter {
10041015
setState(state: CallState) {
10051016
const oldState = this.state;
10061017
this.state = state;
1007-
this.emit("state", state, oldState);
1018+
this.emit(CallEvent.State, state, oldState);
10081019
}
10091020

10101021
/**
@@ -1075,7 +1086,7 @@ export class MatrixCall extends EventEmitter {
10751086
this.peerConn.close();
10761087
}
10771088
if (shouldEmit) {
1078-
this.emit("hangup", self);
1089+
this.emit(CallEvent.Hangup, self);
10791090
}
10801091
}
10811092

@@ -1092,8 +1103,10 @@ export class MatrixCall extends EventEmitter {
10921103
}
10931104
}
10941105

1095-
for (const track of this.remoteStream.getTracks()) {
1096-
track.stop();
1106+
if (this.remoteStream) {
1107+
for (const track of this.remoteStream.getTracks()) {
1108+
track.stop();
1109+
}
10971110
}
10981111
}
10991112

@@ -1167,6 +1180,7 @@ export class MatrixCall extends EventEmitter {
11671180
iceServers: this.turnServers,
11681181
});
11691182

1183+
// 'connectionstatechange' would be better, but firefox doesn't implement that.
11701184
pc.addEventListener('iceconnectionstatechange', this.onIceConnectionStateChanged);
11711185
pc.addEventListener('signalingstatechange', this.onSignallingStateChanged);
11721186
pc.addEventListener('icecandidate', this.gotLocalIceCandidate);

0 commit comments

Comments
 (0)