java.lang.Object
net.i2p.data.i2np.I2NPMessageImpl
- All Implemented Interfaces:
I2NPMessage
- Direct Known Subclasses:
FastI2NPMessageImpl, TunnelBuildMessageBase
Defines the base message implementation.
Note: No longer extends DataStructureImpl as of 0.9.48.
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic interfaceInterface for extending the types of messages handled - unused.Field Summary
Modifier and TypeFieldDescriptionprivate static final Map<Integer, I2NPMessageImpl.Builder> Unused custom message-type builders.protected final I2PAppContextApplication context this message belongs to.protected longExpiration time in milliseconds since the epoch, as an I2P Date.protected final LogLog for the message class, taken from the context's log manager.private final AtomicLongWarning, lazily initialized byreadBytes(byte[], int, int), writeBytes(), toByteArray(),getUniqueId(), and setUniqueId().static final intNumber of checksum bytes the message header carries.static final longDefault lifetime of an unsent message, one minute in milliseconds.static final intI2NP message header size in bytes.Fields inherited from interface I2NPMessage
MAX_ID_VALUE, MAX_SIZEModifier and TypeFieldDescriptionstatic final long4 bytes unsigned.static final intNominal limit, actual max is much less.Constructor Summary
ConstructorsConstructorDescriptionI2NPMessageImpl(I2PAppContext context) Create an empty message with the default expiration.Method Summary
Modifier and TypeMethodDescriptionprotected abstract intCalculate the message body's length (not including the header and footer).static I2NPMessagecreateMessage(I2PAppContext context, int type) Yes, this is fairly ugly, but its the only place it ever happens.static I2NPMessagefromRawByteArray(I2PAppContext ctx, byte[] buffer, int offset, int len, I2NPMessageHandler handler) Read the message with a short 5-byte header.static I2NPMessagefromRawByteArrayNTCP2(I2PAppContext ctx, byte[] buffer, int offset, int len, I2NPMessageHandler handler) Read the message with a short 9-byte header.longDate after which the message should be dropped (and the associated uniqueId forgotten).intSerialized message size, including the 16-byte header.intThe raw header consists of a one-byte type and a 4-byte expiration in seconds only.longUnique id for this message, lazily initialized when negative.longgetUniqueId(long msgIDBloomXor) Replay resistant message Id.intreadBytes(byte[] data, int type, int offset) Read the header, then read the rest into buffer, then call readMessage in the implemented message type.intreadBytes(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.voidreadMessage(byte[] data, int offset, int dataSize, int type, I2NPMessageHandler handler) Read the message fields from the byte array, ignoring the handler.voidsetMessageExpiration(long exp) The expiration is set to one minute from now in the constructor but it can be overridden here.voidsetUniqueId(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.inttoByteArray(byte[] buffer) Write the message to the buffer, returning the number of bytes written.inttoByteArray(byte[] buffer, int off) Write the message to the buffer, returning the new offset (NOT the length).inttoRawByteArray(byte[] buffer) Write the message with a short 5-byte header.inttoRawByteArrayNTCP2(byte[] buffer, int off) Write the message to the buffer, returning the new offset (NOT the length).protected abstract intwriteMessageBody(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, waitMethods inherited from interface I2NPMessage
getType, readMessageModifier and TypeMethodDescriptionintgetType()Return the unique identifier for this type of I2NP message, as defined in the I2NP spec.voidreadMessage(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
Log for the message class, taken from the context's log manager._context
Application context this message belongs to._expiration
protected long _expirationExpiration time in milliseconds since the epoch, as an I2P Date._uniqueId
Warning, lazily initialized byreadBytes(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_MSDefault lifetime of an unsent message, one minute in milliseconds.- See Also:
CHECKSUM_LENGTH
public static final int CHECKSUM_LENGTHNumber of checksum bytes the message header carries.- See Also:
HEADER_LENGTH
public static final int HEADER_LENGTHI2NP message header size in bytes.- See Also:
_builders
Unused custom message-type builders.
Constructor Details
I2NPMessageImpl
Create an empty message with the default expiration.- Parameters:
context- the application context the message belongs to
Method Details
readBytes
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:
readBytesin interfaceI2NPMessage- Parameters:
data- the full serialized message, header includedtype- the message type or -1 if we should read it hereoffset- 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
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:
readBytesin interfaceI2NPMessage- Parameters:
data- the data, may or may not include the typetype- the message type or -1 if we should read it hereoffset- 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:
getUniqueIdin interfaceI2NPMessage- 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:
getUniqueIdin interfaceI2NPMessage- 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:
setUniqueIdin interfaceI2NPMessage- 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:
getMessageExpirationin interfaceI2NPMessage- 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:
setMessageExpirationin interfaceI2NPMessage- 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:
getMessageSizein interfaceI2NPMessage- 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:
getRawMessageSizein interfaceI2NPMessage- Returns:
- the raw message size
toByteArray
public byte[] toByteArray()The message serialized into a new byte array.- Specified by:
toByteArrayin interfaceI2NPMessage- 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:
toByteArrayin interfaceI2NPMessage- Parameters:
buffer- the destination array, which must have room forI2NPMessage.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:
toByteArrayin interfaceI2NPMessage- Parameters:
buffer- the destination array, which must have room forI2NPMessage.getMessageSize()bytes fromoffonoff- 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
Write the message body to the output array, starting at the given index.- Parameters:
out- the buffer to serialize the body intocurIndex- 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:
toRawByteArrayin interfaceI2NPMessage- Parameters:
buffer- the destination array, written from index 0, which must have room forI2NPMessage.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:
toRawByteArrayNTCP2in interfaceI2NPMessage- Parameters:
buffer- the destination array, which must have room forI2NPMessage.getRawMessageSize()bytes fromoffonoff- 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:
readMessagein interfaceI2NPMessage- Parameters:
data- the buffer holding the message, header includedoffset- where to start in the data arraydataSize- how long into the data to readtype- I2NP message typehandler- 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 callsetUniqueId(long)on the returned value. Used by SSU2 only!- Parameters:
ctx- the application context the resulting message belongs tobuffer- the serialized messageoffset- the index in buffer at which the 5-byte header startslen- the total number of readable bytes in buffer, at least 5handler- 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 tobuffer- the serialized messageoffset- the index in buffer at which the 9-byte header startslen- the total number of readable bytes in buffer, at least 9handler- 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
Yes, this is fairly ugly, but its the only place it ever happens.- Parameters:
context- the application context the message will belong totype- the I2NP message type byte- Returns:
- non-null, returns an UnknownI2NPMessage if unknown type