Add IndividualCallMessage

voice-calls
Niels Andriesse 4 years ago
parent 814375c488
commit 92730961fe

@ -172,6 +172,7 @@
B822F9C826B376EF003B8CB8 /* DarwinNotificationCenter.m in Sources */ = {isa = PBXBuildFile; fileRef = B822F9C726B376EF003B8CB8 /* DarwinNotificationCenter.m */; };
B822F9C926B376F6003B8CB8 /* DarwinNotificationCenter.h in Headers */ = {isa = PBXBuildFile; fileRef = B822F9C626B376D2003B8CB8 /* DarwinNotificationCenter.h */; settings = {ATTRIBUTES = (Public, ); }; };
B822F9CB26B37798003B8CB8 /* DarwinNotificationName.swift in Sources */ = {isa = PBXBuildFile; fileRef = B822F9CA26B37798003B8CB8 /* DarwinNotificationName.swift */; };
B822F9CD26B3C538003B8CB8 /* IndividualCallMessage.swift in Sources */ = {isa = PBXBuildFile; fileRef = B822F9CC26B3C538003B8CB8 /* IndividualCallMessage.swift */; };
B8269D2925C7A4B400488AB4 /* InputView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8269D2825C7A4B400488AB4 /* InputView.swift */; };
B8269D3325C7A8C600488AB4 /* InputViewButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8269D3225C7A8C600488AB4 /* InputViewButton.swift */; };
B8269D3D25C7B34D00488AB4 /* InputTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B8269D3C25C7B34D00488AB4 /* InputTextView.swift */; };
@ -1176,6 +1177,7 @@
B822F9C626B376D2003B8CB8 /* DarwinNotificationCenter.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = DarwinNotificationCenter.h; sourceTree = "<group>"; };
B822F9C726B376EF003B8CB8 /* DarwinNotificationCenter.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = DarwinNotificationCenter.m; sourceTree = "<group>"; };
B822F9CA26B37798003B8CB8 /* DarwinNotificationName.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DarwinNotificationName.swift; sourceTree = "<group>"; };
B822F9CC26B3C538003B8CB8 /* IndividualCallMessage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IndividualCallMessage.swift; sourceTree = "<group>"; };
B8269D2825C7A4B400488AB4 /* InputView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputView.swift; sourceTree = "<group>"; };
B8269D3225C7A8C600488AB4 /* InputViewButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputViewButton.swift; sourceTree = "<group>"; };
B8269D3C25C7B34D00488AB4 /* InputTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InputTextView.swift; sourceTree = "<group>"; };
@ -2474,6 +2476,7 @@
B8F5F60225EDE16F003BF8D4 /* DataExtractionNotification.swift */,
C300A5E62554B07300555489 /* ExpirationTimerUpdate.swift */,
C3DA9C0625AE7396008F7C7E /* ConfigurationMessage.swift */,
B822F9CC26B3C538003B8CB8 /* IndividualCallMessage.swift */,
);
path = "Control Messages";
sourceTree = "<group>";
@ -4735,6 +4738,7 @@
C352A32F2557549C00338F3E /* NotifyPNServerJob.swift in Sources */,
C300A5F22554B09800555489 /* MessageSender.swift in Sources */,
C3C2A74D2553A39700C340D1 /* VisibleMessage.swift in Sources */,
B822F9CD26B3C538003B8CB8 /* IndividualCallMessage.swift in Sources */,
C32C5AAD256DBE8F003C73A2 /* TSInfoMessage.m in Sources */,
C32C5A13256DB7A5003C73A2 /* PushNotificationAPI.swift in Sources */,
C32A026325A801AA000ED5D4 /* NSData+messagePadding.m in Sources */,

@ -815,7 +815,7 @@ extension CallService {
}
}
fileprivate func postUserNotificationIfNecessary(message: OWSGroupCallMessage, transaction: SDSAnyWriteTransaction) {
fileprivate func postUserNotificationIfNecessary(message: OWSGroupCallMessage, transaction: YapDatabaseReadWriteTransaction) {
// The message can't be for the current call
guard self.currentCall?.thread.uniqueId != message.uniqueThreadId else { return }
// The creator of the call must be known, and it can't be the local user
@ -823,7 +823,7 @@ extension CallService {
// The message must have at least one participant
guard (message.joinedMemberUuids?.count ?? 0) > 0 else { return }
guard let thread = TSGroupThread.anyFetch(uniqueId: message.uniqueThreadId, transaction: transaction) else {
guard let thread = TSGroupThread.fetch(uniqueId: message.uniqueThreadId, transaction: transaction) else {
owsFailDebug("Unknown thread")
return
}
@ -836,10 +836,10 @@ extension CallService: DatabaseChangeDelegate {
public func databaseChangesDidUpdate(databaseChanges: DatabaseChanges) {
AssertIsOnMainThread()
owsAssertDebug(AppReadiness.isAppReady)
owsAssertDebug(AppReadiness.isAppReady())
guard let thread = currentCall?.thread,
thread.isGroupThread,
thread.isGroupThread(),
databaseChanges.didUpdate(thread: thread) else { return }
updateGroupMembersForCurrentCallIfNecessary()
@ -847,14 +847,14 @@ extension CallService: DatabaseChangeDelegate {
public func databaseChangesDidUpdateExternally() {
AssertIsOnMainThread()
owsAssertDebug(AppReadiness.isAppReady)
owsAssertDebug(AppReadiness.isAppReady())
updateGroupMembersForCurrentCallIfNecessary()
}
public func databaseChangesDidReset() {
AssertIsOnMainThread()
owsAssertDebug(AppReadiness.isAppReady)
owsAssertDebug(AppReadiness.isAppReady())
updateGroupMembersForCurrentCallIfNecessary()
}

@ -6,6 +6,7 @@ import Foundation
import PromiseKit
import SignalRingRTC
import WebRTC
import SessionMessagingKit
// MARK: - CallService
@ -797,14 +798,16 @@ import WebRTC
Logger.info("shouldSendOffer")
firstly { () throws -> Promise<Void> in
let offerBuilder = SNProtoCallMessageOffer.builder(id: callId)
offerBuilder.setOpaque(opaque)
let message = IndividualCallMessage()
message.callID = callId
message.opaque = opaque
switch callMediaType {
case .audioCall: offerBuilder.setType(.offerAudioCall)
case .videoCall: offerBuilder.setType(.offerVideoCall)
case .audioCall: message.kind = .offer(callType: .audio)
case .videoCall: message.kind = .offer(callType: .video)
}
Storage.write { transaction in
MessageSender.send(message, in: call.individualCall.thread, using: transaction)
}
let callMessage = OWSOutgoingCallMessage(thread: call.individualCall.thread, offerMessage: try offerBuilder.build(), destinationDeviceId: NSNumber(value: destinationDeviceId))
return messageSender.sendMessage(.promise, callMessage.asPreparer)
}.done {
Logger.info("sent offer message to \(call.individualCall.thread.contactSessionID()) device: \((destinationDeviceId != nil) ? String(destinationDeviceId!) : "nil")")
try self.callManager.signalingMessageDidSend(callId: callId)
@ -820,10 +823,13 @@ import WebRTC
Logger.info("shouldSendAnswer")
firstly { () throws -> Promise<Void> in
let answerBuilder = SNProtoCallMessageAnswer.builder(id: callId)
answerBuilder.setOpaque(opaque)
let callMessage = OWSOutgoingCallMessage(thread: call.individualCall.thread, answerMessage: try answerBuilder.build(), destinationDeviceId: NSNumber(value: destinationDeviceId))
return messageSender.sendMessage(.promise, callMessage.asPreparer)
let message = IndividualCallMessage()
message.callID = callId
message.opaque = opaque
message.kind = .answer
Storage.write { transaction in
MessageSender.send(message, in: call.individualCall.thread, using: transaction)
}
}.done {
Logger.debug("sent answer message to \(call.individualCall.thread.contactSessionID()) device: \((destinationDeviceId != nil) ? String(destinationDeviceId!) : "nil")")
try self.callManager.signalingMessageDidSend(callId: callId)

@ -0,0 +1,100 @@
import SessionUtilitiesKit
public final class IndividualCallMessage : ControlMessage {
public var callID: UInt64?
public var opaque: Data?
public var kind: Kind?
// let offerBuilder = SNProtoCallMessageOffer.builder(id: callId)
// offerBuilder.setOpaque(opaque)
// switch callMediaType {
// case .audioCall: offerBuilder.setType(.offerAudioCall)
// case .videoCall: offerBuilder.setType(.offerVideoCall)
// }
// let callMessage = OWSOutgoingCallMessage(thread: call.individualCall.thread, offerMessage: try offerBuilder.build(), destinationDeviceId: NSNumber(value: destinationDeviceId))
// MARK: Call Type
public enum CallType : CustomStringConvertible {
case audio, video
public var description: String {
switch self {
case .audio: return "audio"
case .video: return "video"
}
}
}
// MARK: Kind
public enum Kind : CustomStringConvertible {
case offer(callType: CallType)
case answer
public var description: String {
switch self {
case .offer(let callType): return "offer(callType: \(callType))"
case .answer: return "answer"
}
}
}
// MARK: Initialization
public override init() { super.init() }
internal init(callID: UInt64, opaque: Data, kind: Kind) {
super.init()
self.callID = callID
self.opaque = opaque
self.kind = kind
}
// MARK: Validation
public override var isValid: Bool {
guard super.isValid else { return false }
return true
}
// MARK: Coding
public required init?(coder: NSCoder) {
super.init(coder: coder)
}
public override func encode(with coder: NSCoder) {
super.encode(with: coder)
}
// MARK: Proto Conversion
public override class func fromProto(_ proto: SNProtoContent) -> IndividualCallMessage? {
guard let callMessage = proto.callMessage else { return nil }
let callID: UInt64
let opaqueOrNil: Data?
let kind: Kind
if let offer = callMessage.offer {
callID = offer.id
opaqueOrNil = offer.opaque
let callType: CallType = (offer.type == .offerAudioCall) ? .audio : .video
kind = .offer(callType: callType)
} else if let answer = callMessage.answer {
callID = answer.id
opaqueOrNil = answer.opaque
kind = .answer
} else {
return nil
}
guard let opaque = opaqueOrNil else { return nil }
return IndividualCallMessage(callID: callID, opaque: opaque, kind: kind)
}
public override func toProto(using transaction: YapDatabaseReadWriteTransaction) -> SNProtoContent? {
return nil
}
// MARK: Description
public override var description: String {
"""
IndividualCallMessage(
)
"""
}
}

@ -354,6 +354,9 @@ extension SNProtoTypingMessage.SNProtoTypingMessageBuilder {
if let _value = dataMessage {
builder.setDataMessage(_value)
}
if let _value = callMessage {
builder.setCallMessage(_value)
}
if let _value = receiptMessage {
builder.setReceiptMessage(_value)
}
@ -379,6 +382,10 @@ extension SNProtoTypingMessage.SNProtoTypingMessageBuilder {
proto.dataMessage = valueParam.proto
}
@objc public func setCallMessage(_ valueParam: SNProtoCallMessage) {
proto.callMessage = valueParam.proto
}
@objc public func setReceiptMessage(_ valueParam: SNProtoReceiptMessage) {
proto.receiptMessage = valueParam.proto
}
@ -408,6 +415,8 @@ extension SNProtoTypingMessage.SNProtoTypingMessageBuilder {
@objc public let dataMessage: SNProtoDataMessage?
@objc public let callMessage: SNProtoCallMessage?
@objc public let receiptMessage: SNProtoReceiptMessage?
@objc public let typingMessage: SNProtoTypingMessage?
@ -418,12 +427,14 @@ extension SNProtoTypingMessage.SNProtoTypingMessageBuilder {
private init(proto: SessionProtos_Content,
dataMessage: SNProtoDataMessage?,
callMessage: SNProtoCallMessage?,
receiptMessage: SNProtoReceiptMessage?,
typingMessage: SNProtoTypingMessage?,
configurationMessage: SNProtoConfigurationMessage?,
dataExtractionNotification: SNProtoDataExtractionNotification?) {
self.proto = proto
self.dataMessage = dataMessage
self.callMessage = callMessage
self.receiptMessage = receiptMessage
self.typingMessage = typingMessage
self.configurationMessage = configurationMessage
@ -446,6 +457,11 @@ extension SNProtoTypingMessage.SNProtoTypingMessageBuilder {
dataMessage = try SNProtoDataMessage.parseProto(proto.dataMessage)
}
var callMessage: SNProtoCallMessage? = nil
if proto.hasCallMessage {
callMessage = try SNProtoCallMessage.parseProto(proto.callMessage)
}
var receiptMessage: SNProtoReceiptMessage? = nil
if proto.hasReceiptMessage {
receiptMessage = try SNProtoReceiptMessage.parseProto(proto.receiptMessage)
@ -472,6 +488,7 @@ extension SNProtoTypingMessage.SNProtoTypingMessageBuilder {
let result = SNProtoContent(proto: proto,
dataMessage: dataMessage,
callMessage: callMessage,
receiptMessage: receiptMessage,
typingMessage: typingMessage,
configurationMessage: configurationMessage,

@ -210,6 +210,15 @@ struct SessionProtos_Content {
/// Clears the value of `dataMessage`. Subsequent reads from it will return its default value.
mutating func clearDataMessage() {self._dataMessage = nil}
var callMessage: SessionProtos_CallMessage {
get {return _callMessage ?? SessionProtos_CallMessage()}
set {_callMessage = newValue}
}
/// Returns true if `callMessage` has been explicitly set.
var hasCallMessage: Bool {return self._callMessage != nil}
/// Clears the value of `callMessage`. Subsequent reads from it will return its default value.
mutating func clearCallMessage() {self._callMessage = nil}
var receiptMessage: SessionProtos_ReceiptMessage {
get {return _receiptMessage ?? SessionProtos_ReceiptMessage()}
set {_receiptMessage = newValue}
@ -251,6 +260,7 @@ struct SessionProtos_Content {
init() {}
fileprivate var _dataMessage: SessionProtos_DataMessage? = nil
fileprivate var _callMessage: SessionProtos_CallMessage? = nil
fileprivate var _receiptMessage: SessionProtos_ReceiptMessage? = nil
fileprivate var _typingMessage: SessionProtos_TypingMessage? = nil
fileprivate var _configurationMessage: SessionProtos_ConfigurationMessage? = nil
@ -1959,6 +1969,7 @@ extension SessionProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
static let protoMessageName: String = _protobuf_package + ".Content"
static let _protobuf_nameMap: SwiftProtobuf._NameMap = [
1: .same(proto: "dataMessage"),
3: .same(proto: "callMessage"),
5: .same(proto: "receiptMessage"),
6: .same(proto: "typingMessage"),
7: .same(proto: "configurationMessage"),
@ -1981,6 +1992,7 @@ extension SessionProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
// enabled. https://github.com/apple/swift-protobuf/issues/1034
switch fieldNumber {
case 1: try { try decoder.decodeSingularMessageField(value: &self._dataMessage) }()
case 3: try { try decoder.decodeSingularMessageField(value: &self._callMessage) }()
case 5: try { try decoder.decodeSingularMessageField(value: &self._receiptMessage) }()
case 6: try { try decoder.decodeSingularMessageField(value: &self._typingMessage) }()
case 7: try { try decoder.decodeSingularMessageField(value: &self._configurationMessage) }()
@ -1994,6 +2006,9 @@ extension SessionProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
if let v = self._dataMessage {
try visitor.visitSingularMessageField(value: v, fieldNumber: 1)
}
if let v = self._callMessage {
try visitor.visitSingularMessageField(value: v, fieldNumber: 3)
}
if let v = self._receiptMessage {
try visitor.visitSingularMessageField(value: v, fieldNumber: 5)
}
@ -2011,6 +2026,7 @@ extension SessionProtos_Content: SwiftProtobuf.Message, SwiftProtobuf._MessageIm
static func ==(lhs: SessionProtos_Content, rhs: SessionProtos_Content) -> Bool {
if lhs._dataMessage != rhs._dataMessage {return false}
if lhs._callMessage != rhs._callMessage {return false}
if lhs._receiptMessage != rhs._receiptMessage {return false}
if lhs._typingMessage != rhs._typingMessage {return false}
if lhs._configurationMessage != rhs._configurationMessage {return false}

@ -36,6 +36,7 @@ message TypingMessage {
message Content {
optional DataMessage dataMessage = 1;
optional CallMessage callMessage = 3;
optional ReceiptMessage receiptMessage = 5;
optional TypingMessage typingMessage = 6;
optional ConfigurationMessage configurationMessage = 7;
@ -228,7 +229,7 @@ message DataMessage {
optional uint64 timestamp = 7;
optional Quote quote = 8;
repeated Preview preview = 10;
optional GroupCallUpdate groupCallUpdate = 19;
optional GroupCallUpdate groupCallUpdate = 19;
optional LokiProfile profile = 101;
optional OpenGroupInvitation openGroupInvitation = 102;
optional ClosedGroupControlMessage closedGroupControlMessage = 104;

Loading…
Cancel
Save