Skip to content

Commit 43e23e7

Browse files
committed
UDP: Enable sending and receiving of: local-address, traffic-class & hop-limit per packet.
1 parent 2534b91 commit 43e23e7

File tree

3 files changed

+105
-14
lines changed

3 files changed

+105
-14
lines changed

Posix-compatibility.md

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,13 @@ None of the flags are directly present in WASI Sockets:
7676
- `MSG_EOR`: N/A (not supported on TCP & UDP sockets)
7777
- `MSG_CMSG_CLOEXEC`: N/A (only used on Unix domain sockets)
7878

79+
The following ancillary messages are available as regular fields in the datagram parameter:
80+
- `IP_PKTINFO`/`IPV6_PKTINFO`
81+
- `IP_TOS`/`IPV6_TCLASS`
82+
- `IP_TTL`/`IPV6_HOPLIMIT`
83+
84+
There are included unconditionally. There is no need for their RECV* equivalents (IP_RECVTTL, IP_RECVTOS, IP_RECVPKTINFO, etc...)
85+
7986
### `write`, `writev`, `send`, `sendto`, `sendmsg`, `sendmmsg` (non-standard)
8087

8188
TCP sockets can be written to using [`streams::(blocking-)write`](streams). UDP sockets can be written to using [`udp::send`](udp).
@@ -90,6 +97,10 @@ None of the flags are directly present in WASI Sockets:
9097
- `MSG_OOB` (UDP): N/A
9198
- `MSG_EOR`: N/A (not supported on TCP & UDP sockets)
9299

100+
The following ancillary messages are available as regular fields in the datagram parameter:
101+
- `IP_PKTINFO`/`IPV6_PKTINFO`
102+
- `IP_TOS`/`IPV6_TCLASS`
103+
- `IP_TTL`/`IPV6_HOPLIMIT`
93104

94105
### `sendfile` (non-standard)
95106
- TCP: Part of the WASI Streams proposal as [`output-stream::forward`](streams)
@@ -157,14 +168,14 @@ Columns:
157168
| IPV6_HDRINCL ||||||||||||||||| Out of scope. Raw sockets only. |
158169
| IP_TTL ||||||||||||||||| [`tcp::(set-)unicast-hop-limit`](tcp)<br/>[`udp::(set-)unicast-hop-limit`](udp) |
159170
| IPV6_UNICAST_HOPS ||||||||||||||||| [`tcp::(set-)unicast-hop-limit`](tcp)<br/>[`udp::(set-)unicast-hop-limit`](udp) |
160-
| IP_RECVTTL | |||||||||||||||| |
161-
| IPV6_RECVHOPLIMIT | ||| ||||||||||||| |
171+
| IP_RECVTTL | |||||||||||||||| See [`udp::receive`](udp) |
172+
| IPV6_RECVHOPLIMIT | ||| ||||||||||||| See [`udp::receive`](udp) <br/><br/> IPV6_HOPLIMIT on Windows. |
162173
| IP_TOS ||||||||||||||||| |
163174
| IPV6_TCLASS ||||||||||||||||| |
164-
| IP_RECVTOS | |||||||||||||||| |
165-
| IPV6_RECVTCLASS | |||||||||||||||| |
166-
| IP_RECVPKTINFO | |||||||||||||||| IP_PKTINFO on Linux & Windows, IP_RECVDSTADDR+IP_RECVIF on MacOS & FreeBSD. |
167-
| IPV6_RECVPKTINFO | |||||||||||||||| IPV6_PKTINFO on Windows. |
175+
| IP_RECVTOS | |||||||||||||||| See [`udp::receive`](udp) |
176+
| IPV6_RECVTCLASS | |||||||||||||||| See [`udp::receive`](udp) |
177+
| IP_RECVPKTINFO | |||||||||||||||| See [`udp::receive`](udp) <br/><br/> IP_PKTINFO on Linux & Windows, IP_RECVDSTADDR+IP_RECVIF on MacOS & FreeBSD. |
178+
| IPV6_RECVPKTINFO | |||||||||||||||| See [`udp::receive`](udp) <br/><br/> IPV6_PKTINFO on Windows. |
168179
| IP_DONTFRAG ||||||||||||||||| IP_DONTFRAGMENT on Windows, implementable using IP_MTU_DISCOVER on Linux. |
169180
| IPV6_DONTFRAG ||||||||||||||||| |
170181
| IP_MTU_DISCOVER ||||||||||||||||| |

example-world.md

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -325,8 +325,28 @@ mean &quot;ready&quot;.</p>
325325
<h4><a name="datagram"><code>record datagram</code></a></h4>
326326
<h5>Record Fields</h5>
327327
<ul>
328-
<li><a name="datagram.data"><code>data</code></a>: list&lt;<code>u8</code>&gt;</li>
329-
<li><a name="datagram.remote_address"><a href="#remote_address"><code>remote-address</code></a></a>: <a href="#ip_socket_address"><a href="#ip_socket_address"><code>ip-socket-address</code></a></a></li>
328+
<li>
329+
<p><a name="datagram.data"><code>data</code></a>: list&lt;<code>u8</code>&gt;</p>
330+
</li>
331+
<li>
332+
<p><a name="datagram.remote_address"><a href="#remote_address"><code>remote-address</code></a></a>: <a href="#ip_socket_address"><a href="#ip_socket_address"><code>ip-socket-address</code></a></a></p>
333+
</li>
334+
<li>
335+
<p><a name="datagram.local_address"><a href="#local_address"><code>local-address</code></a></a>: option&lt;<a href="#ip_socket_address"><a href="#ip_socket_address"><code>ip-socket-address</code></a></a>&gt;</p>
336+
<p>The local address.
337+
<p>Equivalent to the IP_PKTINFO &amp; IPV6_PKTINFO ancillary messages.</p>
338+
</li>
339+
<li>
340+
<p><a name="datagram.traffic_class"><code>traffic-class</code></a>: option&lt;<code>u8</code>&gt;</p>
341+
<p>The value of the Traffic Class field of the IP packet. (Also known as "Type of Service (TOS)" in IPv4)
342+
<p>This value is typically composed of the DSCP (6 high bits) + ECN (2 low bits).</p>
343+
<p>Equivalent to the IP_TOS &amp; IPV6_TCLASS ancillary messages.</p>
344+
</li>
345+
<li>
346+
<p><a name="datagram.hop_limit"><code>hop-limit</code></a>: option&lt;<code>u8</code>&gt;</p>
347+
<p>The value of the Hop Limit field of the IP packet. (Also known as "Time To Live (TTL)" in IPv4)
348+
<p>Equivalent to the IP_TTL &amp; IPV6_HOPLIMIT ancillary messages.</p>
349+
</li>
330350
</ul>
331351
<hr />
332352
<h3>Functions</h3>
@@ -432,12 +452,28 @@ If the TCP/UDP port is zero, the socket will be bound to a random free port.</p>
432452
<p>This function attempts to receive up to <code>max-results</code> datagrams on the socket without blocking.
433453
The returned list may contain fewer elements than requested, but never more.
434454
If <code>max-results</code> is 0, this function returns successfully with an empty list.</p>
455+
<p>If a platform does not support receiving a particular field, its value will be set to <code>None</code> in the returned datagram.</p>
435456
<h1>Typical errors</h1>
436457
<ul>
437458
<li><code>not-bound</code>: The socket is not bound to any local address. (EINVAL)</li>
438459
<li><code>remote-unreachable</code>: The remote address is not reachable. (ECONNREFUSED, ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN)</li>
439460
<li><code>would-block</code>: There is no pending data available to be read at the moment. (EWOULDBLOCK, EAGAIN)</li>
440461
</ul>
462+
<h1>Implementors note:</h1>
463+
<p>The closest equivalent to this function is Linux' <code>recvmmsg</code> function while having the following options enabled:</p>
464+
<ul>
465+
<li>IP_RECVPKTINFO or IPV6_RECVPKTINFO</li>
466+
<li>IP_RECVTOS or IPV6_RECVTCLASS</li>
467+
<li>IP_RECVTTL or IPV6_RECVHOPLIMIT</li>
468+
</ul>
469+
<p>Naming differences:</p>
470+
<ul>
471+
<li>IP_RECVPKTINFO exists as-is on NetBSD, Solaris, AIX</li>
472+
<li>IP_RECVPKTINFO is named IP_PKTINFO on Linux &amp; Windows.</li>
473+
<li>IP_RECVPKTINFO partially is IP_RECVDSTADDR on MacOS &amp; FreeBSD.</li>
474+
<li>IPV6_RECVPKTINFO is named IPV6_PKTINFO on Windows.</li>
475+
<li>IPV6_RECVHOPLIMIT is named IPV6_HOPLIMIT on Windows</li>
476+
</ul>
441477
<h1>References</h1>
442478
<ul>
443479
<li><a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html">https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html</a></li>
@@ -475,10 +511,20 @@ call <a href="#remote_address"><code>remote-address</code></a> to get their addr
475511
<li><code>invalid-remote-address</code>: The port in <a href="#remote_address"><code>remote-address</code></a> is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL)</li>
476512
<li><code>already-connected</code>: The socket is in &quot;connected&quot; mode and the <code>datagram.remote-address</code> does not match the address passed to <code>connect</code>. (EISCONN)</li>
477513
<li><code>not-bound</code>: The socket is not bound to any local address. Unlike POSIX, this function does not perform an implicit bind.</li>
514+
<li><code>not-supported</code>: An unsupported field in the datagram was set to Some value.</li>
478515
<li><code>remote-unreachable</code>: The remote address is not reachable. (ECONNREFUSED, ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN)</li>
479516
<li><code>datagram-too-large</code>: The datagram is too large. (EMSGSIZE)</li>
480517
<li><code>would-block</code>: The send buffer is currently full. (EWOULDBLOCK, EAGAIN)</li>
481518
</ul>
519+
<h1>Implementors note</h1>
520+
<p>The closest equivalent to this function is Linux' <code>sendmmsg</code> with zero or more
521+
ancillary messages for each not-None datagram field:</p>
522+
<ul>
523+
<li>Some(local-address): IP_PKTINFO or IPV6_PKTINFO</li>
524+
<li>Some(traffic-class): IP_TOS or IPV6_TCLASS</li>
525+
<li>Some(hop-limit): IP_TTL or IPV6_HOPLIMIT
526+
If an implementation does not support a particular ancillary message type, it should return <code>not-supported</code>.</li>
527+
</ul>
482528
<h1>References</h1>
483529
<ul>
484530
<li><a href="https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html">https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html</a></li>

wit/udp.wit

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,22 @@ interface udp {
1212
data: list<u8>, // Theoretical max size: ~64 KiB. In practice, typically less than 1500 bytes.
1313
remote-address: ip-socket-address,
1414

15-
/// Possible future additions:
16-
/// local-address: ip-socket-address, // IP_PKTINFO / IP_RECVDSTADDR / IPV6_PKTINFO
17-
/// local-interface: u32, // IP_PKTINFO / IP_RECVIF
18-
/// ttl: u8, // IP_RECVTTL
19-
/// dscp: u6, // IP_RECVTOS
20-
/// ecn: u2, // IP_RECVTOS
15+
/// The local address.
16+
///
17+
/// Equivalent to the IP_PKTINFO & IPV6_PKTINFO ancillary messages.
18+
local-address: option<ip-socket-address>,
19+
20+
/// The value of the Traffic Class field of the IP packet. (Also known as "Type of Service (TOS)" in IPv4)
21+
///
22+
/// This value is typically composed of the DSCP (6 high bits) + ECN (2 low bits).
23+
///
24+
/// Equivalent to the IP_TOS & IPV6_TCLASS ancillary messages.
25+
traffic-class: option<u8>,
26+
27+
/// The value of the Hop Limit field of the IP packet. (Also known as "Time To Live (TTL)" in IPv4)
28+
///
29+
/// Equivalent to the IP_TTL & IPV6_HOPLIMIT ancillary messages.
30+
hop-limit: option<u8>,
2131
}
2232

2333

@@ -90,11 +100,26 @@ interface udp {
90100
/// The returned list may contain fewer elements than requested, but never more.
91101
/// If `max-results` is 0, this function returns successfully with an empty list.
92102
///
103+
/// If a platform does not support receiving a particular field, its value will be set to `None` in the returned datagram.
104+
///
93105
/// # Typical errors
94106
/// - `not-bound`: The socket is not bound to any local address. (EINVAL)
95107
/// - `remote-unreachable`: The remote address is not reachable. (ECONNREFUSED, ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN)
96108
/// - `would-block`: There is no pending data available to be read at the moment. (EWOULDBLOCK, EAGAIN)
97109
///
110+
/// # Implementors note:
111+
/// The closest equivalent to this function is Linux' `recvmmsg` function while having the following options enabled:
112+
/// - IP_RECVPKTINFO or IPV6_RECVPKTINFO
113+
/// - IP_RECVTOS or IPV6_RECVTCLASS
114+
/// - IP_RECVTTL or IPV6_RECVHOPLIMIT
115+
///
116+
/// Naming differences:
117+
/// - IP_RECVPKTINFO exists as-is on NetBSD, Solaris, AIX
118+
/// - IP_RECVPKTINFO is named IP_PKTINFO on Linux & Windows.
119+
/// - IP_RECVPKTINFO partially is IP_RECVDSTADDR on MacOS & FreeBSD.
120+
/// - IPV6_RECVPKTINFO is named IPV6_PKTINFO on Windows.
121+
/// - IPV6_RECVHOPLIMIT is named IPV6_HOPLIMIT on Windows
122+
///
98123
/// # References
99124
/// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvfrom.html>
100125
/// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/recvmsg.html>
@@ -126,10 +151,19 @@ interface udp {
126151
/// - `invalid-remote-address`: The port in `remote-address` is set to 0. (EDESTADDRREQ, EADDRNOTAVAIL)
127152
/// - `already-connected`: The socket is in "connected" mode and the `datagram.remote-address` does not match the address passed to `connect`. (EISCONN)
128153
/// - `not-bound`: The socket is not bound to any local address. Unlike POSIX, this function does not perform an implicit bind.
154+
/// - `not-supported`: An unsupported field in the datagram was set to Some value.
129155
/// - `remote-unreachable`: The remote address is not reachable. (ECONNREFUSED, ECONNRESET, ENETRESET on Windows, EHOSTUNREACH, EHOSTDOWN, ENETUNREACH, ENETDOWN)
130156
/// - `datagram-too-large`: The datagram is too large. (EMSGSIZE)
131157
/// - `would-block`: The send buffer is currently full. (EWOULDBLOCK, EAGAIN)
132158
///
159+
/// # Implementors note
160+
/// The closest equivalent to this function is Linux' `sendmmsg` with zero or more
161+
/// ancillary messages for each not-None datagram field:
162+
/// - Some(local-address): IP_PKTINFO or IPV6_PKTINFO
163+
/// - Some(traffic-class): IP_TOS or IPV6_TCLASS
164+
/// - Some(hop-limit): IP_TTL or IPV6_HOPLIMIT
165+
/// If an implementation does not support a particular ancillary message type, it should return `not-supported`.
166+
///
133167
/// # References
134168
/// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendto.html>
135169
/// - <https://pubs.opengroup.org/onlinepubs/9699919799/functions/sendmsg.html>

0 commit comments

Comments
 (0)