wasmer_wasix/syscalls/wasix/
sock_accept.rs1use std::task::Waker;
2
3use super::*;
4use crate::{net::socket::TimeType, syscalls::*};
5
6#[instrument(level = "trace", skip_all, fields(%sock, fd = field::Empty), ret)]
19pub fn sock_accept<M: MemorySize>(
20 mut ctx: FunctionEnvMut<'_, WasiEnv>,
21 sock: WasiFd,
22 fd_flags: Fdflags,
23 ro_fd: WasmPtr<WasiFd, M>,
24) -> Result<Errno, WasiError> {
25 WasiEnv::do_pending_operations(&mut ctx)?;
26
27 ctx = wasi_try_ok!(maybe_snapshot::<M>(ctx)?);
28
29 let env = ctx.data();
30 let (memory, state, _) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
31
32 let nonblocking = fd_flags.contains(Fdflags::NONBLOCK);
33
34 let (fd, _, _) = wasi_try_ok!(sock_accept_internal(
35 env,
36 sock,
37 fd_flags,
38 nonblocking,
39 None
40 )?);
41
42 wasi_try_mem_ok!(ro_fd.write(&memory, fd));
43
44 Ok(Errno::Success)
45}
46
47#[instrument(level = "trace", skip_all, fields(%sock, fd = field::Empty), ret)]
61pub fn sock_accept_v2<M: MemorySize>(
62 mut ctx: FunctionEnvMut<'_, WasiEnv>,
63 sock: WasiFd,
64 fd_flags: Fdflags,
65 ro_fd: WasmPtr<WasiFd, M>,
66 ro_addr: WasmPtr<__wasi_addr_port_t, M>,
67) -> Result<Errno, WasiError> {
68 WasiEnv::do_pending_operations(&mut ctx)?;
69
70 let env = ctx.data();
71 let (memory, state, _) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
72
73 let nonblocking = fd_flags.contains(Fdflags::NONBLOCK);
74
75 let (fd, local_addr, peer_addr) = wasi_try_ok!(sock_accept_internal(
76 env,
77 sock,
78 fd_flags,
79 nonblocking,
80 None
81 )?);
82
83 #[cfg(feature = "journal")]
84 if ctx.data().enable_journal {
85 JournalEffector::save_sock_accepted(
86 &mut ctx,
87 sock,
88 fd,
89 local_addr,
90 peer_addr,
91 fd_flags,
92 nonblocking,
93 )
94 .map_err(|err| {
95 tracing::error!("failed to save sock_accepted event - {}", err);
96 WasiError::Exit(ExitCode::from(Errno::Fault))
97 })?;
98 }
99
100 let env = ctx.data();
101 let (memory, state, _) = unsafe { env.get_memory_and_wasi_state_and_inodes(&ctx, 0) };
102 wasi_try_mem_ok!(ro_fd.write(&memory, fd));
103 wasi_try_ok!(crate::net::write_ip_port(
104 &memory,
105 ro_addr,
106 peer_addr.ip(),
107 peer_addr.port()
108 ));
109
110 Ok(Errno::Success)
111}
112
113pub(crate) fn sock_accept_internal(
114 env: &WasiEnv,
115 sock: WasiFd,
116 mut fd_flags: Fdflags,
117 mut nonblocking: bool,
118 with_fd: Option<WasiFd>,
119) -> Result<Result<(WasiFd, SocketAddr, SocketAddr), Errno>, WasiError> {
120 let state = env.state();
121 let inodes = &state.inodes;
122
123 let tasks = env.tasks().clone();
124 let (child, local_addr, peer_addr, fd_flags) = wasi_try_ok_ok!(__sock_asyncify(
125 env,
126 sock,
127 Rights::SOCK_ACCEPT,
128 move |socket, fd| async move {
129 if fd.inner.flags.contains(Fdflags::NONBLOCK) {
130 fd_flags.set(Fdflags::NONBLOCK, true);
131 nonblocking = true;
132 }
133 let timeout = socket
134 .opt_time(TimeType::AcceptTimeout)
135 .ok()
136 .flatten()
137 .unwrap_or(Duration::from_secs(30));
138 let local_addr = socket.addr_local()?;
139 socket
140 .accept(tasks.deref(), nonblocking, Some(timeout))
141 .await
142 .map(|a| (a.0, local_addr, a.1, fd_flags))
143 },
144 ));
145
146 let kind = Kind::Socket {
147 socket: InodeSocket::new(InodeSocketKind::TcpStream {
148 socket: child,
149 write_timeout: None,
150 read_timeout: None,
151 }),
152 };
153 let inode = state
154 .fs
155 .create_inode_with_default_stat(inodes, kind, false, "socket".into());
156
157 let mut new_flags = Fdflags::empty();
158 if fd_flags.contains(Fdflags::NONBLOCK) {
159 new_flags.set(Fdflags::NONBLOCK, true);
160 }
161
162 let mut new_flags = Fdflags::empty();
163 if fd_flags.contains(Fdflags::NONBLOCK) {
164 new_flags.set(Fdflags::NONBLOCK, true);
165 }
166
167 let rights = Rights::all_socket();
168 let fd = wasi_try_ok_ok!(if let Some(fd) = with_fd {
169 state
170 .fs
171 .with_fd(rights, rights, new_flags, Fdflagsext::empty(), 0, inode, fd)
172 .map(|_| fd)
173 } else {
174 state
175 .fs
176 .create_fd(rights, rights, new_flags, Fdflagsext::empty(), 0, inode)
177 });
178 Span::current().record("fd", fd);
179
180 Ok(Ok((fd, local_addr, peer_addr)))
181}