-
Notifications
You must be signed in to change notification settings - Fork 6
Expand file tree
/
Copy pathlib.rs
More file actions
281 lines (230 loc) · 7.97 KB
/
lib.rs
File metadata and controls
281 lines (230 loc) · 7.97 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
#![no_std]
extern crate alloc;
use core::{net::Ipv4Addr, time::Duration};
use alloc::format;
use awkernel_async_lib::net::{
tcp::TcpConfig,
udp::{UdpConfig, UdpSocketError},
IpAddr,
};
const INTERFACE_ID: u64 = 0;
// 10.0.2.0/24 is the IP address range of the Qemu's network.
const INTERFACE_ADDR: Ipv4Addr = Ipv4Addr::new(10, 0, 2, 64);
// const INTERFACE_ADDR: Ipv4Addr = Ipv4Addr::new(192, 168, 100, 52); // For experiment.
// const INTERFACE_ADDR: Ipv4Addr = Ipv4Addr::new(192, 168, 122, 24); // libvirt
// 10.0.2.2 is the IP address of the Qemu's host.
const UDP_TCP_DST_ADDR: Ipv4Addr = Ipv4Addr::new(10, 0, 2, 2);
// const UDP_TCP_DST_ADDR: Ipv4Addr = Ipv4Addr::new(192, 168, 100, 1); // For experiment.
// const UDP_TCP_DST_ADDR: Ipv4Addr = Ipv4Addr::new(192, 168, 122, 1); // libvirt
const UDP_DST_PORT: u16 = 26099;
const TCP_DST_PORT: u16 = 26099;
const TCP_LISTEN_PORT: u16 = 26100;
const MULTICAST_ADDR: Ipv4Addr = Ipv4Addr::new(224, 0, 0, 123);
const MULTICAST_PORT1: u16 = 20001;
const MULTICAST_PORT2: u16 = 30001;
pub async fn run() {
awkernel_lib::net::add_ipv4_addr(INTERFACE_ID, INTERFACE_ADDR, 24);
awkernel_async_lib::spawn(
"test udp".into(),
udp_test(),
awkernel_async_lib::scheduler::SchedulerType::FIFO,
)
.await;
awkernel_async_lib::spawn(
"test tcp listen".into(),
tcp_listen_test(),
awkernel_async_lib::scheduler::SchedulerType::FIFO,
)
.await;
awkernel_async_lib::spawn(
"test tcp connect".into(),
tcp_connect_test(),
awkernel_async_lib::scheduler::SchedulerType::FIFO,
)
.await;
awkernel_async_lib::spawn(
"test IPv4 multicast recv".into(),
ipv4_multicast_recv_test(),
awkernel_async_lib::scheduler::SchedulerType::FIFO,
)
.await;
awkernel_async_lib::spawn(
"test IPv4 multicast send".into(),
ipv4_multicast_send_test(),
awkernel_async_lib::scheduler::SchedulerType::FIFO,
)
.await;
}
async fn ipv4_multicast_send_test() {
// Create a UDP socket on interface 0.
let mut socket = awkernel_async_lib::net::udp::UdpSocket::bind_on_interface(
INTERFACE_ID,
&UdpConfig {
addr: IpAddr::new_v4(INTERFACE_ADDR),
..Default::default()
},
)
.unwrap();
let dst_addr = IpAddr::new_v4(MULTICAST_ADDR);
loop {
// Send a UDP packet.
if let Err(e) = socket
.send(b"Hello Awkernel!", &dst_addr, MULTICAST_PORT1)
.await
{
log::error!("Failed to send a UDP packet: {:?}", e);
awkernel_async_lib::sleep(Duration::from_secs(1)).await;
continue;
}
awkernel_async_lib::sleep(Duration::from_secs(1)).await;
}
}
async fn ipv4_multicast_recv_test() {
// Open a UDP socket for multicast.
let config = UdpConfig {
port: Some(MULTICAST_PORT2),
..UdpConfig::default()
};
let mut socket =
awkernel_async_lib::net::udp::UdpSocket::bind_on_interface(INTERFACE_ID, &config).unwrap();
loop {
// Join the multicast group.
loop {
match socket.join_multicast_v4(MULTICAST_ADDR, INTERFACE_ADDR) {
Ok(_) => {
log::debug!("Joined the multicast group.");
break;
}
Err(UdpSocketError::SendError) => (),
_ => {
log::error!("Failed to join the multicast group.");
return;
}
}
awkernel_async_lib::sleep(Duration::from_secs(1)).await;
}
let mut buf = [0u8; 1024 * 2];
for _ in 0..10 {
// Receive a UDP packet.
let result = socket.recv(&mut buf).await.unwrap();
if let Ok(data) = core::str::from_utf8(&buf[..result.0]) {
let msg = format!(
"Received a Multicast packet from {}:{}: {data}",
result.1.get_addr(),
result.2
);
log::debug!("{msg}");
} else {
log::debug!(
"Received a Multicast packet from {}:{}: {} bytes",
result.1.get_addr(),
result.2,
result.0
);
}
}
// Leave the multicast group.
loop {
match socket.leave_multicast_v4(MULTICAST_ADDR, INTERFACE_ADDR) {
Ok(_) => {
log::debug!("Left the multicast group.");
break;
}
Err(UdpSocketError::SendError) => (),
Err(e) => {
log::error!("Failed to leave the multicast group. {e:?}");
return;
}
}
awkernel_async_lib::sleep(Duration::from_secs(1)).await;
}
}
}
async fn tcp_connect_test() {
let Ok(mut stream) = awkernel_async_lib::net::tcp::TcpStream::connect(
INTERFACE_ID,
IpAddr::new_v4(UDP_TCP_DST_ADDR),
TCP_DST_PORT,
&Default::default(),
)
.await
else {
return;
};
let remote = stream.remote_addr().unwrap();
log::debug!(
"Connected to TCP server: {}:{}",
remote.0.get_addr(),
remote.1
);
stream.send(b"Hello, Awkernel!\r\n").await.unwrap();
let mut buf = [0u8; 1024 * 2];
let n = stream.recv(&mut buf).await.unwrap();
let response = core::str::from_utf8(&buf[..n]).unwrap();
log::debug!("Received TCP response: {}", response);
}
async fn tcp_listen_test() {
let config = TcpConfig {
port: Some(TCP_LISTEN_PORT),
..Default::default()
};
let Ok(mut tcp_listener) =
awkernel_async_lib::net::tcp::TcpListener::bind_on_interface(INTERFACE_ID, &config)
else {
return;
};
loop {
let Ok(tcp_stream) = tcp_listener.accept().await else {
log::error!("Failed to accept TCP connection.");
continue;
};
log::debug!("Accepted a TCP connection. {:?}", tcp_stream.remote_addr());
awkernel_async_lib::spawn(
"bogus HTTP server".into(),
bogus_http_server(tcp_stream),
awkernel_async_lib::scheduler::SchedulerType::FIFO,
)
.await;
}
}
async fn bogus_http_server(mut stream: awkernel_async_lib::net::tcp::TcpStream) {
let mut buf = [0u8; 1024 * 2];
let n = stream.recv(&mut buf).await.unwrap();
let request = core::str::from_utf8(&buf[..n]).unwrap();
log::debug!("Received HTTP request: {}", request);
static MSG: &str = "<html><body><h1>Hello, Awkernel!</h1></body></html>\r\n";
let len = MSG.len();
let response = format!("HTTP/1.0 200 OK\r\nContent-Type: text/html; charset=UTF-8\r\nContent-Length: {len}\r\n\r\n");
stream.send(response.as_bytes()).await.unwrap();
stream.send(MSG.as_bytes()).await.unwrap();
}
async fn udp_test() {
// Create a UDP socket on interface 0.
let mut socket = awkernel_async_lib::net::udp::UdpSocket::bind_on_interface(
INTERFACE_ID,
&Default::default(),
)
.unwrap();
let dst_addr = IpAddr::new_v4(UDP_TCP_DST_ADDR);
let mut buf = [0u8; 1024 * 2];
let mut i = 0;
loop {
let t0 = awkernel_lib::time::Time::now();
// Send a UDP packet.
let msg = format!("Hello Awkernel! {}", i);
if let Err(e) = socket.send(msg.as_bytes(), &dst_addr, UDP_DST_PORT).await {
log::error!("Failed to send a UDP packet: {:?}", e);
awkernel_async_lib::sleep(Duration::from_secs(1)).await;
continue;
}
// Receive a UDP packet.
if let Some(Ok(_)) =
awkernel_async_lib::timeout(Duration::from_secs(1), socket.recv(&mut buf)).await
{
let rtt = t0.elapsed().as_micros() as u64;
log::debug!("i = {i}, RTT: {rtt} [us]");
}
awkernel_async_lib::sleep(Duration::from_secs(1)).await;
i += 1;
}
}