Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed some scenarios where an answered call keeps ringing. #1710

Merged
merged 1 commit into from
Feb 3, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 60 additions & 39 deletions MatrixSDK/VoIP/MXCall.m
Original file line number Diff line number Diff line change
Expand Up @@ -835,13 +835,7 @@ - (void)setState:(MXCallState)state reason:(MXEvent *)event
else if (MXCallStateInviteSent == state)
{
// Start the life expiration timer for the sent invitation
inviteExpirationTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:callManager.inviteLifetime / 1000]
interval:0
target:self
selector:@selector(expireCallInvite)
userInfo:nil
repeats:NO];
[[NSRunLoop mainRunLoop] addTimer:inviteExpirationTimer forMode:NSDefaultRunLoopMode];
[self startInviteExpirationTimer];
}

_state = state;
Expand Down Expand Up @@ -1180,17 +1174,35 @@ - (void)handleCallInvite:(MXEvent *)event
[self didEncounterError:error reason:MXCallHangupReasonUserMediaFailed];
}];

// Start expiration timer
self->inviteExpirationTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:self->callInviteEventContent.lifetime / 1000]
interval:0
target:self
selector:@selector(expireCallInvite)
userInfo:nil
repeats:NO];
[[NSRunLoop mainRunLoop] addTimer:self->inviteExpirationTimer forMode:NSDefaultRunLoopMode];
// Start an expiration timer
[self startInviteExpirationTimer];
}];
}

- (void)startInviteExpirationTimer {
if (inviteExpirationTimer)
{
return;
}

// Start expiration timer
inviteExpirationTimer = [[NSTimer alloc] initWithFireDate:[NSDate dateWithTimeIntervalSinceNow:callInviteEventContent.lifetime / 1000]
interval:0
target:self
selector:@selector(expireCallInvite)
userInfo:nil
repeats:NO];
[[NSRunLoop mainRunLoop] addTimer:inviteExpirationTimer forMode:NSDefaultRunLoopMode];
}

- (void)invalidateInviteExpirationTimer {
if (inviteExpirationTimer)
{
[inviteExpirationTimer invalidate];
inviteExpirationTimer = nil;
}
}

- (void)handleCallAnswer:(MXEvent *)event
{
MXLogDebug(@"[MXCall][%@] handleCallAnswer", _callId)
Expand All @@ -1200,6 +1212,12 @@ - (void)handleCallAnswer:(MXEvent *)event
return;
}

if (_state == MXCallStateEnded) {
// this call is already ended
MXLogDebug(@"[MXCall][%@] handleCallAnswer: this call is already ended", _callId);
return;
}

// Listen to answer event only for call we are making, not receiving
if (!_isIncoming)
{
Expand All @@ -1213,11 +1231,7 @@ - (void)handleCallAnswer:(MXEvent *)event
MXCallAnswerEventContent *content = [MXCallAnswerEventContent modelFromJSON:event.content];

// The peer accepted our outgoing call
if (inviteExpirationTimer)
{
[inviteExpirationTimer invalidate];
inviteExpirationTimer = nil;
}
[self invalidateInviteExpirationTimer];

// mark this as the selected one
self.selectedAnswer = event;
Expand Down Expand Up @@ -1287,6 +1301,12 @@ - (void)handleCallSelectAnswer:(MXEvent *)event
return;
}

if (_state == MXCallStateEnded) {
// this call is already ended
MXLogDebug(@"[MXCall][%@] handleCallAnswer: this call is already ended", _callId);
return;
}

if (_isIncoming)
{
MXCallSelectAnswerEventContent *content = [MXCallSelectAnswerEventContent modelFromJSON:event.content];
Expand Down Expand Up @@ -1353,11 +1373,7 @@ - (void)handleCallReject:(MXEvent *)event
}

// The peer rejected our outgoing call
if (inviteExpirationTimer)
{
[inviteExpirationTimer invalidate];
inviteExpirationTimer = nil;
}
[self invalidateInviteExpirationTimer];

if (_state != MXCallStateEnded)
{
Expand Down Expand Up @@ -1598,11 +1614,7 @@ - (NSString *)description

- (void)terminateWithReason:(MXEvent *)event
{
if (inviteExpirationTimer)
{
[inviteExpirationTimer invalidate];
inviteExpirationTimer = nil;
}
[self invalidateInviteExpirationTimer];

// Do not refresh TURN servers config anymore
[localIceGatheringTimer invalidate];
Expand Down Expand Up @@ -1711,14 +1723,17 @@ - (void)expireCallInvite
[callStackCall end];
}

// Send the notif that the call expired to the app
[self setState:MXCallStateInviteExpired reason:nil];

// Set appropriate call end reason
_endReason = MXCallEndReasonMissed;

// And set the final state: MXCallStateEnded
[self setState:MXCallStateEnded reason:nil];
// If the call is not aleady ended
if (_state != MXCallStateEnded) {
// Send the notif that the call expired to the app
[self setState:MXCallStateInviteExpired reason:nil];

// Set appropriate call end reason
_endReason = MXCallEndReasonMissed;

// And set the final state: MXCallStateEnded
[self setState:MXCallStateEnded reason:nil];
}

// The call manager can now ignore this call
[callManager removeCall:self];
Expand All @@ -1729,6 +1744,9 @@ - (void)onCallAnsweredElsewhere
{
MXLogDebug(@"[MXCall][%@] onCallAnsweredElsewhere", _callId)

// The call has been accepted elsewhere
[self invalidateInviteExpirationTimer];

// Send the notif that the call has been answered from another device to the app
[self setState:MXCallStateAnsweredElseWhere reason:nil];

Expand All @@ -1746,7 +1764,10 @@ - (void)onCallDeclinedElsewhere
{
MXLogDebug(@"[MXCall][%@] onCallDeclinedElsewhere", _callId)

// Send the notif that the call has been answered from another device to the app
// The call has been declined from another device
[self invalidateInviteExpirationTimer];

// Send the notif that the call has been declined from another device to the app
[self setState:MXCallStateAnsweredElseWhere reason:nil];

// Set appropriate call end reason
Expand Down
1 change: 1 addition & 0 deletions changelog.d/pr-1710.bugfix
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fix some scenarios where an answered call continues to ring