1use std::{
2 collections::HashMap,
3 net::SocketAddr,
4 pin::Pin,
5 sync::{
6 atomic::{AtomicBool, Ordering},
7 Arc,
8 },
9 task::{Context, Poll, Waker},
10};
11
12use futures::Stream;
13use smoltcp::{
14 iface::{Config as InterfaceConfig, Interface, SocketHandle, SocketSet},
15 phy::Device,
16 socket::tcp::{Socket as TcpSocket, SocketBuffer as TcpSocketBuffer, State as TcpState},
17 storage::RingBuffer,
18 time::{Duration, Instant},
19 wire::{HardwareAddress, IpAddress, IpCidr, IpProtocol, Ipv4Address, Ipv6Address, TcpPacket},
20};
21use spin::Mutex as SpinMutex;
22use tokio::{
23 io::{AsyncRead, AsyncWrite, ReadBuf},
24 sync::{
25 mpsc::{unbounded_channel, Receiver, Sender, UnboundedReceiver, UnboundedSender},
26 Notify,
27 },
28};
29use tracing::{error, trace};
30
31use crate::{
32 device::VirtualDevice,
33 packet::{AnyIpPktFrame, IpPacket},
34 Runner,
35};
36
37#[derive(Debug, Clone, Copy, Eq, PartialEq)]
38enum TcpSocketState {
39 Normal,
40 Close,
41 Closing,
42 Closed,
43}
44
45struct TcpSocketControl {
46 send_buffer: RingBuffer<'static, u8>,
47 send_waker: Option<Waker>,
48 recv_buffer: RingBuffer<'static, u8>,
49 recv_waker: Option<Waker>,
50 recv_state: TcpSocketState,
51 send_state: TcpSocketState,
52}
53
54struct TcpSocketCreation {
55 control: SharedControl,
56 socket: TcpSocket<'static>,
57}
58
59type SharedNotify = Arc<Notify>;
60type SharedControl = Arc<SpinMutex<TcpSocketControl>>;
61
62struct TcpListenerRunner;
63
64impl TcpListenerRunner {
65 #[allow(clippy::too_many_arguments)]
66 fn create(
67 device: VirtualDevice,
68 iface: Interface,
69 iface_ingress_tx: UnboundedSender<Vec<u8>>,
70 iface_ingress_tx_avail: Arc<AtomicBool>,
71 tcp_rx: Receiver<AnyIpPktFrame>,
72 stream_tx: UnboundedSender<TcpStream>,
73 sockets: HashMap<SocketHandle, SharedControl>,
74 tcp_recv_buffer_size: u32,
75 tcp_send_buffer_size: u32,
76 ) -> Runner {
77 Runner::new(async move {
78 let notify = Arc::new(Notify::new());
79 let (socket_tx, socket_rx) = unbounded_channel::<TcpSocketCreation>();
80 let res = tokio::select! {
81 v = Self::handle_packet(notify.clone(), iface_ingress_tx, iface_ingress_tx_avail.clone(), tcp_rx, stream_tx, socket_tx, tcp_recv_buffer_size, tcp_send_buffer_size) => v,
82 v = Self::handle_socket(notify, device, iface, iface_ingress_tx_avail, sockets, socket_rx) => v,
83 };
84 res?;
85 trace!("VirtDevice::poll thread exited");
86 Ok(())
87 })
88 }
89
90 #[allow(clippy::too_many_arguments)]
91 async fn handle_packet(
92 notify: SharedNotify,
93 iface_ingress_tx: UnboundedSender<Vec<u8>>,
94 iface_ingress_tx_avail: Arc<AtomicBool>,
95 mut tcp_rx: Receiver<AnyIpPktFrame>,
96 stream_tx: UnboundedSender<TcpStream>,
97 socket_tx: UnboundedSender<TcpSocketCreation>,
98 tcp_recv_buffer_size: u32,
99 tcp_send_buffer_size: u32,
100 ) -> std::io::Result<()> {
101 while let Some(frame) = tcp_rx.recv().await {
102 let packet = match IpPacket::new_checked(frame.as_slice()) {
103 Ok(p) => p,
104 Err(err) => {
105 error!("invalid TCP IP packet: {:?}", err,);
106 continue;
107 }
108 };
109
110 if matches!(packet.protocol(), IpProtocol::Icmp | IpProtocol::Icmpv6) {
112 iface_ingress_tx
113 .send(frame)
114 .map_err(|e| std::io::Error::new(std::io::ErrorKind::BrokenPipe, e))?;
115 iface_ingress_tx_avail.store(true, Ordering::Release);
116 notify.notify_one();
117 continue;
118 }
119
120 let src_ip = packet.src_addr();
121 let dst_ip = packet.dst_addr();
122 let payload = packet.payload();
123
124 let packet = match TcpPacket::new_checked(payload) {
125 Ok(p) => p,
126 Err(err) => {
127 error!("invalid TCP err: {err}, src_ip: {src_ip}, dst_ip: {dst_ip}, payload: {payload:?}");
128 continue;
129 }
130 };
131 let src_port = packet.src_port();
132 let dst_port = packet.dst_port();
133
134 let src_addr = SocketAddr::new(src_ip, src_port);
135 let dst_addr = SocketAddr::new(dst_ip, dst_port);
136
137 if packet.syn() && !packet.ack() {
139 let mut socket = TcpSocket::new(
140 TcpSocketBuffer::new(vec![0u8; tcp_recv_buffer_size as usize]),
141 TcpSocketBuffer::new(vec![0u8; tcp_send_buffer_size as usize]),
142 );
143 socket.set_keep_alive(Some(Duration::from_secs(28)));
144 socket.set_timeout(Some(Duration::from_secs(7200)));
146 if let Err(err) = socket.listen(dst_addr) {
150 error!("listen error: {:?}", err);
151 continue;
152 }
153
154 trace!("created TCP connection for {} <-> {}", src_addr, dst_addr);
155
156 let control = Arc::new(SpinMutex::new(TcpSocketControl {
157 send_buffer: RingBuffer::new(vec![0u8; tcp_send_buffer_size as usize]),
158 send_waker: None,
159 recv_buffer: RingBuffer::new(vec![0u8; tcp_recv_buffer_size as usize]),
160 recv_waker: None,
161 recv_state: TcpSocketState::Normal,
162 send_state: TcpSocketState::Normal,
163 }));
164
165 stream_tx
166 .send(TcpStream {
167 src_addr,
168 dst_addr,
169 notify: notify.clone(),
170 control: control.clone(),
171 })
172 .map_err(|e| std::io::Error::new(std::io::ErrorKind::BrokenPipe, e))?;
173 socket_tx
174 .send(TcpSocketCreation { control, socket })
175 .map_err(|e| std::io::Error::new(std::io::ErrorKind::BrokenPipe, e))?;
176 }
177
178 iface_ingress_tx
180 .send(frame)
181 .map_err(|e| std::io::Error::new(std::io::ErrorKind::BrokenPipe, e))?;
182 iface_ingress_tx_avail.store(true, Ordering::Release);
183 notify.notify_one();
184 }
185 Ok(())
186 }
187
188 async fn handle_socket(
189 notify: SharedNotify,
190 mut device: VirtualDevice,
191 mut iface: Interface,
192 iface_ingress_tx_avail: Arc<AtomicBool>,
193 mut sockets: HashMap<SocketHandle, SharedControl>,
194 mut socket_rx: UnboundedReceiver<TcpSocketCreation>,
195 ) -> std::io::Result<()> {
196 let mut socket_set = SocketSet::new(vec![]);
197 loop {
198 while let Ok(TcpSocketCreation { control, socket }) = socket_rx.try_recv() {
199 let handle = socket_set.add(socket);
200 sockets.insert(handle, control);
201 }
202
203 let before_poll = Instant::now();
204 let updated_sockets = iface.poll(before_poll, &mut device, &mut socket_set);
205 if matches!(
206 updated_sockets,
207 smoltcp::iface::PollResult::SocketStateChanged
208 ) {
209 trace!("VirtDevice::poll costed {}", Instant::now() - before_poll);
210 }
211
212 let mut sockets_to_remove = Vec::new();
214
215 for (socket_handle, control) in sockets.iter() {
216 let socket_handle = *socket_handle;
217 let socket = socket_set.get_mut::<TcpSocket>(socket_handle);
218 let mut control = control.lock();
219
220 if socket.state() == TcpState::Closed {
222 sockets_to_remove.push(socket_handle);
223
224 control.send_state = TcpSocketState::Closed;
225 control.recv_state = TcpSocketState::Closed;
226
227 if let Some(waker) = control.send_waker.take() {
228 waker.wake();
229 }
230 if let Some(waker) = control.recv_waker.take() {
231 waker.wake();
232 }
233
234 trace!("closed TCP connection");
235 continue;
236 }
237
238 if matches!(control.send_state, TcpSocketState::Close)
243 && control.send_buffer.is_empty()
244 {
245 trace!("closing TCP Write Half, {:?}", socket.state());
246
247 socket.close();
248 control.send_state = TcpSocketState::Closing;
249 }
250
251 let mut wake_receiver = false;
253 while socket.can_recv() && !control.recv_buffer.is_full() {
254 let result = socket.recv(|buffer| {
255 let n = control.recv_buffer.enqueue_slice(buffer);
256 (n, ())
257 });
258
259 match result {
260 Ok(..) => wake_receiver = true,
261 Err(err) => {
262 error!("socket recv error: {:?}, {:?}", err, socket.state());
263
264 socket.abort();
266
267 if matches!(control.recv_state, TcpSocketState::Normal) {
268 control.recv_state = TcpSocketState::Closed;
269 }
270 wake_receiver = true;
271
272 break;
274 }
275 }
276 }
277
278 let states = [
281 TcpState::Listen,
282 TcpState::SynReceived,
283 TcpState::Established,
284 TcpState::FinWait1,
285 TcpState::FinWait2,
286 ];
287 if matches!(control.recv_state, TcpSocketState::Normal)
288 && !socket.may_recv()
289 && !states.contains(&socket.state())
290 {
291 trace!("closed TCP Read Half, {:?}", socket.state());
292
293 control.recv_state = TcpSocketState::Closed;
295 wake_receiver = true;
296 }
297
298 if wake_receiver && control.recv_waker.is_some() {
299 if let Some(waker) = control.recv_waker.take() {
300 waker.wake();
301 }
302 }
303
304 let mut wake_sender = false;
306 while socket.can_send() && !control.send_buffer.is_empty() {
307 let result = socket.send(|buffer| {
308 let n = control.send_buffer.dequeue_slice(buffer);
309 (n, ())
310 });
311
312 match result {
313 Ok(..) => wake_sender = true,
314 Err(err) => {
315 error!("socket send error: {:?}, {:?}", err, socket.state());
316
317 socket.abort();
319
320 if matches!(control.send_state, TcpSocketState::Normal) {
321 control.send_state = TcpSocketState::Closed;
322 }
323 wake_sender = true;
324
325 break;
327 }
328 }
329 }
330
331 if wake_sender && control.send_waker.is_some() {
332 if let Some(waker) = control.send_waker.take() {
333 waker.wake();
334 }
335 }
336 }
337
338 for socket_handle in sockets_to_remove {
339 sockets.remove(&socket_handle);
340 socket_set.remove(socket_handle);
341 }
342
343 if iface_ingress_tx_avail.load(Ordering::Acquire) {
355 tokio::task::yield_now().await;
356 } else {
357 let next_duration = iface
358 .poll_delay(before_poll, &socket_set)
359 .unwrap_or(Duration::from_millis(5));
360 if next_duration != Duration::ZERO {
361 let _ = tokio::time::timeout(
362 tokio::time::Duration::from(next_duration),
363 notify.notified(),
364 )
365 .await;
366 } else {
367 tokio::task::yield_now().await;
368 }
369 }
370 }
371 }
372}
373
374pub struct TcpListener {
375 stream_rx: UnboundedReceiver<TcpStream>,
376}
377
378impl TcpListener {
379 pub(super) fn new(
380 tcp_rx: Receiver<AnyIpPktFrame>,
381 stack_tx: Sender<AnyIpPktFrame>,
382 mtu: usize,
383 tcp_recv_buffer_size: u32,
384 tcp_send_buffer_size: u32,
385 ) -> std::io::Result<(Runner, Self)> {
386 let (mut device, iface_ingress_tx, iface_ingress_tx_avail) =
387 VirtualDevice::new(stack_tx, mtu);
388 let iface = Self::create_interface(&mut device)?;
389
390 let (stream_tx, stream_rx) = unbounded_channel();
391
392 let runner = TcpListenerRunner::create(
393 device,
394 iface,
395 iface_ingress_tx,
396 iface_ingress_tx_avail,
397 tcp_rx,
398 stream_tx,
399 HashMap::new(),
400 tcp_recv_buffer_size,
401 tcp_send_buffer_size,
402 );
403
404 Ok((runner, Self { stream_rx }))
405 }
406
407 fn create_interface<D>(device: &mut D) -> std::io::Result<Interface>
408 where
409 D: Device + ?Sized,
410 {
411 let mut iface_config = InterfaceConfig::new(HardwareAddress::Ip);
412 iface_config.random_seed = rand::random();
413 let mut iface = Interface::new(iface_config, device, Instant::now());
414 iface.update_ip_addrs(|ip_addrs| {
415 ip_addrs
416 .push(IpCidr::new(IpAddress::v4(0, 0, 0, 1), 0))
417 .expect("iface IPv4");
418 ip_addrs
419 .push(IpCidr::new(IpAddress::v6(0, 0, 0, 0, 0, 0, 0, 1), 0))
420 .expect("iface IPv6");
421 });
422 iface
423 .routes_mut()
424 .add_default_ipv4_route(Ipv4Address::new(0, 0, 0, 1))
425 .map_err(|e| std::io::Error::new(std::io::ErrorKind::AddrNotAvailable, e))?;
426 iface
427 .routes_mut()
428 .add_default_ipv6_route(Ipv6Address::new(0, 0, 0, 0, 0, 0, 0, 1))
429 .map_err(|e| std::io::Error::new(std::io::ErrorKind::AddrNotAvailable, e))?;
430 iface.set_any_ip(true);
431 Ok(iface)
432 }
433}
434
435impl Stream for TcpListener {
436 type Item = (TcpStream, SocketAddr, SocketAddr);
437
438 fn poll_next(
439 mut self: std::pin::Pin<&mut Self>,
440 cx: &mut std::task::Context<'_>,
441 ) -> std::task::Poll<Option<Self::Item>> {
442 self.stream_rx.poll_recv(cx).map(|stream| {
443 stream.map(|stream| {
444 let local_addr = *stream.local_addr();
445 let remote_addr: SocketAddr = *stream.remote_addr();
446 (stream, local_addr, remote_addr)
447 })
448 })
449 }
450}
451
452pub struct TcpStream {
453 src_addr: SocketAddr,
454 dst_addr: SocketAddr,
455 notify: SharedNotify,
456 control: SharedControl,
457}
458
459impl Drop for TcpStream {
460 fn drop(&mut self) {
461 let mut control = self.control.lock();
462
463 if matches!(control.recv_state, TcpSocketState::Normal) {
464 control.recv_state = TcpSocketState::Close;
465 }
466
467 if matches!(control.send_state, TcpSocketState::Normal) {
468 control.send_state = TcpSocketState::Close;
469 }
470
471 self.notify.notify_one();
472 }
473}
474
475impl TcpStream {
476 pub fn local_addr(&self) -> &SocketAddr {
477 &self.src_addr
478 }
479
480 pub fn remote_addr(&self) -> &SocketAddr {
481 &self.dst_addr
482 }
483}
484
485impl AsyncRead for TcpStream {
486 fn poll_read(
487 self: Pin<&mut Self>,
488 cx: &mut Context<'_>,
489 buf: &mut ReadBuf<'_>,
490 ) -> Poll<std::io::Result<()>> {
491 let mut control = self.control.lock();
492
493 if control.recv_buffer.is_empty() {
495 if matches!(control.recv_state, TcpSocketState::Closed) {
497 return Ok(()).into();
498 }
499
500 if let Some(old_waker) = control.recv_waker.replace(cx.waker().clone()) {
502 if !old_waker.will_wake(cx.waker()) {
503 old_waker.wake();
504 }
505 }
506
507 return Poll::Pending;
508 }
509
510 let recv_buf = buf.initialize_unfilled();
511 let n = control.recv_buffer.dequeue_slice(recv_buf);
512 buf.advance(n);
513
514 if n > 0 {
515 self.notify.notify_one();
516 }
517
518 Ok(()).into()
519 }
520}
521
522impl AsyncWrite for TcpStream {
523 fn poll_write(
524 self: Pin<&mut Self>,
525 cx: &mut Context<'_>,
526 buf: &[u8],
527 ) -> Poll<std::io::Result<usize>> {
528 let mut control = self.control.lock();
529
530 if !matches!(control.send_state, TcpSocketState::Normal) {
532 return Err(std::io::ErrorKind::BrokenPipe.into()).into();
533 }
534
535 if control.send_buffer.is_full() {
538 if let Some(old_waker) = control.send_waker.replace(cx.waker().clone()) {
539 if !old_waker.will_wake(cx.waker()) {
540 old_waker.wake();
541 }
542 }
543
544 return Poll::Pending;
545 }
546
547 let n = control.send_buffer.enqueue_slice(buf);
548
549 if n > 0 {
550 self.notify.notify_one();
551 }
552
553 Ok(n).into()
554 }
555
556 fn poll_flush(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
557 Ok(()).into()
558 }
559
560 fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
561 let mut control = self.control.lock();
562
563 if matches!(control.send_state, TcpSocketState::Closed) {
564 return Ok(()).into();
565 }
566
567 if matches!(control.send_state, TcpSocketState::Normal) {
569 control.send_state = TcpSocketState::Close;
570 }
571
572 if let Some(old_waker) = control.send_waker.replace(cx.waker().clone()) {
573 if !old_waker.will_wake(cx.waker()) {
574 old_waker.wake();
575 }
576 }
577
578 self.notify.notify_one();
579
580 Poll::Pending
581 }
582}