java.lang.Object
net.i2p.router.transport.udp.PacketBuilder2

class PacketBuilder2extends Object
Builds and encrypts SSU2 protocol packets for UDP transport. Handles all SSU2 message types including data packets, session establishment, peer testing, relay requests, and hole punching. Provides packet fragmentation, padding, and encryption for secure UDP communication.
  • Field Details

    • _context

      private final RouterContext _context
      The router context.
    • _log

      private final Log _log
      Logger for the packet builder.
    • _transport

      private final UDPTransport _transport
      The transport the packets go out on.
    • _blockPool

      private static final ThreadLocal<PacketBuilder2.BlockPool> _blockPool
      The block pool, one per thread.
    • TYPE_FIRST

      static final int TYPE_FIRST
      For debugging and stats only - does not go out on the wire. These are chosen to be higher than the highest I2NP message type, as a data packet is set to the underlying I2NP message type. SSU2 packet type constant for debugging/stats.
      See Also:
    • TYPE_ACK

      static final int TYPE_ACK
      SSU2 packet type constant for debugging/stats.
      See Also:
    • TYPE_PUNCH

      static final int TYPE_PUNCH
      SSU2 packet type constant for debugging/stats.
      See Also:
    • TYPE_RESP

      static final int TYPE_RESP
      SSU2 packet type constant for debugging/stats.
      See Also:
    • TYPE_INTRO

      static final int TYPE_INTRO
      SSU2 packet type constant for debugging/stats.
      See Also:
    • TYPE_RREQ

      static final int TYPE_RREQ
      SSU2 packet type constant for debugging/stats.
      See Also:
    • TYPE_TCB

      static final int TYPE_TCB
      SSU2 packet type constant for debugging/stats.
      See Also:
    • TYPE_TBC

      static final int TYPE_TBC
      SSU2 packet type constant for debugging/stats.
      See Also:
    • TYPE_TTA

      static final int TYPE_TTA
      SSU2 packet type constant for debugging/stats.
      See Also:
    • TYPE_TFA

      static final int TYPE_TFA
      SSU2 packet type constant for debugging/stats.
      See Also:
    • TYPE_CONF

      static final int TYPE_CONF
      SSU2 packet type constant for debugging/stats.
      See Also:
    • TYPE_SREQ

      static final int TYPE_SREQ
      SSU2 packet type constant for debugging/stats.
      See Also:
    • TYPE_CREAT

      static final int TYPE_CREAT
      SSU2 packet type constant for debugging/stats.
      See Also:
    • TYPE_DESTROY

      static final int TYPE_DESTROY
      SSU2 packet type constant for debugging/stats.
      See Also:
    • IP_HEADER_SIZE

      public static final int IP_HEADER_SIZE
      IPv4 only.
      See Also:
    • UDP_HEADER_SIZE

      public static final int UDP_HEADER_SIZE
      Same for IPv4 and IPv6.
      See Also:
    • MIN_DATA_PACKET_OVERHEAD

      public static final int MIN_DATA_PACKET_OVERHEAD
      Minimum IPv4 data packet overhead with MAC in bytes (60).
      See Also:
    • IPV6_HEADER_SIZE

      public static final int IPV6_HEADER_SIZE
      IPv6 header size in bytes.
      See Also:
    • MIN_IPV6_DATA_PACKET_OVERHEAD

      public static final int MIN_IPV6_DATA_PACKET_OVERHEAD
      Minimum IPv6 data packet overhead with MAC in bytes (80).
      See Also:
    • ABSOLUTE_MAX_ACK_RANGES

      private static final int ABSOLUTE_MAX_ACK_RANGES
      Most ack ranges allowed in one packet.
      See Also:
    • PRIORITY_HIGH

      static final int PRIORITY_HIGH
      Higher than all other OutNetMessage priorities, but still droppable, and will be shown in the codel.UDP-Sender.drop.500 stat.
      See Also:
    • PRIORITY_MEDIUM

      private static final int PRIORITY_MEDIUM
      Send priority of the medium class messages.
      See Also:
    • DATETIME_SEND_FREQUENCY

      private static final int DATETIME_SEND_FREQUENCY
      Packets between date and time blocks.
      See Also:
  • Constructor Details

    • PacketBuilder2

      public PacketBuilder2(RouterContext ctx, UDPTransport transport)
      No state, all methods are thread-safe.
      Parameters:
      ctx - router context for logging, randomness, and router identity
      transport - may be null for unit testing only
  • Method Details

    • getMaxAdditionalFragmentSize

      public static int getMaxAdditionalFragmentSize(PeerState peer, int numFragments, int curDataSize)
      Will a packet to 'peer' that already has 'numFragments' fragments totalling 'curDataSize' bytes fit another fragment? This includes the 3 byte block overhead, but NOT the 5 byte followon fragment overhead.

      This doesn't leave anything for acks or anything else.

      Parameters:
      peer - supplies the MTU and address family for the overhead
      numFragments - >= 1
      curDataSize - bytes of body already committed by those fragments
      Returns:
      max additional fragment size
    • fragmentDataSize

      static int fragmentDataSize(int fragmentSize, int fragment)
      Total bytes a single fragment contributes to a data packet body: the fragment payload plus the per-block header, plus the extra 5-byte overhead carried by follow-on fragments (fragment number and message ID).
      Parameters:
      fragmentSize - size of the fragment payload from OutboundMessageState.fragmentSize(int)
      fragment - 0 for the first fragment, > 0 for follow-ons
      Returns:
      total body bytes for this fragment
    • dataPacketHeaderSize

      static int dataPacketHeaderSize(boolean isIPv6)
      Size of the IP + UDP headers for a data packet to a peer. This excludes the SSU2 short packet header and MAC.
      Parameters:
      isIPv6 - true for IPv6 peers
      Returns:
      combined IP and UDP header size in bytes
    • dataPacketOverhead

      static int dataPacketOverhead(boolean isIPv6)
      Minimum fixed overhead (IP + UDP + short packet header + MAC) of a data packet, used to compute how much room remains for acks and body blocks at the peer's MTU.
      Parameters:
      isIPv6 - true for IPv6 peers
      Returns:
      MIN_IPV6_DATA_PACKET_OVERHEAD or MIN_DATA_PACKET_OVERHEAD
    • otherBlocksSize

      static int otherBlocksSize(List<SSU2Payload.Block> otherBlocks)
      Sum of the on-wire lengths of the non-fragment blocks to be appended to a data packet, used to budget ack space.
      Parameters:
      otherBlocks - may be null or empty
      Returns:
      total block lengths, 0 when null/empty
    • hasRoomForAckBlock

      static boolean hasRoomForAckBlock(int availableForAcks)
      Whether enough ack space remains to fit at least one ack range. An ack block needs its own block header plus a 5-byte first range.
      Parameters:
      availableForAcks - bytes free after the payload fragments
      Returns:
      true when an ack block can be emitted
    • maxAckRanges

      static int maxAckRanges(int availableForAcks)
      Maximum number of ack ranges that fit in the free space, capped at ABSOLUTE_MAX_ACK_RANGES. Each additional range costs 2 bytes.
      Parameters:
      availableForAcks - bytes free after the payload fragments
      Returns:
      range count, >= 0
    • isSingleFragment

      static boolean isSingleFragment(int fragment, int count)
      Whether a message is carried as a single I2NP block: the first fragment is also the only fragment.
      Parameters:
      fragment - fragment number within the message (0 = first)
      count - total fragments in the message
      Returns:
      true for a one-fragment message
    • isDateTimeSendPeriod

      static boolean isDateTimeSendPeriod(long packetNumber)
      Whether this packet number falls on the boundary where a DateTime block should be emitted (packetNumber % DATETIME_SEND_FREQUENCY == DATETIME_SEND_FREQUENCY - 1). Kept cheap via a power-of-two mask.
      Parameters:
      packetNumber - the packet's sequence number
      Returns:
      true to send a DateTime block
    • fitsDateTimeBlock

      static boolean fitsDateTimeBlock(int ipHeaderSize, int sizeWritten, int mtu)
      Whether a 7-byte DateTime block still fits in the packet at the peer's MTU, counting the short header and MAC that surround the body.
      Parameters:
      ipHeaderSize - IP + UDP header size for this peer
      sizeWritten - bytes written to the body so far
      mtu - the peer's current MTU
      Returns:
      true when the block fits
    • buildPacket

      public UDPPacket buildPacket(OutboundMessageState state, int fragment, PeerState2 peer) throws IOException
      This builds a data packet (PAYLOAD_TYPE_DATA). See the methods below for the other message types.

      Note that while the UDP message spec allows for more than one fragment in a message, this method writes exactly one fragment. For no fragments use buildAck().

      Parameters:
      state - the outbound message state
      fragment - fragment number within the message, 0 for the first
      peer - the destination session
      Returns:
      ready to send packet, non-null
      Throws:
      IOException - if peer is dead
    • buildPacket

      public UDPPacket buildPacket(List<PacketBuilder2.Fragment> fragments, PeerState2 peer) throws IOException
      Build a packet from multiple fragments.
      Parameters:
      fragments - one or more fragments of a message, in fragment order
      peer - the destination session
      Returns:
      ready to send packet, non-null
      Throws:
      IOException - if peer is dead
    • buildPacket

      public UDPPacket buildPacket(List<PacketBuilder2.Fragment> fragments, List<SSU2Payload.Block> otherBlocks, SSU2Sender peer) throws IOException
      Build a packet from multiple fragments and optional other blocks.
      Parameters:
      fragments - one or more fragments of a message, in fragment order; empty for an ack-only packet
      otherBlocks - may be null or empty
      peer - the destination session
      Returns:
      ready to send packet, non-null
      Throws:
      IOException - if peer is dead
    • buildPing

      public UDPPacket buildPing(PeerState2 peer) throws IOException
      A DATA packet with padding only. We use this for keepalive purposes.
      Parameters:
      peer - the destination session
      Returns:
      ready to send packet, or null if padding did not fit
      Throws:
      IOException - if peer is dead
    • buildACK

      public UDPPacket buildACK(PeerState2 peer) throws IOException
      Build the ack packet. An ack packet is just a data packet with no data. See buildPacket() for format.
      Parameters:
      peer - the destination session
      Returns:
      ready to send packet, non-null
      Throws:
      IOException - if peer is dead
    • buildSessionDestroyPacket

      public UDPPacket buildSessionDestroyPacket(int reason, SSU2Sender peer) throws IOException
      Build a data packet with a termination block. This will also include acks, a new token block, and padding.
      Parameters:
      reason - termination reason code (0-255), also recorded on the peer
      peer - the session being destroyed
      Returns:
      ready to send packet, non-null
      Throws:
      IOException - if peer is dead
    • buildTokenRequestPacket

      public UDPPacket buildTokenRequestPacket(OutboundEstablishState2 state)
      Build a new SessionRequest packet for the given peer, encrypting it as necessary.
      Parameters:
      state - the outbound establish state carrying conn IDs, version, and keys
      Returns:
      ready to send packet, non-null
    • buildSessionRequestPacket

      public UDPPacket buildSessionRequestPacket(OutboundEstablishState2 state)
      Build a new SessionRequest packet for the given peer, encrypting it as necessary.
      Parameters:
      state - the outbound establish state carrying conn IDs, token, and keys
      Returns:
      ready to send packet, non-null
    • buildSessionCreatedPacket

      public UDPPacket buildSessionCreatedPacket(InboundEstablishState2 state)
      Build a new SessionCreated packet for the given peer, encrypting it as necessary.
      Parameters:
      state - the inbound establish state carrying conn IDs and keys
      Returns:
      ready to send packet, non-null
    • buildRetryPacket

      public UDPPacket buildRetryPacket(InboundEstablishState2 state, int terminationCode)
      Build a new Retry packet for the given peer, encrypting it as necessary.
      Parameters:
      state - the inbound establish state carrying conn IDs and keys
      terminationCode - 0 normally, nonzero to send termination block
      Returns:
      ready to send packet, non-null
    • buildRetryPacket

      public UDPPacket buildRetryPacket(RemoteHostId to, SocketAddress toAddr, long destID, long srcID, int version, int terminationCode)
      Build a new Retry packet with a termination code, for a rejection direct from the EstablishmentManager. No InboundEstablishState2 required.
      Parameters:
      to - remote address family, supplying the IP and port for the address block
      toAddr - socket address to send the packet to
      destID - destination connection ID, or 0 when unknown
      srcID - our connection ID for the reply
      version - SSU2 protocol version of the peer
      terminationCode - must be greater than zero
      Returns:
      ready to send packet, non-null
    • buildSessionConfirmedPackets

      public UDPPacket[] buildSessionConfirmedPackets(OutboundEstablishState2 state, RouterInfo ourInfo)
      Build a new series of SessionConfirmed packets for the given peer, encrypting it as necessary.

      If the RI is large enough that it is fragmented, this will still only return a single Session Confirmed message. The remaining RI blocks will be passed to the establish state via confirmedPacketsSent(), and the state will transmit them via the new PeerState2.

      Parameters:
      state - the outbound establish state carrying conn IDs, keys, and MTU
      ourInfo - the RouterInfo to send, gzipped here if it shrinks
      Returns:
      ready to send packets, non-null
    • buildSessionConfirmedPacket

      private UDPPacket buildSessionConfirmedPacket(OutboundEstablishState2 state, SSU2Payload.RIBlock block)
      Build a single new SessionConfirmed packet for the given peer, unfragmented.
      Parameters:
      state - the in-progress outbound handshake state, source of the connection ID, header encryption keys, MTU and destination address
      block - the RouterInfo payload block to carry, not fragmented
      Returns:
      ready to send packet, non-null
    • buildSessionConfirmedPackets

      private UDPPacket[] buildSessionConfirmedPackets(OutboundEstablishState2 state, SSU2Payload.RIBlock block)
      Build all the fragmented SessionConfirmed packets.
      Parameters:
      state - the in-progress outbound handshake state, source of the connection ID, header encryption keys, MTU and destination address
      block - the RouterInfo payload block to split across the packets
      Returns:
      one packet per fragment, in fragment order, non-null
    • buildPeerTestFromAlice

      public UDPPacket buildPeerTestFromAlice(byte[] signedData, PeerState2 bob) throws IOException
      Build a packet as Alice, to Bob to begin a peer test. In-session, message 1.
      Parameters:
      signedData - flag + signed data
      bob - the destination session
      Returns:
      ready to send packet, non-null
      Throws:
      IOException - if peer is dead
    • buildPeerTestFromAlice

      public UDPPacket buildPeerTestFromAlice(InetAddress toIP, int toPort, SessionKey introKey, long sendID, long rcvID, byte[] signedData)
      Build a packet as Alice to Charlie. Out-of-session, message 6.
      Parameters:
      toIP - Charlie's IP, taken from the introducer that gave us Bob's current address; may be an IPv6 address
      toPort - Charlie's port, from that same introducer
      introKey - static introduction key used to encrypt the packet
      sendID - our connection ID
      rcvID - Charlie's connection ID
      signedData - flag + signed data
      Returns:
      ready to send packet, non-null
    • buildPeerTestToAlice

      public UDPPacket buildPeerTestToAlice(int code, Hash charlieHash, byte[] signedData, PeerState2 alice) throws IOException
      Build a packet as Bob to Alice, with the response from Charlie, or a rejection by Bob. In-session, message 4.
      Parameters:
      code - peer test response code from Charlie, or Bob's rejection code
      charlieHash - fake hash (all zeros) if rejected by bob
      signedData - flag + signed data
      alice - the destination session
      Returns:
      ready to send packet, non-null
      Throws:
      IOException - if peer is dead
    • buildPeerTestToAlice

      public UDPPacket buildPeerTestToAlice(int code, Hash charlieHash, byte[] signedData, SSU2Payload.Block riBlock, PeerState2 alice) throws IOException
      Build a packet as Bob to Alice, with the response from Charlie, or a rejection by Bob. In-session, message 4.
      Parameters:
      code - peer test response code from Charlie, or Bob's rejection code
      charlieHash - fake hash (all zeros) if rejected by bob
      signedData - flag + signed data
      riBlock - to include, may be null
      alice - the destination session
      Returns:
      ready to send packet, non-null
      Throws:
      IOException - if peer is dead
    • buildPeerTestToAlice

      public UDPPacket buildPeerTestToAlice(InetAddress aliceIP, int alicePort, SessionKey introKey, boolean firstSend, long sendID, long rcvID, byte[] signedData)
      Build a packet as Charlie to Alice. Out-of-session, messages 5 and 7.
      Parameters:
      aliceIP - Alice's IP, taken from the peer test we are replying to
      alicePort - Alice's port, from that same peer test
      introKey - static introduction key used to encrypt the packet
      firstSend - true for message 5, false for the message 7 retry
      sendID - our connection ID
      rcvID - Alice's connection ID
      signedData - flag + signed data
      Returns:
      ready to send packet, non-null
    • buildPeerTestToCharlie

      public UDPPacket buildPeerTestToCharlie(Hash aliceHash, byte[] signedData, SSU2Payload.Block riBlock, PeerState2 charlie) throws IOException
      Build a packet as Bob to Charlie to help test Alice. In-session, message 2.
      Parameters:
      aliceHash - hash of Alice's transient key, or all zeros if Alice is unknown
      signedData - flag + signed data
      riBlock - to include, may be null
      charlie - the destination session
      Returns:
      ready to send packet, non-null
      Throws:
      IOException - if peer is dead
    • buildPeerTestToBob

      public UDPPacket buildPeerTestToBob(int code, byte[] signedData, PeerState2 bob) throws IOException
      Build a packet as Charlie to Bob verifying that we will help test Alice. In-session, message 3.
      Parameters:
      code - peer test response code relayed from Charlie to Bob
      signedData - flag + signed data
      bob - the destination session
      Returns:
      ready to send packet, non-null
      Throws:
      IOException - if peer is dead
    • buildRelayRequest

      UDPPacket buildRelayRequest(byte[] signedData, PeerState2 bob) throws IOException
      From Alice to Bob. In-session.
      Parameters:
      signedData - flag + signed data
      bob - the destination session
      Returns:
      non-null
      Throws:
      IOException - if peer is dead
    • buildRelayIntro

      UDPPacket buildRelayIntro(byte[] signedData, SSU2Payload.Block riBlock, PeerState2 charlie) throws IOException
      From Bob to Charlie. In-session.
      Parameters:
      signedData - flag + alice hash + signed data
      riBlock - to include, may be null
      charlie - the destination session
      Returns:
      non-null
      Throws:
      IOException - if peer is dead
    • buildRelayResponse

      UDPPacket buildRelayResponse(byte[] signedData, PeerState2 state) throws IOException
      From Charlie to Bob or Bob to Alice. In-session.
      Parameters:
      signedData - flag + response code + signed data + optional token
      state - Alice or Bob
      Returns:
      non-null
      Throws:
      IOException - if peer is dead
    • buildHolePunch

      public UDPPacket buildHolePunch(InetAddress to, int port, SessionKey introKey, long sendID, long rcvID, byte[] signedData)
      Out-of-session, containing a RelayResponse block.
      Parameters:
      to - the peer's IP address
      port - the peer's port
      introKey - static introduction key used to encrypt the packet
      sendID - our connection ID
      rcvID - the peer's connection ID
      signedData - flag + response code + signed data + optional token
      Returns:
      ready to send packet, non-null
    • buildLongPacketHeader

      private UDPPacket buildLongPacketHeader(long destID, long pktNum, byte type, long srcID, long token, int version)
      Build the header block of a long SSU2 packet.
      Parameters:
      destID - peer's connection ID we are addressing, or 0 when not yet known
      pktNum - 0 - 0xFFFFFFFF
      type - packet type flag byte, written to header offset 12
      srcID - our connection ID, for the peer to address its reply to
      token - token echoed back to the peer, or 0 for none; only meaningful for the handshake and test packet types
      version - SSU2 protocol version of the peer, written to header offset 13
      Returns:
      a packet with the first 32 bytes filled in
    • buildShortPacketHeader

      private UDPPacket buildShortPacketHeader(long destID, long pktNum, byte type)
      Build the header block of a short SSU2 packet.
      Parameters:
      destID - peer's connection ID we are addressing, or 0 when not yet known
      pktNum - 0 - 0xFFFFFFFF
      type - packet type flag byte, written to header offset 12
      Returns:
      a packet with the first 16 bytes filled in
    • setTo

      private static void setTo(UDPPacket packet, InetAddress ip, int port)
      Sets the destination address of the packet.
      Parameters:
      packet - the packet to set
      ip - the destination address
      port - the destination port
    • handshakeWireSize

      static int handshakeWireSize(boolean isIPv6, int blockLen, int pqlen)
      On-wire size of a handshake packet before padding: the IP and UDP headers, the long header and ephemeral key, the PQ frame if any, the MAC, and the payload blocks written so far. A version 4 session request fills the minimum MTU with no padding at all - see PeerState2.MIN_MLKEM768_IPV4_MTU - so that version needs the exact figure to size its padding, while the others fit with room to spare.
      Parameters:
      isIPv6 - the address family of the packet
      blockLen - total length of the payload blocks written so far
      pqlen - the PQ frame length from SSU2Util.pqRequestExtra(int) or SSU2Util.pqCreatedExtra(int), 0 for version 2
      Returns:
      the total on-wire size in bytes
    • handshakePayloadOffset

      static int handshakePayloadOffset(int pqlen)
      Offset within the packet, measured from the start of the long header, where the plaintext payload blocks of a handshake message are staged. Noise writes the ephemeral key, and for the PQ versions the ML-KEM frame, into the message buffer before it reads the payload, so staging the blocks any earlier makes writeMessage() encrypt its own key material as the payload - a well-formed message whose blocks are garbage, with a tag that still verifies.
      Parameters:
      pqlen - the PQ frame length from SSU2Util.pqRequestExtra(int) or SSU2Util.pqCreatedExtra(int), 0 for version 2
      Returns:
      the staging offset from the start of the long header
    • handshakePaddingBase

      static int handshakePaddingBase(int version, boolean isIPv6, int blockLen, int pqlen)
      The size a handshake packet's padding budget is measured against. Version 4 needs the exact on-wire figure, because its ML-KEM frame already fills the minimum MTU; the other versions have room to spare and are measured against the payload blocks alone, as before the PQ work.
      Parameters:
      version - the negotiated SSU2 version
      isIPv6 - the address family of the packet
      blockLen - total length of the payload blocks written so far
      pqlen - the PQ frame length from SSU2Util.pqRequestExtra(int) or SSU2Util.pqCreatedExtra(int), 0 for version 2
      Returns:
      the size in bytes the padding budget is measured against
    • handshakePaddingMTU

      static int handshakePaddingMTU(int version, int mtu)
      The MTU a handshake packet's padding is sized against. Version 4 uses the peer's MTU, because its frame alone exceeds PeerState2.MIN_MTU; the other versions are sized against the minimum, as before the PQ work.
      Parameters:
      version - the negotiated SSU2 version
      mtu - the peer's MTU in bytes
      Returns:
      the MTU budget in bytes
    • addHandshakePadding

      private int addHandshakePadding(List<SSU2Payload.Block> blocks, int len, int version, boolean isIPv6, int pqlen, int mtu, int maxPadding)
      Adds the padding block a handshake packet can afford to the block list, returning the new payload length. The budget comes from the version's own geometry - see handshakePaddingBase(int, boolean, int, int) and handshakePaddingMTU(int, int) - and running out of room is not fatal, the packet simply goes out without padding.
      Parameters:
      blocks - the payload blocks staged so far, appended to if there is padding
      len - total length of those blocks
      version - the negotiated SSU2 version
      isIPv6 - the address family of the packet
      pqlen - the PQ frame length from SSU2Util.pqRequestExtra(int) or SSU2Util.pqCreatedExtra(int), 0 for version 2
      mtu - the peer's MTU in bytes
      maxPadding - the house cap on the padding for this message type
      Returns:
      the payload length, including the padding block if one was added
    • encryptSessionRequest

      private void encryptSessionRequest(UDPPacket packet, HandshakeState state, boolean isIPv6, int mtu, byte[] hdrKey1, byte[] hdrKey2, boolean needIntro, int version, Hash bob)
      Encrypt and write out message 1 of the handshake, the SessionRequest.
      Parameters:
      packet - containing only 32 byte header
      state - the Noise handshake state, already started with our ephemeral key pair
      isIPv6 - the peer's address family, for the version 4 padding budget
      mtu - the peer's MTU, for the version 4 padding budget
      hdrKey1 - 32-byte ChaCha20 key protecting header bytes 0-7
      hdrKey2 - 32-byte ChaCha20 key protecting header bytes 8-31
      needIntro - append a relay tag request block, for a peer that asked us to introduce it to a third peer
      version - the negotiated SSU2 version, 2 to 4
      bob - the peer's router hash, mixed into the handshake for the PQ versions, unused for version 2
    • encryptSessionCreated

      private void encryptSessionCreated(UDPPacket packet, HandshakeState state, int mtu, byte[] hdrKey1, byte[] hdrKey2, long relayTag, EstablishmentManager.Token token, byte[] ip, int port, int version)
      Encrypt and write out message 2 of the handshake, the SessionCreated.
      Parameters:
      packet - containing only 32 byte header
      state - the Noise handshake state, already started with our ephemeral key pair
      mtu - the peer's MTU, for the version 4 padding budget
      hdrKey1 - 32-byte ChaCha20 key protecting header bytes 0-7
      hdrKey2 - 32-byte ChaCha20 key protecting header bytes 8-31
      relayTag - relay tag for the peer to send us, or 0 to omit the relay tag block
      token - may be null
      ip - the peer's address for the address block, 4 or 16 bytes
      port - the peer's UDP port for the address block
      version - the negotiated SSU2 version, 2 to 4
    • encryptRetry

      private void encryptRetry(UDPPacket packet, byte[] chachaKey, long n, byte[] hdrKey1, byte[] hdrKey2, byte[] ip, int port, int terminationCode)
      Encrypt and write out the body of a Retry packet.
      Parameters:
      packet - containing only 32 byte header
      chachaKey - 32-byte ChaCha20-Poly1305 key for the payload, the static introduction key
      n - packet number from the header, also the payload nonce
      hdrKey1 - 32-byte ChaCha20 key protecting header bytes 0-7
      hdrKey2 - 32-byte ChaCha20 key protecting header bytes 8-31
      ip - the peer's address for the address block, 4 or 16 bytes
      port - the peer's UDP port for the address block
      terminationCode - 0 normally, nonzero to send termination block
    • encryptPeerTest

      private void encryptPeerTest(UDPPacket packet, byte[] chachaKey, long n, byte[] hdrKey1, byte[] hdrKey2, byte[] ip, int port, SSU2Payload.Block ptBlock)
      Also used for hole punch with a relay request block. Also used for retry with (usually) ptBlock = null.
      Parameters:
      packet - containing only 32 byte header
      chachaKey - 32-byte ChaCha20-Poly1305 key for the payload, the static introduction key
      n - packet number from the header, also the payload nonce
      hdrKey1 - 32-byte ChaCha20 key protecting header bytes 0-7
      hdrKey2 - 32-byte ChaCha20 key protecting header bytes 8-31
      ip - the recipient's address for the address block, 4 or 16 bytes
      port - the recipient's UDP port for the address block
      ptBlock - Peer Test or Relay Request block. Null for retry.
    • encryptTokenRequest

      private void encryptTokenRequest(UDPPacket packet, byte[] chachaKey, long n, byte[] hdrKey1, byte[] hdrKey2)
      Encrypt and write out the body of a Token Request packet.
      Parameters:
      packet - containing only 32 byte header
      chachaKey - 32-byte ChaCha20-Poly1305 key for the payload, the static introduction key
      n - packet number from the header, also the payload nonce
      hdrKey1 - 32-byte ChaCha20 key protecting header bytes 0-7
      hdrKey2 - 32-byte ChaCha20 key protecting header bytes 8-31
    • encryptSessionConfirmed

      private void encryptSessionConfirmed(UDPPacket packet, HandshakeState state, int mtu, int numFragments, int addPadding, boolean isIPv6, byte[] hdrKey1, byte[] hdrKey2, SSU2Payload.RIBlock riblock, EstablishmentManager.Token token)
      If numFragments larger than 1, we do NOT encrypt the header here, that's caller's responsibility.
      Parameters:
      packet - containing only 16 byte header
      state - the Noise handshake state, still open, that encrypts the payload in place
      mtu - peer's MTU in bytes, including the IP and UDP headers, which are subtracted here
      numFragments - total SessionConfirmed fragments, 1 - 15, written to the header flags byte
      addPadding - force-add exactly this size a padding block, for jumbo only
      isIPv6 - true to subtract the 40-byte IPv6 header from the MTU, false for the 20-byte IPv4 header
      hdrKey1 - 32-byte ChaCha20 key protecting header bytes 0-7
      hdrKey2 - 32-byte ChaCha20 key protecting header bytes 8-15
      riblock - the RouterInfo block to send, already built
      token - may be null
    • encryptDataPacket

      private void encryptDataPacket(UDPPacket packet, CipherState chacha, long n, byte[] hdrKey1, byte[] hdrKey2)
      Encrypts the payload of one data packet and appends the MAC.
      Parameters:
      packet - containing 16 byte header and all data with length set to the end of the data. This will extend the length by 16 for the MAC.
      chacha - the peer's send cipher state, locked for the duration of the encryption
      n - packet number from the header, also the payload nonce
      hdrKey1 - 32-byte ChaCha20 key protecting header bytes 0-7
      hdrKey2 - 32-byte ChaCha20 key protecting header bytes 8-15
    • getPadding

      private SSU2Payload.Block getPadding(int len, int max)
      Random padding block up to the maximum size.
      Parameters:
      len - current length of the packet including IP/UDP header (unless header subtracted from max) If len == 0 ensure 8 byte block minimum
      max - max length of the packet
      Returns:
      null if no room
    • getPadding

      private SSU2Payload.Block getPadding(int len, int max, int maxPadding)
      Random padding block with an explicit cap.
      Parameters:
      len - current length of the packet including IP/UDP header (unless header subtracted from max) If len == 0 ensure 8 byte block minimum
      max - max length of the packet
      maxPadding - max length of the padding (not including block header)
      Returns:
      null if no room
    • getMaxDataSize

      public static int getMaxDataSize(PeerState peer)
      Calculates the maximum payload size that can be sent to this peer in a single data packet.
      Parameters:
      peer - the destination session, may be null
      Returns:
      the max data size in bytes