public abstract class Http2Demux extends org.apache.pekko.stream.stage.GraphStageWithMaterializedValue<org.apache.pekko.stream.BidiShape<Http2SubStream,FrameEvent,FrameEvent,Http2SubStream>,ServerTerminator>
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.
Modifier and Type | Class and Description |
---|---|
static class |
Http2Demux.CompletionTimeout$ |
Constructor and Description |
---|
Http2Demux(Http2CommonSettings http2Settings,
scala.collection.immutable.Seq<FrameEvent.Setting> initialRemoteSettings,
boolean upgraded,
boolean isServer) |
Modifier and Type | Method and Description |
---|---|
abstract scala.concurrent.duration.FiniteDuration |
completionTimeout() |
scala.Tuple2<org.apache.pekko.stream.stage.GraphStageLogic,ServerTerminator> |
createLogicAndMaterializedValue(org.apache.pekko.stream.Attributes inheritedAttributes) |
org.apache.pekko.stream.Inlet<FrameEvent> |
frameIn() |
org.apache.pekko.stream.Outlet<FrameEvent> |
frameOut() |
org.apache.pekko.stream.BidiShape<Http2SubStream,FrameEvent,FrameEvent,Http2SubStream> |
shape() |
org.apache.pekko.stream.Inlet<Http2SubStream> |
substreamIn() |
org.apache.pekko.stream.Outlet<Http2SubStream> |
substreamOut() |
abstract scala.Option<HttpEntity.ChunkStreamPart> |
wrapTrailingHeaders(FrameEvent.ParsedHeadersFrame headers) |
addAttributes, async, async, async, createLogicAndMaterializedValue, getAttributes, initialAttributes, named, traversalBuilder, withAttributes
public Http2Demux(Http2CommonSettings http2Settings, scala.collection.immutable.Seq<FrameEvent.Setting> initialRemoteSettings, boolean upgraded, boolean isServer)
public org.apache.pekko.stream.Inlet<FrameEvent> frameIn()
public org.apache.pekko.stream.Outlet<FrameEvent> frameOut()
public org.apache.pekko.stream.Outlet<Http2SubStream> substreamOut()
public org.apache.pekko.stream.Inlet<Http2SubStream> substreamIn()
public org.apache.pekko.stream.BidiShape<Http2SubStream,FrameEvent,FrameEvent,Http2SubStream> shape()
public abstract scala.Option<HttpEntity.ChunkStreamPart> wrapTrailingHeaders(FrameEvent.ParsedHeadersFrame headers)
public abstract scala.concurrent.duration.FiniteDuration completionTimeout()
public scala.Tuple2<org.apache.pekko.stream.stage.GraphStageLogic,ServerTerminator> createLogicAndMaterializedValue(org.apache.pekko.stream.Attributes inheritedAttributes)
createLogicAndMaterializedValue
in class org.apache.pekko.stream.stage.GraphStageWithMaterializedValue<org.apache.pekko.stream.BidiShape<Http2SubStream,FrameEvent,FrameEvent,Http2SubStream>,ServerTerminator>