Class 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
        sendTestToBob()     receiveFromAliceAsBob()
        PeerTest ------------------->
                            sendTestToCharlie()       receiveFromBobAsCharlie()

    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 Detail

      • 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 Detail

      • runTest

        public void runTest​(InetAddress bobIP,
                            int bobPort,
                            SessionKey bobCipherKey,
                            SessionKey bobMACKey)
        The next few methods are for when we are Alice
        bobIP - IPv4 only
      • receiveTest

        public void receiveTest​(RemoteHostId from,
                                UDPPacketReader reader)
        Entry point for all incoming packets. Most of the source and dest validation is here. 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.