mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-23 05:54:14 +00:00
Use internal signalling
This commit is contained in:
parent
346b8160c4
commit
b8bee2bd70
@ -3,7 +3,7 @@
|
||||
@implementation Serialization
|
||||
|
||||
- (NSUInteger)currentLayer {
|
||||
return 113;
|
||||
return 114;
|
||||
}
|
||||
|
||||
- (id _Nullable)parseMessage:(NSData * _Nullable)data {
|
||||
|
@ -250,6 +250,7 @@ fileprivate let parsers: [Int32 : (BufferReader) -> Any?] = {
|
||||
dict[654302845] = { return Api.Update.parse_updateDialogFilter($0) }
|
||||
dict[-1512627963] = { return Api.Update.parse_updateDialogFilterOrder($0) }
|
||||
dict[889491791] = { return Api.Update.parse_updateDialogFilters($0) }
|
||||
dict[643940105] = { return Api.Update.parse_updatePhoneCallSignalingData($0) }
|
||||
dict[136574537] = { return Api.messages.VotesList.parse_votesList($0) }
|
||||
dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) }
|
||||
dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) }
|
||||
@ -841,7 +842,7 @@ public struct Api {
|
||||
return parser(reader)
|
||||
}
|
||||
else {
|
||||
telegramApiLog("Type constructor \(String(signature, radix: 16, uppercase: false)) not found")
|
||||
telegramApiLog("Type constructor \(String(UInt32(bitPattern: signature), radix: 16, uppercase: false)) not found")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
@ -5894,6 +5894,7 @@ public extension Api {
|
||||
case updateDialogFilter(flags: Int32, id: Int32, filter: Api.DialogFilter?)
|
||||
case updateDialogFilterOrder(order: [Int32])
|
||||
case updateDialogFilters
|
||||
case updatePhoneCallSignalingData(phoneCallId: Int64, data: Buffer)
|
||||
|
||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||
switch self {
|
||||
@ -6566,6 +6567,13 @@ public extension Api {
|
||||
buffer.appendInt32(889491791)
|
||||
}
|
||||
|
||||
break
|
||||
case .updatePhoneCallSignalingData(let phoneCallId, let data):
|
||||
if boxed {
|
||||
buffer.appendInt32(643940105)
|
||||
}
|
||||
serializeInt64(phoneCallId, buffer: buffer, boxed: false)
|
||||
serializeBytes(data, buffer: buffer, boxed: false)
|
||||
break
|
||||
}
|
||||
}
|
||||
@ -6732,6 +6740,8 @@ public extension Api {
|
||||
return ("updateDialogFilterOrder", [("order", order)])
|
||||
case .updateDialogFilters:
|
||||
return ("updateDialogFilters", [])
|
||||
case .updatePhoneCallSignalingData(let phoneCallId, let data):
|
||||
return ("updatePhoneCallSignalingData", [("phoneCallId", phoneCallId), ("data", data)])
|
||||
}
|
||||
}
|
||||
|
||||
@ -8063,6 +8073,20 @@ public extension Api {
|
||||
public static func parse_updateDialogFilters(_ reader: BufferReader) -> Update? {
|
||||
return Api.Update.updateDialogFilters
|
||||
}
|
||||
public static func parse_updatePhoneCallSignalingData(_ reader: BufferReader) -> Update? {
|
||||
var _1: Int64?
|
||||
_1 = reader.readInt64()
|
||||
var _2: Buffer?
|
||||
_2 = parseBytes(reader)
|
||||
let _c1 = _1 != nil
|
||||
let _c2 = _2 != nil
|
||||
if _c1 && _c2 {
|
||||
return Api.Update.updatePhoneCallSignalingData(phoneCallId: _1!, data: _2!)
|
||||
}
|
||||
else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public enum PopularContact: TypeConstructorDescription {
|
||||
|
@ -6477,6 +6477,21 @@ public extension Api {
|
||||
return result
|
||||
})
|
||||
}
|
||||
|
||||
public static func sendSignalingData(peer: Api.InputPhoneCall, data: Buffer) -> (FunctionDescription, Buffer, DeserializeFunctionResponse<Api.Bool>) {
|
||||
let buffer = Buffer()
|
||||
buffer.appendInt32(-8744061)
|
||||
peer.serialize(buffer, true)
|
||||
serializeBytes(data, buffer: buffer, boxed: false)
|
||||
return (FunctionDescription(name: "phone.sendSignalingData", parameters: [("peer", peer), ("data", data)]), buffer, DeserializeFunctionResponse { (buffer: Buffer) -> Api.Bool? in
|
||||
let reader = BufferReader(buffer)
|
||||
var result: Api.Bool?
|
||||
if let signature = reader.readInt32() {
|
||||
result = Api.parse(reader, signature: signature) as? Api.Bool
|
||||
}
|
||||
return result
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -98,6 +98,7 @@ enum AccountStateMutationOperation {
|
||||
case UpdateRecentGifs
|
||||
case UpdateChatInputState(PeerId, SynchronizeableChatInputState?)
|
||||
case UpdateCall(Api.PhoneCall)
|
||||
case AddCallSignalingData(Int64, Data)
|
||||
case UpdateLangPack(String, Api.LangPackDifference?)
|
||||
case UpdateMinAvailableMessage(MessageId)
|
||||
case UpdatePeerChatInclusion(peerId: PeerId, groupId: PeerGroupId, changedGroup: Bool)
|
||||
@ -425,6 +426,10 @@ struct AccountMutableState {
|
||||
self.addOperation(.UpdateCall(call))
|
||||
}
|
||||
|
||||
mutating func addCallSignalingData(callId: Int64, data: Data) {
|
||||
self.addOperation(.AddCallSignalingData(callId, data))
|
||||
}
|
||||
|
||||
mutating func addSyncChatListFilters() {
|
||||
self.addOperation(.SyncChatListFilters)
|
||||
}
|
||||
@ -439,7 +444,7 @@ struct AccountMutableState {
|
||||
|
||||
mutating func addOperation(_ operation: AccountStateMutationOperation) {
|
||||
switch operation {
|
||||
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll/*, .UpdateMessageReactions*/, .UpdateMedia, .ReadOutbox, .ReadGroupFeedInbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdatePeerChatUnreadMark, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .SyncChatListFilters, .UpdateChatListFilterOrder, .UpdateChatListFilter:
|
||||
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll/*, .UpdateMessageReactions*/, .UpdateMedia, .ReadOutbox, .ReadGroupFeedInbox, .MergePeerPresences, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .AddCallSignalingData, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdatePeerChatUnreadMark, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .SyncChatListFilters, .UpdateChatListFilterOrder, .UpdateChatListFilter:
|
||||
break
|
||||
case let .AddMessages(messages, location):
|
||||
for message in messages {
|
||||
@ -555,6 +560,7 @@ struct AccountReplayedFinalState {
|
||||
let updatedTypingActivities: [PeerId: [PeerId: PeerInputActivity?]]
|
||||
let updatedWebpages: [MediaId: TelegramMediaWebpage]
|
||||
let updatedCalls: [Api.PhoneCall]
|
||||
let addedCallSignalingData: [(Int64, Data)]
|
||||
let updatedPeersNearby: [PeerNearby]?
|
||||
let isContactUpdates: [(PeerId, Bool)]
|
||||
let delayNotificatonsUntil: Int32?
|
||||
@ -566,6 +572,7 @@ struct AccountFinalStateEvents {
|
||||
let updatedTypingActivities: [PeerId: [PeerId: PeerInputActivity?]]
|
||||
let updatedWebpages: [MediaId: TelegramMediaWebpage]
|
||||
let updatedCalls: [Api.PhoneCall]
|
||||
let addedCallSignalingData: [(Int64, Data)]
|
||||
let updatedPeersNearby: [PeerNearby]?
|
||||
let isContactUpdates: [(PeerId, Bool)]
|
||||
let displayAlerts: [(text: String, isDropAuth: Bool)]
|
||||
@ -576,15 +583,16 @@ struct AccountFinalStateEvents {
|
||||
let authorizationListUpdated: Bool
|
||||
|
||||
var isEmpty: Bool {
|
||||
return self.addedIncomingMessageIds.isEmpty && self.wasScheduledMessageIds.isEmpty && self.updatedTypingActivities.isEmpty && self.updatedWebpages.isEmpty && self.updatedCalls.isEmpty && self.updatedPeersNearby?.isEmpty ?? true && self.isContactUpdates.isEmpty && self.displayAlerts.isEmpty && delayNotificatonsUntil == nil && self.updatedMaxMessageId == nil && self.updatedQts == nil && self.externallyUpdatedPeerId.isEmpty && !authorizationListUpdated
|
||||
return self.addedIncomingMessageIds.isEmpty && self.wasScheduledMessageIds.isEmpty && self.updatedTypingActivities.isEmpty && self.updatedWebpages.isEmpty && self.updatedCalls.isEmpty && self.addedCallSignalingData.isEmpty && self.updatedPeersNearby?.isEmpty ?? true && self.isContactUpdates.isEmpty && self.displayAlerts.isEmpty && delayNotificatonsUntil == nil && self.updatedMaxMessageId == nil && self.updatedQts == nil && self.externallyUpdatedPeerId.isEmpty && !authorizationListUpdated
|
||||
}
|
||||
|
||||
init(addedIncomingMessageIds: [MessageId] = [], wasScheduledMessageIds: [MessageId] = [], updatedTypingActivities: [PeerId: [PeerId: PeerInputActivity?]] = [:], updatedWebpages: [MediaId: TelegramMediaWebpage] = [:], updatedCalls: [Api.PhoneCall] = [], updatedPeersNearby: [PeerNearby]? = nil, isContactUpdates: [(PeerId, Bool)] = [], displayAlerts: [(text: String, isDropAuth: Bool)] = [], delayNotificatonsUntil: Int32? = nil, updatedMaxMessageId: Int32? = nil, updatedQts: Int32? = nil, externallyUpdatedPeerId: Set<PeerId> = Set(), authorizationListUpdated: Bool = false) {
|
||||
init(addedIncomingMessageIds: [MessageId] = [], wasScheduledMessageIds: [MessageId] = [], updatedTypingActivities: [PeerId: [PeerId: PeerInputActivity?]] = [:], updatedWebpages: [MediaId: TelegramMediaWebpage] = [:], updatedCalls: [Api.PhoneCall] = [], addedCallSignalingData: [(Int64, Data)] = [], updatedPeersNearby: [PeerNearby]? = nil, isContactUpdates: [(PeerId, Bool)] = [], displayAlerts: [(text: String, isDropAuth: Bool)] = [], delayNotificatonsUntil: Int32? = nil, updatedMaxMessageId: Int32? = nil, updatedQts: Int32? = nil, externallyUpdatedPeerId: Set<PeerId> = Set(), authorizationListUpdated: Bool = false) {
|
||||
self.addedIncomingMessageIds = addedIncomingMessageIds
|
||||
self.wasScheduledMessageIds = wasScheduledMessageIds
|
||||
self.updatedTypingActivities = updatedTypingActivities
|
||||
self.updatedWebpages = updatedWebpages
|
||||
self.updatedCalls = updatedCalls
|
||||
self.addedCallSignalingData = addedCallSignalingData
|
||||
self.updatedPeersNearby = updatedPeersNearby
|
||||
self.isContactUpdates = isContactUpdates
|
||||
self.displayAlerts = displayAlerts
|
||||
@ -601,6 +609,7 @@ struct AccountFinalStateEvents {
|
||||
self.updatedTypingActivities = state.updatedTypingActivities
|
||||
self.updatedWebpages = state.updatedWebpages
|
||||
self.updatedCalls = state.updatedCalls
|
||||
self.addedCallSignalingData = state.addedCallSignalingData
|
||||
self.updatedPeersNearby = state.updatedPeersNearby
|
||||
self.isContactUpdates = state.isContactUpdates
|
||||
self.displayAlerts = state.state.state.displayAlerts
|
||||
@ -634,6 +643,6 @@ struct AccountFinalStateEvents {
|
||||
let externallyUpdatedPeerId = self.externallyUpdatedPeerId.union(other.externallyUpdatedPeerId)
|
||||
let authorizationListUpdated = self.authorizationListUpdated || other.authorizationListUpdated
|
||||
|
||||
return AccountFinalStateEvents(addedIncomingMessageIds: self.addedIncomingMessageIds + other.addedIncomingMessageIds, wasScheduledMessageIds: self.wasScheduledMessageIds + other.wasScheduledMessageIds, updatedTypingActivities: self.updatedTypingActivities, updatedWebpages: self.updatedWebpages, updatedCalls: self.updatedCalls + other.updatedCalls, isContactUpdates: self.isContactUpdates + other.isContactUpdates, displayAlerts: self.displayAlerts + other.displayAlerts, delayNotificatonsUntil: delayNotificatonsUntil, updatedMaxMessageId: updatedMaxMessageId, updatedQts: updatedQts, externallyUpdatedPeerId: externallyUpdatedPeerId, authorizationListUpdated: authorizationListUpdated)
|
||||
return AccountFinalStateEvents(addedIncomingMessageIds: self.addedIncomingMessageIds + other.addedIncomingMessageIds, wasScheduledMessageIds: self.wasScheduledMessageIds + other.wasScheduledMessageIds, updatedTypingActivities: self.updatedTypingActivities, updatedWebpages: self.updatedWebpages, updatedCalls: self.updatedCalls + other.updatedCalls, addedCallSignalingData: self.addedCallSignalingData + other.addedCallSignalingData, isContactUpdates: self.isContactUpdates + other.isContactUpdates, displayAlerts: self.displayAlerts + other.displayAlerts, delayNotificatonsUntil: delayNotificatonsUntil, updatedMaxMessageId: updatedMaxMessageId, updatedQts: updatedQts, externallyUpdatedPeerId: externallyUpdatedPeerId, authorizationListUpdated: authorizationListUpdated)
|
||||
}
|
||||
}
|
||||
|
@ -1282,6 +1282,8 @@ private func finalStateWithUpdatesAndServerTime(postbox: Postbox, network: Netwo
|
||||
updatedState.addUpdateChatInputState(peerId: peer.peerId, state: inputState)
|
||||
case let .updatePhoneCall(phoneCall):
|
||||
updatedState.addUpdateCall(phoneCall)
|
||||
case let .updatePhoneCallSignalingData(phoneCallId, data):
|
||||
updatedState.addCallSignalingData(callId: phoneCallId, data: data.makeData())
|
||||
case let .updateLangPackTooLong(langCode):
|
||||
updatedState.updateLangPack(langCode: langCode, difference: nil)
|
||||
case let .updateLangPack(difference):
|
||||
@ -2073,7 +2075,7 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation])
|
||||
var currentAddScheduledMessages: OptimizeAddMessagesState?
|
||||
for operation in operations {
|
||||
switch operation {
|
||||
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll/*, .UpdateMessageReactions*/, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ReadGroupFeedInbox, .ResetReadState, .ResetIncomingReadState, .UpdatePeerChatUnreadMark, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .SyncChatListFilters, .UpdateChatListFilter, .UpdateChatListFilterOrder:
|
||||
case .DeleteMessages, .DeleteMessagesWithGlobalIds, .EditMessage, .UpdateMessagePoll/*, .UpdateMessageReactions*/, .UpdateMedia, .MergeApiChats, .MergeApiUsers, .MergePeerPresences, .UpdatePeer, .ReadInbox, .ReadOutbox, .ReadGroupFeedInbox, .ResetReadState, .ResetIncomingReadState, .UpdatePeerChatUnreadMark, .ResetMessageTagSummary, .UpdateNotificationSettings, .UpdateGlobalNotificationSettings, .UpdateSecretChat, .AddSecretMessages, .ReadSecretOutbox, .AddPeerInputActivity, .UpdateCachedPeerData, .UpdatePinnedItemIds, .ReadMessageContents, .UpdateMessageImpressionCount, .UpdateInstalledStickerPacks, .UpdateRecentGifs, .UpdateChatInputState, .UpdateCall, .AddCallSignalingData, .UpdateLangPack, .UpdateMinAvailableMessage, .UpdateIsContact, .UpdatePeerChatInclusion, .UpdatePeersNearby, .UpdateTheme, .SyncChatListFilters, .UpdateChatListFilter, .UpdateChatListFilterOrder:
|
||||
if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty {
|
||||
result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location))
|
||||
}
|
||||
@ -2157,6 +2159,7 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
|
||||
var updatedSecretChatTypingActivities = Set<PeerId>()
|
||||
var updatedWebpages: [MediaId: TelegramMediaWebpage] = [:]
|
||||
var updatedCalls: [Api.PhoneCall] = []
|
||||
var addedCallSignalingData: [(Int64, Data)] = []
|
||||
var updatedPeersNearby: [PeerNearby]?
|
||||
var isContactUpdates: [(PeerId, Bool)] = []
|
||||
var stickerPackOperations: [AccountStateUpdateStickerPacksOperation] = []
|
||||
@ -2760,6 +2763,8 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
|
||||
})
|
||||
case let .UpdateCall(call):
|
||||
updatedCalls.append(call)
|
||||
case let .AddCallSignalingData(callId, data):
|
||||
addedCallSignalingData.append((callId, data))
|
||||
case let .UpdateLangPack(langCode, difference):
|
||||
if let difference = difference {
|
||||
if langPackDifferences[langCode] == nil {
|
||||
@ -3141,5 +3146,5 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
|
||||
requestChatListFiltersSync(transaction: transaction)
|
||||
}
|
||||
|
||||
return AccountReplayedFinalState(state: finalState, addedIncomingMessageIds: addedIncomingMessageIds, wasScheduledMessageIds: wasScheduledMessageIds, addedSecretMessageIds: addedSecretMessageIds, updatedTypingActivities: updatedTypingActivities, updatedWebpages: updatedWebpages, updatedCalls: updatedCalls, updatedPeersNearby: updatedPeersNearby, isContactUpdates: isContactUpdates, delayNotificatonsUntil: delayNotificatonsUntil)
|
||||
return AccountReplayedFinalState(state: finalState, addedIncomingMessageIds: addedIncomingMessageIds, wasScheduledMessageIds: wasScheduledMessageIds, addedSecretMessageIds: addedSecretMessageIds, updatedTypingActivities: updatedTypingActivities, updatedWebpages: updatedWebpages, updatedCalls: updatedCalls, addedCallSignalingData: addedCallSignalingData, updatedPeersNearby: updatedPeersNearby, isContactUpdates: isContactUpdates, delayNotificatonsUntil: delayNotificatonsUntil)
|
||||
}
|
||||
|
@ -653,6 +653,11 @@ public final class AccountStateManager {
|
||||
strongSelf.callSessionManager.updateSession(call, completion: { _ in })
|
||||
}
|
||||
}
|
||||
if !events.addedCallSignalingData.isEmpty {
|
||||
for (id, data) in events.addedCallSignalingData {
|
||||
strongSelf.callSessionManager.addCallSignalingData(id: id, data: data)
|
||||
}
|
||||
}
|
||||
if !events.isContactUpdates.isEmpty {
|
||||
strongSelf.addIsContactUpdates(events.isContactUpdates)
|
||||
}
|
||||
|
@ -213,12 +213,15 @@ private final class CallSessionContext {
|
||||
let isOutgoing: Bool
|
||||
var state: CallSessionInternalState
|
||||
let subscribers = Bag<(CallSession) -> Void>()
|
||||
let signalingSubscribers = Bag<(Data) -> Void>()
|
||||
|
||||
let signalingDisposables = DisposableSet()
|
||||
|
||||
let acknowledgeIncomingCallDisposable = MetaDisposable()
|
||||
|
||||
var isEmpty: Bool {
|
||||
if case .terminated = self.state {
|
||||
return self.subscribers.isEmpty
|
||||
return self.subscribers.isEmpty && self.signalingSubscribers.isEmpty
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
@ -321,6 +324,31 @@ private final class CallSessionManagerContext {
|
||||
}
|
||||
}
|
||||
|
||||
func callSignalingData(internalId: CallSessionInternalId) -> Signal<Data, NoError> {
|
||||
let queue = self.queue
|
||||
return Signal { [weak self] subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
queue.async {
|
||||
if let strongSelf = self, let context = strongSelf.contexts[internalId] {
|
||||
let index = context.signalingSubscribers.add { next in
|
||||
subscriber.putNext(next)
|
||||
}
|
||||
disposable.set(ActionDisposable {
|
||||
queue.async {
|
||||
if let strongSelf = self, let context = strongSelf.contexts[internalId] {
|
||||
context.signalingSubscribers.remove(index)
|
||||
if context.isEmpty {
|
||||
strongSelf.contexts.removeValue(forKey: internalId)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
|
||||
private func ringingStatesValue() -> [CallSessionRingingState] {
|
||||
var ringingContexts: [CallSessionRingingState] = []
|
||||
for (id, context) in self.contexts {
|
||||
@ -523,6 +551,17 @@ private final class CallSessionManagerContext {
|
||||
}
|
||||
}
|
||||
|
||||
func sendSignalingData(internalId: CallSessionInternalId, data: Data) {
|
||||
if let context = self.contexts[internalId] {
|
||||
switch context.state {
|
||||
case let .active(id, accessHash, _, _, _, _, _, _, _, _):
|
||||
context.signalingDisposables.add(self.network.request(Api.functions.phone.sendSignalingData(peer: .inputPhoneCall(id: id, accessHash: accessHash), data: Buffer(data: data))).start())
|
||||
default:
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func updateSession(_ call: Api.PhoneCall, completion: @escaping ((CallSessionRingingState, CallSession)?) -> Void) {
|
||||
var resultRingingState: (CallSessionRingingState, CallSession)?
|
||||
|
||||
@ -723,6 +762,15 @@ private final class CallSessionManagerContext {
|
||||
completion(resultRingingState)
|
||||
}
|
||||
|
||||
func addCallSignalingData(id: Int64, data: Data) {
|
||||
guard let internalId = self.contextIdByStableId[id], let context = self.contexts[internalId] else {
|
||||
return
|
||||
}
|
||||
for f in context.signalingSubscribers.copyItems() {
|
||||
f(data)
|
||||
}
|
||||
}
|
||||
|
||||
private func makeSessionEncryptionKey(config: SecretChatEncryptionConfig, gAHash: Data, b: Data, gA: Data) -> (key: Data, keyId: Int64, keyVisualHash: Data)? {
|
||||
var key = MTExp(self.network.encryptionProvider, gA, b, config.p.makeData())!
|
||||
|
||||
@ -818,6 +866,12 @@ public final class CallSessionManager {
|
||||
}
|
||||
}
|
||||
|
||||
func addCallSignalingData(id: Int64, data: Data) {
|
||||
self.withContext { context in
|
||||
context.addCallSignalingData(id: id, data: data)
|
||||
}
|
||||
}
|
||||
|
||||
public func drop(internalId: CallSessionInternalId, reason: DropCallReason, debugLog: Signal<String?, NoError>) {
|
||||
self.withContext { context in
|
||||
context.drop(internalId: internalId, reason: reason, debugLog: debugLog)
|
||||
@ -857,6 +911,12 @@ public final class CallSessionManager {
|
||||
}
|
||||
}
|
||||
|
||||
public func sendSignalingData(internalId: CallSessionInternalId, data: Data) {
|
||||
self.withContext { context in
|
||||
context.sendSignalingData(internalId: internalId, data: data)
|
||||
}
|
||||
}
|
||||
|
||||
public func ringingStates() -> Signal<[CallSessionRingingState], NoError> {
|
||||
return Signal { [weak self] subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
@ -880,6 +940,18 @@ public final class CallSessionManager {
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
|
||||
public func callSignalingData(internalId: CallSessionInternalId) -> Signal<Data, NoError> {
|
||||
return Signal { [weak self] subscriber in
|
||||
let disposable = MetaDisposable()
|
||||
self?.withContext { context in
|
||||
disposable.set(context.callSignalingData(internalId: internalId).start(next: { next in
|
||||
subscriber.putNext(next)
|
||||
}))
|
||||
}
|
||||
return disposable
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private enum AcceptedCall {
|
||||
|
@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
|
||||
|
||||
public class Serialization: NSObject, MTSerialization {
|
||||
public func currentLayer() -> UInt {
|
||||
return 113
|
||||
return 114
|
||||
}
|
||||
|
||||
public func parseMessage(_ data: Data!) -> Any! {
|
||||
|
@ -383,6 +383,8 @@ public final class OngoingCallContext {
|
||||
return self.contextState.get()
|
||||
}
|
||||
|
||||
private var signalingDataDisposable: Disposable?
|
||||
|
||||
private let receptionPromise = Promise<Int32?>(nil)
|
||||
public var reception: Signal<Int32?, NoError> {
|
||||
return self.receptionPromise.get()
|
||||
@ -428,7 +430,9 @@ public final class OngoingCallContext {
|
||||
break
|
||||
}
|
||||
}
|
||||
let context = OngoingCallThreadLocalContextWebrtcCustom(queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForTypeWebrtcCustom(initialNetworkType), dataSaving: ongoingDataSavingForTypeWebrtcCustom(dataSaving), derivedState: derivedState.data, key: key, isOutgoing: isOutgoing, primaryConnection: callConnectionDescriptionWebrtcCustom(connections.primary), alternativeConnections: connections.alternatives.map(callConnectionDescriptionWebrtcCustom), maxLayer: maxLayer, allowP2P: allowP2P, logPath: logPath)
|
||||
let context = OngoingCallThreadLocalContextWebrtcCustom(queue: OngoingCallThreadLocalContextQueueImpl(queue: queue), proxy: voipProxyServer, networkType: ongoingNetworkTypeForTypeWebrtcCustom(initialNetworkType), dataSaving: ongoingDataSavingForTypeWebrtcCustom(dataSaving), derivedState: derivedState.data, key: key, isOutgoing: isOutgoing, primaryConnection: callConnectionDescriptionWebrtcCustom(connections.primary), alternativeConnections: connections.alternatives.map(callConnectionDescriptionWebrtcCustom), maxLayer: maxLayer, allowP2P: allowP2P, logPath: logPath, sendSignalingData: { [weak callSessionManager] data in
|
||||
callSessionManager?.sendSignalingData(internalId: internalId, data: data)
|
||||
})
|
||||
|
||||
strongSelf.contextRef = Unmanaged.passRetained(OngoingCallThreadLocalContextHolder(context))
|
||||
context.stateChanged = { state in
|
||||
@ -499,6 +503,15 @@ public final class OngoingCallContext {
|
||||
}
|
||||
}
|
||||
}))
|
||||
|
||||
self.signalingDataDisposable = (callSessionManager.callSignalingData(internalId: internalId)
|
||||
|> deliverOn(self.queue)).start(next: { [weak self] data in
|
||||
self?.withContext { context in
|
||||
if let context = context as? OngoingCallThreadLocalContextWebrtcCustom {
|
||||
context.receiveSignaling(data)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
deinit {
|
||||
|
@ -66,7 +66,7 @@ typedef NS_ENUM(int32_t, OngoingCallDataSavingWebrtcCustom) {
|
||||
@property (nonatomic, copy) void (^ _Nullable stateChanged)(OngoingCallStateWebrtcCustom);
|
||||
@property (nonatomic, copy) void (^ _Nullable signalBarsChanged)(int32_t);
|
||||
|
||||
- (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtcCustom> _Nonnull)queue proxy:(VoipProxyServerWebrtcCustom * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtcCustom)networkType dataSaving:(OngoingCallDataSavingWebrtcCustom)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing primaryConnection:(OngoingCallConnectionDescriptionWebrtcCustom * _Nonnull)primaryConnection alternativeConnections:(NSArray<OngoingCallConnectionDescriptionWebrtcCustom *> * _Nonnull)alternativeConnections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath;
|
||||
- (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtcCustom> _Nonnull)queue proxy:(VoipProxyServerWebrtcCustom * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtcCustom)networkType dataSaving:(OngoingCallDataSavingWebrtcCustom)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing primaryConnection:(OngoingCallConnectionDescriptionWebrtcCustom * _Nonnull)primaryConnection alternativeConnections:(NSArray<OngoingCallConnectionDescriptionWebrtcCustom *> * _Nonnull)alternativeConnections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath sendSignalingData:(void (^)(NSData * _Nonnull))sendSignalingData;
|
||||
- (void)stop:(void (^_Nullable)(NSString * _Nullable debugLog, int64_t bytesSentWifi, int64_t bytesReceivedWifi, int64_t bytesSentMobile, int64_t bytesReceivedMobile))completion;
|
||||
|
||||
- (bool)needRate;
|
||||
@ -75,6 +75,9 @@ typedef NS_ENUM(int32_t, OngoingCallDataSavingWebrtcCustom) {
|
||||
- (NSString * _Nullable)version;
|
||||
- (NSData * _Nonnull)getDerivedState;
|
||||
|
||||
|
||||
- (void)receiveSignalingData:(NSData * _Nonnull)data;
|
||||
|
||||
- (void)setIsMuted:(bool)isMuted;
|
||||
- (void)setNetworkType:(OngoingCallNetworkTypeWebrtcCustom)networkType;
|
||||
- (void)getRemoteCameraView:(void (^_Nonnull)(UIView * _Nullable))completion;
|
||||
|
@ -38,233 +38,6 @@ static void voipLog(NSString* format, ...) {
|
||||
}
|
||||
}
|
||||
|
||||
@class NativeWebSocketDelegate;
|
||||
|
||||
API_AVAILABLE(ios(13.0))
|
||||
@interface NativeWebSocket : NSObject {
|
||||
id<OngoingCallThreadLocalContextQueueWebrtcCustom> _queue;
|
||||
NativeWebSocketDelegate *_socketDelegate;
|
||||
void (^_receivedData)(NSData *);
|
||||
|
||||
NSURLSession *_session;
|
||||
NSURLSessionWebSocketTask *_socket;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
API_AVAILABLE(ios(13.0))
|
||||
@interface NativeWebSocketDelegate: NSObject <NSURLSessionDelegate, NSURLSessionWebSocketDelegate> {
|
||||
id<OngoingCallThreadLocalContextQueueWebrtcCustom> _queue;
|
||||
__weak NativeWebSocket *_target;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NativeWebSocketDelegate
|
||||
|
||||
- (instancetype)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtcCustom>)queue target:(NativeWebSocket *)target {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_queue = queue;
|
||||
_target = target;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)URLSession:(NSURLSession *)session webSocketTask:(NSURLSessionWebSocketTask *)webSocketTask didOpenWithProtocol:(NSString *)protocol {
|
||||
}
|
||||
|
||||
- (void)URLSession:(NSURLSession *)session webSocketTask:(NSURLSessionWebSocketTask *)webSocketTask didCloseWithCode:(NSURLSessionWebSocketCloseCode)closeCode reason:(NSData *)reason {
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation NativeWebSocket
|
||||
|
||||
- (instancetype)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtcCustom>)queue receivedData:(void (^)(NSData *))receivedData {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_queue = queue;
|
||||
_receivedData = [receivedData copy];
|
||||
_socketDelegate = [[NativeWebSocketDelegate alloc] initWithQueue:queue target:self];
|
||||
_session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:_socketDelegate delegateQueue:nil];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)connect {
|
||||
_socket = [_session webSocketTaskWithURL:[[NSURL alloc] initWithString:@"ws://192.168.8.118:8080"]];
|
||||
[_socket resume];
|
||||
[self readMessage];
|
||||
}
|
||||
|
||||
- (void)readMessage {
|
||||
id<OngoingCallThreadLocalContextQueueWebrtcCustom> queue = _queue;
|
||||
__weak NativeWebSocket *weakSelf = self;
|
||||
[_socket receiveMessageWithCompletionHandler:^(NSURLSessionWebSocketMessage * _Nullable message, NSError * _Nullable error) {
|
||||
[queue dispatch:^{
|
||||
__strong NativeWebSocket *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (error != nil) {
|
||||
voipLog(@"WebSocket error: %@", error);
|
||||
} else if (message.data != nil) {
|
||||
if (strongSelf->_receivedData) {
|
||||
strongSelf->_receivedData(message.data);
|
||||
}
|
||||
[strongSelf readMessage];
|
||||
} else {
|
||||
[strongSelf readMessage];
|
||||
}
|
||||
}];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)sendData:(NSData *)data {
|
||||
[_socket sendMessage:[[NSURLSessionWebSocketMessage alloc] initWithData:data] completionHandler:^(__unused NSError * _Nullable error) {
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)disconned {
|
||||
[_socket cancel];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@protocol NativeWebrtcSignallingClientDelegate <NSObject>
|
||||
|
||||
@end
|
||||
|
||||
API_AVAILABLE(ios(13.0))
|
||||
@interface NativeWebrtcSignallingClient : NSObject {
|
||||
id<OngoingCallThreadLocalContextQueueWebrtcCustom> _queue;
|
||||
NativeWebSocket *_socket;
|
||||
void (^_didReceiveSessionDescription)(RTCSessionDescription *);
|
||||
void (^_didReceiveIceCandidate)(RTCIceCandidate *);
|
||||
}
|
||||
|
||||
@property (nonatomic, weak) id<NativeWebrtcSignallingClientDelegate> delegate;
|
||||
|
||||
@end
|
||||
|
||||
@implementation NativeWebrtcSignallingClient
|
||||
|
||||
- (instancetype)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtcCustom>)queue didReceiveSessionDescription:(void (^)(RTCSessionDescription *))didReceiveSessionDescription didReceiveIceCandidate:(void (^)(RTCIceCandidate *))didReceiveIceCandidate {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_queue = queue;
|
||||
_didReceiveSessionDescription = [didReceiveSessionDescription copy];
|
||||
_didReceiveIceCandidate = [didReceiveIceCandidate copy];
|
||||
|
||||
__weak NativeWebrtcSignallingClient *weakSelf = self;
|
||||
_socket = [[NativeWebSocket alloc] initWithQueue:queue receivedData:^(NSData *data) {
|
||||
__strong NativeWebrtcSignallingClient *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
[strongSelf didReceiveData:data];
|
||||
}];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)connect {
|
||||
[_socket connect];
|
||||
}
|
||||
|
||||
- (void)sendSdp:(RTCSessionDescription *)rtcSdp {
|
||||
NSMutableDictionary *json = [[NSMutableDictionary alloc] init];
|
||||
json[@"messageType"] = @"sessionDescription";
|
||||
json[@"sdp"] = rtcSdp.sdp;
|
||||
if (rtcSdp.type == RTCSdpTypeOffer) {
|
||||
json[@"type"] = @"offer";
|
||||
} else if (rtcSdp.type == RTCSdpTypePrAnswer) {
|
||||
json[@"type"] = @"prAnswer";
|
||||
} else if (rtcSdp.type == RTCSdpTypeAnswer) {
|
||||
json[@"type"] = @"answer";
|
||||
}
|
||||
NSData *data = [NSJSONSerialization dataWithJSONObject:json options:0 error:nil];
|
||||
if (data != nil) {
|
||||
[_socket sendData:data];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)sendCandidate:(RTCIceCandidate *)rtcIceCandidate {
|
||||
NSMutableDictionary *json = [[NSMutableDictionary alloc] init];
|
||||
json[@"messageType"] = @"iceCandidate";
|
||||
json[@"sdp"] = rtcIceCandidate.sdp;
|
||||
json[@"mLineIndex"] = @(rtcIceCandidate.sdpMLineIndex);
|
||||
if (rtcIceCandidate.sdpMid != nil) {
|
||||
json[@"sdpMid"] = rtcIceCandidate.sdpMid;
|
||||
}
|
||||
NSData *data = [NSJSONSerialization dataWithJSONObject:json options:0 error:nil];
|
||||
if (data != nil) {
|
||||
[_socket sendData:data];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)didReceiveData:(NSData *)data {
|
||||
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
|
||||
if (![json isKindOfClass:[NSDictionary class]]) {
|
||||
return;
|
||||
}
|
||||
NSString *messageType = json[@"messageType"];
|
||||
if (![messageType isKindOfClass:[NSString class]]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ([messageType isEqualToString:@"sessionDescription"]) {
|
||||
NSString *sdp = json[@"sdp"];
|
||||
if (![sdp isKindOfClass:[NSString class]]) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *typeString = json[@"type"];
|
||||
if (![typeString isKindOfClass:[NSString class]]) {
|
||||
return;
|
||||
}
|
||||
|
||||
RTCSdpType type;
|
||||
if ([typeString isEqualToString:@"offer"]) {
|
||||
type = RTCSdpTypeOffer;
|
||||
} else if ([typeString isEqualToString:@"prAnswer"]) {
|
||||
type = RTCSdpTypePrAnswer;
|
||||
} else if ([typeString isEqualToString:@"answer"]) {
|
||||
type = RTCSdpTypeAnswer;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_didReceiveSessionDescription) {
|
||||
_didReceiveSessionDescription([[RTCSessionDescription alloc] initWithType:type sdp:sdp]);
|
||||
}
|
||||
} else if ([messageType isEqualToString:@"iceCandidate"]) {
|
||||
NSString *sdp = json[@"sdp"];
|
||||
if (![sdp isKindOfClass:[NSString class]]) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSNumber *mLineIndex = json[@"mLineIndex"];
|
||||
if (![mLineIndex isKindOfClass:[NSNumber class]]) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *sdpMidString = json[@"sdpMid"];
|
||||
NSString *sdpMid = nil;
|
||||
if ([sdpMidString isKindOfClass:[NSString class]]) {
|
||||
sdpMid = sdpMidString;
|
||||
}
|
||||
|
||||
if (_didReceiveIceCandidate) {
|
||||
_didReceiveIceCandidate([[RTCIceCandidate alloc] initWithSdp:sdp sdpMLineIndex:[mLineIndex intValue] sdpMid:sdpMid]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@interface NativePeerConnectionDelegate : NSObject <RTCPeerConnectionDelegate> {
|
||||
id<OngoingCallThreadLocalContextQueueWebrtcCustom> _queue;
|
||||
void (^_didGenerateIceCandidate)(RTCIceCandidate *);
|
||||
@ -361,6 +134,9 @@ API_AVAILABLE(ios(13.0))
|
||||
id<OngoingCallThreadLocalContextQueueWebrtcCustom> _queue;
|
||||
int32_t _contextId;
|
||||
|
||||
bool _isOutgoing;
|
||||
void (^_sendSignalingData)(NSData * _Nonnull);
|
||||
|
||||
NativePeerConnectionDelegate *_peerConnectionDelegate;
|
||||
|
||||
OngoingCallNetworkTypeWebrtcCustom _networkType;
|
||||
@ -372,10 +148,10 @@ API_AVAILABLE(ios(13.0))
|
||||
OngoingCallStateWebrtcCustom _state;
|
||||
int32_t _signalBars;
|
||||
|
||||
NativeWebrtcSignallingClient *_signallingClient;
|
||||
|
||||
RTCPeerConnectionFactory *_peerConnectionFactory;
|
||||
|
||||
RTCPeerConnection *_peerConnection;
|
||||
|
||||
RTCVideoCapturer *_videoCapturer;
|
||||
RTCVideoTrack *_localVideoTrack;
|
||||
RTCVideoTrack *_remoteVideoTrack;
|
||||
@ -420,12 +196,15 @@ API_AVAILABLE(ios(13.0))
|
||||
return 80;
|
||||
}
|
||||
|
||||
- (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtcCustom> _Nonnull)queue proxy:(VoipProxyServerWebrtcCustom * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtcCustom)networkType dataSaving:(OngoingCallDataSavingWebrtcCustom)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing primaryConnection:(OngoingCallConnectionDescriptionWebrtcCustom * _Nonnull)primaryConnection alternativeConnections:(NSArray<OngoingCallConnectionDescriptionWebrtcCustom *> * _Nonnull)alternativeConnections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath {
|
||||
- (instancetype _Nonnull)initWithQueue:(id<OngoingCallThreadLocalContextQueueWebrtcCustom> _Nonnull)queue proxy:(VoipProxyServerWebrtcCustom * _Nullable)proxy networkType:(OngoingCallNetworkTypeWebrtcCustom)networkType dataSaving:(OngoingCallDataSavingWebrtcCustom)dataSaving derivedState:(NSData * _Nonnull)derivedState key:(NSData * _Nonnull)key isOutgoing:(bool)isOutgoing primaryConnection:(OngoingCallConnectionDescriptionWebrtcCustom * _Nonnull)primaryConnection alternativeConnections:(NSArray<OngoingCallConnectionDescriptionWebrtcCustom *> * _Nonnull)alternativeConnections maxLayer:(int32_t)maxLayer allowP2P:(BOOL)allowP2P logPath:(NSString * _Nonnull)logPath sendSignalingData:(void (^)(NSData * _Nonnull))sendSignalingData {
|
||||
self = [super init];
|
||||
if (self != nil) {
|
||||
_queue = queue;
|
||||
assert([queue isCurrent]);
|
||||
|
||||
_isOutgoing = isOutgoing;
|
||||
_sendSignalingData = [sendSignalingData copy];
|
||||
|
||||
_callReceiveTimeout = 20.0;
|
||||
_callRingTimeout = 90.0;
|
||||
_callConnectTimeout = 30.0;
|
||||
@ -468,7 +247,7 @@ API_AVAILABLE(ios(13.0))
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
[strongSelf->_signallingClient sendCandidate:iceCandidate];
|
||||
[strongSelf sendCandidate:iceCandidate];
|
||||
} didChangeIceState: ^(OngoingCallStateWebrtcCustom state) {
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
@ -501,58 +280,6 @@ API_AVAILABLE(ios(13.0))
|
||||
_localVideoTrack = [_peerConnectionFactory videoTrackWithSource:videoSource trackId:@"video0"];
|
||||
[_peerConnection addTrack:_localVideoTrack streamIds:@[streamId]];
|
||||
|
||||
NSDictionary *mediaConstraints = @{
|
||||
kRTCMediaConstraintsOfferToReceiveAudio: kRTCMediaConstraintsValueTrue,
|
||||
kRTCMediaConstraintsOfferToReceiveVideo: kRTCMediaConstraintsValueTrue
|
||||
};
|
||||
|
||||
RTCMediaConstraints *connectionConstraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mediaConstraints optionalConstraints:nil];
|
||||
|
||||
_signallingClient = [[NativeWebrtcSignallingClient alloc] initWithQueue:queue didReceiveSessionDescription:^(RTCSessionDescription *sessionDescription) {
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (strongSelf->_receivedRemoteDescription) {
|
||||
return;
|
||||
}
|
||||
strongSelf->_receivedRemoteDescription = true;
|
||||
|
||||
[strongSelf->_peerConnection setRemoteDescription:sessionDescription completionHandler:^(__unused NSError * _Nullable error) {
|
||||
|
||||
}];
|
||||
|
||||
if (!isOutgoing) {
|
||||
[strongSelf->_peerConnection answerForConstraints:connectionConstraints completionHandler:^(RTCSessionDescription * _Nullable sdp, NSError * _Nullable error) {
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
[strongSelf->_peerConnection setLocalDescription:sdp completionHandler:^(__unused NSError * _Nullable error) {
|
||||
[queue dispatch:^{
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
[strongSelf->_signallingClient sendSdp:sdp];
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
} didReceiveIceCandidate:^(RTCIceCandidate *iceCandidate) {
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
voipLog(@"didReceiveIceCandidate: %@", iceCandidate);
|
||||
[strongSelf->_peerConnection addIceCandidate:iceCandidate];
|
||||
}];
|
||||
|
||||
[_signallingClient connect];
|
||||
|
||||
if (isOutgoing) {
|
||||
id<OngoingCallThreadLocalContextQueueWebrtcCustom> queue = _queue;
|
||||
NSDictionary *mediaConstraints = @{
|
||||
@ -596,7 +323,7 @@ API_AVAILABLE(ios(13.0))
|
||||
return;
|
||||
}
|
||||
|
||||
[_signallingClient sendSdp:sessionDescription];
|
||||
[self sendSdp:sessionDescription];
|
||||
__weak OngoingCallThreadLocalContextWebrtcCustom *weakSelf = self;
|
||||
[_queue dispatchAfter:1.0 block:^{
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
@ -657,35 +384,6 @@ API_AVAILABLE(ios(13.0))
|
||||
|
||||
[cameraCapturer startCaptureWithDevice:frontCamera format:bestFormat fps:27 completionHandler:^(NSError * _Nonnull error) {
|
||||
}];
|
||||
|
||||
//add renderer
|
||||
|
||||
/*
|
||||
guard let capturer = self.videoCapturer as? RTCCameraVideoCapturer else {
|
||||
return
|
||||
}
|
||||
|
||||
guard
|
||||
let frontCamera = (RTCCameraVideoCapturer.captureDevices().first { $0.position == .front }),
|
||||
|
||||
// choose highest res
|
||||
let format = (RTCCameraVideoCapturer.supportedFormats(for: frontCamera).sorted { (f1, f2) -> Bool in
|
||||
let width1 = CMVideoFormatDescriptionGetDimensions(f1.formatDescription).width
|
||||
let width2 = CMVideoFormatDescriptionGetDimensions(f2.formatDescription).width
|
||||
return width1 < width2
|
||||
}).last,
|
||||
|
||||
// choose highest fps
|
||||
let fps = (format.videoSupportedFrameRateRanges.sorted { return $0.maxFrameRate < $1.maxFrameRate }.last) else {
|
||||
return
|
||||
}
|
||||
|
||||
capturer.startCapture(with: frontCamera,
|
||||
format: format,
|
||||
fps: Int(fps.maxFrameRate))
|
||||
|
||||
self.localVideoTrack?.add(renderer)
|
||||
*/
|
||||
}
|
||||
|
||||
- (bool)needRate {
|
||||
@ -716,6 +414,129 @@ API_AVAILABLE(ios(13.0))
|
||||
return [NSData data];
|
||||
}
|
||||
|
||||
- (void)sendSdp:(RTCSessionDescription *)rtcSdp {
|
||||
NSMutableDictionary *json = [[NSMutableDictionary alloc] init];
|
||||
json[@"messageType"] = @"sessionDescription";
|
||||
json[@"sdp"] = rtcSdp.sdp;
|
||||
if (rtcSdp.type == RTCSdpTypeOffer) {
|
||||
json[@"type"] = @"offer";
|
||||
} else if (rtcSdp.type == RTCSdpTypePrAnswer) {
|
||||
json[@"type"] = @"prAnswer";
|
||||
} else if (rtcSdp.type == RTCSdpTypeAnswer) {
|
||||
json[@"type"] = @"answer";
|
||||
}
|
||||
NSData *data = [NSJSONSerialization dataWithJSONObject:json options:0 error:nil];
|
||||
if (data != nil) {
|
||||
_sendSignalingData(data);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)sendCandidate:(RTCIceCandidate *)rtcIceCandidate {
|
||||
NSMutableDictionary *json = [[NSMutableDictionary alloc] init];
|
||||
json[@"messageType"] = @"iceCandidate";
|
||||
json[@"sdp"] = rtcIceCandidate.sdp;
|
||||
json[@"mLineIndex"] = @(rtcIceCandidate.sdpMLineIndex);
|
||||
if (rtcIceCandidate.sdpMid != nil) {
|
||||
json[@"sdpMid"] = rtcIceCandidate.sdpMid;
|
||||
}
|
||||
NSData *data = [NSJSONSerialization dataWithJSONObject:json options:0 error:nil];
|
||||
if (data != nil) {
|
||||
_sendSignalingData(data);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)receiveSignalingData:(NSData *)data {
|
||||
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
|
||||
if (![json isKindOfClass:[NSDictionary class]]) {
|
||||
return;
|
||||
}
|
||||
NSString *messageType = json[@"messageType"];
|
||||
if (![messageType isKindOfClass:[NSString class]]) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ([messageType isEqualToString:@"sessionDescription"]) {
|
||||
NSString *sdp = json[@"sdp"];
|
||||
if (![sdp isKindOfClass:[NSString class]]) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *typeString = json[@"type"];
|
||||
if (![typeString isKindOfClass:[NSString class]]) {
|
||||
return;
|
||||
}
|
||||
|
||||
RTCSdpType type;
|
||||
if ([typeString isEqualToString:@"offer"]) {
|
||||
type = RTCSdpTypeOffer;
|
||||
} else if ([typeString isEqualToString:@"prAnswer"]) {
|
||||
type = RTCSdpTypePrAnswer;
|
||||
} else if ([typeString isEqualToString:@"answer"]) {
|
||||
type = RTCSdpTypeAnswer;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
if (_receivedRemoteDescription) {
|
||||
return;
|
||||
}
|
||||
_receivedRemoteDescription = true;
|
||||
|
||||
RTCSessionDescription *sessionDescription = [[RTCSessionDescription alloc] initWithType:type sdp:sdp];
|
||||
|
||||
NSDictionary *mediaConstraints = @{
|
||||
kRTCMediaConstraintsOfferToReceiveAudio: kRTCMediaConstraintsValueTrue,
|
||||
kRTCMediaConstraintsOfferToReceiveVideo: kRTCMediaConstraintsValueTrue
|
||||
};
|
||||
|
||||
RTCMediaConstraints *connectionConstraints = [[RTCMediaConstraints alloc] initWithMandatoryConstraints:mediaConstraints optionalConstraints:nil];
|
||||
|
||||
[_peerConnection setRemoteDescription:sessionDescription completionHandler:^(__unused NSError * _Nullable error) {
|
||||
}];
|
||||
|
||||
if (!_isOutgoing) {
|
||||
__weak OngoingCallThreadLocalContextWebrtcCustom *weakSelf = self;
|
||||
[_peerConnection answerForConstraints:connectionConstraints completionHandler:^(RTCSessionDescription * _Nullable sdp, NSError * _Nullable error) {
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
|
||||
id<OngoingCallThreadLocalContextQueueWebrtcCustom> queue = strongSelf->_queue;
|
||||
[strongSelf->_peerConnection setLocalDescription:sdp completionHandler:^(__unused NSError * _Nullable error) {
|
||||
[queue dispatch:^{
|
||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||
if (strongSelf == nil) {
|
||||
return;
|
||||
}
|
||||
[strongSelf sendSdp:sdp];
|
||||
}];
|
||||
}];
|
||||
}];
|
||||
}
|
||||
} else if ([messageType isEqualToString:@"iceCandidate"]) {
|
||||
NSString *sdp = json[@"sdp"];
|
||||
if (![sdp isKindOfClass:[NSString class]]) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSNumber *mLineIndex = json[@"mLineIndex"];
|
||||
if (![mLineIndex isKindOfClass:[NSNumber class]]) {
|
||||
return;
|
||||
}
|
||||
|
||||
NSString *sdpMidString = json[@"sdpMid"];
|
||||
NSString *sdpMid = nil;
|
||||
if ([sdpMidString isKindOfClass:[NSString class]]) {
|
||||
sdpMid = sdpMidString;
|
||||
}
|
||||
|
||||
RTCIceCandidate *iceCandidate = [[RTCIceCandidate alloc] initWithSdp:sdp sdpMLineIndex:[mLineIndex intValue] sdpMid:sdpMid];
|
||||
voipLog(@"didReceiveIceCandidate: %@", iceCandidate);
|
||||
[_peerConnection addIceCandidate:iceCandidate];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setIsMuted:(bool)isMuted {
|
||||
for (RTCRtpTransceiver *transceiver in _peerConnection.transceivers) {
|
||||
if ([transceiver isKindOfClass:[RTCAudioTrack class]]) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user