Skip to content

Commit

Permalink
Merge pull request #111 from rvolosatovs/feat/0.3.0-draft
Browse files Browse the repository at this point in the history
feat: add `wasi-0.3.0` draft
  • Loading branch information
badeend authored Jan 21, 2025
2 parents a584c2b + 0e6b058 commit c754b33
Show file tree
Hide file tree
Showing 11 changed files with 1,009 additions and 1 deletion.
4 changes: 3 additions & 1 deletion .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ jobs:
- uses: actions/checkout@v4
- name: ensure `./wit/deps` are in sync
run: |
curl -Lo 'wit-deps' https://github.com/bytecodealliance/wit-deps/releases/download/v0.3.3/wit-deps-x86_64-unknown-linux-musl
curl -Lo 'wit-deps' https://github.com/bytecodealliance/wit-deps/releases/download/v0.5.0/wit-deps-x86_64-unknown-linux-musl
chmod +x wit-deps
./wit-deps lock
./wit-deps -m wit-0.3.0-draft/deps.toml -l wit-0.3.0-draft/deps.lock -d wit-0.3.0-draft/deps lock
git add -N wit/deps
git add -N wit-0.3.0-draft/deps
git diff --exit-code
- uses: WebAssembly/wit-abi-up-to-date@v22
with:
Expand Down
54 changes: 54 additions & 0 deletions TcpSocketOperationalSemantics-0.3.0-draft.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Operational semantics of WASI TCP sockets

WASI TCP sockets must behave [as-if](https://en.wikipedia.org/wiki/As-if_rule) they are implemented using the state machine described in this document.

## States
> Note: These refer to the states of the TCP socket, not the [TCP connection](https://datatracker.ietf.org/doc/html/rfc9293#name-state-machine-overview)
In pseudo code:

```wit
interface tcp {
variant state {
unbound,
bound,
listening(accept-stream),
connecting(connect-future),
connected,
closed(option<error-code>),
}
}
```

## Transitions
The following diagram describes the exhaustive set of all possible state transitions:

```mermaid
stateDiagram-v2
state "unbound" as Unbound
state "bound" as Bound
state "connecting" as Connecting
state "connected" as Connected
state "listening" as Listening
state "closed" as Closed
[*] --> Unbound: create-tcp-socket() -> ok
Unbound --> Bound: bind() -> ok
Unbound --> Connecting: connect()
Connecting --> Connected: «task resolves successfully»
Connecting --> Closed: «task resolves with error»
Connected --> Closed: «connection terminated»
Bound --> Connecting: connect()
Bound --> Listening: listen() -> ok
Unbound --> Listening: listen() -> ok
```

- Transitions annotated with `-> ok` only apply when the method returns successfully.
- Calling a method from the wrong state returns `error(invalid-state)` and does not affect the state of the socket.
- This diagram only includes the methods that impact the socket's state. For an overview of all methods and their required states, see [tcp.wit](./wit/tcp.wit)
- Client sockets returned by `listen()` are immediately in the `connected` state.
- A socket resource can be dropped in any state.
5 changes: 5 additions & 0 deletions wit-0.3.0-draft/deps.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[clocks]
url = "https://github.com/WebAssembly/wasi-clocks/archive/main.tar.gz"
subdir = "wit-0.3.0-draft"
sha256 = "26e315db0d371495f8834edfc0e479042f94152ce677d96d54d3623d0e4ffb1e"
sha512 = "e1c76f499435841316f9287b88d8173558e64f277c321ff390556de8707a0b18dd6c1749bbb17bbbba8d523da246ef6eb05c990ceddb762e03efb2ae30cacc76"
1 change: 1 addition & 0 deletions wit-0.3.0-draft/deps.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
clocks = { url = "https://github.com/WebAssembly/wasi-clocks/archive/main.tar.gz", subdir = "wit-0.3.0-draft" }
45 changes: 45 additions & 0 deletions wit-0.3.0-draft/deps/clocks/monotonic-clock.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package wasi:clocks@0.3.0;
/// WASI Monotonic Clock is a clock API intended to let users measure elapsed
/// time.
///
/// It is intended to be portable at least between Unix-family platforms and
/// Windows.
///
/// A monotonic clock is a clock which has an unspecified initial value, and
/// successive reads of the clock will produce non-decreasing values.
@since(version = 0.3.0)
interface monotonic-clock {
/// An instant in time, in nanoseconds. An instant is relative to an
/// unspecified initial value, and can only be compared to instances from
/// the same monotonic-clock.
@since(version = 0.3.0)
type instant = u64;

/// A duration of time, in nanoseconds.
@since(version = 0.3.0)
type duration = u64;

/// Read the current value of the clock.
///
/// The clock is monotonic, therefore calling this function repeatedly will
/// produce a sequence of non-decreasing values.
@since(version = 0.3.0)
now: func() -> instant;

/// Query the resolution of the clock. Returns the duration of time
/// corresponding to a clock tick.
@since(version = 0.3.0)
resolution: func() -> duration;

/// Wait until the specified instant has occurred.
@since(version = 0.3.0)
wait-until: func(
when: instant,
);

/// Wait for the specified duration has elapsed.
@since(version = 0.3.0)
wait-for: func(
how-long: duration,
);
}
55 changes: 55 additions & 0 deletions wit-0.3.0-draft/deps/clocks/timezone.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package wasi:clocks@0.3.0;

@unstable(feature = clocks-timezone)
interface timezone {
@unstable(feature = clocks-timezone)
use wall-clock.{datetime};

/// Return information needed to display the given `datetime`. This includes
/// the UTC offset, the time zone name, and a flag indicating whether
/// daylight saving time is active.
///
/// If the timezone cannot be determined for the given `datetime`, return a
/// `timezone-display` for `UTC` with a `utc-offset` of 0 and no daylight
/// saving time.
@unstable(feature = clocks-timezone)
display: func(when: datetime) -> timezone-display;

/// The same as `display`, but only return the UTC offset.
@unstable(feature = clocks-timezone)
utc-offset: func(when: datetime) -> s32;

/// Information useful for displaying the timezone of a specific `datetime`.
///
/// This information may vary within a single `timezone` to reflect daylight
/// saving time adjustments.
@unstable(feature = clocks-timezone)
record timezone-display {
/// The number of seconds difference between UTC time and the local
/// time of the timezone.
///
/// The returned value will always be less than 86400 which is the
/// number of seconds in a day (24*60*60).
///
/// In implementations that do not expose an actual time zone, this
/// should return 0.
utc-offset: s32,

/// The abbreviated name of the timezone to display to a user. The name
/// `UTC` indicates Coordinated Universal Time. Otherwise, this should
/// reference local standards for the name of the time zone.
///
/// In implementations that do not expose an actual time zone, this
/// should be the string `UTC`.
///
/// In time zones that do not have an applicable name, a formatted
/// representation of the UTC offset may be returned, such as `-04:00`.
name: string,

/// Whether daylight saving time is active.
///
/// In implementations that do not expose an actual time zone, this
/// should return false.
in-daylight-saving-time: bool,
}
}
46 changes: 46 additions & 0 deletions wit-0.3.0-draft/deps/clocks/wall-clock.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package wasi:clocks@0.3.0;
/// WASI Wall Clock is a clock API intended to let users query the current
/// time. The name "wall" makes an analogy to a "clock on the wall", which
/// is not necessarily monotonic as it may be reset.
///
/// It is intended to be portable at least between Unix-family platforms and
/// Windows.
///
/// A wall clock is a clock which measures the date and time according to
/// some external reference.
///
/// External references may be reset, so this clock is not necessarily
/// monotonic, making it unsuitable for measuring elapsed time.
///
/// It is intended for reporting the current date and time for humans.
@since(version = 0.3.0)
interface wall-clock {
/// A time and date in seconds plus nanoseconds.
@since(version = 0.3.0)
record datetime {
seconds: u64,
nanoseconds: u32,
}

/// Read the current value of the clock.
///
/// This clock is not monotonic, therefore calling this function repeatedly
/// will not necessarily produce a sequence of non-decreasing values.
///
/// The returned timestamps represent the number of seconds since
/// 1970-01-01T00:00:00Z, also known as [POSIX's Seconds Since the Epoch],
/// also known as [Unix Time].
///
/// The nanoseconds field of the output is always less than 1000000000.
///
/// [POSIX's Seconds Since the Epoch]: https://pubs.opengroup.org/onlinepubs/9699919799/xrat/V4_xbd_chap04.html#tag_21_04_16
/// [Unix Time]: https://en.wikipedia.org/wiki/Unix_time
@since(version = 0.3.0)
now: func() -> datetime;

/// Query the resolution of the clock.
///
/// The nanoseconds field of the output is always less than 1000000000.
@since(version = 0.3.0)
resolution: func() -> datetime;
}
11 changes: 11 additions & 0 deletions wit-0.3.0-draft/deps/clocks/world.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package wasi:clocks@0.3.0;

@since(version = 0.3.0)
world imports {
@since(version = 0.3.0)
import monotonic-clock;
@since(version = 0.3.0)
import wall-clock;
@unstable(feature = clocks-timezone)
import timezone;
}
62 changes: 62 additions & 0 deletions wit-0.3.0-draft/ip-name-lookup.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
@since(version = 0.3.0)
interface ip-name-lookup {
@since(version = 0.3.0)
use types.{ip-address};

/// Lookup error codes.
@since(version = 0.3.0)
enum error-code {
/// Unknown error
unknown,

/// Access denied.
///
/// POSIX equivalent: EACCES, EPERM
access-denied,

/// `name` is a syntactically invalid domain name or IP address.
///
/// POSIX equivalent: EINVAL
invalid-argument,

/// Name does not exist or has no suitable associated IP addresses.
///
/// POSIX equivalent: EAI_NONAME, EAI_NODATA, EAI_ADDRFAMILY
name-unresolvable,

/// A temporary failure in name resolution occurred.
///
/// POSIX equivalent: EAI_AGAIN
temporary-resolver-failure,

/// A permanent failure in name resolution occurred.
///
/// POSIX equivalent: EAI_FAIL
permanent-resolver-failure,
}

/// 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.
///
/// The results are returned in connection order preference.
///
/// This function never succeeds with 0 results. It either fails or succeeds
/// with at least one address. Additionally, this function never returns
/// IPv4-mapped IPv6 addresses.
///
/// The returned future will resolve to an error code in case of failure.
/// It will resolve to success once the returned stream is exhausted.
///
/// # 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>
@since(version = 0.3.0)
resolve-addresses: func(name: string) -> result<list<ip-address>, error-code>;
}
Loading

0 comments on commit c754b33

Please sign in to comment.