Фикс: исправлено исчезновение части уведомлений при открытии пуша
This commit is contained in:
@@ -14,6 +14,18 @@ enum ConnectionState: String {
|
||||
case authenticated
|
||||
}
|
||||
|
||||
struct MalformedMessagePacketInfo: Sendable {
|
||||
let packetSize: Int
|
||||
let fingerprint: String
|
||||
let messageIdHint: String
|
||||
}
|
||||
|
||||
struct MalformedCriticalPacketInfo: Sendable {
|
||||
let packetId: Int
|
||||
let packetSize: Int
|
||||
let fingerprint: String
|
||||
}
|
||||
|
||||
// MARK: - ProtocolManager
|
||||
|
||||
/// Central networking coordinator. Owns WebSocket, routes packets, manages handshake.
|
||||
@@ -58,6 +70,8 @@ final class ProtocolManager: @unchecked Sendable {
|
||||
var onWebRTCReceived: ((PacketWebRTC) -> Void)?
|
||||
var onIceServersReceived: ((PacketIceServers) -> Void)?
|
||||
var onHandshakeCompleted: ((PacketHandshake) -> Void)?
|
||||
var onMalformedMessageReceived: ((MalformedMessagePacketInfo) -> Void)?
|
||||
var onMalformedCriticalPacketReceived: ((MalformedCriticalPacketInfo) -> Void)?
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
@@ -687,6 +701,15 @@ final class ProtocolManager: @unchecked Sendable {
|
||||
switch packetId {
|
||||
case 0x00:
|
||||
if let p = packet as? PacketHandshake {
|
||||
if p.isMalformed {
|
||||
reportMalformedCriticalPacket(
|
||||
packetId: packetId,
|
||||
packetSize: data.count,
|
||||
fingerprint: p.malformedFingerprint,
|
||||
fallbackFingerprint: "packet00_parse_failed"
|
||||
)
|
||||
return
|
||||
}
|
||||
handleHandshakeResponse(p)
|
||||
}
|
||||
case 0x01:
|
||||
@@ -712,6 +735,25 @@ final class ProtocolManager: @unchecked Sendable {
|
||||
}
|
||||
case 0x06:
|
||||
if let p = packet as? PacketMessage {
|
||||
if p.isMalformed {
|
||||
let messageIdHint = p.messageId.isEmpty ? "-" : String(p.messageId.prefix(8))
|
||||
let fingerprint = p.malformedFingerprint.isEmpty ? "packet06_parse_failed" : p.malformedFingerprint
|
||||
reportMalformedCriticalPacket(
|
||||
packetId: packetId,
|
||||
packetSize: data.count,
|
||||
fingerprint: fingerprint,
|
||||
fallbackFingerprint: "packet06_parse_failed",
|
||||
messageIdHint: messageIdHint
|
||||
)
|
||||
onMalformedMessageReceived?(
|
||||
MalformedMessagePacketInfo(
|
||||
packetSize: data.count,
|
||||
fingerprint: fingerprint,
|
||||
messageIdHint: messageIdHint
|
||||
)
|
||||
)
|
||||
return
|
||||
}
|
||||
onMessageReceived?(p)
|
||||
}
|
||||
case 0x07:
|
||||
@@ -781,6 +823,15 @@ final class ProtocolManager: @unchecked Sendable {
|
||||
}
|
||||
case 0x19:
|
||||
if let p = packet as? PacketSync {
|
||||
if p.isMalformed {
|
||||
reportMalformedCriticalPacket(
|
||||
packetId: packetId,
|
||||
packetSize: data.count,
|
||||
fingerprint: p.malformedFingerprint,
|
||||
fallbackFingerprint: "packet19_parse_failed"
|
||||
)
|
||||
return
|
||||
}
|
||||
// Android parity: set sync flag SYNCHRONOUSLY on receive queue
|
||||
// BEFORE dispatching to MainActor callback. This prevents the race
|
||||
// where a 0x06 message Task runs on MainActor before BATCH_START Task.
|
||||
@@ -797,11 +848,29 @@ final class ProtocolManager: @unchecked Sendable {
|
||||
}
|
||||
case 0x1A:
|
||||
if let p = packet as? PacketSignalPeer {
|
||||
if p.isMalformed {
|
||||
reportMalformedCriticalPacket(
|
||||
packetId: packetId,
|
||||
packetSize: data.count,
|
||||
fingerprint: p.malformedFingerprint,
|
||||
fallbackFingerprint: "packet1a_parse_failed"
|
||||
)
|
||||
return
|
||||
}
|
||||
onSignalPeerReceived?(p)
|
||||
notifySignalPeerHandlers(p)
|
||||
}
|
||||
case 0x1B:
|
||||
if let p = packet as? PacketWebRTC {
|
||||
if p.isMalformed {
|
||||
reportMalformedCriticalPacket(
|
||||
packetId: packetId,
|
||||
packetSize: data.count,
|
||||
fingerprint: p.malformedFingerprint,
|
||||
fallbackFingerprint: "packet1b_parse_failed"
|
||||
)
|
||||
return
|
||||
}
|
||||
onWebRTCReceived?(p)
|
||||
notifyWebRtcHandlers(p)
|
||||
}
|
||||
@@ -861,6 +930,44 @@ final class ProtocolManager: @unchecked Sendable {
|
||||
}
|
||||
}
|
||||
|
||||
private func reportMalformedCriticalPacket(
|
||||
packetId: Int,
|
||||
packetSize: Int,
|
||||
fingerprint: String,
|
||||
fallbackFingerprint: String,
|
||||
messageIdHint: String? = nil
|
||||
) {
|
||||
let packetHex = String(format: "0x%02X", packetId)
|
||||
let normalizedFingerprint = Self.compactFingerprint(
|
||||
fingerprint.isEmpty ? fallbackFingerprint : fingerprint
|
||||
)
|
||||
if let messageIdHint {
|
||||
Self.logger.error(
|
||||
"Dropping malformed \(packetHex) packet size=\(packetSize) msgHint=\(messageIdHint) fp=\(normalizedFingerprint)"
|
||||
)
|
||||
} else {
|
||||
Self.logger.error(
|
||||
"Dropping malformed \(packetHex) packet size=\(packetSize) fp=\(normalizedFingerprint)"
|
||||
)
|
||||
}
|
||||
|
||||
onMalformedCriticalPacketReceived?(
|
||||
MalformedCriticalPacketInfo(
|
||||
packetId: packetId,
|
||||
packetSize: packetSize,
|
||||
fingerprint: normalizedFingerprint
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private static func compactFingerprint(_ fingerprint: String) -> String {
|
||||
let sanitized = fingerprint
|
||||
.replacingOccurrences(of: "\n", with: " ")
|
||||
.replacingOccurrences(of: "\t", with: " ")
|
||||
guard sanitized.count > 120 else { return sanitized }
|
||||
return String(sanitized.prefix(120))
|
||||
}
|
||||
|
||||
private func handleHandshakeResponse(_ packet: PacketHandshake) {
|
||||
handshakeTimeoutTask?.cancel()
|
||||
handshakeTimeoutTask = nil
|
||||
@@ -1091,4 +1198,10 @@ final class ProtocolManager: @unchecked Sendable {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Test Support
|
||||
|
||||
func testHandleIncomingData(_ data: Data) {
|
||||
handleIncomingData(data)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user