Struct Machine

Source
pub struct Machine { /* private fields */ }
Expand description

The entry point for this library.

A machine has its own tokio runtime running in a separate network-isolated thread. Use spawn to spawn futures on this runtime and wait for their result. Use add_ip_iface to add virtual network interfaces to the machine and use the returned IpIface to interfere with its packets or build it into a network. Dropping the machine will shutdown its runtime and cancel any futures executing on it, causing any associated JoinHandles to return None.

Implementations§

Source§

impl Machine

Source

pub fn new() -> Result<Machine>

Create a new machine. A machine initially has no network interfaces, so attempting to (eg.) make an outgoing TCP connection from a future running on the machine will fail.

Examples found in repository?
examples/isolate.rs (lines 10-22)
10fn main() {
11    let addr = addrv4!("127.0.0.1:80");
12
13    let listener = TcpListener::bind(addr).unwrap();
14    let join_handle_inner_0 = thread::spawn(move || {
15        let _stream = listener.accept().unwrap();
16    });
17    let join_handle_inner_1 = thread::spawn(move || {
18        let _stream = TcpStream::connect(addr).unwrap();
19    });
20    join_handle_inner_0.join().unwrap();
21    join_handle_inner_1.join().unwrap();
22}
More examples
Hide additional examples
examples/capture_packet.rs (line 15)
12async fn main() {
13    let addr = addrv4!("10.1.2.3:5555");
14
15    let machine = Machine::new().unwrap();
16    let mut iface = {
17        machine
18        .add_ip_iface()
19        .ipv4_addr(*addr.ip())
20        .ipv4_default_route()
21        .build()
22        .unwrap()
23    };
24    machine.spawn(async move {
25        let socket = UdpSocket::bind(addr).await.unwrap();
26        socket.send_to(b"hello", addrv4!("1.1.1.1:80")).await.unwrap();
27    }).await.unwrap();
28
29    let packet = loop {
30        let packet = iface.next().await.unwrap().unwrap();
31        let IpPacketVersion::V4(packet) = packet.version_box() else { continue };
32        let Ipv4PacketProtocol::Udp(packet) = packet.protocol_box() else { continue };
33        break packet;
34    };
35    assert_eq!(packet.data(), b"hello");
36}
examples/ping_pong.rs (line 19)
16async fn main() {
17
18    // First create two machines.
19    let machine_0 = Machine::new().unwrap();
20    let machine_1 = Machine::new().unwrap();
21
22
23    // Then give each machine a network interface.
24    let ipv4_addr_0 = ipv4!("10.1.2.3");
25    let port_0 = 45666;
26    let addr_0 = SocketAddr::from((ipv4_addr_0, port_0));
27
28    let ipv4_addr_1 = ipv4!("192.168.5.5");
29    let port_1 = 5555;
30    let addr_1 = SocketAddr::from((ipv4_addr_1, port_1));
31
32    let iface_0 = {
33        machine_0
34        .add_ip_iface()
35        .ipv4_addr(ipv4_addr_0)
36        .ipv4_default_route()
37        .build()
38        .unwrap()
39    };
40    let iface_1 = {
41        machine_1
42        .add_ip_iface()
43        .ipv4_addr(ipv4_addr_1)
44        .ipv4_default_route()
45        .build()
46        .unwrap()
47    };
48
49
50    // Connect the network interfaces directly to each other.
51    netsim::connect(iface_0, iface_1);
52
53
54    // Execute a task on machine 0. This task waits to receive a UDP packet then sends a reply.
55    let join_handle_0 = machine_0.spawn(async move {
56        let socket = UdpSocket::bind(addr_0).await.unwrap();
57
58        let mut recv_bytes = [0u8; 100];
59        let (recv_len, peer_addr) = socket.recv_from(&mut recv_bytes).await.unwrap();
60        assert_eq!(peer_addr, addr_1);
61        let recv_msg = str::from_utf8(&recv_bytes[..recv_len]).unwrap();
62        println!("received msg: '{recv_msg}'");
63
64        let send_msg = "pong";
65        let send_len = socket.send_to(send_msg.as_bytes(), addr_1).await.unwrap();
66        assert_eq!(send_len, send_msg.len());
67        println!("sent reply: '{send_msg}'");
68    });
69    // Execute a task on machine 1. This task sends UDP packets until it receives a reply.
70    let join_handle_1 = machine_1.spawn(async move {
71        let socket = UdpSocket::bind(addr_1).await.unwrap();
72        let mut recv_bytes = [0u8; 100];
73
74        let (recv_len, peer_addr) = loop {
75            let send_msg = "ping";
76            let send_len = socket.send_to(send_msg.as_bytes(), addr_0).await.unwrap();
77            assert_eq!(send_len, send_msg.len());
78            println!("sent msg: '{send_msg}'");
79
80            tokio::select! {
81                recv_result = socket.recv_from(&mut recv_bytes) => break recv_result.unwrap(),
82                () = tokio::time::sleep(Duration::from_secs(1)) => (),
83            }
84        };
85        assert_eq!(peer_addr, addr_0);
86        let recv_msg = str::from_utf8(&recv_bytes[..recv_len]).unwrap();
87        println!("received reply: '{recv_msg}'");
88    });
89
90
91    // Wait for both machines to run their tasks to completion.
92    let () = join_handle_0.await.unwrap().unwrap();
93    let () = join_handle_1.await.unwrap().unwrap();
94}
examples/nat.rs (line 20)
17async fn main() {
18    let mut rng = rand::thread_rng();
19
20    let machine_0 = Machine::new().unwrap();
21    let machine_1 = Machine::new().unwrap();
22    
23    let network_0 = ipv4_network!("192.168.0.0/16");
24    let ipv4_addr_0 = network_0.random_addr(&mut rng);
25    let iface_0 = {
26        machine_0
27        .add_ip_iface()
28        .ipv4_addr(ipv4_addr_0)
29        .ipv4_default_route()
30        .build()
31        .unwrap()
32    };
33    let global_ipv4_addr_0 = Ipv4Network::GLOBAL.random_addr(&mut rng);
34    let (mut nat_0, nat_iface_0) = NatBuilder::new(global_ipv4_addr_0, network_0).port_restricted().build();
35    nat_0.insert_iface(iface_0);
36
37    let network_1 = ipv4_network!("10.0.0.0/8");
38    let ipv4_addr_1 = network_1.random_addr(&mut rng);
39    let iface_1 = {
40        machine_1
41        .add_ip_iface()
42        .ipv4_addr(ipv4_addr_1)
43        .ipv4_default_route()
44        .build()
45        .unwrap()
46    };
47    let global_ipv4_addr_1 = Ipv4Network::GLOBAL.random_addr(&mut rng);
48    let (mut nat_1, nat_iface_1) = NatBuilder::new(global_ipv4_addr_1, network_1).port_restricted().build();
49    nat_1.insert_iface(iface_1);
50
51    let machine_rendezvous = Machine::new().unwrap();
52    let ipv4_addr_rendezvous = Ipv4Network::GLOBAL.random_addr(&mut rng);
53    let port_rendezvous = 12345;
54    let addr_rendezvous = SocketAddr::from((ipv4_addr_rendezvous, port_rendezvous));
55    let iface_rendezvous = {
56        machine_rendezvous
57        .add_ip_iface()
58        .ipv4_addr(ipv4_addr_rendezvous)
59        .ipv4_default_route()
60        .build()
61        .unwrap()
62    };
63
64
65    let mut hub = IpHub::new();
66    hub.insert_iface(nat_iface_0);
67    hub.insert_iface(nat_iface_1);
68    hub.insert_iface(iface_rendezvous);
69
70    println!("machine 0 has local ip {} and global ip {}", ipv4_addr_0, global_ipv4_addr_0);
71    println!("machine 1 has local ip {} and global ip {}", ipv4_addr_1, global_ipv4_addr_1);
72    println!("rendezvous machine has ip {}", ipv4_addr_rendezvous);
73
74    let join_handle_rendezvous = machine_rendezvous.spawn(async move {
75        let socket = UdpSocket::bind(addr_rendezvous).await.unwrap();
76
77        let peer_addr_0 = {
78            let mut recv_bytes = [0u8; 100];
79            let (recv_len, peer_addr_0) = socket.recv_from(&mut recv_bytes).await.unwrap();
80            assert_eq!(recv_len, 0);
81            peer_addr_0
82        };
83        println!("rendevous node received packet from {}", peer_addr_0);
84
85        let peer_addr_1 = loop {
86            let mut recv_bytes = [0u8; 100];
87            let (recv_len, peer_addr_1) = socket.recv_from(&mut recv_bytes).await.unwrap();
88            assert_eq!(recv_len, 0);
89            if peer_addr_1 == peer_addr_0 {
90                println!("rendezvous node ignoring extra packet from {}", peer_addr_0);
91                continue;
92            }
93            break peer_addr_1
94        };
95        println!("rendevous node received packet from {}", peer_addr_1);
96
97        let peer_addr_0_str = peer_addr_0.to_string();
98        let peer_addr_1_str = peer_addr_1.to_string();
99        socket.send_to(peer_addr_0_str.as_bytes(), peer_addr_1).await.unwrap();
100        socket.send_to(peer_addr_1_str.as_bytes(), peer_addr_0).await.unwrap();
101    });
102    let join_handle_0 = machine_0.spawn(async move {
103        let socket = UdpSocket::bind(addrv4!("0.0.0.0:0")).await.unwrap();
104        let mut recv_bytes = [0u8; 100];
105
106        let peer_addr_1 = {
107            let (recv_len, recv_addr) = loop {
108                socket.send_to(&[], addr_rendezvous).await.unwrap();
109                println!("machine 0 sending to {}", addr_rendezvous);
110                tokio::select! {
111                    recv_result = socket.recv_from(&mut recv_bytes) => break recv_result.unwrap(),
112                    () = tokio::time::sleep(Duration::from_secs(1)) => (),
113                }
114            };
115            assert_eq!(recv_addr, addr_rendezvous);
116            let recv_msg = str::from_utf8(&recv_bytes[..recv_len]).unwrap();
117            SocketAddr::from_str(recv_msg).unwrap()
118        };
119        let (recv_len, recv_addr) = loop {
120            socket.send_to("hello from machine 0".as_bytes(), peer_addr_1).await.unwrap();
121            tokio::select! {
122                recv_result = socket.recv_from(&mut recv_bytes) => break recv_result.unwrap(),
123                () = tokio::time::sleep(Duration::from_secs(1)) => (),
124            }
125        };
126        assert_eq!(recv_addr, peer_addr_1);
127        let recv_msg = str::from_utf8(&recv_bytes[..recv_len]).unwrap();
128        assert_eq!(recv_msg, "hello from machine 1");
129        socket.send_to("hello from machine 0".as_bytes(), peer_addr_1).await.unwrap();
130    });
131    let join_handle_1 = machine_1.spawn(async move {
132        let socket = UdpSocket::bind(addrv4!("0.0.0.0:0")).await.unwrap();
133        let mut recv_bytes = [0u8; 100];
134
135        let peer_addr_1 = {
136            let (recv_len, recv_addr) = loop {
137                socket.send_to(&[], addr_rendezvous).await.unwrap();
138                println!("machine 1 sending to {}", addr_rendezvous);
139                tokio::select! {
140                    recv_result = socket.recv_from(&mut recv_bytes) => break recv_result.unwrap(),
141                    () = tokio::time::sleep(Duration::from_secs(1)) => (),
142                }
143            };
144            assert_eq!(recv_addr, addr_rendezvous);
145            let recv_msg = str::from_utf8(&recv_bytes[..recv_len]).unwrap();
146            SocketAddr::from_str(recv_msg).unwrap()
147        };
148        let (recv_len, recv_addr) = loop {
149            socket.send_to("hello from machine 1".as_bytes(), peer_addr_1).await.unwrap();
150            tokio::select! {
151                recv_result = socket.recv_from(&mut recv_bytes) => break recv_result.unwrap(),
152                () = tokio::time::sleep(Duration::from_secs(1)) => (),
153            }
154        };
155        assert_eq!(recv_addr, peer_addr_1);
156        let recv_msg = str::from_utf8(&recv_bytes[..recv_len]).unwrap();
157        assert_eq!(recv_msg, "hello from machine 0");
158        socket.send_to("hello from machine 1".as_bytes(), peer_addr_1).await.unwrap();
159    });
160
161    let () = join_handle_0.await.unwrap().unwrap();
162    let () = join_handle_1.await.unwrap().unwrap();
163    let () = join_handle_rendezvous.await.unwrap().unwrap();
164}
Source

pub fn spawn<F, R>(&self, future: F) -> JoinHandle<R>
where F: Future<Output = R> + Send + 'static, R: Send + 'static,

Executes a future on the machine. The future will start executing immediately. You can use the returned JoinHandle to await the future’s result.

Examples found in repository?
examples/isolate.rs (lines 10-22)
10fn main() {
11    let addr = addrv4!("127.0.0.1:80");
12
13    let listener = TcpListener::bind(addr).unwrap();
14    let join_handle_inner_0 = thread::spawn(move || {
15        let _stream = listener.accept().unwrap();
16    });
17    let join_handle_inner_1 = thread::spawn(move || {
18        let _stream = TcpStream::connect(addr).unwrap();
19    });
20    join_handle_inner_0.join().unwrap();
21    join_handle_inner_1.join().unwrap();
22}
More examples
Hide additional examples
examples/capture_packet.rs (lines 24-27)
12async fn main() {
13    let addr = addrv4!("10.1.2.3:5555");
14
15    let machine = Machine::new().unwrap();
16    let mut iface = {
17        machine
18        .add_ip_iface()
19        .ipv4_addr(*addr.ip())
20        .ipv4_default_route()
21        .build()
22        .unwrap()
23    };
24    machine.spawn(async move {
25        let socket = UdpSocket::bind(addr).await.unwrap();
26        socket.send_to(b"hello", addrv4!("1.1.1.1:80")).await.unwrap();
27    }).await.unwrap();
28
29    let packet = loop {
30        let packet = iface.next().await.unwrap().unwrap();
31        let IpPacketVersion::V4(packet) = packet.version_box() else { continue };
32        let Ipv4PacketProtocol::Udp(packet) = packet.protocol_box() else { continue };
33        break packet;
34    };
35    assert_eq!(packet.data(), b"hello");
36}
examples/ping_pong.rs (lines 55-68)
16async fn main() {
17
18    // First create two machines.
19    let machine_0 = Machine::new().unwrap();
20    let machine_1 = Machine::new().unwrap();
21
22
23    // Then give each machine a network interface.
24    let ipv4_addr_0 = ipv4!("10.1.2.3");
25    let port_0 = 45666;
26    let addr_0 = SocketAddr::from((ipv4_addr_0, port_0));
27
28    let ipv4_addr_1 = ipv4!("192.168.5.5");
29    let port_1 = 5555;
30    let addr_1 = SocketAddr::from((ipv4_addr_1, port_1));
31
32    let iface_0 = {
33        machine_0
34        .add_ip_iface()
35        .ipv4_addr(ipv4_addr_0)
36        .ipv4_default_route()
37        .build()
38        .unwrap()
39    };
40    let iface_1 = {
41        machine_1
42        .add_ip_iface()
43        .ipv4_addr(ipv4_addr_1)
44        .ipv4_default_route()
45        .build()
46        .unwrap()
47    };
48
49
50    // Connect the network interfaces directly to each other.
51    netsim::connect(iface_0, iface_1);
52
53
54    // Execute a task on machine 0. This task waits to receive a UDP packet then sends a reply.
55    let join_handle_0 = machine_0.spawn(async move {
56        let socket = UdpSocket::bind(addr_0).await.unwrap();
57
58        let mut recv_bytes = [0u8; 100];
59        let (recv_len, peer_addr) = socket.recv_from(&mut recv_bytes).await.unwrap();
60        assert_eq!(peer_addr, addr_1);
61        let recv_msg = str::from_utf8(&recv_bytes[..recv_len]).unwrap();
62        println!("received msg: '{recv_msg}'");
63
64        let send_msg = "pong";
65        let send_len = socket.send_to(send_msg.as_bytes(), addr_1).await.unwrap();
66        assert_eq!(send_len, send_msg.len());
67        println!("sent reply: '{send_msg}'");
68    });
69    // Execute a task on machine 1. This task sends UDP packets until it receives a reply.
70    let join_handle_1 = machine_1.spawn(async move {
71        let socket = UdpSocket::bind(addr_1).await.unwrap();
72        let mut recv_bytes = [0u8; 100];
73
74        let (recv_len, peer_addr) = loop {
75            let send_msg = "ping";
76            let send_len = socket.send_to(send_msg.as_bytes(), addr_0).await.unwrap();
77            assert_eq!(send_len, send_msg.len());
78            println!("sent msg: '{send_msg}'");
79
80            tokio::select! {
81                recv_result = socket.recv_from(&mut recv_bytes) => break recv_result.unwrap(),
82                () = tokio::time::sleep(Duration::from_secs(1)) => (),
83            }
84        };
85        assert_eq!(peer_addr, addr_0);
86        let recv_msg = str::from_utf8(&recv_bytes[..recv_len]).unwrap();
87        println!("received reply: '{recv_msg}'");
88    });
89
90
91    // Wait for both machines to run their tasks to completion.
92    let () = join_handle_0.await.unwrap().unwrap();
93    let () = join_handle_1.await.unwrap().unwrap();
94}
examples/nat.rs (lines 74-101)
17async fn main() {
18    let mut rng = rand::thread_rng();
19
20    let machine_0 = Machine::new().unwrap();
21    let machine_1 = Machine::new().unwrap();
22    
23    let network_0 = ipv4_network!("192.168.0.0/16");
24    let ipv4_addr_0 = network_0.random_addr(&mut rng);
25    let iface_0 = {
26        machine_0
27        .add_ip_iface()
28        .ipv4_addr(ipv4_addr_0)
29        .ipv4_default_route()
30        .build()
31        .unwrap()
32    };
33    let global_ipv4_addr_0 = Ipv4Network::GLOBAL.random_addr(&mut rng);
34    let (mut nat_0, nat_iface_0) = NatBuilder::new(global_ipv4_addr_0, network_0).port_restricted().build();
35    nat_0.insert_iface(iface_0);
36
37    let network_1 = ipv4_network!("10.0.0.0/8");
38    let ipv4_addr_1 = network_1.random_addr(&mut rng);
39    let iface_1 = {
40        machine_1
41        .add_ip_iface()
42        .ipv4_addr(ipv4_addr_1)
43        .ipv4_default_route()
44        .build()
45        .unwrap()
46    };
47    let global_ipv4_addr_1 = Ipv4Network::GLOBAL.random_addr(&mut rng);
48    let (mut nat_1, nat_iface_1) = NatBuilder::new(global_ipv4_addr_1, network_1).port_restricted().build();
49    nat_1.insert_iface(iface_1);
50
51    let machine_rendezvous = Machine::new().unwrap();
52    let ipv4_addr_rendezvous = Ipv4Network::GLOBAL.random_addr(&mut rng);
53    let port_rendezvous = 12345;
54    let addr_rendezvous = SocketAddr::from((ipv4_addr_rendezvous, port_rendezvous));
55    let iface_rendezvous = {
56        machine_rendezvous
57        .add_ip_iface()
58        .ipv4_addr(ipv4_addr_rendezvous)
59        .ipv4_default_route()
60        .build()
61        .unwrap()
62    };
63
64
65    let mut hub = IpHub::new();
66    hub.insert_iface(nat_iface_0);
67    hub.insert_iface(nat_iface_1);
68    hub.insert_iface(iface_rendezvous);
69
70    println!("machine 0 has local ip {} and global ip {}", ipv4_addr_0, global_ipv4_addr_0);
71    println!("machine 1 has local ip {} and global ip {}", ipv4_addr_1, global_ipv4_addr_1);
72    println!("rendezvous machine has ip {}", ipv4_addr_rendezvous);
73
74    let join_handle_rendezvous = machine_rendezvous.spawn(async move {
75        let socket = UdpSocket::bind(addr_rendezvous).await.unwrap();
76
77        let peer_addr_0 = {
78            let mut recv_bytes = [0u8; 100];
79            let (recv_len, peer_addr_0) = socket.recv_from(&mut recv_bytes).await.unwrap();
80            assert_eq!(recv_len, 0);
81            peer_addr_0
82        };
83        println!("rendevous node received packet from {}", peer_addr_0);
84
85        let peer_addr_1 = loop {
86            let mut recv_bytes = [0u8; 100];
87            let (recv_len, peer_addr_1) = socket.recv_from(&mut recv_bytes).await.unwrap();
88            assert_eq!(recv_len, 0);
89            if peer_addr_1 == peer_addr_0 {
90                println!("rendezvous node ignoring extra packet from {}", peer_addr_0);
91                continue;
92            }
93            break peer_addr_1
94        };
95        println!("rendevous node received packet from {}", peer_addr_1);
96
97        let peer_addr_0_str = peer_addr_0.to_string();
98        let peer_addr_1_str = peer_addr_1.to_string();
99        socket.send_to(peer_addr_0_str.as_bytes(), peer_addr_1).await.unwrap();
100        socket.send_to(peer_addr_1_str.as_bytes(), peer_addr_0).await.unwrap();
101    });
102    let join_handle_0 = machine_0.spawn(async move {
103        let socket = UdpSocket::bind(addrv4!("0.0.0.0:0")).await.unwrap();
104        let mut recv_bytes = [0u8; 100];
105
106        let peer_addr_1 = {
107            let (recv_len, recv_addr) = loop {
108                socket.send_to(&[], addr_rendezvous).await.unwrap();
109                println!("machine 0 sending to {}", addr_rendezvous);
110                tokio::select! {
111                    recv_result = socket.recv_from(&mut recv_bytes) => break recv_result.unwrap(),
112                    () = tokio::time::sleep(Duration::from_secs(1)) => (),
113                }
114            };
115            assert_eq!(recv_addr, addr_rendezvous);
116            let recv_msg = str::from_utf8(&recv_bytes[..recv_len]).unwrap();
117            SocketAddr::from_str(recv_msg).unwrap()
118        };
119        let (recv_len, recv_addr) = loop {
120            socket.send_to("hello from machine 0".as_bytes(), peer_addr_1).await.unwrap();
121            tokio::select! {
122                recv_result = socket.recv_from(&mut recv_bytes) => break recv_result.unwrap(),
123                () = tokio::time::sleep(Duration::from_secs(1)) => (),
124            }
125        };
126        assert_eq!(recv_addr, peer_addr_1);
127        let recv_msg = str::from_utf8(&recv_bytes[..recv_len]).unwrap();
128        assert_eq!(recv_msg, "hello from machine 1");
129        socket.send_to("hello from machine 0".as_bytes(), peer_addr_1).await.unwrap();
130    });
131    let join_handle_1 = machine_1.spawn(async move {
132        let socket = UdpSocket::bind(addrv4!("0.0.0.0:0")).await.unwrap();
133        let mut recv_bytes = [0u8; 100];
134
135        let peer_addr_1 = {
136            let (recv_len, recv_addr) = loop {
137                socket.send_to(&[], addr_rendezvous).await.unwrap();
138                println!("machine 1 sending to {}", addr_rendezvous);
139                tokio::select! {
140                    recv_result = socket.recv_from(&mut recv_bytes) => break recv_result.unwrap(),
141                    () = tokio::time::sleep(Duration::from_secs(1)) => (),
142                }
143            };
144            assert_eq!(recv_addr, addr_rendezvous);
145            let recv_msg = str::from_utf8(&recv_bytes[..recv_len]).unwrap();
146            SocketAddr::from_str(recv_msg).unwrap()
147        };
148        let (recv_len, recv_addr) = loop {
149            socket.send_to("hello from machine 1".as_bytes(), peer_addr_1).await.unwrap();
150            tokio::select! {
151                recv_result = socket.recv_from(&mut recv_bytes) => break recv_result.unwrap(),
152                () = tokio::time::sleep(Duration::from_secs(1)) => (),
153            }
154        };
155        assert_eq!(recv_addr, peer_addr_1);
156        let recv_msg = str::from_utf8(&recv_bytes[..recv_len]).unwrap();
157        assert_eq!(recv_msg, "hello from machine 0");
158        socket.send_to("hello from machine 1".as_bytes(), peer_addr_1).await.unwrap();
159    });
160
161    let () = join_handle_0.await.unwrap().unwrap();
162    let () = join_handle_1.await.unwrap().unwrap();
163    let () = join_handle_rendezvous.await.unwrap().unwrap();
164}
Source

pub fn add_ip_iface(&self) -> IpIfaceBuilder<'_>

Adds a network interface to the machine. See the IpIfaceBuilder docs for details.

Examples found in repository?
examples/capture_packet.rs (line 18)
12async fn main() {
13    let addr = addrv4!("10.1.2.3:5555");
14
15    let machine = Machine::new().unwrap();
16    let mut iface = {
17        machine
18        .add_ip_iface()
19        .ipv4_addr(*addr.ip())
20        .ipv4_default_route()
21        .build()
22        .unwrap()
23    };
24    machine.spawn(async move {
25        let socket = UdpSocket::bind(addr).await.unwrap();
26        socket.send_to(b"hello", addrv4!("1.1.1.1:80")).await.unwrap();
27    }).await.unwrap();
28
29    let packet = loop {
30        let packet = iface.next().await.unwrap().unwrap();
31        let IpPacketVersion::V4(packet) = packet.version_box() else { continue };
32        let Ipv4PacketProtocol::Udp(packet) = packet.protocol_box() else { continue };
33        break packet;
34    };
35    assert_eq!(packet.data(), b"hello");
36}
More examples
Hide additional examples
examples/ping_pong.rs (line 34)
16async fn main() {
17
18    // First create two machines.
19    let machine_0 = Machine::new().unwrap();
20    let machine_1 = Machine::new().unwrap();
21
22
23    // Then give each machine a network interface.
24    let ipv4_addr_0 = ipv4!("10.1.2.3");
25    let port_0 = 45666;
26    let addr_0 = SocketAddr::from((ipv4_addr_0, port_0));
27
28    let ipv4_addr_1 = ipv4!("192.168.5.5");
29    let port_1 = 5555;
30    let addr_1 = SocketAddr::from((ipv4_addr_1, port_1));
31
32    let iface_0 = {
33        machine_0
34        .add_ip_iface()
35        .ipv4_addr(ipv4_addr_0)
36        .ipv4_default_route()
37        .build()
38        .unwrap()
39    };
40    let iface_1 = {
41        machine_1
42        .add_ip_iface()
43        .ipv4_addr(ipv4_addr_1)
44        .ipv4_default_route()
45        .build()
46        .unwrap()
47    };
48
49
50    // Connect the network interfaces directly to each other.
51    netsim::connect(iface_0, iface_1);
52
53
54    // Execute a task on machine 0. This task waits to receive a UDP packet then sends a reply.
55    let join_handle_0 = machine_0.spawn(async move {
56        let socket = UdpSocket::bind(addr_0).await.unwrap();
57
58        let mut recv_bytes = [0u8; 100];
59        let (recv_len, peer_addr) = socket.recv_from(&mut recv_bytes).await.unwrap();
60        assert_eq!(peer_addr, addr_1);
61        let recv_msg = str::from_utf8(&recv_bytes[..recv_len]).unwrap();
62        println!("received msg: '{recv_msg}'");
63
64        let send_msg = "pong";
65        let send_len = socket.send_to(send_msg.as_bytes(), addr_1).await.unwrap();
66        assert_eq!(send_len, send_msg.len());
67        println!("sent reply: '{send_msg}'");
68    });
69    // Execute a task on machine 1. This task sends UDP packets until it receives a reply.
70    let join_handle_1 = machine_1.spawn(async move {
71        let socket = UdpSocket::bind(addr_1).await.unwrap();
72        let mut recv_bytes = [0u8; 100];
73
74        let (recv_len, peer_addr) = loop {
75            let send_msg = "ping";
76            let send_len = socket.send_to(send_msg.as_bytes(), addr_0).await.unwrap();
77            assert_eq!(send_len, send_msg.len());
78            println!("sent msg: '{send_msg}'");
79
80            tokio::select! {
81                recv_result = socket.recv_from(&mut recv_bytes) => break recv_result.unwrap(),
82                () = tokio::time::sleep(Duration::from_secs(1)) => (),
83            }
84        };
85        assert_eq!(peer_addr, addr_0);
86        let recv_msg = str::from_utf8(&recv_bytes[..recv_len]).unwrap();
87        println!("received reply: '{recv_msg}'");
88    });
89
90
91    // Wait for both machines to run their tasks to completion.
92    let () = join_handle_0.await.unwrap().unwrap();
93    let () = join_handle_1.await.unwrap().unwrap();
94}
examples/nat.rs (line 27)
17async fn main() {
18    let mut rng = rand::thread_rng();
19
20    let machine_0 = Machine::new().unwrap();
21    let machine_1 = Machine::new().unwrap();
22    
23    let network_0 = ipv4_network!("192.168.0.0/16");
24    let ipv4_addr_0 = network_0.random_addr(&mut rng);
25    let iface_0 = {
26        machine_0
27        .add_ip_iface()
28        .ipv4_addr(ipv4_addr_0)
29        .ipv4_default_route()
30        .build()
31        .unwrap()
32    };
33    let global_ipv4_addr_0 = Ipv4Network::GLOBAL.random_addr(&mut rng);
34    let (mut nat_0, nat_iface_0) = NatBuilder::new(global_ipv4_addr_0, network_0).port_restricted().build();
35    nat_0.insert_iface(iface_0);
36
37    let network_1 = ipv4_network!("10.0.0.0/8");
38    let ipv4_addr_1 = network_1.random_addr(&mut rng);
39    let iface_1 = {
40        machine_1
41        .add_ip_iface()
42        .ipv4_addr(ipv4_addr_1)
43        .ipv4_default_route()
44        .build()
45        .unwrap()
46    };
47    let global_ipv4_addr_1 = Ipv4Network::GLOBAL.random_addr(&mut rng);
48    let (mut nat_1, nat_iface_1) = NatBuilder::new(global_ipv4_addr_1, network_1).port_restricted().build();
49    nat_1.insert_iface(iface_1);
50
51    let machine_rendezvous = Machine::new().unwrap();
52    let ipv4_addr_rendezvous = Ipv4Network::GLOBAL.random_addr(&mut rng);
53    let port_rendezvous = 12345;
54    let addr_rendezvous = SocketAddr::from((ipv4_addr_rendezvous, port_rendezvous));
55    let iface_rendezvous = {
56        machine_rendezvous
57        .add_ip_iface()
58        .ipv4_addr(ipv4_addr_rendezvous)
59        .ipv4_default_route()
60        .build()
61        .unwrap()
62    };
63
64
65    let mut hub = IpHub::new();
66    hub.insert_iface(nat_iface_0);
67    hub.insert_iface(nat_iface_1);
68    hub.insert_iface(iface_rendezvous);
69
70    println!("machine 0 has local ip {} and global ip {}", ipv4_addr_0, global_ipv4_addr_0);
71    println!("machine 1 has local ip {} and global ip {}", ipv4_addr_1, global_ipv4_addr_1);
72    println!("rendezvous machine has ip {}", ipv4_addr_rendezvous);
73
74    let join_handle_rendezvous = machine_rendezvous.spawn(async move {
75        let socket = UdpSocket::bind(addr_rendezvous).await.unwrap();
76
77        let peer_addr_0 = {
78            let mut recv_bytes = [0u8; 100];
79            let (recv_len, peer_addr_0) = socket.recv_from(&mut recv_bytes).await.unwrap();
80            assert_eq!(recv_len, 0);
81            peer_addr_0
82        };
83        println!("rendevous node received packet from {}", peer_addr_0);
84
85        let peer_addr_1 = loop {
86            let mut recv_bytes = [0u8; 100];
87            let (recv_len, peer_addr_1) = socket.recv_from(&mut recv_bytes).await.unwrap();
88            assert_eq!(recv_len, 0);
89            if peer_addr_1 == peer_addr_0 {
90                println!("rendezvous node ignoring extra packet from {}", peer_addr_0);
91                continue;
92            }
93            break peer_addr_1
94        };
95        println!("rendevous node received packet from {}", peer_addr_1);
96
97        let peer_addr_0_str = peer_addr_0.to_string();
98        let peer_addr_1_str = peer_addr_1.to_string();
99        socket.send_to(peer_addr_0_str.as_bytes(), peer_addr_1).await.unwrap();
100        socket.send_to(peer_addr_1_str.as_bytes(), peer_addr_0).await.unwrap();
101    });
102    let join_handle_0 = machine_0.spawn(async move {
103        let socket = UdpSocket::bind(addrv4!("0.0.0.0:0")).await.unwrap();
104        let mut recv_bytes = [0u8; 100];
105
106        let peer_addr_1 = {
107            let (recv_len, recv_addr) = loop {
108                socket.send_to(&[], addr_rendezvous).await.unwrap();
109                println!("machine 0 sending to {}", addr_rendezvous);
110                tokio::select! {
111                    recv_result = socket.recv_from(&mut recv_bytes) => break recv_result.unwrap(),
112                    () = tokio::time::sleep(Duration::from_secs(1)) => (),
113                }
114            };
115            assert_eq!(recv_addr, addr_rendezvous);
116            let recv_msg = str::from_utf8(&recv_bytes[..recv_len]).unwrap();
117            SocketAddr::from_str(recv_msg).unwrap()
118        };
119        let (recv_len, recv_addr) = loop {
120            socket.send_to("hello from machine 0".as_bytes(), peer_addr_1).await.unwrap();
121            tokio::select! {
122                recv_result = socket.recv_from(&mut recv_bytes) => break recv_result.unwrap(),
123                () = tokio::time::sleep(Duration::from_secs(1)) => (),
124            }
125        };
126        assert_eq!(recv_addr, peer_addr_1);
127        let recv_msg = str::from_utf8(&recv_bytes[..recv_len]).unwrap();
128        assert_eq!(recv_msg, "hello from machine 1");
129        socket.send_to("hello from machine 0".as_bytes(), peer_addr_1).await.unwrap();
130    });
131    let join_handle_1 = machine_1.spawn(async move {
132        let socket = UdpSocket::bind(addrv4!("0.0.0.0:0")).await.unwrap();
133        let mut recv_bytes = [0u8; 100];
134
135        let peer_addr_1 = {
136            let (recv_len, recv_addr) = loop {
137                socket.send_to(&[], addr_rendezvous).await.unwrap();
138                println!("machine 1 sending to {}", addr_rendezvous);
139                tokio::select! {
140                    recv_result = socket.recv_from(&mut recv_bytes) => break recv_result.unwrap(),
141                    () = tokio::time::sleep(Duration::from_secs(1)) => (),
142                }
143            };
144            assert_eq!(recv_addr, addr_rendezvous);
145            let recv_msg = str::from_utf8(&recv_bytes[..recv_len]).unwrap();
146            SocketAddr::from_str(recv_msg).unwrap()
147        };
148        let (recv_len, recv_addr) = loop {
149            socket.send_to("hello from machine 1".as_bytes(), peer_addr_1).await.unwrap();
150            tokio::select! {
151                recv_result = socket.recv_from(&mut recv_bytes) => break recv_result.unwrap(),
152                () = tokio::time::sleep(Duration::from_secs(1)) => (),
153            }
154        };
155        assert_eq!(recv_addr, peer_addr_1);
156        let recv_msg = str::from_utf8(&recv_bytes[..recv_len]).unwrap();
157        assert_eq!(recv_msg, "hello from machine 0");
158        socket.send_to("hello from machine 1".as_bytes(), peer_addr_1).await.unwrap();
159    });
160
161    let () = join_handle_0.await.unwrap().unwrap();
162    let () = join_handle_1.await.unwrap().unwrap();
163    let () = join_handle_rendezvous.await.unwrap().unwrap();
164}

Trait Implementations§

Source§

impl Drop for Machine

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V