mirror of
https://github.com/Swiftgram/Telegram-iOS.git
synced 2025-08-23 14:05:33 +00:00
Use internal signalling
This commit is contained in:
parent
346b8160c4
commit
b8bee2bd70
@ -3,7 +3,7 @@
|
|||||||
@implementation Serialization
|
@implementation Serialization
|
||||||
|
|
||||||
- (NSUInteger)currentLayer {
|
- (NSUInteger)currentLayer {
|
||||||
return 113;
|
return 114;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id _Nullable)parseMessage:(NSData * _Nullable)data {
|
- (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[654302845] = { return Api.Update.parse_updateDialogFilter($0) }
|
||||||
dict[-1512627963] = { return Api.Update.parse_updateDialogFilterOrder($0) }
|
dict[-1512627963] = { return Api.Update.parse_updateDialogFilterOrder($0) }
|
||||||
dict[889491791] = { return Api.Update.parse_updateDialogFilters($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[136574537] = { return Api.messages.VotesList.parse_votesList($0) }
|
||||||
dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) }
|
dict[1558266229] = { return Api.PopularContact.parse_popularContact($0) }
|
||||||
dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) }
|
dict[-373643672] = { return Api.FolderPeer.parse_folderPeer($0) }
|
||||||
@ -841,7 +842,7 @@ public struct Api {
|
|||||||
return parser(reader)
|
return parser(reader)
|
||||||
}
|
}
|
||||||
else {
|
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
|
return nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5894,6 +5894,7 @@ public extension Api {
|
|||||||
case updateDialogFilter(flags: Int32, id: Int32, filter: Api.DialogFilter?)
|
case updateDialogFilter(flags: Int32, id: Int32, filter: Api.DialogFilter?)
|
||||||
case updateDialogFilterOrder(order: [Int32])
|
case updateDialogFilterOrder(order: [Int32])
|
||||||
case updateDialogFilters
|
case updateDialogFilters
|
||||||
|
case updatePhoneCallSignalingData(phoneCallId: Int64, data: Buffer)
|
||||||
|
|
||||||
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
public func serialize(_ buffer: Buffer, _ boxed: Swift.Bool) {
|
||||||
switch self {
|
switch self {
|
||||||
@ -6566,6 +6567,13 @@ public extension Api {
|
|||||||
buffer.appendInt32(889491791)
|
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
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6732,6 +6740,8 @@ public extension Api {
|
|||||||
return ("updateDialogFilterOrder", [("order", order)])
|
return ("updateDialogFilterOrder", [("order", order)])
|
||||||
case .updateDialogFilters:
|
case .updateDialogFilters:
|
||||||
return ("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? {
|
public static func parse_updateDialogFilters(_ reader: BufferReader) -> Update? {
|
||||||
return Api.Update.updateDialogFilters
|
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 {
|
public enum PopularContact: TypeConstructorDescription {
|
||||||
|
@ -6477,6 +6477,21 @@ public extension Api {
|
|||||||
return result
|
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 UpdateRecentGifs
|
||||||
case UpdateChatInputState(PeerId, SynchronizeableChatInputState?)
|
case UpdateChatInputState(PeerId, SynchronizeableChatInputState?)
|
||||||
case UpdateCall(Api.PhoneCall)
|
case UpdateCall(Api.PhoneCall)
|
||||||
|
case AddCallSignalingData(Int64, Data)
|
||||||
case UpdateLangPack(String, Api.LangPackDifference?)
|
case UpdateLangPack(String, Api.LangPackDifference?)
|
||||||
case UpdateMinAvailableMessage(MessageId)
|
case UpdateMinAvailableMessage(MessageId)
|
||||||
case UpdatePeerChatInclusion(peerId: PeerId, groupId: PeerGroupId, changedGroup: Bool)
|
case UpdatePeerChatInclusion(peerId: PeerId, groupId: PeerGroupId, changedGroup: Bool)
|
||||||
@ -425,6 +426,10 @@ struct AccountMutableState {
|
|||||||
self.addOperation(.UpdateCall(call))
|
self.addOperation(.UpdateCall(call))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutating func addCallSignalingData(callId: Int64, data: Data) {
|
||||||
|
self.addOperation(.AddCallSignalingData(callId, data))
|
||||||
|
}
|
||||||
|
|
||||||
mutating func addSyncChatListFilters() {
|
mutating func addSyncChatListFilters() {
|
||||||
self.addOperation(.SyncChatListFilters)
|
self.addOperation(.SyncChatListFilters)
|
||||||
}
|
}
|
||||||
@ -439,7 +444,7 @@ struct AccountMutableState {
|
|||||||
|
|
||||||
mutating func addOperation(_ operation: AccountStateMutationOperation) {
|
mutating func addOperation(_ operation: AccountStateMutationOperation) {
|
||||||
switch operation {
|
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
|
break
|
||||||
case let .AddMessages(messages, location):
|
case let .AddMessages(messages, location):
|
||||||
for message in messages {
|
for message in messages {
|
||||||
@ -555,6 +560,7 @@ struct AccountReplayedFinalState {
|
|||||||
let updatedTypingActivities: [PeerId: [PeerId: PeerInputActivity?]]
|
let updatedTypingActivities: [PeerId: [PeerId: PeerInputActivity?]]
|
||||||
let updatedWebpages: [MediaId: TelegramMediaWebpage]
|
let updatedWebpages: [MediaId: TelegramMediaWebpage]
|
||||||
let updatedCalls: [Api.PhoneCall]
|
let updatedCalls: [Api.PhoneCall]
|
||||||
|
let addedCallSignalingData: [(Int64, Data)]
|
||||||
let updatedPeersNearby: [PeerNearby]?
|
let updatedPeersNearby: [PeerNearby]?
|
||||||
let isContactUpdates: [(PeerId, Bool)]
|
let isContactUpdates: [(PeerId, Bool)]
|
||||||
let delayNotificatonsUntil: Int32?
|
let delayNotificatonsUntil: Int32?
|
||||||
@ -566,6 +572,7 @@ struct AccountFinalStateEvents {
|
|||||||
let updatedTypingActivities: [PeerId: [PeerId: PeerInputActivity?]]
|
let updatedTypingActivities: [PeerId: [PeerId: PeerInputActivity?]]
|
||||||
let updatedWebpages: [MediaId: TelegramMediaWebpage]
|
let updatedWebpages: [MediaId: TelegramMediaWebpage]
|
||||||
let updatedCalls: [Api.PhoneCall]
|
let updatedCalls: [Api.PhoneCall]
|
||||||
|
let addedCallSignalingData: [(Int64, Data)]
|
||||||
let updatedPeersNearby: [PeerNearby]?
|
let updatedPeersNearby: [PeerNearby]?
|
||||||
let isContactUpdates: [(PeerId, Bool)]
|
let isContactUpdates: [(PeerId, Bool)]
|
||||||
let displayAlerts: [(text: String, isDropAuth: Bool)]
|
let displayAlerts: [(text: String, isDropAuth: Bool)]
|
||||||
@ -576,15 +583,16 @@ struct AccountFinalStateEvents {
|
|||||||
let authorizationListUpdated: Bool
|
let authorizationListUpdated: Bool
|
||||||
|
|
||||||
var isEmpty: 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.addedIncomingMessageIds = addedIncomingMessageIds
|
||||||
self.wasScheduledMessageIds = wasScheduledMessageIds
|
self.wasScheduledMessageIds = wasScheduledMessageIds
|
||||||
self.updatedTypingActivities = updatedTypingActivities
|
self.updatedTypingActivities = updatedTypingActivities
|
||||||
self.updatedWebpages = updatedWebpages
|
self.updatedWebpages = updatedWebpages
|
||||||
self.updatedCalls = updatedCalls
|
self.updatedCalls = updatedCalls
|
||||||
|
self.addedCallSignalingData = addedCallSignalingData
|
||||||
self.updatedPeersNearby = updatedPeersNearby
|
self.updatedPeersNearby = updatedPeersNearby
|
||||||
self.isContactUpdates = isContactUpdates
|
self.isContactUpdates = isContactUpdates
|
||||||
self.displayAlerts = displayAlerts
|
self.displayAlerts = displayAlerts
|
||||||
@ -601,6 +609,7 @@ struct AccountFinalStateEvents {
|
|||||||
self.updatedTypingActivities = state.updatedTypingActivities
|
self.updatedTypingActivities = state.updatedTypingActivities
|
||||||
self.updatedWebpages = state.updatedWebpages
|
self.updatedWebpages = state.updatedWebpages
|
||||||
self.updatedCalls = state.updatedCalls
|
self.updatedCalls = state.updatedCalls
|
||||||
|
self.addedCallSignalingData = state.addedCallSignalingData
|
||||||
self.updatedPeersNearby = state.updatedPeersNearby
|
self.updatedPeersNearby = state.updatedPeersNearby
|
||||||
self.isContactUpdates = state.isContactUpdates
|
self.isContactUpdates = state.isContactUpdates
|
||||||
self.displayAlerts = state.state.state.displayAlerts
|
self.displayAlerts = state.state.state.displayAlerts
|
||||||
@ -634,6 +643,6 @@ struct AccountFinalStateEvents {
|
|||||||
let externallyUpdatedPeerId = self.externallyUpdatedPeerId.union(other.externallyUpdatedPeerId)
|
let externallyUpdatedPeerId = self.externallyUpdatedPeerId.union(other.externallyUpdatedPeerId)
|
||||||
let authorizationListUpdated = self.authorizationListUpdated || other.authorizationListUpdated
|
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)
|
updatedState.addUpdateChatInputState(peerId: peer.peerId, state: inputState)
|
||||||
case let .updatePhoneCall(phoneCall):
|
case let .updatePhoneCall(phoneCall):
|
||||||
updatedState.addUpdateCall(phoneCall)
|
updatedState.addUpdateCall(phoneCall)
|
||||||
|
case let .updatePhoneCallSignalingData(phoneCallId, data):
|
||||||
|
updatedState.addCallSignalingData(callId: phoneCallId, data: data.makeData())
|
||||||
case let .updateLangPackTooLong(langCode):
|
case let .updateLangPackTooLong(langCode):
|
||||||
updatedState.updateLangPack(langCode: langCode, difference: nil)
|
updatedState.updateLangPack(langCode: langCode, difference: nil)
|
||||||
case let .updateLangPack(difference):
|
case let .updateLangPack(difference):
|
||||||
@ -2073,7 +2075,7 @@ private func optimizedOperations(_ operations: [AccountStateMutationOperation])
|
|||||||
var currentAddScheduledMessages: OptimizeAddMessagesState?
|
var currentAddScheduledMessages: OptimizeAddMessagesState?
|
||||||
for operation in operations {
|
for operation in operations {
|
||||||
switch operation {
|
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 {
|
if let currentAddMessages = currentAddMessages, !currentAddMessages.messages.isEmpty {
|
||||||
result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location))
|
result.append(.AddMessages(currentAddMessages.messages, currentAddMessages.location))
|
||||||
}
|
}
|
||||||
@ -2157,6 +2159,7 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
|
|||||||
var updatedSecretChatTypingActivities = Set<PeerId>()
|
var updatedSecretChatTypingActivities = Set<PeerId>()
|
||||||
var updatedWebpages: [MediaId: TelegramMediaWebpage] = [:]
|
var updatedWebpages: [MediaId: TelegramMediaWebpage] = [:]
|
||||||
var updatedCalls: [Api.PhoneCall] = []
|
var updatedCalls: [Api.PhoneCall] = []
|
||||||
|
var addedCallSignalingData: [(Int64, Data)] = []
|
||||||
var updatedPeersNearby: [PeerNearby]?
|
var updatedPeersNearby: [PeerNearby]?
|
||||||
var isContactUpdates: [(PeerId, Bool)] = []
|
var isContactUpdates: [(PeerId, Bool)] = []
|
||||||
var stickerPackOperations: [AccountStateUpdateStickerPacksOperation] = []
|
var stickerPackOperations: [AccountStateUpdateStickerPacksOperation] = []
|
||||||
@ -2760,6 +2763,8 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
|
|||||||
})
|
})
|
||||||
case let .UpdateCall(call):
|
case let .UpdateCall(call):
|
||||||
updatedCalls.append(call)
|
updatedCalls.append(call)
|
||||||
|
case let .AddCallSignalingData(callId, data):
|
||||||
|
addedCallSignalingData.append((callId, data))
|
||||||
case let .UpdateLangPack(langCode, difference):
|
case let .UpdateLangPack(langCode, difference):
|
||||||
if let difference = difference {
|
if let difference = difference {
|
||||||
if langPackDifferences[langCode] == nil {
|
if langPackDifferences[langCode] == nil {
|
||||||
@ -3141,5 +3146,5 @@ func replayFinalState(accountManager: AccountManager, postbox: Postbox, accountP
|
|||||||
requestChatListFiltersSync(transaction: transaction)
|
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 })
|
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 {
|
if !events.isContactUpdates.isEmpty {
|
||||||
strongSelf.addIsContactUpdates(events.isContactUpdates)
|
strongSelf.addIsContactUpdates(events.isContactUpdates)
|
||||||
}
|
}
|
||||||
|
@ -213,12 +213,15 @@ private final class CallSessionContext {
|
|||||||
let isOutgoing: Bool
|
let isOutgoing: Bool
|
||||||
var state: CallSessionInternalState
|
var state: CallSessionInternalState
|
||||||
let subscribers = Bag<(CallSession) -> Void>()
|
let subscribers = Bag<(CallSession) -> Void>()
|
||||||
|
let signalingSubscribers = Bag<(Data) -> Void>()
|
||||||
|
|
||||||
|
let signalingDisposables = DisposableSet()
|
||||||
|
|
||||||
let acknowledgeIncomingCallDisposable = MetaDisposable()
|
let acknowledgeIncomingCallDisposable = MetaDisposable()
|
||||||
|
|
||||||
var isEmpty: Bool {
|
var isEmpty: Bool {
|
||||||
if case .terminated = self.state {
|
if case .terminated = self.state {
|
||||||
return self.subscribers.isEmpty
|
return self.subscribers.isEmpty && self.signalingSubscribers.isEmpty
|
||||||
} else {
|
} else {
|
||||||
return false
|
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] {
|
private func ringingStatesValue() -> [CallSessionRingingState] {
|
||||||
var ringingContexts: [CallSessionRingingState] = []
|
var ringingContexts: [CallSessionRingingState] = []
|
||||||
for (id, context) in self.contexts {
|
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) {
|
func updateSession(_ call: Api.PhoneCall, completion: @escaping ((CallSessionRingingState, CallSession)?) -> Void) {
|
||||||
var resultRingingState: (CallSessionRingingState, CallSession)?
|
var resultRingingState: (CallSessionRingingState, CallSession)?
|
||||||
|
|
||||||
@ -723,6 +762,15 @@ private final class CallSessionManagerContext {
|
|||||||
completion(resultRingingState)
|
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)? {
|
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())!
|
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>) {
|
public func drop(internalId: CallSessionInternalId, reason: DropCallReason, debugLog: Signal<String?, NoError>) {
|
||||||
self.withContext { context in
|
self.withContext { context in
|
||||||
context.drop(internalId: internalId, reason: reason, debugLog: debugLog)
|
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> {
|
public func ringingStates() -> Signal<[CallSessionRingingState], NoError> {
|
||||||
return Signal { [weak self] subscriber in
|
return Signal { [weak self] subscriber in
|
||||||
let disposable = MetaDisposable()
|
let disposable = MetaDisposable()
|
||||||
@ -880,6 +940,18 @@ public final class CallSessionManager {
|
|||||||
return disposable
|
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 {
|
private enum AcceptedCall {
|
||||||
|
@ -210,7 +210,7 @@ public class BoxedMessage: NSObject {
|
|||||||
|
|
||||||
public class Serialization: NSObject, MTSerialization {
|
public class Serialization: NSObject, MTSerialization {
|
||||||
public func currentLayer() -> UInt {
|
public func currentLayer() -> UInt {
|
||||||
return 113
|
return 114
|
||||||
}
|
}
|
||||||
|
|
||||||
public func parseMessage(_ data: Data!) -> Any! {
|
public func parseMessage(_ data: Data!) -> Any! {
|
||||||
|
@ -383,6 +383,8 @@ public final class OngoingCallContext {
|
|||||||
return self.contextState.get()
|
return self.contextState.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var signalingDataDisposable: Disposable?
|
||||||
|
|
||||||
private let receptionPromise = Promise<Int32?>(nil)
|
private let receptionPromise = Promise<Int32?>(nil)
|
||||||
public var reception: Signal<Int32?, NoError> {
|
public var reception: Signal<Int32?, NoError> {
|
||||||
return self.receptionPromise.get()
|
return self.receptionPromise.get()
|
||||||
@ -428,7 +430,9 @@ public final class OngoingCallContext {
|
|||||||
break
|
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))
|
strongSelf.contextRef = Unmanaged.passRetained(OngoingCallThreadLocalContextHolder(context))
|
||||||
context.stateChanged = { state in
|
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 {
|
deinit {
|
||||||
|
@ -66,7 +66,7 @@ typedef NS_ENUM(int32_t, OngoingCallDataSavingWebrtcCustom) {
|
|||||||
@property (nonatomic, copy) void (^ _Nullable stateChanged)(OngoingCallStateWebrtcCustom);
|
@property (nonatomic, copy) void (^ _Nullable stateChanged)(OngoingCallStateWebrtcCustom);
|
||||||
@property (nonatomic, copy) void (^ _Nullable signalBarsChanged)(int32_t);
|
@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;
|
- (void)stop:(void (^_Nullable)(NSString * _Nullable debugLog, int64_t bytesSentWifi, int64_t bytesReceivedWifi, int64_t bytesSentMobile, int64_t bytesReceivedMobile))completion;
|
||||||
|
|
||||||
- (bool)needRate;
|
- (bool)needRate;
|
||||||
@ -75,6 +75,9 @@ typedef NS_ENUM(int32_t, OngoingCallDataSavingWebrtcCustom) {
|
|||||||
- (NSString * _Nullable)version;
|
- (NSString * _Nullable)version;
|
||||||
- (NSData * _Nonnull)getDerivedState;
|
- (NSData * _Nonnull)getDerivedState;
|
||||||
|
|
||||||
|
|
||||||
|
- (void)receiveSignalingData:(NSData * _Nonnull)data;
|
||||||
|
|
||||||
- (void)setIsMuted:(bool)isMuted;
|
- (void)setIsMuted:(bool)isMuted;
|
||||||
- (void)setNetworkType:(OngoingCallNetworkTypeWebrtcCustom)networkType;
|
- (void)setNetworkType:(OngoingCallNetworkTypeWebrtcCustom)networkType;
|
||||||
- (void)getRemoteCameraView:(void (^_Nonnull)(UIView * _Nullable))completion;
|
- (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> {
|
@interface NativePeerConnectionDelegate : NSObject <RTCPeerConnectionDelegate> {
|
||||||
id<OngoingCallThreadLocalContextQueueWebrtcCustom> _queue;
|
id<OngoingCallThreadLocalContextQueueWebrtcCustom> _queue;
|
||||||
void (^_didGenerateIceCandidate)(RTCIceCandidate *);
|
void (^_didGenerateIceCandidate)(RTCIceCandidate *);
|
||||||
@ -361,6 +134,9 @@ API_AVAILABLE(ios(13.0))
|
|||||||
id<OngoingCallThreadLocalContextQueueWebrtcCustom> _queue;
|
id<OngoingCallThreadLocalContextQueueWebrtcCustom> _queue;
|
||||||
int32_t _contextId;
|
int32_t _contextId;
|
||||||
|
|
||||||
|
bool _isOutgoing;
|
||||||
|
void (^_sendSignalingData)(NSData * _Nonnull);
|
||||||
|
|
||||||
NativePeerConnectionDelegate *_peerConnectionDelegate;
|
NativePeerConnectionDelegate *_peerConnectionDelegate;
|
||||||
|
|
||||||
OngoingCallNetworkTypeWebrtcCustom _networkType;
|
OngoingCallNetworkTypeWebrtcCustom _networkType;
|
||||||
@ -372,10 +148,10 @@ API_AVAILABLE(ios(13.0))
|
|||||||
OngoingCallStateWebrtcCustom _state;
|
OngoingCallStateWebrtcCustom _state;
|
||||||
int32_t _signalBars;
|
int32_t _signalBars;
|
||||||
|
|
||||||
NativeWebrtcSignallingClient *_signallingClient;
|
|
||||||
|
|
||||||
RTCPeerConnectionFactory *_peerConnectionFactory;
|
RTCPeerConnectionFactory *_peerConnectionFactory;
|
||||||
|
|
||||||
RTCPeerConnection *_peerConnection;
|
RTCPeerConnection *_peerConnection;
|
||||||
|
|
||||||
RTCVideoCapturer *_videoCapturer;
|
RTCVideoCapturer *_videoCapturer;
|
||||||
RTCVideoTrack *_localVideoTrack;
|
RTCVideoTrack *_localVideoTrack;
|
||||||
RTCVideoTrack *_remoteVideoTrack;
|
RTCVideoTrack *_remoteVideoTrack;
|
||||||
@ -420,12 +196,15 @@ API_AVAILABLE(ios(13.0))
|
|||||||
return 80;
|
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];
|
self = [super init];
|
||||||
if (self != nil) {
|
if (self != nil) {
|
||||||
_queue = queue;
|
_queue = queue;
|
||||||
assert([queue isCurrent]);
|
assert([queue isCurrent]);
|
||||||
|
|
||||||
|
_isOutgoing = isOutgoing;
|
||||||
|
_sendSignalingData = [sendSignalingData copy];
|
||||||
|
|
||||||
_callReceiveTimeout = 20.0;
|
_callReceiveTimeout = 20.0;
|
||||||
_callRingTimeout = 90.0;
|
_callRingTimeout = 90.0;
|
||||||
_callConnectTimeout = 30.0;
|
_callConnectTimeout = 30.0;
|
||||||
@ -468,7 +247,7 @@ API_AVAILABLE(ios(13.0))
|
|||||||
if (strongSelf == nil) {
|
if (strongSelf == nil) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
[strongSelf->_signallingClient sendCandidate:iceCandidate];
|
[strongSelf sendCandidate:iceCandidate];
|
||||||
} didChangeIceState: ^(OngoingCallStateWebrtcCustom state) {
|
} didChangeIceState: ^(OngoingCallStateWebrtcCustom state) {
|
||||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||||
if (strongSelf == nil) {
|
if (strongSelf == nil) {
|
||||||
@ -501,58 +280,6 @@ API_AVAILABLE(ios(13.0))
|
|||||||
_localVideoTrack = [_peerConnectionFactory videoTrackWithSource:videoSource trackId:@"video0"];
|
_localVideoTrack = [_peerConnectionFactory videoTrackWithSource:videoSource trackId:@"video0"];
|
||||||
[_peerConnection addTrack:_localVideoTrack streamIds:@[streamId]];
|
[_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) {
|
if (isOutgoing) {
|
||||||
id<OngoingCallThreadLocalContextQueueWebrtcCustom> queue = _queue;
|
id<OngoingCallThreadLocalContextQueueWebrtcCustom> queue = _queue;
|
||||||
NSDictionary *mediaConstraints = @{
|
NSDictionary *mediaConstraints = @{
|
||||||
@ -596,7 +323,7 @@ API_AVAILABLE(ios(13.0))
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
[_signallingClient sendSdp:sessionDescription];
|
[self sendSdp:sessionDescription];
|
||||||
__weak OngoingCallThreadLocalContextWebrtcCustom *weakSelf = self;
|
__weak OngoingCallThreadLocalContextWebrtcCustom *weakSelf = self;
|
||||||
[_queue dispatchAfter:1.0 block:^{
|
[_queue dispatchAfter:1.0 block:^{
|
||||||
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
__strong OngoingCallThreadLocalContextWebrtcCustom *strongSelf = weakSelf;
|
||||||
@ -657,35 +384,6 @@ API_AVAILABLE(ios(13.0))
|
|||||||
|
|
||||||
[cameraCapturer startCaptureWithDevice:frontCamera format:bestFormat fps:27 completionHandler:^(NSError * _Nonnull error) {
|
[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 {
|
- (bool)needRate {
|
||||||
@ -716,6 +414,129 @@ API_AVAILABLE(ios(13.0))
|
|||||||
return [NSData data];
|
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 {
|
- (void)setIsMuted:(bool)isMuted {
|
||||||
for (RTCRtpTransceiver *transceiver in _peerConnection.transceivers) {
|
for (RTCRtpTransceiver *transceiver in _peerConnection.transceivers) {
|
||||||
if ([transceiver isKindOfClass:[RTCAudioTrack class]]) {
|
if ([transceiver isKindOfClass:[RTCAudioTrack class]]) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user