Skip to content

Commit b25f493

Browse files
committed
Implement net for WASIp3
1 parent 2065eb8 commit b25f493

13 files changed

Lines changed: 414 additions & 145 deletions

‎examples/tcp_echo_server.rs‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
#![cfg_attr(not(all(target_os = "wasi", target_env = "p2")), no_main)]
2-
#![cfg(all(target_os = "wasi", target_env = "p2"))]
1+
#![cfg_attr(not(target_os = "wasi"), no_main)]
2+
#![cfg(target_os = "wasi")]
33

44
use wstd::io;
55
use wstd::iter::AsyncIterator;
66
use wstd::net::TcpListener;
77

88
#[wstd::main]
99
async fn main() -> io::Result<()> {
10-
let mut listener = TcpListener::bind("127.0.0.1:8080").await?;
10+
let mut listener = TcpListener::bind("127.0.0.1:0").await?;
1111
println!("Listening on {}", listener.local_addr()?);
12-
println!("type `nc localhost 8080` to create a TCP client");
12+
println!("type `nc localhost <PORT>` to create a TCP client");
1313

1414
let mut incoming = listener.incoming();
1515
while let Some(stream) = incoming.next().await {

‎examples/tcp_stream_client.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#![cfg_attr(not(all(target_os = "wasi", target_env = "p2")), no_main)]
2-
#![cfg(all(target_os = "wasi", target_env = "p2"))]
1+
#![cfg_attr(not(target_os = "wasi"), no_main)]
2+
#![cfg(target_os = "wasi")]
33

44
use wstd::io::{self, AsyncRead, AsyncWrite};
55
use wstd::net::TcpStream;

‎examples/udp_echo_server.rs‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
#![cfg_attr(not(all(target_os = "wasi", target_env = "p2")), no_main)]
2-
#![cfg(all(target_os = "wasi", target_env = "p2"))]
1+
#![cfg_attr(not(target_os = "wasi"), no_main)]
2+
#![cfg(target_os = "wasi")]
33

44
use wstd::io;
55
use wstd::net::UdpSocket;
66

77
#[wstd::main]
88
async fn main() -> io::Result<()> {
9-
let socket = UdpSocket::bind("127.0.0.1:8080").await?;
9+
let socket = UdpSocket::bind("127.0.0.1:0").await?;
1010
println!("Listening on {}", socket.local_addr()?);
11-
println!("type `nc -u localhost 8080` to create a UDP client");
11+
println!("type `nc -u localhost <PORT>` to create a UDP client");
1212

1313
let mut buf = vec![0; 65535];
1414
loop {

‎examples/udp_stream_client.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
#![cfg_attr(not(all(target_os = "wasi", target_env = "p2")), no_main)]
2-
#![cfg(all(target_os = "wasi", target_env = "p2"))]
1+
#![cfg_attr(not(target_os = "wasi"), no_main)]
2+
#![cfg(target_os = "wasi")]
33

44
use wstd::io;
55
use wstd::net::{UdpSocket, UdpStream};

‎src/lib.rs‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,6 @@ pub mod future;
6262
pub mod http;
6363
pub mod io;
6464
pub mod iter;
65-
#[cfg(all(target_os = "wasi", target_env = "p2"))]
6665
pub mod net;
6766
pub mod rand;
6867
pub mod runtime;

‎src/net/mod.rs‎

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,16 @@
11
//! Async network abstractions.
22
33
use std::io::{self, ErrorKind};
4-
use wasip2::sockets::network::{ErrorCode, IpSocketAddress, Ipv4SocketAddress};
4+
#[cfg(target_env = "p2")]
5+
use wasip2::sockets::{
6+
network::{ErrorCode, IpSocketAddress, Ipv4SocketAddress, Ipv6SocketAddress},
7+
tcp_create_socket::create_tcp_socket,
8+
udp_create_socket::create_udp_socket,
9+
};
10+
#[cfg(target_env = "p3")]
11+
use wasip3::sockets::types::{
12+
ErrorCode, IpAddressFamily, IpSocketAddress, Ipv4SocketAddress, Ipv6SocketAddress, TcpSocket,
13+
};
514

615
mod tcp_listener;
716
mod tcp_stream;
@@ -13,26 +22,39 @@ pub use udp::*;
1322

1423
fn to_io_err(err: ErrorCode) -> io::Error {
1524
match err {
16-
ErrorCode::Unknown => ErrorKind::Other.into(),
1725
ErrorCode::AccessDenied => ErrorKind::PermissionDenied.into(),
1826
ErrorCode::NotSupported => ErrorKind::Unsupported.into(),
1927
ErrorCode::InvalidArgument => ErrorKind::InvalidInput.into(),
2028
ErrorCode::OutOfMemory => ErrorKind::OutOfMemory.into(),
2129
ErrorCode::Timeout => ErrorKind::TimedOut.into(),
22-
ErrorCode::WouldBlock => ErrorKind::WouldBlock.into(),
2330
ErrorCode::InvalidState => ErrorKind::InvalidData.into(),
2431
ErrorCode::AddressInUse => ErrorKind::AddrInUse.into(),
2532
ErrorCode::ConnectionRefused => ErrorKind::ConnectionRefused.into(),
2633
ErrorCode::ConnectionReset => ErrorKind::ConnectionReset.into(),
2734
ErrorCode::ConnectionAborted => ErrorKind::ConnectionAborted.into(),
28-
ErrorCode::ConcurrencyConflict => ErrorKind::AlreadyExists.into(),
2935
ErrorCode::DatagramTooLarge => ErrorKind::InvalidInput.into(),
36+
37+
#[cfg(target_env = "p2")]
38+
ErrorCode::Unknown => ErrorKind::Other.into(),
39+
#[cfg(target_env = "p2")]
40+
ErrorCode::WouldBlock => ErrorKind::WouldBlock.into(),
41+
#[cfg(target_env = "p2")]
42+
ErrorCode::ConcurrencyConflict => ErrorKind::AlreadyExists.into(),
43+
#[cfg(target_env = "p2")]
3044
_ => ErrorKind::Other.into(),
45+
46+
#[cfg(target_env = "p3")]
47+
ErrorCode::AddressNotBindable => ErrorKind::AddrNotAvailable.into(),
48+
#[cfg(target_env = "p3")]
49+
ErrorCode::RemoteUnreachable => ErrorKind::HostUnreachable.into(),
50+
#[cfg(target_env = "p3")]
51+
ErrorCode::ConnectionBroken => ErrorKind::BrokenPipe.into(),
52+
#[cfg(target_env = "p3")]
53+
ErrorCode::Other(s) => io::Error::other(s.unwrap_or_default()),
3154
}
3255
}
3356

3457
fn sockaddr_from_wasi(addr: IpSocketAddress) -> std::net::SocketAddr {
35-
use wasip2::sockets::network::Ipv6SocketAddress;
3658
match addr {
3759
IpSocketAddress::Ipv4(Ipv4SocketAddress { address, port }) => {
3860
std::net::SocketAddr::V4(std::net::SocketAddrV4::new(
@@ -58,7 +80,6 @@ fn sockaddr_from_wasi(addr: IpSocketAddress) -> std::net::SocketAddr {
5880
}
5981

6082
fn sockaddr_to_wasi(addr: std::net::SocketAddr) -> IpSocketAddress {
61-
use wasip2::sockets::network::Ipv6SocketAddress;
6283
match addr {
6384
std::net::SocketAddr::V4(addr) => {
6485
let ip = addr.ip().octets();
@@ -78,3 +99,17 @@ fn sockaddr_to_wasi(addr: std::net::SocketAddr) -> IpSocketAddress {
7899
}
79100
}
80101
}
102+
103+
#[cfg(target_env = "p3")]
104+
fn create_tcp_socket(
105+
family: IpAddressFamily,
106+
) -> Result<TcpSocket, wasip3::sockets::types::ErrorCode> {
107+
TcpSocket::create(family)
108+
}
109+
110+
#[cfg(target_env = "p3")]
111+
fn create_udp_socket(
112+
family: IpAddressFamily,
113+
) -> Result<wasip3::sockets::types::UdpSocket, wasip3::sockets::types::ErrorCode> {
114+
wasip3::sockets::types::UdpSocket::create(family)
115+
}

‎src/net/tcp_listener.rs‎

Lines changed: 51 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,27 @@
1+
#[cfg(target_env = "p2")]
12
use wasip2::sockets::tcp::{IpAddressFamily, TcpSocket};
3+
#[cfg(target_env = "p3")]
4+
use wasip3::{
5+
sockets::types::{IpAddressFamily, TcpSocket},
6+
wit_bindgen::StreamReader,
7+
};
28

39
use crate::io;
410
use crate::iter::AsyncIterator;
511
use std::net::SocketAddr;
612

7-
use super::{TcpStream, sockaddr_from_wasi, sockaddr_to_wasi, to_io_err};
13+
use super::{TcpStream, create_tcp_socket, sockaddr_from_wasi, sockaddr_to_wasi, to_io_err};
14+
#[cfg(target_env = "p2")]
815
use crate::runtime::AsyncPollable;
916

1017
/// A TCP socket server, listening for connections.
1118
#[derive(Debug)]
1219
pub struct TcpListener {
1320
// Field order matters: must drop this child before parent below
21+
#[cfg(target_env = "p2")]
1422
pollable: AsyncPollable,
23+
#[cfg(target_env = "p3")]
24+
connections: StreamReader<TcpSocket>,
1525
socket: TcpSocket,
1626
}
1727

@@ -27,31 +37,42 @@ impl TcpListener {
2737
SocketAddr::V4(_) => IpAddressFamily::Ipv4,
2838
SocketAddr::V6(_) => IpAddressFamily::Ipv6,
2939
};
30-
let socket =
31-
wasip2::sockets::tcp_create_socket::create_tcp_socket(family).map_err(to_io_err)?;
32-
let network = wasip2::sockets::instance_network::instance_network();
33-
40+
let socket = create_tcp_socket(family).map_err(to_io_err)?;
3441
let local_address = sockaddr_to_wasi(addr);
3542

36-
socket
37-
.start_bind(&network, local_address)
38-
.map_err(to_io_err)?;
39-
let pollable = AsyncPollable::new(socket.subscribe());
40-
pollable.wait_for().await;
41-
socket.finish_bind().map_err(to_io_err)?;
43+
#[cfg(target_env = "p2")]
44+
{
45+
let network = wasip2::sockets::instance_network::instance_network();
46+
socket
47+
.start_bind(&network, local_address)
48+
.map_err(to_io_err)?;
49+
let pollable = AsyncPollable::new(socket.subscribe());
50+
pollable.wait_for().await;
51+
socket.finish_bind().map_err(to_io_err)?;
4252

43-
socket.start_listen().map_err(to_io_err)?;
44-
pollable.wait_for().await;
45-
socket.finish_listen().map_err(to_io_err)?;
46-
Ok(Self { pollable, socket })
53+
socket.start_listen().map_err(to_io_err)?;
54+
pollable.wait_for().await;
55+
socket.finish_listen().map_err(to_io_err)?;
56+
Ok(Self { pollable, socket })
57+
}
58+
#[cfg(target_env = "p3")]
59+
{
60+
socket.bind(local_address).map_err(to_io_err)?;
61+
let connections = socket.listen().map_err(to_io_err)?;
62+
Ok(Self {
63+
connections,
64+
socket,
65+
})
66+
}
4767
}
4868

4969
/// Returns the local socket address of this listener.
5070
pub fn local_addr(&self) -> io::Result<std::net::SocketAddr> {
51-
self.socket
52-
.local_address()
53-
.map_err(to_io_err)
54-
.map(sockaddr_from_wasi)
71+
#[cfg(target_env = "p2")]
72+
let addr = self.socket.local_address();
73+
#[cfg(target_env = "p3")]
74+
let addr = self.socket.get_local_address();
75+
addr.map_err(to_io_err).map(sockaddr_from_wasi)
5576
}
5677

5778
/// Returns an iterator over the connections being received on this listener.
@@ -69,6 +90,7 @@ pub struct Incoming<'a> {
6990
impl<'a> AsyncIterator for Incoming<'a> {
7091
type Item = io::Result<TcpStream>;
7192

93+
#[cfg(target_env = "p2")]
7294
async fn next(&mut self) -> Option<Self::Item> {
7395
self.listener.pollable.wait_for().await;
7496
let (socket, input, output) = match self.listener.socket.accept().map_err(to_io_err) {
@@ -77,4 +99,14 @@ impl<'a> AsyncIterator for Incoming<'a> {
7799
};
78100
Some(Ok(TcpStream::new(input, output, socket)))
79101
}
102+
103+
#[cfg(target_env = "p3")]
104+
async fn next(&mut self) -> Option<Self::Item> {
105+
self.listener.connections.next().await.map(|socket| {
106+
let (input, _receive_result) = socket.receive();
107+
let (output, receiver) = wasip3::wit_stream::new();
108+
let _send_result = socket.send(receiver);
109+
Ok(TcpStream::new(input, output, socket))
110+
})
111+
}
80112
}

0 commit comments

Comments
 (0)