Class Recovery

java.lang.Object
io.github.mahmoudimus.quic.connection.Recovery

public final class Recovery extends Object
Loss detection and congestion control of one connection (RFC 9002): the three packet number spaces, the in-flight counts, the RTT estimator, the congestion controller, the pacer, MTU discovery and the probe timeout. It sets 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.

  • Constructor Details

  • Method Details

    • space

      public PacketSpace space(SpaceId id)
      A packet number space.
      Parameters:
      id - which space
      Returns:
      the space
    • path

      public PathData path()
      The path packets are sent on.
      Returns:
      the current path
    • prevPath

      public PathData prevPath()
      The path before the last migration, kept for the packets still in flight on it.
      Returns:
      the previous path, or null
    • rtt

      public RttEstimator rtt()
      The RTT estimator.
      Returns:
      the estimator
    • congestion

      public Controller congestion()
      The congestion controller.
      Returns:
      the controller
    • mtud

      public MtuDiscovery mtud()
      MTU discovery.
      Returns:
      the discovery state
    • ackFrequency

      public AckFrequencyState 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

      public DeliveryRate 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

      public void setPeerParams(TransportParameters params)
      Applies the peer's transport parameters: its ack_delay_exponent, max_ack_delay and max_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_VALUE once the peer's address is validated
    • nextPacketNumber

      public long nextPacketNumber(SpaceId id)
      Allocates the next packet number of a space; the application data space occasionally skips one (see PacketNumberFilter).
      Parameters:
      id - the space
      Returns:
      the packet number
    • peekPacketNumber

      public long peekPacketNumber(SpaceId id)
      Parameters:
      id - the space
      Returns:
      the packet number
    • onPacketSent

      public void onPacketSent(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.
      Parameters:
      now - the current time
      id - the packet's space
      packetNumber - its number
      packet - 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 time
      bytes - the datagram's size
      lastPacketNumber - 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 stops Timer.PACING.
      Parameters:
      now - the current time
      bytesToSend - the packet's size
      Returns:
      the time to try again, or NanoClock.NONE to send now
    • onPacketReceived

      public boolean onPacketReceived(long now, SpaceId id, long packetNumber, boolean ackEliciting)
      Records an authenticated packet: duplicate detection, ACK bookkeeping, and the Timer.MAX_ACK_DELAY timer in the application data space.
      Parameters:
      now - the current time
      id - the packet's space
      packetNumber - its number
      ackEliciting - whether it is ack-eliciting
      Returns:
      true if it is a duplicate, to be dropped
    • onAcksSent

      public void onAcksSent(SpaceId id)
      Records that an ACK frame was sent in a space.
      Parameters:
      id - the space
    • onMaxAckDelayTimeout

      public void onMaxAckDelayTimeout()
      Handles the expiry of Timer.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 time
      id - the space the ACK arrived in
      ack - the frame
      listener - receives the acknowledged and lost packets
      Throws:
      QuicException - PROTOCOL_VIOLATION if the ACK covers a packet number never sent
    • onLossDetectionTimeout

      public void onLossDetectionTimeout(long now, Recovery.Listener listener)
      Handles the expiry of Timer.LOSS_DETECTION: time-threshold loss detection if a loss time is set, otherwise a probe timeout, which asks for one or two probe packets (see PacketSpace.lossProbes()) and doubles the next timeout.
      Parameters:
      now - the current time
      listener - 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 stops Timer.LOSS_DETECTION (RFC 9002 appendix A.8).
      Parameters:
      now - the current time
    • pto

      public long pto(SpaceId id)
      The probe timeout of a space, without backoff: smoothed_rtt + max(4 * rttvar, kGranularity), plus the peer's max_ack_delay in the application data space.
      Parameters:
      id - the space
      Returns:
      nanoseconds
    • discardSpace

      public void discardSpace(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.
      Parameters:
      now - the current time
      id - SpaceId.INITIAL or SpaceId.HANDSHAKE
    • discardZeroRttPackets

      public List<SentPacket> 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).
      Parameters:
      now - the current time
      Returns:
      the packets, whose control frames may be queued again
    • resetIdleTimer

      public void resetIdleTimer(long now, SpaceId id, long idleTimeout)
      Restarts Timer.IDLE: the idle timeout, but at least three PTOs (RFC 9000 section 10.1).
      Parameters:
      now - the current time
      id - the space of the packet that prompted the reset
      idleTimeout - the negotiated idle timeout in nanoseconds, or 0 for none
    • setKeyDiscardTimer

      public void setKeyDiscardTimer(long start, SpaceId id)
      Sets Timer.KEY_DISCARD to 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, see updateKeyDiscardTimer().
      Parameters:
      start - when the timer starts, such as when the key update was acknowledged
      id - 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: unlike ptoCount(), 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