java.lang.Object
net.i2p.data.i2np.I2NPMessageImpl
net.i2p.data.i2np.FastI2NPMessageImpl
net.i2p.data.i2np.TunnelDataMessage
- All Implemented Interfaces:
I2NPMessage
Defines the message sent between routers as part of the tunnel delivery
The tunnel ID is changed in-place by TunnelParticipant.send(), so we can't reuse the checksum on output, but we still subclass FastI2NPMessageImpl so we don't verify the checksum on input... because this is a high-usage class.
Nested Class Summary
Nested classes/interfaces inherited from class I2NPMessageImpl
I2NPMessageImpl.BuilderModifier and TypeClassDescriptionstatic interfaceInterface for extending the types of messages handled - unused.Field Summary
Modifier and TypeFieldDescriptionprivate static final ByteCachePooled buffers for message payloads.private byte[]The message's payload bytes.private ByteArrayThe payload as a buffer, for reuse.private booleanFor use-after-free checks.private longThe tunnel this message is routed on.private TunnelIdThe tunnel id in object form.static final intSize of the data payload in bytes.private static final intIf we can't deliver a tunnel message in 10s, forget it.static final intMessage type ID for this I2NP message.private static final booleanWhen true, this tunnelDataMessage is used as part of a tunnel processing pipeline.Fields inherited from class FastI2NPMessageImpl
_checksum, _hasChecksumModifier and TypeFieldDescriptionprotected byteOne-byte checksum.protected booleanWhether the message includes a checksum.Fields inherited from class I2NPMessageImpl
_context, _expiration, _log, CHECKSUM_LENGTH, DEFAULT_EXPIRATION_MS, HEADER_LENGTHModifier and TypeFieldDescriptionprotected 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.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
ConstructorsConstructorDescriptionTunnelDataMessage(I2PAppContext context) Constructor with 10-second message expiration from context clock.Method Summary
Public MethodsModifier and TypeMethodDescriptionprotected intCalculate the message body's length (not including the header and footer).booleanTwo TunnelDataMessages are equal if they have the same tunnel ID and data.byte[]getData()The payload this message carries, for a message already read or written.longNumeric form of the tunnel ID, for callers that cannot use aTunnelId.TheTunnelIdform of the tunnel ID, built once and then cached.intgetType()Return the type.inthashCode()Hash based on tunnel ID and data payload.voidreadMessage(byte[] data, int offset, int dataSize, int type) Read and parse the message from raw data into fields.voidsetData(byte[] data) Tunnel payload; may only be set once.voidsetTunnelId(long id) (correctly) Invalidates stored checksum.voidsetTunnelId(TunnelId id) (correctly) Invalidates stored checksum.byte[]Serialized message bytes with header and footer.toString()Label with unique ID for logging.protected intwriteMessageBody(byte[] out, int curIndex) Write the message body to the output array, starting at the given index.Methods inherited from class FastI2NPMessageImpl
readBytes, toByteArray, toByteArrayWithSavedChecksumModifier and TypeMethodDescriptionintreadBytes(byte[] data, int type, int offset, int maxLen) Ignore, but save, the checksum, to be used later if necessary.inttoByteArray(byte[] buffer) If available, use the previously-computed or previously-read checksum for speed.protected inttoByteArrayWithSavedChecksum(byte[] buffer) Use a previously-computed checksum for speed.Methods inherited from class I2NPMessageImpl
createMessage, fromRawByteArray, fromRawByteArrayNTCP2, getMessageExpiration, getMessageSize, getRawMessageSize, getUniqueId, getUniqueId, readBytes, readMessage, setMessageExpiration, setUniqueId, toByteArray, toRawByteArray, toRawByteArrayNTCP2Modifier and TypeMethodDescriptionstatic 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.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.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).
Field Details
_tunnelId
private long _tunnelIdThe tunnel this message is routed on._tunnelIdObj
The tunnel id in object form._data
private byte[] _dataThe message's payload bytes._dataBuf
The payload as a buffer, for reuse.MESSAGE_TYPE
public static final int MESSAGE_TYPEMessage type ID for this I2NP message.- See Also:
DATA_SIZE
EXPIRATION_PERIOD
private static final int EXPIRATION_PERIODIf we can't deliver a tunnel message in 10s, forget it.- See Also:
_cache
Pooled buffers for message payloads.PIPELINED_CACHE
private static final boolean PIPELINED_CACHEWhen true, this tunnelDataMessage is used as part of a tunnel processing pipeline. The byte array is acquired during the TunnelDataMessage's creation (per readMessage), held onto through several transitions (updating and moving that array between different TunnelDataMessage instances or the fragment handler's cache, etc.), until it is finally released back into the cache when written to the next peer (or explicitly by the fragment handler's completion). Setting this to false just increases memory churn.This is tricky to get right and avoid data corruption.
- See Also:
_hadCache
private boolean _hadCacheFor use-after-free checks. Always false if PIPELINED_CACHE is false.
Constructor Details
TunnelDataMessage
Constructor with 10-second message expiration from context clock.- Parameters:
context- the context whose clock supplies the expiration stamp
Method Details
getTunnelId
public long getTunnelId()Numeric form of the tunnel ID, for callers that cannot use aTunnelId.- Returns:
- the tunnel this data message is addressed to
setTunnelId
public void setTunnelId(long id) (correctly) Invalidates stored checksum.- Parameters:
id- the tunnel to address; assigning it invalidates the cached checksum
getTunnelIdObj
setTunnelId
(correctly) Invalidates stored checksum.- Parameters:
id- the tunnel to address; assigning it invalidates the cached checksum
getData
public byte[] getData()The payload this message carries, for a message already read or written.- Returns:
- the tunnel payload bytes
setData
public void setData(byte[] data) Tunnel payload; may only be set once.- Parameters:
data- the payload to carry; must be non-empty and may only be assigned once- Throws:
IllegalStateException- if data previously set, to protect saved checksum
readMessage
public void readMessage(byte[] data, int offset, int dataSize, int type) throws I2NPMessageException Read and parse the message from raw data into fields.- Parameters:
data- data to read fromoffset- where to start in the data arraydataSize- how long into the data to readtype- I2NP message type- Throws:
I2NPMessageException- if the stream doesn't contain a valid message that this class can read.
calculateWrittenLength
protected int calculateWrittenLength()Calculate the message body's length (not including the header and footer).- Specified by:
calculateWrittenLengthin classI2NPMessageImpl- 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.- Specified by:
writeMessageBodyin classI2NPMessageImpl- 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
getType
public int getType()Return the type.- Returns:
- the message type number, as defined in the I2NP spec
hashCode
equals
toByteArray
public byte[] toByteArray()Serialized message bytes with header and footer.- Specified by:
toByteArrayin interfaceI2NPMessage- Overrides:
toByteArrayin classI2NPMessageImpl- Returns:
- a new array holding the whole message, full 16 byte header included
toString