turmoil/
ip.rs

1use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
2
3/// The kinds of networks that can be simulated in turmoil
4#[derive(Debug, Clone, PartialEq, Eq, Default)]
5pub enum IpVersion {
6    /// An Ipv4 network with an address space of 192.168.0.0/16
7    #[default]
8    V4,
9    /// An local area Ipv6 network with an address space of fe80::/64
10    V6,
11}
12
13impl IpVersion {
14    pub(crate) fn iter(&self) -> IpVersionAddrIter {
15        match self {
16            Self::V4 => IpVersionAddrIter::V4(1),
17            Self::V6 => IpVersionAddrIter::V6(1),
18        }
19    }
20}
21
22#[derive(Debug)]
23pub(crate) enum IpVersionAddrIter {
24    /// the next ip addr without the network prefix, as u32
25    V4(u32),
26    /// the next ip addr without the network prefix, as u128
27    V6(u128),
28}
29
30impl Default for IpVersionAddrIter {
31    fn default() -> Self {
32        Self::V4(1)
33    }
34}
35
36impl IpVersionAddrIter {
37    pub(crate) fn next(&mut self) -> IpAddr {
38        match self {
39            Self::V4(next) => {
40                let host = *next;
41                *next = next.wrapping_add(1);
42
43                let a = (host >> 8) as u8;
44                let b = (host & 0xFF) as u8;
45
46                IpAddr::V4(Ipv4Addr::new(192, 168, a, b))
47            }
48            Self::V6(next) => {
49                let host = *next;
50                *next = next.wrapping_add(1);
51
52                let a = ((host >> 48) & 0xffff) as u16;
53                let b = ((host >> 32) & 0xffff) as u16;
54                let c = ((host >> 16) & 0xffff) as u16;
55                let d = (host & 0xffff) as u16;
56
57                IpAddr::V6(Ipv6Addr::new(0xfe80, 0, 0, 0, a, b, c, d))
58            }
59        }
60    }
61}
62
63#[cfg(test)]
64mod tests {
65    use crate::{lookup, Builder, IpVersion, Result};
66    use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
67
68    #[test]
69    fn ip_version_v4() -> Result {
70        let mut sim = Builder::new().build();
71        sim.client("client", async move {
72            assert_eq!(lookup("client"), IpAddr::V4(Ipv4Addr::new(192, 168, 0, 1)));
73            assert_eq!(lookup("server"), IpAddr::V4(Ipv4Addr::new(192, 168, 0, 2)));
74            Ok(())
75        });
76        sim.client("server", async move { Ok(()) });
77
78        assert_eq!(
79            sim.lookup("client"),
80            IpAddr::V4(Ipv4Addr::new(192, 168, 0, 1))
81        );
82        assert_eq!(
83            sim.lookup("server"),
84            IpAddr::V4(Ipv4Addr::new(192, 168, 0, 2))
85        );
86
87        sim.run()
88    }
89
90    #[test]
91    fn ip_version_v6() -> Result {
92        let mut sim = Builder::new().ip_version(IpVersion::V6).build();
93        sim.client("client", async move {
94            assert_eq!(
95                lookup("client"),
96                IpAddr::V6(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1))
97            );
98            assert_eq!(
99                lookup("server"),
100                IpAddr::V6(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 2))
101            );
102            Ok(())
103        });
104        sim.client("server", async move { Ok(()) });
105
106        assert_eq!(
107            sim.lookup("client"),
108            IpAddr::V6(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 1))
109        );
110        assert_eq!(
111            sim.lookup("server"),
112            IpAddr::V6(Ipv6Addr::new(0xfe80, 0, 0, 0, 0, 0, 0, 2))
113        );
114
115        sim.run()
116    }
117}