quic_flow (quic v1.10.0)
View SourceConnection-level flow control accounting.
Standalone helper: quic_connection does not use it. The flow control that runs on the wire is inline in quic_connection, which auto-tunes the window from the RTT, keeps per-stream limits, sends the frames and closes the connection on a violation. Read that for the library's behaviour; use this module when you want the accounting on its own.
What it does: - Tracking bytes sent against peer's MAX_DATA limit - Tracking bytes received against our MAX_DATA limit - Telling you when a MAX_DATA update is due, and what value to grant - Detecting when we're blocked by flow control
What it does not do: stream-level accounting, and sending anything. It emits no frames, so you send MAX_DATA and DATA_BLOCKED yourself and you decide what a violation does.
Flow Control Concepts
- MAX_DATA: Maximum total bytes the peer can send - DATA_BLOCKED: Indicates sender is blocked by receiver's limit - Window: The difference between max_data and bytes received
Summary
Functions
Get total bytes we've received.
Get total bytes we've sent.
Check if we can send the specified number of bytes.
Generate a new MAX_DATA value to send. Returns {NewMaxData, UpdatedState}.
Create a new flow control state.
Create a new flow control state with options.
Record that we received data.
Record that we sent data. Returns {ok, NewState} or {blocked, NewState} if we hit the limit.
Process a MAX_DATA frame from peer. Updates our send limit.
Get our current receive limit (our MAX_DATA).
Get available receive window.
Check if we're currently blocked on send flow control.
Get our current send limit (peer's MAX_DATA).
Get available send window.
Check if we should send a MAX_DATA update. True once the granted window is down to its last ?WINDOW_UPDATE_THRESHOLD fraction. That constant is the fraction remaining, not the fraction consumed, so 0.75 fires after 25% of the window has been used.
Types
Functions
-spec bytes_received(flow_state()) -> non_neg_integer().
Get total bytes we've received.
-spec bytes_sent(flow_state()) -> non_neg_integer().
Get total bytes we've sent.
-spec can_send(flow_state(), non_neg_integer()) -> boolean().
Check if we can send the specified number of bytes.
-spec generate_max_data(flow_state()) -> {non_neg_integer(), flow_state()}.
Generate a new MAX_DATA value to send. Returns {NewMaxData, UpdatedState}.
-spec new() -> flow_state().
Create a new flow control state.
-spec new(map()) -> flow_state().
Create a new flow control state with options.
-spec on_data_received(flow_state(), non_neg_integer()) -> {ok, flow_state()} | {error, flow_control_error}.
Record that we received data.
-spec on_data_sent(flow_state(), non_neg_integer()) -> {ok | blocked, flow_state()}.
Record that we sent data. Returns {ok, NewState} or {blocked, NewState} if we hit the limit.
-spec on_max_data_received(flow_state(), non_neg_integer()) -> flow_state().
Process a MAX_DATA frame from peer. Updates our send limit.
-spec recv_limit(flow_state()) -> non_neg_integer().
Get our current receive limit (our MAX_DATA).
-spec recv_window(flow_state()) -> non_neg_integer().
Get available receive window.
-spec send_blocked(flow_state()) -> boolean().
Check if we're currently blocked on send flow control.
-spec send_limit(flow_state()) -> non_neg_integer().
Get our current send limit (peer's MAX_DATA).
-spec send_window(flow_state()) -> non_neg_integer().
Get available send window.
-spec should_send_max_data(flow_state()) -> boolean().
Check if we should send a MAX_DATA update. True once the granted window is down to its last ?WINDOW_UPDATE_THRESHOLD fraction. That constant is the fraction remaining, not the fraction consumed, so 0.75 fires after 25% of the window has been used.