Skip to content

Commit 6f21e2e

Browse files
Add polling and networking for target_os = "wasi"
Based on tokio-rs#1395 And with * bytecodealliance/wasmtime#3711 * rust-lang/rust#93158 merged, mio can have limited support for networking for the `wasm32-wasi` target. Co-authored-by: Thomas de Zeeuw <[email protected]> Signed-off-by: Harald Hoyer <[email protected]>
1 parent efb1728 commit 6f21e2e

File tree

13 files changed

+503
-2
lines changed

13 files changed

+503
-2
lines changed

Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ miow = "0.3.6"
4949
winapi = { version = "0.3", features = ["winsock2", "mswsock"] }
5050
ntapi = "0.3"
5151

52+
[target.'cfg(target_os = "wasi")'.dependencies]
53+
wasi = "0.11.0"
54+
libc = "0.2.86"
55+
5256
[dev-dependencies]
5357
env_logger = { version = "0.8.4", default-features = false }
5458
rand = "0.8"

src/io_source.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use std::ops::{Deref, DerefMut};
22
#[cfg(unix)]
33
use std::os::unix::io::AsRawFd;
4+
#[cfg(target_os = "wasi")]
5+
use std::os::wasi::io::AsRawFd;
46
#[cfg(windows)]
57
use std::os::windows::io::AsRawSocket;
68
#[cfg(target_os = "hermit")]
@@ -204,6 +206,44 @@ where
204206
}
205207
}
206208

209+
#[cfg(target_os = "wasi")]
210+
impl<T> event::Source for IoSource<T>
211+
where
212+
T: AsRawFd,
213+
{
214+
fn register(
215+
&mut self,
216+
registry: &Registry,
217+
token: Token,
218+
interests: Interest,
219+
) -> io::Result<()> {
220+
#[cfg(debug_assertions)]
221+
self.selector_id.associate(registry)?;
222+
registry
223+
.selector()
224+
.register(self.inner.as_raw_fd() as _, token, interests)
225+
}
226+
227+
fn reregister(
228+
&mut self,
229+
registry: &Registry,
230+
token: Token,
231+
interests: Interest,
232+
) -> io::Result<()> {
233+
#[cfg(debug_assertions)]
234+
self.selector_id.check_association(registry)?;
235+
registry
236+
.selector()
237+
.reregister(self.inner.as_raw_fd() as _, token, interests)
238+
}
239+
240+
fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
241+
#[cfg(debug_assertions)]
242+
self.selector_id.remove_association(registry)?;
243+
registry.selector().deregister(self.inner.as_raw_fd() as _)
244+
}
245+
}
246+
207247
#[cfg(target_os = "hermit")]
208248
impl<T> event::Source for IoSource<T>
209249
where

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ mod interest;
5252
mod poll;
5353
mod sys;
5454
mod token;
55+
#[cfg(not(target_os = "wasi"))]
5556
mod waker;
5657

5758
pub mod event;
@@ -69,6 +70,7 @@ pub use event::Events;
6970
pub use interest::Interest;
7071
pub use poll::{Poll, Registry};
7172
pub use token::Token;
73+
#[cfg(not(target_os = "wasi"))]
7274
pub use waker::Waker;
7375

7476
#[cfg(all(unix, feature = "os-ext"))]

src/net/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
mod tcp;
2929
pub use self::tcp::{TcpListener, TcpStream};
3030

31+
#[cfg(not(target_os = "wasi"))]
3132
mod udp;
33+
#[cfg(not(target_os = "wasi"))]
3234
pub use self::udp::UdpSocket;
3335

3436
#[cfg(unix)]

src/net/tcp/listener.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
use std::net::{self, SocketAddr};
22
#[cfg(unix)]
33
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
4+
#[cfg(target_os = "wasi")]
5+
use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
46
#[cfg(windows)]
57
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
68
#[cfg(target_os = "hermit")]
@@ -13,6 +15,7 @@ use crate::io_source::IoSource;
1315
use crate::net::TcpStream;
1416
#[cfg(unix)]
1517
use crate::sys::tcp::set_reuseaddr;
18+
#[cfg(not(target_os = "wasi"))]
1619
use crate::sys::tcp::{bind, listen, new_for_addr};
1720
use crate::{event, sys, Interest, Registry, Token};
1821

@@ -54,6 +57,7 @@ impl TcpListener {
5457
/// 2. Set the `SO_REUSEADDR` option on the socket on Unix.
5558
/// 3. Bind the socket to the specified address.
5659
/// 4. Calls `listen` on the socket to prepare it to receive new connections.
60+
#[cfg(not(target_os = "wasi"))]
5761
pub fn bind(addr: SocketAddr) -> io::Result<TcpListener> {
5862
let socket = new_for_addr(addr)?;
5963
#[cfg(unix)]
@@ -243,3 +247,30 @@ impl FromAbi for TcpListener {
243247
TcpListener::from_std(FromAbi::from_abi(socket))
244248
}
245249
}
250+
251+
#[cfg(target_os = "wasi")]
252+
impl IntoRawFd for TcpListener {
253+
fn into_raw_fd(self) -> RawFd {
254+
self.inner.into_inner().into_raw_fd()
255+
}
256+
}
257+
258+
#[cfg(target_os = "wasi")]
259+
impl AsRawFd for TcpListener {
260+
fn as_raw_fd(&self) -> RawFd {
261+
self.inner.as_raw_fd()
262+
}
263+
}
264+
265+
#[cfg(target_os = "wasi")]
266+
impl FromRawFd for TcpListener {
267+
/// Converts a `RawFd` to a `TcpListener`.
268+
///
269+
/// # Notes
270+
///
271+
/// The caller is responsible for ensuring that the socket is in
272+
/// non-blocking mode.
273+
unsafe fn from_raw_fd(fd: RawFd) -> TcpListener {
274+
TcpListener::from_std(FromRawFd::from_raw_fd(fd))
275+
}
276+
}

src/net/tcp/stream.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ use std::io::{self, IoSlice, IoSliceMut, Read, Write};
33
use std::net::{self, Shutdown, SocketAddr};
44
#[cfg(unix)]
55
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
6+
#[cfg(target_os = "wasi")]
7+
use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
68
#[cfg(windows)]
79
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
810
#[cfg(target_os = "hermit")]
@@ -11,6 +13,7 @@ use std::os::hermit::abi;
1113
use std::os::hermit::io::{AsAbi, FromAbi, IntoAbi};
1214

1315
use crate::io_source::IoSource;
16+
#[cfg(not(target_os = "wasi"))]
1417
use crate::sys::tcp::{connect, new_for_addr};
1518
use crate::{event, Interest, Registry, Token};
1619

@@ -77,6 +80,7 @@ impl TcpStream {
7780
/// 5. Now the stream can be used.
7881
///
7982
/// [read interest]: Interest::READABLE
83+
#[cfg(not(target_os = "wasi"))]
8084
pub fn connect(addr: SocketAddr) -> io::Result<TcpStream> {
8185
let socket = new_for_addr(addr)?;
8286
#[cfg(unix)]
@@ -362,3 +366,30 @@ impl FromAbi for TcpStream {
362366
TcpStream::from_std(FromAbi::from_abi(socket))
363367
}
364368
}
369+
370+
#[cfg(target_os = "wasi")]
371+
impl IntoRawFd for TcpStream {
372+
fn into_raw_fd(self) -> RawFd {
373+
self.inner.into_inner().into_raw_fd()
374+
}
375+
}
376+
377+
#[cfg(target_os = "wasi")]
378+
impl AsRawFd for TcpStream {
379+
fn as_raw_fd(&self) -> RawFd {
380+
self.inner.as_raw_fd()
381+
}
382+
}
383+
384+
#[cfg(target_os = "wasi")]
385+
impl FromRawFd for TcpStream {
386+
/// Converts a `RawFd` to a `TcpStream`.
387+
///
388+
/// # Notes
389+
///
390+
/// The caller is responsible for ensuring that the socket is in
391+
/// non-blocking mode.
392+
unsafe fn from_raw_fd(fd: RawFd) -> TcpStream {
393+
TcpStream::from_std(FromRawFd::from_raw_fd(fd))
394+
}
395+
}

src/poll.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -635,6 +635,7 @@ impl Registry {
635635
///
636636
/// Event sources registered with this `Registry` will be registered with
637637
/// the original `Registry` and `Poll` instance.
638+
#[cfg(not(target_os = "wasi"))]
638639
pub fn try_clone(&self) -> io::Result<Registry> {
639640
self.selector
640641
.try_clone()
@@ -643,7 +644,7 @@ impl Registry {
643644

644645
/// Internal check to ensure only a single `Waker` is active per [`Poll`]
645646
/// instance.
646-
#[cfg(debug_assertions)]
647+
#[cfg(all(debug_assertions, not(target_os = "wasi")))]
647648
pub(crate) fn register_waker(&self) {
648649
assert!(
649650
!self.selector.register_waker(),
@@ -652,6 +653,7 @@ impl Registry {
652653
}
653654

654655
/// Get access to the `sys::Selector`.
656+
#[cfg(any(not(target_os = "wasi"), feature = "net"))]
655657
pub(crate) fn selector(&self) -> &sys::Selector {
656658
&self.selector
657659
}

src/sys/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,12 @@ cfg_os_poll! {
7070
pub use self::windows::*;
7171
}
7272

73+
#[cfg(target_os = "wasi")]
74+
cfg_os_poll! {
75+
mod wasi;
76+
pub(crate) use self::wasi::*;
77+
}
78+
7379
cfg_not_os_poll! {
7480
mod shell;
7581
pub(crate) use self::shell::*;

src/sys/shell/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ macro_rules! os_required {
77
mod selector;
88
pub(crate) use self::selector::{event, Event, Events, Selector};
99

10+
#[cfg(not(target_os = "wasi"))]
1011
mod waker;
12+
#[cfg(not(target_os = "wasi"))]
1113
pub(crate) use self::waker::Waker;
1214

1315
cfg_net! {

src/sys/shell/selector.rs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub type Events = Vec<Event>;
1111
pub struct Selector {}
1212

1313
impl Selector {
14+
#[cfg(not(target_os = "wasi"))]
1415
pub fn try_clone(&self) -> io::Result<Selector> {
1516
os_required!();
1617
}
@@ -19,7 +20,7 @@ impl Selector {
1920
os_required!();
2021
}
2122

22-
#[cfg(debug_assertions)]
23+
#[cfg(all(debug_assertions, not(target_os = "wasi")))]
2324
pub fn register_waker(&self) -> bool {
2425
os_required!();
2526
}
@@ -44,6 +45,25 @@ cfg_any_os_ext! {
4445
}
4546
}
4647

48+
#[cfg(target_os = "wasi")]
49+
cfg_any_os_ext! {
50+
use crate::{Interest, Token};
51+
52+
impl Selector {
53+
pub fn register(&self, _: wasi::Fd, _: Token, _: Interest) -> io::Result<()> {
54+
os_required!();
55+
}
56+
57+
pub fn reregister(&self, _: wasi::Fd, _: Token, _: Interest) -> io::Result<()> {
58+
os_required!();
59+
}
60+
61+
pub fn deregister(&self, _: wasi::Fd) -> io::Result<()> {
62+
os_required!();
63+
}
64+
}
65+
}
66+
4767
cfg_io_source! {
4868
#[cfg(debug_assertions)]
4969
impl Selector {

0 commit comments

Comments
 (0)