Class Recovery
Timer.LOSS_DETECTION in the connection's TimerTable; the connection calls onLossDetectionTimeout(long, io.github.mahmoudimus.quic.connection.Recovery.Listener) when it fires.
The connection layer reports what it sends (onPacketSent(long, io.github.mahmoudimus.quic.connection.SpaceId, long, io.github.mahmoudimus.quic.connection.SentPacket), onDatagramSent(long, long, long))
and receives (onPacketReceived(long, io.github.mahmoudimus.quic.connection.SpaceId, long, boolean), onAckReceived(long, io.github.mahmoudimus.quic.connection.SpaceId, io.github.mahmoudimus.quic.frame.Frame.Ack, io.github.mahmoudimus.quic.connection.Recovery.Listener)); acknowledged and lost packets
are handed to a Recovery.Listener, and the control frames of lost packets are queued again in their
space's PacketSpace.pending().
Persistent congestion (RFC 9002 section 7.6) is detected among packets deemed lost on receipt
of an ACK: two ack-eliciting packets lost more than persistentCongestionThreshold PTOs
apart, with nothing acknowledged between them, both sent after the first RTT sample.
Times and durations are nanoseconds.
Threads. Not thread-safe and takes no locks; owned by one connection, which serializes access.
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic interfaceReceives acknowledged and lost packets. -
Constructor Summary
ConstructorsConstructorDescriptionRecovery(Side side, RecoveryConfig config, TimerTable timers, RandomGenerator random, long now) Loss recovery for a new connection. -
Method Summary
Modifier and TypeMethodDescriptionlongAck-eliciting packets in flight.The ACK delays of both endpoints.booleanantiAmplificationBlocked(long bytesToSend) Whether a server must not send yet: until the peer's address is validated it may send at most three times what it received (RFC 9000 section 8.1).longHow many more bytes the anti-amplification limit lets this endpoint send.longMTU black holes detected.longBytes in flight.voidclose()Stops loss detection for good, as the connection closes.The congestion controller.longCongestion events, from loss or ECN.The delivery rate sampler of the connection's congestion-controlled packets.voiddiscardSpace(long now, SpaceId id) Discards the Initial or Handshake space once its keys are no longer needed (RFC 9001 section 4.9, RFC 9002 section 6.4): its keys, sent packets and in-flight bytes are dropped, and the PTO backoff restarts.discardZeroRttPackets(long now) Forgets the packets sent in the application data space without counting them lost, after the server rejected 0-RTT: it never processed them (quinn's handling of rejected 0-RTT).booleanWhether the application, not the congestion window or the pacer, limited the last send.booleanisCongestionBlocked(long bytes) Whether a packet of some size fits the congestion window.longBytes of packets deemed lost.longMTU probes lost.longPackets deemed lost, not counting MTU probes.mtud()MTU discovery.longAllocates the next packet number of a space; the application data space occasionally skips one (seePacketNumberFilter).voidonAckReceived(long now, SpaceId id, Frame.Ack ack, Recovery.Listener listener) Processes an ACK frame (RFC 9002 section 6 and appendix A.7): acknowledges packets, takes an RTT sample, detects loss, validates ECN counts and rearms the loss detection timer.voidonAcksSent(SpaceId id) Records that an ACK frame was sent in a space.voidonDatagramReceived(long bytes) Records a received datagram, for the anti-amplification limit.voidonDatagramSent(long now, long bytes, long lastPacketNumber) Records a sent datagram, for the congestion controller and the anti-amplification limit.voidonLossDetectionTimeout(long now, Recovery.Listener listener) Handles the expiry ofTimer.LOSS_DETECTION: time-threshold loss detection if a loss time is set, otherwise a probe timeout, which asks for one or two probe packets (seePacketSpace.lossProbes()) and doubles the next timeout.voidHandles the expiry ofTimer.MAX_ACK_DELAY: an ACK is now due.booleanonPacketReceived(long now, SpaceId id, long packetNumber, boolean ackEliciting) Records an authenticated packet: duplicate detection, ACK bookkeeping, and theTimer.MAX_ACK_DELAYtimer in the application data space.voidonPacketSent(long now, SpaceId id, long packetNumber, SentPacket packet) Records a sent packet: in-flight counts, the time of the last ack-eliciting packet, pacing, and the loss detection timer.longpacingDelay(long now, long bytesToSend) When pacing allows a packet; sets or stopsTimer.PACING.path()The path packets are sent on.longThe packet numbernextPacketNumber(io.github.mahmoudimus.quic.connection.SpaceId)would allocate.booleanWhether the peer must have validated this endpoint's address: always for a server; for a client once a Handshake or 1-RTT packet is acknowledged, or the handshake keys are discarded while 1-RTT keys are installed.prevPath()The path before the last migration, kept for the packets still in flight on it.longProbe timeouts so far: unlikeptoCount(), never reset.longThe probe timeout of a space, without backoff:smoothed_rtt + max(4 * rttvar, kGranularity), plus the peer'smax_ack_delayin the application data space.intptoCount()The number of probe timeouts since the last acknowledgement, which sets the backoff.longBytes of datagrams received and taken by the connection, as UDP payloads, on every path.voidresetIdleTimer(long now, SpaceId id, long idleTimeout) RestartsTimer.IDLE: the idle timeout, but at least three PTOs (RFC 9000 section 10.1).rtt()The RTT estimator.booleanWhether ECN-marked packets are being sent; an ACK without ECN counts or with invalid ones turns it off.longBytes of datagrams sent, as UDP payloads, on every path.longPackets sent.voidRecords that the peer's address is validated, lifting the anti-amplification limit.voidsetAppLimited(boolean appLimited) Records whether the application, not the congestion window, limited the last send; ACKs then do not grow the window.voidsetHandshakeConfirmed(boolean confirmed) Records that the handshake is confirmed (RFC 9001 section 4.1.2); until then the probe timeout ignores the application data space (RFC 9002 section 6.2.1).voidsetKeyDiscardTimer(long start, SpaceId id) SetsTimer.KEY_DISCARDto three PTOs after a start time, when old keys may go (RFC 9001 sections 4.9.3 and 6.5).voidsetLossDetectionTimer(long now) Arms or stopsTimer.LOSS_DETECTION(RFC 9002 appendix A.8).voidsetPeerParams(TransportParameters params) Applies the peer's transport parameters: itsack_delay_exponent,max_ack_delayandmax_udp_payload_size.voidsetSendingEcn(boolean sendingEcn) Sets whether ECN is in use, for a connection that cannot mark packets.A packet number space.longCongestion events found spurious.
-
Constructor Details
-
Recovery
public Recovery(Side side, RecoveryConfig config, TimerTable timers, RandomGenerator random, long now) Loss recovery for a new connection.- Parameters:
side- this endpoint's role; a client's address is always validated, a server's peer address is not untilsetAddressValidated()config- the configurationtimers- the connection's timers, whereTimer.LOSS_DETECTIONandTimer.MAX_ACK_DELAYare setrandom- the source of randomness for skipped packet numbersnow- the current time
-
-
Method Details
-
space
A packet number space.- Parameters:
id- which space- Returns:
- the space
-
path
The path packets are sent on.- Returns:
- the current path
-
prevPath
The path before the last migration, kept for the packets still in flight on it.- Returns:
- the previous path, or null
-
rtt
The RTT estimator.- Returns:
- the estimator
-
congestion
The congestion controller.- Returns:
- the controller
-
mtud
MTU discovery.- Returns:
- the discovery state
-
ackFrequency
The ACK delays of both endpoints.- Returns:
- the ACK frequency state
-
bytesInFlight
public long bytesInFlight()Bytes in flight.- Returns:
- the size of congestion-controlled packets neither acknowledged nor lost
-
ackElicitingInFlight
public long ackElicitingInFlight()Ack-eliciting packets in flight.- Returns:
- the count
-
ptoCount
public int ptoCount()The number of probe timeouts since the last acknowledgement, which sets the backoff.- Returns:
- the PTO count
-
isCongestionBlocked
public boolean isCongestionBlocked(long bytes) Whether a packet of some size fits the congestion window.- Parameters:
bytes- the packet's size- Returns:
- true if sending it would exceed the window
-
setAppLimited
public void setAppLimited(boolean appLimited) Records whether the application, not the congestion window, limited the last send; ACKs then do not grow the window.- Parameters:
appLimited- whether sending was application limited
-
deliveryRate
The delivery rate sampler of the connection's congestion-controlled packets.- Returns:
- the sampler
-
isAppLimited
public boolean isAppLimited()Whether the application, not the congestion window or the pacer, limited the last send.- Returns:
- the flag ACKs are processed with
-
setHandshakeConfirmed
public void setHandshakeConfirmed(boolean confirmed) Records that the handshake is confirmed (RFC 9001 section 4.1.2); until then the probe timeout ignores the application data space (RFC 9002 section 6.2.1).- Parameters:
confirmed- whether it is confirmed
-
close
public void close()Stops loss detection for good, as the connection closes. -
sendingEcn
public boolean sendingEcn()Whether ECN-marked packets are being sent; an ACK without ECN counts or with invalid ones turns it off.- Returns:
- true while ECN is in use
-
setSendingEcn
public void setSendingEcn(boolean sendingEcn) Sets whether ECN is in use, for a connection that cannot mark packets.- Parameters:
sendingEcn- whether outgoing packets carry ECT(0)
-
setPeerParams
Applies the peer's transport parameters: itsack_delay_exponent,max_ack_delayandmax_udp_payload_size.- Parameters:
params- the peer's parameters
-
setAddressValidated
public void setAddressValidated()Records that the peer's address is validated, lifting the anti-amplification limit. -
antiAmplificationBlocked
public boolean antiAmplificationBlocked(long bytesToSend) Whether a server must not send yet: until the peer's address is validated it may send at most three times what it received (RFC 9000 section 8.1).- Parameters:
bytesToSend- the bytes about to be sent- Returns:
- true if they would exceed the limit
-
antiAmplificationBudget
public long antiAmplificationBudget()How many more bytes the anti-amplification limit lets this endpoint send.- Returns:
- three times the bytes received less those sent, at least 0;
Long.MAX_VALUEonce the peer's address is validated
-
nextPacketNumber
Allocates the next packet number of a space; the application data space occasionally skips one (seePacketNumberFilter).- Parameters:
id- the space- Returns:
- the packet number
-
peekPacketNumber
The packet numbernextPacketNumber(io.github.mahmoudimus.quic.connection.SpaceId)would allocate.- Parameters:
id- the space- Returns:
- the packet number
-
onPacketSent
Records a sent packet: in-flight counts, the time of the last ack-eliciting packet, pacing, and the loss detection timer.- Parameters:
now- the current timeid- the packet's spacepacketNumber- its numberpacket- what to remember about it
-
onDatagramSent
public void onDatagramSent(long now, long bytes, long lastPacketNumber) Records a sent datagram, for the congestion controller and the anti-amplification limit.- Parameters:
now- the current timebytes- the datagram's sizelastPacketNumber- the number of the last packet in it
-
onDatagramReceived
public void onDatagramReceived(long bytes) Records a received datagram, for the anti-amplification limit.- Parameters:
bytes- the datagram's size
-
pacingDelay
public long pacingDelay(long now, long bytesToSend) When pacing allows a packet; sets or stopsTimer.PACING.- Parameters:
now- the current timebytesToSend- the packet's size- Returns:
- the time to try again, or
NanoClock.NONEto send now
-
onPacketReceived
Records an authenticated packet: duplicate detection, ACK bookkeeping, and theTimer.MAX_ACK_DELAYtimer in the application data space.- Parameters:
now- the current timeid- the packet's spacepacketNumber- its numberackEliciting- whether it is ack-eliciting- Returns:
- true if it is a duplicate, to be dropped
-
onAcksSent
Records that an ACK frame was sent in a space.- Parameters:
id- the space
-
onMaxAckDelayTimeout
public void onMaxAckDelayTimeout()Handles the expiry ofTimer.MAX_ACK_DELAY: an ACK is now due. -
onAckReceived
public void onAckReceived(long now, SpaceId id, Frame.Ack ack, Recovery.Listener listener) throws QuicException Processes an ACK frame (RFC 9002 section 6 and appendix A.7): acknowledges packets, takes an RTT sample, detects loss, validates ECN counts and rearms the loss detection timer.- Parameters:
now- the current timeid- the space the ACK arrived inack- the framelistener- receives the acknowledged and lost packets- Throws:
QuicException-PROTOCOL_VIOLATIONif the ACK covers a packet number never sent
-
onLossDetectionTimeout
Handles the expiry ofTimer.LOSS_DETECTION: time-threshold loss detection if a loss time is set, otherwise a probe timeout, which asks for one or two probe packets (seePacketSpace.lossProbes()) and doubles the next timeout.- Parameters:
now- the current timelistener- receives lost packets
-
peerCompletedAddressValidation
public boolean peerCompletedAddressValidation()Whether the peer must have validated this endpoint's address: always for a server; for a client once a Handshake or 1-RTT packet is acknowledged, or the handshake keys are discarded while 1-RTT keys are installed.- Returns:
- true if the peer completed address validation
-
setLossDetectionTimer
public void setLossDetectionTimer(long now) Arms or stopsTimer.LOSS_DETECTION(RFC 9002 appendix A.8).- Parameters:
now- the current time
-
pto
The probe timeout of a space, without backoff:smoothed_rtt + max(4 * rttvar, kGranularity), plus the peer'smax_ack_delayin the application data space.- Parameters:
id- the space- Returns:
- nanoseconds
-
discardSpace
Discards the Initial or Handshake space once its keys are no longer needed (RFC 9001 section 4.9, RFC 9002 section 6.4): its keys, sent packets and in-flight bytes are dropped, and the PTO backoff restarts.- Parameters:
now- the current timeid-SpaceId.INITIALorSpaceId.HANDSHAKE
-
discardZeroRttPackets
Forgets the packets sent in the application data space without counting them lost, after the server rejected 0-RTT: it never processed them (quinn's handling of rejected 0-RTT).- Parameters:
now- the current time- Returns:
- the packets, whose control frames may be queued again
-
resetIdleTimer
RestartsTimer.IDLE: the idle timeout, but at least three PTOs (RFC 9000 section 10.1).- Parameters:
now- the current timeid- the space of the packet that prompted the resetidleTimeout- the negotiated idle timeout in nanoseconds, or 0 for none
-
setKeyDiscardTimer
SetsTimer.KEY_DISCARDto three PTOs after a start time, when old keys may go (RFC 9001 sections 4.9.3 and 6.5). The timer follows the current PTO: each new RTT estimate moves it, seeupdateKeyDiscardTimer().- Parameters:
start- when the timer starts, such as when the key update was acknowledgedid- the space whose PTO applies
-
sentPackets
public long sentPackets()Packets sent.- Returns:
- the count
-
sentBytes
public long sentBytes()Bytes of datagrams sent, as UDP payloads, on every path.- Returns:
- the count
-
receivedBytes
public long receivedBytes()Bytes of datagrams received and taken by the connection, as UDP payloads, on every path.- Returns:
- the count
-
probeTimeouts
public long probeTimeouts()Probe timeouts so far: unlikeptoCount(), never reset.- Returns:
- the count
-
lostPackets
public long lostPackets()Packets deemed lost, not counting MTU probes.- Returns:
- the count
-
lostBytes
public long lostBytes()Bytes of packets deemed lost.- Returns:
- the count
-
congestionEvents
public long congestionEvents()Congestion events, from loss or ECN.- Returns:
- the count
-
spuriousCongestionEvents
public long spuriousCongestionEvents()Congestion events found spurious.- Returns:
- the count
-
lostMtuProbes
public long lostMtuProbes()MTU probes lost.- Returns:
- the count
-
blackHolesDetected
public long blackHolesDetected()MTU black holes detected.- Returns:
- the count
-