Closed Sword-Smith closed 1 year ago
An example where listen_address
is used in incorrectly can be found in the peer discovery method
// 0) Ask all peers for their peer lists
// 1) Get peer candidate from these responses
// 2) Connect to one of those peers, A.
// 3) Ask this newly connected peer, A, for its peers.
// 4) Connect to one of those peers
// 5) Disconnect from A. (not yet implemented)
// 0)
self.main_to_peer_broadcast_tx
.send(MainToPeerThread::MakePeerDiscoveryRequest)?;
// 1)
let (peer_candidate, candidate_distance) =
match main_loop_state.potential_peers.get_distant_candidate(
&connected_peers,
self.global_state.cli.get_own_listen_address(),
self.global_state.net.instance_id,
) {
Some(candidate) => candidate,
None => return Ok(()),
};
and the callee looks like this
/// Return a random peer from the potential peer list that we aren't connected to
/// and that isn't our own address. Returns (socket address, peer distance)
fn get_distant_candidate(
&self,
connected_clients: &[PeerInfo],
own_listen_socket: Option<SocketAddr>,
own_instance_id: u128,
) -> Option<(SocketAddr, u8)> {
let peers_instance_ids: Vec<u128> =
connected_clients.iter().map(|x| x.instance_id).collect();
// Only pick those peers that report a listening port
let peers_listen_addresses: Vec<SocketAddr> = connected_clients
.iter()
.filter_map(|x| x.address_for_incoming_connections)
.collect();
// Find the appropriate candidates
let not_connected_peers = self
.potential_peers
.iter()
// Prevent connecting to self
.filter(|pp| pp.1.instance_id != own_instance_id)
.filter(|pp| own_listen_socket.is_some() && *pp.0 != own_listen_socket.unwrap())
// Prevent connecting to peer we already are connected to
.filter(|potential_peer| !peers_instance_ids.contains(&potential_peer.1.instance_id))
.filter(|potential_peer| !peers_listen_addresses.contains(potential_peer.0))
.collect::<Vec<_>>();
// Get the candidate list with the highest distance
let max_distance_candidates = not_connected_peers.iter().max_by_key(|pp| pp.1.distance);
// Pick a random candidate from the appropriate candidates
let mut rng = rand::thread_rng();
max_distance_candidates
.iter()
.choose(&mut rng)
.map(|x| (x.0.to_owned(), x.1.distance))
}
The problem is that listen_address
is a NATted address, and defaults to 0.0.0.0
which is how to tell the OS to listen on all network interfaces. It does not represent the public IP address as the above code assumes.
It doesn't represent what I thought it did, at least not in its current form. It is the listen address of the internal network interface, not the public socket address.