Skip to content

Commit

Permalink
Call reconnect fixes
Browse files Browse the repository at this point in the history
Signed-off-by: Marcel Müller <[email protected]>
  • Loading branch information
SystemKeeper committed Aug 21, 2024
1 parent 7c9b42c commit 64838dd
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 16 deletions.
20 changes: 19 additions & 1 deletion NextcloudTalk/CallViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -2024,6 +2024,7 @@ - (void)callController:(NCCallController *)callController peerLeft:(NCPeerConnec
{
[self removePeer:peer];
}

- (void)callController:(NCCallController *)callController didCreateCameraController:(NCCameraController *)cameraController
{
dispatch_async(dispatch_get_main_queue(), ^{
Expand Down Expand Up @@ -2207,7 +2208,24 @@ - (void)callController:(NCCallController *)callController didReceiveReaction:(NS

- (void)callControllerIsReconnectingCall:(NCCallController *)callController
{
[self setCallState:CallStateReconnecting];
dispatch_async(dispatch_get_main_queue(), ^{
// Cancel any pending operations
_pendingPeerInserts = [[NSMutableArray alloc] init];
_pendingPeerDeletions = [[NSMutableArray alloc] init];
_pendingPeerUpdates = [[NSMutableArray alloc] init];
_peersInCall = [[NSMutableArray alloc] init];

// Reset a potential queued batch update
[self->_batchUpdateTimer invalidate];
self->_batchUpdateTimer = nil;

// Force the collectionView to reload all data
[self.collectionView reloadData];
[self.collectionView.collectionViewLayout invalidateLayout];
[self.collectionView layoutSubviews];

[self setCallState:CallStateReconnecting];
});
}

- (void)callControllerWantsToHangUpCall:(NCCallController *)callController
Expand Down
24 changes: 19 additions & 5 deletions NextcloudTalk/NCCallController.m
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,11 @@ - (void)joinCall
self->_joinedCallOnce = YES;
self->_joinCallAttempts = 0;
} else {
if (error.code == NSURLErrorCancelled) {
self->_joinCallAttempts = 0;
return;
}

if (self->_joinCallAttempts < 3) {
NSLog(@"Could not join call, retrying. %ld", (long)self->_joinCallAttempts);
self->_joinCallAttempts += 1;
Expand Down Expand Up @@ -310,6 +315,9 @@ - (void)forceReconnect
[NCUtils log:@"Force reconnect"];

[[WebRTCCommon shared] dispatch:^{
[self.joinCallTask cancel];
self.joinCallTask = nil;

self->_userInCall = 0;
[self cleanCurrentPeerConnections];
[self.delegate callControllerIsReconnectingCall:self];
Expand All @@ -318,11 +326,12 @@ - (void)forceReconnect
self->_disableAudioAtStart = ![self isAudioEnabled];
self->_disableVideoAtStart = ![self isVideoEnabled];

if (self->_externalSignalingController) {
[self->_externalSignalingController forceReconnectForRejoin];
} else {
if (!self->_externalSignalingController) {
[self rejoinCallUsingInternalSignaling];
return;
}

[self->_externalSignalingController forceReconnectForRejoin];
}];
}

Expand Down Expand Up @@ -1244,9 +1253,14 @@ - (void)externalSignalingControllerShouldRejoinCall:(NCExternalSignalingControll
// Also we should check that it has joined the call first with the startCall method.

[[WebRTCCommon shared] dispatch:^{
if (self->_preparedForRejoin && self->_joinedCallOnce) {
if (self->_preparedForRejoin) {
self->_preparedForRejoin = NO;
[self shouldRejoinCall];

if (self->_joinedCallOnce) {
[self shouldRejoinCall];
} else {
[self joinCall];
}
}
}];
}
Expand Down
16 changes: 13 additions & 3 deletions NextcloudTalk/NCExternalSignalingController.m
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,16 @@ - (void)forceReconnectForRejoin
// In `helloResponseReceived` we determine that we were in a room and that the sessionId changed, in that case
// we trigger a re-join in `NCRoomsManager` which takes care of re-joining.
dispatch_async(dispatch_get_main_queue(), ^{
self->_resumeId = nil;
[self reconnect];
NSDictionary *byeDict = @{
@"type": @"bye",
@"bye": @{}
};

// Close our current session. Don't leave the room, as that would defeat the above mentioned purpose
[self sendMessage:byeDict withCompletionBlock:^(NSURLSessionWebSocketTask *task, NCExternalSignalingSendMessageStatus status) {
self->_resumeId = nil;
[self reconnect];
}];
});
}

Expand Down Expand Up @@ -359,7 +367,9 @@ - (void)helloResponseReceived:(NSDictionary *)messageDict
// Re-join if user was in a room
if (_currentRoom && _sessionChanged) {
[self.delegate externalSignalingControllerWillRejoinCall:self];
[[NCRoomsManager sharedInstance] rejoinRoom:_currentRoom];
[[NCRoomsManager sharedInstance] rejoinRoom:_currentRoom completionBlock:^(NSString * _Nullable, NCRoom * _Nullable, NSError * _Nullable, NSInteger, NSString * _Nullable) {
// TODO: Instead of waiting for a room message, can we call [self.delegate externalSignalingControllerShouldRejoinCall:self]; here?
}];
}
}

Expand Down
28 changes: 21 additions & 7 deletions NextcloudTalk/NCRoomsManagerExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -203,26 +203,40 @@ import Foundation
}
}

public func rejoinRoom(_ token: String) {
public func rejoinRoom(_ token: String, completionBlock: @escaping (_ sessionId: String?, _ room: NCRoom?, _ error: Error?, _ statusCode: Int, _ statusReason: String?) -> Void) {
guard let roomController = self.activeRooms[token] as? NCRoomController else { return }

let activeAccount = NCDatabaseManager.sharedInstance().activeAccount()

self.joiningRoomToken = token
self.joinRoomTask = NCAPIController.sharedInstance().joinRoom(token, for: activeAccount, withCompletionBlock: { sessionId, _, error, statusCode, _ in
self.joinRoomTask = NCAPIController.sharedInstance().joinRoom(token, for: activeAccount, withCompletionBlock: { sessionId, room, error, statusCode, statusReason in
if error == nil {
roomController.userSessionId = sessionId
roomController.inChat = true

if let extSignalingController = NCSettingsController.sharedInstance().externalSignalingController(forAccountId: activeAccount.accountId) {
self.getSignalingSettingsHelper(for: activeAccount, forRoom: token) { signalingSettings in
let federation = signalingSettings?.getFederationJoinDictionary()
guard let extSignalingController = NCSettingsController.sharedInstance().externalSignalingController(forAccountId: activeAccount.accountId)
else {
// Joined room in NC successfully and no external signaling server configured.
completionBlock(sessionId, room, nil, 0, nil)
return
}

extSignalingController.joinRoom(token, withSessionId: sessionId, withFederation: federation, withCompletionBlock: nil)
self.getSignalingSettingsHelper(for: activeAccount, forRoom: token) { signalingSettings in
let federation = signalingSettings?.getFederationJoinDictionary()

extSignalingController.joinRoom(token, withSessionId: sessionId, withFederation: federation) { error in
if error == nil {
NCUtils.log("Re-Joined room \(token) in external signaling server successfully.")
completionBlock(sessionId, room, nil, 0, nil)
} else {
NCUtils.log("Failed re-joining room \(token) in external signaling server.")
completionBlock(nil, nil, error, statusCode, statusReason)
}
}
}
} else {
print("Could not re-join room. Status code: \(statusCode). Error: \(error?.localizedDescription ?? "Unknown")")
NCUtils.log("Could not re-join room \(token). Status code: \(statusCode). Error: \(error?.localizedDescription ?? "Unknown")")
completionBlock(nil, nil, error, statusCode, statusReason)
}

self.joiningRoomToken = nil
Expand Down

0 comments on commit 64838dd

Please sign in to comment.