Skip to content
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
7 changes: 7 additions & 0 deletions NextcloudTalk/Calls/NCCallController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1510,6 +1510,13 @@ internal class NCCallController: NSObject, NCPeerConnectionDelegate, NCSignaling
}
}

func signalingControllerSessionExpired(_ signalingController: NCSignalingController!) {
NCLog.log("Internal signaling session expired for \(self.room.token), ending call")

// The join failure path already shows the reason in the foreground and ends via CallKit in the background
self.delegate?.callControllerDidFailedJoiningCall(self, statusCode: 404, errorReason: self.getJoinCallErrorReason(404))
}

// MARK: - NCCameraController delegate

func didDrawFirstFrameOnLocalView() {
Expand Down
5 changes: 5 additions & 0 deletions NextcloudTalk/WebRTC/NCSignalingController.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@

- (void)signalingController:(NCSignalingController *)signalingController didReceiveSignalingMessage:(NSDictionary *)message;

@optional

// The server no longer knows our session in this room, which polling cannot recover from
- (void)signalingControllerSessionExpired:(NCSignalingController *)signalingController;

@end

typedef void (^SignalingSettingsUpdatedCompletionBlock)(SignalingSettings *signalingSettings);
Expand Down
48 changes: 48 additions & 0 deletions NextcloudTalk/WebRTC/NCSignalingController.m
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,18 @@ @interface NCSignalingController()
{
NCRoom *_room;
BOOL _shouldStopPullingMessages;
NSInteger _consecutivePullFailures;
NSInteger _consecutiveSessionGoneFailures;
SignalingSettings *_signalingSettings;
NSURLSessionTask *_getSignalingSettingsTask;
NSURLSessionTask *_pullSignalingMessagesTask;
}

@end

// About 45s of retrying with the backoff below
static NSInteger const kMaxConsecutiveSessionGoneFailures = 5;

@implementation NCSignalingController

- (instancetype)initForRoom:(NCRoom *)room
Expand Down Expand Up @@ -92,6 +97,8 @@ - (void)startPullingSignalingMessages
[NCLog log:[NSString stringWithFormat:@"Start pulling internal signaling messages for token %@", _room.token]];

_shouldStopPullingMessages = NO;
_consecutivePullFailures = 0;
_consecutiveSessionGoneFailures = 0;
[self pullSignalingMessages];
}

Expand All @@ -108,6 +115,47 @@ - (void)pullSignalingMessages
return;
}

if (error) {
self->_consecutivePullFailures += 1;

// A 404 means our session is gone server side, which polling cannot recover from
if (error.responseStatusCode == 404) {
self->_consecutiveSessionGoneFailures += 1;

if (self->_consecutiveSessionGoneFailures >= kMaxConsecutiveSessionGoneFailures) {
[NCLog log:[NSString stringWithFormat:@"Internal signaling has no session for token %@ anymore, ending the call", self->_room.token]];

self->_shouldStopPullingMessages = YES;

if ([self.observer respondsToSelector:@selector(signalingControllerSessionExpired:)]) {
[self.observer signalingControllerSessionExpired:self];
}

return;
}
} else {
self->_consecutiveSessionGoneFailures = 0;
}

// The request is only re-armed from here, so retrying immediately would busy loop
NSTimeInterval delay = MIN(pow(2, MIN(self->_consecutivePullFailures, 4)), 16);

[NCLog log:[NSString stringWithFormat:@"Could not pull internal signaling messages (failure %ld, status %ld), retrying in %.0fs", (long)self->_consecutivePullFailures, (long)error.responseStatusCode, delay]];

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (self->_shouldStopPullingMessages) {
return;
}

[self pullSignalingMessages];
});

return;
}

self->_consecutivePullFailures = 0;
self->_consecutiveSessionGoneFailures = 0;

for (NSDictionary *message in messages) {
if ([self.observer respondsToSelector:@selector(signalingController:didReceiveSignalingMessage:)]) {
[self.observer signalingController:self didReceiveSignalingMessage:message];
Expand Down
Loading