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 JoinHandle
s to return None
.
Implementations§
Source§impl Machine
impl Machine
Sourcepub fn new() -> Result<Machine>
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?
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
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}
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}
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}
Sourcepub fn spawn<F, R>(&self, future: F) -> JoinHandle<R>
pub fn spawn<F, R>(&self, future: F) -> JoinHandle<R>
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?
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
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}
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}
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}
Sourcepub fn add_ip_iface(&self) -> IpIfaceBuilder<'_>
pub fn add_ip_iface(&self) -> IpIfaceBuilder<'_>
Adds a network interface to the machine. See the IpIfaceBuilder
docs for details.
Examples found in repository?
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
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}
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}