Skip to content

Commit 2628793

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 9f8ed3d commit 2628793

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(debug_assertions)]
@@ -200,6 +202,44 @@ where
200202
}
201203
}
202204

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

src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ mod interest;
4848
mod poll;
4949
mod sys;
5050
mod token;
51+
#[cfg(not(target_os = "wasi"))]
5152
mod waker;
5253

5354
pub mod event;
@@ -65,6 +66,7 @@ pub use event::Events;
6566
pub use interest::Interest;
6667
pub use poll::{Poll, Registry};
6768
pub use token::Token;
69+
#[cfg(not(target_os = "wasi"))]
6870
pub use waker::Waker;
6971

7072
#[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
use std::{fmt, io};
@@ -9,6 +11,7 @@ use crate::io_source::IoSource;
911
use crate::net::TcpStream;
1012
#[cfg(unix)]
1113
use crate::sys::tcp::set_reuseaddr;
14+
#[cfg(not(target_os = "wasi"))]
1215
use crate::sys::tcp::{bind, listen, new_for_addr};
1316
use crate::{event, sys, Interest, Registry, Token};
1417

@@ -52,6 +55,7 @@ impl TcpListener {
5255
/// 2. Set the `SO_REUSEADDR` option on the socket on Unix.
5356
/// 3. Bind the socket to the specified address.
5457
/// 4. Calls `listen` on the socket to prepare it to receive new connections.
58+
#[cfg(not(target_os = "wasi"))]
5559
pub fn bind(addr: SocketAddr) -> io::Result<TcpListener> {
5660
let socket = new_for_addr(addr)?;
5761
#[cfg(unix)]
@@ -215,3 +219,30 @@ impl FromRawSocket for TcpListener {
215219
TcpListener::from_std(FromRawSocket::from_raw_socket(socket))
216220
}
217221
}
222+
223+
#[cfg(target_os = "wasi")]
224+
impl IntoRawFd for TcpListener {
225+
fn into_raw_fd(self) -> RawFd {
226+
self.inner.into_inner().into_raw_fd()
227+
}
228+
}
229+
230+
#[cfg(target_os = "wasi")]
231+
impl AsRawFd for TcpListener {
232+
fn as_raw_fd(&self) -> RawFd {
233+
self.inner.as_raw_fd()
234+
}
235+
}
236+
237+
#[cfg(target_os = "wasi")]
238+
impl FromRawFd for TcpListener {
239+
/// Converts a `RawFd` to a `TcpListener`.
240+
///
241+
/// # Notes
242+
///
243+
/// The caller is responsible for ensuring that the socket is in
244+
/// non-blocking mode.
245+
unsafe fn from_raw_fd(fd: RawFd) -> TcpListener {
246+
TcpListener::from_std(FromRawFd::from_raw_fd(fd))
247+
}
248+
}

src/net/tcp/stream.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,13 @@ 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

911
use crate::io_source::IoSource;
12+
#[cfg(not(target_os = "wasi"))]
1013
use crate::sys::tcp::{connect, new_for_addr};
1114
use crate::{event, Interest, Registry, Token};
1215

@@ -73,6 +76,7 @@ impl TcpStream {
7376
/// 5. Now the stream can be used.
7477
///
7578
/// [read interest]: Interest::READABLE
79+
#[cfg(not(target_os = "wasi"))]
7680
pub fn connect(addr: SocketAddr) -> io::Result<TcpStream> {
7781
let socket = new_for_addr(addr)?;
7882
#[cfg(unix)]
@@ -332,3 +336,30 @@ impl FromRawSocket for TcpStream {
332336
TcpStream::from_std(FromRawSocket::from_raw_socket(socket))
333337
}
334338
}
339+
340+
#[cfg(target_os = "wasi")]
341+
impl IntoRawFd for TcpStream {
342+
fn into_raw_fd(self) -> RawFd {
343+
self.inner.into_inner().into_raw_fd()
344+
}
345+
}
346+
347+
#[cfg(target_os = "wasi")]
348+
impl AsRawFd for TcpStream {
349+
fn as_raw_fd(&self) -> RawFd {
350+
self.inner.as_raw_fd()
351+
}
352+
}
353+
354+
#[cfg(target_os = "wasi")]
355+
impl FromRawFd for TcpStream {
356+
/// Converts a `RawFd` to a `TcpStream`.
357+
///
358+
/// # Notes
359+
///
360+
/// The caller is responsible for ensuring that the socket is in
361+
/// non-blocking mode.
362+
unsafe fn from_raw_fd(fd: RawFd) -> TcpStream {
363+
TcpStream::from_std(FromRawFd::from_raw_fd(fd))
364+
}
365+
}

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
@@ -63,6 +63,12 @@ cfg_os_poll! {
6363
pub use self::windows::*;
6464
}
6565

66+
#[cfg(target_os = "wasi")]
67+
cfg_os_poll! {
68+
mod wasi;
69+
pub(crate) use self::wasi::*;
70+
}
71+
6672
cfg_not_os_poll! {
6773
mod shell;
6874
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 {

src/sys/shell/tcp.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,22 @@
11
use std::io;
22
use std::net::{self, SocketAddr};
33

4+
#[cfg(not(target_os = "wasi"))]
45
pub(crate) fn new_for_addr(_: SocketAddr) -> io::Result<i32> {
56
os_required!();
67
}
78

9+
#[cfg(not(target_os = "wasi"))]
810
pub(crate) fn bind(_: &net::TcpListener, _: SocketAddr) -> io::Result<()> {
911
os_required!();
1012
}
1113

14+
#[cfg(not(target_os = "wasi"))]
1215
pub(crate) fn connect(_: &net::TcpStream, _: SocketAddr) -> io::Result<()> {
1316
os_required!();
1417
}
1518

19+
#[cfg(not(target_os = "wasi"))]
1620
pub(crate) fn listen(_: &net::TcpListener, _: u32) -> io::Result<()> {
1721
os_required!();
1822
}

src/sys/shell/udp.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
#![cfg(not(target_os = "wasi"))]
12
use std::io;
23
use std::net::{self, SocketAddr};
34

0 commit comments

Comments
 (0)