diff --git a/Session/Calls/Individual/IndividualCallService.swift b/Session/Calls/Individual/IndividualCallService.swift index ba9cd80c3..be739ef02 100644 --- a/Session/Calls/Individual/IndividualCallService.swift +++ b/Session/Calls/Individual/IndividualCallService.swift @@ -800,10 +800,9 @@ import SessionMessagingKit firstly { () throws -> Promise in let message = IndividualCallMessage() message.callID = callId - message.opaque = opaque switch callMediaType { - case .audioCall: message.kind = .offer(callType: .audio) - case .videoCall: message.kind = .offer(callType: .video) + case .audioCall: message.kind = .offer(opaque: opaque, callType: .audio) + case .videoCall: message.kind = .offer(opaque: opaque, callType: .video) } Storage.write { transaction in MessageSender.send(message, in: call.individualCall.thread, using: transaction) @@ -825,8 +824,7 @@ import SessionMessagingKit firstly { () throws -> Promise in let message = IndividualCallMessage() message.callID = callId - message.opaque = opaque - message.kind = .answer + message.kind = .answer(opaque: opaque) Storage.write { transaction in MessageSender.send(message, in: call.individualCall.thread, using: transaction) } @@ -844,24 +842,18 @@ import SessionMessagingKit owsAssertDebug(call.isIndividualCall) Logger.info("shouldSendIceCandidates") + guard !candidates.isEmpty else { + Logger.error("no ice updates to send") + return callManager.signalingMessageDidFail(callId: callId) + } + firstly { () throws -> Promise in - var iceUpdateProtos = [SNProtoCallMessageIceUpdate]() - - for iceCandidate in candidates { - let iceUpdateProto: SNProtoCallMessageIceUpdate - let iceUpdateBuilder = SNProtoCallMessageIceUpdate.builder(id: callId) - iceUpdateBuilder.setOpaque(iceCandidate) - - iceUpdateProto = try iceUpdateBuilder.build() - iceUpdateProtos.append(iceUpdateProto) + let message = IndividualCallMessage() + message.callID = callId + message.kind = .iceUpdate(candidates: candidates) + Storage.write { transaction in + MessageSender.send(message, in: call.individualCall.thread, using: transaction) } - - guard !iceUpdateProtos.isEmpty else { - throw OWSAssertionError("no ice updates to send") - } - - let callMessage = OWSOutgoingCallMessage(thread: call.individualCall.thread, iceUpdateMessages: iceUpdateProtos, destinationDeviceId: NSNumber(value: destinationDeviceId)) - return messageSender.sendMessage(.promise, callMessage.asPreparer) }.done { Logger.debug("sent ice update message to \(call.individualCall.thread.contactSessionID()) device: \((destinationDeviceId != nil) ? String(destinationDeviceId!) : "nil")") try self.callManager.signalingMessageDidSend(callId: callId) @@ -877,29 +869,20 @@ import SessionMessagingKit Logger.info("shouldSendHangup") firstly { () throws -> Promise in - let hangupBuilder = SNProtoCallMessageHangup.builder(id: callId) - + let type: IndividualCallMessage.HangupType switch hangupType { - case .normal: hangupBuilder.setType(.hangupNormal) - case .accepted: hangupBuilder.setType(.hangupAccepted) - case .declined: hangupBuilder.setType(.hangupDeclined) - case .busy: hangupBuilder.setType(.hangupBusy) - case .needPermission: hangupBuilder.setType(.hangupNeedPermission) + case .normal: type = .normal + case .accepted: type = .accepted + case .declined: type = .declined + case .busy: type = .busy + case .needPermission: type = .needPermission } - - if hangupType != .normal { - // deviceId is optional and only used when indicated by a hangup due to - // a call being accepted elsewhere. - hangupBuilder.setDeviceID(deviceId) + let message = IndividualCallMessage() + message.callID = callId + message.kind = .hangup(type: type) + Storage.write { transaction in + MessageSender.send(message, in: call.individualCall.thread, using: transaction) } - - let callMessage: OWSOutgoingCallMessage - if useLegacyHangupMessage { - callMessage = OWSOutgoingCallMessage(thread: call.individualCall.thread, legacyHangupMessage: try hangupBuilder.build(), destinationDeviceId: NSNumber(value: destinationDeviceId)) - } else { - callMessage = OWSOutgoingCallMessage(thread: call.individualCall.thread, hangupMessage: try hangupBuilder.build(), destinationDeviceId: NSNumber(value: destinationDeviceId)) - } - return messageSender.sendMessage(.promise, callMessage.asPreparer) }.done { Logger.debug("sent hangup message to \(call.individualCall.thread.contactSessionID()) device: \((destinationDeviceId != nil) ? String(destinationDeviceId!) : "nil")") try self.callManager.signalingMessageDidSend(callId: callId) @@ -915,9 +898,12 @@ import SessionMessagingKit Logger.info("shouldSendBusy") firstly { () throws -> Promise in - let busyBuilder = SNProtoCallMessageBusy.builder(id: callId) - let callMessage = OWSOutgoingCallMessage(thread: call.individualCall.thread, busyMessage: try busyBuilder.build(), destinationDeviceId: NSNumber(value: destinationDeviceId)) - return messageSender.sendMessage(.promise, callMessage.asPreparer) + let message = IndividualCallMessage() + message.callID = callId + message.kind = .busy + Storage.write { transaction in + MessageSender.send(message, in: call.individualCall.thread, using: transaction) + } }.done { Logger.debug("sent busy message to \(call.individualCall.thread.contactSessionID()) device: \((destinationDeviceId != nil) ? String(destinationDeviceId!) : "nil")") try self.callManager.signalingMessageDidSend(callId: callId) diff --git a/SessionMessagingKit/Messages/Control Messages/IndividualCallMessage.swift b/SessionMessagingKit/Messages/Control Messages/IndividualCallMessage.swift index 4167d941b..92bb21f3c 100644 --- a/SessionMessagingKit/Messages/Control Messages/IndividualCallMessage.swift +++ b/SessionMessagingKit/Messages/Control Messages/IndividualCallMessage.swift @@ -2,38 +2,50 @@ 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 { + public enum CallType : String { case audio, video - public var description: String { - switch self { - case .audio: return "audio" - case .video: return "video" + fileprivate static func from(_ proto: SNProtoCallMessageOffer.SNProtoCallMessageOfferType) -> CallType { + switch proto { + case .offerAudioCall: return .audio + case .offerVideoCall: return .video + } + } + } + + // MARK: Hangup Type + public enum HangupType : String { + case normal, accepted, declined, busy, needPermission + + fileprivate static func from(_ proto: SNProtoCallMessageHangup.SNProtoCallMessageHangupType) -> HangupType { + switch proto { + case .hangupNormal: return .normal + case .hangupAccepted: return .accepted + case .hangupDeclined: return .declined + case .hangupBusy: return .busy + case .hangupNeedPermission: return .needPermission } } } // MARK: Kind public enum Kind : CustomStringConvertible { - case offer(callType: CallType) - case answer + case offer(opaque: Data, callType: CallType) + case answer(opaque: Data) + case iceUpdate(candidates: [Data]) + case hangup(type: HangupType) + case busy public var description: String { switch self { - case .offer(let callType): return "offer(callType: \(callType))" - case .answer: return "answer" + case .offer(let opaque, let callType): return "offer(opaque: \(opaque.count) bytes, callType: \(callType.rawValue))" + case .answer(let opaque): return "answer(opaque: \(opaque.count) bytes)" + case .iceUpdate(let candidates): return "iceUpdate(candidates: \(candidates.count) candidates)" + case .hangup(let type): return "hangup(type: \(type.rawValue)" + case .busy: return "busy" } } } @@ -41,10 +53,9 @@ public final class IndividualCallMessage : ControlMessage { // MARK: Initialization public override init() { super.init() } - internal init(callID: UInt64, opaque: Data, kind: Kind) { + internal init(callID: UInt64, kind: Kind) { super.init() self.callID = callID - self.opaque = opaque self.kind = kind } @@ -67,22 +78,30 @@ public final class IndividualCallMessage : ControlMessage { 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 { + guard let opaque = offer.opaque else { return nil } callID = offer.id - opaqueOrNil = offer.opaque - let callType: CallType = (offer.type == .offerAudioCall) ? .audio : .video - kind = .offer(callType: callType) + let callType = CallType.from(offer.type) + kind = .offer(opaque: opaque, callType: callType) } else if let answer = callMessage.answer { + guard let opaque = answer.opaque else { return nil } callID = answer.id - opaqueOrNil = answer.opaque - kind = .answer + kind = .answer(opaque: opaque) + } else if !callMessage.iceUpdate.isEmpty { + callID = callMessage.iceUpdate.first!.id // TODO: Is this how it's supposed to work? + kind = .iceUpdate(candidates: callMessage.iceUpdate.compactMap { $0.opaque }) // Should never contain entries with a `nil` `opaque` + } else if let hangup = callMessage.hangup { + callID = hangup.id + let type = HangupType.from(hangup.type) + kind = .hangup(type: type) + } else if let busy = callMessage.busy { + callID = busy.id + kind = .busy } else { return nil } - guard let opaque = opaqueOrNil else { return nil } - return IndividualCallMessage(callID: callID, opaque: opaque, kind: kind) + return IndividualCallMessage(callID: callID, kind: kind) } public override func toProto(using transaction: YapDatabaseReadWriteTransaction) -> SNProtoContent? {