in Sources/NIOHTTP2/Frame Buffers/OutboundFrameBuffer.swift [71:128]
mutating func processOutboundFrame(_ frame: HTTP2Frame, promise: EventLoopPromise<Void>?, channelWritable: Bool) throws -> OutboundFrameAction {
var framesToDrop: MarkedCircularBuffer<(HTTP2Frame, EventLoopPromise<Void>?)> = MarkedCircularBuffer(initialCapacity: 0)
var error: NIOHTTP2Errors.StreamClosed? = nil
// The outbound frames pass through the buffers in order, with the following logic:
//
// 1. If a buffer returns .nothing, return .nothing as the frame has been buffered.
// 2. If a buffer returns .forward, pass to the next buffer.
// 3. If a buffer returns .forwardAndDrop, pass to the next buffer and store the dropped frames. Future buffers may append
// to the dropped frames.
// 4. If a buffer returns .succeedAndDrop, return .succeedAndDrop.
// The return value of the last buffer is the return value of the compound buffer, unless we returned early.
switch try self.concurrentStreamsBuffer.processOutboundFrame(frame, promise: promise, channelWritable: channelWritable) {
case .nothing:
return .nothing
case .succeedAndDrop(let framesToDrop, let error):
return .succeedAndDrop(framesToDrop, error)
case .forwardAndDrop(let newFramesToDrop, let newError):
for frame in newFramesToDrop {
framesToDrop.append(frame)
}
error = newError
break
case .forward:
break
}
switch try self.flowControlBuffer.processOutboundFrame(frame, promise: promise) {
case .nothing:
return .nothing
case .succeedAndDrop(let framesToDrop, let error):
return .succeedAndDrop(framesToDrop, error)
case .forwardAndDrop(let newFramesToDrop, let newError):
for frame in newFramesToDrop {
framesToDrop.append(frame)
}
error = newError
break
case .forward:
break
}
switch try self.controlFrameBuffer.processOutboundFrame(frame, promise: promise, channelWritable: channelWritable) {
case .nothing:
return .nothing
case .forward:
break
case .succeedAndDrop, .forwardAndDrop:
preconditionFailure("Control frame buffer may never drop internal frames")
}
// Ok, we're at the end. If we have an error, return .forwardAndDrop. Otherwise, return .forward.
if let error = error {
return .forwardAndDrop(framesToDrop, error)
} else {
return .forward
}
}