- Direct Known Subclasses:
PacketLocal
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):
FLAG_SYNCHRONIZE: no option dataFLAG_CLOSE: no option dataFLAG_RESET: no option dataFLAG_SIGNATURE_INCLUDED:SignatureFLAG_SIGNATURE_REQUESTED: no option dataFLAG_FROM_INCLUDED:DestinationFLAG_DELAY_REQUESTED: 2 byte integerFLAG_MAX_PACKET_SIZE_INCLUDED: 2 byte integerFLAG_PROFILE_INTERACTIVE: no option dataFLAG_ECHO: no option dataFLAG_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
FieldsModifier and TypeFieldDescriptionprotected long[]Sequence numbers the sender has not had acknowledged.protected SignatureDestination's signature made with the transient key of an offline block.protected DestinationSending destination, when that option is included.protected SignatureDestination's signature on the packet, when that option is included.protected final I2PSessionSession the packet travels over, set at construction.protected longWhen the offline signature's transient key stops being valid.protected SigningPublicKeyEphemeral signing public key taken from the offline signing block.static final intDEFAULT_MAX_SIZE.static final intThe sender of this packet will not be sending any more payload data.static final intThis packet includes an explicit request for the recipient to delay sending any packets with data for a given amount of time.static final intIf set, this packet is a ping (if sendStreamId is set) or a ping reply (if receiveStreamId is set).static final intThis packet includes the full I2P destination of the packet's sender.static final intThis packet includes a request that the recipient not send any subsequent packets with payloads greater than a specific size.static final intIf set, this packet doesn't really want to ack anything.static final intIf set, this packet is travelling as part of an interactive flow, meaning it is more lag sensitive than throughput sensitive.static final intThis 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 final intThis packet contains a DSA signature from the packet's sender.static final intIf set, an offline signing block is in the options.static final intThis packet wants the recipient to include signatures on subsequent packets sent to the creator of this packet.static final intThis 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 final intLargest delay in milliseconds a peer may request before being choked.static final intLargest payload a streaming packet may carry, in bytes.static final longLargest stream ID the 32-bit field can carry.static final intDelay request at or above which the peer is treated as choked.static final intDelay sent to a choked peer, asking it to pause roughly a minute.static final longThe 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
ConstructorsMethod Summary
Modifier and TypeMethodDescriptionAllocate a MAX_PAYLOAD_SIZE buffer for this packet.(package private) booleanalignSignatureToType(SigType type) Recast the signature to the signing key's type when the bytes we read are long enough to be a signature of that type.protected StringBuilderFormat as a string builder for logging, full form.protected StringBuilderformatAsString(boolean withContext) Format as a string builder for logging.longThe highest packet sequence number that received on the receiveStreamId.intLocal port.long[]getNacks()List of packet sequence numbers below the getAckThrough() value have not been received.intHow 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).Sender of the packet, only included if the flag for it is set.intWhat is the largest payload the sender of this packet wants to receive?The signature on the packet (only included if the flag for it is set)Actual payload of the message, may be null.intPayload size in bytes.longStream the replies should be sent on.intRemote port.intHow long is the creator of this packet going to wait before resending this packet (if it hasn't yet been ACKed).longStream we send data to the peer on.long0-indexed sequence number for this Packet in the sendStream.Return the session this packet belongs to.Transient signing public key, only if an offline signing block was included, else null.booleanisFlagSet(int flag) Is a particular flag set on this packet?voidlogTCPDump(Connection con) Generate a pcap/tcpdump-compatible format, so we can use standard debugging tools.voidreadPacket(byte[] buffer, int offset, int length) Read the packet from the buffer (starting at the offset) and return the number of bytes read.voidNo-op, payload buffers are garbage-collected, not pooled.voidsetAckThrough(long id) ACK-through value to set; if < 0, sets FLAG_NO_ACK.voidsetFlag(int flag) Marks the flag(s) set.voidsetFlag(int flag, boolean set) Marks the flag(s) set or clear.voidsetLocalPort(int port) Must be called to change the port, not set by readPacket() as the port is out-of-band in the I2CP header.voidsetNacks(long[] nacks) NACK list to set.voidsetOptionalDelay(int delayMs) Caller must also call setFlag(FLAG_DELAY_REQUESTED).voidsetOptionalMaxSize(int numBytes) This also sets flag FLAG_MAX_PACKET_SIZE_INCLUDED.voidThis also sets flag FLAG_SIGNATURE_INCLUDED.voidsetPayload(ByteArray payload) Payload to set.voidsetReceiveStreamId(long id) Stream the peer will send replies on.voidsetRemotePort(int port) Must be called to change the port, not set by readPacket() as the port is out-of-band in the I2CP header.voidsetResendDelay(int numSeconds) Unused.voidsetSendStreamId(long id) Stream the peer will receive data on.voidsetSequenceNum(long num) Sequence number to set.(package private) intsignatureSpaceLen(SigType keyType) How many option bytes to reserve for the signature when this packet is written, which is also how many bytes the signature covers.(package private) static final StringtoId(long id) Format a stream ID for display.toString()String representation of this packet.booleanverifySignature(I2PAppContext ctx, byte[] buffer) Determine whether the signature on the data is valid.booleanverifySignature(I2PAppContext ctx, SigningPublicKey altSPK, byte[] buffer) Determine whether the signature on the data is valid.intwritePacket(byte[] buffer, int offset) Write the packet to the buffer (starting at the offset) and return the number of bytes written.protected intwritePacket(byte[] buffer, int offset, int fakeSigLen) Write the packet to the buffer, leaving room for a fake signature if requested.(package private) intwrittenSize(SigType keyType) Size of this packet if written to a buffer.
Field Details
_session
Session the packet travels over, set at construction._nacks
protected long[] _nacksSequence numbers the sender has not had acknowledged._optionSignature
Destination's signature on the packet, when that option is included._optionFrom
Sending destination, when that option is included._transientExpires
protected long _transientExpiresWhen the offline signature's transient key stops being valid._offlineSignature
Destination's signature made with the transient key of an offline block._transientSigningPublicKey
Ephemeral signing public key taken from the offline signing block.STREAM_ID_UNKNOWN
public static final long STREAM_ID_UNKNOWNThe 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_IDLargest stream ID the 32-bit field can carry.- See Also:
FLAG_SYNCHRONIZE
public static final int FLAG_SYNCHRONIZEThis 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_CLOSEThe sender of this packet will not be sending any more payload data.- See Also:
FLAG_RESET
public static final int FLAG_RESETThis 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_INCLUDEDThis 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_REQUESTEDThis 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_INCLUDEDThis 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_REQUESTEDThis 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_INCLUDEDThis 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_INTERACTIVEIf 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_ECHOIf 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_ACKIf set, this packet doesn't really want to ack anything.- See Also:
FLAG_SIGNATURE_OFFLINE
public static final int FLAG_SIGNATURE_OFFLINEIf set, an offline signing block is in the options.- See Also:
DEFAULT_MAX_SIZE
public static final int DEFAULT_MAX_SIZEDEFAULT_MAX_SIZE. 32768 is the largest value the 2-byte max-size wire field can carry (toLong(buffer, cur, 2, ...)); 128K would silently truncate to 0. Matches mainline's encodable 32768.- See Also:
MAX_DELAY_REQUEST
protected static final int MAX_DELAY_REQUESTLargest delay in milliseconds a peer may request before being choked.- See Also:
MIN_DELAY_CHOKE
public static final int MIN_DELAY_CHOKEDelay request at or above which the peer is treated as choked.- See Also:
SEND_DELAY_CHOKE
public static final int SEND_DELAY_CHOKEDelay sent to a choked peer, asking it to pause roughly a minute.- See Also:
MAX_PAYLOAD_SIZE
public static final int MAX_PAYLOAD_SIZELargest payload a streaming packet may carry, in bytes.- See Also:
Constructor Details
Packet
Does no initialization. See readPacket() for inbound packets, and the setters for outbound packets.- Parameters:
session- the session this packet is sent or received on, or null before one is assigned
Method Details
getSession
Return the session this packet belongs to.- Returns:
- the session the packet is sent or received on
getSendStreamId
public long getSendStreamId()Stream we send data to the peer on.- Returns:
- stream ID we use to send data
setSendStreamId
public void setSendStreamId(long id) Stream the peer will receive data on.- Parameters:
id- the send stream ID to set- Throws:
RuntimeException- if the send stream ID has already been set to a different value
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) Stream the peer will send replies on.- Parameters:
id- the receive stream ID to set- Throws:
RuntimeException- if the receive stream ID has already been set to a different value
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) Sequence number to set.- Parameters:
num- the sequence number to set
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) ACK-through value to set; if < 0, sets FLAG_NO_ACK.- Parameters:
id- the ack through value to set, 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.Warning: This is different than getNACKs() in PacketLocal.
- Returns:
- List of packet sequence numbers not ACKed, or null if there are none.
setNacks
public void setNacks(long[] nacks) NACK list to set.- Parameters:
nacks- list of packet sequence numbers not ACKed, or null if there are none.
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.- Parameters:
numSeconds- the resend delay in seconds, ignored by this release
getPayload
Actual payload of the message, may be null.- Returns:
- the payload of the message, null if none.
setPayload
Payload to set.- Parameters:
payload- the payload to set, or null to clear- Throws:
IllegalArgumentException- if the payload exceeds MAX_PAYLOAD_SIZE
getPayloadSize
public int getPayloadSize()Payload size in bytes.- Returns:
- the size of the payload in bytes, or 0 if no payload
releasePayload
public void releasePayload()No-op, payload buffers are garbage-collected, not pooled.acquirePayload
Allocate a MAX_PAYLOAD_SIZE buffer for this packet.- Returns:
- a new ByteArray of MAX_PAYLOAD_SIZE for this packet
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) Marks the flag(s) set.- Parameters:
flag- bitmask of any flag(s)
setFlag
public void setFlag(int flag, boolean set) Marks the flag(s) set or clear.- Parameters:
flag- bitmask of any flag(s)set- true to set, false to clear
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
This also sets flag FLAG_SIGNATURE_INCLUDED.- Parameters:
sig- the signature to attach to the packet, or null to clear it and drop the flag
getOptionalFrom
Sender of the packet, only included if the flag for it is set.- Returns:
- the sending Destination
getTransientSPK
Transient signing public key, only if an offline signing block was included, else null.- Returns:
- the transient signing public key
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).- Parameters:
delayMs- how long the sender should be asked to wait in ms, clamped to 0..MAX_DELAY_REQUEST
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.- Parameters:
numBytes- the largest payload the sender should be told it may receive, or 0 to unset the flag
getLocalPort
public int getLocalPort()Local port.- Returns:
- Default I2PSession.PORT_UNSPECIFIED (0) or PORT_ANY (0)
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.- Parameters:
port- the local port to record, I2PSession.PORT_UNSPECIFIED (0) for unspecified or PORT_ANY (0) for any
getRemotePort
public int getRemotePort()Remote port.- Returns:
- Default I2PSession.PORT_UNSPECIFIED (0) or PORT_ANY (0)
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.- Parameters:
port- the remote port to record, I2PSession.PORT_UNSPECIFIED (0) for unspecified or PORT_ANY (0) for any
writePacket
Write the packet to the buffer (starting at the offset) and return the number of bytes written.- Parameters:
buffer- bytes to write to a destinationoffset- starting point in the buffer to send- Returns:
- Count actually written
- Throws:
IllegalStateException- if a required option is missing
writePacket
Write the packet to the buffer, leaving room for a fake signature if requested.- Parameters:
buffer- bytes to write to a destinationoffset- starting point in the buffer to sendfakeSigLen- if 0, include the real signature in _optionSignature; if nonzero, leave space for that many bytes- Returns:
- the number of bytes written
- Throws:
IllegalStateException- if a required option is missing
writtenSize
Size of this packet if written to a buffer.- Parameters:
keyType- the signing key's type, or null when it is not known yet- Returns:
- How large the current packet would be the same way
writePacket(byte[], int)will write it
signatureSpaceLen
How many option bytes to reserve for the signature when this packet is written, which is also how many bytes the signature covers.For a packet read from the network this is the number of option bytes the signature really occupied. That can be more than the signature length: without a FROM field the type is guessed from the option bytes left over (streaming spec, "Flags and Option Data Fields"), so a sender that padded the signature region makes the region look like a longer signature type. The padding is not signature data, but it is covered by the signature and has to be reproduced for verification to succeed.
- Parameters:
keyType- the signing key's type, or null when it is not known yet- Returns:
- option bytes to reserve for the signature, 0 if there is none
alignSignatureToType
Recast the signature to the signing key's type when the bytes we read are long enough to be a signature of that type.readPacket(byte[], int, int)cannot know the signature type when the packet carries no FROM field - a stray CLOSE or RESET packet - and guesses it from the option length. That guess is wrong whenever another type shares the length (ECDSA_SHA256_P256 and all the EdDSA types are 64 bytes) and whenever the sender padded the signature region, in which case the signature is the leadingtype.getSigLen()bytes and the rest is signed padding.- Parameters:
type- the signing key's type, non-null- Returns:
- true if
_optionSignatureis of that type afterwards, false if the bytes read cannot be a signature of that type
readPacket
Read the packet from the buffer (starting at the offset) and return the number of bytes read.- Parameters:
buffer- packet buffer containing the dataoffset- index into the buffer to start readinglength- how many bytes within the buffer past the offset are part of the packet?- Throws:
IllegalArgumentException- if the buffer is too small for the declared length, or the header is shorter than the minimumIndexOutOfBoundsException- if the data ends mid-packet
verifySignature
Determine whether the signature on the data is valid. Packet MUST have a FROM option or will return false.- Parameters:
ctx- the context supplying the DSA engine and loggerbuffer- 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
Determine whether the signature on the data is valid.- Parameters:
ctx- the context supplying the DSA engine and loggeraltSPK- 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
formatAsString
Format as a string builder for logging, full form.Not gated on the log level: every caller builds this from inside a log message that has already passed its own shouldXxx() test, so gating the description on INFO meant a WARN or ERROR about a packet logged an empty string - the one thing that makes such a message useless. The bulky parts (the NACK list, offline key material) stay behind shouldDebug(). The description is two lines: the header (stream IDs and sequence number), then one
" * "continuation line carrying the flags, options and payload size together.- Returns:
- a buffer holding the human readable form of this packet, ready to be appended to a log message
formatAsString
Format as a string builder for logging.- Parameters:
withContext- whenfalse, omit the facts the caller's own message already carries - the stream-ID header and the sequence number here, the send count and the connection pair inPacketLocal: a caller that leads with the connection prefix must not print them a second time- Returns:
- a buffer holding the human readable form of this packet, ready to be appended to a log message
toId
Format a stream ID for display.- Parameters:
id- the stream ID to format- Returns:
- base64-encoded stream ID without trailing '='
logTCPDump
Generate a pcap/tcpdump-compatible format, so we can use standard debugging tools.- Parameters:
con- the connection, may be null for unknown connections