Skip to content

Commit

Permalink
Add networking for target_os = "wasi"
Browse files Browse the repository at this point in the history
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 <harald@profian.com>
  • Loading branch information
haraldh committed Feb 15, 2022
1 parent 3473d06 commit 3bb6000
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 3 deletions.
2 changes: 2 additions & 0 deletions src/net/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,9 @@
mod tcp;
pub use self::tcp::{TcpListener, TcpStream};

#[cfg(not(target_os = "wasi"))]
mod udp;
#[cfg(not(target_os = "wasi"))]
pub use self::udp::UdpSocket;

#[cfg(unix)]
Expand Down
33 changes: 31 additions & 2 deletions src/net/tcp/listener.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
use std::net::{self, SocketAddr};
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
#[cfg(target_os = "wasi")]
use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
use std::{fmt, io};

use crate::io_source::IoSource;
use crate::net::TcpStream;
#[cfg(unix)]
#[cfg(any(unix, target_os = "wasi"))]
use crate::sys::tcp::set_reuseaddr;
use crate::sys::tcp::{bind, listen, new_for_addr};
use crate::{event, sys, Interest, Registry, Token};
Expand Down Expand Up @@ -54,7 +56,7 @@ impl TcpListener {
/// 4. Calls `listen` on the socket to prepare it to receive new connections.
pub fn bind(addr: SocketAddr) -> io::Result<TcpListener> {
let socket = new_for_addr(addr)?;
#[cfg(unix)]
#[cfg(any(unix, target_os = "wasi"))]
let listener = unsafe { TcpListener::from_raw_fd(socket) };
#[cfg(windows)]
let listener = unsafe { TcpListener::from_raw_socket(socket as _) };
Expand Down Expand Up @@ -215,3 +217,30 @@ impl FromRawSocket for TcpListener {
TcpListener::from_std(FromRawSocket::from_raw_socket(socket))
}
}

#[cfg(target_os = "wasi")]
impl IntoRawFd for TcpListener {
fn into_raw_fd(self) -> RawFd {
self.inner.into_inner().into_raw_fd()
}
}

#[cfg(target_os = "wasi")]
impl AsRawFd for TcpListener {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}

#[cfg(target_os = "wasi")]
impl FromRawFd for TcpListener {
/// Converts a `RawFd` to a `TcpListener`.
///
/// # Notes
///
/// The caller is responsible for ensuring that the socket is in
/// non-blocking mode.
unsafe fn from_raw_fd(fd: RawFd) -> TcpListener {
TcpListener::from_std(FromRawFd::from_raw_fd(fd))
}
}
31 changes: 30 additions & 1 deletion src/net/tcp/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ use std::io::{self, IoSlice, IoSliceMut, Read, Write};
use std::net::{self, Shutdown, SocketAddr};
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
#[cfg(target_os = "wasi")]
use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
#[cfg(windows)]
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};

Expand Down Expand Up @@ -75,7 +77,7 @@ impl TcpStream {
/// [read interest]: Interest::READABLE
pub fn connect(addr: SocketAddr) -> io::Result<TcpStream> {
let socket = new_for_addr(addr)?;
#[cfg(unix)]
#[cfg(any(unix, target_os = "wasi"))]
let stream = unsafe { TcpStream::from_raw_fd(socket) };
#[cfg(windows)]
let stream = unsafe { TcpStream::from_raw_socket(socket as _) };
Expand Down Expand Up @@ -332,3 +334,30 @@ impl FromRawSocket for TcpStream {
TcpStream::from_std(FromRawSocket::from_raw_socket(socket))
}
}

#[cfg(target_os = "wasi")]
impl IntoRawFd for TcpStream {
fn into_raw_fd(self) -> RawFd {
self.inner.into_inner().into_raw_fd()
}
}

#[cfg(target_os = "wasi")]
impl AsRawFd for TcpStream {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}

#[cfg(target_os = "wasi")]
impl FromRawFd for TcpStream {
/// Converts a `RawFd` to a `TcpStream`.
///
/// # Notes
///
/// The caller is responsible for ensuring that the socket is in
/// non-blocking mode.
unsafe fn from_raw_fd(fd: RawFd) -> TcpStream {
TcpStream::from_std(FromRawFd::from_raw_fd(fd))
}
}
6 changes: 6 additions & 0 deletions src/sys/wasi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ use std::time::Duration;

use crate::{Interest, Token};

cfg_net! {
mod net;

pub(crate) use net::tcp;
}

/// Unique id for use as `SelectorId`.
#[cfg(debug_assertions)]
static NEXT_ID: AtomicUsize = AtomicUsize::new(1);
Expand Down
45 changes: 45 additions & 0 deletions src/sys/wasi/net.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
#![allow(dead_code)]

use std::io;

/// A lot of function are not support on Wasi, this function returns a
/// consistent error when calling those functions.
fn unsupported() -> io::Error {
io::Error::new(io::ErrorKind::Other, "not supported on wasi")
}

pub(crate) mod tcp {
use std::io;
use std::net;

use super::unsupported;

pub type TcpSocket = wasi::Fd;

pub(crate) fn new_for_addr(_address: net::SocketAddr) -> io::Result<i32> {
Err(unsupported())
}

pub(crate) fn bind(_: &net::TcpListener, _: net::SocketAddr) -> io::Result<()> {
Ok(())
}

pub(crate) fn connect(_: &net::TcpStream, _: net::SocketAddr) -> io::Result<net::TcpStream> {
Err(unsupported())
}

pub(crate) fn listen(_: &net::TcpListener, _: u32) -> io::Result<()> {
Ok(())
}

pub(crate) fn set_reuseaddr(_: &net::TcpListener, _: bool) -> io::Result<()> {
Ok(())
}
pub(crate) fn accept(
listener: &net::TcpListener,
) -> io::Result<(net::TcpStream, net::SocketAddr)> {
let res = listener.accept();
res
}
}

0 comments on commit 3bb6000

Please sign in to comment.