java.lang.Object
net.i2p.router.transport.udp.SSU2Payload
SSU2 Payload generation and parsing utilities.
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classBlock containing acknowledgment data.static classBlock containing IP address and port information.static classBase class for blocks to be transmitted.static classBlock containing the current date and time.static classSame format as I2NPBlock.static classFollow-on fragment block for SSU2 payload.static classBlock containing I2NP message data.static classBlock containing a new session token.static classBlock containing session options.static classBlock containing padding data.static classPath challenge block for SSU2 payload.static classPath response block for SSU2 payload.static interfaceFor all callbacks, recommend throwing exceptions only from the handshake.static classBlock containing peer test data.static classBlock containing relay introduction data.static classBlock containing relay request data.static classBlock containing relay response data.static classBlock containing relay tag data.static classBlock containing relay tag request data.static classBlock containing router information data.static classBlock containing session termination data.Field Summary
FieldsModifier and TypeFieldDescription(package private) static final intSSU2 block type: ACK.(package private) static final intSSU2 block type: ADDRESS.(package private) static final intSSU2 block type: DATETIME (must be the first block of a handshake).(package private) static final intSSU2 block type: FIRSTFRAG.(package private) static final intSSU2 block type: FOLLOWONFRAG.static final intBytes of type-and-length prefix that precede the data of every block.(package private) static final intSSU2 block type: I2NP.(package private) static final intSSU2 block type: NEWTOKEN.(package private) static final intSSU2 block type: OPTIONS.(package private) static final intSSU2 block type: PADDING (must end the block list).(package private) static final intSSU2 block type: PATHCHALLENGE.(package private) static final intSSU2 block type: PATHRESP.(package private) static final intSSU2 block type: PEERTEST.(package private) static final intSSU2 block type: RELAYINTRO.(package private) static final intSSU2 block type: RELAYREQ.(package private) static final intSSU2 block type: RELAYRESP.(package private) static final intSSU2 block type: RELAYTAG.(package private) static final intSSU2 block type: RELAYTAGREQ.(package private) static final intSSU2 block type: ROUTERINFO.static final intSSU2 block type: TERMINATION.Constructor Summary
ConstructorsModifierConstructorDescriptionprivateThe block writers and parsers below are static, and the only fields are block-type constants, so an instance carries nothing.Method Summary
Public MethodsModifier and TypeMethodDescription(package private) static voidcheckBlockOrder(int type, boolean gotPadding, boolean gotTermination, boolean isHandshake, int blocks) Order-rule guard for the incoming-block scan.(package private) static voidcheckFrameOverflow(int off, int length, int dataOff, int len, int blocks, int type) Guard that a block's declared length fits inside the frame.(package private) static voidcheckHandshakeNotEmpty(boolean isHandshake, int blocks) Guard that a handshake frame carries at least one block.(package private) static voidparseACK(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) Parse an ACK block (data blocks only).(package private) static voidparseAddress(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len) Parse an ADDRESS block of 4 bytes IPv4 or 16 bytes IPv6.(package private) static voidparseDateTime(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len) Parse a DATETIME block of exactly 4 bytes.(package private) static voidparseFirstFragment(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) Parse the first fragment of a fragmented message (data blocks only).(package private) static voidparseFollowonFragment(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) Parse a follow-on fragment block (data blocks only).(package private) static voidparseI2NP(I2PAppContext ctx, SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) Parse an I2NP block (data blocks only, never in handshakes).(package private) static voidparseNewToken(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len) Parse a NEWTOKEN block of at least 12 bytes: 4-byte expiry, 8-byte token.(package private) static voidparseOptions(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) Parse an OPTIONS block, copying the option bytes for the callback.(package private) static voidparsePathChallenge(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake, RemoteHostId from) Parse a PATHCHALLENGE block (data blocks only), passing the challenge array up with the originating address.(package private) static voidparsePathResponse(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake, RemoteHostId from) Parse a PATHRESP block (data blocks only), passing the response array up with the originating address.(package private) static voidparsePeerTest(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) Parse a PEERTEST block (data blocks only): message number, response code, an optional 32-byte hash for questions 2/4, and the data payload.(package private) static voidparseRelayIntro(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) Parse a RELAYINTRO block (data blocks only): 1 flag byte, the 32-byte introducer hash, then the intro data.(package private) static voidparseRelayRequest(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) Parse a RELAYREQ block (data blocks only): 1 flag byte then the relay request (IPv4 address + DSA signature).(package private) static voidparseRelayResponse(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) Parse a RELAYRESP block (data blocks only): 1 flag byte, 1 response code byte, and the remaining response data.(package private) static voidparseRelayTag(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len) Parse a RELAYTAG block of at least 4 bytes.(package private) static voidparseRouterInfo(I2PAppContext ctx, SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) Parse a ROUTERINFO block: one- or two-byte header, then either a single (possibly compressed) RouterInfo or a fragment piece.(package private) static RouterInfoRead a complete RouterInfo from the stream, falling back to an alternate signature verification when the strict parse fails.(package private) static voidparseTermination(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len) Parse a TERMINATION block of at least 9 bytes: 8-byte receive time, 1 byte reason code.(package private) static voidparseUnknown(I2PAppContext ctx, SSU2Payload.PayloadCallback cb, int type, int len) Unknown block type: warn once per occurrence and skip the block.static intprocessPayload(I2PAppContext ctx, SSU2Payload.PayloadCallback cb, byte[] payload, int off, int length, boolean isHandshake, RemoteHostId from) Incoming payload.(package private) static RouterInforecoverRouterInfo(I2PAppContext ctx, ByteArrayInputStream bais, DataFormatException dfe) Alternate verification of a RouterInfo whose strict parse failed: if the signed prefix is valid, return a partially filled-in RI (published = -1) so the session layer can still act on the identity.static intwritePayload(byte[] payload, int off, List<SSU2Payload.Block> blocks) Serialize a list of blocks into a payload.
Field Details
BLOCK_ACK
BLOCK_ADDRESS
BLOCK_DATETIME
static final int BLOCK_DATETIMESSU2 block type: DATETIME (must be the first block of a handshake).- See Also:
BLOCK_FIRSTFRAG
BLOCK_FOLLOWONFRAG
BLOCK_I2NP
BLOCK_NEWTOKEN
BLOCK_OPTIONS
BLOCK_PADDING
static final int BLOCK_PADDINGSSU2 block type: PADDING (must end the block list).- See Also:
BLOCK_PATHCHALLENGE
BLOCK_PATHRESP
BLOCK_PEERTEST
BLOCK_RELAYINTRO
BLOCK_RELAYREQ
BLOCK_RELAYRESP
BLOCK_RELAYTAG
BLOCK_RELAYTAGREQ
BLOCK_ROUTERINFO
BLOCK_HEADER_SIZE
public static final int BLOCK_HEADER_SIZEBytes of type-and-length prefix that precede the data of every block.- See Also:
BLOCK_TERMINATION
public static final int BLOCK_TERMINATIONSSU2 block type: TERMINATION.- See Also:
Constructor Details
SSU2Payload
private SSU2Payload()The block writers and parsers below are static, and the only fields are block-type constants, so an instance carries nothing.
Method Details
processPayload
public static int processPayload(I2PAppContext ctx, SSU2Payload.PayloadCallback cb, byte[] payload, int off, int length, boolean isHandshake, RemoteHostId from) throws IOException, DataFormatException, I2NPMessageException Incoming payload. Calls the callback for each received block.- Parameters:
ctx- the application contextcb- called once per received blockpayload- buffer holding the payloadoff- offset in payload of the first bytelength- number of bytes to readisHandshake- true for Token Req, Retry, Sess Req, Sess Created; false for Sess Confirmedfrom- for path challenge/response only, may be null- Returns:
- number of blocks processed
- Throws:
IOException- on major errorsDataFormatException- on parsing of individual blocksI2NPMessageException- on parsing of I2NP block
checkBlockOrder
static void checkBlockOrder(int type, boolean gotPadding, boolean gotTermination, boolean isHandshake, int blocks) throws IOException Order-rule guard for the incoming-block scan. Padding must terminate the block list; only padding may follow a termination block; a handshake must start with a DATETIME block. Each violation is a protocol error, thrown as an IOException.- Parameters:
type- the current block type bytegotPadding- true if a BLOCK_PADDING preceded this blockgotTermination- true if a BLOCK_TERMINATION preceded this blockisHandshake- true if this is a handshake frame, where the first block must be DATETIMEblocks- the number of blocks processed before this one- Throws:
IOException- on any ordering violation
checkHandshakeNotEmpty
Guard that a handshake frame carries at least one block.- Parameters:
isHandshake- true if this is a handshake frameblocks- the total number of blocks processed in the frame- Throws:
IOException- if the frame is a handshake with no blocks
checkFrameOverflow
static void checkFrameOverflow(int off, int length, int dataOff, int len, int blocks, int type) throws IOException Guard that a block's declared length fits inside the frame. Offsets in the error message are byte positions relative to the frame. The frame contents are deliberately not included, they may be decrypted data. Callers that want a dump log it at DEBUG.- Parameters:
off- start of the payload in the arraylength- frame size in bytesdataOff- offset of the block's 2-byte length fieldlen- the declared block lengthblocks- the zero-based index of this block for the error messagetype- the block type byte for the error message- Throws:
IOException- if the block runs past the end of the frame
parseDateTime
static void parseDateTime(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len) throws IOException, DataFormatException Parse a DATETIME block of exactly 4 bytes.- Parameters:
cb- callbackpayload- the whole framei- offset of the block datalen- declared block length, must be 4- Throws:
IOException- on bad lengthDataFormatException- if the callback rejects the timestamp
parseOptions
static void parseOptions(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) throws DataFormatException Parse an OPTIONS block, copying the option bytes for the callback.- Parameters:
cb- callbackpayload- the whole framei- offset of the block datalen- declared block lengthisHandshake- passed through to the callback- Throws:
DataFormatException- if the callback rejects the options
parseRouterInfo
static void parseRouterInfo(I2PAppContext ctx, SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) throws IOException, DataFormatException Parse a ROUTERINFO block: one- or two-byte header, then either a single (possibly compressed) RouterInfo or a fragment piece.- Parameters:
ctx- context for decompression and loggingcb- callbackpayload- the whole framei- offset of the block datalen- declared block length, must be > 1isHandshake- passed through to the callback- Throws:
IOException- on framing errorsDataFormatException- if the RouterInfo is too large or fails verification
parseRouterInfoSingle
static RouterInfo parseRouterInfoSingle(I2PAppContext ctx, ByteArrayInputStream bais) throws IOException, DataFormatException Read a complete RouterInfo from the stream, falling back to an alternate signature verification when the strict parse fails.- Parameters:
ctx- context for loggingbais- the RI bytes, positioned at the start- Returns:
- the parsed RouterInfo (possibly a partially filled-in one, signalled by
RouterInfo.setPublished(long)of -1) - Throws:
IOException- on any I/O while reading the streamDataFormatException- on a genuinely malformed RI that fails the alternate verification
recoverRouterInfo
static RouterInfo recoverRouterInfo(I2PAppContext ctx, ByteArrayInputStream bais, DataFormatException dfe) throws IOException, DataFormatException Alternate verification of a RouterInfo whose strict parse failed: if the signed prefix is valid, return a partially filled-in RI (published = -1) so the session layer can still act on the identity.- Parameters:
ctx- context for loggingbais- the RI bytes; position is reset for re-reading identity and signaturedfe- the original parse failure- Returns:
- a partially filled-in
RouterInfowhen the signature verifies - Throws:
IOException- on any I/O while re-reading the streamDataFormatException- the original parse failure when verification fails
parseI2NP
static void parseI2NP(I2PAppContext ctx, SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) throws IOException, I2NPMessageException Parse an I2NP block (data blocks only, never in handshakes).- Parameters:
ctx- context for I2NP parsingcb- callbackpayload- the whole framei- offset of the block datalen- declared block length, must be ≥ 9isHandshake- if true the block is illegal- Throws:
IOException- if the block appears in a handshake or is too shortI2NPMessageException- if the embedded I2NP message is malformed
parseFirstFragment
static void parseFirstFragment(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) throws IOException, DataFormatException Parse the first fragment of a fragmented message (data blocks only). The 1-byte flag and 4-byte message ID precede the fragment data; the callback receives the raw payload slice.- Parameters:
cb- callbackpayload- the whole framei- offset of the block datalen- declared block length, must be > 9isHandshake- if true the block is illegal- Throws:
IOException- if the block appears in a handshake or is too shortDataFormatException- if the callback rejects the fragment
parseFollowonFragment
static void parseFollowonFragment(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) throws IOException, DataFormatException Parse a follow-on fragment block (data blocks only). The low bit of the flag byte marks the last fragment; the remaining bits carry the fragment number.- Parameters:
cb- callbackpayload- the whole framei- offset of the block datalen- declared block length, must be > 5isHandshake- if true the block is illegal- Throws:
IOException- if the block appears in a handshake, is too short, or has fragment number 0DataFormatException- if the callback rejects the fragment
parseACK
static void parseACK(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) throws IOException Parse an ACK block (data blocks only). Odd block length: 4-byte ack ID, 1-byte fragment count, then the ACK range bitmap (possibly zero length).- Parameters:
cb- callbackpayload- the whole framei- offset of the block datalen- declared block length, must be ≥ 5 and oddisHandshake- if true the block is illegal- Throws:
IOException- if the block appears in a handshake or has a bad length
parseAddress
static void parseAddress(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len) throws IOException Parse an ADDRESS block of 4 bytes IPv4 or 16 bytes IPv6.- Parameters:
cb- callbackpayload- the whole framei- offset of the block datalen- declared block length, must be 6 or 18- Throws:
IOException- on bad length
parseRelayTag
static void parseRelayTag(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len) throws IOException Parse a RELAYTAG block of at least 4 bytes.- Parameters:
cb- callbackpayload- the whole framei- offset of the block datalen- declared block length, must be ≥ 4- Throws:
IOException- on bad length
parseRelayRequest
static void parseRelayRequest(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) throws IOException Parse a RELAYREQ block (data blocks only): 1 flag byte then the relay request (IPv4 address + DSA signature).- Parameters:
cb- callbackpayload- the whole framei- offset of the block datalen- declared block length, must be ≥ 61isHandshake- if true the block is illegal- Throws:
IOException- if the block appears in a handshake or is too short
parseRelayResponse
static void parseRelayResponse(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) throws IOException Parse a RELAYRESP block (data blocks only): 1 flag byte, 1 response code byte, and the remaining response data.- Parameters:
cb- callbackpayload- the whole framei- offset of the block datalen- declared block length, must be ≥ 52isHandshake- if true the block is illegal- Throws:
IOException- if the block appears in a handshake or is too short
parseRelayIntro
static void parseRelayIntro(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) throws IOException Parse a RELAYINTRO block (data blocks only): 1 flag byte, the 32-byte introducer hash, then the intro data.- Parameters:
cb- callbackpayload- the whole framei- offset of the block datalen- declared block length, must be ≥ 93isHandshake- if true the block is illegal- Throws:
IOException- if the block appears in a handshake or is too short
parsePeerTest
static void parsePeerTest(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake) throws IOException, DataFormatException Parse a PEERTEST block (data blocks only): message number, response code, an optional 32-byte hash for questions 2/4, and the data payload.- Parameters:
cb- callbackpayload- the whole framei- offset of the block datalen- declared block length, must be ≥ 19isHandshake- if true the block is illegal- Throws:
IOException- if the block appears in a handshake or is too shortDataFormatException- if the message number is out of the 1-7 range
parseNewToken
static void parseNewToken(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len) throws IOException Parse a NEWTOKEN block of at least 12 bytes: 4-byte expiry, 8-byte token.- Parameters:
cb- callbackpayload- the whole framei- offset of the block datalen- declared block length, must be ≥ 12- Throws:
IOException- on bad length
parseTermination
static void parseTermination(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len) throws IOException Parse a TERMINATION block of at least 9 bytes: 8-byte receive time, 1 byte reason code. The caller must flag the frame as terminated.- Parameters:
cb- callbackpayload- the whole framei- offset of the block datalen- declared block length, must be ≥ 9- Throws:
IOException- on bad length
parsePathChallenge
static void parsePathChallenge(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake, RemoteHostId from) throws IOException Parse a PATHCHALLENGE block (data blocks only), passing the challenge array up with the originating address.- Parameters:
cb- callbackpayload- the whole framei- offset of the block datalen- declared block lengthisHandshake- if true the block is illegalfrom- the originating address, may be null- Throws:
IOException- if the block appears in a handshake
parsePathResponse
static void parsePathResponse(SSU2Payload.PayloadCallback cb, byte[] payload, int i, int len, boolean isHandshake, RemoteHostId from) throws IOException Parse a PATHRESP block (data blocks only), passing the response array up with the originating address.- Parameters:
cb- callbackpayload- the whole framei- offset of the block datalen- declared block lengthisHandshake- if true the block is illegalfrom- the originating address, may be null- Throws:
IOException- if the block appears in a handshake
parseUnknown
Unknown block type: warn once per occurrence and skip the block.- Parameters:
ctx- context for loggingcb- callback, included in the message for contexttype- the unknown block type bytelen- the declared block length
writePayload
Serialize a list of blocks into a payload.- Parameters:
payload- writes to it starting at offoff- offset in payload to start writing atblocks- the blocks to write, in order- Returns:
- the new offset