Class IntroductionManager

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

class IntroductionManager extends Object
Keep track of inbound and outbound introductions. IPv6 info: Alice-Bob communication may be via IPv4 or IPv6. Bob-Charlie communication must be via established IPv4 session as that's the only way that Bob knows Charlie's IPv4 address to give it to Alice. Alice-Charlie communication is via IPv4. If Alice-Bob is over IPv6, Alice must include her IPv4 address in the RelayRequest message. From udp.html on the website:

Indirect session establishment by means of a third party introduction is necessary for efficient NAT traversal. Charlie, a router behind a NAT or firewall which does not allow unsolicited inbound UDP packets, first contacts a few peers, choosing some to serve as introducers. Each of these peers (Bob, Bill, Betty, etc) provide Charlie with an introduction tag - a 4 byte random number - which he then makes available to the public as methods of contacting him. Alice, a router who has Charlie's published contact methods, first sends a RelayRequest packet to one or more of the introducers, asking each to introduce her to Charlie (offering the introduction tag to identify Charlie). Bob then forwards a RelayIntro packet to Charlie including Alice's public IP and port number, then sends Alice back a RelayResponse packet containing Charlie's public IP and port number. When Charlie receives the RelayIntro packet, he sends off a small random packet to Alice's IP and port (poking a hole in his NAT/firewall), and when Alice receives Bob's RelayResponse packet, she begins a new full direction session establishment with the specified IP and port.

Alice first connects to introducer Bob, who relays the request to Charlie.

        Alice                         Bob                  Charlie
    RelayRequest ---------------------->
         <-------------- RelayResponse    RelayIntro ----------->
         <-------------------------------------------- HolePunch (data ignored)
    SessionRequest -------------------------------------------->
         <-------------------------------------------- SessionCreated
    SessionConfirmed ------------------------------------------>
         <-------------------------------------------- DeliveryStatusMessage
         <-------------------------------------------- DatabaseStoreMessage
    DatabaseStoreMessage -------------------------------------->
    Data <--------------------------------------------------> Data

After the hole punch, the session is established between Alice and Charlie as in a direct establishment.

  • Field Details

    • MAX_OUTBOUND

      public static final int MAX_OUTBOUND
      This is enforced in EstablishmentManager
      Since:
      0.8.11
      See Also:
  • Constructor Details

  • Method Details

    • reset

      public void reset()
    • add

      public void add(PeerState peer)
    • remove

      public void remove(PeerState peer)
    • isInboundTagValid

      public boolean isInboundTagValid(long tag)
      Is this inbound tag currently valid, i.e. is the peer still connected?
      Since:
      0.9.50
    • 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
      Returns:
      number of introducers added
    • pingIntroducers

      public void pingIntroducers()
      Was part of pickInbound(), moved out so we can call it more often
      Since:
      0.8.11
    • 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
      Since:
      0.9.3
    • receiveRelayIntro

      void receiveRelayIntro(RemoteHostId bob, UDPPacketReader reader)
      We are Charlie and we got this from Bob. Send a HolePunch to Alice, who will soon be sending us a SessionRequest. We should already have a session with Bob, but probably not with Alice. If we don't have a session with Bob, we removed the relay tag from our _outbound table, so this won't work. We do some throttling here. SSU 1 only.
    • receiveRelayRequest

      void receiveRelayRequest(RemoteHostId alice, UDPPacketReader reader)
      We are Bob and we got this from Alice. Send a RelayIntro to Charlie and a RelayResponse to Alice. We should already have a session with Charlie, but not necessarily with Alice. SSU 1 only.
    • 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.
      Since:
      0.9.55
    • receiveRelayIntro

      void receiveRelayIntro(PeerState2 bob, Hash alice, byte[] data)
      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.
      Since:
      0.9.55
    • 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.
      Since:
      0.9.55
    • 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.
      Since:
      0.9.55