From daa28d413d8d2cd121d56ed23719794f8adc4166 Mon Sep 17 00:00:00 2001 From: Michelle Linington Date: Fri, 13 Nov 2020 22:56:18 -0800 Subject: [PATCH] Handle incoming GroupCallUpdate messages This builds out infrastructure to fetch updated PeekInfo structs from RingRTC on a GroupCallUpdate. There are still a bunch of TODOs to resolve once RingRTC adds PeekInfo. --- Signal/src/Calls/CallService.swift | 64 ++++++++++++++++++- .../GroupCallUpdateMessageHandler.swift | 4 ++ .../Signaling/WebRTCCallMessageHandler.swift | 7 ++ .../environment/NoopCallMessageHandler.swift | 4 ++ .../src/Messages/OWSMessageManager.m | 23 +++++++ .../src/Protocols/OWSCallMessageHandler.h | 6 ++ .../src/TestUtils/OWSFakeCallMessageHandler.m | 6 ++ 7 files changed, 113 insertions(+), 1 deletion(-) diff --git a/Signal/src/Calls/CallService.swift b/Signal/src/Calls/CallService.swift index 8f2695ff63..a9f4917f2b 100644 --- a/Signal/src/Calls/CallService.swift +++ b/Signal/src/Calls/CallService.swift @@ -548,7 +548,12 @@ extension CallService: CallObserver { } public func groupCallRemoteDeviceStatesChanged(_ call: SignalCall) {} - public func groupCallPeekChanged(_ call: SignalCall) {} + public func groupCallPeekChanged(_ call: SignalCall) { + // TODO: Fetch the real PeekInfo from call.groupCall.localDeviceState + let peekInfo = PeekInfo() + guard let groupThread = call.thread as? TSGroupThread else { return } + updateGroupCallMessageWithInfo(peekInfo, for: groupThread) + } public func groupCallRequestMembershipProof(_ call: SignalCall) { owsAssertDebug(call.isGroupCall) @@ -591,6 +596,63 @@ extension CallService: CallObserver { } } +// MARK: - Group call participant updates + +extension CallService { + + func peekCallAndUpdateThread(_ thread: TSGroupThread) { + let groupCall = (currentCall?.isGroupCall == true) ? currentCall?.groupCall : nil + let groupCallConnectionState = groupCall?.localDeviceState.connectionState + + guard currentCall?.thread != thread || groupCallConnectionState != .connected else { + // If we're already connected to the group call that we want to peek, ignore + // We'll have PeekInfo updates handed to us directly from an observer callback + Logger.info("Ignoring peek request for currently connected call") + return + } + + firstly { + // TODO: Fetch PeekInfo + return .value(PeekInfo()) + + }.done { info in + self.updateGroupCallMessageWithInfo(info, for: thread) + + }.catch { error in + Logger.error("Failed to fetch PeekInfo for \(thread): \(error)") + } + } + + fileprivate func updateGroupCallMessageWithInfo(_ info: PeekInfo, for thread: TSGroupThread) { + databaseStorage.write { writeTx in + // TODO: Build InteractionFinder method to find unended OWSGroupCallMessages for the current thread + let results: [OWSGroupCallMessage] = [] + + // Update everything that doesn't match the current call era to mark as ended + results + .filter { $0.conferenceId != info.eraId } + .forEach { toExpire in + toExpire.anyUpdateGroupCallMessage(transaction: writeTx) { $0.hasCallEnded = true } + } + + // Update the message for the current era if it exists, or insert a new one. + let currentEraMessages = results.filter { $0.conferenceId == info.eraId } + owsAssertDebug(currentEraMessages.count <= 1) + + if let currentMessage = results.first { + currentMessage.anyUpdateGroupCallMessage(transaction: writeTx) { (toUpdate) in + toUpdate.update(with: info, transaction: writeTx) + } + } else { + // TODO: Plumb through a more relevant timestamp if available + let timestamp = NSDate.ows_millisecondTimeStamp() + let newMessage = OWSGroupCallMessage(peekInfo: info, thread: thread, sentAtTimestamp: timestamp ) + newMessage.anyInsert(transaction: writeTx) + } + } + } +} + extension CallService: UIDatabaseSnapshotDelegate { public func uiDatabaseSnapshotWillUpdate() {} diff --git a/Signal/src/Calls/Signaling/GroupCallUpdateMessageHandler.swift b/Signal/src/Calls/Signaling/GroupCallUpdateMessageHandler.swift index a7b8a2cfbd..91616991be 100644 --- a/Signal/src/Calls/Signaling/GroupCallUpdateMessageHandler.swift +++ b/Signal/src/Calls/Signaling/GroupCallUpdateMessageHandler.swift @@ -36,6 +36,10 @@ class GroupCallUpdateMessageHandler: CallServiceObserver, CallObserver { } } + func handleUpdateMessage(_ message: SSKProtoDataMessageGroupCallUpdate, for thread: TSGroupThread) { + AppEnvironment.shared.callService.peekCallAndUpdateThread(thread) + } + // MARK: - CallServiceObserver func didUpdateCall(call: SignalCall?) { diff --git a/Signal/src/Calls/Signaling/WebRTCCallMessageHandler.swift b/Signal/src/Calls/Signaling/WebRTCCallMessageHandler.swift index 70fe2f3c95..637ac66b07 100644 --- a/Signal/src/Calls/Signaling/WebRTCCallMessageHandler.swift +++ b/Signal/src/Calls/Signaling/WebRTCCallMessageHandler.swift @@ -164,4 +164,11 @@ public class WebRTCCallMessageHandler: NSObject, OWSCallMessageHandler { messageAgeSec: messageAgeSec ) } + + public func receivedGroupCallUpdateMessage( + _ update: SSKProtoDataMessageGroupCallUpdate, + for thread: TSGroupThread) { + + self.callService.groupCallMessageHandler.handleUpdateMessage(update, for: thread) + } } diff --git a/SignalMessaging/environment/NoopCallMessageHandler.swift b/SignalMessaging/environment/NoopCallMessageHandler.swift index 53bb08f605..5f89c6283d 100644 --- a/SignalMessaging/environment/NoopCallMessageHandler.swift +++ b/SignalMessaging/environment/NoopCallMessageHandler.swift @@ -30,4 +30,8 @@ public class NoopCallMessageHandler: NSObject, OWSCallMessageHandler { public func receivedOpaque(_ opaque: SSKProtoCallMessageOpaque, from caller: SignalServiceAddress, sourceDevice device: UInt32, serverReceivedTimestamp: UInt64, serverDeliveryTimestamp: UInt64) { owsFailDebug("") } + + public func receivedGroupCallUpdateMessage(_ update: SSKProtoDataMessageGroupCallUpdate, for thread: TSGroupThread) { + owsFailDebug("") + } } diff --git a/SignalServiceKit/src/Messages/OWSMessageManager.m b/SignalServiceKit/src/Messages/OWSMessageManager.m index 5c0da4f23f..ba04922146 100644 --- a/SignalServiceKit/src/Messages/OWSMessageManager.m +++ b/SignalServiceKit/src/Messages/OWSMessageManager.m @@ -1699,6 +1699,19 @@ NS_ASSUME_NONNULL_BEGIN associatedMessageAuthor:envelope.sourceAddress]; break; } + } else if (dataMessage.groupCallUpdate != nil) { + TSGroupThread *_Nullable groupThread = nil; + NSData *_Nullable groupId = [self groupIdForDataMessage:dataMessage]; + if (groupId) { + groupThread = [TSGroupThread fetchWithGroupId:groupId transaction:transaction]; + } + + if (groupThread) { + [self.callMessageHandler receivedGroupCallUpdateMessage:dataMessage.groupCallUpdate forThread:groupThread]; + } else { + OWSLogError(@"Received GroupCallUpdate for unknown groupId: %@", groupId); + } + } else { [OWSRecordTranscriptJob processIncomingSentMessageTranscript:transcript @@ -2137,6 +2150,16 @@ NS_ASSUME_NONNULL_BEGIN return nil; } + if (dataMessage.groupCallUpdate) { + if (!thread.isGroupThread) { + OWSLogError(@"Invalid thread for GroupUpdateMessage: %@", thread); + return nil; + } + TSGroupThread *groupThread = (TSGroupThread *)thread; + [self.callMessageHandler receivedGroupCallUpdateMessage:dataMessage.groupCallUpdate + forThread:groupThread]; + } + NSString *body = dataMessage.body; MessageBodyRanges *_Nullable bodyRanges; diff --git a/SignalServiceKit/src/Protocols/OWSCallMessageHandler.h b/SignalServiceKit/src/Protocols/OWSCallMessageHandler.h index fc8d47ac48..3685f34b43 100644 --- a/SignalServiceKit/src/Protocols/OWSCallMessageHandler.h +++ b/SignalServiceKit/src/Protocols/OWSCallMessageHandler.h @@ -10,7 +10,9 @@ NS_ASSUME_NONNULL_BEGIN @class SSKProtoCallMessageIceUpdate; @class SSKProtoCallMessageOffer; @class SSKProtoCallMessageOpaque; +@class SSKProtoDataMessageGroupCallUpdate; @class SignalServiceAddress; +@class TSGroupThread; @protocol OWSCallMessageHandler @@ -45,6 +47,10 @@ NS_ASSUME_NONNULL_BEGIN serverReceivedTimestamp:(uint64_t)serverReceivedTimestamp serverDeliveryTimestamp:(uint64_t)serverDeliveryTimestamp NS_SWIFT_NAME(receivedOpaque(_:from:sourceDevice:serverReceivedTimestamp:serverDeliveryTimestamp:)); +- (void)receivedGroupCallUpdateMessage:(SSKProtoDataMessageGroupCallUpdate *)update + forThread:(TSGroupThread *)groupThread + NS_SWIFT_NAME(receivedGroupCallUpdateMessage(_:for:)); + @end NS_ASSUME_NONNULL_END diff --git a/SignalServiceKit/src/TestUtils/OWSFakeCallMessageHandler.m b/SignalServiceKit/src/TestUtils/OWSFakeCallMessageHandler.m index 68fe632cce..b104276c5c 100644 --- a/SignalServiceKit/src/TestUtils/OWSFakeCallMessageHandler.m +++ b/SignalServiceKit/src/TestUtils/OWSFakeCallMessageHandler.m @@ -59,6 +59,12 @@ NS_ASSUME_NONNULL_BEGIN OWSLogInfo(@""); } +- (void)receivedGroupCallUpdateMessage:(SSKProtoDataMessageGroupCallUpdate *)update + forThread:(TSGroupThread *)groupThread +{ + OWSLogInfo(@""); +} + @end #endif