async_wasi/snapshots/preview_1/
async_poll.rs1use crate::snapshots::{
2 common::{
3 memory::{Memory, WasmPtr},
4 net::{self, ConnectState, SubscriptionClock},
5 types::*,
6 },
7 Errno, WasiCtx,
8};
9use futures::{stream::FuturesUnordered, StreamExt};
10use net::{async_tokio::AsyncWasiSocket, PrePoll, SubscriptionFd, SubscriptionFdType};
11use std::time::Duration;
12
13fn handle_event_err(type_: SubscriptionFdType, errno: Errno) -> __wasi_event_t {
14 let mut r = __wasi_event_t {
15 userdata: 0,
16 error: errno.0,
17 type_: 0,
18 fd_readwrite: __wasi_event_fd_readwrite_t {
19 nbytes: 0,
20 flags: 0,
21 },
22 };
23 match type_ {
24 SubscriptionFdType::Read(userdata) => {
25 r.userdata = userdata;
26 r.type_ = __wasi_eventtype_t::__WASI_EVENTTYPE_FD_READ;
27 }
28 SubscriptionFdType::Write(userdata) => {
29 r.userdata = userdata;
30 r.type_ = __wasi_eventtype_t::__WASI_EVENTTYPE_FD_WRITE;
31 }
32 SubscriptionFdType::Both { read: userdata, .. } => {
33 r.userdata = userdata;
34 r.type_ = __wasi_eventtype_t::__WASI_EVENTTYPE_FD_READ;
35 }
36 }
37 r
38}
39
40async fn wait_fd(
41 fd_index: usize,
42 socket: &AsyncWasiSocket,
43 type_: SubscriptionFdType,
44) -> Result<(__wasi_event_t, Option<usize>), Errno> {
45 let connecting = ConnectState::Connecting == socket.state.so_conn_state;
46
47 let handler = |r: Result<(), std::io::Error>, userdata, type_| {
48 log::trace!("wait_fd {fd_index} {r:?}");
49 match r {
50 Ok(_) => (
51 __wasi_event_t {
52 userdata,
53 error: 0,
54 type_,
55 fd_readwrite: __wasi_event_fd_readwrite_t {
56 nbytes: 0,
57 flags: 0,
58 },
59 },
60 if connecting { Some(fd_index) } else { None },
61 ),
62 Err(e) => (
63 __wasi_event_t {
64 userdata,
65 error: Errno::from(e).0,
66 type_,
67 fd_readwrite: __wasi_event_fd_readwrite_t {
68 nbytes: 0,
69 flags: __wasi_eventrwflags_t::__WASI_EVENTRWFLAGS_FD_READWRITE_HANGUP,
70 },
71 },
72 None,
73 ),
74 }
75 };
76
77 match type_ {
78 SubscriptionFdType::Write(userdata) => {
79 let write_result = socket.writable().await;
80 log::trace!("wait_fd {fd_index} writeable");
81
82 Ok(handler(
83 write_result,
84 userdata,
85 __wasi_eventtype_t::__WASI_EVENTTYPE_FD_WRITE,
86 ))
87 }
88 SubscriptionFdType::Read(userdata) => {
89 let read_result = socket.readable().await;
90 log::trace!("wait_fd {fd_index} readable");
91
92 Ok(handler(
93 read_result,
94 userdata,
95 __wasi_eventtype_t::__WASI_EVENTTYPE_FD_READ,
96 ))
97 }
98 SubscriptionFdType::Both { read, write } => {
99 tokio::select! {
100 read_result=socket.readable()=>{
101 log::trace!("wait_fd {fd_index} readable");
102
103 Ok(handler(
104 read_result,
105 read,
106 __wasi_eventtype_t::__WASI_EVENTTYPE_FD_READ,
107 ))
108 }
109 write_result=socket.writable()=>{
110 log::trace!("wait_fd {fd_index} writeable");
111
112 Ok(handler(
113 write_result,
114 write,
115 __wasi_eventtype_t::__WASI_EVENTTYPE_FD_WRITE,
116 ))
117 }
118 }
119 }
120 }
121}
122
123async fn poll_only_fd<M: Memory>(
124 ctx: &mut WasiCtx,
125 mem: &mut M,
126 out_ptr: WasmPtr<__wasi_event_t>,
127 nsubscriptions: usize,
128 revents_num_ptr: WasmPtr<__wasi_size_t>,
129 fd_vec: Vec<SubscriptionFd>,
130) -> Result<(), Errno> {
131 if fd_vec.is_empty() {
132 mem.write_data(revents_num_ptr, 0)?;
133 } else {
134 let r_events = mem.mut_slice(out_ptr, nsubscriptions)?;
135 let mut wait = FuturesUnordered::new();
136 let mut i = 0;
137 for SubscriptionFd { fd, type_ } in fd_vec {
138 match ctx.vfs.get_socket(fd as usize) {
139 Ok(s) => {
140 wait.push(wait_fd(fd as usize, s, type_));
141 }
142 Err(e) => {
143 r_events[i] = handle_event_err(type_, e);
144 i += 1;
145 }
146 }
147 }
148
149 if i == 0 {
150 let mut connected_fds = vec![];
151
152 let (v, connected_fd) = wait.select_next_some().await?;
153 connected_fds.push(connected_fd);
154 r_events[i] = v;
155 i += 1;
156
157 'wait_poll: loop {
158 if i >= nsubscriptions {
159 break 'wait_poll;
160 }
161 futures::select! {
162 v = wait.next() => {
163 if let Some(v) = v {
164 let (v, connected_fd) = v?;
165 connected_fds.push(connected_fd);
166 r_events[i] = v;
167 i += 1;
168 } else {
169 break 'wait_poll;
170 }
171 }
172 default => {
173 break 'wait_poll;
174 }
175 };
176 }
177
178 drop(wait);
179
180 for fd in connected_fds.into_iter().flatten() {
181 if let Ok(socket) = ctx.vfs.get_mut_socket(fd) {
182 socket.state.so_conn_state = ConnectState::Connected;
183 socket.writable.set_writable();
184 }
185 }
186 }
187
188 mem.write_data(revents_num_ptr, i as u32)?;
189 }
190 Ok(())
191}
192
193async fn poll_fd_timeout<M: Memory>(
194 ctx: &mut WasiCtx,
195 mem: &mut M,
196 out_ptr: WasmPtr<__wasi_event_t>,
197 nsubscriptions: usize,
198 revents_num_ptr: WasmPtr<__wasi_size_t>,
199 clock: SubscriptionClock,
200 fd_vec: Vec<SubscriptionFd>,
201) -> Result<(), Errno> {
202 let r_events = mem.mut_slice(out_ptr, nsubscriptions)?;
203 let mut wait = FuturesUnordered::new();
204
205 let mut i = 0;
206
207 for SubscriptionFd { fd, type_ } in fd_vec {
208 match ctx.vfs.get_socket(fd as usize) {
209 Ok(s) => {
210 wait.push(wait_fd(fd as usize, s, type_));
211 }
212 Err(e) => {
213 r_events[i] = handle_event_err(type_, e);
214 i += 1;
215 }
216 }
217 }
218
219 if i == 0 {
220 let ddl = clock.timeout.unwrap();
221 let now = std::time::SystemTime::now();
222 let timeout = ddl.duration_since(now).unwrap_or(Duration::from_secs(0));
223 let sleep = tokio::time::timeout(timeout, wait.select_next_some()).await;
224 if sleep.is_err() {
225 let r_event = &mut r_events[0];
226 r_event.userdata = clock.userdata;
227 r_event.type_ = __wasi_eventtype_t::__WASI_EVENTTYPE_CLOCK;
228 mem.write_data(revents_num_ptr, 1)?;
229 return Ok(());
230 }
231
232 let mut connected_fds = vec![];
233
234 let (first, connected_fd) = sleep.unwrap()?;
235 connected_fds.push(connected_fd);
236 r_events[i] = first;
237 i += 1;
238
239 'wait: loop {
240 if i >= nsubscriptions {
241 break 'wait;
242 }
243 futures::select! {
244 v = wait.next() => {
245 if let Some(v) = v {
246 let (v,connected_fd) = v?;
247 connected_fds.push(connected_fd);
248 r_events[i] = v;
249 i += 1;
250 } else {
251 break 'wait;
252 }
253 }
254 default => {
255 break 'wait;
256 }
257 };
258 }
259
260 drop(wait);
261
262 for fd in connected_fds.into_iter().flatten() {
263 if let Ok(socket) = ctx.vfs.get_mut_socket(fd) {
264 socket.state.so_conn_state = ConnectState::Connected;
265 }
266 }
267 }
268
269 mem.write_data(revents_num_ptr, i as u32)?;
270 Ok(())
271}
272
273pub async fn poll_oneoff<M: Memory>(
274 ctx: &mut WasiCtx,
275 mem: &mut M,
276 in_ptr: WasmPtr<__wasi_subscription_t>,
277 out_ptr: WasmPtr<__wasi_event_t>,
278 nsubscriptions: __wasi_size_t,
279 revents_num_ptr: WasmPtr<__wasi_size_t>,
280) -> Result<(), Errno> {
281 log::trace!("poll_oneoff");
282 poll_oneoff_impl(ctx, mem, in_ptr, out_ptr, nsubscriptions, revents_num_ptr).await
283}
284
285async fn poll_oneoff_impl<M: Memory>(
286 ctx: &mut WasiCtx,
287 mem: &mut M,
288 in_ptr: WasmPtr<__wasi_subscription_t>,
289 out_ptr: WasmPtr<__wasi_event_t>,
290 nsubscriptions: __wasi_size_t,
291 revents_num_ptr: WasmPtr<__wasi_size_t>,
292) -> Result<(), Errno> {
293 if nsubscriptions == 0 {
294 return Ok(());
295 }
296
297 let nsubscriptions = nsubscriptions as usize;
298
299 let subs = mem.get_slice(in_ptr, nsubscriptions)?;
300 let prepoll = PrePoll::from_wasi_subscription(subs)?;
301
302 log::trace!("poll_oneoff subs prepoll={:#?}", prepoll);
303
304 match prepoll {
305 PrePoll::OnlyFd(fd_vec) => {
306 poll_only_fd(ctx, mem, out_ptr, nsubscriptions, revents_num_ptr, fd_vec).await?;
307 }
308 PrePoll::ClockAndFd(clock, fd_vec) => {
309 poll_fd_timeout(
310 ctx,
311 mem,
312 out_ptr,
313 nsubscriptions,
314 revents_num_ptr,
315 clock,
316 fd_vec,
317 )
318 .await?;
319 }
320 PrePoll::OnlyClock(clock) => {
321 if let Some(e) = clock.err {
322 let r_event = mem.mut_data(out_ptr)?;
323 r_event.userdata = clock.userdata;
324 r_event.type_ = __wasi_eventtype_t::__WASI_EVENTTYPE_CLOCK;
325 r_event.error = e.0;
326 mem.write_data(revents_num_ptr, 1)?;
327 return Ok(());
328 }
329 if let Some(ddl) = clock.timeout {
330 let now = std::time::SystemTime::now();
331 let dur = ddl.duration_since(now).unwrap_or(Duration::from_secs(0));
332 tokio::time::sleep(dur).await;
333 let r_event = mem.mut_data(out_ptr)?;
334 r_event.userdata = clock.userdata;
335 r_event.type_ = __wasi_eventtype_t::__WASI_EVENTTYPE_CLOCK;
336 mem.write_data(revents_num_ptr, 1)?;
337 return Ok(());
338 }
339 }
340 }
341 Ok(())
342}