Class Http2Demux

  • All Implemented Interfaces:
    akka.stream.Graph<akka.stream.BidiShape<Http2SubStream,​FrameEvent,​FrameEvent,​Http2SubStream>,​ServerTerminator>
    Direct Known Subclasses:
    Http2ClientDemux, Http2ServerDemux

    public abstract class Http2Demux
    extends akka.stream.stage.GraphStageWithMaterializedValue<akka.stream.BidiShape<Http2SubStream,​FrameEvent,​FrameEvent,​Http2SubStream>,​ServerTerminator>
    INTERNAL API

    This stage contains all control logic for handling frames and (de)muxing data to/from substreams.

    The BidiStage consumes and produces FrameEvents from the network. It will output one Http2SubStream for incoming frames per substream and likewise accepts a single Http2SubStream per substream with outgoing frames.

    (An alternative API would just push a BidiHttp2SubStream(subStreamFlow: Flow[StreamFrameEvent, StreamFrameEvent]) similarly to IncomingConnection. This would more accurately model the one-to-one relation between incoming and outgoing Http2Substream directions but wouldn't stack so nicely with other BidiFlows.)

    Backpressure logic:

    * read all incoming frames without applying backpressure * this ensures that all "control" frames are read in a timely manner * though, make sure limits are not exceeded * max connection limit (which limits number of parallel requests) * window sizes for incoming data frames * that means we need to buffer incoming substream data until the user handler (consuming the source in the Http2SubStream) will read it * per-connection and per-stream window updates should reflect how much data was (not) yet passed into the user handler and therefore are the main backpressure mechanism towards the peer * for the outgoing frame side we need to decide which frames to send per incoming demand * control frames (settings, ping, acks, window updates etc.) -> responses to incoming frames * substream frames -> incoming frame data from substreams * to be able to make a decision some data must already be buffered for those two sources of incoming frames

    Demultiplexing: * distribute incoming frames to their respective targets: * control frames: handled internally, may generate outgoing control frames directly * incoming HEADERS frames: creates a new Http2SubStream including a SubSource that will receive all upcoming data frames * incoming data frames: buffered and pushed to the SubSource of the respective substream

    Multiplexing: * schedule incoming frames from multiple sources to be pushed onto the shared medium * control frames: as generated from the stage itself (should probably preferred over everything else) * Http2SubStream produced by the user handler: read and push initial frame ASAP * outgoing data frames for each of the substreams: will comprise the bulk of the data and is where any clever, prioritizing, etc. i.e. tbd later sending strategies will apply

    In the best case we could just flattenMerge the outgoing side (hoping for the best) but this will probably not work because the sending decision relies on dynamic window size and settings information that will be only available in this stage.

    param: initialRemoteSettings sequence of settings received on the initial header sent from the client in an ' HTTP2-Settings:' header. This parameter should only be used on the server end of a connection.