1use std::{
2 future::Future,
3 io,
4 mem::MaybeUninit,
5 net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr},
6 pin::Pin,
7 sync::{Arc, RwLock},
8 task::{Context, Poll},
9 time::Duration,
10};
11
12use virtual_mio::InterestHandler;
13use virtual_net::{
14 NetworkError, VirtualIcmpSocket, VirtualNetworking, VirtualRawSocket, VirtualTcpBoundSocket,
15 VirtualTcpListener, VirtualTcpSocket, VirtualUdpSocket, net_error_into_io_err,
16};
17use wasmer_types::MemorySize;
18use wasmer_wasix_types::wasi::{Addressfamily, Errno, Rights, SockProto, Sockoption, Socktype};
19
20use crate::{VirtualTaskManager, net::net_error_into_wasi_err};
21
22#[derive(Debug)]
23pub enum InodeHttpSocketType {
24 Request,
26 Response,
28 Headers,
30}
31
32type TcpConnectFuture<'a> =
33 Pin<Box<dyn Future<Output = Result<Box<dyn VirtualTcpSocket + Sync>, Errno>> + 'a>>;
34
35#[derive(Debug)]
36pub struct SocketProperties {
37 pub family: Addressfamily,
38 pub ty: Socktype,
39 pub pt: SockProto,
40 pub only_v6: bool,
41 pub reuse_port: bool,
42 pub reuse_addr: bool,
43 pub no_delay: Option<bool>,
44 pub keep_alive: Option<bool>,
45 pub dont_route: Option<bool>,
46 pub send_buf_size: Option<usize>,
47 pub recv_buf_size: Option<usize>,
48 pub write_timeout: Option<Duration>,
49 pub read_timeout: Option<Duration>,
50 pub accept_timeout: Option<Duration>,
51 pub connect_timeout: Option<Duration>,
52 pub handler: Option<Box<dyn InterestHandler + Send + Sync>>,
53}
54
55impl SocketProperties {
56 fn snapshot_for_bound(&self) -> Self {
57 Self {
58 family: self.family,
59 ty: self.ty,
60 pt: self.pt,
61 only_v6: self.only_v6,
62 reuse_port: self.reuse_port,
63 reuse_addr: self.reuse_addr,
64 no_delay: self.no_delay,
65 keep_alive: self.keep_alive,
66 dont_route: self.dont_route,
67 send_buf_size: self.send_buf_size,
68 recv_buf_size: self.recv_buf_size,
69 write_timeout: self.write_timeout,
70 read_timeout: self.read_timeout,
71 accept_timeout: self.accept_timeout,
72 connect_timeout: self.connect_timeout,
73 handler: None,
74 }
75 }
76}
77
78#[derive(Debug)]
79pub enum InodeSocketKind {
80 PreSocket {
81 props: SocketProperties,
82 addr: Option<SocketAddr>,
83 },
84 Icmp(Box<dyn VirtualIcmpSocket + Sync>),
85 Raw(Box<dyn VirtualRawSocket + Sync>),
86 TcpListener {
87 socket: Box<dyn VirtualTcpListener + Sync>,
88 accept_timeout: Option<Duration>,
89 },
90 TcpStream {
91 socket: Box<dyn VirtualTcpSocket + Sync>,
92 write_timeout: Option<Duration>,
93 read_timeout: Option<Duration>,
94 },
95 BoundTcp {
96 socket: Box<dyn VirtualTcpBoundSocket + Sync>,
97 props: SocketProperties,
98 },
99 UdpSocket {
100 socket: Box<dyn VirtualUdpSocket + Sync>,
101 peer: Option<SocketAddr>,
102 },
103 RemoteSocket {
104 props: SocketProperties,
105 local_addr: SocketAddr,
106 peer_addr: SocketAddr,
107 ttl: u32,
108 multicast_ttl: u32,
109 is_dead: bool,
110 },
111}
112
113pub enum WasiSocketOption {
114 Noop,
115 ReusePort,
116 ReuseAddr,
117 NoDelay,
118 DontRoute,
119 OnlyV6,
120 Broadcast,
121 MulticastLoopV4,
122 MulticastLoopV6,
123 Promiscuous,
124 Listening,
125 LastError,
126 KeepAlive,
127 Linger,
128 OobInline,
129 RecvBufSize,
130 SendBufSize,
131 RecvLowat,
132 SendLowat,
133 RecvTimeout,
134 SendTimeout,
135 ConnectTimeout,
136 AcceptTimeout,
137 Ttl,
138 MulticastTtlV4,
139 Type,
140 Proto,
141}
142
143impl TryFrom<Sockoption> for WasiSocketOption {
144 type Error = Errno;
145
146 fn try_from(opt: Sockoption) -> Result<Self, Self::Error> {
147 use WasiSocketOption::*;
148 match opt {
149 Sockoption::Noop => Ok(Noop),
150 Sockoption::ReusePort => Ok(ReusePort),
151 Sockoption::ReuseAddr => Ok(ReuseAddr),
152 Sockoption::NoDelay => Ok(NoDelay),
153 Sockoption::DontRoute => Ok(DontRoute),
154 Sockoption::OnlyV6 => Ok(OnlyV6),
155 Sockoption::Broadcast => Ok(Broadcast),
156 Sockoption::MulticastLoopV4 => Ok(MulticastLoopV4),
157 Sockoption::MulticastLoopV6 => Ok(MulticastLoopV6),
158 Sockoption::Promiscuous => Ok(Promiscuous),
159 Sockoption::Listening => Ok(Listening),
160 Sockoption::LastError => Ok(LastError),
161 Sockoption::KeepAlive => Ok(KeepAlive),
162 Sockoption::Linger => Ok(Linger),
163 Sockoption::OobInline => Ok(OobInline),
164 Sockoption::RecvBufSize => Ok(RecvBufSize),
165 Sockoption::SendBufSize => Ok(SendBufSize),
166 Sockoption::RecvLowat => Ok(RecvLowat),
167 Sockoption::SendLowat => Ok(SendLowat),
168 Sockoption::RecvTimeout => Ok(RecvTimeout),
169 Sockoption::SendTimeout => Ok(SendTimeout),
170 Sockoption::ConnectTimeout => Ok(ConnectTimeout),
171 Sockoption::AcceptTimeout => Ok(AcceptTimeout),
172 Sockoption::Ttl => Ok(Ttl),
173 Sockoption::MulticastTtlV4 => Ok(MulticastTtlV4),
174 Sockoption::Type => Ok(Type),
175 Sockoption::Proto => Ok(Proto),
176 _ => Err(Errno::Inval),
177 }
178 }
179}
180
181#[derive(Debug)]
182pub enum WasiSocketStatus {
183 Opening,
184 Opened,
185 Closed,
186 Failed,
187}
188
189#[derive(Debug, Copy, Clone, PartialEq, Eq)]
190pub enum TimeType {
191 ReadTimeout,
192 WriteTimeout,
193 AcceptTimeout,
194 ConnectTimeout,
195 BindTimeout,
196 Linger,
197}
198
199impl From<TimeType> for wasmer_journal::SocketOptTimeType {
200 fn from(value: TimeType) -> Self {
201 match value {
202 TimeType::ReadTimeout => Self::ReadTimeout,
203 TimeType::WriteTimeout => Self::WriteTimeout,
204 TimeType::AcceptTimeout => Self::AcceptTimeout,
205 TimeType::ConnectTimeout => Self::ConnectTimeout,
206 TimeType::BindTimeout => Self::BindTimeout,
207 TimeType::Linger => Self::Linger,
208 }
209 }
210}
211
212impl From<wasmer_journal::SocketOptTimeType> for TimeType {
213 fn from(value: wasmer_journal::SocketOptTimeType) -> Self {
214 use wasmer_journal::SocketOptTimeType;
215 match value {
216 SocketOptTimeType::ReadTimeout => TimeType::ReadTimeout,
217 SocketOptTimeType::WriteTimeout => TimeType::WriteTimeout,
218 SocketOptTimeType::AcceptTimeout => TimeType::AcceptTimeout,
219 SocketOptTimeType::ConnectTimeout => TimeType::ConnectTimeout,
220 SocketOptTimeType::BindTimeout => TimeType::BindTimeout,
221 SocketOptTimeType::Linger => TimeType::Linger,
222 }
223 }
224}
225
226#[derive(Debug)]
227pub(crate) struct InodeSocketProtected {
228 pub kind: InodeSocketKind,
229}
230
231#[derive(Debug)]
232pub(crate) struct InodeSocketInner {
233 pub protected: RwLock<InodeSocketProtected>,
234}
235
236#[derive(Debug, Clone)]
237pub struct InodeSocket {
238 pub(crate) inner: Arc<InodeSocketInner>,
239}
240
241impl InodeSocket {
242 pub fn new(kind: InodeSocketKind) -> Self {
243 let protected = InodeSocketProtected { kind };
244 Self {
245 inner: Arc::new(InodeSocketInner {
246 protected: RwLock::new(protected),
247 }),
248 }
249 }
250
251 pub fn poll_read_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<usize>> {
252 let mut inner = self.inner.protected.write().unwrap();
253 inner.poll_read_ready(cx)
254 }
255
256 pub fn poll_write_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<usize>> {
257 let mut inner = self.inner.protected.write().unwrap();
258 inner.poll_write_ready(cx)
259 }
260
261 pub async fn auto_bind_udp(
264 &self,
265 tasks: &dyn VirtualTaskManager,
266 net: &dyn VirtualNetworking,
267 ) -> Result<Option<InodeSocket>, Errno> {
268 let timeout = self
269 .opt_time(TimeType::BindTimeout)
270 .ok()
271 .flatten()
272 .unwrap_or(Duration::from_secs(30));
273 let family = {
274 let inner = self.inner.protected.read().unwrap();
275 match &inner.kind {
276 InodeSocketKind::PreSocket { props, .. } if props.ty == Socktype::Dgram => {
277 Some(props.family)
278 }
279 _ => None,
280 }
281 };
282 let Some(family) = family else {
283 return Ok(None);
284 };
285
286 let addr = match family {
287 Addressfamily::Inet4 => SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0),
288 Addressfamily::Inet6 => SocketAddr::new(IpAddr::V6(Ipv6Addr::UNSPECIFIED), 0),
289 _ => return Err(Errno::Notsup),
290 };
291
292 self.bind_internal(tasks, net, addr, timeout).await
293 }
294
295 pub async fn bind(
296 &self,
297 tasks: &dyn VirtualTaskManager,
298 net: &dyn VirtualNetworking,
299 set_addr: SocketAddr,
300 ) -> Result<Option<InodeSocket>, Errno> {
301 let timeout = self
302 .opt_time(TimeType::BindTimeout)
303 .ok()
304 .flatten()
305 .unwrap_or(Duration::from_secs(30));
306 self.bind_internal(tasks, net, set_addr, timeout).await
307 }
308
309 async fn bind_internal(
310 &self,
311 tasks: &dyn VirtualTaskManager,
312 net: &dyn VirtualNetworking,
313 set_addr: SocketAddr,
314 timeout: Duration,
315 ) -> Result<Option<InodeSocket>, Errno> {
316 enum PendingBind {
317 Tcp {
318 addr: SocketAddr,
319 props: SocketProperties,
320 },
321 Udp {
322 addr: SocketAddr,
323 reuse_port: bool,
324 reuse_addr: bool,
325 },
326 }
327
328 let bind = {
329 let mut inner = self.inner.protected.write().unwrap();
330 match &mut inner.kind {
331 InodeSocketKind::PreSocket { props, addr, .. } => {
332 match props.family {
333 Addressfamily::Inet4 => {
334 if !set_addr.is_ipv4() {
335 tracing::debug!(
336 "IP address is the wrong type IPv4 ({set_addr}) vs IPv6 family"
337 );
338 return Err(Errno::Inval);
339 }
340 }
341 Addressfamily::Inet6 => {
342 if !set_addr.is_ipv6() {
343 tracing::debug!(
344 "IP address is the wrong type IPv6 ({set_addr}) vs IPv4 family"
345 );
346 return Err(Errno::Inval);
347 }
348 }
349 _ => {
350 return Err(Errno::Notsup);
351 }
352 }
353
354 addr.replace(set_addr);
355 let addr = (*addr).unwrap();
356
357 match props.ty {
358 Socktype::Stream => PendingBind::Tcp {
359 addr,
360 props: props.snapshot_for_bound(),
361 },
362 Socktype::Dgram => PendingBind::Udp {
363 addr,
364 reuse_port: props.reuse_port,
365 reuse_addr: props.reuse_addr,
366 },
367 _ => return Err(Errno::Inval),
368 }
369 }
370 InodeSocketKind::RemoteSocket {
371 props,
372 local_addr: addr,
373 ..
374 } => {
375 match props.family {
376 Addressfamily::Inet4 => {
377 if !set_addr.is_ipv4() {
378 tracing::debug!(
379 "IP address is the wrong type IPv4 ({set_addr}) vs IPv6 family"
380 );
381 return Err(Errno::Inval);
382 }
383 }
384 Addressfamily::Inet6 => {
385 if !set_addr.is_ipv6() {
386 tracing::debug!(
387 "IP address is the wrong type IPv6 ({set_addr}) vs IPv4 family"
388 );
389 return Err(Errno::Inval);
390 }
391 }
392 _ => {
393 return Err(Errno::Notsup);
394 }
395 }
396
397 *addr = set_addr;
398 let addr = *addr;
399
400 match props.ty {
401 Socktype::Stream => {
402 return Ok(None);
405 }
406 Socktype::Dgram => PendingBind::Udp {
407 addr,
408 reuse_port: props.reuse_port,
409 reuse_addr: props.reuse_addr,
410 },
411 _ => return Err(Errno::Inval),
412 }
413 }
414 InodeSocketKind::BoundTcp { .. } => return Err(Errno::Inval),
415 _ => return Err(Errno::Notsup),
416 }
417 };
418
419 match bind {
420 PendingBind::Tcp { addr, mut props } => {
421 tokio::select! {
422 socket = net.bind_tcp(
423 addr,
424 props.only_v6,
425 props.reuse_port,
426 props.reuse_addr,
427 ) => {
428 match socket {
429 Ok(socket) => {
430 props.handler = {
431 let mut inner = self.inner.protected.write().unwrap();
432 match &mut inner.kind {
433 InodeSocketKind::PreSocket { props: live_props, .. } => {
434 live_props.handler.take()
435 }
436 _ => return Err(Errno::Inval),
437 }
438 };
439 Ok(Some(InodeSocket::new(InodeSocketKind::BoundTcp { socket, props })))
440 }
441 Err(NetworkError::Unsupported) => {
442 tracing::debug!(
443 "bind_tcp unsupported by networking backend; leaving socket unbound"
444 );
445 let mut inner = self.inner.protected.write().unwrap();
446 if let InodeSocketKind::PreSocket { addr, .. } = &mut inner.kind {
447 addr.take();
448 }
449 Err(Errno::Notsup)
450 }
451 Err(err) => {
452 let mut inner = self.inner.protected.write().unwrap();
456 if let InodeSocketKind::PreSocket { addr, .. } = &mut inner.kind {
457 addr.take();
458 }
459 Err(net_error_into_wasi_err(err))
460 }
461 }
462 },
463 _ = tasks.sleep_now(timeout) => {
464 let mut inner = self.inner.protected.write().unwrap();
466 if let InodeSocketKind::PreSocket { addr, .. } = &mut inner.kind {
467 addr.take();
468 }
469 Err(Errno::Timedout)
470 }
471 }
472 }
473 PendingBind::Udp {
474 addr,
475 reuse_port,
476 reuse_addr,
477 } => {
478 tokio::select! {
479 socket = net.bind_udp(addr, reuse_port, reuse_addr) => {
480 match socket {
481 Ok(socket) => Ok(Some(InodeSocket::new(InodeSocketKind::UdpSocket {
482 socket,
483 peer: None,
484 }))),
485 Err(err) => {
486 let mut inner = self.inner.protected.write().unwrap();
487 if let InodeSocketKind::PreSocket { addr, .. } = &mut inner.kind {
488 addr.take();
489 }
490 Err(net_error_into_wasi_err(err))
491 }
492 }
493 },
494 _ = tasks.sleep_now(timeout) => {
495 let mut inner = self.inner.protected.write().unwrap();
496 if let InodeSocketKind::PreSocket { addr, .. } = &mut inner.kind {
497 addr.take();
498 }
499 Err(Errno::Timedout)
500 }
501 }
502 }
503 }
504 }
505
506 pub async fn listen(
507 &self,
508 tasks: &dyn VirtualTaskManager,
509 net: &dyn VirtualNetworking,
510 _backlog: usize,
511 ) -> Result<Option<InodeSocket>, Errno> {
512 let timeout = self
513 .opt_time(TimeType::AcceptTimeout)
514 .ok()
515 .flatten()
516 .unwrap_or(Duration::from_secs(30));
517
518 let socket = {
519 let mut inner = self.inner.protected.write().unwrap();
520 match &mut inner.kind {
521 InodeSocketKind::PreSocket { props, addr, .. } => match props.ty {
522 Socktype::Stream => {
523 if addr.is_none() {
524 tracing::warn!("wasi[?]::sock_listen - failed - address not set");
525 return Err(Errno::Inval);
526 }
527 let addr = *addr.as_ref().unwrap();
528 let only_v6 = props.only_v6;
529 let reuse_port = props.reuse_port;
530 let reuse_addr = props.reuse_addr;
531 drop(inner);
532
533 net.listen_tcp(addr, only_v6, reuse_port, reuse_addr)
534 }
535 ty => {
536 tracing::warn!(
537 "wasi[?]::sock_listen - failed - not supported(pre-socket:{:?})",
538 ty
539 );
540 return Err(Errno::Notsup);
541 }
542 },
543 InodeSocketKind::RemoteSocket {
544 props,
545 local_addr: addr,
546 ..
547 } => match props.ty {
548 Socktype::Stream => {
549 let addr = *addr;
550 let only_v6 = props.only_v6;
551 let reuse_port = props.reuse_port;
552 let reuse_addr = props.reuse_addr;
553 drop(inner);
554
555 net.listen_tcp(addr, only_v6, reuse_port, reuse_addr)
556 }
557 ty => {
558 tracing::warn!(
559 "wasi[?]::sock_listen - failed - not supported(remote-socket:{:?})",
560 ty
561 );
562 return Err(Errno::Notsup);
563 }
564 },
565 InodeSocketKind::BoundTcp { socket, .. } => {
566 return Ok(Some(InodeSocket::new(InodeSocketKind::TcpListener {
567 socket: socket.listen().map_err(net_error_into_wasi_err)?,
568 accept_timeout: Some(timeout),
569 })));
570 }
571 InodeSocketKind::Icmp(_) => {
572 tracing::warn!("wasi[?]::sock_listen - failed - not supported(icmp)");
573 return Err(Errno::Notsup);
574 }
575 InodeSocketKind::Raw(_) => {
576 tracing::warn!("wasi[?]::sock_listen - failed - not supported(raw)");
577 return Err(Errno::Notsup);
578 }
579 InodeSocketKind::TcpListener { .. } => {
580 tracing::warn!(
581 "wasi[?]::sock_listen - failed - already listening (tcp-listener)"
582 );
583 return Err(Errno::Notsup);
584 }
585 InodeSocketKind::TcpStream { .. } => {
586 tracing::warn!("wasi[?]::sock_listen - failed - not supported(tcp-stream)");
587 return Err(Errno::Notsup);
588 }
589 InodeSocketKind::UdpSocket { .. } => {
590 tracing::warn!("wasi[?]::sock_listen - failed - not supported(udp-socket)");
591 return Err(Errno::Notsup);
592 }
593 }
594 };
595
596 tokio::select! {
597 socket = socket => {
598 let socket = socket.map_err(net_error_into_wasi_err)?;
599 Ok(Some(InodeSocket::new(InodeSocketKind::TcpListener {
600 socket,
601 accept_timeout: Some(timeout),
602 })))
603 },
604 _ = tasks.sleep_now(timeout) => Err(Errno::Timedout)
605 }
606 }
607
608 pub async fn accept(
609 &self,
610 tasks: &dyn VirtualTaskManager,
611 nonblocking: bool,
612 timeout: Option<Duration>,
613 ) -> Result<(Box<dyn VirtualTcpSocket + Sync>, SocketAddr), Errno> {
614 struct SocketAccepter<'a> {
615 sock: &'a InodeSocket,
616 nonblocking: bool,
617 handler_registered: bool,
618 }
619 impl Drop for SocketAccepter<'_> {
620 fn drop(&mut self) {
621 if self.handler_registered {
622 let mut inner = self.sock.inner.protected.write().unwrap();
623 inner.remove_handler();
624 }
625 }
626 }
627 impl Future for SocketAccepter<'_> {
628 type Output = Result<(Box<dyn VirtualTcpSocket + Sync>, SocketAddr), Errno>;
629 fn poll(
630 mut self: Pin<&mut Self>,
631 cx: &mut std::task::Context<'_>,
632 ) -> std::task::Poll<Self::Output> {
633 loop {
634 let mut inner = self.sock.inner.protected.write().unwrap();
635 return match &mut inner.kind {
636 InodeSocketKind::TcpListener { socket, .. } => match socket.try_accept() {
637 Ok((child, addr)) => Poll::Ready(Ok((child, addr))),
638 Err(NetworkError::WouldBlock) if self.nonblocking => {
639 Poll::Ready(Err(Errno::Again))
640 }
641 Err(NetworkError::WouldBlock) if !self.handler_registered => {
642 let res = socket.set_handler(cx.waker().into());
643 if let Err(err) = res {
644 return Poll::Ready(Err(net_error_into_wasi_err(err)));
645 }
646 drop(inner);
647 self.handler_registered = true;
648 continue;
649 }
650 Err(NetworkError::WouldBlock) => Poll::Pending,
651 Err(err) => Poll::Ready(Err(net_error_into_wasi_err(err))),
652 },
653 InodeSocketKind::PreSocket { .. } => Poll::Ready(Err(Errno::Notconn)),
654 _ => Poll::Ready(Err(Errno::Notsup)),
655 };
656 }
657 }
658 }
659
660 let acceptor = SocketAccepter {
661 sock: self,
662 nonblocking,
663 handler_registered: false,
664 };
665 if let Some(timeout) = timeout {
666 tokio::select! {
667 res = acceptor => res,
668 _ = tasks.sleep_now(timeout) => Err(Errno::Timedout)
669 }
670 } else {
671 acceptor.await
672 }
673 }
674
675 pub fn close(&self) -> Result<(), Errno> {
676 let mut inner = self.inner.protected.write().unwrap();
677 match &mut inner.kind {
678 InodeSocketKind::TcpListener { .. } => {}
679 InodeSocketKind::TcpStream { socket, .. } => {
680 socket.close().map_err(net_error_into_wasi_err)?;
681 }
682 InodeSocketKind::BoundTcp { .. } => {}
683 InodeSocketKind::Icmp(_) => {}
684 InodeSocketKind::UdpSocket { .. } => {}
685 InodeSocketKind::Raw(_) => {}
686 InodeSocketKind::PreSocket { .. } => return Err(Errno::Notconn),
687 InodeSocketKind::RemoteSocket { .. } => {}
688 };
689 Ok(())
690 }
691
692 pub async fn connect(
693 &mut self,
694 tasks: &dyn VirtualTaskManager,
695 net: &dyn VirtualNetworking,
696 peer: SocketAddr,
697 timeout: Option<std::time::Duration>,
698 nonblocking: bool,
699 ) -> Result<Option<InodeSocket>, Errno> {
700 let new_write_timeout;
701 let new_read_timeout;
702
703 let timeout = timeout
704 .or_else(|| self.opt_time(TimeType::ConnectTimeout).ok().flatten())
705 .unwrap_or(Duration::from_secs(30));
706
707 let handler;
708 let connect: TcpConnectFuture<'_> = {
709 let mut inner = self.inner.protected.write().unwrap();
710 match &mut inner.kind {
711 InodeSocketKind::PreSocket { props, addr, .. } => {
712 handler = props.handler.take();
713 new_write_timeout = props.write_timeout;
714 new_read_timeout = props.read_timeout;
715 match props.ty {
716 Socktype::Stream => {
717 let no_delay = props.no_delay;
718 let keep_alive = props.keep_alive;
719 let dont_route = props.dont_route;
720 let addr = match addr {
721 Some(a) => *a,
722 None => {
723 let ip = match peer.is_ipv4() {
724 true => IpAddr::V4(Ipv4Addr::UNSPECIFIED),
725 false => IpAddr::V6(Ipv6Addr::UNSPECIFIED),
726 };
727 SocketAddr::new(ip, 0)
728 }
729 };
730 Box::pin(async move {
731 let mut ret = net
732 .connect_tcp(addr, peer)
733 .await
734 .map_err(net_error_into_wasi_err)?;
735 if let Some(no_delay) = no_delay {
736 ret.set_nodelay(no_delay).ok();
737 }
738 if let Some(keep_alive) = keep_alive {
739 ret.set_keepalive(keep_alive).ok();
740 }
741 if let Some(dont_route) = dont_route {
742 ret.set_dontroute(dont_route).ok();
743 }
744 if !nonblocking {
745 futures::future::poll_fn(|cx| ret.poll_write_ready(cx))
746 .await
747 .map_err(net_error_into_wasi_err)?;
748 }
749 Ok(ret)
750 })
751 }
752 Socktype::Dgram => return Err(Errno::Inval),
753 _ => return Err(Errno::Notsup),
754 }
755 }
756 InodeSocketKind::BoundTcp { socket, props } => {
757 handler = props.handler.take();
758 new_write_timeout = props.write_timeout;
759 new_read_timeout = props.read_timeout;
760 match props.ty {
761 Socktype::Stream => {
762 let no_delay = props.no_delay;
763 let keep_alive = props.keep_alive;
764 let dont_route = props.dont_route;
765 let mut ret = socket.connect(peer).map_err(net_error_into_wasi_err)?;
766 if let Some(no_delay) = no_delay {
767 ret.set_nodelay(no_delay).ok();
768 }
769 if let Some(keep_alive) = keep_alive {
770 ret.set_keepalive(keep_alive).ok();
771 }
772 if let Some(dont_route) = dont_route {
773 ret.set_dontroute(dont_route).ok();
774 }
775 Box::pin(async move {
776 if !nonblocking {
777 futures::future::poll_fn(|cx| ret.poll_write_ready(cx))
778 .await
779 .map_err(net_error_into_wasi_err)?;
780 }
781 Ok(ret)
782 })
783 }
784 Socktype::Dgram => return Err(Errno::Inval),
785 _ => return Err(Errno::Notsup),
786 }
787 }
788 InodeSocketKind::UdpSocket {
789 peer: target_peer, ..
790 } => {
791 target_peer.replace(peer);
792 return Ok(None);
793 }
794 InodeSocketKind::RemoteSocket { peer_addr, .. } => {
795 *peer_addr = peer;
796 return Ok(None);
797 }
798 _ => return Err(Errno::Notsup),
799 }
800 };
801
802 let mut socket = tokio::select! {
803 res = connect => res?,
804 _ = tasks.sleep_now(timeout) => return Err(Errno::Timedout)
805 };
806
807 if let Some(handler) = handler {
808 socket
809 .set_handler(handler)
810 .map_err(net_error_into_wasi_err)?;
811 }
812
813 let socket = InodeSocket::new(InodeSocketKind::TcpStream {
814 socket,
815 write_timeout: new_write_timeout,
816 read_timeout: new_read_timeout,
817 });
818
819 Ok(Some(socket))
820 }
821
822 pub fn status(&self) -> Result<WasiSocketStatus, Errno> {
823 let inner = self.inner.protected.read().unwrap();
824 Ok(match &inner.kind {
825 InodeSocketKind::PreSocket { .. } => WasiSocketStatus::Opening,
826 InodeSocketKind::BoundTcp { .. } => WasiSocketStatus::Opened,
827 InodeSocketKind::TcpListener { .. } => WasiSocketStatus::Opened,
828 InodeSocketKind::TcpStream { socket, .. } => match socket.status() {
829 Ok(virtual_net::SocketStatus::Opening) => WasiSocketStatus::Opening,
830 Ok(virtual_net::SocketStatus::Opened) => WasiSocketStatus::Opened,
831 Ok(virtual_net::SocketStatus::Closed) => WasiSocketStatus::Closed,
832 Ok(virtual_net::SocketStatus::Failed) => WasiSocketStatus::Failed,
833 Err(_) => WasiSocketStatus::Failed,
834 },
835 InodeSocketKind::UdpSocket { .. } => WasiSocketStatus::Opened,
836 InodeSocketKind::RemoteSocket { is_dead, .. } => match is_dead {
837 true => WasiSocketStatus::Closed,
838 false => WasiSocketStatus::Opened,
839 },
840 _ => WasiSocketStatus::Failed,
841 })
842 }
843
844 pub fn last_error(&self) -> Result<Errno, Errno> {
845 self.status()?;
846
847 let inner = self.inner.protected.read().unwrap();
848 match &inner.kind {
849 InodeSocketKind::TcpStream { socket, .. } => socket
850 .last_error()
851 .map_err(net_error_into_wasi_err)
852 .map(|err| err.map(net_error_into_wasi_err).unwrap_or(Errno::Success)),
853 InodeSocketKind::RemoteSocket { is_dead, .. } if *is_dead => Ok(Errno::Connreset),
854 _ => Ok(Errno::Success),
855 }
856 }
857
858 pub fn addr_local(&self) -> Result<SocketAddr, Errno> {
859 let inner = self.inner.protected.read().unwrap();
860 Ok(match &inner.kind {
861 InodeSocketKind::PreSocket { props, addr, .. } => {
862 if let Some(addr) = addr {
863 *addr
864 } else {
865 SocketAddr::new(
866 match props.family {
867 Addressfamily::Inet4 => IpAddr::V4(Ipv4Addr::UNSPECIFIED),
868 Addressfamily::Inet6 => IpAddr::V6(Ipv6Addr::UNSPECIFIED),
869 _ => return Err(Errno::Inval),
870 },
871 0,
872 )
873 }
874 }
875 InodeSocketKind::Icmp(sock) => sock.addr_local().map_err(net_error_into_wasi_err)?,
876 InodeSocketKind::TcpListener { socket, .. } => {
877 socket.addr_local().map_err(net_error_into_wasi_err)?
878 }
879 InodeSocketKind::TcpStream { socket, .. } => {
880 socket.addr_local().map_err(net_error_into_wasi_err)?
881 }
882 InodeSocketKind::BoundTcp { socket, .. } => {
883 socket.addr_local().map_err(net_error_into_wasi_err)?
884 }
885 InodeSocketKind::UdpSocket { socket, .. } => {
886 socket.addr_local().map_err(net_error_into_wasi_err)?
887 }
888 InodeSocketKind::RemoteSocket {
889 local_addr: addr, ..
890 } => *addr,
891 _ => return Err(Errno::Notsup),
892 })
893 }
894
895 pub fn addr_peer(&self) -> Result<SocketAddr, Errno> {
896 let inner = self.inner.protected.read().unwrap();
897 match &inner.kind {
898 InodeSocketKind::BoundTcp { .. } => Err(Errno::Notconn),
899 InodeSocketKind::PreSocket { props, .. } => Ok(SocketAddr::new(
900 match props.family {
901 Addressfamily::Inet4 => IpAddr::V4(Ipv4Addr::UNSPECIFIED),
902 Addressfamily::Inet6 => IpAddr::V6(Ipv6Addr::UNSPECIFIED),
903 _ => return Err(Errno::Inval),
904 },
905 0,
906 )),
907 InodeSocketKind::TcpStream { socket, .. } => {
908 socket.addr_peer().map_err(net_error_into_wasi_err)
909 }
910 InodeSocketKind::UdpSocket {
911 peer: Some(peer), ..
912 } => Ok(*peer),
913 InodeSocketKind::UdpSocket { socket, .. } => socket
914 .addr_peer()
915 .map_err(net_error_into_wasi_err)?
916 .ok_or(Errno::Notconn),
917 InodeSocketKind::RemoteSocket { peer_addr, .. } => Ok(*peer_addr),
918 _ => Err(Errno::Notsup),
919 }
920 }
921
922 pub fn set_opt_flag(&mut self, option: WasiSocketOption, val: bool) -> Result<(), Errno> {
923 let mut inner = self.inner.protected.write().unwrap();
924 match &mut inner.kind {
925 InodeSocketKind::PreSocket { props, .. }
926 | InodeSocketKind::BoundTcp { props, .. }
927 | InodeSocketKind::RemoteSocket { props, .. } => {
928 match option {
929 WasiSocketOption::OnlyV6 => props.only_v6 = val,
930 WasiSocketOption::ReusePort => props.reuse_port = val,
931 WasiSocketOption::ReuseAddr => props.reuse_addr = val,
932 WasiSocketOption::NoDelay => props.no_delay = Some(val),
933 WasiSocketOption::KeepAlive => props.keep_alive = Some(val),
934 WasiSocketOption::DontRoute => props.dont_route = Some(val),
935 _ => return Err(Errno::Inval),
936 };
937 }
938 InodeSocketKind::Raw(sock) => match option {
939 WasiSocketOption::Promiscuous => {
940 sock.set_promiscuous(val).map_err(net_error_into_wasi_err)?
941 }
942 _ => return Err(Errno::Inval),
943 },
944 InodeSocketKind::TcpStream { socket, .. } => match option {
945 WasiSocketOption::NoDelay => {
946 socket.set_nodelay(val).map_err(net_error_into_wasi_err)?
947 }
948 WasiSocketOption::KeepAlive => {
949 socket.set_keepalive(val).map_err(net_error_into_wasi_err)?
950 }
951 WasiSocketOption::DontRoute => {
952 socket.set_dontroute(val).map_err(net_error_into_wasi_err)?
953 }
954 _ => return Err(Errno::Inval),
955 },
956 InodeSocketKind::TcpListener { .. } => return Err(Errno::Inval),
957 InodeSocketKind::UdpSocket { socket, .. } => match option {
958 WasiSocketOption::Broadcast => {
959 socket.set_broadcast(val).map_err(net_error_into_wasi_err)?
960 }
961 WasiSocketOption::MulticastLoopV4 => socket
962 .set_multicast_loop_v4(val)
963 .map_err(net_error_into_wasi_err)?,
964 WasiSocketOption::MulticastLoopV6 => socket
965 .set_multicast_loop_v6(val)
966 .map_err(net_error_into_wasi_err)?,
967 _ => return Err(Errno::Inval),
968 },
969 _ => return Err(Errno::Notsup),
970 }
971 Ok(())
972 }
973
974 pub fn get_opt_flag(&self, option: WasiSocketOption) -> Result<bool, Errno> {
975 let mut inner = self.inner.protected.write().unwrap();
976 Ok(match &mut inner.kind {
977 InodeSocketKind::PreSocket { props, .. }
978 | InodeSocketKind::BoundTcp { props, .. }
979 | InodeSocketKind::RemoteSocket { props, .. } => match option {
980 WasiSocketOption::OnlyV6 => props.only_v6,
981 WasiSocketOption::ReusePort => props.reuse_port,
982 WasiSocketOption::ReuseAddr => props.reuse_addr,
983 WasiSocketOption::NoDelay => props.no_delay.unwrap_or_default(),
984 WasiSocketOption::KeepAlive => props.keep_alive.unwrap_or_default(),
985 _ => return Err(Errno::Inval),
986 },
987 InodeSocketKind::Raw(sock) => match option {
988 WasiSocketOption::Promiscuous => {
989 sock.promiscuous().map_err(net_error_into_wasi_err)?
990 }
991 _ => return Err(Errno::Inval),
992 },
993 InodeSocketKind::TcpStream { socket, .. } => match option {
994 WasiSocketOption::NoDelay => socket.nodelay().map_err(net_error_into_wasi_err)?,
995 WasiSocketOption::KeepAlive => {
996 socket.keepalive().map_err(net_error_into_wasi_err)?
997 }
998 WasiSocketOption::DontRoute => {
999 socket.dontroute().map_err(net_error_into_wasi_err)?
1000 }
1001 _ => return Err(Errno::Inval),
1002 },
1003 InodeSocketKind::UdpSocket { socket, .. } => match option {
1004 WasiSocketOption::Broadcast => {
1005 socket.broadcast().map_err(net_error_into_wasi_err)?
1006 }
1007 WasiSocketOption::MulticastLoopV4 => socket
1008 .multicast_loop_v4()
1009 .map_err(net_error_into_wasi_err)?,
1010 WasiSocketOption::MulticastLoopV6 => socket
1011 .multicast_loop_v6()
1012 .map_err(net_error_into_wasi_err)?,
1013 _ => return Err(Errno::Inval),
1014 },
1015 _ => return Err(Errno::Notsup),
1016 })
1017 }
1018
1019 pub fn set_send_buf_size(&mut self, size: usize) -> Result<(), Errno> {
1020 let mut inner = self.inner.protected.write().unwrap();
1021 match &mut inner.kind {
1022 InodeSocketKind::PreSocket { props, .. }
1023 | InodeSocketKind::BoundTcp { props, .. }
1024 | InodeSocketKind::RemoteSocket { props, .. } => {
1025 props.send_buf_size = Some(size);
1026 }
1027 InodeSocketKind::TcpStream { socket, .. } => {
1028 socket
1029 .set_send_buf_size(size)
1030 .map_err(net_error_into_wasi_err)?;
1031 }
1032 _ => return Err(Errno::Notsup),
1033 }
1034 Ok(())
1035 }
1036
1037 pub fn send_buf_size(&self) -> Result<usize, Errno> {
1038 let inner = self.inner.protected.read().unwrap();
1039 match &inner.kind {
1040 InodeSocketKind::PreSocket { props, .. }
1041 | InodeSocketKind::BoundTcp { props, .. }
1042 | InodeSocketKind::RemoteSocket { props, .. } => {
1043 Ok(props.send_buf_size.unwrap_or_default())
1044 }
1045 InodeSocketKind::TcpStream { socket, .. } => {
1046 socket.send_buf_size().map_err(net_error_into_wasi_err)
1047 }
1048 _ => Err(Errno::Notsup),
1049 }
1050 }
1051
1052 pub fn set_recv_buf_size(&mut self, size: usize) -> Result<(), Errno> {
1053 let mut inner = self.inner.protected.write().unwrap();
1054 match &mut inner.kind {
1055 InodeSocketKind::PreSocket { props, .. }
1056 | InodeSocketKind::BoundTcp { props, .. }
1057 | InodeSocketKind::RemoteSocket { props, .. } => {
1058 props.recv_buf_size = Some(size);
1059 }
1060 InodeSocketKind::TcpStream { socket, .. } => {
1061 socket
1062 .set_recv_buf_size(size)
1063 .map_err(net_error_into_wasi_err)?;
1064 }
1065 _ => return Err(Errno::Notsup),
1066 }
1067 Ok(())
1068 }
1069
1070 pub fn recv_buf_size(&self) -> Result<usize, Errno> {
1071 let inner = self.inner.protected.read().unwrap();
1072 match &inner.kind {
1073 InodeSocketKind::PreSocket { props, .. }
1074 | InodeSocketKind::BoundTcp { props, .. }
1075 | InodeSocketKind::RemoteSocket { props, .. } => {
1076 Ok(props.recv_buf_size.unwrap_or_default())
1077 }
1078 InodeSocketKind::TcpStream { socket, .. } => {
1079 socket.recv_buf_size().map_err(net_error_into_wasi_err)
1080 }
1081 _ => Err(Errno::Notsup),
1082 }
1083 }
1084
1085 pub fn set_linger(&mut self, linger: Option<std::time::Duration>) -> Result<(), Errno> {
1086 let mut inner = self.inner.protected.write().unwrap();
1087 match &mut inner.kind {
1088 InodeSocketKind::TcpStream { socket, .. } => {
1089 socket.set_linger(linger).map_err(net_error_into_wasi_err)
1090 }
1091 InodeSocketKind::RemoteSocket { .. } => Ok(()),
1092 InodeSocketKind::BoundTcp { .. } => Err(Errno::Io),
1093 InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
1094 _ => Err(Errno::Notsup),
1095 }
1096 }
1097
1098 pub fn linger(&self) -> Result<Option<std::time::Duration>, Errno> {
1099 let inner = self.inner.protected.read().unwrap();
1100 match &inner.kind {
1101 InodeSocketKind::TcpStream { socket, .. } => {
1102 socket.linger().map_err(net_error_into_wasi_err)
1103 }
1104 InodeSocketKind::BoundTcp { .. } => Err(Errno::Io),
1105 InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
1106 _ => Err(Errno::Notsup),
1107 }
1108 }
1109
1110 pub fn set_opt_time(
1111 &self,
1112 ty: TimeType,
1113 timeout: Option<std::time::Duration>,
1114 ) -> Result<(), Errno> {
1115 let mut inner = self.inner.protected.write().unwrap();
1116 match &mut inner.kind {
1117 InodeSocketKind::TcpStream {
1118 write_timeout,
1119 read_timeout,
1120 ..
1121 } => {
1122 match ty {
1123 TimeType::WriteTimeout => *write_timeout = timeout,
1124 TimeType::ReadTimeout => *read_timeout = timeout,
1125 _ => return Err(Errno::Inval),
1126 }
1127 Ok(())
1128 }
1129 InodeSocketKind::TcpListener { accept_timeout, .. } => {
1130 match ty {
1131 TimeType::AcceptTimeout => *accept_timeout = timeout,
1132 _ => return Err(Errno::Inval),
1133 }
1134 Ok(())
1135 }
1136 InodeSocketKind::PreSocket { props, .. }
1137 | InodeSocketKind::BoundTcp { props, .. }
1138 | InodeSocketKind::RemoteSocket { props, .. } => {
1139 match ty {
1140 TimeType::ConnectTimeout => props.connect_timeout = timeout,
1141 TimeType::AcceptTimeout => props.accept_timeout = timeout,
1142 TimeType::ReadTimeout => props.read_timeout = timeout,
1143 TimeType::WriteTimeout => props.write_timeout = timeout,
1144 _ => return Err(Errno::Io),
1145 }
1146 Ok(())
1147 }
1148 _ => Err(Errno::Notsup),
1149 }
1150 }
1151
1152 pub fn opt_time(&self, ty: TimeType) -> Result<Option<std::time::Duration>, Errno> {
1153 let inner = self.inner.protected.read().unwrap();
1154 match &inner.kind {
1155 InodeSocketKind::TcpStream {
1156 read_timeout,
1157 write_timeout,
1158 ..
1159 } => Ok(match ty {
1160 TimeType::ReadTimeout => *read_timeout,
1161 TimeType::WriteTimeout => *write_timeout,
1162 _ => return Err(Errno::Inval),
1163 }),
1164 InodeSocketKind::TcpListener { accept_timeout, .. } => Ok(match ty {
1165 TimeType::AcceptTimeout => *accept_timeout,
1166 _ => return Err(Errno::Inval),
1167 }),
1168 InodeSocketKind::PreSocket { props, .. }
1169 | InodeSocketKind::BoundTcp { props, .. }
1170 | InodeSocketKind::RemoteSocket { props, .. } => match ty {
1171 TimeType::ConnectTimeout => Ok(props.connect_timeout),
1172 TimeType::AcceptTimeout => Ok(props.accept_timeout),
1173 TimeType::ReadTimeout => Ok(props.read_timeout),
1174 TimeType::WriteTimeout => Ok(props.write_timeout),
1175 _ => Err(Errno::Inval),
1176 },
1177 _ => Err(Errno::Notsup),
1178 }
1179 }
1180
1181 pub fn set_ttl(&self, ttl: u32) -> Result<(), Errno> {
1182 let mut inner = self.inner.protected.write().unwrap();
1183 match &mut inner.kind {
1184 InodeSocketKind::BoundTcp { socket, .. } => {
1185 socket.set_ttl(ttl).map_err(net_error_into_wasi_err)
1186 }
1187 InodeSocketKind::TcpStream { socket, .. } => {
1188 socket.set_ttl(ttl).map_err(net_error_into_wasi_err)
1189 }
1190 InodeSocketKind::UdpSocket { socket, .. } => {
1191 socket.set_ttl(ttl).map_err(net_error_into_wasi_err)
1192 }
1193 InodeSocketKind::RemoteSocket { ttl: set_ttl, .. } => {
1194 *set_ttl = ttl;
1195 Ok(())
1196 }
1197 InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
1198 _ => Err(Errno::Notsup),
1199 }
1200 }
1201
1202 pub fn ttl(&self) -> Result<u32, Errno> {
1203 let inner = self.inner.protected.read().unwrap();
1204 match &inner.kind {
1205 InodeSocketKind::BoundTcp { socket, .. } => {
1206 socket.ttl().map_err(net_error_into_wasi_err)
1207 }
1208 InodeSocketKind::TcpStream { socket, .. } => {
1209 socket.ttl().map_err(net_error_into_wasi_err)
1210 }
1211 InodeSocketKind::UdpSocket { socket, .. } => {
1212 socket.ttl().map_err(net_error_into_wasi_err)
1213 }
1214 InodeSocketKind::RemoteSocket { ttl, .. } => Ok(*ttl),
1215 InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
1216 _ => Err(Errno::Notsup),
1217 }
1218 }
1219
1220 pub fn set_multicast_ttl_v4(&self, ttl: u32) -> Result<(), Errno> {
1221 let mut inner = self.inner.protected.write().unwrap();
1222 match &mut inner.kind {
1223 InodeSocketKind::UdpSocket { socket, .. } => socket
1224 .set_multicast_ttl_v4(ttl)
1225 .map_err(net_error_into_wasi_err),
1226 InodeSocketKind::RemoteSocket {
1227 multicast_ttl: set_ttl,
1228 ..
1229 } => {
1230 *set_ttl = ttl;
1231 Ok(())
1232 }
1233 InodeSocketKind::BoundTcp { .. } => Err(Errno::Io),
1234 InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
1235 _ => Err(Errno::Notsup),
1236 }
1237 }
1238
1239 pub fn multicast_ttl_v4(&self) -> Result<u32, Errno> {
1240 let inner = self.inner.protected.read().unwrap();
1241 match &inner.kind {
1242 InodeSocketKind::UdpSocket { socket, .. } => {
1243 socket.multicast_ttl_v4().map_err(net_error_into_wasi_err)
1244 }
1245 InodeSocketKind::RemoteSocket { multicast_ttl, .. } => Ok(*multicast_ttl),
1246 InodeSocketKind::BoundTcp { .. } => Err(Errno::Io),
1247 InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
1248 _ => Err(Errno::Notsup),
1249 }
1250 }
1251
1252 pub fn join_multicast_v4(&self, multiaddr: Ipv4Addr, iface: Ipv4Addr) -> Result<(), Errno> {
1253 let mut inner = self.inner.protected.write().unwrap();
1254 match &mut inner.kind {
1255 InodeSocketKind::UdpSocket { socket, .. } => socket
1256 .join_multicast_v4(multiaddr, iface)
1257 .map_err(net_error_into_wasi_err),
1258 InodeSocketKind::RemoteSocket { .. } => Ok(()),
1259 InodeSocketKind::BoundTcp { .. } => Err(Errno::Io),
1260 InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
1261 _ => Err(Errno::Notsup),
1262 }
1263 }
1264
1265 pub fn leave_multicast_v4(&self, multiaddr: Ipv4Addr, iface: Ipv4Addr) -> Result<(), Errno> {
1266 let mut inner = self.inner.protected.write().unwrap();
1267 match &mut inner.kind {
1268 InodeSocketKind::UdpSocket { socket, .. } => socket
1269 .leave_multicast_v4(multiaddr, iface)
1270 .map_err(net_error_into_wasi_err),
1271 InodeSocketKind::RemoteSocket { .. } => Ok(()),
1272 InodeSocketKind::BoundTcp { .. } => Err(Errno::Io),
1273 InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
1274 _ => Err(Errno::Notsup),
1275 }
1276 }
1277
1278 pub fn join_multicast_v6(&self, multiaddr: Ipv6Addr, iface: u32) -> Result<(), Errno> {
1279 let mut inner = self.inner.protected.write().unwrap();
1280 match &mut inner.kind {
1281 InodeSocketKind::UdpSocket { socket, .. } => socket
1282 .join_multicast_v6(multiaddr, iface)
1283 .map_err(net_error_into_wasi_err),
1284 InodeSocketKind::RemoteSocket { .. } => Ok(()),
1285 InodeSocketKind::BoundTcp { .. } => Err(Errno::Io),
1286 InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
1287 _ => Err(Errno::Notsup),
1288 }
1289 }
1290
1291 pub fn leave_multicast_v6(&mut self, multiaddr: Ipv6Addr, iface: u32) -> Result<(), Errno> {
1292 let mut inner = self.inner.protected.write().unwrap();
1293 match &mut inner.kind {
1294 InodeSocketKind::UdpSocket { socket, .. } => socket
1295 .leave_multicast_v6(multiaddr, iface)
1296 .map_err(net_error_into_wasi_err),
1297 InodeSocketKind::RemoteSocket { .. } => Ok(()),
1298 InodeSocketKind::BoundTcp { .. } => Err(Errno::Io),
1299 InodeSocketKind::PreSocket { .. } => Err(Errno::Io),
1300 _ => Err(Errno::Notsup),
1301 }
1302 }
1303
1304 pub async fn send(
1305 &self,
1306 tasks: &dyn VirtualTaskManager,
1307 buf: &[u8],
1308 timeout: Option<Duration>,
1309 nonblocking: bool,
1310 ) -> Result<usize, Errno> {
1311 struct SocketSender<'a, 'b> {
1312 inner: &'a InodeSocketInner,
1313 data: &'b [u8],
1314 nonblocking: bool,
1315 handler_registered: bool,
1316 }
1317 impl Drop for SocketSender<'_, '_> {
1318 fn drop(&mut self) {
1319 if self.handler_registered {
1320 let mut inner = self.inner.protected.write().unwrap();
1321 inner.remove_handler();
1322 }
1323 }
1324 }
1325 impl Future for SocketSender<'_, '_> {
1326 type Output = Result<usize, Errno>;
1327 fn poll(
1328 mut self: Pin<&mut Self>,
1329 cx: &mut std::task::Context<'_>,
1330 ) -> Poll<Self::Output> {
1331 loop {
1332 let mut inner = self.inner.protected.write().unwrap();
1333 let res = match &mut inner.kind {
1334 InodeSocketKind::Raw(socket) => socket.try_send(self.data),
1335 InodeSocketKind::TcpStream { socket, .. } => socket.try_send(self.data),
1336 InodeSocketKind::UdpSocket { socket, peer } => {
1337 if let Some(peer) = peer {
1338 socket.try_send_to(self.data, *peer)
1339 } else {
1340 Err(NetworkError::NotConnected)
1341 }
1342 }
1343 InodeSocketKind::PreSocket { .. } => {
1344 return Poll::Ready(Err(Errno::Notconn));
1345 }
1346 InodeSocketKind::RemoteSocket { is_dead, .. } => {
1347 return match is_dead {
1348 true => Poll::Ready(Err(Errno::Connreset)),
1349 false => Poll::Ready(Ok(self.data.len())),
1350 };
1351 }
1352 _ => return Poll::Ready(Err(Errno::Notsup)),
1353 };
1354 return match res {
1355 Ok(amt) => Poll::Ready(Ok(amt)),
1356 Err(NetworkError::WouldBlock) if self.nonblocking => {
1357 Poll::Ready(Err(Errno::Again))
1358 }
1359 Err(NetworkError::WouldBlock) if !self.handler_registered => {
1360 inner
1361 .set_handler(cx.waker().into())
1362 .map_err(net_error_into_wasi_err)?;
1363 drop(inner);
1364 self.handler_registered = true;
1365 continue;
1366 }
1367 Err(NetworkError::WouldBlock) => Poll::Pending,
1368 Err(err) => Poll::Ready(Err(net_error_into_wasi_err(err))),
1369 };
1370 }
1371 }
1372 }
1373
1374 let poller = SocketSender {
1375 inner: &self.inner,
1376 data: buf,
1377 nonblocking,
1378 handler_registered: false,
1379 };
1380 if let Some(timeout) = timeout {
1381 tokio::select! {
1382 res = poller => res,
1383 _ = tasks.sleep_now(timeout) => Err(Errno::Timedout)
1384 }
1385 } else {
1386 poller.await
1387 }
1388 }
1389
1390 pub async fn send_to<M: MemorySize>(
1391 &self,
1392 tasks: &dyn VirtualTaskManager,
1393 buf: &[u8],
1394 addr: SocketAddr,
1395 timeout: Option<Duration>,
1396 nonblocking: bool,
1397 ) -> Result<usize, Errno> {
1398 struct SocketSender<'a, 'b> {
1399 inner: &'a InodeSocketInner,
1400 data: &'b [u8],
1401 addr: SocketAddr,
1402 nonblocking: bool,
1403 handler_registered: bool,
1404 }
1405 impl Drop for SocketSender<'_, '_> {
1406 fn drop(&mut self) {
1407 if self.handler_registered {
1408 let mut inner = self.inner.protected.write().unwrap();
1409 inner.remove_handler();
1410 }
1411 }
1412 }
1413 impl Future for SocketSender<'_, '_> {
1414 type Output = Result<usize, Errno>;
1415 fn poll(
1416 mut self: Pin<&mut Self>,
1417 cx: &mut std::task::Context<'_>,
1418 ) -> Poll<Self::Output> {
1419 loop {
1420 let mut inner = self.inner.protected.write().unwrap();
1421 let res = match &mut inner.kind {
1422 InodeSocketKind::Icmp(socket) => socket.try_send_to(self.data, self.addr),
1423 InodeSocketKind::TcpStream { socket, .. } => socket.try_send(self.data),
1424 InodeSocketKind::UdpSocket { socket, .. } => {
1425 socket.try_send_to(self.data, self.addr)
1426 }
1427 InodeSocketKind::PreSocket { .. } => {
1428 return Poll::Ready(Err(Errno::Notconn));
1429 }
1430 InodeSocketKind::RemoteSocket { is_dead, .. } => {
1431 return match is_dead {
1432 true => Poll::Ready(Err(Errno::Connreset)),
1433 false => Poll::Ready(Ok(self.data.len())),
1434 };
1435 }
1436 _ => return Poll::Ready(Err(Errno::Notsup)),
1437 };
1438 return match res {
1439 Ok(amt) => Poll::Ready(Ok(amt)),
1440 Err(NetworkError::WouldBlock) if self.nonblocking => {
1441 Poll::Ready(Err(Errno::Again))
1442 }
1443 Err(NetworkError::WouldBlock) if !self.handler_registered => {
1444 inner
1445 .set_handler(cx.waker().into())
1446 .map_err(net_error_into_wasi_err)?;
1447 self.handler_registered = true;
1448 drop(inner);
1449 continue;
1450 }
1451 Err(NetworkError::WouldBlock) => Poll::Pending,
1452 Err(err) => Poll::Ready(Err(net_error_into_wasi_err(err))),
1453 };
1454 }
1455 }
1456 }
1457
1458 let poller = SocketSender {
1459 inner: &self.inner,
1460 data: buf,
1461 addr,
1462 nonblocking,
1463 handler_registered: false,
1464 };
1465 if let Some(timeout) = timeout {
1466 tokio::select! {
1467 res = poller => res,
1468 _ = tasks.sleep_now(timeout) => Err(Errno::Timedout)
1469 }
1470 } else {
1471 poller.await
1472 }
1473 }
1474
1475 pub async fn recv(
1476 &self,
1477 tasks: &dyn VirtualTaskManager,
1478 buf: &mut [MaybeUninit<u8>],
1479 timeout: Option<Duration>,
1480 nonblocking: bool,
1481 peek: bool,
1482 ) -> Result<usize, Errno> {
1483 struct SocketReceiver<'a, 'b> {
1484 inner: &'a InodeSocketInner,
1485 data: &'b mut [MaybeUninit<u8>],
1486 nonblocking: bool,
1487 peek: bool,
1488 handler_registered: bool,
1489 }
1490 impl Drop for SocketReceiver<'_, '_> {
1491 fn drop(&mut self) {
1492 if self.handler_registered {
1493 let mut inner = self.inner.protected.write().unwrap();
1494 inner.remove_handler();
1495 }
1496 }
1497 }
1498 impl Future for SocketReceiver<'_, '_> {
1499 type Output = Result<usize, Errno>;
1500 fn poll(
1501 mut self: Pin<&mut Self>,
1502 cx: &mut std::task::Context<'_>,
1503 ) -> Poll<Self::Output> {
1504 loop {
1505 let peek = self.peek;
1506 let mut inner = self.inner.protected.write().unwrap();
1507 let res = match &mut inner.kind {
1508 InodeSocketKind::Raw(socket) => socket.try_recv(self.data, peek),
1509 InodeSocketKind::TcpStream { socket, .. } => {
1510 socket.try_recv(self.data, peek)
1511 }
1512 InodeSocketKind::UdpSocket { socket, peer } => match peer {
1513 Some(peer) => {
1514 try_recv_from_connected_udp(socket.as_mut(), self.data, peek, peer)
1515 .map(|(amt, _)| amt)
1516 }
1517 None => socket.try_recv_from(self.data, peek).map(|(amt, _)| amt),
1518 },
1519 InodeSocketKind::RemoteSocket { is_dead, .. } => {
1520 return match is_dead {
1521 true => Poll::Ready(Ok(0)),
1522 false => Poll::Pending,
1523 };
1524 }
1525 InodeSocketKind::PreSocket { .. } => {
1526 return Poll::Ready(Err(Errno::Notconn));
1527 }
1528 _ => return Poll::Ready(Err(Errno::Notsup)),
1529 };
1530 return match res {
1531 Ok(amt) => Poll::Ready(Ok(amt)),
1532 Err(NetworkError::WouldBlock) if self.nonblocking => {
1533 Poll::Ready(Err(Errno::Again))
1534 }
1535 Err(NetworkError::WouldBlock) if !self.handler_registered => {
1536 inner
1537 .set_handler(cx.waker().into())
1538 .map_err(net_error_into_wasi_err)?;
1539 self.handler_registered = true;
1540 drop(inner);
1541 continue;
1542 }
1543
1544 Err(NetworkError::WouldBlock) => Poll::Pending,
1545 Err(err) => Poll::Ready(Err(net_error_into_wasi_err(err))),
1546 };
1547 }
1548 }
1549 }
1550
1551 let poller = SocketReceiver {
1552 inner: &self.inner,
1553 data: buf,
1554 nonblocking,
1555 peek,
1556 handler_registered: false,
1557 };
1558 if let Some(timeout) = timeout {
1559 tokio::select! {
1560 res = poller => res,
1561 _ = tasks.sleep_now(timeout) => Err(Errno::Timedout)
1562 }
1563 } else {
1564 poller.await
1565 }
1566 }
1567
1568 pub async fn recv_from(
1569 &self,
1570 tasks: &dyn VirtualTaskManager,
1571 buf: &mut [MaybeUninit<u8>],
1572 timeout: Option<Duration>,
1573 nonblocking: bool,
1574 peek: bool,
1575 ) -> Result<(usize, SocketAddr), Errno> {
1576 struct SocketReceiver<'a, 'b> {
1577 inner: &'a InodeSocketInner,
1578 data: &'b mut [MaybeUninit<u8>],
1579 nonblocking: bool,
1580 peek: bool,
1581 handler_registered: bool,
1582 }
1583 impl Drop for SocketReceiver<'_, '_> {
1584 fn drop(&mut self) {
1585 if self.handler_registered {
1586 let mut inner = self.inner.protected.write().unwrap();
1587 inner.remove_handler();
1588 }
1589 }
1590 }
1591 impl Future for SocketReceiver<'_, '_> {
1592 type Output = Result<(usize, SocketAddr), Errno>;
1593 fn poll(
1594 mut self: Pin<&mut Self>,
1595 cx: &mut std::task::Context<'_>,
1596 ) -> Poll<Self::Output> {
1597 let peek = self.peek;
1598 let mut inner = self.inner.protected.write().unwrap();
1599 loop {
1600 let res = match &mut inner.kind {
1601 InodeSocketKind::Icmp(socket) => socket.try_recv_from(self.data, peek),
1602 InodeSocketKind::UdpSocket { socket, peer } => match peer {
1603 Some(peer) => {
1604 try_recv_from_connected_udp(socket.as_mut(), self.data, peek, peer)
1605 }
1606 None => socket.try_recv_from(self.data, peek),
1607 },
1608 InodeSocketKind::RemoteSocket {
1609 is_dead, peer_addr, ..
1610 } => {
1611 return match is_dead {
1612 true => Poll::Ready(Ok((0, *peer_addr))),
1613 false => Poll::Pending,
1614 };
1615 }
1616 InodeSocketKind::PreSocket { .. } => {
1617 return Poll::Ready(Err(Errno::Notconn));
1618 }
1619 _ => return Poll::Ready(Err(Errno::Notsup)),
1620 };
1621 return match res {
1622 Ok((amt, addr)) => Poll::Ready(Ok((amt, addr))),
1623 Err(NetworkError::WouldBlock) if self.nonblocking => {
1624 Poll::Ready(Err(Errno::Again))
1625 }
1626 Err(NetworkError::WouldBlock) if !self.handler_registered => {
1627 inner
1628 .set_handler(cx.waker().into())
1629 .map_err(net_error_into_wasi_err)?;
1630 self.handler_registered = true;
1631 continue;
1632 }
1633 Err(NetworkError::WouldBlock) => Poll::Pending,
1634 Err(err) => Poll::Ready(Err(net_error_into_wasi_err(err))),
1635 };
1636 }
1637 }
1638 }
1639
1640 let poller = SocketReceiver {
1641 inner: &self.inner,
1642 data: buf,
1643 nonblocking,
1644 peek,
1645 handler_registered: false,
1646 };
1647 if let Some(timeout) = timeout {
1648 tokio::select! {
1649 res = poller => res,
1650 _ = tasks.sleep_now(timeout) => Err(Errno::Timedout)
1651 }
1652 } else {
1653 poller.await
1654 }
1655 }
1656
1657 pub fn shutdown(&mut self, how: std::net::Shutdown) -> Result<(), Errno> {
1658 let mut inner = self.inner.protected.write().unwrap();
1659 match &mut inner.kind {
1660 InodeSocketKind::TcpStream { socket, .. } => {
1661 socket.shutdown(how).map_err(net_error_into_wasi_err)?;
1662 }
1663 InodeSocketKind::RemoteSocket { .. } => return Ok(()),
1664 InodeSocketKind::BoundTcp { .. } => return Err(Errno::Notconn),
1665 InodeSocketKind::PreSocket { .. } => return Err(Errno::Notconn),
1666 _ => return Err(Errno::Notsup),
1667 }
1668 Ok(())
1669 }
1670
1671 pub async fn can_write(&self) -> bool {
1672 if let Ok(mut guard) = self.inner.protected.try_write() {
1673 #[allow(clippy::match_like_matches_macro)]
1674 match &mut guard.kind {
1675 InodeSocketKind::TcpStream { .. }
1676 | InodeSocketKind::BoundTcp { .. }
1677 | InodeSocketKind::UdpSocket { .. }
1678 | InodeSocketKind::Raw(..) => true,
1679 InodeSocketKind::RemoteSocket { is_dead, .. } => !(*is_dead),
1680 _ => false,
1681 }
1682 } else {
1683 false
1684 }
1685 }
1686
1687 pub fn is_dgram(&self) -> bool {
1688 let guard = self.inner.protected.read().unwrap();
1689 match &guard.kind {
1690 InodeSocketKind::UdpSocket { .. } => true,
1691 InodeSocketKind::RemoteSocket { props, .. } => props.ty == Socktype::Dgram,
1692 _ => false,
1693 }
1694 }
1695}
1696
1697fn discard_non_matching_udp_datagrams(
1700 socket: &mut dyn VirtualUdpSocket,
1701 peer: &SocketAddr,
1702) -> Result<(), NetworkError> {
1703 let mut discard = [MaybeUninit::<u8>::uninit()];
1704 loop {
1705 match socket.try_recv_from(&mut discard, true) {
1706 Ok((_, addr)) if addr == *peer => return Ok(()),
1707 Ok(_) => match socket.try_recv_from(&mut discard, false) {
1708 Ok(_) => {}
1709 Err(NetworkError::WouldBlock) => {}
1710 Err(err) => return Err(err),
1711 },
1712 Err(NetworkError::WouldBlock) => return Ok(()),
1713 Err(err) => return Err(err),
1714 }
1715 }
1716}
1717
1718fn try_recv_from_connected_udp(
1719 socket: &mut dyn VirtualUdpSocket,
1720 data: &mut [MaybeUninit<u8>],
1721 peek: bool,
1722 peer: &SocketAddr,
1723) -> Result<(usize, SocketAddr), NetworkError> {
1724 discard_non_matching_udp_datagrams(socket, peer)?;
1725 loop {
1726 match socket.try_recv_from(data, peek) {
1727 Ok((amt, addr)) if addr == *peer => return Ok((amt, addr)),
1728 Ok(_) if peek => match socket.try_recv_from(data, false) {
1729 Ok(_) => {}
1730 Err(NetworkError::WouldBlock) => {}
1731 Err(err) => return Err(err),
1732 },
1733 Ok(_) => continue,
1734 Err(err) => return Err(err),
1735 }
1736 }
1737}
1738
1739impl InodeSocketProtected {
1740 pub fn remove_handler(&mut self) {
1741 match &mut self.kind {
1742 InodeSocketKind::TcpListener { socket, .. } => socket.remove_handler(),
1743 InodeSocketKind::TcpStream { socket, .. } => socket.remove_handler(),
1744 InodeSocketKind::UdpSocket { socket, .. } => socket.remove_handler(),
1745 InodeSocketKind::Raw(socket) => socket.remove_handler(),
1746 InodeSocketKind::Icmp(socket) => socket.remove_handler(),
1747 InodeSocketKind::PreSocket { props, .. } => {
1748 props.handler.take();
1749 }
1750 InodeSocketKind::BoundTcp { props, .. } => {
1751 props.handler.take();
1752 }
1753 InodeSocketKind::RemoteSocket { props, .. } => {
1754 props.handler.take();
1755 }
1756 }
1757 }
1758
1759 pub fn poll_read_ready(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<usize>> {
1760 match &mut self.kind {
1761 InodeSocketKind::TcpListener { socket, .. } => socket.poll_read_ready(cx),
1762 InodeSocketKind::TcpStream { socket, .. } => socket.poll_read_ready(cx),
1763 InodeSocketKind::UdpSocket {
1764 socket,
1765 peer: Some(peer),
1766 } => loop {
1767 if let Err(err) = discard_non_matching_udp_datagrams(socket.as_mut(), peer) {
1768 break Poll::Ready(Err(err));
1769 }
1770 match socket.poll_read_ready(cx) {
1771 Poll::Pending => break Poll::Pending,
1772 Poll::Ready(Err(err)) => break Poll::Ready(Err(err)),
1773 Poll::Ready(Ok(n)) => {
1774 let mut peek_buf = [MaybeUninit::<u8>::uninit()];
1775 match socket.try_recv_from(&mut peek_buf, true) {
1776 Ok((_, addr)) if addr == *peer => break Poll::Ready(Ok(n)),
1777 Ok(_) => continue,
1778 Err(NetworkError::WouldBlock) => break Poll::Pending,
1779 Err(err) => break Poll::Ready(Err(err)),
1780 }
1781 }
1782 }
1783 },
1784 InodeSocketKind::UdpSocket { socket, peer: None } => socket.poll_read_ready(cx),
1785 InodeSocketKind::Raw(socket) => socket.poll_read_ready(cx),
1786 InodeSocketKind::Icmp(socket) => socket.poll_read_ready(cx),
1787 InodeSocketKind::BoundTcp { .. } => Poll::Pending,
1788 InodeSocketKind::PreSocket { .. } => Poll::Pending,
1789 InodeSocketKind::RemoteSocket { is_dead, .. } => match is_dead {
1790 true => Poll::Ready(Ok(0)),
1791 false => Poll::Pending,
1792 },
1793 }
1794 .map_err(net_error_into_io_err)
1795 }
1796
1797 pub fn poll_write_ready(&mut self, cx: &mut Context<'_>) -> Poll<io::Result<usize>> {
1798 match &mut self.kind {
1799 InodeSocketKind::TcpListener { socket, .. } => socket.poll_write_ready(cx),
1800 InodeSocketKind::TcpStream { socket, .. } => socket.poll_write_ready(cx),
1801 InodeSocketKind::UdpSocket { socket, .. } => socket.poll_write_ready(cx),
1802 InodeSocketKind::Raw(socket) => socket.poll_write_ready(cx),
1803 InodeSocketKind::Icmp(socket) => socket.poll_write_ready(cx),
1804 InodeSocketKind::BoundTcp { .. } => Poll::Ready(Ok(1)),
1807 InodeSocketKind::PreSocket { .. } => Poll::Pending,
1808 InodeSocketKind::RemoteSocket { is_dead, .. } => match is_dead {
1809 true => Poll::Ready(Ok(0)),
1810 false => Poll::Pending,
1811 },
1812 }
1813 .map_err(net_error_into_io_err)
1814 }
1815
1816 pub fn set_handler(
1817 &mut self,
1818 handler: Box<dyn InterestHandler + Send + Sync>,
1819 ) -> virtual_net::Result<()> {
1820 match &mut self.kind {
1821 InodeSocketKind::TcpListener { socket, .. } => socket.set_handler(handler),
1822 InodeSocketKind::TcpStream { socket, .. } => socket.set_handler(handler),
1823 InodeSocketKind::UdpSocket { socket, .. } => socket.set_handler(handler),
1824 InodeSocketKind::Raw(socket) => socket.set_handler(handler),
1825 InodeSocketKind::Icmp(socket) => socket.set_handler(handler),
1826 InodeSocketKind::PreSocket { props, .. }
1827 | InodeSocketKind::BoundTcp { props, .. }
1828 | InodeSocketKind::RemoteSocket { props, .. } => {
1829 props.handler.replace(handler);
1830 Ok(())
1831 }
1832 }
1833 }
1834}
1835
1836#[allow(dead_code)]
1838pub(crate) fn all_socket_rights() -> Rights {
1839 Rights::FD_FDSTAT_SET_FLAGS
1840 .union(Rights::FD_FILESTAT_GET)
1841 .union(Rights::FD_READ)
1842 .union(Rights::FD_WRITE)
1843 .union(Rights::POLL_FD_READWRITE)
1844 .union(Rights::SOCK_SHUTDOWN)
1845 .union(Rights::SOCK_CONNECT)
1846 .union(Rights::SOCK_LISTEN)
1847 .union(Rights::SOCK_BIND)
1848 .union(Rights::SOCK_ACCEPT)
1849 .union(Rights::SOCK_RECV)
1850 .union(Rights::SOCK_SEND)
1851 .union(Rights::SOCK_ADDR_LOCAL)
1852 .union(Rights::SOCK_ADDR_REMOTE)
1853 .union(Rights::SOCK_RECV_FROM)
1854 .union(Rights::SOCK_SEND_TO)
1855}
1856
1857#[cfg(test)]
1858mod tests {
1859 use super::{InodeSocket, InodeSocketKind, SocketProperties, WasiSocketStatus};
1860 use std::{
1861 future::pending,
1862 mem::MaybeUninit,
1863 net::{Ipv4Addr, Shutdown, SocketAddr},
1864 pin::Pin,
1865 sync::{
1866 Arc,
1867 atomic::{AtomicUsize, Ordering},
1868 },
1869 task::{Context, Poll},
1870 time::Duration,
1871 };
1872 use virtual_mio::InterestHandler;
1873 use virtual_net::{
1874 NetworkError, Result as NetResult, SocketStatus, VirtualConnectedSocket, VirtualIoSource,
1875 VirtualNetworking, VirtualSocket, VirtualTcpBoundSocket, VirtualTcpSocket,
1876 };
1877 use wasmer_wasix_types::wasi::{Addressfamily, Errno, SockProto, Socktype};
1878
1879 #[derive(Debug)]
1880 struct MockTcpSocket {
1881 read_calls: Arc<AtomicUsize>,
1882 write_calls: Arc<AtomicUsize>,
1883 status: Arc<AtomicUsize>,
1884 }
1885
1886 const MOCK_STATUS_OPENING: usize = 0;
1887 const MOCK_STATUS_OPENED: usize = 1;
1888
1889 fn decode_mock_status(value: usize) -> SocketStatus {
1890 match value {
1891 MOCK_STATUS_OPENED => SocketStatus::Opened,
1892 _ => SocketStatus::Opening,
1893 }
1894 }
1895
1896 impl VirtualIoSource for MockTcpSocket {
1897 fn remove_handler(&mut self) {}
1898
1899 fn poll_read_ready(&mut self, _cx: &mut Context<'_>) -> Poll<NetResult<usize>> {
1900 self.read_calls.fetch_add(1, Ordering::Relaxed);
1901 Poll::Ready(Ok(3))
1902 }
1903
1904 fn poll_write_ready(&mut self, _cx: &mut Context<'_>) -> Poll<NetResult<usize>> {
1905 self.write_calls.fetch_add(1, Ordering::Relaxed);
1906 self.status.store(MOCK_STATUS_OPENED, Ordering::Relaxed);
1907 Poll::Ready(Ok(7))
1908 }
1909 }
1910
1911 impl VirtualSocket for MockTcpSocket {
1912 fn set_ttl(&mut self, _ttl: u32) -> NetResult<()> {
1913 Ok(())
1914 }
1915
1916 fn ttl(&self) -> NetResult<u32> {
1917 Ok(64)
1918 }
1919
1920 fn addr_local(&self) -> NetResult<SocketAddr> {
1921 Ok(SocketAddr::from((Ipv4Addr::LOCALHOST, 0)))
1922 }
1923
1924 fn status(&self) -> NetResult<SocketStatus> {
1925 Ok(decode_mock_status(self.status.load(Ordering::Relaxed)))
1926 }
1927
1928 fn set_handler(
1929 &mut self,
1930 _handler: Box<dyn InterestHandler + Send + Sync>,
1931 ) -> NetResult<()> {
1932 Ok(())
1933 }
1934 }
1935
1936 impl VirtualConnectedSocket for MockTcpSocket {
1937 fn set_linger(&mut self, _linger: Option<Duration>) -> NetResult<()> {
1938 Ok(())
1939 }
1940
1941 fn linger(&self) -> NetResult<Option<Duration>> {
1942 Ok(None)
1943 }
1944
1945 fn try_send(&mut self, _data: &[u8]) -> NetResult<usize> {
1946 Err(NetworkError::Unsupported)
1947 }
1948
1949 fn try_flush(&mut self) -> NetResult<()> {
1950 Err(NetworkError::Unsupported)
1951 }
1952
1953 fn close(&mut self) -> NetResult<()> {
1954 Ok(())
1955 }
1956
1957 fn try_recv(&mut self, _buf: &mut [MaybeUninit<u8>], _peek: bool) -> NetResult<usize> {
1958 Err(NetworkError::Unsupported)
1959 }
1960 }
1961
1962 impl VirtualTcpSocket for MockTcpSocket {
1963 fn set_recv_buf_size(&mut self, _size: usize) -> NetResult<()> {
1964 Ok(())
1965 }
1966
1967 fn recv_buf_size(&self) -> NetResult<usize> {
1968 Ok(0)
1969 }
1970
1971 fn set_send_buf_size(&mut self, _size: usize) -> NetResult<()> {
1972 Ok(())
1973 }
1974
1975 fn send_buf_size(&self) -> NetResult<usize> {
1976 Ok(0)
1977 }
1978
1979 fn set_nodelay(&mut self, _reuse: bool) -> NetResult<()> {
1980 Ok(())
1981 }
1982
1983 fn nodelay(&self) -> NetResult<bool> {
1984 Ok(true)
1985 }
1986
1987 fn set_keepalive(&mut self, _keepalive: bool) -> NetResult<()> {
1988 Ok(())
1989 }
1990
1991 fn keepalive(&self) -> NetResult<bool> {
1992 Ok(false)
1993 }
1994
1995 fn set_dontroute(&mut self, _keepalive: bool) -> NetResult<()> {
1996 Ok(())
1997 }
1998
1999 fn dontroute(&self) -> NetResult<bool> {
2000 Ok(false)
2001 }
2002
2003 fn addr_peer(&self) -> NetResult<SocketAddr> {
2004 Ok(SocketAddr::from((Ipv4Addr::LOCALHOST, 80)))
2005 }
2006
2007 fn shutdown(&mut self, _how: Shutdown) -> NetResult<()> {
2008 Ok(())
2009 }
2010
2011 fn is_closed(&self) -> bool {
2012 false
2013 }
2014 }
2015
2016 #[derive(Debug)]
2017 struct MockTcpBoundSocket {
2018 ttl: Arc<AtomicUsize>,
2019 }
2020
2021 impl VirtualTcpBoundSocket for MockTcpBoundSocket {
2022 fn addr_local(&self) -> NetResult<SocketAddr> {
2023 Ok(SocketAddr::from((Ipv4Addr::LOCALHOST, 0)))
2024 }
2025
2026 fn listen(&mut self) -> NetResult<Box<dyn virtual_net::VirtualTcpListener + Sync>> {
2027 Err(NetworkError::Unsupported)
2028 }
2029
2030 fn connect(
2031 &mut self,
2032 _peer: SocketAddr,
2033 ) -> NetResult<Box<dyn virtual_net::VirtualTcpSocket + Sync>> {
2034 Err(NetworkError::Unsupported)
2035 }
2036
2037 fn set_ttl(&mut self, ttl: u32) -> NetResult<()> {
2038 self.ttl.store(ttl as usize, Ordering::Relaxed);
2039 Ok(())
2040 }
2041
2042 fn ttl(&self) -> NetResult<u32> {
2043 Ok(self.ttl.load(Ordering::Relaxed) as u32)
2044 }
2045 }
2046
2047 #[derive(Debug)]
2048 struct PendingBindNetworking;
2049
2050 #[async_trait::async_trait]
2051 impl VirtualNetworking for PendingBindNetworking {
2052 async fn bind_tcp(
2053 &self,
2054 _addr: SocketAddr,
2055 _only_v6: bool,
2056 _reuse_port: bool,
2057 _reuse_addr: bool,
2058 ) -> NetResult<Box<dyn VirtualTcpBoundSocket + Sync>> {
2059 pending::<()>().await;
2060 unreachable!("pending bind_tcp future should never complete")
2061 }
2062 }
2063
2064 #[test]
2065 fn inode_socket_poll_write_ready_uses_write_path() {
2066 let read_calls = Arc::new(AtomicUsize::new(0));
2067 let write_calls = Arc::new(AtomicUsize::new(0));
2068 let status = Arc::new(AtomicUsize::new(MOCK_STATUS_OPENED));
2069 let mut inode = InodeSocket::new(InodeSocketKind::TcpStream {
2070 socket: Box::new(MockTcpSocket {
2071 read_calls: read_calls.clone(),
2072 write_calls: write_calls.clone(),
2073 status,
2074 }),
2075 write_timeout: None,
2076 read_timeout: None,
2077 });
2078
2079 let waker = futures::task::noop_waker();
2080 let mut cx = Context::from_waker(&waker);
2081 let ready = Pin::new(&mut inode).poll_write_ready(&mut cx);
2082
2083 assert!(matches!(ready, Poll::Ready(Ok(7))));
2084 assert_eq!(read_calls.load(Ordering::Relaxed), 0);
2085 assert_eq!(write_calls.load(Ordering::Relaxed), 1);
2086 }
2087
2088 #[test]
2089 fn inode_socket_status_tracks_tcp_socket_status() {
2090 let status = Arc::new(AtomicUsize::new(MOCK_STATUS_OPENING));
2091 let inode = InodeSocket::new(InodeSocketKind::TcpStream {
2092 socket: Box::new(MockTcpSocket {
2093 read_calls: Arc::new(AtomicUsize::new(0)),
2094 write_calls: Arc::new(AtomicUsize::new(0)),
2095 status: status.clone(),
2096 }),
2097 write_timeout: None,
2098 read_timeout: None,
2099 });
2100
2101 assert!(matches!(inode.status().unwrap(), WasiSocketStatus::Opening));
2102 status.store(MOCK_STATUS_OPENED, Ordering::Relaxed);
2103 assert!(matches!(inode.status().unwrap(), WasiSocketStatus::Opened));
2104 }
2105
2106 #[test]
2107 fn inode_socket_bound_tcp_forwards_ttl() {
2108 let ttl = Arc::new(AtomicUsize::new(64));
2109 let inode = InodeSocket::new(InodeSocketKind::BoundTcp {
2110 socket: Box::new(MockTcpBoundSocket { ttl: ttl.clone() }),
2111 props: SocketProperties {
2112 family: Addressfamily::Inet4,
2113 ty: Socktype::Stream,
2114 pt: SockProto::Tcp,
2115 only_v6: false,
2116 reuse_port: false,
2117 reuse_addr: false,
2118 no_delay: None,
2119 keep_alive: None,
2120 dont_route: None,
2121 send_buf_size: None,
2122 recv_buf_size: None,
2123 write_timeout: None,
2124 read_timeout: None,
2125 accept_timeout: None,
2126 connect_timeout: None,
2127 handler: None,
2128 },
2129 });
2130
2131 inode.set_ttl(42).unwrap();
2132 assert_eq!(inode.ttl().unwrap(), 42);
2133 assert_eq!(ttl.load(Ordering::Relaxed), 42);
2134 }
2135
2136 #[cfg(feature = "sys")]
2137 #[tokio::test(flavor = "current_thread")]
2138 async fn inode_socket_tcp_bind_respects_bind_timeout() {
2139 let inode = InodeSocket::new(InodeSocketKind::PreSocket {
2140 props: SocketProperties {
2141 family: Addressfamily::Inet4,
2142 ty: Socktype::Stream,
2143 pt: SockProto::Tcp,
2144 only_v6: false,
2145 reuse_port: false,
2146 reuse_addr: false,
2147 no_delay: None,
2148 keep_alive: None,
2149 dont_route: None,
2150 send_buf_size: None,
2151 recv_buf_size: None,
2152 write_timeout: None,
2153 read_timeout: None,
2154 accept_timeout: None,
2155 connect_timeout: None,
2156 handler: None,
2157 },
2158 addr: None,
2159 });
2160 let tasks = crate::runtime::task_manager::tokio::TokioTaskManager::default();
2161 let net = PendingBindNetworking;
2162
2163 let err = inode
2164 .bind_internal(
2165 &tasks,
2166 &net,
2167 SocketAddr::from((Ipv4Addr::LOCALHOST, 0)),
2168 Duration::from_millis(10),
2169 )
2170 .await
2171 .unwrap_err();
2172 assert_eq!(err, Errno::Timedout);
2173 }
2174}