mutating func processOutboundFrame()

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
        }
    }