Merge pull request #1727 from nextcloud/federation-v2

Federation v2
This commit is contained in:
Marcel Müller 2024-07-30 19:56:16 +02:00 коммит произвёл GitHub
Родитель 5e53b9ee55 28e2cd151a
Коммит 1f5514688e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: B5690EEEBB952194
19 изменённых файлов: 319 добавлений и 121 удалений

Просмотреть файл

@ -184,6 +184,18 @@
1F8848122A75B68D00063860 /* IntentsUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1F90EFC225FE489B00F3FA55 /* IntentsUI.framework */; };
1F8995B32970644C00CABA33 /* ColorGenerator.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F8995B22970644C00CABA33 /* ColorGenerator.swift */; };
1F8995B52973547700CABA33 /* WebRTCCommon.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F8995B42973547700CABA33 /* WebRTCCommon.swift */; };
1F8AAC322C518759004DA20A /* SignalingSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F8AAC312C518759004DA20A /* SignalingSettings.swift */; };
1F8AAC332C518B8A004DA20A /* SignalingSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F8AAC312C518759004DA20A /* SignalingSettings.swift */; };
1F8AAC342C518B8A004DA20A /* SignalingSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F8AAC312C518759004DA20A /* SignalingSettings.swift */; };
1F8AAC352C518B8B004DA20A /* SignalingSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F8AAC312C518759004DA20A /* SignalingSettings.swift */; };
1F8AAC372C519577004DA20A /* TurnServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F8AAC362C519577004DA20A /* TurnServer.swift */; };
1F8AAC382C519577004DA20A /* TurnServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F8AAC362C519577004DA20A /* TurnServer.swift */; };
1F8AAC392C519577004DA20A /* TurnServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F8AAC362C519577004DA20A /* TurnServer.swift */; };
1F8AAC3A2C519577004DA20A /* TurnServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F8AAC362C519577004DA20A /* TurnServer.swift */; };
1F8AAC3C2C519689004DA20A /* StunServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F8AAC3B2C519689004DA20A /* StunServer.swift */; };
1F8AAC3D2C519689004DA20A /* StunServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F8AAC3B2C519689004DA20A /* StunServer.swift */; };
1F8AAC3E2C519689004DA20A /* StunServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F8AAC3B2C519689004DA20A /* StunServer.swift */; };
1F8AAC3F2C519689004DA20A /* StunServer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F8AAC3B2C519689004DA20A /* StunServer.swift */; };
1F90DA0429E9A28E00E81E3D /* AvatarManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1F90DA0329E9A28E00E81E3D /* AvatarManager.swift */; };
1F90EFBC25FE39F800F3FA55 /* NCIntentController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F90EFBB25FE39F800F3FA55 /* NCIntentController.m */; };
1F90EFBD25FE39F800F3FA55 /* NCIntentController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1F90EFBB25FE39F800F3FA55 /* NCIntentController.m */; };
@ -707,6 +719,9 @@
1F785DDC2707865F00AC4B40 /* VoiceMessageTranscribeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = VoiceMessageTranscribeViewController.h; sourceTree = "<group>"; };
1F8995B22970644C00CABA33 /* ColorGenerator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ColorGenerator.swift; sourceTree = "<group>"; };
1F8995B42973547700CABA33 /* WebRTCCommon.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WebRTCCommon.swift; sourceTree = "<group>"; };
1F8AAC312C518759004DA20A /* SignalingSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignalingSettings.swift; sourceTree = "<group>"; };
1F8AAC362C519577004DA20A /* TurnServer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TurnServer.swift; sourceTree = "<group>"; };
1F8AAC3B2C519689004DA20A /* StunServer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = StunServer.swift; sourceTree = "<group>"; };
1F90DA0329E9A28E00E81E3D /* AvatarManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AvatarManager.swift; sourceTree = "<group>"; };
1F90EFBA25FE39F800F3FA55 /* NCIntentController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NCIntentController.h; sourceTree = "<group>"; };
1F90EFBB25FE39F800F3FA55 /* NCIntentController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NCIntentController.m; sourceTree = "<group>"; };
@ -1859,6 +1874,9 @@
2CD5F3232142781A006B71BF /* NCExternalSignalingController.m */,
2C69323B2923ECAA00017AD2 /* WSMessage.h */,
2C69323C2923ECAA00017AD2 /* WSMessage.m */,
1F8AAC312C518759004DA20A /* SignalingSettings.swift */,
1F8AAC362C519577004DA20A /* TurnServer.swift */,
1F8AAC3B2C519689004DA20A /* StunServer.swift */,
1F8995B42973547700CABA33 /* WebRTCCommon.swift */,
);
name = WebRTC;
@ -2685,6 +2703,7 @@
1F77A5F82AB9A4CD007B6037 /* NCDeckCardParameter.m in Sources */,
1F77A5FD2AB9A4F3007B6037 /* ServerCapabilities.m in Sources */,
1FF4DA892C0262BB00C1B952 /* NCBaseSessionManager.swift in Sources */,
1F8AAC352C518B8B004DA20A /* SignalingSettings.swift in Sources */,
1F77A6062AB9A581007B6037 /* NCKeyChainController.m in Sources */,
1F0B0A732BA265300073FF8D /* MentionSuggestion.swift in Sources */,
1F77A5FB2AB9A4E6007B6037 /* NCMessageParameter.m in Sources */,
@ -2701,6 +2720,7 @@
1F77A60D2AB9A5CC007B6037 /* NCPoll.m in Sources */,
1F77A6032AB9A56D007B6037 /* NotificationCenterNotifications.m in Sources */,
1F77A60A2AB9A5AE007B6037 /* NCUser.m in Sources */,
1F8AAC3F2C519689004DA20A /* StunServer.swift in Sources */,
1FF4DA992C0327FF00C1B952 /* NCWebImageDownloaderOperation.swift in Sources */,
1F1B504A2B90CF0800B0F2F4 /* TalkCapabilities.m in Sources */,
2C6955122B0CE1A10070F6E1 /* NCUtils.swift in Sources */,
@ -2709,6 +2729,7 @@
1F77A5F52AB9A4B9007B6037 /* NCAPIController.m in Sources */,
1F77A5F92AB9A4D9007B6037 /* NCMessageFileParameter.m in Sources */,
1FF2FD852AB99F51000C9905 /* NCUserStatus.m in Sources */,
1F8AAC3A2C519577004DA20A /* TurnServer.swift in Sources */,
1FB78E202B6ADBB600B0D69D /* NCAPIControllerExtensions.swift in Sources */,
1FF136122BFB4F8C006A6101 /* NCRoom.swift in Sources */,
1FF2FD7F2AB99E4D000C9905 /* Atomic.swift in Sources */,
@ -2774,6 +2795,7 @@
1F1B0F452BE047CE003FD766 /* ModalPresentationController.swift in Sources */,
2CBF82AE1FC888FC00636459 /* NCPushNotification.m in Sources */,
2CC7159420C54D080045C789 /* ChatTableViewCell.m in Sources */,
1F8AAC322C518759004DA20A /* SignalingSettings.swift in Sources */,
1F1B0F272BDA61C5003FD766 /* AllocationTracker.swift in Sources */,
2CA1CCAA1F02D1A4002FE6A2 /* NCAPIController.m in Sources */,
1F1B0F302BDBC9D6003FD766 /* NCMediaViewerPageViewController.swift in Sources */,
@ -2797,6 +2819,7 @@
2C9B0B9C217F756B00A4752C /* NCNotification.m in Sources */,
2C2D7A172B8C9C0000642373 /* RoomCreationTableViewController.swift in Sources */,
1F8995B52973547700CABA33 /* WebRTCCommon.swift in Sources */,
1F8AAC3C2C519689004DA20A /* StunServer.swift in Sources */,
2C2145682BF6B8E900470C0C /* NewRoomTableViewController.swift in Sources */,
1F1B503E2B8FB12100B0F2F4 /* BaseChatTableViewCell+Message.swift in Sources */,
DA66583127B6B24E00B46B11 /* UserProfileTableViewController+Utils.swift in Sources */,
@ -2825,6 +2848,7 @@
1FAB2E852ACB482B001214EB /* ChatViewController.swift in Sources */,
1F5813F828EB23EF00318FC3 /* NCSplitViewController.swift in Sources */,
2C5BFBFE2891C3DF00E75118 /* PollResultsDetailsViewController.swift in Sources */,
1F8AAC372C519577004DA20A /* TurnServer.swift in Sources */,
2CA1CCA41F025F64002FE6A2 /* RoomsTableViewController.m in Sources */,
2CB3041A2264775E0053078A /* SLKTextInput+Implementation.m in Sources */,
2C90E5D31EE80C870093D85A /* AuthenticationViewController.m in Sources */,
@ -2976,6 +3000,7 @@
1FF136172BFB74CF006A6101 /* NCChatMessage.swift in Sources */,
1FF4DA8A2C0262BB00C1B952 /* NCBaseSessionManager.swift in Sources */,
2C62B00C24C1BDC1007E460A /* NCNotification.m in Sources */,
1F8AAC3E2C519689004DA20A /* StunServer.swift in Sources */,
1F1C0D7F29A7F33600D17C6D /* NCNotificationAction.swift in Sources */,
1F35F8E62AEEBC0300044BDA /* SLKTextInput+Implementation.m in Sources */,
1FF4DA982C0327FF00C1B952 /* NCWebImageDownloaderOperation.swift in Sources */,
@ -3004,6 +3029,7 @@
1FDFC94F2BA50B9100670DF4 /* UIFontExtension.swift in Sources */,
1F35F8EA2AEEBC0E00044BDA /* SLKTextViewController.m in Sources */,
2C6955132B0CE1A20070F6E1 /* NCUtils.swift in Sources */,
1F8AAC342C518B8A004DA20A /* SignalingSettings.swift in Sources */,
2C62AFFF24C1BDAA007E460A /* NCUser.m in Sources */,
1FAB2EF22AD1EAA3001214EB /* RLMSupport.swift in Sources */,
1FB78E212B6ADBB700B0D69D /* NCAPIControllerExtensions.swift in Sources */,
@ -3033,6 +3059,7 @@
1F35F8FC2AEEDBC600044BDA /* ChatViewControllerExtension.swift in Sources */,
1FEDE3D0257D43AB00853F79 /* NCMessageFileParameter.m in Sources */,
2C62AFB924C1A4E6007E460A /* ShareViewController.m in Sources */,
1F8AAC392C519577004DA20A /* TurnServer.swift in Sources */,
1F35F8F32AEEC29A00044BDA /* AvatarButton.swift in Sources */,
2C4446DF2658158000DF1DBC /* NCChatBlock.m in Sources */,
1FF4DAAC2C0A114900C1B952 /* OcsResponse.swift in Sources */,
@ -3071,14 +3098,17 @@
1F45A1352A026EFA005FE87D /* NCWebImageDownloaderOperation.m in Sources */,
2CC0017324A3795B00A20167 /* NCImageSessionManager.m in Sources */,
1FB7B9922BF0CDF90093CE98 /* BannedActor.swift in Sources */,
1F8AAC382C519577004DA20A /* TurnServer.swift in Sources */,
2CC001C124A37AC500A20167 /* NCNotification.m in Sources */,
2C4446FD265D5DFA00DF1DBC /* ABContact.m in Sources */,
1F8AAC3D2C519689004DA20A /* StunServer.swift in Sources */,
2C4446F8265D5A0700DF1DBC /* NotificationCenterNotifications.m in Sources */,
2C6955142B0CE1A20070F6E1 /* NCUtils.swift in Sources */,
1FF4DA942C02678000C1B952 /* NCImageSessionManager.swift in Sources */,
1F0B0A752BA265310073FF8D /* MentionSuggestion.swift in Sources */,
1FC940B92A5F21FC00FFFADE /* SwiftMarkdownObjCBridge.swift in Sources */,
1FF4DA882C0262BA00C1B952 /* NCBaseSessionManager.swift in Sources */,
1F8AAC332C518B8A004DA20A /* SignalingSettings.swift in Sources */,
2CB6ACDB2641483800D3D641 /* NCMessageLocationParameter.m in Sources */,
2C4446FB265D5C5700DF1DBC /* NCRoomParticipants.m in Sources */,
2CC1FF492818395E009F7288 /* NCDeckCardParameter.m in Sources */,

Просмотреть файл

@ -153,6 +153,13 @@ class BaseChatTableViewCell: UITableViewCell, ReactionsViewDelegate {
}
}
var titleLabel = actorDisplayName.withTextColor(.secondaryLabel)
if message.actorType == "federated_users", let remoteServer = message.actorId.split(separator: "@").last {
let remoteServerString = " (\(String(remoteServer)))"
titleLabel.append(remoteServerString.withTextColor(.tertiaryLabel))
}
if let lastEditActorDisplayName = message.lastEditActorDisplayName, message.lastEditTimestamp > 0 {
var editedString = ""
@ -161,18 +168,16 @@ class BaseChatTableViewCell: UITableViewCell, ReactionsViewDelegate {
editedString = " (\(editedString))"
} else {
editedString = NSLocalizedString("edited by", comment: "A message was edited by ...")
editedString = " (\(editedString) \(lastEditActorDisplayName)"
editedString = " (\(editedString) \(lastEditActorDisplayName))"
}
let editedAttributedString = editedString.withTextColor(.tertiaryLabel)
let actorDisplayName = actorDisplayName.withTextColor(.secondaryLabel)
actorDisplayName.append(editedAttributedString)
self.titleLabel.attributedText = actorDisplayName
} else {
self.titleLabel.text = actorDisplayName
titleLabel.append(editedAttributedString)
}
self.titleLabel.attributedText = titleLabel
let activeAccount = NCDatabaseManager.sharedInstance().activeAccount()
guard let room = NCDatabaseManager.sharedInstance().room(withToken: message.token, forAccountId: activeAccount.accountId)

Просмотреть файл

@ -155,10 +155,7 @@ import UIKit
public override func viewDidLoad() {
super.viewDidLoad()
if NCDatabaseManager.sharedInstance().roomTalkCapabilities(for: self.room)?.callEnabled ?? false &&
room.type != .changelog && room.type != .noteToSelf,
!room.isFederated {
if room.supportsCalling {
self.navigationItem.rightBarButtonItems = [videoCallButton, voiceCallButton]
}
@ -1187,8 +1184,10 @@ import UIKit
let activeAccount = NCDatabaseManager.sharedInstance().activeAccount()
let userId = notification.userInfo?["userId"] as? String
let isFederated = notification.userInfo?["isFederated"] as? Bool ?? false
if userId == activeAccount.userId || serverCapabilities.typingPrivacy {
// Since our own userId can exist on other servers, only suppress the notification if it's not federated
if (userId == activeAccount.userId && !isFederated) || serverCapabilities.typingPrivacy {
return
}

Просмотреть файл

@ -67,7 +67,6 @@ typedef void (^PollCompletionBlock)(NCPoll *poll, NSError *error, NSInteger stat
typedef void (^SendSignalingMessagesCompletionBlock)(NSError *error);
typedef void (^PullSignalingMessagesCompletionBlock)(NSDictionary *messages, NSError *error);
typedef void (^GetSignalingSettingsCompletionBlock)(NSDictionary *settings, NSError *error);
typedef void (^SetReadStatusPrivacySettingCompletionBlock)(NSError *error);
typedef void (^SetTypingPrivacySettingCompletionBlock)(NSError *error);
@ -226,7 +225,6 @@ extern NSInteger const kReceivedChatMessagesLimit;
// Signaling Controller
- (NSURLSessionDataTask *)sendSignalingMessages:(NSString *)messages toRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(SendSignalingMessagesCompletionBlock)block;
- (NSURLSessionDataTask *)pullSignalingMessagesFromRoom:(NSString *)token forAccount:(TalkAccount *)account withCompletionBlock:(PullSignalingMessagesCompletionBlock)block;
- (NSURLSessionDataTask *)getSignalingSettingsForAccount:(TalkAccount *)account withCompletionBlock:(GetSignalingSettingsCompletionBlock)block;
- (NSString *)authenticationBackendUrlForAccount:(TalkAccount *)account;
// Settings Controller

Просмотреть файл

@ -1810,29 +1810,6 @@ NSInteger const kReceivedChatMessagesLimit = 100;
return task;
}
- (NSURLSessionDataTask *)getSignalingSettingsForAccount:(TalkAccount *)account withCompletionBlock:(GetSignalingSettingsCompletionBlock)block
{
NSString *endpoint = @"signaling/settings";
NSInteger signalingAPIVersion = [self signalingAPIVersionForAccount:account];
NSString *URLString = [self getRequestURLForEndpoint:endpoint withAPIVersion:signalingAPIVersion forAccount:account];
NCAPISessionManager *apiSessionManager = [_apiSessionManagers objectForKey:account.accountId];
NSURLSessionDataTask *task = [apiSessionManager GET:URLString parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSDictionary *responseDict = responseObject;
if (block) {
block(responseDict, nil);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSInteger statusCode = [self getResponseStatusCode:task.response];
[self checkResponseStatusCode:statusCode forAccount:account];
if (block) {
block(nil, error);
}
}];
return task;
}
- (NSString *)authenticationBackendUrlForAccount:(TalkAccount *)account
{
NSString *endpoint = @"signaling/backend";

Просмотреть файл

@ -213,6 +213,32 @@ import Foundation
}
}
// MARK: - Signaling
@discardableResult
public func getSignalingSettings(for account: TalkAccount, forRoom roomToken: String?, completionBlock: @escaping (_ signalingSettings: SignalingSettings?, _ error: (any Error)?) -> Void) -> URLSessionDataTask? {
guard let apiSessionManager = self.apiSessionManagers.object(forKey: account.accountId) as? NCAPISessionManager
else {
completionBlock(nil, nil)
return nil
}
let apiVersion = self.signalingAPIVersion(for: account)
let urlString = self.getRequestURL(forEndpoint: "signaling/settings", withAPIVersion: apiVersion, for: account)
var parameters: [String: Any]?
if let roomToken, let encodedToken = roomToken.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed) {
parameters = [
"token": encodedToken
]
}
return apiSessionManager.getOcs(urlString, account: account, parameters: parameters) { ocs, error in
completionBlock(SignalingSettings(dictionary: ocs?.dataDict), error)
}
}
// MARK: - Mentions
public func getMentionSuggestions(for accountId: String, in roomToken: String, with searchString: String, completionBlock: @escaping (_ mentions: [MentionSuggestion]?) -> Void) {

Просмотреть файл

@ -139,19 +139,22 @@ static NSString * const kNCScreenTrackKind = @"screen";
- (void)startCall
{
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
// Make sure the signaling controller has retrieved the settings before joining a call
[_signalingController updateSignalingSettingsWithCompletionBlock:^(SignalingSettings *signalingSettings) {
AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeVideo];
if (!_isAudioOnly && authStatus == AVAuthorizationStatusNotDetermined) {
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
[self createLocalMedia];
[self joinCall];
}];
if (!self->_isAudioOnly && authStatus == AVAuthorizationStatusNotDetermined) {
[AVCaptureDevice requestAccessForMediaType:AVMediaTypeVideo completionHandler:^(BOOL granted) {
[self createLocalMedia];
[self joinCall];
}];
return;
}
return;
}
[self createLocalMedia];
[self joinCall];
[self createLocalMedia];
[self joinCall];
}];
}
- (NSString *)signalingSessionId

Просмотреть файл

@ -69,6 +69,7 @@ extern NSString * const kCapabilityMediaCaption;
extern NSString * const kCapabilityEditMessages;
extern NSString * const kCapabilityDeleteMessagesUnlimited;
extern NSString * const kCapabilityFederationV1;
extern NSString * const kCapabilityFederationV2;
extern NSString * const kCapabilityChatReadLast;
extern NSString * const kCapabilityBanV1;

Просмотреть файл

@ -70,6 +70,7 @@ NSString * const kCapabilityMediaCaption = @"media-caption";
NSString * const kCapabilityEditMessages = @"edit-messages";
NSString * const kCapabilityDeleteMessagesUnlimited = @"delete-messages-unlimited";
NSString * const kCapabilityFederationV1 = @"federation-v1";
NSString * const kCapabilityFederationV2 = @"federation-v2";
NSString * const kCapabilityChatReadLast = @"chat-read-last";
NSString * const kCapabilityBanV1 = @"ban-v1";

Просмотреть файл

@ -45,7 +45,7 @@ typedef void (^JoinRoomExternalSignalingCompletionBlock)(NSError *error);
- (instancetype)initWithAccount:(TalkAccount *)account server:(NSString *)serverUrl andTicket:(NSString *)ticket;
- (BOOL)hasMCU;
- (NSString *)sessionId;
- (void)joinRoom:(NSString *)roomId withSessionId:(NSString *)sessionId withCompletionBlock:(JoinRoomExternalSignalingCompletionBlock)block;
- (void)joinRoom:(NSString *)roomId withSessionId:(NSString *)sessionId withFederation:(NSDictionary * _Nullable)federationDict withCompletionBlock:(JoinRoomExternalSignalingCompletionBlock)block;
- (void)leaveRoom:(NSString *)roomId;
- (void)sendCallMessage:(NCSignalingMessage *)message;
- (void)sendSendOfferMessageWithSessionId:(NSString *)sessionId andRoomType:(NSString *)roomType;

Просмотреть файл

@ -381,7 +381,7 @@ NSString * const NCExternalSignalingControllerDidReceiveStoppedTypingNotificatio
[self executeCompletionBlockForMessageId:messageId withStatus:SendMessageApplicationError];
}
- (void)joinRoom:(NSString *)roomId withSessionId:(NSString *)sessionId withCompletionBlock:(JoinRoomExternalSignalingCompletionBlock)block
- (void)joinRoom:(NSString *)roomId withSessionId:(NSString *)sessionId withFederation:(NSDictionary *)federationDict withCompletionBlock:(JoinRoomExternalSignalingCompletionBlock)block
{
if (_disconnected) {
@ -400,6 +400,17 @@ NSString * const NCExternalSignalingControllerDidReceiveStoppedTypingNotificatio
}
};
if (federationDict) {
messageDict = @{
@"type": @"room",
@"room": @{
@"roomid": roomId,
@"sessionid": sessionId,
@"federation": federationDict
}
};
}
[self sendMessage:messageDict withCompletionBlock:^(NSURLSessionWebSocketTask *task, NCExternalSignalingSendMessageStatus status) {
if (status == SendMessageSocketError && task == self->_webSocket) {
// Reconnect if this is still the same socket we tried to send the message on
@ -425,7 +436,7 @@ NSString * const NCExternalSignalingControllerDidReceiveStoppedTypingNotificatio
{
if ([_currentRoom isEqualToString:roomId]) {
_currentRoom = nil;
[self joinRoom:@"" withSessionId:@"" withCompletionBlock:nil];
[self joinRoom:@"" withSessionId:@"" withFederation:nil withCompletionBlock:nil];
} else {
NSLog(@"External signaling: Not leaving because it's not room we joined");
}
@ -665,8 +676,10 @@ NSString * const NCExternalSignalingControllerDidReceiveStoppedTypingNotificatio
NSString *messageType = [[messageDict objectForKey:@"data"] objectForKey:@"type"];
if ([messageType isEqualToString:@"startedTyping"] || [messageType isEqualToString:@"stoppedTyping"]) {
NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init];
NSString *fromSession = [[messageDict objectForKey:@"sender"] objectForKey:@"sessionid"];
NSString *fromUser = [[messageDict objectForKey:@"sender"] objectForKey:@"userid"];
NSDictionary *sender = [messageDict objectForKey:@"sender"];
NSString *fromSession = [sender objectForKey:@"sessionid"];
NSString *fromUser = [sender objectForKey:@"userid"];
if (_currentRoom && fromSession){
[userInfo setObject:_currentRoom forKey:@"roomToken"];
@ -676,6 +689,12 @@ NSString * const NCExternalSignalingControllerDidReceiveStoppedTypingNotificatio
[userInfo setObject:fromUser forKey:@"userId"];
}
NSDictionary *participant = [_participantsMap objectForKey:fromSession];
if (participant) {
BOOL isFederated = [[participant objectForKey:@"federated"] boolValue];
[userInfo setObject:@(isFederated) forKey:@"isFederated"];
}
NSString *displayName = [self getDisplayNameFromSessionId:fromSession];
if (displayName) {

Просмотреть файл

@ -58,6 +58,16 @@ import Realm
return false
}
public var supportsCalling: Bool {
// Federated calling is only supported with federation-v2
if self.isFederated, !NCDatabaseManager.sharedInstance().roomHasTalkCapability(kCapabilityFederationV2, for: self) {
return false
}
return NCDatabaseManager.sharedInstance().roomTalkCapabilities(for: self)?.callEnabled ?? false &&
self.type != .changelog && self.type != .noteToSelf
}
public var isBreakoutRoom: Bool {
return self.objectType == NCRoomObjectTypeRoom
}

Просмотреть файл

@ -162,32 +162,49 @@ import Foundation
// Remember the latest sessionId we're using to join a room, to be able to check when joining the external signaling server
self.joiningSessionId = sessionId
extSignalingController.joinRoom(token, withSessionId: sessionId) { error in
// If the sessionId is not the same anymore we tried to join with, we either already left again before
// joining the external signaling server succeeded, or we already have another join in process
if !self.isJoiningRoom(withToken: token) {
NCUtils.log("Not joining the room any more. Ignore external signaling completion block, but we joined the Nextcloud instance before.")
completionBlock(nil, nil, nil, NCRoomsManager.statusCodeShouldIgnoreAttemptButJoinedSuccessfully, nil)
return
}
self.getSignalingSettingsHelper(for: activeAccount, forRoom: token) { signalingSettings in
let federation = signalingSettings?.getFederationJoinDictionary()
if !self.isJoiningRoom(withSessionId: sessionId ?? "") {
NCUtils.log("Joining the same room with a different sessionId. Ignore external signaling completion block.")
completionBlock(nil, nil, nil, NCRoomsManager.statusCodeIgnoreJoinAttempt, nil)
return
}
extSignalingController.joinRoom(token, withSessionId: sessionId, withFederation: federation) { error in
// If the sessionId is not the same anymore we tried to join with, we either already left again before
// joining the external signaling server succeeded, or we already have another join in process
if !self.isJoiningRoom(withToken: token) {
NCUtils.log("Not joining the room any more. Ignore external signaling completion block, but we joined the Nextcloud instance before.")
completionBlock(nil, nil, nil, NCRoomsManager.statusCodeShouldIgnoreAttemptButJoinedSuccessfully, nil)
return
}
if error == nil {
NCUtils.log("Joined room \(token) in external signaling server successfully.")
completionBlock(sessionId, room, nil, 0, nil)
} else {
NCUtils.log("Failed joining room \(token) in external signaling server.")
completionBlock(nil, nil, error, statusCode, statusReason)
if !self.isJoiningRoom(withSessionId: sessionId ?? "") {
NCUtils.log("Joining the same room with a different sessionId. Ignore external signaling completion block.")
completionBlock(nil, nil, nil, NCRoomsManager.statusCodeIgnoreJoinAttempt, nil)
return
}
if error == nil {
NCUtils.log("Joined room \(token) in external signaling server successfully.")
completionBlock(sessionId, room, nil, 0, nil)
} else {
NCUtils.log("Failed joining room \(token) in external signaling server.")
completionBlock(nil, nil, error, statusCode, statusReason)
}
}
}
})
}
private func getSignalingSettingsHelper(for account: TalkAccount, forRoom token: String, withCompletion completion: @escaping (SignalingSettings?) -> Void) {
// Currently we only need the signaling settings in case the room is federated and we support federation-v2
if let room = NCDatabaseManager.sharedInstance().room(withToken: token, forAccountId: account.accountId), room.isFederated,
NCDatabaseManager.sharedInstance().serverHasTalkCapability(kCapabilityFederationV2, forAccountId: account.accountId) {
NCAPIController.sharedInstance().getSignalingSettings(for: account, forRoom: token) { signalingSettings, _ in
completion(signalingSettings)
}
} else {
completion(nil)
}
}
public func rejoinRoom(_ token: String) {
guard let roomController = self.activeRooms[token] as? NCRoomController else { return }
@ -200,7 +217,11 @@ import Foundation
roomController.inChat = true
if let extSignalingController = NCSettingsController.sharedInstance().externalSignalingController(forAccountId: activeAccount.accountId) {
extSignalingController.joinRoom(token, withSessionId: sessionId, withCompletionBlock: nil)
self.getSignalingSettingsHelper(for: activeAccount, forRoom: token) { signalingSettings in
let federation = signalingSettings?.getFederationJoinDictionary()
extSignalingController.joinRoom(token, withSessionId: sessionId, withFederation: federation, withCompletionBlock: nil)
}
}
} else {
print("Could not re-join room. Status code: \(statusCode). Error: \(error?.localizedDescription ?? "Unknown")")

Просмотреть файл

@ -474,12 +474,10 @@ NSString * const kDidReceiveCallsFromOldAccount = @"receivedCallsFromOldAccount"
return;
}
[[NCAPIController sharedInstance] getSignalingSettingsForAccount:account withCompletionBlock:^(NSDictionary *settings, NSError *error) {
[[NCAPIController sharedInstance] getSignalingSettingsFor:account forRoom:nil completionBlock:^(SignalingSettings * _Nullable settings, NSError * _Nullable error) {
if (!error) {
NSDictionary *signalingConfiguration = [[settings objectForKey:@"ocs"] objectForKey:@"data"];
if (signalingConfiguration && account && account.accountId) {
[self->_signalingConfigurations setObject:signalingConfiguration forKey:account.accountId];
if (settings && account && account.accountId) {
[self->_signalingConfigurations setObject:settings forKey:account.accountId];
if (block) {
block(nil);
@ -501,16 +499,9 @@ NSString * const kDidReceiveCallsFromOldAccount = @"receivedCallsFromOldAccount"
// SetSignalingConfiguration should be called just once
- (void)setSignalingConfigurationForAccountId:(NSString *)accountId
{
NSDictionary *signalingConfiguration = [_signalingConfigurations objectForKey:accountId];
NSString *externalSignalingTicket = [signalingConfiguration objectForKey:@"ticket"];
NSString *externalSignalingServer = nil;
id server = [signalingConfiguration objectForKey:@"server"];
if ([server isKindOfClass:[NSString class]] && ![server isEqualToString:@""]) {
externalSignalingServer = server;
}
SignalingSettings *signalingSettings = [_signalingConfigurations objectForKey:accountId];
if (externalSignalingServer && externalSignalingTicket) {
if (signalingSettings.server && signalingSettings.server.length > 0 && signalingSettings.ticket && signalingSettings.ticket.length > 0) {
BGTaskHelper *bgTask = [BGTaskHelper startBackgroundTaskWithName:@"NCSetSignalingConfiguration" expirationHandler:nil];
dispatch_async(dispatch_get_main_queue(), ^{
@ -521,7 +512,7 @@ NSString * const kDidReceiveCallsFromOldAccount = @"receivedCallsFromOldAccount"
}
TalkAccount *account = [[NCDatabaseManager sharedInstance] talkAccountForAccountId:accountId];
extSignalingController = [[NCExternalSignalingController alloc] initWithAccount:account server:externalSignalingServer andTicket:externalSignalingTicket];
extSignalingController = [[NCExternalSignalingController alloc] initWithAccount:account server:signalingSettings.server andTicket:signalingSettings.ticket];
[self->_externalSignalingControllers setObject:extSignalingController forKey:accountId];
[bgTask stopBackgroundTask];

Просмотреть файл

@ -9,6 +9,7 @@
#import "NCSignalingMessage.h"
@class NCSignalingController;
@class SignalingSettings;
@protocol NCSignalingControllerObserver <NSObject>
@ -16,6 +17,8 @@
@end
typedef void (^SignalingSettingsUpdatedCompletionBlock)(SignalingSettings *signalingSettings);
@interface NCSignalingController : NSObject
@property (nonatomic, weak) id<NCSignalingControllerObserver> observer;
@ -25,5 +28,6 @@
- (void)startPullingSignalingMessages;
- (void)sendSignalingMessage:(NCSignalingMessage *)message;
- (void)stopAllRequests;
- (void)updateSignalingSettingsWithCompletionBlock:(SignalingSettingsUpdatedCompletionBlock)block;
@end

Просмотреть файл

@ -10,11 +10,13 @@
#import "NCAPIController.h"
#import "NCDatabaseManager.h"
#import "NextcloudTalk-Swift.h"
@interface NCSignalingController()
{
NCRoom *_room;
BOOL _shouldStopPullingMessages;
NSDictionary *_signalingSettings;
SignalingSettings *_signalingSettings;
NSURLSessionTask *_getSignalingSettingsTask;
NSURLSessionTask *_pullSignalingMessagesTask;
}
@ -28,7 +30,6 @@
self = [super init];
if (self) {
_room = room;
[self getSignalingSettings];
}
return self;
}
@ -38,16 +39,26 @@
NSLog(@"NCSignalingController dealloc");
}
- (void)getSignalingSettings
- (void)updateSignalingSettingsWithCompletionBlock:(SignalingSettingsUpdatedCompletionBlock)block
{
_getSignalingSettingsTask = [[NCAPIController sharedInstance] getSignalingSettingsForAccount:[[NCDatabaseManager sharedInstance] activeAccount] withCompletionBlock:^(NSDictionary *settings, NSError *error) {
TalkAccount *activeAccount = [[NCDatabaseManager sharedInstance] activeAccount];
_getSignalingSettingsTask = [[NCAPIController sharedInstance] getSignalingSettingsFor:activeAccount forRoom:_room.token completionBlock:^(SignalingSettings * _Nullable settings, NSError * _Nullable error) {
if (error) {
//TODO: Error handling
NSLog(@"Error getting signaling settings.");
if (error.code == NSURLErrorCancelled) {
return;
}
// TODO: Error handling
[NCUtils log:[NSString stringWithFormat:@"Could not get signaling settings. Error: %@", error.description]];
}
if (settings) {
self->_signalingSettings = [[settings objectForKey:@"ocs"] objectForKey:@"data"];
self->_signalingSettings = settings;
}
if (block) {
block(self->_signalingSettings);
}
}];
}
@ -55,36 +66,20 @@
- (NSArray *)getIceServers
{
NSMutableArray *servers = [[NSMutableArray alloc] init];
NSInteger signalingAPIVersion = [[NCAPIController sharedInstance] signalingAPIVersionForAccount:[[NCDatabaseManager sharedInstance] activeAccount]];
if (_signalingSettings) {
NSArray *stunServers = [_signalingSettings objectForKey:@"stunservers"];
for (NSDictionary *stunServer in stunServers) {
NSArray *stunURLs = nil;
if (signalingAPIVersion >= APIv3) {
stunURLs = [stunServer objectForKey:@"urls"];
} else {
NSString *stunURL = [stunServer objectForKey:@"url"];
stunURLs = @[stunURL];
}
RTCIceServer *iceServer = [[RTCIceServer alloc] initWithURLStrings:stunURLs
username:@""
credential:@""];
for (StunServer *stunServer in _signalingSettings.stunServers) {
RTCIceServer *iceServer = [[RTCIceServer alloc] initWithURLStrings:stunServer.urls
username:@""
credential:@""];
[servers addObject:iceServer];
}
NSArray *turnServers = [_signalingSettings objectForKey:@"turnservers"];
for (NSDictionary *turnServer in turnServers) {
NSArray *turnURLs = nil;
if (signalingAPIVersion >= APIv3) {
turnURLs = [turnServer objectForKey:@"urls"];
} else {
turnURLs = [turnServer objectForKey:@"url"];
}
NSString *turnUserName = [turnServer objectForKey:@"username"];
NSString *turnCredential = [turnServer objectForKey:@"credential"];
RTCIceServer *iceServer = [[RTCIceServer alloc] initWithURLStrings:turnURLs
username:turnUserName
credential:turnCredential];
for (TurnServer *turnServer in _signalingSettings.turnServers) {
RTCIceServer *iceServer = [[RTCIceServer alloc] initWithURLStrings:turnServer.urls
username:turnServer.username
credential:turnServer.credential];
[servers addObject:iceServer];
}
}

Просмотреть файл

@ -0,0 +1,66 @@
//
// SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
// SPDX-License-Identifier: GPL-3.0-or-later
//
import Foundation
@objcMembers public class SignalingSettings: NSObject {
public var server: String?
public var signalingMode: String?
public var ticket: String?
public var userId: String?
public var stunServers: [StunServer] = []
public var turnServers: [TurnServer] = []
public var federation: [String: Any]?
init?(dictionary: [String: Any]?) {
guard let dictionary else { return nil }
super.init()
self.server = dictionary["server"] as? String
self.signalingMode = dictionary["signalingMode"] as? String
self.ticket = dictionary["ticket"] as? String
self.userId = dictionary["userId"] as? String
self.federation = dictionary["federation"] as? [String: Any]
if let stunArray = dictionary["stunservers"] as? [[String: Any]] {
for case let stunDict in stunArray {
stunServers.append(StunServer(dictionary: stunDict))
}
}
if let turnArray = dictionary["turnservers"] as? [[String: Any]] {
for case let turnDict in turnArray {
turnServers.append(TurnServer(dictionary: turnDict))
}
}
}
public func getFederationJoinDictionary() -> [String: String]? {
guard let federation, !federation.isEmpty else { return nil }
var result: [String: String] = [:]
if let server = federation["server"] as? String {
result["signaling"] = server
}
if let roomid = federation["roomId"] as? String {
result["roomid"] = roomid
}
if let url = federation["nextcloudServer"] as? String {
// TODO: Add index.php here to be safe?
result["url"] = url + "/ocs/v2.php/apps/spreed/api/v3/signaling/backend"
}
if let helloAuthParams = federation["helloAuthParams"] as? [String: String], let token = helloAuthParams["token"] {
result["token"] = token
}
return result
}
}

Просмотреть файл

@ -0,0 +1,21 @@
//
// SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
// SPDX-License-Identifier: GPL-3.0-or-later
//
import Foundation
@objcMembers public class StunServer: NSObject {
public var urls: [String]?
init(dictionary: [String: Any]) {
super.init()
if let stunUrl = dictionary["url"] as? String {
urls = [stunUrl]
} else if let stunUrls = dictionary["urls"] as? [String] {
urls = stunUrls
}
}
}

Просмотреть файл

@ -0,0 +1,31 @@
//
// SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
// SPDX-License-Identifier: GPL-3.0-or-later
//
import Foundation
@objcMembers public class TurnServer: NSObject {
public var urls: [String]?
public var username: String?
public var credential: String?
init(dictionary: [String: Any]) {
super.init()
if let turnUrl = dictionary["url"] as? String {
urls = [turnUrl]
} else if let turnUrls = dictionary["urls"] as? [String] {
urls = turnUrls
}
if let turnUsername = dictionary["username"] as? String {
username = turnUsername
}
if let turnCredential = dictionary["credential"] as? String {
credential = turnCredential
}
}
}