Skip to content

Commit eafecd3

Browse files
committed
Better handling of send failures on VoIP events
Don't leave candidate message sin the queue, abort if we fail to send the invite.
1 parent fccf08e commit eafecd3

File tree

1 file changed

+46
-28
lines changed

1 file changed

+46
-28
lines changed

src/webrtc/call.ts

Lines changed: 46 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -886,7 +886,7 @@ export class MatrixCall extends EventEmitter {
886886
// Now we wait for the negotiationneeded event
887887
};
888888

889-
private sendAnswer() {
889+
private async sendAnswer() {
890890
const answerContent = {
891891
answer: {
892892
sdp: this.peerConn.localDescription.sdp,
@@ -908,12 +908,12 @@ export class MatrixCall extends EventEmitter {
908908
logger.info(`Discarding ${this.candidateSendQueue.length} candidates that will be sent in answer`);
909909
this.candidateSendQueue = [];
910910

911-
this.sendVoipEvent(EventType.CallAnswer, answerContent).then(() => {
911+
try {
912+
await this.sendVoipEvent(EventType.CallAnswer, answerContent);
912913
// If this isn't the first time we've tried to send the answer,
913914
// we may have candidates queued up, so send them now.
914915
this.inviteOrAnswerSent = true;
915-
this.sendCandidateQueue();
916-
}).catch((error) => {
916+
} catch (error) {
917917
// We've failed to answer: back to the ringing state
918918
this.setState(CallState.Ringing);
919919
this.client.cancelPendingEvent(error.event);
@@ -926,7 +926,11 @@ export class MatrixCall extends EventEmitter {
926926
}
927927
this.emit(CallEvent.Error, new CallError(code, message, error));
928928
throw error;
929-
});
929+
}
930+
931+
// error handler re-throws so this won't happen on error, but
932+
// we don't want the same error handling on the candidate queue
933+
this.sendCandidateQueue();
930934
}
931935

932936
private gotUserMediaForAnswer = async (stream: MediaStream) => {
@@ -1260,19 +1264,9 @@ export class MatrixCall extends EventEmitter {
12601264

12611265
try {
12621266
await this.sendVoipEvent(eventType, content);
1263-
this.sendCandidateQueue();
1264-
if (this.state === CallState.CreateOffer) {
1265-
this.inviteOrAnswerSent = true;
1266-
this.setState(CallState.InviteSent);
1267-
this.inviteTimeout = setTimeout(() => {
1268-
this.inviteTimeout = null;
1269-
if (this.state === CallState.InviteSent) {
1270-
this.hangup(CallErrorCode.InviteTimeout, false);
1271-
}
1272-
}, CALL_TIMEOUT_MS);
1273-
}
12741267
} catch (error) {
1275-
this.client.cancelPendingEvent(error.event);
1268+
logger.error("Failed to send invite", error);
1269+
if (error.event) this.client.cancelPendingEvent(error.event);
12761270

12771271
let code = CallErrorCode.SignallingFailed;
12781272
let message = "Signalling failed";
@@ -1287,6 +1281,22 @@ export class MatrixCall extends EventEmitter {
12871281

12881282
this.emit(CallEvent.Error, new CallError(code, message, error));
12891283
this.terminate(CallParty.Local, code, false);
1284+
1285+
// no need to carry on & send the candidate queue, but we also
1286+
// don't want to rethrow the error
1287+
return;
1288+
}
1289+
1290+
this.sendCandidateQueue();
1291+
if (this.state === CallState.CreateOffer) {
1292+
this.inviteOrAnswerSent = true;
1293+
this.setState(CallState.InviteSent);
1294+
this.inviteTimeout = setTimeout(() => {
1295+
this.inviteTimeout = null;
1296+
if (this.state === CallState.InviteSent) {
1297+
this.hangup(CallErrorCode.InviteTimeout, false);
1298+
}
1299+
}, CALL_TIMEOUT_MS);
12901300
}
12911301
};
12921302

@@ -1623,7 +1633,7 @@ export class MatrixCall extends EventEmitter {
16231633
}
16241634
}
16251635

1626-
private sendCandidateQueue() {
1636+
private async sendCandidateQueue() {
16271637
if (this.candidateSendQueue.length === 0) {
16281638
return;
16291639
}
@@ -1635,20 +1645,28 @@ export class MatrixCall extends EventEmitter {
16351645
candidates: cands,
16361646
};
16371647
logger.debug("Attempting to send " + cands.length + " candidates");
1638-
this.sendVoipEvent(EventType.CallCandidates, content).then(() => {
1639-
this.candidateSendTries = 0;
1640-
this.sendCandidateQueue();
1641-
}, (error) => {
1642-
for (let i = 0; i < cands.length; i++) {
1643-
this.candidateSendQueue.push(cands[i]);
1644-
}
1648+
try {
1649+
await this.sendVoipEvent(EventType.CallCandidates, content);
1650+
} catch (error) {
1651+
// don't retry this event: we'll send another one later as we might
1652+
// have more candidates by then.
1653+
if (error.event) this.client.cancelPendingEvent(error.event);
1654+
1655+
// put all the candidates we failed to send back in the queue
1656+
this.candidateSendQueue.push(...cands);
16451657

16461658
if (this.candidateSendTries > 5) {
16471659
logger.debug(
16481660
"Failed to send candidates on attempt " + this.candidateSendTries +
1649-
". Giving up for now.", error,
1661+
". Giving up on this call.", error,
16501662
);
1651-
this.candidateSendTries = 0;
1663+
1664+
const code = CallErrorCode.SignallingFailed;
1665+
const message = "Signalling failed";
1666+
1667+
this.emit(CallEvent.Error, new CallError(code, message, error));
1668+
this.hangup(code, false);
1669+
16521670
return;
16531671
}
16541672

@@ -1658,7 +1676,7 @@ export class MatrixCall extends EventEmitter {
16581676
setTimeout(() => {
16591677
this.sendCandidateQueue();
16601678
}, delayMs);
1661-
});
1679+
}
16621680
}
16631681

16641682
private async placeCallWithConstraints(constraints: MediaStreamConstraints) {

0 commit comments

Comments
 (0)