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