Skip to content

Commit 8b55675

Browse files
committed
Add networking for target_os = "wasi"
With * bytecodealliance/wasmtime#3711 * rust-lang/rust#93158 merged, mio can have limited support for networking for the `wasm32-wasi` target. Signed-off-by: Harald Hoyer <[email protected]>
1 parent 7fcfa6f commit 8b55675

File tree

5 files changed

+116
-3
lines changed

5 files changed

+116
-3
lines changed

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 & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
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};
79

810
use crate::io_source::IoSource;
911
use crate::net::TcpStream;
10-
#[cfg(unix)]
12+
#[cfg(any(unix, target_os = "wasi"))]
1113
use crate::sys::tcp::set_reuseaddr;
1214
use crate::sys::tcp::{bind, listen, new_for_addr};
1315
use crate::{event, sys, Interest, Registry, Token};
@@ -54,7 +56,7 @@ impl TcpListener {
5456
/// 4. Calls `listen` on the socket to prepare it to receive new connections.
5557
pub fn bind(addr: SocketAddr) -> io::Result<TcpListener> {
5658
let socket = new_for_addr(addr)?;
57-
#[cfg(unix)]
59+
#[cfg(any(unix, target_os = "wasi"))]
5860
let listener = unsafe { TcpListener::from_raw_fd(socket) };
5961
#[cfg(windows)]
6062
let listener = unsafe { TcpListener::from_raw_socket(socket as _) };
@@ -215,3 +217,30 @@ impl FromRawSocket for TcpListener {
215217
TcpListener::from_std(FromRawSocket::from_raw_socket(socket))
216218
}
217219
}
220+
221+
#[cfg(target_os = "wasi")]
222+
impl IntoRawFd for TcpListener {
223+
fn into_raw_fd(self) -> RawFd {
224+
self.inner.into_inner().into_raw_fd()
225+
}
226+
}
227+
228+
#[cfg(target_os = "wasi")]
229+
impl AsRawFd for TcpListener {
230+
fn as_raw_fd(&self) -> RawFd {
231+
self.inner.as_raw_fd()
232+
}
233+
}
234+
235+
#[cfg(target_os = "wasi")]
236+
impl FromRawFd for TcpListener {
237+
/// Converts a `RawFd` to a `TcpListener`.
238+
///
239+
/// # Notes
240+
///
241+
/// The caller is responsible for ensuring that the socket is in
242+
/// non-blocking mode.
243+
unsafe fn from_raw_fd(fd: RawFd) -> TcpListener {
244+
TcpListener::from_std(FromRawFd::from_raw_fd(fd))
245+
}
246+
}

src/net/tcp/stream.rs

Lines changed: 30 additions & 1 deletion
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

@@ -75,7 +77,7 @@ impl TcpStream {
7577
/// [read interest]: Interest::READABLE
7678
pub fn connect(addr: SocketAddr) -> io::Result<TcpStream> {
7779
let socket = new_for_addr(addr)?;
78-
#[cfg(unix)]
80+
#[cfg(any(unix, target_os = "wasi"))]
7981
let stream = unsafe { TcpStream::from_raw_fd(socket) };
8082
#[cfg(windows)]
8183
let stream = unsafe { TcpStream::from_raw_socket(socket as _) };
@@ -332,3 +334,30 @@ impl FromRawSocket for TcpStream {
332334
TcpStream::from_std(FromRawSocket::from_raw_socket(socket))
333335
}
334336
}
337+
338+
#[cfg(target_os = "wasi")]
339+
impl IntoRawFd for TcpStream {
340+
fn into_raw_fd(self) -> RawFd {
341+
self.inner.into_inner().into_raw_fd()
342+
}
343+
}
344+
345+
#[cfg(target_os = "wasi")]
346+
impl AsRawFd for TcpStream {
347+
fn as_raw_fd(&self) -> RawFd {
348+
self.inner.as_raw_fd()
349+
}
350+
}
351+
352+
#[cfg(target_os = "wasi")]
353+
impl FromRawFd for TcpStream {
354+
/// Converts a `RawFd` to a `TcpStream`.
355+
///
356+
/// # Notes
357+
///
358+
/// The caller is responsible for ensuring that the socket is in
359+
/// non-blocking mode.
360+
unsafe fn from_raw_fd(fd: RawFd) -> TcpStream {
361+
TcpStream::from_std(FromRawFd::from_raw_fd(fd))
362+
}
363+
}

src/sys/wasi/mod.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,12 @@ use std::time::Duration;
2222

2323
use crate::{Interest, Token};
2424

25+
cfg_net! {
26+
mod net;
27+
28+
pub(crate) use net::tcp;
29+
}
30+
2531
/// Unique id for use as `SelectorId`.
2632
#[cfg(debug_assertions)]
2733
static NEXT_ID: AtomicUsize = AtomicUsize::new(1);

src/sys/wasi/net.rs

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#![allow(dead_code)]
2+
3+
use std::io;
4+
5+
/// A lot of function are not support on Wasi, this function returns a
6+
/// consistent error when calling those functions.
7+
#[inline]
8+
fn unsupported() -> io::Error {
9+
io::Error::new(io::ErrorKind::Other, "not supported on wasi")
10+
}
11+
12+
pub(crate) mod tcp {
13+
use std::io;
14+
use std::net;
15+
16+
use super::unsupported;
17+
18+
pub type TcpSocket = wasi::Fd;
19+
20+
pub(crate) fn new_for_addr(_address: net::SocketAddr) -> io::Result<i32> {
21+
Err(unsupported())
22+
}
23+
24+
pub(crate) fn bind(_: &net::TcpListener, _: net::SocketAddr) -> io::Result<()> {
25+
Err(unsupported())
26+
}
27+
28+
pub(crate) fn connect(_: &net::TcpStream, _: net::SocketAddr) -> io::Result<net::TcpStream> {
29+
Err(unsupported())
30+
}
31+
32+
pub(crate) fn listen(_: &net::TcpListener, _: u32) -> io::Result<()> {
33+
Err(unsupported())
34+
}
35+
36+
pub(crate) fn set_reuseaddr(_: &net::TcpListener, _: bool) -> io::Result<()> {
37+
Err(unsupported())
38+
}
39+
40+
pub(crate) fn accept(
41+
listener: &net::TcpListener,
42+
) -> io::Result<(net::TcpStream, net::SocketAddr)> {
43+
let (stream, addr) = listener.accept()?;
44+
stream.set_nonblocking(true)?;
45+
Ok((stream, addr))
46+
}
47+
}

0 commit comments

Comments
 (0)