jellyflood/JellyfinPlayer/OpenCastSwift/Helpers/CastV2PlatformReader.swift

84 lines
2.1 KiB
Swift

//
// CastV2PlatformReader.swift
// OpenCastSwift Mac
//
// Created by Miles Hollingsworth on 4/22/18
// Copyright © 2018 Miles Hollingsworth. All rights reserved.
//
let maxBufferLength = 8192
import Foundation
class CastV2PlatformReader {
let stream: InputStream
var readPosition = 0
var buffer = Data(capacity: maxBufferLength)
init(stream: InputStream) {
self.stream = stream
}
func readStream() {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
var totalBytesRead = 0
let bufferSize = 32
while stream.hasBytesAvailable {
var bytes = [UInt8](repeating: 0, count: bufferSize)
let bytesRead = stream.read(&bytes, maxLength: bufferSize)
if bytesRead < 0 { continue }
buffer.append(Data(bytes: &bytes, count: bytesRead))
totalBytesRead += bytesRead
}
}
func nextMessage() -> Data? {
objc_sync_enter(self)
defer { objc_sync_exit(self) }
let headerSize = MemoryLayout<UInt32>.size
guard buffer.count - readPosition >= headerSize else { return nil }
let header = buffer.withUnsafeBytes({ (pointer: UnsafePointer<Int8>) -> UInt32 in
return pointer.advanced(by: self.readPosition).withMemoryRebound(to: UInt32.self, capacity: 1, { $0.pointee })
})
let payloadSize = Int(CFSwapInt32BigToHost(header))
readPosition += headerSize
guard buffer.count >= readPosition + payloadSize, buffer.count - readPosition >= payloadSize, payloadSize >= 0 else {
// Message hasn't arrived
readPosition -= headerSize
return nil
}
let payload = buffer.withUnsafeBytes({ (pointer: UnsafePointer<Int8>) -> Data in
return Data(bytes: pointer.advanced(by: self.readPosition), count: payloadSize)
})
readPosition += payloadSize
resetBufferIfNeeded()
return payload
}
private func resetBufferIfNeeded() {
guard buffer.count >= maxBufferLength else { return }
if readPosition == buffer.count {
buffer = Data(capacity: maxBufferLength)
} else {
buffer = buffer.advanced(by: readPosition)
}
readPosition = 0
}
}