Class Packet

java.lang.Object
net.i2p.client.streaming.impl.Packet
Direct Known Subclasses:
PacketLocal

class Packet extends Object
This contains solely the data that goes out on the wire, including the local and remote port which is embedded in the I2CP overhead, not in the packet itself. This is the class used for inbound packets. For local state saved for outbound packets, see the PacketLocal extension.

Contain a single packet transferred as part of a streaming connection. The data format is as follows:

  • sendStreamId [4 byte value]
  • receiveStreamId [4 byte value]
  • sequenceNum [4 byte unsigned integer]
  • ackThrough [4 byte unsigned integer]
  • number of NACKs [1 byte unsigned integer]
  • that many NACKs
  • resendDelay [1 byte integer]
  • flags [2 byte value]
  • option data size [2 byte integer]
  • option data specified by those flags [0 or more bytes]
  • payload [remaining packet size]

The flags field above specifies some metadata about the packet, and in turn may require certain additional data to be included. The flags are as follows (with any data structures specified added to the options area in the given order):

  1. FLAG_SYNCHRONIZE: no option data
  2. FLAG_CLOSE: no option data
  3. FLAG_RESET: no option data
  4. FLAG_SIGNATURE_INCLUDED: Signature
  5. FLAG_SIGNATURE_REQUESTED: no option data
  6. FLAG_FROM_INCLUDED: Destination
  7. FLAG_DELAY_REQUESTED: 2 byte integer
  8. FLAG_MAX_PACKET_SIZE_INCLUDED: 2 byte integer
  9. FLAG_PROFILE_INTERACTIVE: no option data
  10. FLAG_ECHO: no option data
  11. FLAG_NO_ACK: no option data - this appears to be unused, we always ack, even for the first packet

If the signature is included, it uses the Destination's DSA key to sign the entire header and payload with the space in the options for the signature being set to all zeroes.

If the sequenceNum is 0 and the SYN is not set, this is a plain ACK packet that should not be ACKed

NOTE: All setters unsynchronized.
  • Field Details

    • _session

      protected final I2PSession _session
    • _nacks

      protected long[] _nacks
    • _optionSignature

      protected Signature _optionSignature
    • _optionFrom

      protected Destination _optionFrom
    • _transientExpires

      protected long _transientExpires
    • _offlineSignature

      protected Signature _offlineSignature
    • _transientSigningPublicKey

      protected SigningPublicKey _transientSigningPublicKey
    • STREAM_ID_UNKNOWN

      public static final long STREAM_ID_UNKNOWN
      The receiveStreamId will be set to this when the packet doesn't know what ID will be assigned by the remote peer (aka this is the initial synchronize packet)
      See Also:
    • MAX_STREAM_ID

      public static final long MAX_STREAM_ID
      See Also:
    • FLAG_SYNCHRONIZE

      public static final int FLAG_SYNCHRONIZE
      This packet is creating a new socket connection (if the receiveStreamId is STREAM_ID_UNKNOWN) or it is acknowledging a request to create a connection and in turn is accepting the socket.
      See Also:
    • FLAG_CLOSE

      public static final int FLAG_CLOSE
      The sender of this packet will not be sending any more payload data.
      See Also:
    • FLAG_RESET

      public static final int FLAG_RESET
      This packet is being sent to signify that the socket does not exist (or, if in response to an initial synchronize packet, that the connection was refused).
      See Also:
    • FLAG_SIGNATURE_INCLUDED

      public static final int FLAG_SIGNATURE_INCLUDED
      This packet contains a DSA signature from the packet's sender. This signature is within the packet options. All synchronize packets must have this flag set.
      See Also:
    • FLAG_SIGNATURE_REQUESTED

      public static final int FLAG_SIGNATURE_REQUESTED
      This packet wants the recipient to include signatures on subsequent packets sent to the creator of this packet.
      See Also:
    • FLAG_FROM_INCLUDED

      public static final int FLAG_FROM_INCLUDED
      This packet includes the full I2P destination of the packet's sender. The initial synchronize packet must have this flag set.
      See Also:
    • FLAG_DELAY_REQUESTED

      public static final int FLAG_DELAY_REQUESTED
      This packet includes an explicit request for the recipient to delay sending any packets with data for a given amount of time.
      See Also:
    • FLAG_MAX_PACKET_SIZE_INCLUDED

      public static final int FLAG_MAX_PACKET_SIZE_INCLUDED
      This packet includes a request that the recipient not send any subsequent packets with payloads greater than a specific size. If not set and no prior value was delivered, the maximum value will be assumed (approximately 32KB).
      See Also:
    • FLAG_PROFILE_INTERACTIVE

      public static final int FLAG_PROFILE_INTERACTIVE
      If set, this packet is travelling as part of an interactive flow, meaning it is more lag sensitive than throughput sensitive. aka send data ASAP rather than waiting around to send full packets.
      See Also:
    • FLAG_ECHO

      public static final int FLAG_ECHO
      If set, this packet is a ping (if sendStreamId is set) or a ping reply (if receiveStreamId is set).
      See Also:
    • FLAG_NO_ACK

      public static final int FLAG_NO_ACK
      If set, this packet doesn't really want to ack anything
      See Also:
    • FLAG_SIGNATURE_OFFLINE

      public static final int FLAG_SIGNATURE_OFFLINE
      If set, an offline signing block is in the options.
      Since:
      0.9.39
      See Also:
    • DEFAULT_MAX_SIZE

      public static final int DEFAULT_MAX_SIZE
      See Also:
    • MAX_DELAY_REQUEST

      protected static final int MAX_DELAY_REQUEST
      See Also:
    • MIN_DELAY_CHOKE

      public static final int MIN_DELAY_CHOKE
      See Also:
    • SEND_DELAY_CHOKE

      public static final int SEND_DELAY_CHOKE
      See Also:
    • MAX_PAYLOAD_SIZE

      public static final int MAX_PAYLOAD_SIZE
      See Also:
  • Constructor Details

    • Packet

      public Packet(I2PSession session)
      Does no initialization. See readPacket() for inbound packets, and the setters for outbound packets.
  • Method Details

    • getSession

      public I2PSession getSession()
      Since:
      0.9.21
    • getSendStreamId

      public long getSendStreamId()
      what stream do we send data to the peer on?
      Returns:
      stream ID we use to send data
    • setSendStreamId

      public void setSendStreamId(long id)
    • getReceiveStreamId

      public long getReceiveStreamId()
      stream the replies should be sent on. this should be 0 if the connection is still being built.
      Returns:
      stream ID we use to get data, zero if the connection is still being built.
    • setReceiveStreamId

      public void setReceiveStreamId(long id)
    • getSequenceNum

      public long getSequenceNum()
      0-indexed sequence number for this Packet in the sendStream
      Returns:
      0-indexed sequence number for current Packet in current sendStream
    • setSequenceNum

      public void setSequenceNum(long num)
    • getAckThrough

      public long getAckThrough()
      The highest packet sequence number that received on the receiveStreamId. This field is ignored on the initial connection packet (where receiveStreamId is the unknown id) or if FLAG_NO_ACK is set.
      Returns:
      The highest packet sequence number received on receiveStreamId, or -1 if FLAG_NO_ACK
    • setAckThrough

      public void setAckThrough(long id)
      Parameters:
      id - if < 0, sets FLAG_NO_ACK
    • getNacks

      public long[] getNacks()
      List of packet sequence numbers below the getAckThrough() value have not been received. this may be null.
      Returns:
      List of packet sequence numbers not ACKed, or null if there are none.
    • setNacks

      public void setNacks(long[] nacks)
    • getResendDelay

      public int getResendDelay()
      How long is the creator of this packet going to wait before resending this packet (if it hasn't yet been ACKed). The value is seconds since the packet was created. Unused. Broken before release 0.7.8 Not to be used without sanitizing for huge values. Setters from options did not divide by 1000, and the options default is 1000, so the value sent in the 1-byte field was always 1000 & 0xff = 0xe8 = 232
      Returns:
      Delay before resending a packet in seconds.
    • setResendDelay

      public void setResendDelay(int numSeconds)
      Unused. Broken before release 0.7.8 See above
    • getPayload

      public ByteArray getPayload()
      get the actual payload of the message. may be null
      Returns:
      the payload of the message, null if none.
    • setPayload

      public void setPayload(ByteArray payload)
    • getPayloadSize

      public int getPayloadSize()
    • releasePayload

      public void releasePayload()
      does nothing right now
    • acquirePayload

      public ByteArray acquirePayload()
    • isFlagSet

      public boolean isFlagSet(int flag)
      is a particular flag set on this packet?
      Parameters:
      flag - bitmask of any flag(s)
      Returns:
      true if set, false if not.
    • setFlag

      public void setFlag(int flag)
      Parameters:
      flag - bitmask of any flag(s)
    • setFlag

      public void setFlag(int flag, boolean set)
      Parameters:
      flag - bitmask of any flag(s)
      set - true to set, false to clear
    • getOptionalSignature

      public Signature getOptionalSignature()
      The signature on the packet (only included if the flag for it is set) Warning, may be typed wrong on incoming packets for EdDSA before verifySignature() is called.
      Returns:
      signature on the packet if the flag for signatures is set
    • setOptionalSignature

      public void setOptionalSignature(Signature sig)
      This also sets flag FLAG_SIGNATURE_INCLUDED
    • getOptionalFrom

      public Destination getOptionalFrom()
      the sender of the packet (only included if the flag for it is set)
      Returns:
      the sending Destination
    • getTransientSPK

      public SigningPublicKey getTransientSPK()
      Only if an offline signing block was included, else null
      Since:
      0.9.39
    • getOptionalDelay

      public int getOptionalDelay()
      How many milliseconds the sender of this packet wants the recipient to wait before sending any more data (only valid if the flag for it is set)
      Returns:
      How long the sender wants the recipient to wait before sending any more data in ms.
    • setOptionalDelay

      public void setOptionalDelay(int delayMs)
      Caller must also call setFlag(FLAG_DELAY_REQUESTED)
    • getOptionalMaxSize

      public int getOptionalMaxSize()
      What is the largest payload the sender of this packet wants to receive?
      Returns:
      Maximum payload size sender can receive (MRU) or zero if unset
    • setOptionalMaxSize

      public void setOptionalMaxSize(int numBytes)
      This also sets flag FLAG_MAX_PACKET_SIZE_INCLUDED
    • getLocalPort

      public int getLocalPort()
      Returns:
      Default I2PSession.PORT_UNSPECIFIED (0) or PORT_ANY (0)
      Since:
      0.8.9
    • setLocalPort

      public void setLocalPort(int port)
      Must be called to change the port, not set by readPacket() as the port is out-of-band in the I2CP header.
      Since:
      0.8.9
    • getRemotePort

      public int getRemotePort()
      Returns:
      Default I2PSession.PORT_UNSPECIFIED (0) or PORT_ANY (0)
      Since:
      0.8.9
    • setRemotePort

      public void setRemotePort(int port)
      Must be called to change the port, not set by readPacket() as the port is out-of-band in the I2CP header.
      Since:
      0.8.9
    • writePacket

      public int writePacket(byte[] buffer, int offset) throws IllegalStateException
      Write the packet to the buffer (starting at the offset) and return the number of bytes written.
      Parameters:
      buffer - bytes to write to a destination
      offset - starting point in the buffer to send
      Returns:
      Count actually written
      Throws:
      IllegalStateException - if there is data missing or otherwise b0rked
    • writePacket

      protected int writePacket(byte[] buffer, int offset, int fakeSigLen) throws IllegalStateException
      Parameters:
      fakeSigLen - if 0, include the real signature in _optionSignature; if nonzero, leave space for that many bytes
      Throws:
      IllegalStateException
    • readPacket

      public void readPacket(byte[] buffer, int offset, int length) throws IllegalArgumentException
      Read the packet from the buffer (starting at the offset) and return the number of bytes read.
      Parameters:
      buffer - packet buffer containing the data
      offset - index into the buffer to start readign
      length - how many bytes within the buffer past the offset are part of the packet?
      Throws:
      IllegalArgumentException - if the data is b0rked
      IndexOutOfBoundsException - if the data is b0rked
    • verifySignature

      public boolean verifySignature(I2PAppContext ctx, byte[] buffer)
      Determine whether the signature on the data is valid. Packet MUST have a FROM option or will return false.
      Parameters:
      ctx - Application context
      buffer - data to validate with signature, or null to use our own buffer.
      Returns:
      true if the signature exists and validates against the data, false otherwise.
      Since:
      0.9.39
    • verifySignature

      public boolean verifySignature(I2PAppContext ctx, SigningPublicKey altSPK, byte[] buffer)
      Determine whether the signature on the data is valid.
      Parameters:
      ctx - Application context
      altSPK - Signing key to verify with, ONLY if there is no FROM field in this packet. May be the SPK from a FROM field or offline sig field from a previous packet on this connection. Ignored if this packet contains a FROM option block. Null ok if none available.
      buffer - data to validate with signature, or null to use our own buffer.
      Returns:
      true if the signature exists and validates against the data, false otherwise.
    • toString

      public String toString()
      Overrides:
      toString in class Object
    • formatAsString

      protected StringBuilder formatAsString()
    • toId

      static final String toId(long id)
    • logTCPDump

      public void logTCPDump(Connection con)
      Generate a pcap/tcpdump-compatible format, so we can use standard debugging tools.