-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Added Ability to create Wasi Sockets - Managed conversion between IpAddr and IpAddressFamily - Managed conversion between ErrorCodes and ErrorKind
- Loading branch information
1 parent
b452c7e
commit cba06b9
Showing
16 changed files
with
4,621 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
pub mod net; | ||
pub mod timer; | ||
pub use timer::Timer; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
use crate::bindings::wasi::sockets::{ | ||
network::IpAddress, | ||
tcp::{IpAddressFamily, TcpSocket}, | ||
tcp_create_socket::{create_tcp_socket, ErrorCode}, | ||
}; | ||
use std::io::ErrorKind; | ||
use std::net::IpAddr; | ||
struct TcpStream { | ||
_socket: TcpSocket, | ||
} | ||
type IOResult<T> = std::io::Result<T>; | ||
type IOError = std::io::Error; | ||
|
||
impl TcpStream { | ||
pub fn create<T: Into<IpAddressFamily>>(ip_address: T) -> IOResult<Self> { | ||
Ok(Self { | ||
_socket: create_tcp_socket(ip_address.into())?, | ||
}) | ||
} | ||
} | ||
|
||
impl From<IpAddr> for IpAddress { | ||
fn from(address: IpAddr) -> Self { | ||
match address { | ||
IpAddr::V4(v4) => { | ||
let ocets = v4.octets(); | ||
IpAddress::Ipv4((ocets[0], ocets[1], ocets[2], ocets[3])) | ||
} | ||
IpAddr::V6(v6) => { | ||
let segments = v6.segments(); | ||
IpAddress::Ipv6(( | ||
segments[0], | ||
segments[1], | ||
segments[2], | ||
segments[3], | ||
segments[4], | ||
segments[5], | ||
segments[6], | ||
segments[7], | ||
)) | ||
} | ||
} | ||
} | ||
} | ||
|
||
impl From<IpAddr> for IpAddressFamily { | ||
fn from(address: IpAddr) -> Self { | ||
if address.is_ipv4() { | ||
IpAddressFamily::Ipv4 | ||
} else { | ||
IpAddressFamily::Ipv6 | ||
} | ||
} | ||
} | ||
|
||
impl From<ErrorCode> for IOError { | ||
fn from(address: ErrorCode) -> Self { | ||
let kind = (&address).into(); | ||
IOError::new(kind, address) | ||
} | ||
} | ||
|
||
impl From<&ErrorCode> for ErrorKind { | ||
fn from(address: &ErrorCode) -> Self { | ||
match address { | ||
ErrorCode::Unknown => ErrorKind::Other, | ||
ErrorCode::AccessDenied => ErrorKind::PermissionDenied, | ||
ErrorCode::NotSupported => ErrorKind::Unsupported, | ||
ErrorCode::InvalidArgument => ErrorKind::InvalidInput, | ||
ErrorCode::OutOfMemory => ErrorKind::OutOfMemory, | ||
ErrorCode::Timeout => ErrorKind::TimedOut, | ||
ErrorCode::ConcurrencyConflict => ErrorKind::Other, | ||
ErrorCode::NotInProgress => ErrorKind::Other, | ||
ErrorCode::WouldBlock => ErrorKind::WouldBlock, | ||
ErrorCode::InvalidState => ErrorKind::Other, | ||
ErrorCode::NewSocketLimit => ErrorKind::Other, | ||
ErrorCode::AddressNotBindable => ErrorKind::Other, | ||
ErrorCode::AddressInUse => ErrorKind::AddrInUse, | ||
ErrorCode::RemoteUnreachable => ErrorKind::NotFound, | ||
ErrorCode::ConnectionRefused => ErrorKind::ConnectionRefused, | ||
ErrorCode::ConnectionReset => ErrorKind::ConnectionReset, | ||
ErrorCode::ConnectionAborted => ErrorKind::ConnectionAborted, | ||
ErrorCode::DatagramTooLarge => ErrorKind::Other, | ||
ErrorCode::NameUnresolvable => ErrorKind::Other, | ||
ErrorCode::TemporaryResolverFailure => ErrorKind::Other, | ||
ErrorCode::PermanentResolverFailure => ErrorKind::Other, | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
|
||
/// This interface provides a value-export of the default network handle.. | ||
interface instance-network { | ||
use network.{network}; | ||
|
||
/// Get a handle to the default network. | ||
instance-network: func() -> network; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
|
||
interface ip-name-lookup { | ||
use wasi:io/poll@0.2.0.{pollable}; | ||
use network.{network, error-code, ip-address}; | ||
|
||
|
||
/// Resolve an internet host name to a list of IP addresses. | ||
/// | ||
/// Unicode domain names are automatically converted to ASCII using IDNA encoding. | ||
/// If the input is an IP address string, the address is parsed and returned | ||
/// as-is without making any external requests. | ||
/// | ||
/// See the wasi-socket proposal README.md for a comparison with getaddrinfo. | ||
/// | ||
/// This function never blocks. It either immediately fails or immediately | ||
/// returns successfully with a `resolve-address-stream` that can be used | ||
/// to (asynchronously) fetch the results. | ||
/// | ||
/// # Typical errors | ||
/// - `invalid-argument`: `name` is a syntactically invalid domain name or IP address. | ||
/// | ||
/// # References: | ||
/// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/getaddrinfo.html> | ||
/// - <https://man7.org/linux/man-pages/man3/getaddrinfo.3.html> | ||
/// - <https://learn.microsoft.com/en-us/windows/win32/api/ws2tcpip/nf-ws2tcpip-getaddrinfo> | ||
/// - <https://man.freebsd.org/cgi/man.cgi?query=getaddrinfo&sektion=3> | ||
resolve-addresses: func(network: borrow<network>, name: string) -> result<resolve-address-stream, error-code>; | ||
|
||
resource resolve-address-stream { | ||
/// Returns the next address from the resolver. | ||
/// | ||
/// This function should be called multiple times. On each call, it will | ||
/// return the next address in connection order preference. If all | ||
/// addresses have been exhausted, this function returns `none`. | ||
/// | ||
/// This function never returns IPv4-mapped IPv6 addresses. | ||
/// | ||
/// # Typical errors | ||
/// - `name-unresolvable`: Name does not exist or has no suitable associated IP addresses. (EAI_NONAME, EAI_NODATA, EAI_ADDRFAMILY) | ||
/// - `temporary-resolver-failure`: A temporary failure in name resolution occurred. (EAI_AGAIN) | ||
/// - `permanent-resolver-failure`: A permanent failure in name resolution occurred. (EAI_FAIL) | ||
/// - `would-block`: A result is not available yet. (EWOULDBLOCK, EAGAIN) | ||
resolve-next-address: func() -> result<option<ip-address>, error-code>; | ||
|
||
/// Create a `pollable` which will resolve once the stream is ready for I/O. | ||
/// | ||
/// Note: this function is here for WASI Preview2 only. | ||
/// It's planned to be removed when `future` is natively supported in Preview3. | ||
subscribe: func() -> pollable; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,145 @@ | ||
|
||
interface network { | ||
/// An opaque resource that represents access to (a subset of) the network. | ||
/// This enables context-based security for networking. | ||
/// There is no need for this to map 1:1 to a physical network interface. | ||
resource network; | ||
|
||
/// Error codes. | ||
/// | ||
/// In theory, every API can return any error code. | ||
/// In practice, API's typically only return the errors documented per API | ||
/// combined with a couple of errors that are always possible: | ||
/// - `unknown` | ||
/// - `access-denied` | ||
/// - `not-supported` | ||
/// - `out-of-memory` | ||
/// - `concurrency-conflict` | ||
/// | ||
/// See each individual API for what the POSIX equivalents are. They sometimes differ per API. | ||
enum error-code { | ||
/// Unknown error | ||
unknown, | ||
|
||
/// Access denied. | ||
/// | ||
/// POSIX equivalent: EACCES, EPERM | ||
access-denied, | ||
|
||
/// The operation is not supported. | ||
/// | ||
/// POSIX equivalent: EOPNOTSUPP | ||
not-supported, | ||
|
||
/// One of the arguments is invalid. | ||
/// | ||
/// POSIX equivalent: EINVAL | ||
invalid-argument, | ||
|
||
/// Not enough memory to complete the operation. | ||
/// | ||
/// POSIX equivalent: ENOMEM, ENOBUFS, EAI_MEMORY | ||
out-of-memory, | ||
|
||
/// The operation timed out before it could finish completely. | ||
timeout, | ||
|
||
/// This operation is incompatible with another asynchronous operation that is already in progress. | ||
/// | ||
/// POSIX equivalent: EALREADY | ||
concurrency-conflict, | ||
|
||
/// Trying to finish an asynchronous operation that: | ||
/// - has not been started yet, or: | ||
/// - was already finished by a previous `finish-*` call. | ||
/// | ||
/// Note: this is scheduled to be removed when `future`s are natively supported. | ||
not-in-progress, | ||
|
||
/// The operation has been aborted because it could not be completed immediately. | ||
/// | ||
/// Note: this is scheduled to be removed when `future`s are natively supported. | ||
would-block, | ||
|
||
|
||
/// The operation is not valid in the socket's current state. | ||
invalid-state, | ||
|
||
/// A new socket resource could not be created because of a system limit. | ||
new-socket-limit, | ||
|
||
/// A bind operation failed because the provided address is not an address that the `network` can bind to. | ||
address-not-bindable, | ||
|
||
/// A bind operation failed because the provided address is already in use or because there are no ephemeral ports available. | ||
address-in-use, | ||
|
||
/// The remote address is not reachable | ||
remote-unreachable, | ||
|
||
|
||
/// The TCP connection was forcefully rejected | ||
connection-refused, | ||
|
||
/// The TCP connection was reset. | ||
connection-reset, | ||
|
||
/// A TCP connection was aborted. | ||
connection-aborted, | ||
|
||
|
||
/// The size of a datagram sent to a UDP socket exceeded the maximum | ||
/// supported size. | ||
datagram-too-large, | ||
|
||
|
||
/// Name does not exist or has no suitable associated IP addresses. | ||
name-unresolvable, | ||
|
||
/// A temporary failure in name resolution occurred. | ||
temporary-resolver-failure, | ||
|
||
/// A permanent failure in name resolution occurred. | ||
permanent-resolver-failure, | ||
} | ||
|
||
enum ip-address-family { | ||
/// Similar to `AF_INET` in POSIX. | ||
ipv4, | ||
|
||
/// Similar to `AF_INET6` in POSIX. | ||
ipv6, | ||
} | ||
|
||
type ipv4-address = tuple<u8, u8, u8, u8>; | ||
type ipv6-address = tuple<u16, u16, u16, u16, u16, u16, u16, u16>; | ||
|
||
variant ip-address { | ||
ipv4(ipv4-address), | ||
ipv6(ipv6-address), | ||
} | ||
|
||
record ipv4-socket-address { | ||
/// sin_port | ||
port: u16, | ||
/// sin_addr | ||
address: ipv4-address, | ||
} | ||
|
||
record ipv6-socket-address { | ||
/// sin6_port | ||
port: u16, | ||
/// sin6_flowinfo | ||
flow-info: u32, | ||
/// sin6_addr | ||
address: ipv6-address, | ||
/// sin6_scope_id | ||
scope-id: u32, | ||
} | ||
|
||
variant ip-socket-address { | ||
ipv4(ipv4-socket-address), | ||
ipv6(ipv6-socket-address), | ||
} | ||
|
||
} |
Oops, something went wrong.