예제 #1
0
    def restore_exitnodes_from_disk(self):
        """
        Send introduction requests to peers stored in the file self.exitnode_cache.

        :returns: None
        """
        if self.exitnode_cache.is_file():
            self.logger.debug('Loading exit nodes from cache: %s',
                              self.exitnode_cache)
            exit_nodes = Network()
            with self.exitnode_cache.open('rb') as cache:
                exit_nodes.load_snapshot(cache.read())
            for exit_node in exit_nodes.get_walkable_addresses():
                self.endpoint.send(exit_node,
                                   self.create_introduction_request(exit_node))
        else:
            self.logger.warning(
                'Could not retrieve backup exitnode cache, file does not exist!'
            )
예제 #2
0
class TestNetwork(unittest.TestCase):

    peers = [_generate_peer() for _ in range(4)]

    def setUp(self):
        self.network = Network()

    def test_discover_address(self):
        """
        Check registration of introducer and introduced when a new address is discovered.

        The introducer should be verified and not walkable.
        The introduced should not be verified and walkable.
        """
        self.network.discover_address(self.peers[0], self.peers[1].address)

        self.assertNotIn(self.peers[0].address,
                         self.network.get_walkable_addresses())
        self.assertIn(self.peers[1].address,
                      self.network.get_walkable_addresses())
        self.assertIn(self.peers[0], self.network.verified_peers)
        self.assertNotIn(self.peers[1], self.network.verified_peers)
        self.assertIn(self.peers[1].address,
                      self.network.get_introductions_from(self.peers[0]))
        self.assertTrue(
            self.network.graph.has_edge(b64encode(self.peers[0].mid),
                                        self.peers[1].address))

    def test_discover_address_duplicate(self):
        """
        Check registration of introducer and introduced when the same address is discovered twice.
        """
        self.network.discover_address(self.peers[0], self.peers[1].address)
        self.network.discover_address(self.peers[0], self.peers[1].address)

        self.assertNotIn(self.peers[0].address,
                         self.network.get_walkable_addresses())
        self.assertIn(self.peers[1].address,
                      self.network.get_walkable_addresses())
        self.assertIn(self.peers[0], self.network.verified_peers)
        self.assertNotIn(self.peers[1], self.network.verified_peers)
        self.assertIn(self.peers[1].address,
                      self.network.get_introductions_from(self.peers[0]))
        self.assertTrue(
            self.network.graph.has_edge(b64encode(self.peers[0].mid),
                                        self.peers[1].address))

    def test_discover_address_known(self):
        """
        Check if an address is already known, the network isn't updated.
        """
        self.network.discover_address(self.peers[0], self.peers[1].address)
        self.network.discover_address(self.peers[2], self.peers[1].address)

        self.assertNotIn(self.peers[0].address,
                         self.network.get_walkable_addresses())
        self.assertIn(self.peers[1].address,
                      self.network.get_walkable_addresses())
        self.assertNotIn(self.peers[2].address,
                         self.network.get_walkable_addresses())
        self.assertIn(self.peers[0], self.network.verified_peers)
        self.assertNotIn(self.peers[1], self.network.verified_peers)
        self.assertIn(self.peers[2], self.network.verified_peers)
        self.assertIn(self.peers[1].address,
                      self.network.get_introductions_from(self.peers[0]))
        self.assertTrue(
            self.network.graph.has_edge(b64encode(self.peers[0].mid),
                                        self.peers[1].address))

    def test_discover_address_known_parent_deceased(self):
        """
        Check if an address is already known, the new introducer adopts the introduced.
        """
        self.network.discover_address(self.peers[0], self.peers[1].address)
        self.network.remove_peer(self.peers[0])
        self.network.discover_address(self.peers[2], self.peers[1].address)

        self.assertIn(self.peers[1].address,
                      self.network.get_walkable_addresses())
        self.assertNotIn(self.peers[2].address,
                         self.network.get_walkable_addresses())
        self.assertIn(self.peers[2], self.network.verified_peers)
        self.assertNotIn(self.peers[1], self.network.verified_peers)
        self.assertIn(self.peers[1].address,
                      self.network.get_introductions_from(self.peers[2]))
        self.assertTrue(
            self.network.graph.has_edge(b64encode(self.peers[2].mid),
                                        self.peers[1].address))

    def test_discover_address_blacklist(self):
        """
        Check if an address is in the blacklist, the network isn't updated.
        """
        self.network.blacklist.append(self.peers[2].address)
        self.network.discover_address(self.peers[0], self.peers[1].address)
        self.network.discover_address(self.peers[0], self.peers[2].address)

        self.assertNotIn(self.peers[0].address,
                         self.network.get_walkable_addresses())
        self.assertIn(self.peers[1].address,
                      self.network.get_walkable_addresses())
        self.assertNotIn(self.peers[2].address,
                         self.network.get_walkable_addresses())
        self.assertIn(self.peers[0], self.network.verified_peers)
        self.assertNotIn(self.peers[1], self.network.verified_peers)
        self.assertNotIn(self.peers[2], self.network.verified_peers)
        self.assertIn(self.peers[1].address,
                      self.network.get_introductions_from(self.peers[0]))
        self.assertTrue(
            self.network.graph.has_edge(b64encode(self.peers[0].mid),
                                        self.peers[1].address))

    def test_discover_address_multiple(self):
        """
        Check if a single peer can perform multiple introductions.
        """
        self.network.discover_address(self.peers[0], self.peers[1].address)
        self.network.discover_address(self.peers[0], self.peers[2].address)

        self.assertNotIn(self.peers[0].address,
                         self.network.get_walkable_addresses())
        self.assertIn(self.peers[0], self.network.verified_peers)

        for other in [1, 2]:
            self.assertIn(self.peers[other].address,
                          self.network.get_walkable_addresses())
            self.assertNotIn(self.peers[other], self.network.verified_peers)
            self.assertIn(self.peers[other].address,
                          self.network.get_introductions_from(self.peers[0]))
            self.assertTrue(
                self.network.graph.has_edge(b64encode(self.peers[0].mid),
                                            self.peers[other].address))

    def test_discover_services(self):
        """
        Check if services are properly registered for a peer.
        """
        service = "".join([chr(i) for i in range(20)])
        self.network.discover_services(self.peers[0], [service])
        self.network.add_verified_peer(self.peers[0])

        self.assertIn(service,
                      self.network.get_services_for_peer(self.peers[0]))
        self.assertIn(self.peers[0],
                      self.network.get_peers_for_service(service))

    def test_discover_services_unverified(self):
        """
        Check if services are properly registered for an unverified peer.

        You can query the services of an unverified peer, but it won't show up as a reachable peer for a service.
        """
        service = "".join([chr(i) for i in range(20)])
        self.network.discover_services(self.peers[0], [service])

        self.assertIn(service,
                      self.network.get_services_for_peer(self.peers[0]))
        self.assertNotIn(self.peers[0],
                         self.network.get_peers_for_service(service))

    def test_discover_services_update(self):
        """
        Check if services are properly combined for a peer.
        """
        service1 = "".join([chr(i) for i in range(20)])
        service2 = "".join([chr(i) for i in range(20, 40)])
        self.network.discover_services(self.peers[0], [service1])
        self.network.discover_services(self.peers[0], [service2])
        self.network.add_verified_peer(self.peers[0])

        self.assertIn(service1,
                      self.network.get_services_for_peer(self.peers[0]))
        self.assertIn(service2,
                      self.network.get_services_for_peer(self.peers[0]))
        self.assertIn(self.peers[0],
                      self.network.get_peers_for_service(service1))
        self.assertIn(self.peers[0],
                      self.network.get_peers_for_service(service2))

    def test_discover_services_update_overlap(self):
        """
        Check if services are properly combined when discovered services overlap.
        """
        service1 = "".join([chr(i) for i in range(20)])
        service2 = "".join([chr(i) for i in range(20, 40)])
        self.network.discover_services(self.peers[0], [service1])
        self.network.discover_services(self.peers[0], [service1, service2])
        self.network.add_verified_peer(self.peers[0])

        self.assertIn(service1,
                      self.network.get_services_for_peer(self.peers[0]))
        self.assertIn(service2,
                      self.network.get_services_for_peer(self.peers[0]))
        self.assertIn(self.peers[0],
                      self.network.get_peers_for_service(service1))
        self.assertIn(self.peers[0],
                      self.network.get_peers_for_service(service2))

    def test_add_verified_peer_new(self):
        """
        Check if a new verified peer can be added to the network.
        """
        self.network.add_verified_peer(self.peers[0])

        self.assertNotIn(self.peers[0].address,
                         self.network.get_walkable_addresses())
        self.assertIn(self.peers[0], self.network.verified_peers)
        self.assertListEqual([],
                             self.network.get_introductions_from(
                                 self.peers[0]))
        self.assertTrue(
            self.network.graph.has_node(b64encode(self.peers[0].mid)))

    def test_add_verified_peer_blacklist(self):
        """
        Check if a new verified peer can be added to the network.
        """
        self.network.blacklist.append(self.peers[0].address)
        self.network.add_verified_peer(self.peers[0])

        self.assertNotIn(self.peers[0].address,
                         self.network.get_walkable_addresses())
        self.assertNotIn(self.peers[0], self.network.verified_peers)
        self.assertFalse(
            self.network.graph.has_node(b64encode(self.peers[0].mid)))

    def test_add_verified_peer_duplicate(self):
        """
        Check if an already verified (by slightly changed) peer doesn't cause duplicates in the network.
        """
        self.network.add_verified_peer(self.peers[0])
        self.peers[0].update_clock(1)
        self.network.add_verified_peer(self.peers[0])

        self.assertNotIn(self.peers[0].address,
                         self.network.get_walkable_addresses())
        self.assertIn(self.peers[0], self.network.verified_peers)
        self.assertListEqual([],
                             self.network.get_introductions_from(
                                 self.peers[0]))
        self.assertTrue(
            self.network.graph.has_node(b64encode(self.peers[0].mid)))

    def test_add_verified_peer_promote(self):
        """
        Check if a peer can be promoted from an address to a verified peer.
        """
        self.network.discover_address(self.peers[1], self.peers[0].address)
        self.network.add_verified_peer(self.peers[0])

        self.assertNotIn(self.peers[0].address,
                         self.network.get_walkable_addresses())
        self.assertIn(self.peers[0], self.network.verified_peers)
        self.assertListEqual([],
                             self.network.get_introductions_from(
                                 self.peers[0]))
        self.assertTrue(
            self.network.graph.has_node(b64encode(self.peers[0].mid)))
        self.assertFalse(self.network.graph.has_node(self.peers[0].address))

    def test_get_verified_by_address(self):
        """
        Check if we can find a peer in our network by its address.
        """
        self.network.add_verified_peer(self.peers[0])

        self.assertEqual(
            self.peers[0],
            self.network.get_verified_by_address(self.peers[0].address))

    def test_get_verified_by_public_key(self):
        """
        Check if we can find a peer in our network by its public key.
        """
        self.network.add_verified_peer(self.peers[0])

        self.assertEqual(
            self.peers[0],
            self.network.get_verified_by_public_key_bin(
                self.peers[0].public_key.key_to_bin()))

    def test_remove_by_address(self):
        """
        Check if we can remove a peer from our network by its address.
        """
        self.network.add_verified_peer(self.peers[0])
        self.network.discover_services(self.peers[0], ["0" * 20])
        self.network.remove_by_address(self.peers[0].address)

        self.assertNotIn(self.peers[0], self.network.verified_peers)
        self.assertNotIn(self.peers[0].address,
                         self.network.get_walkable_addresses())
        self.assertEqual(set(),
                         self.network.get_services_for_peer(self.peers[0]))
        self.assertFalse(
            self.network.graph.has_node(b64encode(self.peers[0].mid)))

    def test_remove_by_address_unverified(self):
        """
        Check if we can remove an unverified peer from our network by its address.
        """
        self.network.discover_address(self.peers[0], self.peers[1].address)
        self.network.remove_by_address(self.peers[1].address)

        self.assertNotIn(self.peers[1].address,
                         self.network.get_walkable_addresses())
        self.assertFalse(self.network.graph.has_node(self.peers[1].address))

    def test_remove_by_address_unknown(self):
        """
        Removing unknown peers should not affect other peers.
        """
        self.network.add_verified_peer(self.peers[0])

        previous_walkable = self.network.get_walkable_addresses()
        previous_verified = self.network.verified_peers

        self.network.remove_by_address(self.peers[1].address)

        self.assertEqual(previous_walkable,
                         self.network.get_walkable_addresses())
        self.assertEqual(previous_verified, self.network.verified_peers)

    def test_remove_by_address_no_services(self):
        """
        Check if we can remove a peer from our network if it doesn't have services by address.
        """
        self.network.add_verified_peer(self.peers[0])
        self.network.remove_by_address(self.peers[0].address)

        self.assertNotIn(self.peers[0], self.network.verified_peers)
        self.assertNotIn(self.peers[0].address,
                         self.network.get_walkable_addresses())
        self.assertFalse(
            self.network.graph.has_node(b64encode(self.peers[0].mid)))

    def test_remove_peer(self):
        """
        Check if we can remove a peer from our network.
        """
        self.network.add_verified_peer(self.peers[0])
        self.network.discover_services(self.peers[0], ["0" * 20])
        self.network.remove_peer(self.peers[0])

        self.assertNotIn(self.peers[0], self.network.verified_peers)
        self.assertNotIn(self.peers[0].address,
                         self.network.get_walkable_addresses())
        self.assertEqual(set(),
                         self.network.get_services_for_peer(self.peers[0]))
        self.assertFalse(
            self.network.graph.has_node(b64encode(self.peers[0].mid)))

    def test_remove_peer_external(self):
        """
        Check if we can remove an externally created peer from our network.
        """
        self.network.discover_address(self.peers[1], self.peers[0].address)
        self.network.remove_peer(self.peers[0])

        self.assertNotIn(self.peers[0].address,
                         self.network.get_walkable_addresses())
        self.assertFalse(
            self.network.graph.has_node(b64encode(self.peers[0].mid)))
        self.assertFalse(self.network.graph.has_node(self.peers[0].address))

    def test_remove_peer_unknown(self):
        """
        Removing unknown peers should not affect other peers.
        """
        self.network.add_verified_peer(self.peers[0])

        previous_walkable = self.network.get_walkable_addresses()
        previous_verified = self.network.verified_peers

        self.network.remove_peer(self.peers[1])

        self.assertEqual(previous_walkable,
                         self.network.get_walkable_addresses())
        self.assertEqual(previous_verified, self.network.verified_peers)

    def test_get_walkable_by_service(self):
        """
        Check if we can retrieve walkable addresses by parent service id.
        """
        service = "".join([chr(i) for i in range(20)])
        self.network.discover_address(self.peers[2], self.peers[3].address)
        self.network.discover_address(self.peers[0], self.peers[1].address)
        self.network.discover_services(self.peers[0], [service])

        self.assertEqual([self.peers[1].address],
                         self.network.get_walkable_addresses(service))