java.lang.Object
net.i2p.router.transport.udp.OutboundEstablishState
net.i2p.router.transport.udp.OutboundEstablishState2
All Implemented Interfaces:
SSU2Payload.PayloadCallback

class OutboundEstablishState2extends OutboundEstablishState implements SSU2Payload.PayloadCallback
Data for a new connection being established, where we initiated the connection with a remote peer. In other words, we are Alice and they are Bob.

SSU2 only.

  • Field Details

    • _banLogger

      private final BanLogger _banLogger
      Records why routers were banned.
    • _bobSocketAddress

      private InetSocketAddress _bobSocketAddress
      Bob's socket address.
    • _transport

      private final UDPTransport _transport
      The SSU transport we serve.
    • _sendConnID

      private final long _sendConnID
      Connection id we send with.
    • _rcvConnID

      private final long _rcvConnID
      Connection id we receive with.
    • _routerAddress

      private final RouterAddress _routerAddress
      The router address being connected to.
    • _introducers

      private final Map<Hash, OutboundEstablishState2.IntroState> _introducers
      Introduction states, by introducer hash.
    • _token

      private long _token
      The handshake token echoed by Bob.
    • _handshakeState

      private HandshakeState _handshakeState
      Handshake state for the ratchet keys.
    • _version

      private final int _version
      Version of the handshake.
    • _headerEncryptKey1

      private final byte[] _headerEncryptKey1
      First header encryption key, Bob's introduction key, used for sending and receiving alike.
    • _sendHeaderEncryptKey2

      private byte[] _sendHeaderEncryptKey2
      Second header encryption key for sending.
    • _rcvHeaderEncryptKey2

      private byte[] _rcvHeaderEncryptKey2
      Second header encryption key for receiving.
    • _rcvRetryHeaderEncryptKey2

      private final byte[] _rcvRetryHeaderEncryptKey2
      Retry key for the second receive header.
    • _mtu

      private final int _mtu
      The MTU agreed for the new peer.
    • _sessReqForReTX

      private byte[] _sessReqForReTX
      Session Request packet held for retransmission.
    • _sessConfForReTX

      private byte[][] _sessConfForReTX
      Session Confirmed fragments for retransmission.
    • _timeReceived

      private long _timeReceived
      When the handshake started.
    • _skew

      private long _skew
      Our clock skew to Bob, in ms, not adjusted for RTT.
    • _pstate

      private PeerState2 _pstate
      The peer state being built, once created.
    • MAX_SKEW

      private static final long MAX_SKEW
      Maximum clock skew accepted in a handshake.
      See Also:
  • Constructor Details

    • OutboundEstablishState2

      public OutboundEstablishState2(RouterContext ctx, UDPTransport transport, RemoteHostId claimedAddress, RemoteHostId remoteHostId, RouterIdentity remotePeer, boolean needIntroduction, SessionKey introKey, RouterAddress ra, UDPAddress addr, int version) throws IllegalArgumentException
      Prepare to start a new handshake with the given peer.

      Caller must then check OutboundEstablishState.getState() and build a Token Request or Session Request to send to the peer.

      Parameters:
      ctx - the router context
      transport - the UDP transport
      claimedAddress - an IP/port based RemoteHostId, or null if unknown
      remoteHostId - non-null, == claimedAddress if direct, or a hash-based one if indirect
      remotePeer - must have supported sig type
      needIntroduction - should we ask Bob to be an introducer for us? ignored unless allowExtendedOptions is true
      introKey - Bob's introduction key, as published in the netdb
      ra - the router address
      addr - non-null
      version - the SSU2 version
      Throws:
      IllegalArgumentException
  • Method Details

    • introduced

      public void introduced(byte[] ip, int port, long token)
      After introduction.
      Parameters:
      ip - the IP address bytes
      port - the port number
      token - the token received
    • createNewState

      private void createNewState(RouterAddress addr)
      This will be called 0 times if we don't have a token and never get a retry; once if we have a token; and twice if the token we had was bad and we got a retry. We must regenerate the handshake state if we get a new token, because we only save the full encrypted packet for retransmission, and the encryption changes if the token does.

      caller must synch.

      Parameters:
      addr - the introducer's RouterAddress carrying the SSU2 keys and token
      Throws:
      IllegalArgumentException - if the address has no SSU2 static key option
    • processPayload

      private void processPayload(byte[] payload, int offset, int length, boolean isHandshake) throws GeneralSecurityException
      Processes one handshake payload.
      Parameters:
      payload - the packet payload
      offset - where the handshake data starts
      length - the handshake data length
      isHandshake - true for a handshake packet
      Throws:
      GeneralSecurityException - if the decryption or MAC fails
    • gotDateTime

      public void gotDateTime(long time)
      //////////////////////////////////////////////////////
      Specified by:
      gotDateTime in interface SSU2Payload.PayloadCallback
      Parameters:
      time - time in milliseconds since epoch
    • gotOptions

      public void gotOptions(byte[] options, boolean isHandshake)
      Description copied from interface: SSU2Payload.PayloadCallback
      Receive a session options block.
      Specified by:
      gotOptions in interface SSU2Payload.PayloadCallback
      Parameters:
      options - the option data
      isHandshake - true only for message 3 part 2
    • gotRI

      public void gotRI(RouterInfo ri, boolean isHandshake, boolean flood) throws DataFormatException
      Description copied from interface: SSU2Payload.PayloadCallback
      Receive a complete RouterInfo block.
      Specified by:
      gotRI in interface SSU2Payload.PayloadCallback
      Parameters:
      ri - will already be validated
      isHandshake - true only for message 3 part 2
      flood - true if this is a floodfill router
      Throws:
      DataFormatException - if the RouterInfo block is malformed
    • gotRIFragment

      public void gotRIFragment(byte[] data, boolean isHandshake, boolean flood, boolean isGzipped, int frag, int totalFrags)
      Description copied from interface: SSU2Payload.PayloadCallback
      Receive a fragment of a RouterInfo block.
      Specified by:
      gotRIFragment in interface SSU2Payload.PayloadCallback
      Parameters:
      data - is first gzipped and then fragmented
      isHandshake - true only for message 3 part 2
      flood - true if this is a floodfill router
      isGzipped - true if the data is gzipped
      frag - fragment number (0-based)
      totalFrags - total number of fragments
    • gotAddress

      public void gotAddress(byte[] ip, int port)
      Description copied from interface: SSU2Payload.PayloadCallback
      Receive an address block.
      Specified by:
      gotAddress in interface SSU2Payload.PayloadCallback
      Parameters:
      ip - IP address bytes
      port - the port number to send
    • gotRelayTagRequest

      public void gotRelayTagRequest()
      Description copied from interface: SSU2Payload.PayloadCallback
      Receive a relay tag request.
      Specified by:
      gotRelayTagRequest in interface SSU2Payload.PayloadCallback
    • gotRelayTag

      public void gotRelayTag(long tag)
      Description copied from interface: SSU2Payload.PayloadCallback
      Receive a relay tag.
      Specified by:
      gotRelayTag in interface SSU2Payload.PayloadCallback
      Parameters:
      tag - the relay tag
    • gotRelayRequest

      public void gotRelayRequest(byte[] data)
      Description copied from interface: SSU2Payload.PayloadCallback
      Receive a relay request.
      Specified by:
      gotRelayRequest in interface SSU2Payload.PayloadCallback
      Parameters:
      data - excludes flag, includes signature
    • gotRelayResponse

      public void gotRelayResponse(int status, byte[] data)
      Description copied from interface: SSU2Payload.PayloadCallback
      Receive a relay response.
      Specified by:
      gotRelayResponse in interface SSU2Payload.PayloadCallback
      Parameters:
      status - 0 = accept, 1-255 = reject
      data - excludes flag, includes signature
    • gotRelayIntro

      public void gotRelayIntro(Hash aliceHash, byte[] data)
      Description copied from interface: SSU2Payload.PayloadCallback
      Receive a relay introduction.
      Specified by:
      gotRelayIntro in interface SSU2Payload.PayloadCallback
      Parameters:
      aliceHash - hash of the introducer
      data - excludes flag, includes signature
    • gotPeerTest

      public void gotPeerTest(int msg, int status, Hash h, byte[] data)
      Description copied from interface: SSU2Payload.PayloadCallback
      Receive a peer test block.
      Specified by:
      gotPeerTest in interface SSU2Payload.PayloadCallback
      Parameters:
      msg - 1-7
      status - 0 = accept, 1-255 = reject
      h - Alice or Charlie hash for msg 2 and 4, null for msg 1, 3, 5-7
      data - excludes flag, includes signature
    • gotToken

      public void gotToken(long token, long expires)
      Description copied from interface: SSU2Payload.PayloadCallback
      Receive a new session token.
      Specified by:
      gotToken in interface SSU2Payload.PayloadCallback
      Parameters:
      token - the session token to attach to the next peer test
      expires - token expiration time in milliseconds
    • gotI2NP

      public void gotI2NP(I2NPMessage msg)
      Description copied from interface: SSU2Payload.PayloadCallback
      Receive an I2NP message block.
      Specified by:
      gotI2NP in interface SSU2Payload.PayloadCallback
      Parameters:
      msg - the parsed I2NP message
    • gotFragment

      public void gotFragment(byte[] data, int off, int len, long messageId, int frag, boolean isLast) throws DataFormatException
      Description copied from interface: SSU2Payload.PayloadCallback
      Receive a fragment of a fragmented message. Data must be copied out in this method. Data starts at the 9 byte header for fragment 0.
      Specified by:
      gotFragment in interface SSU2Payload.PayloadCallback
      Parameters:
      data - buffer containing fragment data
      off - offset in data
      len - length of data to copy
      messageId - unique message identifier
      frag - fragment number (0-based)
      isLast - whether this is the last fragment
      Throws:
      DataFormatException - if the fragment is malformed
    • gotACK

      public void gotACK(long ackThru, int acks, byte[] ranges)
      Description copied from interface: SSU2Payload.PayloadCallback
      Receive an acknowledgment block.
      Specified by:
      gotACK in interface SSU2Payload.PayloadCallback
      Parameters:
      ackThru - highest contiguous sequence number acknowledged
      acks - number of additional acknowledgments beyond ackThru
      ranges - null if none
    • gotTermination

      public void gotTermination(int reason, long count)
      Description copied from interface: SSU2Payload.PayloadCallback
      Receive a session termination block.
      Specified by:
      gotTermination in interface SSU2Payload.PayloadCallback
      Parameters:
      reason - termination reason code
      count - in theory could wrap around to negative, but very unlikely
    • gotPathChallenge

      public void gotPathChallenge(RemoteHostId from, byte[] data)
      Description copied from interface: SSU2Payload.PayloadCallback
      Receive a path challenge block.
      Specified by:
      gotPathChallenge in interface SSU2Payload.PayloadCallback
      Parameters:
      from - null if unknown
      data - the challenge bytes, which must be copied out
    • gotPathResponse

      public void gotPathResponse(RemoteHostId from, byte[] data)
      Description copied from interface: SSU2Payload.PayloadCallback
      Receive a path response block.
      Specified by:
      gotPathResponse in interface SSU2Payload.PayloadCallback
      Parameters:
      from - null if unknown
      data - the response bytes, which must be copied out
    • fail

      public void fail()
      Overridden from SSU1 to destroy the handshake state.
      Overrides:
      fail in class OutboundEstablishState
    • validateSessionCreated

      public boolean validateSessionCreated()
      Description copied from class: OutboundEstablishState
      Blocking call (run in the establisher thread) to determine if the session was created properly. If it wasn't, all the SessionCreated remnants are dropped (perhaps they were spoofed, etc) so that we can receive another one

      Generates session key and mac key.

      Overrides:
      validateSessionCreated in class OutboundEstablishState
      Returns:
      true if valid
    • receiveHolePunch

      boolean receiveHolePunch()
      Overridden because we don't have to wait for Relay Response first.
      Overrides:
      receiveHolePunch in class OutboundEstablishState
      Returns:
      true if we should send the SessionRequest now
    • getVersion

      public int getVersion()
      Description copied from class: OutboundEstablishState
      Version of the SSU protocol in use.
      Overrides:
      getVersion in class OutboundEstablishState
      Returns:
      the protocol version
    • getSendConnID

      public long getSendConnID()
      Connection ID we use when sending.
      Returns:
      the send connection ID
    • getRcvConnID

      public long getRcvConnID()
      Connection ID we receive from the peer.
      Returns:
      the receive connection ID
    • getToken

      public long getToken()
      Current session token.
      Returns:
      the current token
    • getNextToken

      public EstablishmentManager.Token getNextToken()
      Get the next token for this connection.
      Returns:
      may be null
    • getHandshakeState

      public HandshakeState getHandshakeState()
      Current handshake state.
      Returns:
      the handshake state
    • getSendHeaderEncryptKey1

      public byte[] getSendHeaderEncryptKey1()
      Header encryption key 1 for sending.
      Returns:
      the send header encrypt key 1
    • getRcvHeaderEncryptKey1

      public byte[] getRcvHeaderEncryptKey1()
      Header encryption key 1 for receiving.
      Returns:
      the receive header encrypt key 1
    • getSendHeaderEncryptKey2

      public byte[] getSendHeaderEncryptKey2()
      Header encryption key 2 for sending.
      Returns:
      the send header encrypt key 2
    • getRcvHeaderEncryptKey2

      public byte[] getRcvHeaderEncryptKey2()
      Header encryption key 2 for receiving.
      Returns:
      null before Session Request is sent (i.e. we sent a Token Request first)
    • getRcvRetryHeaderEncryptKey2

      public byte[] getRcvRetryHeaderEncryptKey2()
      Retry header encryption key 2 for receiving.
      Returns:
      the retry header encrypt key 2
    • getSentAddress

      public InetSocketAddress getSentAddress()
      Socket address we sent the session request to.
      Returns:
      the Bob socket address
    • getMTU

      public int getMTU()
      What is the largest packet we can send to the peer? His MTU, capped by ours. Only used for Session Confirmed packets. Session Request is very small, except for MLKEM768.
      Returns:
      the MTU in bytes
    • effectiveMTU

      static int effectiveMTU(int version, byte[] bobIP, int peerMTU, int ourMTU)
      The MTU to size a packet to this peer against: his MTU, capped by our own for that address family. IPv6, and a peer whose address family we do not know, is held to PeerState2.MIN_MTU to avoid PMTU problems on brokered IPv6 tunnels - the data phase probes and increases if possible. Version 4 is exempt, because its ML-KEM frame is already larger than that minimum and the version gate only negotiates it where the real MTU fits; clamping it would leave the handshake no padding room at all.
      Parameters:
      version - the negotiated SSU2 version
      bobIP - the peer's address bytes, 4 or 16 of them, null if unknown
      peerMTU - the peer's MTU in bytes
      ourMTU - our own MTU for that address family, 0 if unavailable
      Returns:
      the MTU in bytes to size packets against
    • receiveRetry

      public void receiveRetry(UDPPacket packet) throws GeneralSecurityException
      Receive a retry packet.
      Parameters:
      packet - the UDP packet received
      Throws:
      GeneralSecurityException - if the packet does not match the pending Retry request - wrong address, connection IDs, or an unexpected retry token - or carries a bad or zero DateTime block
    • locked_receiveRetry

      private void locked_receiveRetry(UDPPacket packet) throws GeneralSecurityException
      Process a Retry packet, with the lock held.
      Parameters:
      packet - the Retry packet from the peer
      Throws:
      GeneralSecurityException - if the source address does not match the configured one, or decrypting or validating the retry fails
    • receiveSessionCreated

      public void receiveSessionCreated(UDPPacket packet) throws GeneralSecurityException
      Receive a SessionCreated packet.
      Parameters:
      packet - the UDP packet received
      Throws:
      GeneralSecurityException - if the packet does not match the pending request - wrong address or connection IDs - or is missing its DateTime or address block, or exceeds the two minute skew limit
    • locked_receiveSessionCreated

      private void locked_receiveSessionCreated(UDPPacket packet) throws GeneralSecurityException
      Process SessionCreated, with the lock held.
      Parameters:
      packet - the SessionCreated packet from the peer
      Throws:
      GeneralSecurityException - if the source address does not match or decrypting or validating the response fails
    • tokenRequestSent

      public void tokenRequestSent(DatagramPacket packet)
      Note that we just sent a token request packet and save it for retransmission.
      Parameters:
      packet - the datagram packet sent
    • requestSent

      public void requestSent(DatagramPacket pkt)
      Note that we just sent the SessionRequest packet and save it for retransmission.
      Parameters:
      pkt - the datagram packet sent
    • confirmedPacketsSent

      public PeerState2 confirmedPacketsSent(UDPPacket[] packets)
      Note that we just sent the SessionConfirmed packets and save them for retransmission.
      Parameters:
      packets - the UDP packets sent
      Returns:
      the new PeerState2, may also be retrieved from getPeerState()
    • getRetransmitSessionRequestPacket

      public UDPPacket getRetransmitSessionRequestPacket()
      A packet to retransmit the SessionRequest.
      Returns:
      null if not sent or already got the session created
    • getPeerState

      public PeerState2 getPeerState()
      The peer state for this connection.
      Returns:
      null if we have not sent the session confirmed
    • getIntroState

      public OutboundEstablishState2.IntroState getIntroState(Hash h)
      The current state for the SSU2 introducer specified.
      Parameters:
      h - the introducer hash
      Returns:
      non-null current state for the SSU2 introducer specified, or INTRO_STATE_INVALID if peer is not an SSU2 introducer
    • setIntroState

      public void setIntroState(Hash h, OutboundEstablishState2.IntroState state)
      The current state for the SSU2 introducer specified.
      Parameters:
      h - the introducer hash
      state - the new state
    • introSent

      public void introSent(Hash h)
      A relay request was sent to the SSU2 introducer specified.
      Parameters:
      h - the introducer hash
    • toShortString

      String toShortString()
      Compact one-line establish-state identifier for log output: peer hash and current state. No lifetime or introducer details, no newlines.
      Returns:
      the peer hash and state, on one line
    • toString

      public String toString()
      Description copied from class: OutboundEstablishState
      String representation.
      Overrides:
      toString in class OutboundEstablishState
    • countIntroducers

      public int countIntroducers()
      Number of current introducers.
      Returns:
      the number of introducers
    • _x

      private static final String _x(String s)
      Mark a string for extraction by xgettext and translation. Use this only in static initializers. It does not translate!
      Parameters:
      s - the string to mark for extraction
      Returns:
      the string unchanged and untranslated