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

class IntroductionManagerextends Object
Keep track of inbound and outbound introductions. See http://i2p-projekt.i2p/spec/ssu2 for documentation.
  • Field Details

    • _context

      private final RouterContext _context
      The router context.
    • _log

      private final Log _log
      Logger for the SSU introductions.
    • _transport

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

      private final PacketBuilder2 _builder2
      Builder for the SSU2 packets.
    • _outbound

      private final Map<Long, PeerState> _outbound
      Map of relay tag to Charlie PeerState that should receive the introduction (we are Bob).
    • _inbound

      private final Map<Long, PeerState> _inbound
      Map of relay tag to Bob PeerState who have given us introduction tags (we are Charlie).
    • _nonceToAlice

      private final ConcurrentHashMap<Long, PeerState2> _nonceToAlice
      Map of relay nonce to Alice PeerState who requested it.
    • _recentHolePunches

      private final Set<Long> _recentHolePunches
      Hole punch nonces recently sent.
    • _lastHolePunchClean

      private long _lastHolePunchClean
      When the hole punch set was last cleaned.
    • _recentRelaysAsBob

      private final Map<Long,Object> _recentRelaysAsBob
      Relay requests recently handled as Bob.
    • DUMMY

      private static final Object DUMMY
      Placeholder value for the relay map.
    • MAX_INBOUND

      private static final int MAX_INBOUND
      Limit since we ping to keep the conn open.
      See Also:
    • MAX_OUTBOUND

      public static final int MAX_OUTBOUND
      This is enforced in EstablishmentManager.
      See Also:
    • INTRODUCER_EXPIRATION

      private static final long INTRODUCER_EXPIRATION
      Time an introducer stays valid.
      See Also:
    • MIN_IPV6_INTRODUCER_VERSION

      private static final String MIN_IPV6_INTRODUCER_VERSION
      First version supporting IPv6 introducers.
      See Also:
    • MAX_SKEW

      private static final long MAX_SKEW
      Maximum clock skew accepted in an introduction.
      See Also:
    • PUNCH_CLEAN_TIME

      private static final long PUNCH_CLEAN_TIME
      Interval between hole punch cleanups.
      See Also:
    • MAX_PUNCHES

      private static final int MAX_PUNCHES
      Hole punches remembered at once.
      See Also:
  • Constructor Details

    • IntroductionManager

      public IntroductionManager(RouterContext ctx, UDPTransport transport)
      Creates the introduction manager.
      Parameters:
      ctx - the router context
      transport - the UDP transport it serves
  • Method Details

    • reset

      public void reset()
      Clear all introduction mappings.
    • add

      public void add(PeerState peer)
      Register the peer's relay tags.
      Parameters:
      peer - the peer whose tags are being registered
    • remove

      public void remove(PeerState peer)
      Unregister the peer's relay tags.
      Parameters:
      peer - the peer whose tags are being dropped
    • isInboundTagValid

      public boolean isInboundTagValid(long tag)
      Is this inbound tag currently valid, i.e. is the peer still connected?
      Parameters:
      tag - the relay tag to look up
      Returns:
      whether inbound tag valid
    • pickInbound

      public int pickInbound(RouterAddress current, boolean ipv6, Properties ssuOptions, int howMany)
      Grab a bunch of peers who are willing to be introducers for us that are locally known (duh) and have published their own SSU address (duh^2). The picked peers have their info tacked on to the ssuOptions parameter for use in the SSU RouterAddress.

      Try to use "good" peers (i.e. reachable, active)

      Also, ping all idle peers that were introducers in the last 2 hours, to keep the connection up, since the netDb can have quite stale information, and we want to keep our introducers valid.

      Parameters:
      current - current router address, may be null
      ipv6 - what type is the current address we need introducers for?
      ssuOptions - out parameter, options are added
      howMany - the most introducers to return
      Returns:
      number of introducers added
    • pingIntroducers

      public void pingIntroducers()
      Was part of pickInbound(RouterAddress, boolean, Properties, int), moved out so we can call it more often.
    • introducerCount

      int introducerCount(boolean ipv6)
      Not as elaborate as pickInbound() above. Just a quick check to see how many volunteers we know, which the Transport uses to see if we need more.
      Parameters:
      ipv6 - what type of address are they introducing us for
      Returns:
      number of peers that have volunteered to introduce us
    • introducedCount

      int introducedCount()
      Combined IPv4 and IPv6.
      Returns:
      number of peers we have volunteered to introduce
    • receiveRelayRequest

      void receiveRelayRequest(PeerState2 alice, byte[] data)
      We are Bob and we got this from Alice. Send Alice's RI and a RelayIntro to Charlie, or reject with a RelayResponse to Alice. We should already have a session with Charlie and definitely with Alice.

      SSU 2 only.

      Parameters:
      alice - the peer that asked us to relay
      data - the encrypted request, with the timestamp in the first 4 bytes
    • receiveRelayIntro

      void receiveRelayIntro(PeerState2 bob, Hash alice, byte[] data)
      Processes a relay introduction message received from another peer.

      This method is responsible for initiating a HolePunch to the specified destination peer ('Alice') and preparing a RelayResponse to be sent back to the originating peer ('Bob'). It is designed for use with the SSU 2 protocol.

      Parameters:
      bob - the PeerState2 instance representing the peer that sent the relay introduction message
      alice - the Hash object identifying the destination peer ('Alice') to which a HolePunch will be initiated
      data - the byte array containing the data payload of the relay introduction message
    • sendRelayRejectLimit

      private void sendRelayRejectLimit(PeerState2 bob, byte[] data)
      Sends a relay reject when Bob is over the limit.
      Parameters:
      bob - Bob's peer state
      data - the relay request data
    • receiveRelayIntro

      private boolean receiveRelayIntro(PeerState2 bob, Hash alice, byte[] data, int retryCount)
      We are Charlie and we got this from Bob. Bob should have sent us the RI, but maybe it's in the block after this, or maybe it's in a different packet. Check for RI, if not found, return true to retry, unless retryCount is at the limit. Creates the timer if retryCount == 0.

      SSU 2 only.

      Parameters:
      bob - the peer that relayed the introduction to us
      alice - the hash of the peer being introduced
      data - the relay intro payload to forward once Alice's RI is known
      retryCount - the number of retries so far, 0 on first receipt, retried up to 5 times
      Returns:
      false if Alice's RouterInfo is not yet available and the intro should be retried, true if the intro was processed
    • receiveRelayIntro

      private boolean receiveRelayIntro(PeerState2 bob, Hash alice, byte[] data, RouterInfo aliceRI)
      We are Charlie and we got this from Bob. Send a HolePunch to Alice, who will soon be sending us a SessionRequest. And send a RelayResponse to bob.

      SSU 2 only.

      Parameters:
      bob - the peer that relayed the introduction to us
      alice - the hash of the peer being introduced
      data - the signed relay intro payload to validate
      aliceRI - Alice's router info, or null if Bob did not deliver it
      Returns:
      true if a RelayResponse was sent to Bob, false if the intro was invalid or the reply could not be built
    • receiveRelayResponse

      void receiveRelayResponse(PeerState2 peer, int status, byte[] data)
      We are Bob and we got this from Charlie, OR we are Alice and we got this from Bob.

      If we are Bob, send to Alice. If we are Alice, send a SessionRequest to Charlie. We should already have a session with Charlie, but not necessarily with Alice.

      SSU 2 only.

      Parameters:
      peer - the peer that answered our relay request
      status - the status code the peer replied with
      data - the encrypted response, with the nonce and timestamp first
    • receiveHolePunch

      void receiveHolePunch(RemoteHostId charlie, byte[] data)
      We are Alice and we got this from Charlie. Send a SessionRequest to Charlie, whether or not we got the Relay Response already.

      SSU 2 only, out-of-session.

      Parameters:
      charlie - the peer we were relaying to
      data - the encrypted response, with the nonce and timestamp first
    • getAddress

      private RouterAddress getAddress(RouterInfo ri, boolean isIPv6)
      Address out of a RouterInfo. SSU2 only.
      Parameters:
      ri - the router info to take the address from
      isIPv6 - true to select an IPv6 address, false for IPv4
      Returns:
      address or null
    • isValid

      private boolean isValid(byte[] ip, int port, boolean allowIPv6)
      Are IP and port valid?
      Parameters:
      ip - the address bytes to check
      port - the port to check
      allowIPv6 - whether a 16-byte IPv6 address is acceptable
      Returns:
      true if the address and port form an acceptable introduction target
    • cleanup

      public void cleanup()
      Loop and cleanup _nonceToAlice Called from EstablishmentManager doFailSafe() so we don't need a cleaner timer here.