CongestionController class
QUIC-style congestion control for a UDX connection, after RFC 9002, with CUBIC congestion avoidance.
It is told about every send (onPacketSent), about every ACK frame once (onPacketAcked, with everything the frame newly acknowledged together) and about detected loss (onPacketLost). There is no cumulative-ack point and no duplicate-ACK counting: QUIC has neither. A retransmission goes out under a fresh sequence number, so the original number is never acknowledged, and anything that waited for it to be would wait forever. That was how this controller used to work, and after the first loss on a connection it never sampled the RTT or grew the window again.
Constructors
- CongestionController({required PacketManager packetManager, int? initialCwnd, Clock? clock})
Properties
- clock → Clock
-
The clock timing runs on; see Clock.
final
- connectionId ↔ ConnectionId?
-
Connection ID for metrics reporting.
getter/setter pair
- cwnd → int
-
The current congestion window size in bytes.
no setter
- hashCode → int
-
The hash code for this object.
no setterinherited
- hasRttSample → bool
-
Whether any RTT sample has been taken; persistent congestion is only
declared once one has (RFC 9002 section 7.6.2).
no setter
- inflight → int
-
The number of bytes in flight.
no setter
- isInRecoveryForTest → bool
-
Whether the controller is in a recovery period.
no setter
- latestRttForTest → Duration
-
The latest RTT sample, exposed for testing.
no setter
- metricsObserver ↔ UdxMetricsObserver?
-
Metrics observer for this controller (optional).
getter/setter pair
- minRtt → Duration?
-
The minimum RTT observed so far; null before the first sample.
no setter
- nextPto → Duration
-
The wait for the next probe: the base PTO backed off by the number of
PTOs that have fired without an ACK.
no setter
- onProbe ↔ void Function()?
-
Called when the PTO fires: the socket sends a probe or two (the oldest
outstanding data under fresh sequences), without touching the window.
getter/setter pair
- pacingController → PacingController
-
The packet pacer.
final
- packetManager → PacketManager
-
final
- persistentCongestionDuration → Duration
-
How long a span of loss must cover before it counts as persistent
congestion (RFC 9002 section 7.6.1): three PTOs, the PTO already
including the max_ack_delay term.
no setter
- pto → Duration
-
The base probe timeout (RFC 9002 section 6.2.1): smoothed_rtt +
max(4 * rttvar, kGranularity) + max_ack_delay. The peer delays its ACKs
by up to max_ack_delay, so a PTO without that term fires on a delayed
ACK alone. There is no floor beyond the granularity and no cap: on a
30 ms path a loss costs about 60 ms, not the 200 ms floor that used to
stand in for the missing max_ack_delay term, and a slow path's PTO is
bounded by the backoff and the idle timeout, not by a constant. Before
the first sample it is about a second (initialRtt).
no setter
- ptoCount → int
-
no setter
- rttVar → Duration
-
The RTT variation; initialRttVar before the first sample.
no setter
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
- smoothedRtt → Duration
-
The smoothed round-trip time; initialRtt before the first sample.
no setter
- ssthresh → int
-
The slow start threshold. Slow start runs until the first loss (RFC
9002 section 7.3.1). This was 65535, so slow start ended at 64 KB, 44
packets, and the window crawled up from there at CUBIC's pace.
no setter
Methods
-
destroy(
) → void - Destroys the congestion controller and cancels all timers.
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
onPacketAcked(
int bytes, Duration? sentTime, Duration ackDelay, bool largestNewlyAcked, int largestAcked) → void - Called once per ACK frame with everything it newly acknowledged.
-
onPacketLost(
int bytes, List< UDXPacket> lostPackets) → void - Called when packets are declared lost: their bytes leave flight (RFC 9002 section 7.3) and the window contracts, once per recovery epoch. When the data is re-sent it is booked again by onPacketSent, as the new packet it is. Persistent congestion is the socket's call (PacketManager.persistentCongestion, then onPersistentCongestion).
-
onPacketSent(
int bytes) → void - Called when a packet is sent.
-
onPersistentCongestion(
) → void - The RFC 9002 section 7.6 reaction: the window collapses to the minimum and recovery ends, so sending restarts in slow start, as after an outage long enough that everything sent in three PTOs was lost. Called after onPacketLost for the same loss event.
-
processEcnFeedback(
int ect0, int ect1, int ce) → void - Processes ECN (Explicit Congestion Notification) feedback from ACK frames.
-
setRttVar(
Duration rttVar) → void - Sets the RTT variation for testing purposes.
-
setSmoothedRtt(
Duration rtt) → void - Sets the smoothed RTT for testing purposes.
-
toString(
) → String -
A string representation of this object.
inherited
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited
Static Properties
- initialCwnd → int
-
final
Constants
- betaCubic → const double
- c → const double
- kPersistentCongestionThreshold → const int
- maxAckDelay → const int
- maxDatagramSize → const int
- minCwnd → const int
- noSsthresh → const int