java.lang.Object
net.i2p.data.i2np.I2NPMessageImpl
All Implemented Interfaces:
I2NPMessage
Direct Known Subclasses:
FastI2NPMessageImpl, TunnelBuildMessageBase

public abstract class I2NPMessageImplextends Object implements I2NPMessage
Defines the base message implementation.

Note: No longer extends DataStructureImpl as of 0.9.48.

  • Nested Class Summary

    Nested Classes
    Modifier and Type
    Class
    Description
    static interface 
    Interface for extending the types of messages handled - unused.
  • Field Summary

    Modifier and Type
    Field
    Description
    private static final Map<Integer, I2NPMessageImpl.Builder>
    Unused custom message-type builders.
    protected final I2PAppContext
    Application context this message belongs to.
    protected long
    Expiration time in milliseconds since the epoch, as an I2P Date.
    protected final Log
    Log for the message class, taken from the context's log manager.
    private final AtomicLong
    Warning, lazily initialized by readBytes(byte[], int, int), writeBytes(), toByteArray(), getUniqueId(), and setUniqueId().
    static final int
    Number of checksum bytes the message header carries.
    static final long
    Default lifetime of an unsent message, one minute in milliseconds.
    static final int
    I2NP message header size in bytes.

    Fields inherited from interface I2NPMessage

    MAX_ID_VALUE, MAX_SIZE
    Modifier and Type
    Field
    Description
    static final long
    4 bytes unsigned.
    static final int
    Nominal limit, actual max is much less.
  • Constructor Summary

    Constructors
    Constructor
    Description
    Create an empty message with the default expiration.
  • Method Summary

    Modifier and Type
    Method
    Description
    protected abstract int
    Calculate the message body's length (not including the header and footer).
    createMessage(I2PAppContext context, int type)
    Yes, this is fairly ugly, but its the only place it ever happens.
    fromRawByteArray(I2PAppContext ctx, byte[] buffer, int offset, int len, I2NPMessageHandler handler)
    Read the message with a short 5-byte header.
    fromRawByteArrayNTCP2(I2PAppContext ctx, byte[] buffer, int offset, int len, I2NPMessageHandler handler)
    Read the message with a short 9-byte header.
    long
    Date after which the message should be dropped (and the associated uniqueId forgotten).
    int
    Serialized message size, including the 16-byte header.
    int
    The raw header consists of a one-byte type and a 4-byte expiration in seconds only.
    long
    Unique id for this message, lazily initialized when negative.
    long
    getUniqueId(long msgIDBloomXor)
    Replay resistant message Id.
    int
    readBytes(byte[] data, int type, int offset)
    Read the header, then read the rest into buffer, then call readMessage in the implemented message type.
    int
    readBytes(byte[] data, int type, int offset, int maxLen)
    Limit the max to read from the data buffer, so that we can use a large buffer but prevent the reader from reading off the end.
    void
    readMessage(byte[] data, int offset, int dataSize, int type, I2NPMessageHandler handler)
    Read the message fields from the byte array, ignoring the handler.
    void
    The expiration is set to one minute from now in the constructor but it can be overridden here.
    void
    setUniqueId(long id)
    The ID is set to a random value when written but it can be overridden here.
    byte[]
    The message serialized into a new byte array.
    int
    toByteArray(byte[] buffer)
    Write the message to the buffer, returning the number of bytes written.
    int
    toByteArray(byte[] buffer, int off)
    Write the message to the buffer, returning the new offset (NOT the length).
    int
    toRawByteArray(byte[] buffer)
    Write the message with a short 5-byte header.
    int
    toRawByteArrayNTCP2(byte[] buffer, int off)
    Write the message to the buffer, returning the new offset (NOT the length).
    protected abstract int
    writeMessageBody(byte[] out, int curIndex)
    Write the message body to the output array, starting at the given index.

    Methods inherited from class Object

    clone, equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait

    Methods inherited from interface I2NPMessage

    getType, readMessage
    Modifier and Type
    Method
    Description
    int
    Return the unique identifier for this type of I2NP message, as defined in the I2NP spec.
    void
    readMessage(byte[] data, int offset, int dataSize, int type)
    Read the body into the data structures, after the initial type byte and the uniqueId / expiration, using the current class's format as defined by the I2NP specification.
  • Field Details

    • _log

      protected final Log _log
      Log for the message class, taken from the context's log manager.
    • _context

      protected final I2PAppContext _context
      Application context this message belongs to.
    • _expiration

      protected long _expiration
      Expiration time in milliseconds since the epoch, as an I2P Date.
    • _uniqueId

      private final AtomicLong _uniqueId
      Warning, lazily initialized by readBytes(byte[], int, int), writeBytes(), toByteArray(), getUniqueId(), and setUniqueId(). Otherwise will be -1. Extending classes should take care when accessing this field; to ensure initialization, use getUniqueId() instead.
    • DEFAULT_EXPIRATION_MS

      public static final long DEFAULT_EXPIRATION_MS
      Default lifetime of an unsent message, one minute in milliseconds.
      See Also:
    • CHECKSUM_LENGTH

      public static final int CHECKSUM_LENGTH
      Number of checksum bytes the message header carries.
      See Also:
    • HEADER_LENGTH

      public static final int HEADER_LENGTH
      I2NP message header size in bytes.
      See Also:
    • _builders

      private static final Map<Integer, I2NPMessageImpl.Builder> _builders
      Unused custom message-type builders.
  • Constructor Details

    • I2NPMessageImpl

      public I2NPMessageImpl(I2PAppContext context)
      Create an empty message with the default expiration.
      Parameters:
      context - the application context the message belongs to
  • Method Details

    • readBytes

      public int readBytes(byte[] data, int type, int offset) throws I2NPMessageException
      Read the header, then read the rest into buffer, then call readMessage in the implemented message type.
       Specifically:
       1 byte type (if caller didn't read already, as specified by the type param
       4 byte ID
       8 byte expiration
       2 byte size
       1 byte checksum
       size bytes of payload (read by readMessage() in implementation)
      
      Specified by:
      readBytes in interface I2NPMessage
      Parameters:
      data - the full serialized message, header included
      type - the message type or -1 if we should read it here
      offset - where to start starting at type if type is < 0 (16 byte header) starting at ID if type is >= 0 (15 byte header)
      Returns:
      total length of the message
      Throws:
      I2NPMessageException - if there is no valid message
    • readBytes

      public int readBytes(byte[] data, int type, int offset, int maxLen) throws I2NPMessageException
      Limit the max to read from the data buffer, so that we can use a large buffer but prevent the reader from reading off the end.
      Specified by:
      readBytes in interface I2NPMessage
      Parameters:
      data - the data, may or may not include the type
      type - the message type or -1 if we should read it here
      offset - where to start starting at type if type is < 0 (16 byte header) starting at ID if type is >= 0 (15 byte header)
      maxLen - read no more than this many bytes from data starting at offset, even if it is longer This includes the type byte only if type < 0
      Returns:
      total length of the message
      Throws:
      I2NPMessageException - if there is no valid message
    • getUniqueId

      public long getUniqueId(long msgIDBloomXor)
      Replay resistant message Id.
      Specified by:
      getUniqueId in interface I2NPMessage
      Parameters:
      msgIDBloomXor - value to XOR the id with, or 0 for the id unchanged
      Returns:
      the unique id
    • getUniqueId

      public long getUniqueId()
      Unique id for this message, lazily initialized when negative.
      Specified by:
      getUniqueId in interface I2NPMessage
      Returns:
      the unique id
    • setUniqueId

      public void setUniqueId(long id)
      The ID is set to a random value when written but it can be overridden here.
      Specified by:
      setUniqueId in interface I2NPMessage
      Parameters:
      id - the unique id to attach to this message
    • getMessageExpiration

      public long getMessageExpiration()
      Date after which the message should be dropped (and the associated uniqueId forgotten).
      Specified by:
      getMessageExpiration in interface I2NPMessage
      Returns:
      the message expiration
    • setMessageExpiration

      public void setMessageExpiration(long exp)
      The expiration is set to one minute from now in the constructor but it can be overridden here.
      Specified by:
      setMessageExpiration in interface I2NPMessage
      Parameters:
      exp - the expiration as milliseconds since the epoch, which is also when the peer should stop forwarding the message
    • getMessageSize

      public int getMessageSize()
      Serialized message size, including the 16-byte header.

      Kept synchronized: subclasses (DatabaseStoreMessage, TunnelGatewayMessage) lazily cache mutable state in calculateWrittenLength() and rely on the enclosing monitor for safe publication.

      Specified by:
      getMessageSize in interface I2NPMessage
      Returns:
      the message size
    • getRawMessageSize

      public int getRawMessageSize()
      The raw header consists of a one-byte type and a 4-byte expiration in seconds only. Used by SSU only!
      Specified by:
      getRawMessageSize in interface I2NPMessage
      Returns:
      the raw message size
    • toByteArray

      public byte[] toByteArray()
      The message serialized into a new byte array.
      Specified by:
      toByteArray in interface I2NPMessage
      Returns:
      a new array holding the whole message, full 16 byte header included
    • toByteArray

      public int toByteArray(byte[] buffer)
      Write the message to the buffer, returning the number of bytes written. The data is formatted so as to be self contained, with the type, size, expiration, unique id, as well as a checksum bundled along. Full 16 byte header for NTCP 1.
      Specified by:
      toByteArray in interface I2NPMessage
      Parameters:
      buffer - the destination array, which must have room for I2NPMessage.getMessageSize() bytes
      Returns:
      the length written
    • toByteArray

      public int toByteArray(byte[] buffer, int off)
      Write the message to the buffer, returning the new offset (NOT the length). the data is formatted so as to be self contained, with the type, size, expiration, unique id, as well as a checksum bundled along. Full 16 byte header for NTCP 1.
      Specified by:
      toByteArray in interface I2NPMessage
      Parameters:
      buffer - the destination array, which must have room for I2NPMessage.getMessageSize() bytes from off on
      off - the offset to start writing at
      Returns:
      the new offset (NOT the length)
    • calculateWrittenLength

      protected abstract int calculateWrittenLength()
      Calculate the message body's length (not including the header and footer).
      Returns:
      the number of bytes the body will occupy once serialized
    • writeMessageBody

      protected abstract int writeMessageBody(byte[] out, int curIndex) throws I2NPMessageException
      Write the message body to the output array, starting at the given index.
      Parameters:
      out - the buffer to serialize the body into
      curIndex - the offset into out at which to begin writing; leave room for the signature where the header format calls for one
      Returns:
      the index into the array after the last byte written (NOT the length)
      Throws:
      I2NPMessageException - if the body cannot be serialized into out, because it is too small or a field is unserializable
    • toRawByteArray

      public int toRawByteArray(byte[] buffer)
      Write the message with a short 5-byte header. The header consists of a one-byte type and a 4-byte expiration in seconds only. Used by SSU only!
      Specified by:
      toRawByteArray in interface I2NPMessage
      Parameters:
      buffer - the destination array, written from index 0, which must have room for I2NPMessage.getRawMessageSize() bytes
      Returns:
      the new offset (NOT the length)
    • toRawByteArrayNTCP2

      public int toRawByteArrayNTCP2(byte[] buffer, int off)
      Write the message to the buffer, returning the new offset (NOT the length). the data is is not self contained - it does not include the size, unique id, or any checksum, but does include the type and expiration. Short 9 byte header for NTCP2 and SSU2.
      Specified by:
      toRawByteArrayNTCP2 in interface I2NPMessage
      Parameters:
      buffer - the destination array, which must have room for I2NPMessage.getRawMessageSize() bytes from off on
      off - the offset to start writing at
      Returns:
      the new offset (NOT the length)
    • readMessage

      public void readMessage(byte[] data, int offset, int dataSize, int type, I2NPMessageHandler handler) throws I2NPMessageException
      Read the message fields from the byte array, ignoring the handler.
      Specified by:
      readMessage in interface I2NPMessage
      Parameters:
      data - the buffer holding the message, header included
      offset - where to start in the data array
      dataSize - how long into the data to read
      type - I2NP message type
      handler - the target for the message the buffer contains
      Throws:
      I2NPMessageException - if the stream doesn't contain a valid message that this class can read.
    • fromRawByteArray

      public static I2NPMessage fromRawByteArray(I2PAppContext ctx, byte[] buffer, int offset, int len, I2NPMessageHandler handler) throws I2NPMessageException
      Read the message with a short 5-byte header. The header consists of a one-byte type and a 4-byte expiration in seconds only. Caller MUST call setUniqueId(long) on the returned value. Used by SSU2 only!
      Parameters:
      ctx - the application context the resulting message belongs to
      buffer - the serialized message
      offset - the index in buffer at which the 5-byte header starts
      len - the total number of readable bytes in buffer, at least 5
      handler - ignored, may be null
      Returns:
      the deserialized message, never null; an unrecognized type yields an UnknownI2NPMessage
      Throws:
      I2NPMessageException - if len is under 5, or the body cannot be parsed
    • fromRawByteArrayNTCP2

      public static I2NPMessage fromRawByteArrayNTCP2(I2PAppContext ctx, byte[] buffer, int offset, int len, I2NPMessageHandler handler) throws I2NPMessageException
      Read the message with a short 9-byte header. The header consists of a one-byte type, 4-byte ID, and a 4-byte expiration in seconds only. Used by NTCP2 and SSU2 only!
      Parameters:
      ctx - the application context the resulting message belongs to
      buffer - the serialized message
      offset - the index in buffer at which the 9-byte header starts
      len - the total number of readable bytes in buffer, at least 9
      handler - ignored, may be null
      Returns:
      the deserialized message, never null; an unrecognized type yields an UnknownI2NPMessage
      Throws:
      I2NPMessageException - if len is under 9, or the body cannot be parsed
    • createMessage

      public static I2NPMessage createMessage(I2PAppContext context, int type)
      Yes, this is fairly ugly, but its the only place it ever happens.
      Parameters:
      context - the application context the message will belong to
      type - the I2NP message type byte
      Returns:
      non-null, returns an UnknownI2NPMessage if unknown type