java.lang.Object
net.i2p.router.transport.udp.PeerState
Direct Known Subclasses:
PeerState2

public class PeerStateextends Object
Contain all of the state about a UDP connection to a peer. This is instantiated only after a connection is fully established.

Public only for UI peers page. Not a public API, not for external use.

  • Field Details

    • _context

      protected final RouterContext _context
      The router context.
    • _log

      protected final Log _log
      The log.
    • _remotePeer

      protected final Hash _remotePeer
      The peer are we talking to. This should be set as soon as this state is created if we are initiating a connection, but if we are receiving the connection this will be set only after the connection is established.
    • _shortHash

      protected final String _shortHash
      Six-char base64 prefix of the remote peer hash, pre-computed for log messages (the full encode per log line was hot on floodfills).
    • _keyEstablishedTime

      protected final long _keyEstablishedTime
      The key establishment time.
    • _clockSkew

      private long _clockSkew
      How far off is the remote peer from our clock, in milliseconds? A positive number means our clock is ahead of theirs.
    • _clockSkewLock

      private final Object _clockSkewLock
      Lock for the clock skew calculations.
    • _lastSendTime

      private long _lastSendTime
      When did we last send them a packet?
    • _lastSendFullyTime

      private volatile long _lastSendFullyTime
      When did we last send them a message that was ACKed.
    • _lastPingTime

      private long _lastPingTime
      When did we last send them a ping?
    • _lastReceiveTime

      private volatile long _lastReceiveTime
      When did we last receive a packet from them?
    • _consecutiveFailedSends

      private volatile int _consecutiveFailedSends
      How many consecutive messages have we sent and not received an ACK to.
    • _lastACKSend

      protected volatile long _lastACKSend
      When did we last send ACKs to the peer?
    • _wantACKSendSince

      protected volatile long _wantACKSendSince
      When did we decide we need to ACK to this peer?
    • _sendWindowBytes

      private final AtomicInteger _sendWindowBytes
      How many bytes should we send to the peer in a second.
    • _sendWindowBytesRemaining

      private volatile int _sendWindowBytesRemaining
      How many bytes can we send to the peer in the current second.
    • _sendWindowBytesRemainingLock

      private final Object _sendWindowBytesRemainingLock
      Lock for the send window calculations.
    • _bwEstimator

      private final SimpleBandwidthEstimator _bwEstimator
      Estimator of the peer's bandwidth.
    • _receiveBps

      private int _receiveBps
      Smoothed receive rate, for display only.
    • _receiveBytes

      private int _receiveBytes
      Bytes received in the current period.
    • _receivePeriodBegin

      private long _receivePeriodBegin
      When the receive period began.
    • _lastCongestionOccurred

      private volatile long _lastCongestionOccurred
      When congestion last occurred.
    • _pathUnverifiedUntil

      private volatile long _pathUnverifiedUntil
      When the path-unverified send-window growth freeze expires; 0 = not frozen.
    • _slowStartThreshold

      private volatile int _slowStartThreshold
      When sendWindowBytes is below this, grow the window size quickly, but after we reach it, grow it slowly.
    • _remoteIP

      protected final byte[] _remoteIP
      What IP is the peer sending and receiving packets on?
    • _remoteIPAddress

      protected volatile InetAddress _remoteIPAddress
      Cached IP address.
    • _remotePort

      protected volatile int _remotePort
      What port is the peer sending and receiving packets on?
    • _remoteHostId

      protected volatile RemoteHostId _remoteHostId
      Cached RemoteHostId, used to find the peerState by remote info.
    • _weRelayToThemAs

      private long _weRelayToThemAs
      If we are serving as an introducer to them, this is the the tag that they can publish that, when presented to us, will cause us to send a relay introduction to the current peer.
    • _theyRelayToUsAs

      private long _theyRelayToUsAs
      If they have offered to serve as an introducer to us, this is the tag we can use to publish that fact.
    • _mtu

      protected volatile int _mtu
      What is the largest packet we can currently send to the peer?
    • _mtuReceive

      private int _mtuReceive
      The MTU for receiving from the peer.
    • _largeMTU

      private int _largeMTU
      What is the largest packet we will ever send to the peer?
    • _minMTU

      private final int _minMTU
      Smallest MTU allowed for this peer.
    • _consecutiveSmall

      private long _consecutiveSmall
      Consecutive small packets seen for MTU probing.
    • _mtuIncreases

      private int _mtuIncreases
      MTU increases counted for this peer.
    • _mtuDecreases

      private int _mtuDecreases
      MTU decreases counted for this peer.
    • _rtt

      protected volatile int _rtt
      Current round trip time estimate.
    • _rttDeviation

      private volatile int _rttDeviation
      Smoothed mean deviation in the RTT.
    • _rto

      private volatile int _rto
      Current retransmission timeout.
    • RETRANSMISSION_PERIOD_WIDTH

      static final long RETRANSMISSION_PERIOD_WIDTH
      How many packets will be considered within the retransmission rate calculation.
    • _messagesReceived

      private int _messagesReceived
      Messages received from the peer.
    • _messagesSent

      private final AtomicInteger _messagesSent
      Messages sent to the peer.
    • _lastRejectionLogTime

      private long _lastRejectionLogTime
      Last time we logged a send rejection (for rate-limited logging).
    • REJECTION_LOG_INTERVAL

      private static final long REJECTION_LOG_INTERVAL
      Interval between rejection log messages.
      See Also:
    • _packetsTransmitted

      private int _packetsTransmitted
      Packets transmitted to the peer.
    • _packetsRetransmitted

      private int _packetsRetransmitted
      How many packets were retransmitted within the last RETRANSMISSION_PERIOD_WIDTH packets.
    • _lastReportedLossBucket

      private int _lastReportedLossBucket
      Last 5% loss-ratio bucket reported to the profile, -1 = nothing reported yet. Lock: _outboundLock.
    • _lossyMinPackets

      private final int _lossyMinPackets
      Minimum transmitted packets before a loss ratio is reported, from ProfileOrganizer.PROP_LOSSY_MIN_PACKETS. Read once per peer rather than per volley: reportLossRatio() is called under _outboundLock, and a property lookup there falls through to System.getProperty every time. A peer reads it once at construction, which is off the hot path.
    • _nextSequenceNumber

      private long _nextSequenceNumber
      Next outbound message sequence number.
    • _fastRetransmit

      private final AtomicBoolean _fastRetransmit
      True while a fast retransmit is pending.
    • _packetsReceivedDuplicate

      protected volatile int _packetsReceivedDuplicate
      How many duplicate packets were received within the last RETRANSMISSION_PERIOD_WIDTH packets.
    • _packetsReceived

      private int _packetsReceived
      Packets received from the peer.
    • _mayDisconnect

      private volatile boolean _mayDisconnect
      True when the peer may be disconnected.
    • _inboundMessages

      protected final ConcurrentMap<Long, InboundMessageState> _inboundMessages
      List of InboundMessageState for active messages.
    • _outboundMessages

      private final CachedIteratorCollection<OutboundMessageState> _outboundMessages
      Mostly messages that have been transmitted and are awaiting acknowledgement, although there could be some that have not been sent yet.
    • _outboundQueue

      private final PriBlockingQueue<OutboundMessageState> _outboundQueue
      Priority queue of messages that have not yet been sent. They are taken from here and put in _outboundMessages.
    • _retransmitTimer

      private final AtomicLong _retransmitTimer
      When the retransmit timer is about to trigger.
    • _transport

      protected final UDPTransport _transport
      The UDP transport.
    • _dead

      protected volatile boolean _dead
      Have we migrated away from this peer to another newer one?
    • MIN_CONCURRENT_MSGS

      private static volatile int MIN_CONCURRENT_MSGS
      The minimum number of outstanding messages (NOT fragments/packets) — configurable.
    • MAX_MESSAGE_LIFETIME

      private static final long MAX_MESSAGE_LIFETIME
      Maximum lifetime before a message is considered stuck and expired (60 seconds).
      See Also:
    • MAX_INBOUND_MESSAGES

      static final int MAX_INBOUND_MESSAGES
      Hard cap on partially-received inbound messages held per peer. Each entry owns pooled fragment buffers of up to UDPPacket.MAX_PACKET_SIZE, and a peer that sends one fragment per distinct message ID never trips the same-ID expiry branch, so without a cap the map grows for the life of the connection.
      See Also:
    • BACKOFF_START_LIFETIME

      private static final long BACKOFF_START_LIFETIME
      After this time, we start adding backoff delay (5 seconds).
      See Also:
    • INIT_CONCURRENT_MSGS

      private static volatile int INIT_CONCURRENT_MSGS
      Initial concurrent messages per peer — configurable.
    • MAX_CONCURRENT_MSGS

      private static volatile int MAX_CONCURRENT_MSGS
      Hard cap on concurrent messages per peer — adjustable via Tuner.
    • TARGET_RTT

      private static volatile int TARGET_RTT
      Target RTT in ms — below this, increase concurrency; above this, decrease. I2P network RTT through 2-4 hops is typically 500-2000ms. High enough to avoid false congestion signals from normal network latency. Configurable via i2p.transport.udp.targetRTT.
    • RTT_DECREASE_FACTOR

      private static volatile int RTT_DECREASE_FACTOR
      RTT multiplier above which we multiplicative-decrease concurrency. Only decrease when RTT > TARGET_RTT * RTT_DECREASE_FACTOR — truly congested. Configurable via i2p.transport.udp.rttDecreaseFactor.
    • QUEUE_BACKPRESSURE_INCREASE

      private static final int QUEUE_BACKPRESSURE_INCREASE
      When RTT > TARGET_RTT but there are queued messages, increase modestly.
      See Also:
    • _concurrentMessagesAllowed

      private int _concurrentMessagesAllowed
      How many concurrent outbound messages do we allow OutboundMessageFragments to send. This counts full messages, NOT fragments (UDP packets). Dynamically adjusted based on measured RTT: increased when RTT < TARGET_RTT, decreased when RTT > TARGET_RTT * RTT_DECREASE_FACTOR.
    • _consecutiveRejections

      private int _consecutiveRejections
      How many concurrency rejections have we had in a row.
    • _isInbound

      protected final boolean _isInbound
      Is it inbound?
    • _lastIntroducerTime

      private long _lastIntroducerTime
      Last time it was made an introducer.
    • MAX_SEND_WINDOW_BYTES

      private static volatile int MAX_SEND_WINDOW_BYTES
      Max send window bytes — configurable via i2p.transport.udp.maxSendWindow.
    • MAX_SEND_WINDOW_CEILING

      static final int MAX_SEND_WINDOW_CEILING
      Heap-scaled CWIN ceiling: 1MB minimum, up to 16MB, roughly 1MB per 256MB of heap. Replaces the fixed 1MB cap that clamped tuner growth and kept high-memory routers below 1MB/s throughput (0.9.70+), and doubled from heap/512 to heap/256 in 0.9.71+ so a 4GB router can reach the streaming ceiling (~8 MB/s) instead of topping out at 2MB/s.
    • DEFAULT_MTU

      public static final int DEFAULT_MTU
      Default MTU.
      See Also:
    • MIN_MTU

      public static final int MIN_MTU
      IPv4 minimum MTU.

      Sized so a 1044 byte tunnel data message still fits in two packets: that needs 522 fragment bytes each, plus 46 for SSU, 20 for IP and 8 for UDP, giving 596. This leaves headroom above that floor (the smallest value meeting the floor and the alignment rule below would be 604) because the ACK allowance has to fit as well.

      The IPv4 IP and UDP headers are 28 bytes, so the SSU payload area is 620 - 28 = 592, which is 37 whole 16-byte blocks. PacketBuilder2.buildPacket(OutboundMessageState, int, PeerState2) requires that alignment for its padding.

      ACKs also have to fit, especially 1 + (4 * MAX_RESEND_ACKS_SMALL), so the max acks are reduced when the small MTU is in use. That is a best effort: a 2646 byte maximum-size message needs about 5 fragments at this MTU (2646 / (620 - 87)), which the small-MTU ACK allowance does not cover.

      See Also:
    • MIN_IPV6_MTU

      public static final int MIN_IPV6_MTU
      IPv6 minimum MTU. The IPv6 IP and UDP headers are 48 bytes, so 1280 - 48 = 1232, which is 77 whole 16-byte blocks.
      See Also:
    • MAX_IPV6_MTU

      public static final int MAX_IPV6_MTU
      IPv6 maximum MTU. 1488 - 48 = 1440, which is 90 whole 16-byte blocks, so it satisfies the same payload alignment as MIN_IPV6_MTU.
      See Also:
    • LARGE_MTU

      public static final int LARGE_MTU
      IPv4 maximum MTU.

      The size is set by two constraints.

      First, 1480 bytes are needed to carry a maximum-size I2NP message as two fragments: 2646 / 2 = 1323 data bytes each, plus 157 bytes of per-packet SSU and datagram overhead (74 + 46 + 1 + 4 * 9, the last term covering the fragment block header and four nine-byte ACK allowances).

      Second, the IPv4 IP and UDP headers are 28 bytes, so the SSU payload area must be a whole number of 16-byte blocks for PacketBuilder2.buildPacket(OutboundMessageState, int, PeerState2) to pad correctly. 1480 would leave 1452 bytes, which is not a multiple of 16; the next aligned size is 1484 - 28 = 1456 = 91 * 16. 1484 is therefore the smallest value that meets both constraints.

      Measurements put most small I2NP messages well below this; messages of 1900 to 4500 bytes do not fit any live network MTU anyway.

      See Also:
    • MAX_MTU

      public static final int MAX_MTU
      Max of IPv4 and IPv6 max MTUs.
    • MTU_STEP

      private static final int MTU_STEP
      Amount to adjust up or down in adjustMTU(int, boolean) - should be multiple of 16, at least for SSU 1.
      See Also:
    • MIN_RTO

      private static volatile int MIN_RTO
      Minimum retransmission timeout in milliseconds, configurable via "i2p.transport.udp.minRTO" and clamped to [100, 2000].
    • INIT_RTO

      private static volatile int INIT_RTO
      Initial RTO before first RTT sample — configurable via i2p.transport.udp.initRTO.
    • INIT_RTT

      private static final int INIT_RTT
      Initial round trip time estimate.
      See Also:
    • MAX_RTO

      private static volatile int MAX_RTO
      Maximum retransmission timeout — configurable via i2p.transport.udp.maxRTO.
    • POST_RTO_WINDOW_MTUS

      private static volatile int POST_RTO_WINDOW_MTUS
      Number of MTUs to restart the send window at after an RTO-timeout collapse. 1 = RFC 5681 loss window (one packet, the conservative default). Higher values speed slow-start recovery for bulk peers at the cost of more in-flight bytes immediately after loss. Tuned via Tuner.
    • CONGESTION_COOLDOWN_MIN_MS

      static final long CONGESTION_COOLDOWN_MIN_MS
      Floor on the gap between full congestion responses (ms). Congestion cooldown used to track _rto, which the death-spiral fix pulled from tens of seconds down to ~1s — allowing a window collapse every second under sustained loss. Real congestion still uses max(rto, this); migration never reaches this path.
      See Also:
    • PATH_UNVERIFIED_FREEZE_MS

      static final long PATH_UNVERIFIED_FREEZE_MS
      How long send-window growth stays frozen after a path-unverified migration signal (ms). Refreshed while the path remains unverified; cleared by pathVerified() when migration ends.
      See Also:
    • OUTBOUND_QUEUE_SIZE

      private static volatile int OUTBOUND_QUEUE_SIZE
      Outbound message queue depth per peer, -1 = use router config. Set by the Tuner when autotuning router.peerOutboundQueueSize.
    • ACK_FREQUENCY

      private static final AtomicInteger ACK_FREQUENCY
      How frequently do we want to send ACKs to a peer? (dynamically tuned).
    • FAST_RTX_ACKS

      private static final int FAST_RTX_ACKS
      If this many acks arrive out of order, fast rtx.
      See Also:
    • _outboundLock

      private final Object _outboundLock
      Lock for outbound operations.
    • _inboundLock

      protected final Object _inboundLock
      Lock for inbound operations.
    • _succeededBuffer

      private final List<OutboundMessageState> _succeededBuffer
      Reusable lists for finishAndAllocate() — avoids per-volley allocation churn.
    • _failedBuffer

      private final List<OutboundMessageState> _failedBuffer
      Messages that failed, buffered for retry.
    • _cachedOutboundCount

      private volatile int _cachedOutboundCount
      Cached count from the most recent finishAndAllocate() pass. Used by getNextVolley() to determine if a peer has messages.
    • _cachedOldestLifetime

      private volatile long _cachedOldestLifetime
      Cached oldest message lifetime from the most recent finishAndAllocate() pass. Updated during the finishAndAllocate() iteration across _outboundMessages.
    • RETRANSMIT_FAILSAFE_MS

      private static final long RETRANSMIT_FAILSAFE_MS
      Failsafe push of the retransmit timer when a retransmit pass selected nothing.
      See Also:
    • RTT_DAMPENING

      private static final float RTT_DAMPENING
      This is the value specified in RFC 2988.
      See Also:
    • MTU_RCV_DISPLAY_THRESHOLD

      private static final int MTU_RCV_DISPLAY_THRESHOLD
      Receive MTU change shown in the log.
      See Also:
    • OVERHEAD_SIZE

      private static final int OVERHEAD_SIZE
      IPv4 packet overhead in bytes (IP + UDP + MAC + IV, 60).
      See Also:
    • IPV6_OVERHEAD_SIZE

      private static final int IPV6_OVERHEAD_SIZE
      IPv6 packet overhead in bytes (IP + UDP + MAC + IV, 80).
      See Also:
    • MIN_EXPLICIT_ACKS

      private static final int MIN_EXPLICIT_ACKS
      Always leave room for this many explicit acks. Only for data packets. Does not affect ack-only packets. This directly affects data packet overhead, adjust with care.
      See Also:
    • MIN_ACK_SIZE

      private static final int MIN_ACK_SIZE
      This is room for three explicit acks or two partial acks or one of each = 13.
      See Also:
  • Constructor Details

    • PeerState

      protected PeerState(RouterContext ctx, UDPTransport transport, InetSocketAddress addr, Hash remotePeer, boolean isInbound, int rtt)
      For SSU2.
      Parameters:
      ctx - the router context, supplying the log manager and tunables
      transport - the UDP transport that owns this peer state and can drop the peer
      addr - the remote socket address; its IP bytes and port seed _remoteIP and _remotePort
      remotePeer - the peer's RouterIdentity hash
      isInbound - true when the peer dialed us, false when we dialed the peer
      rtt - the round trip time in ms, or 0 when unmeasured, leaving the initial RTO in place
  • Method Details

    • getMaxConcurrentMessages

      public static int getMaxConcurrentMessages()
      Max concurrent messages per peer.
      Returns:
      the current max concurrent messages per peer
    • setMaxConcurrentMessages

      public static void setMaxConcurrentMessages(int max)
      Max concurrent messages per peer (called by Tuner). Scales with available RAM: ~1/4 of RAM in MB, clamped 256-4096.
      Parameters:
      max - the max concurrent messages to set
    • getSentMessagesCleanTime

      public static long getSentMessagesCleanTime()
      Bridge to PeerState2.sentMessagesCleanTime for Tuner (different package).
      Returns:
      the sent messages clean time
    • setSentMessagesCleanTime

      public static void setSentMessagesCleanTime(long ms)
      Bridge to PeerState2.setSentMessagesCleanTime for Tuner (different package).
      Parameters:
      ms - the clean time in ms
    • getOutboundMsgExpiration

      public static long getOutboundMsgExpiration()
      Bridge to OutboundMessageState.getMessageExpiration for Tuner (different package).
      Returns:
      the outbound message expiration
    • setOutboundMsgExpiration

      public static void setOutboundMsgExpiration(long ms)
      Bridge to OutboundMessageState.setMessageExpiration for Tuner (different package).
      Parameters:
      ms - the expiration in ms
    • loadConfig

      public static void loadConfig(RouterContext ctx)
      Load configurable UDP transport parameters from router.config. Called once during UDPTransport initialization.
      Parameters:
      ctx - router context for property access
    • getAggregateStats

      public static long[] getAggregateStats(Collection<PeerState> peers)
      Compute aggregate transport stats across all peers for tuner visibility. Called periodically from OutboundMessageFragments.
      Parameters:
      peers - collection of active peer states
      Returns:
      array: [avgSendWindow, avgRTO, avgConcurrentMsgs, avgEffectiveRTO], or null if no peers. Index 1 is the raw per-peer estimate (the historical series, unchanged for existing readers); index 3 is the clamped [MIN_RTO, MAX_RTO] value each peer actually uses to schedule retransmits, so the two can be compared.
    • setOutboundQueueSize

      public static void setOutboundQueueSize(int size)
      Outbound message queue depth per peer (called by Tuner).
      Parameters:
      size - queue depth; the Tuner clamps to 50-1000 before calling
    • getOutboundQueueSize

      public static int getOutboundQueueSize(RouterContext ctx, int def)
      Outbound message queue depth per peer.
      Parameters:
      ctx - router context for config fallback when untuned
      def - fallback default when neither tuned nor configured
      Returns:
      the queue depth to use
    • getAckFrequency

      public static int getAckFrequency()
      Current ACK frequency.
      Returns:
      seconds between ACKs to a peer, dynamically tuned
    • setAckFrequency

      public static void setAckFrequency(int freq)
      ACK frequency.
      Parameters:
      freq - new ACK frequency (bounded 50-300)
    • setInitRTO

      public static void setInitRTO(int ms)
      Initial RTO for new peers (called by Tuner).
      Parameters:
      ms - initial RTO in ms, clamped 250-2000
    • setMinRTO

      public static void setMinRTO(int ms)
      Minimum RTO floor (called by Tuner). Floor is 100 so the Tuner's death-spiral cut is effective; recalculateTimeouts(long) still uses max(MIN_RTO, RTT-based estimate).
      Parameters:
      ms - minimum RTO in ms, clamped 100-2000
    • setMaxRTO

      public static void setMaxRTO(int ms)
      Maximum RTO ceiling (called by Tuner). Floor is 3000 so the Tuner's death-spiral cut is effective; default remains 60s for high-RTT paths until autotune tightens it.
      Parameters:
      ms - maximum RTO in ms, clamped 3000-120000
    • setMaxSendWindow

      public static void setMaxSendWindow(int bytes)
      Max send window / CWIN (called by Tuner).
      Parameters:
      bytes - max send window in bytes, clamped 32KB to heap-scaled ceiling
    • getPostRTOWindowMTUs

      public static int getPostRTOWindowMTUs()
      Post-RTO-collapse window restart size.
      Returns:
      the post-RTO-collapse window restart size, in MTUs
    • setPostRTOWindowMTUs

      public static void setPostRTOWindowMTUs(int mtus)
      Send-window restart size after an RTO-timeout collapse (called by Tuner).
      Parameters:
      mtus - number of MTUs, clamped 1-4 (1 = RFC 5681 loss window)
    • setInitConcurrentMsgs

      public static void setInitConcurrentMsgs(int msgs)
      Initial concurrent messages per peer (called by Tuner).
      Parameters:
      msgs - initial concurrent messages, clamped 16-256
    • setMinConcurrentMsgs

      public static void setMinConcurrentMsgs(int msgs)
      Minimum concurrent messages per peer (called by Tuner).
      Parameters:
      msgs - minimum concurrent messages, clamped 8-128
    • getInitRTO

      public static int getInitRTO()
      Initial RTO for new peers.
      Returns:
      the initial RTO for new peers in ms
    • getMinRTO

      public static int getMinRTO()
      Minimum RTO floor.
      Returns:
      the minimum RTO floor in ms
    • getMaxRTO

      public static int getMaxRTO()
      Maximum RTO ceiling.
      Returns:
      the maximum RTO ceiling in ms
    • getMaxSendWindow

      public static int getMaxSendWindow()
      Max send window (CWIN).
      Returns:
      the max send window (CWIN) in bytes
    • getMaxSendWindowCeiling

      public static int getMaxSendWindowCeiling()
      The heap-scaled CWIN ceiling, for use by the Tuner's MaxSendWindowParam (max range must match the clamp applied in setMaxSendWindow(int)).
      Returns:
      the CWIN ceiling in bytes
    • getInitConcurrentMsgs

      public static int getInitConcurrentMsgs()
      Concurrent messages a new peer starts with.
      Returns:
      the initial window, in messages
    • getMinConcurrentMsgs

      public static int getMinConcurrentMsgs()
      Concurrent messages a degraded peer is limited to.
      Returns:
      the minimum window, in messages
    • getClockSkewFudge

      public static int getClockSkewFudge()
      Clock skew fudge factor.
      Returns:
      clock skew fudge derived from current ACK frequency
    • classifyOutcome

      static PeerState.Outcome classifyOutcome(boolean complete, boolean expired, boolean overSent)
      Per-message outcome in a finishAndAllocate() scan, computed once per message so the scan loop stays a thin dispatcher. Precedence: COMPLETE > EXPIRED > OVER_SENT > SENDABLE - an expired message is reported as EXPIRED even when it also exceeded the volley cap, keeping the expire/aggressive stats distinct.
      Parameters:
      complete - the message finished (all fragments acked)
      expired - the message's expiry passed
      overSent - the message exceeded OutboundMessageFragments.MAX_VOLLEYS
      Returns:
      the dominated outcome
    • retransmitFireTime

      static long retransmitFireTime(boolean firstArming, boolean fastRetransmit, long now, long rto)
      Decide the next retransmit-timer fire time after a volley. A new timer is armed on first arming or while fast retransmit is active; otherwise the existing timer is left alone. Pure so the RTO policy is unit-testable.
      Parameters:
      firstArming - true if no retransmit timer is currently armed
      fastRetransmit - whether fast retransmit is active
      now - the current clock reading in milliseconds
      rto - the current smoothed retransmit timeout
      Returns:
      the fire time to arm, or -1L to leave the timer unchanged
    • shouldSkipFastRetransmit

      static boolean shouldSkipFastRetransmit(boolean fastRetransmit, int nacks)
      Whether to skip a message during a retransmit-mode scan. During fast retransmit, messages that have not yet accumulated FAST_RTX_ACKS NACKs are spared — they were not implicated in the loss and resending them would merely amplify congestion (RFC 5681 sec. 4.2). Pure so the scan loop gate is unit-testable.
      Parameters:
      fastRetransmit - whether fast retransmit is currently active
      nacks - the message's current NACK count
      Returns:
      true to leave the message alone during this pass
    • reachedRetransmitCap

      static boolean reachedRetransmitCap(int rvSize, int sizeBefore, boolean fastRetransmit)
      Whether a retransmit-mode scan has accumulated enough messages to stop. Caps each pass at half of the pre-cleanup active set unless fast retransmit is active (which deliberately floods the tail to trigger duplicate ACKs, RFC 5681 sec. 4.2). Pure so the scan cap is unit-testable.
      Parameters:
      rvSize - how many messages the current pass has selected
      sizeBefore - the active-message count before this pass
      fastRetransmit - whether fast retransmit is currently active
      Returns:
      true when the pass should stop selecting
    • isTotalFail

      static boolean isTotalFail(OutNetMessage msg, boolean isInbound, long seqNum)
      Whether a failed outbound message counts as a total-first-message failure. Only the first outbound message (sequence number 0) of an outbound connection can destroy the peer. Failures of messages sent to an inbound peer are never total. Pure so the destroy decision is unit-testable.
      Parameters:
      msg - the failed message wrapper, may be null
      isInbound - whether this PeerState is the inbound side
      seqNum - the message's sequence number
      Returns:
      true if this failure should destroy the peer
    • finishAndAllocate

      List<OutboundMessageState> finishAndAllocate(long now)
      Replaces the two-pass pattern of finishMessages() + allocateSend() with a single pass through _outboundMessages. Cleans up completed/expired messages and selects messages to send in one iteration.

      Sets _cachedOutboundCount for hasOutbound() and _cachedOldestLifetime for getNextDelay(). Does NOT scan _outboundQueue for oldest start time — the _outboundMessages iteration is sufficient for the delay heuristic, avoiding per-volley PriorityBlockingQueue iterator allocation.

      Parameters:
      now - the current clock reading in milliseconds, used to age messages out of the queue
      Returns:
      messages to send, or null if none ready
    • cappedRefund

      static int cappedRefund(int remaining, int refund, int windowBytes)
      Refund refund bytes into the send-window remaining budget, capped at the window size (never let the remaining budget exceed the congestion window, per RFC 5681). Pure so the refund bookkeeping is unit-testable.
      Parameters:
      remaining - the current _sendWindowBytesRemaining
      refund - the byte count to add back (failed sends, freed blocks)
      windowBytes - the current _sendWindowBytes
      Returns:
      the capped new remaining budget
    • handleFailed

      private boolean handleFailed(List<OutboundMessageState> failed, int failedSize, int failedCount, boolean totalFail, boolean shouldLogInfo, boolean shouldLogWarn)
      Process failed outbound messages and their side effects, completely outside _outboundLock. Window bytes for unacked fragments are refunded under _sendWindowBytesRemainingLock (capped at the full window). A total failure of the first outbound message destroys the peer with REASON_FRAME_TIMEOUT and drops it.

      Logging is suppressed for banlisted peers.

      Parameters:
      failed - the collected failed states, never empty
      failedSize - total unacked size bytes to refund
      failedCount - total unacked fragments to refund overhead for
      totalFail - true if the first (seq 0) outbound message failed
      shouldLogInfo - whether info logs are enabled
      shouldLogWarn - whether warn logs are enabled
      Returns:
      true if the peer was dropped (the caller must return null)
    • hasOutbound

      boolean hasOutbound()
      After a finishAndAllocate() pass, reports whether any outbound messages remain.
      Returns:
      true if there are pending outbound messages
    • getVersion

      public int getVersion()
      Peer SSU version.
      Returns:
      the version number (1 for SSU1)
    • changePort

      void changePort(int newPort)
      Change the remote port. Caller should sync; UDPTransport must remove and add to peersByRemoteHost map.
      Parameters:
      newPort - the new port number
    • getRemotePeer

      public Hash getRemotePeer()
      Remote peer hash. The peer are we talking to. Non-null.
      Returns:
      the remote peer hash
    • getKeyEstablishedTime

      public long getKeyEstablishedTime()
      When the cipher and MAC keys were established. When were the current cipher and MAC keys established/rekeyed? This is the connection uptime.
      Returns:
      the key establishment time
    • getClockSkew

      public long getClockSkew()
      Clock skew. How far off is the remote peer from our clock, in milliseconds? A positive number means our clock is ahead of theirs.
      Returns:
      the clock skew in ms
    • getLastSendTime

      public long getLastSendTime()
      Last send time. When did we last send them a packet? Updated for data, relay, and peer test, but not acks, pings, or termination.
      Returns:
      the last send time
    • getLastSendFullyTime

      public long getLastSendFullyTime()
      Last send fully time.
      Returns:
      the time in ms of the last send that did not need a retransmit
    • getLastReceiveTime

      public long getLastReceiveTime()
      Last receive time. When did we last receive a packet from them? Updated for data, relay, and peer test, but not acks, pings, or termination.
      Returns:
      the last receive time
    • getConsecutiveFailedSends

      public int getConsecutiveFailedSends()
      Consecutive failed sends count.
      Returns:
      how many sends to this peer have failed back to back, reset by the first send that succeeds
    • getSendWindowBytes

      public int getSendWindowBytes()
      Send window bytes. How many bytes should we send to the peer in a second. 1st stat in CWND column, otherwise unused, candidate for removal.
      Returns:
      the send window bytes
    • getSendWindowBytesRemaining

      public int getSendWindowBytesRemaining()
      Send window bytes remaining.
      Returns:
      the bytes still allowed in the current one-second send window
    • getRemoteIP

      public byte[] getRemoteIP()
      Remote IP address bytes.
      Returns:
      the raw address of the remote peer, 4 bytes for IPv4 and 16 for IPv6
    • getRemoteIPAddress

      public InetAddress getRemoteIPAddress()
      Cached remote IP address.
      Returns:
      may be null if IP is invalid
    • getRemotePort

      public int getRemotePort()
      Remote port.
      Returns:
      the UDP port number the remote peer is reached on
    • getWeRelayToThemAs

      public long getWeRelayToThemAs()
      Tag we relay to them as. If we are serving as an introducer to them, this is the the tag that they can publish that, when presented to us, will cause us to send a relay introduction to the current peer.
      Returns:
      0 (no relay) if unset previously
    • getTheyRelayToUsAs

      public long getTheyRelayToUsAs()
      Tag they relay to us as. If they have offered to serve as an introducer to us, this is the tag we can use to publish that fact.
      Returns:
      0 (no relay) if unset previously
    • getMTU

      public int getMTU()
      Maximum transmission unit.
      Returns:
      the largest packet we will send to this peer, in bytes
    • getReceiveMTU

      public int getReceiveMTU()
      Receive MTU estimate. Estimate how large the other side's MTU is. This could be wrong. It is used only for the HTML status.
      Returns:
      the receive MTU
    • adjustClockSkew

      void adjustClockSkew(long skew)
      Update the moving-average clock skew based on the current difference. The raw skew will be adjusted for RTT/2 here. A positive number means our clock is ahead of theirs.
      Parameters:
      skew - milliseconds, NOT adjusted for RTT.
    • setLastSendTime

      void setLastSendTime(long when)
      Last send time. When did we last send them a packet? Updated for data, relay, and peer test, but not acks, pings, or termination.
      Parameters:
      when - the time to set
    • setLastReceiveTime

      void setLastReceiveTime(long when)
      Last receive time. When did we last receive a packet from them? Updated for data, relay, and peer test, but not acks, pings, or termination.
      Parameters:
      when - the time to set
    • setLastPingTime

      void setLastPingTime(long when)
      Last ping time. Note ping sent. Does not update last send time.
      Parameters:
      when - the time to set
    • getLastSendOrPingTime

      long getLastSendOrPingTime()
      Latest of last sent, last ACK, last ping.
      Returns:
      the latest time
    • getSendBps

      public int getSendBps(long now)
      The Westwood+ bandwidth estimate.
      Parameters:
      now - the current time
      Returns:
      the smoothed send transfer rate
    • getReceiveBps

      public int getReceiveBps(long now)
      Receive Bps estimate. An approximation, for display only.
      Parameters:
      now - the current time
      Returns:
      the smoothed receive transfer rate
    • incrementConsecutiveFailedSends

      int incrementConsecutiveFailedSends()
      Increment consecutive failed sends.
      Returns:
      the consecutive failed send count after this increment
    • getInactivityTime

      public long getInactivityTime()
      Time since the peer was last heard from or sent to fully.
      Returns:
      the time, in ms
    • allocateSendingBytes

      private boolean allocateSendingBytes(OutboundMessageState state, long now)
      Decrement the remaining bytes in the current period's window, returning true if the full size can be decremented, false if it cannot. If it is not decremented, the window size remaining is not adjusted at all.

      Caller should synch.

      Parameters:
      state - the message to allocate send-window space for
      now - current time in ms, recorded as the last send time when the allocation succeeds
      Returns:
      true if the message's bytes were deducted from the send window, false if the concurrency limit or the remaining window blocked it
    • setWeRelayToThemAs

      void setWeRelayToThemAs(long tag)
      If we are serving as an introducer to them, this is the the tag that they can publish that, when presented to us, will cause us to send a relay introduction to the current peer.
      Parameters:
      tag - 1 to Integer.MAX_VALUE, or 0 if relaying disabled
    • setTheyRelayToUsAs

      void setTheyRelayToUsAs(long tag)
      If they have offered to serve as an introducer to us, this is the tag we can use to publish that fact.
      Parameters:
      tag - 1 to Integer.MAX_VALUE, or 0 if relaying disabled
    • getSlowStartThreshold

      public int getSlowStartThreshold()
      Slow start threshold. Stat in SST column, otherwise unused - candidate for removal.
      Returns:
      the slow start threshold
    • getConcurrentSends

      public int getConcurrentSends()
      Concurrent sends count. 2nd stat in CWND column, otherwise unused - candidate for removal.
      Returns:
      the concurrent sends count
    • getConcurrentSendWindow

      public int getConcurrentSendWindow()
      Concurrent send window. 3rd stat in CWND column, otherwise unused, candidate for removal.
      Returns:
      the concurrent send window
    • getConsecutiveSendRejections

      public int getConsecutiveSendRejections()
      Consecutive send rejections count. 4th stat in CWND column, otherwise unused - candidate for removal.
      Returns:
      the consecutive send rejections count
    • isInbound

      public boolean isInbound()
      Whether this is an inbound connection.
      Returns:
      true if we accepted this connection rather than dialling out
    • isIPv6

      public boolean isIPv6()
      Whether the connection uses IPv6.
      Returns:
      whether the peer is using IPv6
    • getIntroducerTime

      long getIntroducerTime()
      Last introducer time.
      Returns:
      the last time we used them as an introducer, or 0
    • setIntroducerTime

      void setIntroducerTime()
      Record the last time we used them as an introducer.
    • messageFullyReceived

      void messageFullyReceived(Long messageId, int bytes)
      We received the message specified completely.
      Parameters:
      messageId - the message ID
      bytes - if less than or equal to zero, message is a duplicate.
    • messagePartiallyReceived

      void messagePartiallyReceived()
      We received a partial message, or we want to send some acks.
    • messagePartiallyReceived

      protected void messagePartiallyReceived(long now)
      We received a partial message, or we want to send some acks.
      Parameters:
      now - the current time
    • getInboundMessages

      Map<Long, InboundMessageState> getInboundMessages()
      Fetch the internal id (Long) to InboundMessageState for incomplete inbound messages. Access to this map must be synchronized explicitly!
      Returns:
      a map of message IDs to inbound message states
    • expireInboundMessages

      int expireInboundMessages()
      Expire partially received inbound messages, returning how many are still pending. This should probably be fired periodically, in case a peer goes silent and we don't try to send them any messages (and don't receive any messages from them either).
      Returns:
      the number of partially received inbound messages still pending
    • evictInboundMessage

      static InboundMessageState evictInboundMessage(ConcurrentMap<Long, InboundMessageState> inbound)
      Make room for one more partially-received inbound message. Expired and complete entries go first, since they are dead weight that simply has not been swept yet; only when none are left do we drop the live entry that has been waiting longest, which under a fragment flood is the one least likely ever to complete.

      The caller must hold _inboundLock.

      Parameters:
      inbound - the per-peer map of partial inbound messages
      Returns:
      the evicted state, already released, or null if the map was empty
    • congestionOccurred

      private void congestionOccurred()
      Either they told us to back off, or we had to resend to get the data through. Caller should synch on this.
    • nextCongestionRTO

      static int nextCongestionRTO(int currentRTO, int rtt, int rttDeviation, int minRTO, int maxRTO)
      Compute the RTO to apply after a congestion signal.

      Congestion must not inflate RTO. RFC 6298 §5.5 doubling applies to retransmit-timer expiry, not every retransmit volley (which includes fast retransmit). Doubling here under sustained loss drove avgRTO to 33s while RTT stayed ~96ms — a death spiral that stalled each retransmit for half a minute and collapsed CWIN. With a known RTT, cap RTO at 4× the RFC 2988 estimate so historical inflation cannot outlive fresh latency samples; without an RTT sample, leave the current value unchanged (the RTT path in recalculateTimeouts() remains the sole authority for growth).

      Parameters:
      currentRTO - current RTO in ms
      rtt - smoothed RTT in ms, or <= 0 if unknown
      rttDeviation - RTT deviation in ms
      minRTO - floor in ms
      maxRTO - ceiling in ms
      Returns:
      the RTO to store, clamped to [minRTO, maxRTO]
    • congestionCooldownElapsed

      static boolean congestionCooldownElapsed(long last, long now, int rto)
      Whether enough time has elapsed since the last congestion response to allow another one. Pure so the cooldown policy is unit-testable.

      The cooldown is max(rto, CONGESTION_COOLDOWN_MIN_MS) so a low RTO cannot shrink the gap to ~1s and collapse the window every second under sustained loss.

      Parameters:
      last - congestion timestamp in ms, or 0 if never
      now - current time in ms
      rto - current RTO in ms
      Returns:
      true if a new congestion response may proceed
    • pathUnverifiedBlocksGrowth

      static boolean pathUnverifiedBlocksGrowth(long now, long pathUnverifiedUntil)
      Whether send-window growth must be held because the path is unverified (SSU2 connection migration). Pure so the freeze gate is unit-testable.
      Parameters:
      now - current time in ms
      pathUnverifiedUntil - freeze expiry in ms, or 0 if not frozen
      Returns:
      true if window growth must not proceed
    • nextConcurrentLimit

      static int nextConcurrentLimit(int numSends, int rtt, int current, int queued, int randomInt)
      Compute the next concurrent-messages limit after an ACK, pure so the AIMD tuning policy is unit-testable. Latency-based: additive increase while RTT is healthy (backlog-aware, ramping faster far from the cap), a soft *3/4 multiplicative decrease when RTT is well above target, a modest bump when the RTT hysteresis zone still has queued messages, and a hold otherwise. Retransmits (numSends >= 2) get a gentle /8 decrease to avoid grinding to the floor.
      Parameters:
      numSends - how many times the message was sent before the ACK
      rtt - the current smoothed RTT estimate (ms), or <= 0 if unknown
      current - the current _concurrentMessagesAllowed
      queued - how many messages are currently in _outboundQueue
      randomInt - a uniform draw in [0, INIT_CONCURRENT_MSGS); only consumed when rtt <= 0, pass 0 otherwise
      Returns:
      the new concurrent-message limit
    • shouldGrowSendWindow

      static boolean shouldGrowSendWindow(int sendWindow, int slowStartThreshold, int bytesACKed, float randomFloat)
      Whether an ACK should grow the send window. Classic slow-start / congestion-avoidance split (RFC 5681): grow unconditionally while at or below the slow-start threshold, otherwise grow probabilistically with probability bytesACKed / (2 * sendWindow). Pure so the growth gate is unit-testable.
      Parameters:
      sendWindow - the current _sendWindowBytes
      slowStartThreshold - the current _slowStartThreshold
      bytesACKed - the byte count newly ACKed
      randomFloat - a uniform draw in [0, 1)
      Returns:
      true if the window should grow by bytesACKed
    • locked_messageACKed

      private void locked_messageACKed(int bytesACKed, int maxPktSz, long lifetime, int numSends, boolean anyPending, boolean anyQueued)
      We sent a message which was ACKed containing the given # of bytes. Caller should synch on this.
      Parameters:
      bytesACKed - bytes newly confirmed by the ACK, added to the send window
      maxPktSz - full packet size of the ACKed message's first fragment, including the block header and IP/UDP overhead
      lifetime - ms from the first send to this ACK, the RTT sample
      numSends - how many times the message was sent; below 2 the RTT, MTU and congestion-window updates run
      anyPending - true if other sent messages are still unACKed; false clears the retransmit timer and exits fast retransmit
      anyQueued - true if the outbound queue still holds messages, used to decide whether to nudge the message fragments job
    • messageACKed

      private void messageACKed(int bytesACKed, int maxPktSz, long lifetime, int numSends, boolean anyPending, boolean anyQueued)
      We sent a message which was ACKed containing the given # of bytes. Takes the send-window lock and delegates to locked_messageACKed(int, int, long, int, boolean, boolean).
      Parameters:
      bytesACKed - bytes newly confirmed by the ACK
      maxPktSz - full packet size of the ACKed message's first fragment
      lifetime - ms from the first send to this ACK, the RTT sample
      numSends - how many times the message was sent
      anyPending - true if other sent messages are still unACKed
      anyQueued - true if the outbound queue still holds messages
    • recalculateTimeouts

      private void recalculateTimeouts(long lifetime)
      Adjust the tcp-esque timeouts. Caller should synch on this.
      Parameters:
      lifetime - network RTT — time from first send to ACK (excludes queue time)
    • wantLargerMTU

      static boolean wantLargerMTU(boolean success, int packetsTransmitted, int packetsRetransmitted)
      Whether a near-lossless transmission history warrants probing a larger MTU. Requires a successful send on a link with an observed retransmit ratio under 10%. Pure so the MTU tuning policy is unit-testable.
      Parameters:
      success - whether the triggering send completed without retransmit
      packetsTransmitted - the value of _packetsTransmitted
      packetsRetransmitted - the value of _packetsRetransmitted
      Returns:
      true if the MTU should be considered for an increase
    • mtuIncreaseEligible

      static boolean mtuIncreaseEligible(int mtu, int largeMTU, int maxPktSz, int mtuDecreases, int randomInt)
      Whether a larger MTU is eligible after a clean transmission. Requires the probe packet to have credibly hit the current MTU ceiling, and, after any prior decrease, a probabilistic gate (increasingly likely to allow the probe the longer the link has stayed healthy). Pure so the eligibility policy is unit-testable without the router RNG.
      Parameters:
      mtu - the value of _mtu
      largeMTU - the value of _largeMTU
      maxPktSz - the size of the ACKed maximum-size packet
      mtuDecreases - the value of _mtuDecreases
      randomInt - the uniform draw in [0, mtuDecreases), consumed only when mtuDecreases > 1; pass 0 otherwise
      Returns:
      true if the MTU may be increased
    • mtuDecreaseEligible

      static boolean mtuDecreaseEligible(int mtu, int minMTU, int maxPktSz)
      Whether the MTU should be reduced after a lossy transmission. Requires a packet that credibly hit the current ceiling. Pure so the eligibility policy is unit-testable.
      Parameters:
      mtu - the value of _mtu
      minMTU - the value of _minMTU
      maxPktSz - the size of the retransmitted maximum-size packet
      Returns:
      true if the MTU may be decreased
    • adjustMTU

      private void adjustMTU(int maxPktSz, boolean success)
      Adjust upward if a large packet was successfully sent without retransmission. Adjust downward if a packet was retransmitted.

      Caller should synch on this.

      Parameters:
      maxPktSz - the largest packet that was sent
      success - was it sent successfully?
    • setHisMTU

      void setHisMTU(int mtu)
      Remote peer's MTU.
      Parameters:
      mtu - the MTU to set
    • messageRetransmitted

      void messageRetransmitted(int packets, int maxPktSz)
      Handle a message retransmission.
      Parameters:
      packets - the number of packets retransmitted
      maxPktSz - the maximum packet size
    • packetsTransmitted

      void packetsTransmitted(int packets)
      Record that packets were transmitted.
      Parameters:
      packets - the number of packets just handed to the transport, not bytes
    • reportLossRatio

      private void reportLossRatio()
      Report the current retransmit ratio to the profile when it crosses a 5% bucket boundary since the last report. Bucketing keeps profile writes to at most one per bucket change per connection.

      No report until the connection has transmitted at least ProfileOrganizer.PROP_LOSSY_MIN_PACKETS packets, so the ratio is only ever based on a meaningful sample. The bucket is not advanced in that case, so the first bucket change after the minimum is reached still fires.

      Caller must hold _outboundLock.

    • getRTT

      public int getRTT()
      Round trip time.
      Returns:
      the RTT in ms
    • getRTO

      public int getRTO()
      Retransmission timeout.

      Clamped to the current [MIN_RTO, MAX_RTO] so a peer that inflated before the Tuner cut the ceiling is not stuck on a stale high RTO.

      Returns:
      the RTO in ms
    • effectiveRTO

      public static int effectiveRTO(int rto, int minRto, int maxRto)
      Clamp a raw RTO estimate into the active [minRto, maxRto] window.

      Extracted from getRTO() so telemetry can report the value a packet actually waits under — raw estimates can sit outside the window (set at INIT_RTO, then re-clamped only on the next RTT sample) and would otherwise make the effective-vs-raw comparison untestable.

      Parameters:
      rto - the raw retransmission timeout estimate
      minRto - lower bound in ms
      maxRto - upper bound in ms; if below minRto it is ignored
      Returns:
      the effective RTO in ms, within [minRto, maxRto]
    • getRTTDeviation

      public int getRTTDeviation()
      RTT deviation.
      Returns:
      the RTT deviation in ms
    • getMessagesSent

      public int getMessagesSent()
      I2NP messages sent - does not include duplicates. As of 0.9.24, incremented when bandwidth is allocated just before sending, not when acked.
      Returns:
      the messages sent count
    • getMessagesReceived

      public int getMessagesReceived()
      I2NP messages received. As of 0.9.24, does not include duplicates.
      Returns:
      the messages received count
    • getPacketsTransmitted

      public int getPacketsTransmitted()
      Packets transmitted count.
      Returns:
      how many packets have been handed to the transport for this peer
    • getPacketsRetransmitted

      public int getPacketsRetransmitted()
      Packets retransmitted count.
      Returns:
      how many packets had to be sent again after loss or congestion
    • getPacketsReceived

      public int getPacketsReceived()
      Packets received count.
      Returns:
      how many packets have arrived from this peer
    • getPacketsReceivedDuplicate

      public int getPacketsReceivedDuplicate()
      Packets received duplicate count.
      Returns:
      how many packets from this peer repeated data we had already stored
    • packetReceived

      void packetReceived(int size)
      Record a received packet.
      Parameters:
      size - not including IP header, UDP header, MAC or IV
    • pathUnverified

      void pathUnverified()
      Hold send-window growth while the path is unverified (SSU2 connection migration, limitSending). Freezes growth only for a short window; does not collapse CWIN or adjust RTO. Migration is a path change, not congestion, and a full collapse thrashes multi-homed peers. Growth resumes via pathVerified() or when the freeze expires.
    • pathVerified

      void pathVerified()
      Clear the path-unverified growth freeze (migration completed, failed, or cancelled — the current path is again the verified one).
    • dataReceived

      void dataReceived()
      Same as setLastReceivedTime(now).
    • getLastACKSend

      public long getLastACKSend()
      When we last sent an ACK.
      Returns:
      the last ACK send time
    • clearWantedACKSendSince

      void clearWantedACKSendSince()
      All acks have been sent - SSU 1 only, see override.
    • getRemoteHostId

      public RemoteHostId getRemoteHostId()
      Remote host ID.
      Returns:
      non-null
    • add

      void add(OutboundMessageState state)
      Add an outbound message state to the queue.
      Parameters:
      state - the outbound message state to add
    • dropOutbound

      void dropOutbound()
      Drop all outbound messages.
    • getOutboundMessageCount

      public int getOutboundMessageCount()
      Outbound message count.
      Returns:
      number of active outbound messages remaining (unsynchronized)
    • setMayDisconnect

      public void setMayDisconnect()
      May disconnect to true.
    • getMayDisconnect

      public boolean getMayDisconnect()
      Whether we may disconnect.
      Returns:
      true if we may disconnect
    • getNextDelay

      int getNextDelay(long now)
      Uses cached oldest lifetime from the most recent finishAndAllocate() pass.
      Parameters:
      now - what time it is now
      Returns:
      how long to wait before sending, or Integer.MAX_VALUE if we have nothing to send. If ready now, will return 0.
    • isBacklogged

      public boolean isBacklogged()
      Whether the peer is dead or its outbound queue is backlogged.
      Returns:
      true if the peer is dead or its outbound queue is full
    • fragmentSize

      int fragmentSize()
      How much payload data can we shove in there?
      Returns:
      MTU - 87, i.e. 533 or 1397 (IPv4), MTU - 107 (IPv6)
    • fragmentOverhead

      int fragmentOverhead()
      Packet overhead plus room for acks.
      Returns:
      87 (IPv4), 107 (IPv6)
    • locked_shouldSend

      private boolean locked_shouldSend(OutboundMessageState state, long now)
      Locks this.
      Parameters:
      state - the message to allocate send-window space for
      now - current time in ms, used to throttle the rejection log
      Returns:
      true if send-window space was allocated for the message, false if it was rejected and counted in udp.sendRejected
    • newlyAckedBytes

      static int newlyAckedBytes(int unackedBefore, boolean complete, int unackedAfter)
      Compute the bytes newly confirmed by one incoming ACK for a single message: the full previously-unacked size when the message just became complete, otherwise only the delta newly covered by this ACK. Pure so the partial-ACK byte accounting is unit-testable.
      Parameters:
      unackedBefore - the message's unacked byte count before this ACK
      complete - whether this ACK completed the message
      unackedAfter - the message's unacked byte count after this ACK
      Returns:
      the byte count to credit toward the send window
    • acked

      protected boolean acked(PacketBuilder2.Fragment f)
      An ACK of a fragment was received.

      SSU 2 only.

      Parameters:
      f - the SSU2 fragment whose acknowledgement has arrived
      Returns:
      true if this fragment of the message was acked for the first time
    • fastRtxMode

      static PeerState.FastRtxMode fastRtxMode(int nacks)
      Fast-retransmit progression as a function of the NACK count for a single message. Threshold FAST_RTX_ACKS: the first exactly-threshold NACK starts fast retransmit (recovery begins, SST/cwnd set per RFC 5681 sec. 3.2 #2/#3); subsequent NACKs continue it (cwnd inflate per #4). Below threshold there is no action. Pure so the recovery cascade is unit-testable without router state.
      Parameters:
      nacks - the incremented NACK count for the message
      Returns:
      NONE, START, or CONTINUE
    • highestSeqNumAcked

      boolean highestSeqNumAcked(long highest)
      Enter or leave fast retransmit mode, and adjust SST and window variables accordingly. See RFC 5681 sec. 2.4.
      Parameters:
      highest - the highest sequence number that was acked
      Returns:
      true if we have something to fast-retransmit
    • exitFastRetransmit

      private void exitFastRetransmit()
      Leave fast retransmit mode if we were in it, and adjust SST and window variables accordingly. See RFC 5681 sec. 2.4.
    • shouldRequestImmediateAck

      protected boolean shouldRequestImmediateAck()
      SSU 2 only.
      Returns:
      whether request immediate ack
    • loadFrom

      void loadFrom(PeerState oldPeer)
      Transfer the basic activity/state from the old peer to the current peer

      SSU 1 or 2.

      Parameters:
      oldPeer - non-null
    • getTransport

      UDPTransport getTransport()
      Convenience for OutboundMessageState so it can fail itself.
      Returns:
      the UDPTransport this peer state belongs to
    • toShortString

      String toShortString()
      Compact one-line peer identifier for log output: short hash, direction, version and remote host id. No stats, no newlines.
      Returns:
      the short hash, direction, version and host id, on one line
    • toString

      public String toString()
      Overrides:
      toString in class Object