net.i2p.client.streaming.impl

## 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 Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `protected long[]` | `_nacks`
    `protected Signature` | `_offlineSignature`
    `protected Destination` | `_optionFrom`
    `protected Signature` | `_optionSignature`
    `protected I2PSession` | `_session`
    `protected long` | `_transientExpires`
    `protected SigningPublicKey` | `_transientSigningPublicKey`
    `static int` | `DEFAULT_MAX_SIZE`
    `static int` | `FLAG_CLOSE` The sender of this packet will not be sending any more payload data.
    `static 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.
    `static int` | `FLAG_ECHO` If set, this packet is a ping (if sendStreamId is set) or a ping reply (if receiveStreamId is set).
    `static int` | `FLAG_FROM_INCLUDED` This packet includes the full I2P destination of the packet's sender.
    `static 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.
    `static int` | `FLAG_NO_ACK` If set, this packet doesn't really want to ack anything
    `static 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.
    `static 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).
    `static int` | `FLAG_SIGNATURE_INCLUDED` This packet contains a DSA signature from the packet's sender.
    `static int` | `FLAG_SIGNATURE_OFFLINE` If set, an offline signing block is in the options.
    `static int` | `FLAG_SIGNATURE_REQUESTED` This packet wants the recipient to include signatures on subsequent packets sent to the creator of this packet.
    `static 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.
    `protected static int` | `MAX_DELAY_REQUEST`
    `static int` | `MAX_PAYLOAD_SIZE`
    `static long` | `MAX_STREAM_ID`
    `static int` | `MIN_DELAY_CHOKE`
    `static int` | `SEND_DELAY_CHOKE`
    `static 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)

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `Packet(I2PSession session)` Does no initialization.

  - ### Method Summary

    All Methods Static Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `ByteArray` | `acquirePayload()`
    `protected StringBuilder` | `formatAsString()`
    `long` | `getAckThrough()` The highest packet sequence number that received on the receiveStreamId.
    `int` | `getLocalPort()`
    `long[]` | `getNacks()` List of packet sequence numbers below the getAckThrough() value have not been received.
    `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)
    `Destination` | `getOptionalFrom()` the sender of the packet (only included if the flag for it is set)
    `int` | `getOptionalMaxSize()` What is the largest payload the sender of this packet wants to receive?
    `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.
    `ByteArray` | `getPayload()` get the actual payload of the message.
    `int` | `getPayloadSize()`
    `long` | `getReceiveStreamId()` stream the replies should be sent on.
    `int` | `getRemotePort()`
    `int` | `getResendDelay()` How long is the creator of this packet going to wait before resending this packet (if it hasn't yet been ACKed).
    `long` | `getSendStreamId()` what stream do we send data to the peer on?
    `long` | `getSequenceNum()` 0-indexed sequence number for this Packet in the sendStream
    `I2PSession` | `getSession()`
    `SigningPublicKey` | `getTransientSPK()` Only if an offline signing block was included, else null
    `boolean` | `isFlagSet(int flag)` is a particular flag set on this packet?
    `void` | `logTCPDump(Connection con)` Generate a pcap/tcpdump-compatible format, so we can use standard debugging tools.
    `void` | `readPacket(byte[] buffer, int offset, int length)` Read the packet from the buffer (starting at the offset) and return the number of bytes read.
    `void` | `releasePayload()` does nothing right now
    `void` | `setAckThrough(long id)`
    `void` | `setFlag(int flag)`
    `void` | `setFlag(int flag, boolean set)`
    `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.
    `void` | `setNacks(long[] nacks)`
    `void` | `setOptionalDelay(int delayMs)` Caller must also call setFlag(FLAG_DELAY_REQUESTED)
    `void` | `setOptionalMaxSize(int numBytes)` This also sets flag FLAG_MAX_PACKET_SIZE_INCLUDED
    `void` | `setOptionalSignature(Signature sig)` This also sets flag FLAG_SIGNATURE_INCLUDED
    `void` | `setPayload(ByteArray payload)`
    `void` | `setReceiveStreamId(long id)`
    `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.
    `void` | `setResendDelay(int numSeconds)` Unused.
    `void` | `setSendStreamId(long id)`
    `void` | `setSequenceNum(long num)`
    `(package private) static String` | `toId(long id)`
    `String` | `toString()`
    `boolean` | `verifySignature(I2PAppContext ctx, byte[] buffer)` Determine whether the signature on the data is valid.
    `boolean` | `verifySignature(I2PAppContext ctx, SigningPublicKey altSPK, byte[] buffer)` Determine whether the signature on the data is valid.
    `int` | `writePacket(byte[] buffer, int offset)` Write the packet to the buffer (starting at the offset) and return the number of bytes written.
    `protected int` | `writePacket(byte[] buffer, int offset, int fakeSigLen)`

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, wait, wait, wait`

- - ### Field Detail

    - #### _nacks

          protected long[] _nacks

    - #### _offlineSignature

          protected Signature _offlineSignature

    - #### _optionFrom

          protected Destination _optionFrom

    - #### _optionSignature

          protected Signature _optionSignature

    - #### _session

          protected final I2PSession _session

    - #### _transientExpires

          protected long _transientExpires

    - #### _transientSigningPublicKey

          protected SigningPublicKey _transientSigningPublicKey

    - #### DEFAULT_MAX_SIZE

          public static final int DEFAULT_MAX_SIZE

    - #### FLAG_CLOSE

          public static final int FLAG_CLOSE

      The sender of this packet will not be sending any more payload data.
      See Also:
        Constant Field Values

    - #### 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:
        Constant Field Values

    - #### 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:
        Constant Field Values

    - #### 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:
        Constant Field Values

    - #### 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:
        Constant Field Values

    - #### FLAG_NO_ACK

          public static final int FLAG_NO_ACK

      If set, this packet doesn't really want to ack anything
      See Also:
        Constant Field Values

    - #### 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:
        Constant Field Values

    - #### 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:
        Constant Field Values

    - #### 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:
        Constant Field Values

    - #### FLAG_SIGNATURE_OFFLINE

          public static final int FLAG_SIGNATURE_OFFLINE

      If set, an offline signing block is in the options.
      See Also:
        Constant Field Values

    - #### 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:
        Constant Field Values

    - #### 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:
        Constant Field Values

    - #### MAX_DELAY_REQUEST

          protected static final int MAX_DELAY_REQUEST

      See Also:
        Constant Field Values

    - #### MAX_PAYLOAD_SIZE

          public static final int MAX_PAYLOAD_SIZE

      See Also:
        Constant Field Values

    - #### MAX_STREAM_ID

          public static final long MAX_STREAM_ID

      See Also:
        Constant Field Values

    - #### MIN_DELAY_CHOKE

          public static final int MIN_DELAY_CHOKE

      See Also:
        Constant Field Values

    - #### SEND_DELAY_CHOKE

          public static final int SEND_DELAY_CHOKE

      See Also:
        Constant Field Values

    - #### 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:
        Constant Field Values

  - ### Constructor Detail

    - #### Packet

          public Packet(I2PSession session)

      Does no initialization. See readPacket() for inbound packets, and the setters for outbound packets.

  - ### Method Detail

    - #### acquirePayload

          public ByteArray acquirePayload()

    - #### formatAsString

          protected StringBuilder formatAsString()

    - #### 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

    - #### getLocalPort

          public int getLocalPort()

      Returns:
        Default I2PSession.PORT_UNSPECIFIED (0) or PORT_ANY (0)

    - #### getNacks

          public long[] getNacks()

      List of packet sequence numbers below the getAckThrough() value have not been received. this may be null. Warning: This is different than getNACKs() in PacketLocal
      Returns:
        List of packet sequence numbers not ACKed, or null if there are none.

    - #### 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.

    - #### getOptionalFrom

          public Destination getOptionalFrom()

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

    - #### 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

    - #### 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

    - #### getPayload

          public ByteArray getPayload()

      get the actual payload of the message. may be null
      Returns:
        the payload of the message, null if none.

    - #### getPayloadSize

          public int getPayloadSize()

    - #### 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.

    - #### getRemotePort

          public int getRemotePort()

      Returns:
        Default I2PSession.PORT_UNSPECIFIED (0) or PORT_ANY (0)

    - #### 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.

    - #### getSendStreamId

          public long getSendStreamId()

      what stream do we send data to the peer on?
      Returns:
        stream ID we use to send data

    - #### 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

    - #### getSession

          public I2PSession getSession()

    - #### getTransientSPK

          public SigningPublicKey getTransientSPK()

      Only if an offline signing block was included, else null

    - #### 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.

    - #### logTCPDump

          public void logTCPDump(Connection con)

      Generate a pcap/tcpdump-compatible format, so we can use standard debugging tools.

    - #### 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

    - #### releasePayload

          public void releasePayload()

      does nothing right now

    - #### setAckThrough

          public void setAckThrough(long id)

      Parameters:
        `id` - if < 0, sets FLAG_NO_ACK

    - #### 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

    - #### 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.

    - #### setNacks

          public void setNacks(long[] nacks)

    - #### setOptionalDelay

          public void setOptionalDelay(int delayMs)

      Caller must also call setFlag(FLAG_DELAY_REQUESTED)

    - #### setOptionalMaxSize

          public void setOptionalMaxSize(int numBytes)

      This also sets flag FLAG_MAX_PACKET_SIZE_INCLUDED

    - #### setOptionalSignature

          public void setOptionalSignature(Signature sig)

      This also sets flag FLAG_SIGNATURE_INCLUDED

    - #### setPayload

          public void setPayload(ByteArray payload)

    - #### setReceiveStreamId

          public void setReceiveStreamId(long id)

    - #### 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.

    - #### setResendDelay

          public void setResendDelay(int numSeconds)

      Unused. Broken before release 0.7.8 See above

    - #### setSendStreamId

          public void setSendStreamId(long id)

    - #### setSequenceNum

          public void setSequenceNum(long num)

    - #### toId

          static final String toId(long id)

    - #### toString

          public String toString()

      Overrides:
        `toString` in class `Object`

    - #### 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.

    - #### 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.

    - #### 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`