Skip to content

Commit b465726

Browse files
committed
feat: wasm32-wasi target support
Signed-off-by: Richard Zak <[email protected]>
1 parent b2052a4 commit b465726

File tree

3 files changed

+45
-16
lines changed

3 files changed

+45
-16
lines changed

Cargo.toml

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -28,18 +28,22 @@ http = "0.2"
2828
http-body = "0.4"
2929
httpdate = "1.0"
3030
httparse = "1.6"
31-
h2 = { version = "0.3.9", optional = true }
31+
# h2 = { version = "0.3.9", optional = true }
32+
h2 = { git = "https://github.com/rjzak/h2", branch = "wasi_wip", optional = true }
3233
itoa = "1"
3334
tracing = { version = "0.1", default-features = false, features = ["std"] }
3435
pin-project-lite = "0.2.4"
3536
tower-service = "0.3"
36-
tokio = { version = "1", features = ["sync"] }
37+
# tokio = { version = "1", features = ["sync"] }
38+
tokio = { git = "https://github.com/rjzak/tokio", branch = "wasi_wip", features = ["sync"] }
3739
want = "0.3"
3840

3941
# Optional
4042

4143
libc = { version = "0.2", optional = true }
42-
socket2 = { version = "0.4", optional = true }
44+
45+
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
46+
socket2 = { version = "0.4" }
4347

4448
[dev-dependencies]
4549
futures-util = { version = "0.3", default-features = false, features = ["alloc"] }
@@ -49,7 +53,8 @@ pretty_env_logger = "0.4"
4953
spmc = "0.3"
5054
serde = { version = "1.0", features = ["derive"] }
5155
serde_json = "1.0"
52-
tokio = { version = "1", features = [
56+
# tokio = { version = "1", features = [
57+
tokio = { git = "https://github.com/rjzak/tokio", branch = "wasi_wip", features = [
5358
"fs",
5459
"macros",
5560
"io-std",
@@ -61,7 +66,8 @@ tokio = { version = "1", features = [
6166
"test-util",
6267
] }
6368
tokio-test = "0.4"
64-
tokio-util = { version = "0.7", features = ["codec"] }
69+
# tokio-util = { version = "0.7", features = ["codec"] }
70+
tokio-util = { git = "https://github.com/rjzak/tokio", branch = "wasi_wip", features = ["codec"] }
6571
tower = { version = "0.4", features = ["make", "util"] }
6672
url = "2.2"
6773

@@ -100,7 +106,6 @@ runtime = [
100106
"tokio/time",
101107
]
102108
tcp = [
103-
"socket2",
104109
"tokio/net",
105110
"tokio/rt",
106111
"tokio/time",

src/server/server.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ impl Server<AddrIncoming, ()> {
7272
///
7373
/// This method will panic if binding to the address fails. For a method
7474
/// to bind to an address and return a `Result`, see `Server::try_bind`.
75+
#[cfg(not(target_os = "wasi"))]
7576
pub fn bind(addr: &SocketAddr) -> Builder<AddrIncoming> {
7677
let incoming = AddrIncoming::new(addr).unwrap_or_else(|e| {
7778
panic!("error binding to {}: {}", addr, e);
@@ -80,6 +81,7 @@ impl Server<AddrIncoming, ()> {
8081
}
8182

8283
/// Tries to bind to the provided address, and returns a [`Builder`](Builder).
84+
#[cfg(not(target_os = "wasi"))]
8385
pub fn try_bind(addr: &SocketAddr) -> crate::Result<Builder<AddrIncoming>> {
8486
AddrIncoming::new(addr).map(Server::builder)
8587
}

src/server/tcp.rs

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@ use std::io;
33
use std::net::{SocketAddr, TcpListener as StdTcpListener};
44
use std::time::Duration;
55

6+
#[cfg(target_os = "wasi")]
7+
use std::net::{IpAddr, Ipv4Addr};
8+
69
use tokio::net::TcpListener;
710
use tokio::time::Sleep;
811
use tracing::{debug, error, trace};
@@ -25,6 +28,7 @@ pub struct AddrIncoming {
2528
}
2629

2730
impl AddrIncoming {
31+
#[cfg(not(target_os = "wasi"))]
2832
pub(super) fn new(addr: &SocketAddr) -> crate::Result<Self> {
2933
let std_listener = StdTcpListener::bind(addr).map_err(crate::Error::new_listen)?;
3034

@@ -41,13 +45,21 @@ impl AddrIncoming {
4145
}
4246

4347
/// Creates a new `AddrIncoming` binding to provided socket address.
48+
#[cfg(not(target_os = "wasi"))]
4449
pub fn bind(addr: &SocketAddr) -> crate::Result<Self> {
4550
AddrIncoming::new(addr)
4651
}
4752

4853
/// Creates a new `AddrIncoming` from an existing `tokio::net::TcpListener`.
54+
/// For target `wasm32-wasi`, the assumed local address is "0.0.0.0:0", since
55+
/// WebAssembly-Wasi has no way to know the local address used for listening.
56+
/// This could be removed, but would require refactoring a lot of code in Hyper,
57+
/// and other downstream projects.
4958
pub fn from_listener(listener: TcpListener) -> crate::Result<Self> {
59+
#[cfg(not(target_os = "wasi"))]
5060
let addr = listener.local_addr().map_err(crate::Error::new_listen)?;
61+
#[cfg(target_os = "wasi")]
62+
let addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0);
5163
Ok(AddrIncoming {
5264
listener,
5365
addr,
@@ -108,18 +120,26 @@ impl AddrIncoming {
108120
loop {
109121
match ready!(self.listener.poll_accept(cx)) {
110122
Ok((socket, remote_addr)) => {
111-
if let Some(dur) = self.tcp_keepalive_timeout {
112-
let socket = socket2::SockRef::from(&socket);
113-
let conf = socket2::TcpKeepalive::new().with_time(dur);
114-
if let Err(e) = socket.set_tcp_keepalive(&conf) {
115-
trace!("error trying to set TCP keepalive: {}", e);
123+
#[cfg(not(target_os = "wasi"))]
124+
{
125+
if let Some(dur) = self.tcp_keepalive_timeout {
126+
let socket = socket2::SockRef::from(&socket);
127+
let conf = socket2::TcpKeepalive::new().with_time(dur);
128+
if let Err(e) = socket.set_tcp_keepalive(&conf) {
129+
trace!("error trying to set TCP keepalive: {}", e);
130+
}
116131
}
132+
if let Err(e) = socket.set_nodelay(self.tcp_nodelay) {
133+
trace!("error trying to set TCP nodelay: {}", e);
134+
}
135+
let local_addr = socket.local_addr()?;
136+
return Poll::Ready(Ok(AddrStream::new(socket, remote_addr, local_addr)));
117137
}
118-
if let Err(e) = socket.set_nodelay(self.tcp_nodelay) {
119-
trace!("error trying to set TCP nodelay: {}", e);
138+
#[cfg(target_os = "wasi")]
139+
{
140+
let local_addr = SocketAddr::new(IpAddr::V4(Ipv4Addr::UNSPECIFIED), 0);
141+
return Poll::Ready(Ok(AddrStream::new(socket, remote_addr, local_addr)));
120142
}
121-
let local_addr = socket.local_addr()?;
122-
return Poll::Ready(Ok(AddrStream::new(socket, remote_addr, local_addr)));
123143
}
124144
Err(e) => {
125145
// Connection errors can be ignored directly, continue by
@@ -199,6 +219,8 @@ mod addr_stream {
199219
use std::net::SocketAddr;
200220
#[cfg(unix)]
201221
use std::os::unix::io::{AsRawFd, RawFd};
222+
#[cfg(target_os = "wasi")]
223+
use std::os::wasi::io::{AsRawFd, RawFd};
202224
use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
203225
use tokio::net::TcpStream;
204226

@@ -309,7 +331,7 @@ mod addr_stream {
309331
}
310332
}
311333

312-
#[cfg(unix)]
334+
#[cfg(any(unix, target_os = "wasi"))]
313335
impl AsRawFd for AddrStream {
314336
fn as_raw_fd(&self) -> RawFd {
315337
self.inner.as_raw_fd()

0 commit comments

Comments
 (0)