net.i2p.router.transport.udp

## Class PacketBuilder2

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

-     class PacketBuilder2
      extends 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 Summary

    Fields
    Modifier and Type | Field and Description
    --- | ---
    `static int` | `IP_HEADER_SIZE` IPv4 only
    `static int` | `IPV6_HEADER_SIZE`
    `static int` | `MIN_DATA_PACKET_OVERHEAD` 60
    `static int` | `MIN_IPV6_DATA_PACKET_OVERHEAD` 80
    `(package private) static int` | `PRIORITY_HIGH`
    `(package private) static int` | `TYPE_ACK`
    `(package private) static int` | `TYPE_CONF`
    `(package private) static int` | `TYPE_CREAT`
    `(package private) static int` | `TYPE_DESTROY`
    `(package private) static int` | `TYPE_FIRST` For debugging and stats only - does not go out on the wire.
    `(package private) static int` | `TYPE_INTRO`
    `(package private) static int` | `TYPE_PUNCH`
    `(package private) static int` | `TYPE_RESP`
    `(package private) static int` | `TYPE_RREQ`
    `(package private) static int` | `TYPE_SREQ`
    `(package private) static int` | `TYPE_TBC`
    `(package private) static int` | `TYPE_TCB`
    `(package private) static int` | `TYPE_TFA`
    `(package private) static int` | `TYPE_TTA`
    `static int` | `UDP_HEADER_SIZE` Same for IPv4 and IPv6

  - ### Constructor Summary

    Constructors
    Constructor and Description
    `PacketBuilder2(RouterContext ctx, UDPTransport transport)` No state, all methods are thread-safe.

  - ### Method Summary

    All Methods Static Methods Instance Methods Concrete Methods
    Modifier and Type | Method and Description
    --- | ---
    `UDPPacket` | `buildACK(PeerState2 peer)` Build the ack packet.
    `UDPPacket` | `buildHolePunch(InetAddress to, int port, SessionKey introKey, long sendID, long rcvID, byte[] signedData)` Out-of-session, containing a RelayResponse block.
    `UDPPacket` | `buildPacket(List<PacketBuilder.Fragment> fragments, List<SSU2Payload.Block> otherBlocks, SSU2Sender peer)`
    `UDPPacket` | `buildPacket(List<PacketBuilder.Fragment> fragments, PeerState2 peer)`
    `UDPPacket` | `buildPacket(OutboundMessageState state, int fragment, PeerState2 peer)` This builds a data packet (PAYLOAD_TYPE_DATA).
    `UDPPacket` | `buildPeerTestFromAlice(byte[] signedData, PeerState2 bob)` Build a packet as Alice, to Bob to begin a peer test.
    `UDPPacket` | `buildPeerTestFromAlice(InetAddress toIP, int toPort, SessionKey introKey, long sendID, long rcvID, byte[] signedData)` Build a packet as Alice to Charlie.
    `UDPPacket` | `buildPeerTestToAlice(InetAddress aliceIP, int alicePort, SessionKey introKey, boolean firstSend, long sendID, long rcvID, byte[] signedData)` Build a packet as Charlie to Alice.
    `UDPPacket` | `buildPeerTestToAlice(int code, Hash charlieHash, byte[] signedData, PeerState2 alice)` Build a packet as Bob to Alice, with the response from Charlie, or a rejection by Bob.
    `UDPPacket` | `buildPeerTestToAlice(int code, Hash charlieHash, byte[] signedData, SSU2Payload.Block riBlock, PeerState2 alice)` Build a packet as Bob to Alice, with the response from Charlie, or a rejection by Bob.
    `UDPPacket` | `buildPeerTestToBob(int code, byte[] signedData, PeerState2 bob)` Build a packet as Charlie to Bob verifying that we will help test Alice.
    `UDPPacket` | `buildPeerTestToCharlie(Hash aliceHash, byte[] signedData, SSU2Payload.Block riBlock, PeerState2 charlie)` Build a packet as Bob to Charlie to help test Alice.
    `UDPPacket` | `buildPing(PeerState2 peer)` A DATA packet with padding only.
    `(package private) UDPPacket` | `buildRelayIntro(byte[] signedData, SSU2Payload.Block riBlock, PeerState2 charlie)` From Bob to Charlie.
    `(package private) UDPPacket` | `buildRelayRequest(byte[] signedData, PeerState2 bob)` From Alice to Bob.
    `(package private) UDPPacket` | `buildRelayResponse(byte[] signedData, PeerState2 state)` From Charlie to Bob or Bob to Alice.
    `UDPPacket` | `buildRetryPacket(InboundEstablishState2 state, int terminationCode)` Build a new Retry packet for the given peer, encrypting it as necessary.
    `UDPPacket` | `buildRetryPacket(RemoteHostId to, SocketAddress toAddr, long destID, long srcID, int terminationCode)` Build a new Retry packet with a termination code, for a rejection direct from the EstablishmentManager.
    `UDPPacket[]` | `buildSessionConfirmedPackets(OutboundEstablishState2 state, RouterInfo ourInfo)` Build a new series of SessionConfirmed packets for the given peer, encrypting it as necessary.
    `UDPPacket` | `buildSessionCreatedPacket(InboundEstablishState2 state)` Build a new SessionCreated packet for the given peer, encrypting it as necessary.
    `UDPPacket` | `buildSessionDestroyPacket(int reason, SSU2Sender peer)` Build a data packet with a termination block.
    `UDPPacket` | `buildSessionRequestPacket(OutboundEstablishState2 state)` Build a new SessionRequest packet for the given peer, encrypting it as necessary.
    `UDPPacket` | `buildTokenRequestPacket(OutboundEstablishState2 state)` Build a new SessionRequest packet for the given peer, encrypting it as necessary.
    `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.
    `static int` | `getMaxDataSize(PeerState peer)` Calculates the maximum payload size that can be sent to this peer in a single data packet.

    - ### Methods inherited from class java.lang.Object

      `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Field Detail

    - #### IP_HEADER_SIZE

          public static final int IP_HEADER_SIZE

      IPv4 only
      See Also:
        Constant Field Values

    - #### IPV6_HEADER_SIZE

          public static final int IPV6_HEADER_SIZE

      See Also:
        Constant Field Values

    - #### MIN_DATA_PACKET_OVERHEAD

          public static final int MIN_DATA_PACKET_OVERHEAD

      60
      See Also:
        Constant Field Values

    - #### MIN_IPV6_DATA_PACKET_OVERHEAD

          public static final int MIN_IPV6_DATA_PACKET_OVERHEAD

      80
      See Also:
        Constant Field Values

    - #### PRIORITY_HIGH

          static final int PRIORITY_HIGH

      See Also:
        Constant Field Values

    - #### TYPE_ACK

          static final int TYPE_ACK

      See Also:
        Constant Field Values

    - #### TYPE_CONF

          static final int TYPE_CONF

      See Also:
        Constant Field Values

    - #### TYPE_CREAT

          static final int TYPE_CREAT

      See Also:
        Constant Field Values

    - #### TYPE_DESTROY

          static final int TYPE_DESTROY

      See Also:
        Constant Field Values

    - #### 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.
      See Also:
        Constant Field Values

    - #### TYPE_INTRO

          static final int TYPE_INTRO

      See Also:
        Constant Field Values

    - #### TYPE_PUNCH

          static final int TYPE_PUNCH

      See Also:
        Constant Field Values

    - #### TYPE_RESP

          static final int TYPE_RESP

      See Also:
        Constant Field Values

    - #### TYPE_RREQ

          static final int TYPE_RREQ

      See Also:
        Constant Field Values

    - #### TYPE_SREQ

          static final int TYPE_SREQ

      See Also:
        Constant Field Values

    - #### TYPE_TBC

          static final int TYPE_TBC

      See Also:
        Constant Field Values

    - #### TYPE_TCB

          static final int TYPE_TCB

      See Also:
        Constant Field Values

    - #### TYPE_TFA

          static final int TYPE_TFA

      See Also:
        Constant Field Values

    - #### TYPE_TTA

          static final int TYPE_TTA

      See Also:
        Constant Field Values

    - #### UDP_HEADER_SIZE

          public static final int UDP_HEADER_SIZE

      Same for IPv4 and IPv6
      See Also:
        Constant Field Values

  - ### Constructor Detail

    - #### PacketBuilder2

          public PacketBuilder2(RouterContext ctx,
                                UDPTransport transport)

      No state, all methods are thread-safe.
      Parameters:
        `transport` - may be null for unit testing only

  - ### Method Detail

    - #### 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.
      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.

    - #### buildPacket

          public UDPPacket buildPacket(List<PacketBuilder.Fragment> fragments,
                                       List<SSU2Payload.Block> otherBlocks,
                                       SSU2Sender peer)
                                throws IOException

      Throws:
        `IOException`

    - #### buildPacket

          public UDPPacket buildPacket(List<PacketBuilder.Fragment> fragments,
                                       PeerState2 peer)
                                throws IOException

      Throws:
        `IOException`

    - #### 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().
      Throws:
        `IOException` - if peer is dead

    - #### 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.
      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.
      Returns:
        ready to send packet, non-null

    - #### 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.
      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:
        `charlieHash` - fake hash (all zeros) if rejected by bob
      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:
        `charlieHash` - fake hash (all zeros) if rejected by bob
        `riBlock` - to include, may be null
      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.
      Returns:
        ready to send packet, non-null
      Throws:
        `IOException` - if peer is dead

    - #### 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:
        `riBlock` - to include, may be null
      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.
      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
      Returns:
        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
      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

    - #### buildRetryPacket

          public UDPPacket buildRetryPacket(InboundEstablishState2 state,
                                            int terminationCode)

      Build a new Retry packet for the given peer, encrypting it as necessary.
      Parameters:
        `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 terminationCode)

      Build a new Retry packet with a termination code, for a rejection direct from the EstablishmentManager. No InboundEstablishState2 required.
      Parameters:
        `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.
      Returns:
        ready to send packets, non-null

    - #### buildSessionCreatedPacket

          public UDPPacket buildSessionCreatedPacket(InboundEstablishState2 state)

      Build a new SessionCreated packet for the given peer, encrypting it as necessary.
      Returns:
        ready to send packet, non-null

    - #### 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.
      Throws:
        `IOException` - if peer is dead

    - #### buildSessionRequestPacket

          public UDPPacket buildSessionRequestPacket(OutboundEstablishState2 state)

      Build a new SessionRequest packet for the given peer, encrypting it as necessary.
      Returns:
        ready to send packet, non-null

    - #### buildTokenRequestPacket

          public UDPPacket buildTokenRequestPacket(OutboundEstablishState2 state)

      Build a new SessionRequest packet for the given peer, encrypting it as necessary.
      Returns:
        ready to send packet, non-null

    - #### 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:
        `numFragments` - >= 1
      Returns:
        max additional fragment size

    - #### getMaxDataSize

          public static int getMaxDataSize(PeerState peer)

      Calculates the maximum payload size that can be sent to this peer in a single data packet.