p2p 0.5.2

A peer-to-peer NAT traversal library
Documentation
use priv_prelude::*;

pub fn filter_addrs(
    our_addrs: &HashSet<SocketAddr>,
    their_addrs: &HashSet<SocketAddr>,
) -> HashSet<SocketAddr> {
    let our_global_addrs = {
        our_addrs
            .iter()
            .cloned()
            .filter(|addr| IpAddrExt::is_global(&addr.ip()))
            .collect::<HashSet<_>>()
    };
    let our_private_addrs = {
        our_addrs
            .iter()
            .cloned()
            .filter(|addr| addr.ip().is_private())
            .collect::<HashSet<_>>()
    };
    let their_global_addrs = {
        their_addrs
            .iter()
            .cloned()
            .filter(|addr| IpAddrExt::is_global(&addr.ip()))
            .collect::<HashSet<_>>()
    };
    let any_global_ips_in_common = {
        their_global_addrs
            .iter()
            .any(|a0| our_global_addrs.iter().any(|a1| a0.ip() == a1.ip()))
    };
    let maybe_same_subnet =
        any_global_ips_in_common || (their_global_addrs.is_empty() && our_global_addrs.is_empty());
    let their_filtered_private_addrs = {
        if maybe_same_subnet {
            their_addrs
                .iter()
                .cloned()
                .filter(|addr| addr.ip().is_private())
                .collect::<HashSet<_>>()
        } else {
            HashSet::new()
        }
    };
    let any_private_ips_in_common = {
        their_filtered_private_addrs
            .iter()
            .any(|a0| our_private_addrs.iter().any(|a1| a0.ip() == a1.ip()))
    };
    let maybe_same_machine = any_private_ips_in_common
        || (their_filtered_private_addrs.is_empty()
            && our_private_addrs.is_empty()
            && maybe_same_subnet);
    let their_filtered_loopback_addr = {
        if maybe_same_machine {
            their_addrs
                .iter()
                .cloned()
                .find(|addr| addr.ip().is_loopback())
        } else {
            None
        }
    };

    their_global_addrs
        .into_iter()
        .chain({
            their_filtered_private_addrs
                .into_iter()
                .chain(their_filtered_loopback_addr)
        })
        .collect()
}

#[test]
fn test() {
    let our_addrs = hashset!{
        addr!("78.60.234.207:45666"),
        addr!("192.168.0.1:45666"),
        addr!("127.0.0.1:45666"),
    };

    let their_addrs = hashset!{
        addr!("78.60.234.208:45667"),
        addr!("192.168.0.1:45667"),
        addr!("127.0.0.1:45667"),
    };
    let supposed_addrs = hashset!{
        addr!("78.60.234.208:45667"),
    };
    let result = filter_addrs(&our_addrs, &their_addrs);
    assert_eq!(result, supposed_addrs);

    let their_addrs = hashset!{
        addr!("78.60.234.207:45667"),
        addr!("192.168.0.2:45667"),
        addr!("127.0.0.1:45667"),
    };
    let supposed_addrs = hashset!{
        addr!("78.60.234.207:45667"),
        addr!("192.168.0.2:45667"),
    };
    let result = filter_addrs(&our_addrs, &their_addrs);
    assert_eq!(result, supposed_addrs);

    let their_addrs = hashset!{
        addr!("78.60.234.207:45667"),
        addr!("192.168.0.1:45667"),
        addr!("127.0.0.1:45667"),
    };
    let supposed_addrs = hashset!{
        addr!("78.60.234.207:45667"),
        addr!("192.168.0.1:45667"),
        addr!("127.0.0.1:45667"),
    };
    let result = filter_addrs(&our_addrs, &their_addrs);
    assert_eq!(result, supposed_addrs);
}