java.lang.Object
net.i2p.client.streaming.impl.ConnectionPacketHandler

class ConnectionPacketHandlerextends Object
Receive a packet for a particular connection - placing the data onto the queue, marking packets as acked, updating various fields, etc.

I2PSession -> MessageHandler -> PacketHandler -> ConnectionPacketHandler -> MessageInputStream

One of these is instantiated per-Destination (i.e. per-ConnectionManager, not per-Connection). It doesn't store any state.

  • Field Summary

    Fields
    Modifier and Type
    Field
    Description
    private final ByteCache
    Byte cache for packet buffers.
    private final I2PAppContext
    Application context.
    private final Log
    Class logger.
    private int
    Messages received with a payload size already seen in this connection
    private int
    Sample counters for the per-packet size stats (one per call site).
    (package private) static final String
    Immediate ACK delay in ms, applied as min(this, rtt/8) so it can only ever delay an immediate ACK by a fraction of the measured RTT.
    private static final long[]
    Period for rates.
    private static final int
    Record every Nth receive-size stat sample.
  • Constructor Summary

    Constructors
    Constructor
    Description
    Create a new ConnectionPacketHandler.
  • Method Summary

    Modifier and Type
    Method
    Description
    private boolean
    ack(Connection con, long ackThrough, long[] nacks, Packet packet, boolean isNew, boolean choke)
    Process the acks in a received packet, and adjust our window and RTT.
    private boolean
    adjustWindow(Connection con, boolean isNew, long sequenceNum, int numResends, int acked, boolean choke)
    Adjust the congestion window based on ACKs received.
    (package private) static long
    caGrowthCredit(long accum, int effAcked, int caFactor, int windowSize)
    Credit increment for the deterministic congestion-avoidance ratchet.
    (package private) static int
    caWindowIncrements(long accum)
    Whole-packet increments harvested from the fixed-point accumulator.
    (package private) static long
    caWindowRemainder(long accum)
    Fractional remainder after harvesting whole increments; carries over into the next ACK event.
    static int
    Maximum slow start window size.
    (package private) void
    Takes ownership of the packet and calls packet.releasePayload() unless it is passed to the MessageInputStream.
    (package private) static void
    Register the live stream RTT and send-window stats.
    (package private) static boolean
    shouldRemainChoked(Connection con, long seqNum, int payloadSize)
    Determine if a packet should keep the connection choked.
    (package private) static boolean
    shouldSampleLiveStreamStats(int receiveMsgCount)
    Whether this received message is the one that samples the receive-side size stat and, from it, the live stream RTT and send window.
    private boolean
    Make sure this packet is ok and that we can continue processing its data.
    private void
    Make sure this RST packet is valid, and if it is, act on it.
    private void
    Verify the signature if necessary.

    Methods inherited from class Object

    clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • _context

      private final I2PAppContext _context
      Application context.
    • _log

      private final Log _log
      Class logger.
    • _cache

      private final ByteCache _cache
      Byte cache for packet buffers.
    • TELEMETRY_SAMPLE_PERIOD

      private static final int TELEMETRY_SAMPLE_PERIOD
      Record every Nth receive-size stat sample. Per-packet RateStat updates lock each period's Rate; these size stats are display-only telemetry, so sampling the aggregate (scaling the recorded value by the period) preserves the graph with a fraction of the monitor traffic.
      See Also:
    • _receiveMsgSizeCnt

      private int _receiveMsgSizeCnt
      Sample counters for the per-packet size stats (one per call site).
    • _receiveDupMsgSizeCnt

      private int _receiveDupMsgSizeCnt
      Messages received with a payload size already seen in this connection
    • PROP_IMMEDIATE_ACK_DELAY

      static final String PROP_IMMEDIATE_ACK_DELAY
      Immediate ACK delay in ms, applied as min(this, rtt/8) so it can only ever delay an immediate ACK by a fraction of the measured RTT.
      See Also:
    • RATES

      private static final long[] RATES
      Period for rates.
  • Constructor Details

    • ConnectionPacketHandler

      public ConnectionPacketHandler(I2PAppContext context)
      Create a new ConnectionPacketHandler.
      Parameters:
      context - the I2P application context
  • Method Details

    • registerLiveStreamStats

      static void registerLiveStreamStats(StatManager sm)
      Register the live stream RTT and send-window stats.

      Separated from the constructor so a test can register against a fresh StatManager without building a whole handler — the same shape as ConnectionManager.registerRtxRatioStats(StatManager).

      Both are createRequiredRateStat because StatManager silently discards data for a name it was never told about. That failure mode is invisible from the console: the stat reads "not present" rather than wrong, which is how transport.banlistOnUsupportedSigType sat at zero through every signature-type banlisting.

      Parameters:
      sm - stat manager to register with, non-null
    • shouldSampleLiveStreamStats

      static boolean shouldSampleLiveStreamStats(int receiveMsgCount)
      Whether this received message is the one that samples the receive-side size stat and, from it, the live stream RTT and send window.

      One predicate for all three, because the live RTT and window are deliberately written inside the same block as the existing size sample: the cost stays two extra stat writes per sampled message rather than two per packet. Sharing the predicate is what stops the cadences drifting apart later — the mask alone would let a change to one silently leave the other per-packet.

      Pure predicate — no state, no router, safe for unit tests.

      Parameters:
      receiveMsgCount - monotonically increasing count of messages this handler has accepted, 1-based
      Returns:
      true when this message is a sampling point
    • getMaxSlowStartWindow

      public static int getMaxSlowStartWindow(I2PAppContext ctx)
      Maximum slow start window size. Tunable via i2p.streaming.maxSlowStartWindow (default: 32).
      Parameters:
      ctx - the I2P application context, unused by this static lookup
      Returns:
      the max slow start window
    • receivePacket

      void receivePacket(Packet packet, Connection con) throws I2PException
      Takes ownership of the packet and calls packet.releasePayload() unless it is passed to the MessageInputStream.
      Parameters:
      packet - the received packet
      con - the connection the packet belongs to
      Throws:
      I2PException - if the packet fails verification
    • ack

      private boolean ack(Connection con, long ackThrough, long[] nacks, Packet packet, boolean isNew, boolean choke)
      Process the acks in a received packet, and adjust our window and RTT.
      Parameters:
      con - the connection whose window and RTT are adjusted; may be null
      ackThrough - the highest ACKed sequence number
      nacks - the NACKed sequence numbers, may be null
      packet - the received packet
      isNew - was it a new packet? false for ack-only
      choke - did we get a choke in the packet?
      Returns:
      true if congested
    • adjustWindow

      private boolean adjustWindow(Connection con, boolean isNew, long sequenceNum, int numResends, int acked, boolean choke)
      Adjust the congestion window based on ACKs received. This either does nothing or increases the window; it never decreases it. Decreasing is done in Connection.ResendPacketEvent.retransmit().
      Parameters:
      con - the connection whose window is adjusted
      isNew - was it a new packet? false for ack-only
      sequenceNum - 0 for ack-only
      numResends - number of resent packets in this ACK
      acked - number of packets ACKed
      choke - did we get a choke in the packet?
      Returns:
      true if congested
    • caGrowthCredit

      static long caGrowthCredit(long accum, int effAcked, int caFactor, int windowSize)
      Credit increment for the deterministic congestion-avoidance ratchet. Accumulated in 16.16 fixed-point; each whole unit corresponds to one packet-in-flight increment on the congestion window.

      The expected value equals effAcked / (caFactor * windowSize), which is the probability that the old random gate would have incremented.

      Parameters:
      accum - the 16.16 fixed-point accumulator so far
      effAcked - effective number of packets ACKed this round
      caFactor - congestion-avoidance growth divisor
      windowSize - current congestion window
      Returns:
      the accumulator including this round's credit
    • caWindowIncrements

      static int caWindowIncrements(long accum)
      Whole-packet increments harvested from the fixed-point accumulator.
      Parameters:
      accum - the fixed-point credit accumulated so far
      Returns:
      number of whole window increments
    • caWindowRemainder

      static long caWindowRemainder(long accum)
      Fractional remainder after harvesting whole increments; carries over into the next ACK event.
      Parameters:
      accum - the fixed-point credit accumulated so far
      Returns:
      fractional remainder in [0, 1048575]
    • verifyPacket

      private boolean verifyPacket(Packet packet, Connection con) throws I2PException
      Make sure this packet is ok and that we can continue processing its data.

      SIDE EFFECT: Sets the SendStreamId and RemotePeer for the con, using the packet's ReceiveStreamId and OptionalFrom, If this is a SYN packet and the con's SendStreamId is not set.

      Parameters:
      packet - the incoming packet to verify
      con - the connection the packet is being processed on
      Returns:
      true if the packet is ok for this connection, false if we shouldn't continue processing.
      Throws:
      I2PException - if the packet is from the wrong destination, or a required signature is missing or forged
    • verifyReset

      private void verifyReset(Packet packet, Connection con)
      Make sure this RST packet is valid, and if it is, act on it. The destination is verified against the connection's own remote peer, so a reset arriving on an established stream is checked against the peer we actually negotiated with, not against a FROM field in the packet.
      Parameters:
      packet - the RST packet to validate and act on
      con - non-null
    • verifySignature

      private void verifySignature(Packet packet, Connection con) throws I2PException
      Verify the signature if necessary.
      Parameters:
      packet - the packet whose signature is checked
      con - the connection the packet arrived on; supplies the remote peer and key
      Throws:
      I2PException - if the signature was necessary and it was invalid
    • shouldRemainChoked

      static boolean shouldRemainChoked(Connection con, long seqNum, int payloadSize)
      Determine if a packet should keep the connection choked. Used for testing the unchoking decision logic.
      Parameters:
      con - the connection whose choked state is being decided
      seqNum - the packet sequence number
      payloadSize - the packet payload size
      Returns:
      true if the connection should remain choked