java.lang.Object
net.i2p.router.transport.udp.OutboundMessageState
All Implemented Interfaces:
CDPQEntry, CDQEntry, PQEntry

class OutboundMessageStateextends Object implements CDPQEntry
Maintain the outbound fragmentation for resending, for a single message.

All methods are thread-safe.

  • Field Details

    • _context

      private final I2PAppContext _context
      The app context.
    • _log

      private final Log _log
      Logger for the outbound message state.
    • _message

      private final OutNetMessage _message
      May be null if we are part of the establishment.
    • _i2npMessage

      private final I2NPMessage _i2npMessage
      The message being tracked.
    • _peer

      private final PeerState _peer
      Will be null, unless we are part of the establishment.
    • _expiration

      private final long _expiration
      When the message expires.
    • _messageBuf

      private final byte[] _messageBuf
      The message bytes prepared for sending.
    • _fragmentSize

      private final int _fragmentSize
      Fixed fragment size across the message.
    • _fragmentAcks

      private long _fragmentAcks
      Bitmask, 0 if acked, all 0 = complete.
    • _numFragments

      private final int _numFragments
      Fragments the message was split into.
    • _fragmentSends

      private final byte[] _fragmentSends
      Sends for each fragment, or null if only one fragment.
    • _startedOn

      private final long _startedOn
      When the message sending started.
    • _firstSendTime

      private volatile long _firstSendTime
      Time of first fragment send (for network RTT measurement, excludes queue time).
    • _pushCount

      private int _pushCount
      Times the message has been pushed.
    • _maxSends

      private int _maxSends
      Most sends of the message allowed.
    • _enqueueTime

      private volatile long _enqueueTime
      When the message was last enqueued, tracked here since the message itself is null for injections.
    • _seqNum

      private volatile long _seqNum
      Sequence number of the message.
    • _allowedSendBytes

      private int _allowedSendBytes
      How many bytes push(List) is allowed to send.
    • _nacks

      private final AtomicInteger _nacks
      Nacks received for the fragments.
    • MAX_MSG_SIZE

      public static final int MAX_MSG_SIZE
      Largest message body SSU will carry, in bytes; larger ones are rejected.
      See Also:
    • _messageExpiration

      private static volatile long _messageExpiration
      Configurable message expiration. Default 60s, adjusted by Tuner under load.
  • Constructor Details

    • OutboundMessageState

      public OutboundMessageState(I2PAppContext context, I2NPMessage msg, PeerState peer)
      "injected" message from the establisher.

      Called from UDPTransport.

      Parameters:
      context - the router context supplying the clock and bandwidth manager
      msg - the message to fragment and send
      peer - the peer the message is destined for
      Throws:
      IllegalArgumentException - if too big or if msg or peer is null
    • OutboundMessageState

      public OutboundMessageState(I2PAppContext context, OutNetMessage m, PeerState peer)
      Normal constructor.

      Called from OutboundMessageFragments.

      Parameters:
      context - the router context supplying the clock and bandwidth manager
      m - the outbound message carrying the payload and its send options
      peer - the peer the message is destined for
      Throws:
      IllegalArgumentException - if too big or if msg or peer is null
    • OutboundMessageState

      private OutboundMessageState(I2PAppContext context, OutNetMessage m, I2NPMessage msg, PeerState peer)
      Fragments the given message for transmission.
      Parameters:
      context - the application context
      m - null if msg is "injected"
      msg - the message to fragment
      peer - the peer the message is being sent to
      Throws:
      IllegalArgumentException - if too big or if msg or peer is null
  • Method Details

    • getMessageExpiration

      public static long getMessageExpiration()
      How long an outbound SSU message stays in flight before it is dropped.
      Returns:
      the duration in ms, 5000-300000, 60000 unless the Tuner changed it
    • setMessageExpiration

      public static void setMessageExpiration(long ms)
      The outbound message expiration, called by Tuner.
      Parameters:
      ms - expiration in ms, clamped to [5000, 300000]
    • getVersion

      public int getVersion()
      The SSU 2 version of the peer.
      Returns:
      the peer's SSU version, 1 for SSU1
    • mask

      private static long mask(int fragment)
      Bit mask for the given fragment index.
      Parameters:
      fragment - 0-63
      Returns:
      a long with bit fragment set
    • getMessage

      public OutNetMessage getMessage()
      The message.
      Returns:
      the OutNetMessage this state tracks
    • getMessageId

      public long getMessageId()
      The message ID.
      Returns:
      the unique ID of the I2NP message being tracked
    • incrementNACKs

      public int incrementNACKs()
      Increment and return the NACK count.
      Returns:
      new value
    • getNACKs

      public int getNACKs()
      The NACK count.
      Returns:
      the nacks received since the last ACK
    • clearNACKs

      public void clearNACKs()
      Reset the NACK counter to zero, so the retransmission accounting for this message starts over from the next ACK.
    • getPeer

      public PeerState getPeer()
      The peer.
      Returns:
      the PeerState the message was sent to
    • isExpired

      public boolean isExpired()
      Whether the message has expired.
      Returns:
      true if the expiration is before the current time
    • isExpired

      public boolean isExpired(long now)
      Whether the message has expired at the given time.
      Parameters:
      now - the current time in milliseconds since the epoch to test against
      Returns:
      true if the expiration is before the given time
    • isComplete

      public boolean isComplete()
      Whether all fragments have been acked.
      Returns:
      true when the ack bitmask has no bits left set
    • getUnackedSize

      public int getUnackedSize()
      The total size of the fragments that have not yet been acked, counting the packet overhead of each fragment needing to be sent.
      Returns:
      the unacked size
    • getUnackedFragments

      public int getUnackedFragments()
      How many fragments of the message still need an ack.
      Returns:
      0 when the message is complete, otherwise 1 to the fragment count
    • hasUnsentFragments

      public boolean hasUnsentFragments()
      Is any fragment unsent?
      Returns:
      whether unsent fragments is present
    • getMinSendCount

      private int getMinSendCount()
      The min send count of unacked fragments. Only call if not complete and _numFragments greater than 1. Caller must synch.
      Returns:
      the min send count
    • getMinSendSize

      public int getMinSendSize()
      The minimum number of bytes we can send, which is the smallest unacked fragment we will send next. Includes packet overhead.
      Returns:
      0 to total size
    • getSendSize

      public int getSendSize(int max)
      How many bytes we can send under the max given. Side effect: if applicable, amount to send will be saved for the push() call. Note: With multiple fragments, this will allocate only the fragments with the lowest push count. Example: If push counts are 1 1 1 0 0, this will only return the size of the last two fragments, even if any of the first three need to be retransmitted. Includes packet overhead.
      Parameters:
      max - the maximum number of bytes we can send, including packet overhead
      Returns:
      0 to max bytes
    • needsSending

      public boolean needsSending(int fragment)
      Whether the fragment has not been ACKed.
      Parameters:
      fragment - the zero-based fragment number to test
      Returns:
      true if the fragment has not been ACKed
    • getLifetime

      public long getLifetime()
      The lifetime.
      Returns:
      ms elapsed since the message was created
    • getStartedOn

      public long getStartedOn()
      When this message was created, for computing lifetime without a repeated clock read in hot loops.
      Returns:
      the creation time (ms since epoch)
    • getSendLifetime

      public long getSendLifetime()
      Network RTT: time since first fragment was sent (excludes queue time). Falls back to total lifetime if message hasn't been sent yet.
      Returns:
      the send lifetime
    • acked

      public boolean acked(ACKBitfield bitfield)
      Ack all the fragments in the ack list.
      Parameters:
      bitfield - the ACK bitfield received from the peer, marking the fragments it holds
      Returns:
      true if the message was completely ACKed
    • acked

      public boolean acked(int fragmentNum)
      Ack this fragment number. For SSU 2 only.
      Parameters:
      fragmentNum - the zero-based fragment number to clear, ignored when outside the range of fragments in this message
      Returns:
      true if the message was completely ACKed
    • getMaxSends

      public int getMaxSends()
      The max number of sends for any fragment. As of 0.9.49, may be less than getPushCount() if we pushed only some fragments.
      Returns:
      the max sends
    • getPushCount

      public int getPushCount()
      The number of times we've pushed some fragments. As of 0.9.49, may be greater than getMaxSends() if we pushed only some fragments.
      Returns:
      the push count
    • push

      public int push(List<PacketBuilder2.Fragment> toSend)
      Add fragments up to the number of bytes allowed by setAllowedSendBytes() Side effects: Clears setAllowedSendBytes. Increments pushCount. Increments maxSends if applicable. Note: With multiple fragments, this will send only the fragments with the lowest push count. Example: If push counts are 1 1 1 0 0, this will only send the last two fragments, even if any of the first three need to be retransmitted.
      Parameters:
      toSend - list the added fragments are appended to
      Returns:
      the number of Fragments added
    • getFragmentCount

      public int getFragmentCount()
      How many fragments in the message.
      Returns:
      the fragment count
    • getMessageSize

      public int getMessageSize()
      The size of the I2NP message. Does not include any SSU overhead.
      Returns:
      the message size
    • fragmentSize

      public int fragmentSize(int fragmentNum)
      The size in bytes of the fragment. Does NOT include any SSU overhead (SSU2 is 3 for all fragments, + 5 for followon fragments).
      Parameters:
      fragmentNum - the number of the fragment
      Returns:
      the size of the fragment specified by the number
    • writeFragment

      public int writeFragment(byte[] out, int outOffset, int fragmentNum)
      Write a part of the the message onto the specified buffer.
      Parameters:
      out - target to write
      outOffset - into outOffset to begin writing
      fragmentNum - fragment to write (0 indexed)
      Returns:
      bytesWritten, NOT including packet overhead
    • setEnqueueTime

      public void setEnqueueTime(long now)
      For CDQ.
      Specified by:
      setEnqueueTime in interface CDQEntry
      Parameters:
      now - the enqueue timestamp
    • getEnqueueTime

      public long getEnqueueTime()
      For CDQ.
      Specified by:
      getEnqueueTime in interface CDQEntry
      Returns:
      the enqueue time
    • drop

      public void drop()
      For CDQ.
      Specified by:
      drop in interface CDQEntry
    • setSeqNum

      public void setSeqNum(long num)
      For CDPQ.
      Specified by:
      setSeqNum in interface PQEntry
      Parameters:
      num - the sequence number
    • getSeqNum

      public long getSeqNum()
      For CDPQ.
      Specified by:
      getSeqNum in interface PQEntry
      Returns:
      the seq num
    • getPriority

      public int getPriority()
      For CDPQ.
      Specified by:
      getPriority in interface PQEntry
      Returns:
      OutNetMessage priority or 1000 for injected
    • toString

      public String toString()
      A string summary of this message state.
      Overrides:
      toString in class Object