Class PeerTestManager

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

class PeerTestManager extends Object
Entry points are runTest() to start a new test as Alice, and receiveTest() for all received test packets. IPv6 info: All Alice-Bob and Alice-Charlie communication is via IPv4. The Bob-Charlie communication may be via IPv6, however Charlie must be IPv4-capable. The IP address (of Alice) in the message must be IPv4 if present, as we only support testing of IPv4. Testing of IPv6 could be added in the future. From udp.html on the website:

The automation of collaborative reachability testing for peers is enabled by a sequence of PeerTest messages. With its proper execution, a peer will be able to determine their own reachability and may update its behavior accordingly. The testing process is quite simple:

        Alice                  Bob                  Charlie

    runTest()
    sendTestToBob()     receiveFromAliceAsBob()
    PeerTest ------------------->

                        sendTestToCharlie()       receiveFromBobAsCharlie()
                             PeerTest-------------------->

                        receiveFromCharlieAsBob()
                                <-------------------PeerTest

    receiveTestReply()
         <-------------------PeerTest

    receiveTestReply()
         <------------------------------------------PeerTest

                                                  receiveFromAliceAsCharlie()
    PeerTest------------------------------------------>

    receiveTestReply()
         <------------------------------------------PeerTest

Each of the PeerTest messages carry a nonce identifying the test series itself, as initialized by Alice. If Alice doesn't get a particular message that she expects, she will retransmit accordingly, and based upon the data received or the messages missing, she will know her reachability. The various end states that may be reached are as follows:

  • If she doesn't receive a response from Bob, she will retransmit up to a certain number of times, but if no response ever arrives, she will know that her firewall or NAT is somehow misconfigured, rejecting all inbound UDP packets even in direct response to an outbound packet. Alternately, Bob may be down or unable to get Charlie to reply.
  • If Alice doesn't receive a PeerTest message with the expected nonce from a third party (Charlie), she will retransmit her initial request to Bob up to a certain number of times, even if she has received Bob's reply already. If Charlie's first message still doesn't get through but Bob's does, she knows that she is behind a NAT or firewall that is rejecting unsolicited connection attempts and that port forwarding is not operating properly (the IP and port that Bob offered up should be forwarded).
  • If Alice receives Bob's PeerTest message and both of Charlie's PeerTest messages but the enclosed IP and port numbers in Bob's and Charlie's second messages don't match, she knows that she is behind a symmetric NAT, rewriting all of her outbound packets with different 'from' ports for each peer contacted. She will need to explicitly forward a port and always have that port exposed for remote connectivity, ignoring further port discovery.
  • If Alice receives Charlie's first message but not his second, she will retransmit her PeerTest message to Charlie up to a certain number of times, but if no response is received she knows that Charlie is either confused or no longer online.

Alice should choose Bob arbitrarily from known peers who seem to be capable of participating in peer tests. Bob in turn should choose Charlie arbitrarily from peers that he knows who seem to be capable of participating in peer tests and who are on a different IP from both Bob and Alice. If the first error condition occurs (Alice doesn't get PeerTest messages from Bob), Alice may decide to designate a new peer as Bob and try again with a different nonce.

Alice's introduction key is included in all of the PeerTest messages so that she doesn't need to already have an established session with Bob and so that Charlie can contact her without knowing any additional information. Alice may go on to establish a session with either Bob or Charlie, but it is not required.

  • Constructor Details

    • PeerTestManager

      public PeerTestManager(RouterContext context, UDPTransport transport)
      Have seen peer tests (as Alice) get stuck (_currentTest != null) so I've thrown some synchronizization on the methods; don't know the root cause or whether this fixes it
  • Method Details

    • runTest

      public void runTest(PeerState bob)
      The next few methods are for when we are Alice
      Parameters:
      bob - IPv4 only
    • receiveTest

      public void receiveTest(RemoteHostId from, PeerState fromPeer, boolean inSession, UDPPacketReader reader)
      Entry point for all incoming packets. Most of the source and dest validation is here. SSU 1 only. Receive a test message of some sort from the given peer, queueing up any packet that should be sent in response, or if its a reply to our own current testing, adjusting our test state. We could be Alice, Bob, or Charlie.
      Parameters:
      fromPeer - non-null if an associated session was found, otherwise null
      inSession - true if authenticated in-session
    • receiveTest

      public void receiveTest(RemoteHostId from, UDPPacket packet)
      Entry point for all out-of-session packets, messages 5-7 only. SSU 2 only. Receive a test message of some sort from the given peer, queueing up any packet that should be sent in response, or if its a reply to our own current testing, adjusting our test state. We could be Alice or Charlie.
      Parameters:
      from - non-null
      packet - header already decrypted
      Since:
      0.9.54
    • receiveTest

      public void receiveTest(RemoteHostId from, PeerState2 fromPeer, int msg, int status, Hash h, byte[] data)
      Entry point for all in-session incoming packets. SSU 2 only. Receive a test message of some sort from the given peer, queueing up any packet that should be sent in response, or if its a reply to our own current testing, adjusting our test state. We could be Alice, Bob, or Charlie.
      Parameters:
      from - non-null
      fromPeer - non-null if an associated session was found, otherwise null
      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
      Since:
      0.9.54
    • getAddress

      static RouterAddress getAddress(List<RouterAddress> addrs, boolean isIPv6)
      Get an address out of a list of addresses. SSU2 only.
      Returns:
      address or null
      Since:
      0.9.55
    • getIntroKey

      static SessionKey getIntroKey(RouterAddress ra)
      Get an intro key out of an address. SSU2 only.
      Since:
      0.9.54, pkg private since 0.9.55 for IntroManager