HaishinKit.swift/Sources/RTMP/RTMPSocket.swift

107 lines
3.2 KiB
Swift

import Foundation
// MARK: -
final class RTMPSocket: NetSocket, RTMPSocketCompatible {
var readyState: RTMPSocketReadyState = .uninitialized {
didSet {
delegate?.didSetReadyState(readyState)
}
}
var timestamp: TimeInterval {
handshake.timestamp
}
var chunkSizeC: Int = RTMPChunk.defaultSize
var chunkSizeS: Int = RTMPChunk.defaultSize
weak var delegate: RTMPSocketDelegate?
private var handshake = RTMPHandshake()
override var totalBytesIn: Atomic<Int64> {
didSet {
delegate?.didSetTotalBytesIn(totalBytesIn.value)
}
}
override var connected: Bool {
didSet {
if connected {
doOutput(data: handshake.c0c1packet)
readyState = .versionSent
return
}
readyState = .closed
for event in events {
delegate?.dispatch(event: event)
}
events.removeAll()
}
}
private var events: [Event] = []
@discardableResult
func doOutput(chunk: RTMPChunk, locked: UnsafeMutablePointer<UInt32>? = nil) -> Int {
let chunks: [Data] = chunk.split(chunkSizeS)
for i in 0..<chunks.count - 1 {
doOutput(data: chunks[i])
}
doOutput(data: chunks.last!, locked: locked)
if logger.isEnabledFor(level: .trace) {
logger.trace(chunk)
}
return chunk.message!.length
}
override func listen() {
switch readyState {
case .versionSent:
if inputBuffer.count < RTMPHandshake.sigSize + 1 {
break
}
doOutput(data: handshake.c2packet(inputBuffer))
inputBuffer.removeSubrange(0...RTMPHandshake.sigSize)
readyState = .ackSent
if RTMPHandshake.sigSize <= inputBuffer.count {
listen()
}
case .ackSent:
if inputBuffer.count < RTMPHandshake.sigSize {
break
}
inputBuffer.removeAll()
readyState = .handshakeDone
case .handshakeDone:
if inputBuffer.isEmpty {
break
}
let bytes: Data = inputBuffer
inputBuffer.removeAll()
delegate?.listen(bytes)
default:
break
}
}
override func initConnection() {
handshake.clear()
readyState = .uninitialized
chunkSizeS = RTMPChunk.defaultSize
chunkSizeC = RTMPChunk.defaultSize
super.initConnection()
}
override func deinitConnection(isDisconnected: Bool) {
if isDisconnected {
let data: ASObject = (readyState == .handshakeDone) ?
RTMPConnection.Code.connectClosed.data("") : RTMPConnection.Code.connectFailed.data("")
events.append(Event(type: .rtmpStatus, bubbles: false, data: data))
}
readyState = .closing
super.deinitConnection(isDisconnected: isDisconnected)
}
override func didTimeout() {
deinitConnection(isDisconnected: false)
delegate?.dispatch(.ioError, bubbles: false, data: nil)
logger.warn("connection timedout")
}
}