c43dd3ca4a
A native iOS receiver so an iPhone can act as the second receiver, speaking the existing signaling + RTP protocol (no C++ changes) and mirroring the Android receiver (Phase 8) source-to-source. - RTP core (header/packet, jitter buffer, H.264 depacketizer) ported from the Android receiver - BSD-socket signaling server (dual-stack, most-recent-peer, never-throwing sends) + NSBonjourServices - VideoToolbox H.264 decode (in-band SPS/PPS, real-time, rebuilds on size change) -> AVSampleBufferDisplayLayer - PLI keyframe recovery (500 ms) + pendingOffer for late surface attach - XcodeGen project + bootstrap.sh; XCTest port of the Android suite + new coverage - .gitignore for generated artifacts; CHANGELOG; PHASES + MEMORY updated Status: authored; on-device validation pending a Mac + Xcode 26 + iPhone 16.
34 lines
1.2 KiB
Swift
34 lines
1.2 KiB
Swift
import Foundation
|
|
|
|
/// Splits a byte stream into newline-terminated lines, dropping CR and
|
|
/// enforcing the 64 KB line cap — the same framing the C++ and Kotlin
|
|
/// receivers use. Extracted so the logic is testable in isolation.
|
|
final class LineAssembler {
|
|
private var pending: [UInt8] = []
|
|
private let maxLine = SignalingMessage.maxMessageBytes
|
|
|
|
/// Feed a chunk of received bytes; returns the complete lines it contained.
|
|
func feed(_ chunk: [UInt8]) -> [String] {
|
|
var lines: [String] = []
|
|
for b in chunk {
|
|
if b == 0x0A { // \n
|
|
let text = String(bytes: pending, encoding: .utf8) ?? ""
|
|
pending.removeAll(keepingCapacity: true)
|
|
if !text.isEmpty { lines.append(text) }
|
|
} else if b != 0x0D { // \r
|
|
if pending.count < maxLine {
|
|
pending.append(b)
|
|
} else {
|
|
// Hostile or broken peer: drop the oversized line.
|
|
pending.removeAll(keepingCapacity: true)
|
|
}
|
|
}
|
|
}
|
|
return lines
|
|
}
|
|
|
|
func reset() {
|
|
pending.removeAll(keepingCapacity: true)
|
|
}
|
|
}
|