iOS звонки в foreground с full E2EE и паритетом call-attachment

This commit is contained in:
2026-03-28 23:40:39 +05:00
parent e49d224e6a
commit 16191ef197
30 changed files with 2719 additions and 44 deletions

View File

@@ -54,6 +54,9 @@ final class ProtocolManager: @unchecked Sendable {
var onGroupBanReceived: ((PacketGroupBan) -> Void)?
var onSyncReceived: ((PacketSync) -> Void)?
var onDeviceNewReceived: ((PacketDeviceNew) -> Void)?
var onSignalPeerReceived: ((PacketSignalPeer) -> Void)?
var onWebRTCReceived: ((PacketWebRTC) -> Void)?
var onIceServersReceived: ((PacketIceServers) -> Void)?
var onHandshakeCompleted: ((PacketHandshake) -> Void)?
// MARK: - Private
@@ -82,9 +85,15 @@ final class ProtocolManager: @unchecked Sendable {
return val
}
private let resultHandlersLock = NSLock()
private let signalPeerHandlersLock = NSLock()
private let webRTCHandlersLock = NSLock()
private let iceServersHandlersLock = NSLock()
private let packetQueueLock = NSLock()
private let searchRouter = SearchPacketRouter()
private var resultHandlers: [UUID: (PacketResult) -> Void] = [:]
private var signalPeerHandlers: [UUID: (PacketSignalPeer) -> Void] = [:]
private var webRTCHandlers: [UUID: (PacketWebRTC) -> Void] = [:]
private var iceServersHandlers: [UUID: (PacketIceServers) -> Void] = [:]
// Saved credentials for auto-reconnect
private var savedPublicKey: String?
@@ -279,6 +288,33 @@ final class ProtocolManager: @unchecked Sendable {
sendPacket(packet)
}
func sendCallSignal(
signalType: SignalType,
src: String = "",
dst: String = "",
sharedPublic: String = "",
roomId: String = ""
) {
var packet = PacketSignalPeer()
packet.signalType = signalType
packet.src = src
packet.dst = dst
packet.sharedPublic = sharedPublic
packet.roomId = roomId
sendPacket(packet)
}
func sendWebRtcSignal(signalType: WebRTCSignalType, sdpOrCandidate: String) {
var packet = PacketWebRTC()
packet.signalType = signalType
packet.sdpOrCandidate = sdpOrCandidate
sendPacket(packet)
}
func requestIceServers() {
sendPacket(PacketIceServers())
}
func sendPacket(_ packet: any Packet) {
PerformanceLogger.shared.track("protocol.sendPacket")
let id = String(type(of: packet).packetId, radix: 16)
@@ -307,6 +343,53 @@ final class ProtocolManager: @unchecked Sendable {
searchRouter.removeHandler(id)
}
// MARK: - Call Packet Handlers (Android-like wait/unwait)
@discardableResult
func addSignalPeerHandler(_ handler: @escaping (PacketSignalPeer) -> Void) -> UUID {
let id = UUID()
signalPeerHandlersLock.lock()
signalPeerHandlers[id] = handler
signalPeerHandlersLock.unlock()
return id
}
func removeSignalPeerHandler(_ id: UUID) {
signalPeerHandlersLock.lock()
signalPeerHandlers.removeValue(forKey: id)
signalPeerHandlersLock.unlock()
}
@discardableResult
func addWebRtcHandler(_ handler: @escaping (PacketWebRTC) -> Void) -> UUID {
let id = UUID()
webRTCHandlersLock.lock()
webRTCHandlers[id] = handler
webRTCHandlersLock.unlock()
return id
}
func removeWebRtcHandler(_ id: UUID) {
webRTCHandlersLock.lock()
webRTCHandlers.removeValue(forKey: id)
webRTCHandlersLock.unlock()
}
@discardableResult
func addIceServersHandler(_ handler: @escaping (PacketIceServers) -> Void) -> UUID {
let id = UUID()
iceServersHandlersLock.lock()
iceServersHandlers[id] = handler
iceServersHandlersLock.unlock()
return id
}
func removeIceServersHandler(_ id: UUID) {
iceServersHandlersLock.lock()
iceServersHandlers.removeValue(forKey: id)
iceServersHandlersLock.unlock()
}
// MARK: - Result Handlers (Android parity: waitPacket(0x02))
/// Register a one-shot handler for PacketResult (0x02).
@@ -563,6 +646,21 @@ final class ProtocolManager: @unchecked Sendable {
}
onSyncReceived?(p)
}
case 0x1A:
if let p = packet as? PacketSignalPeer {
onSignalPeerReceived?(p)
notifySignalPeerHandlers(p)
}
case 0x1B:
if let p = packet as? PacketWebRTC {
onWebRTCReceived?(p)
notifyWebRtcHandlers(p)
}
case 0x1C:
if let p = packet as? PacketIceServers {
onIceServersReceived?(p)
notifyIceServersHandlers(p)
}
default:
break
}
@@ -584,6 +682,36 @@ final class ProtocolManager: @unchecked Sendable {
}
}
private func notifySignalPeerHandlers(_ packet: PacketSignalPeer) {
signalPeerHandlersLock.lock()
let handlers = signalPeerHandlers.values
signalPeerHandlersLock.unlock()
for handler in handlers {
handler(packet)
}
}
private func notifyWebRtcHandlers(_ packet: PacketWebRTC) {
webRTCHandlersLock.lock()
let handlers = webRTCHandlers.values
webRTCHandlersLock.unlock()
for handler in handlers {
handler(packet)
}
}
private func notifyIceServersHandlers(_ packet: PacketIceServers) {
iceServersHandlersLock.lock()
let handlers = iceServersHandlers.values
iceServersHandlersLock.unlock()
for handler in handlers {
handler(packet)
}
}
private func handleHandshakeResponse(_ packet: PacketHandshake) {
handshakeTimeoutTask?.cancel()
handshakeTimeoutTask = nil