PacketManager class
Manages packet sending and receiving for a UDXStream Tracks sent packets, matches ACKs to them, and declares loss the way RFC 9002 section 6.1 does: from acknowledgements, never from a per-packet timer. The port of go-udx's PacketManager.
A packet is lost once a later one has been acknowledged and it is either lossReorderThreshold sequences behind the largest acknowledged or older than lossDelay (9/8 of the RTT). Packets behind but not yet old enough wait on the loss timer, which declares them lost when the delay elapses without another ACK. What is lost is handed to onPacketsLost; the socket contracts its window once per recovery epoch and re-sends the data under fresh sequences through the congestion window and the pacer (LostQueue).
This replaced one retransmission timer per packet, armed at the RTO and backing off to a 2 s cap. On a radio gap every timer fired together and the whole window went out again at once, past the congestion window, and again every 2 s into a dead path; the resends did not contract the window either. QUIC's one PTO per connection (CongestionController) sends a probe or two instead, backing off until the idle timeout, and loss is declared only once an ACK proves it.
Constructors
- PacketManager({CongestionController? congestionController, Clock? clock})
- Creates a new packet manager
Properties
- clock → Clock
-
The clock send times and the loss timer run on; see Clock.
final
- congestionController ↔ CongestionController
-
The congestion control algorithm
getter/setter pair
- hashCode → int
-
The hash code for this object.
no setterinherited
- largestAcked → int
-
The largest sequence the peer has acknowledged, -1 if none; when the
last ACK that acknowledged something arrived; and the one before the
ACK (or timer) that last declared loss: persistent congestion asks
whether anything was acknowledged since the oldest lost packet went
out, which the ACK that revealed the loss does not answer.
no setter
- lastSentPacketNumber ↔ int
-
The sequence number of the last packet that was sent.
getter/setter pair
- lossDelay → Duration
-
How long a packet must have been outstanding before age alone marks it
lost: 9/8 of the larger of the smoothed and latest RTT, floored at the
timer granularity (RFC 9002 section 6.1.2). The larger of the two: after
a sudden increase in delay the smoothed estimate lags, and alone it would
declare a window of packets lost for being slower than they used to be.
no setter
- lossTimerArmed → bool
-
Whether a packet is waiting on the time threshold.
no setter
- nextSequence → int
-
The next sequence number to use
no setter
- onPacketLossEvent ↔ void Function(int sequence, String lossType)?
-
Callback for metrics when packet loss is detected.
Provides sequence number and loss type ('ack' or 'time').
getter/setter pair
- onPacketRetransmitEvent ↔ void Function(int sequence, int attemptCount, Duration rto)?
-
Callback for metrics when a packet is retransmitted.
Provides sequence number, attempt count, and the current PTO.
getter/setter pair
-
onPacketsLost
↔ void Function(List<
UDXPacket> lost)? -
Told what loss detection declared lost, oldest first. The packets are no
longer tracked: the receiver re-sends them (resend) and books them.
getter/setter pair
- onRetransmit ↔ void Function(UDXPacket packet)?
-
Puts a packet back on the wire. By the time it is called the packet's
sequence has been advanced to a fresh number (resend), so this only
encodes and sends.
getter/setter pair
- runtimeType → Type
-
A representation of the runtime type of the object.
no setterinherited
-
sentPackets
→ List<
UDXPacket> -
no setter
Methods
-
destroy(
) → void - Stops the loss timer and forgets every packet.
-
detectLostPackets(
) → List< UDXPacket> - Runs loss detection over everything outstanding (RFC 9002 section 6.1) and returns what it declared lost, also handed to onPacketsLost. The socket calls it after each ACK that acknowledged something; the loss timer calls it when the time threshold elapses.
-
drop(
UDXPacket packet) → void - Forgets a tracked packet that is being replaced by others (fitToPath), neither acknowledged nor lost.
-
fitToPath(
UDXPacket packet, int limit) → List< UDXPacket> - Re-chunks a packet larger than the path now carries (the size fell back after a black hole, MtuDiscovery) into packets that fit, in its place: the original is dropped from tracking and the pieces take fresh sequences when they are re-sent (resend). A packet that fits is returned as it is. Only a packet carrying one STREAM frame is split, which is every data packet a stream sends.
-
forget(
int sequence) → void -
Stops tracking
sequence, if it is still tracked. -
getPacket(
int sequence) → UDXPacket? - Gets a sent packet by its sequence number
-
getSentPacketsTestHook(
) → Map< int, UDXPacket> -
handleAckFrame(
AckFrame frame) → List< UDXPacket> - Processes an incoming AckFrame, marking packets as acknowledged.
-
handleData(
UDXPacket packet) → void - Handles received data
-
noSuchMethod(
Invocation invocation) → dynamic -
Invoked when a nonexistent method or property is accessed.
inherited
-
oldestUnacked(
int n) → List< UDXPacket> -
Up to
noutstanding packets, lowest sequence first: what a PTO probe re-sends. A re-send takes a fresh sequence, so the lowest numbers are the longest unsent. -
persistentCongestion(
List< UDXPacket> lost) → bool -
Whether
lost, as just declared, is persistent congestion (RFC 9002 section 7.6): the sender has an RTT sample, the newest lost packet went out at least three PTOs after the oldest, and nothing was acknowledged between the oldest going out and the ACK (or timer) that revealed the loss. The socket then collapses the window. -
resend(
UDXPacket packet) → int? - Gives a packet a FRESH sequence number for another transmission and tracks it under that number, returning the number, or null when the packet has been acknowledged and must not go out again.
-
sendPacket(
UDXPacket packet) → void - Sends a packet
-
sendProbe(
{int? maxDatagram}) → bool -
Sends the PTO's probes: the ptoProbes oldest outstanding packets,
re-sent under fresh sequences (RFC 9002 section 6.2.4: a probe carries
data when there is data to carry). They are not declared lost (an ACK
will say), their bytes stay in flight, and neither the window nor the
pacer is consulted: a probe is allowed out when nothing else is (RFC
9002 section 7.7 exempts probes from pacing), though it is drawn from
the pacing budget so that what follows it is paced as if it had been.
maxDatagram, when given, is what the path carries now: a larger packet is re-chunked to fit. Returns whether anything went out. -
toString(
) → String -
A string representation of this object.
inherited
-
trackUntilAcked(
UDXPacket packet) → void - Tracks a packet the caller sends itself, so that handleAckFrame returns it when acknowledged, without ever retransmitting it: a PING sent to test liveness (UDPSocket.ping). The caller forgets it (forget) when it stops waiting, so a lost ACK leaves nothing behind.
Operators
-
operator ==(
Object other) → bool -
The equality operator.
inherited
Constants
- lossReorderThreshold → const int
- How many sequences a packet must trail the largest acknowledged before a gap counts as loss (kPacketThreshold, RFC 9002 section 6.1.1).
- lossTimerGranularity → const Duration
- The floor on the loss delay (kGranularity).
- ptoProbes → const int
- How many outstanding packets a PTO re-sends, the oldest first (RFC 9002 section 6.2.4 allows up to two).