Skip to content

Commit 74f9517

Browse files
committed
async UDP: rustfmt
1 parent 80f654e commit 74f9517

File tree

3 files changed

+182
-153
lines changed

3 files changed

+182
-153
lines changed

embedded-nal-async/src/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@ pub use no_std_net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr, SocketAddrV4, Socke
1515
pub use dns::Dns;
1616
pub use embedded_nal::AddrType;
1717
pub use stack::TcpConnect;
18-
pub use stack::{ConnectedUdp, UnconnectedUdp, UdpStack};
18+
pub use stack::{ConnectedUdp, UdpStack, UnconnectedUdp};

embedded-nal-async/src/stack/mod.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ mod tcp;
22
mod udp;
33

44
pub use tcp::TcpConnect;
5-
pub use udp::{ConnectedUdp, UnconnectedUdp, UdpStack};
5+
pub use udp::{ConnectedUdp, UdpStack, UnconnectedUdp};

embedded-nal-async/src/stack/udp.rs

+180-151
Original file line numberDiff line numberDiff line change
@@ -27,37 +27,41 @@ use no_std_net::SocketAddr;
2727
/// `bind()` call in the creation of such sockets, these are implicitly bound to a suitable local
2828
/// address at connect time.
2929
pub trait ConnectedUdp {
30-
/// Error type returned by send and receive operations.
31-
type Error: embedded_io::Error;
32-
33-
/// Send the provided data to the connected peer
34-
fn send<'a>(&'a mut self, data: &'a [u8]) -> Self::SendFuture<'a>;
35-
/// Return type of the [`.send()`] method
36-
type SendFuture<'a>: Future<Output = Result<(), Self::Error>> where Self: 'a;
37-
38-
/// Receive a datagram into the provided buffer.
39-
///
40-
/// If the received datagram exceeds the buffer's length, it is received regardless, and the
41-
/// remaining bytes are discarded. The full datagram size is still indicated in the result,
42-
/// allowing the recipient to detect that truncation.
43-
///
44-
/// ## Compatibility note
45-
///
46-
/// This deviates from the sync/nb equivalent trait in that it describes the overflow behavior
47-
/// (a possibility not considered there). The name deviates from the original `receive()` to
48-
/// make room for a version that is more zero-copy friendly.
49-
fn receive_into<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReceiveIntoFuture<'a>;
50-
/// Return type of the [`.receive_into()`] method
51-
type ReceiveIntoFuture<'a>: Future<Output = Result<usize, Self::Error>> where Self: 'a;
52-
53-
// WIP to allow zero-copy operation
54-
// The plain receive is simple and can be provided -- implementations that don't populate
55-
// receive calls from scatter-gather can just return a slice of the raw data instead, and rely
56-
// on the socket still being exclusively owned. receive_oned is harder as providing it requires
57-
// alloc.
58-
//
59-
// fn receive(&mut self, buffer: &mut [u8]) -> impl Future<Output = Result<impl AsRef<u8> + '_, Self::Error>>;
60-
// fn receive_owned(&mut self) -> impl Future<Output = Result<impl AsRef<u8> + 'static, Self::Error>>;
30+
/// Error type returned by send and receive operations.
31+
type Error: embedded_io::Error;
32+
33+
/// Send the provided data to the connected peer
34+
fn send<'a>(&'a mut self, data: &'a [u8]) -> Self::SendFuture<'a>;
35+
/// Return type of the [`.send()`] method
36+
type SendFuture<'a>: Future<Output = Result<(), Self::Error>>
37+
where
38+
Self: 'a;
39+
40+
/// Receive a datagram into the provided buffer.
41+
///
42+
/// If the received datagram exceeds the buffer's length, it is received regardless, and the
43+
/// remaining bytes are discarded. The full datagram size is still indicated in the result,
44+
/// allowing the recipient to detect that truncation.
45+
///
46+
/// ## Compatibility note
47+
///
48+
/// This deviates from the sync/nb equivalent trait in that it describes the overflow behavior
49+
/// (a possibility not considered there). The name deviates from the original `receive()` to
50+
/// make room for a version that is more zero-copy friendly.
51+
fn receive_into<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReceiveIntoFuture<'a>;
52+
/// Return type of the [`.receive_into()`] method
53+
type ReceiveIntoFuture<'a>: Future<Output = Result<usize, Self::Error>>
54+
where
55+
Self: 'a;
56+
57+
// WIP to allow zero-copy operation
58+
// The plain receive is simple and can be provided -- implementations that don't populate
59+
// receive calls from scatter-gather can just return a slice of the raw data instead, and rely
60+
// on the socket still being exclusively owned. receive_oned is harder as providing it requires
61+
// alloc.
62+
//
63+
// fn receive(&mut self, buffer: &mut [u8]) -> impl Future<Output = Result<impl AsRef<u8> + '_, Self::Error>>;
64+
// fn receive_owned(&mut self) -> impl Future<Output = Result<impl AsRef<u8> + 'static, Self::Error>>;
6165
}
6266

6367
/// This trait is implemented by UDP sockets.
@@ -70,47 +74,57 @@ pub trait ConnectedUdp {
7074
/// caller MUST pass in the same (or compatible) values, MAY and pass in unspecified values where
7175
/// applicable. The implementer MAY check them for compatibility, and SHOULD do that in debug mode.
7276
pub trait UnconnectedUdp {
73-
/// Error type returned by send and receive operations.
74-
type Error: embedded_io::Error;
75-
76-
/// Send the provided data to a peer
77-
///
78-
/// ## Sending initial messages
79-
///
80-
/// The local address can be left unspecified by leaving any of its component zero -- that
81-
/// gives the "any" address (`[::]` / `0.0.0.0`), the uncspecified port (0) or the unspecified
82-
/// zone identifier (0). Unless the operating system provides facilities exceeding this crate's traits for
83-
/// enumerating local interfaces and addresses, this is the only way to initiate outbound
84-
/// traffic.
85-
///
86-
/// ## Responding to messages
87-
///
88-
/// Users who have previously received data from a peer and want to respond have a choice of
89-
/// sending from the address to which the original datagram was addressed, or from an unbound
90-
/// address. Both are valid choices in some situations, and the right choice depends on the
91-
/// protocol used.
92-
///
93-
/// Note that users of sockets created through [`UdpStack::bind_single()`] should always pass
94-
/// in that single address -- even though they've made their intention clear at construction.
95-
/// They can pass either the one obtained at socket creation time, or the one obtained at
96-
/// receive time; these should be equal. This allows implementations of the trait to use a
97-
/// single kind of socket for both sockets bound to a single and sockets bound to multiple
98-
/// addresses.
99-
fn send<'a>(&'a mut self, local: SocketAddr, remote: SocketAddr, data: &'a [u8]) -> Self::SendFuture<'a>;
100-
/// Return type of the [`.send()`] method
101-
type SendFuture<'a>: Future<Output = Result<(), Self::Error>> where Self: 'a;
102-
103-
/// Receive a datagram into the provided buffer.
104-
///
105-
/// If the received datagram exceeds the buffer's length, it is received regardless, and the
106-
/// remaining bytes are discarded. The full datagram size is still indicated in the result,
107-
/// allowing the recipient to detect that truncation.
108-
///
109-
/// The local and remote address are given, in that order, in the result along with the number
110-
/// of bytes.
111-
fn receive_into<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReceiveIntoFuture<'a>;
112-
/// Return type of the [`.receive_into()`] method
113-
type ReceiveIntoFuture<'a>: Future<Output = Result<(usize, SocketAddr, SocketAddr), Self::Error>> where Self: 'a;
77+
/// Error type returned by send and receive operations.
78+
type Error: embedded_io::Error;
79+
80+
/// Send the provided data to a peer
81+
///
82+
/// ## Sending initial messages
83+
///
84+
/// The local address can be left unspecified by leaving any of its component zero -- that
85+
/// gives the "any" address (`[::]` / `0.0.0.0`), the uncspecified port (0) or the unspecified
86+
/// zone identifier (0). Unless the operating system provides facilities exceeding this crate's traits for
87+
/// enumerating local interfaces and addresses, this is the only way to initiate outbound
88+
/// traffic.
89+
///
90+
/// ## Responding to messages
91+
///
92+
/// Users who have previously received data from a peer and want to respond have a choice of
93+
/// sending from the address to which the original datagram was addressed, or from an unbound
94+
/// address. Both are valid choices in some situations, and the right choice depends on the
95+
/// protocol used.
96+
///
97+
/// Note that users of sockets created through [`UdpStack::bind_single()`] should always pass
98+
/// in that single address -- even though they've made their intention clear at construction.
99+
/// They can pass either the one obtained at socket creation time, or the one obtained at
100+
/// receive time; these should be equal. This allows implementations of the trait to use a
101+
/// single kind of socket for both sockets bound to a single and sockets bound to multiple
102+
/// addresses.
103+
fn send<'a>(
104+
&'a mut self,
105+
local: SocketAddr,
106+
remote: SocketAddr,
107+
data: &'a [u8],
108+
) -> Self::SendFuture<'a>;
109+
/// Return type of the [`.send()`] method
110+
type SendFuture<'a>: Future<Output = Result<(), Self::Error>>
111+
where
112+
Self: 'a;
113+
114+
/// Receive a datagram into the provided buffer.
115+
///
116+
/// If the received datagram exceeds the buffer's length, it is received regardless, and the
117+
/// remaining bytes are discarded. The full datagram size is still indicated in the result,
118+
/// allowing the recipient to detect that truncation.
119+
///
120+
/// The local and remote address are given, in that order, in the result along with the number
121+
/// of bytes.
122+
fn receive_into<'a>(&'a mut self, buffer: &'a mut [u8]) -> Self::ReceiveIntoFuture<'a>;
123+
/// Return type of the [`.receive_into()`] method
124+
type ReceiveIntoFuture<'a>: Future<
125+
Output = Result<(usize, SocketAddr, SocketAddr), Self::Error>,
126+
> where
127+
Self: 'a;
114128
}
115129

116130
/// This trait is implemented by UDP/IP stacks. The trait allows the underlying driver to
@@ -119,83 +133,98 @@ pub trait UnconnectedUdp {
119133
/// Note that stacks with exotic connection creation methods may still not implement this, yet have
120134
/// objects that implement [`ConnectedUdp`] or similar.
121135
pub trait UdpStack {
122-
/// Error type returned on socket creation failure.
123-
type Error: embedded_io::Error;
124-
125-
/// Eventual socket return type of the [`.connect()`] method
126-
type Connected<'m>: ConnectedUdp where Self: 'm;
127-
/// Eventual socket return type of the [`.bind_single()`] method
128-
type Bound<'m>: UnconnectedUdp where Self: 'm;
129-
/// Eventual return type of the [`.bind_multiple()`] method
130-
type Unbound<'m>: UnconnectedUdp where Self: 'm;
131-
132-
/// Create a socket that has a fixed remote address.
133-
///
134-
/// The local address is chosen automatically.
135-
///
136-
/// While asynchronous traits implemented through GAT can not have provided default methods,
137-
/// implementers are encouraged to use the hidden `.connect_default()` method if all they would
138-
/// do is delegating to [`.connect_from`] with a suitable unspecified local address.
139-
fn connect(&self, remote: SocketAddr) -> Self::ConnectFuture<'_>;
140-
/// Future return type of the [`.connect()`] method
141-
type ConnectFuture<'a>: Future<Output = Result<(SocketAddr, Self::Connected<'a>), Self::Error>> where Self: 'a;
142-
143-
/// Create a socket that has a fixed remote address.
144-
///
145-
/// The local address is given explicitly, but may be partially unspecified; it is fixed by the
146-
/// network stack at connection time. The full local address is returned along with the
147-
/// connected socket, primarily for debugging purposes.
148-
fn connect_from(&self, local: SocketAddr, remote: SocketAddr) -> Self::ConnectFromFuture<'_>;
149-
/// Future return type of the [`.connect_from()`] method
150-
type ConnectFromFuture<'a>: Future<Output = Result<(SocketAddr, Self::Connected<'a>), Self::Error>> where Self: 'a;
151-
152-
/// Helper that implements [`connect()`] using [`connect_from()`].
153-
#[doc(hidden)]
154-
fn connect_default(&self, remote: SocketAddr) -> Self::ConnectFromFuture<'_> {
155-
use no_std_net::{SocketAddrV4, SocketAddrV6, SocketAddr::*, Ipv4Addr, Ipv6Addr};
156-
157-
let local = match remote {
158-
V4(_) => V4(SocketAddrV4::new(Ipv4Addr::unspecified(), 0)),
159-
V6(_) => V6(SocketAddrV6::new(Ipv6Addr::unspecified(), 0, 0, 0)),
160-
};
161-
self.connect_from(local, remote)
162-
}
163-
164-
/// Create a socket that has a fixed local address.
165-
///
166-
/// Note that the giving an unspecified address here is *not* the same as a POSIX `bind()` --
167-
/// if the underlying stack supports multiple local addresses, it will pick *one* of the
168-
/// applicable addresses, rather than binding to all of them.
169-
///
170-
/// The full local address is returned along with the bound socket; it may then be passed on to
171-
/// other protocols for advertising purposes.
172-
fn bind_single(&self, local: SocketAddr) -> Self::BindSingleFuture<'_>;
173-
/// Future return type of the [`.bind_single()`] method
174-
type BindSingleFuture<'a>: Future<Output = Result<(SocketAddr, Self::Bound<'a>), Self::Error>> where Self: 'a;
175-
176-
/// Create a socket that has no single fixed local address.
177-
///
178-
/// The IP address part of the local address is typically left unspecified, and the port is
179-
/// given. There are use cases for other constellations, and this interface does not rule out
180-
/// that they can be used, but they are rare (e.g. using the same IP address on different
181-
/// network interfaces, and listening to datagrams arriving at any of them) or not well
182-
/// supported by operating systems (e.g., binding to all ports at the same is not possible on
183-
/// POSIX systems, where giving port 0 to a bind makes the OS pick *some* suitable port).
184-
///
185-
/// Caveats:
186-
///
187-
/// * There is currently no way to pass in a local address that has an unspecified address
188-
/// family (which would effectively create a single socket that servers both IPv4 and IPv6);
189-
/// it is not specified whether stacks that use V6MAPPED IPv4 addresses could simply used
190-
/// that mechanism.
191-
///
192-
/// * It is currently not specified whether this mechanism can be used to join multicast
193-
/// groups.
194-
///
195-
/// * There is currently no hybrid binding that allows emulating what POSIX systems do when
196-
/// binding to `[::]:0`, that is, picking some available port but then still leaving the
197-
/// interface and IP address unspecified.
198-
fn bind_multiple(&self, local: SocketAddr) -> Self::BindMultipleFuture<'_>;
199-
/// Future return type of the [`.bind_multiple()`] method
200-
type BindMultipleFuture<'a>: Future<Output = Result<Self::Unbound<'a>, Self::Error>> where Self: 'a;
136+
/// Error type returned on socket creation failure.
137+
type Error: embedded_io::Error;
138+
139+
/// Eventual socket return type of the [`.connect()`] method
140+
type Connected<'m>: ConnectedUdp
141+
where
142+
Self: 'm;
143+
/// Eventual socket return type of the [`.bind_single()`] method
144+
type Bound<'m>: UnconnectedUdp
145+
where
146+
Self: 'm;
147+
/// Eventual return type of the [`.bind_multiple()`] method
148+
type Unbound<'m>: UnconnectedUdp
149+
where
150+
Self: 'm;
151+
152+
/// Create a socket that has a fixed remote address.
153+
///
154+
/// The local address is chosen automatically.
155+
///
156+
/// While asynchronous traits implemented through GAT can not have provided default methods,
157+
/// implementers are encouraged to use the hidden `.connect_default()` method if all they would
158+
/// do is delegating to [`.connect_from`] with a suitable unspecified local address.
159+
fn connect(&self, remote: SocketAddr) -> Self::ConnectFuture<'_>;
160+
/// Future return type of the [`.connect()`] method
161+
type ConnectFuture<'a>: Future<Output = Result<(SocketAddr, Self::Connected<'a>), Self::Error>>
162+
where
163+
Self: 'a;
164+
165+
/// Create a socket that has a fixed remote address.
166+
///
167+
/// The local address is given explicitly, but may be partially unspecified; it is fixed by the
168+
/// network stack at connection time. The full local address is returned along with the
169+
/// connected socket, primarily for debugging purposes.
170+
fn connect_from(&self, local: SocketAddr, remote: SocketAddr) -> Self::ConnectFromFuture<'_>;
171+
/// Future return type of the [`.connect_from()`] method
172+
type ConnectFromFuture<'a>: Future<
173+
Output = Result<(SocketAddr, Self::Connected<'a>), Self::Error>,
174+
> where
175+
Self: 'a;
176+
177+
/// Helper that implements [`connect()`] using [`connect_from()`].
178+
#[doc(hidden)]
179+
fn connect_default(&self, remote: SocketAddr) -> Self::ConnectFromFuture<'_> {
180+
use no_std_net::{Ipv4Addr, Ipv6Addr, SocketAddr::*, SocketAddrV4, SocketAddrV6};
181+
182+
let local = match remote {
183+
V4(_) => V4(SocketAddrV4::new(Ipv4Addr::unspecified(), 0)),
184+
V6(_) => V6(SocketAddrV6::new(Ipv6Addr::unspecified(), 0, 0, 0)),
185+
};
186+
self.connect_from(local, remote)
187+
}
188+
189+
/// Create a socket that has a fixed local address.
190+
///
191+
/// Note that the giving an unspecified address here is *not* the same as a POSIX `bind()` --
192+
/// if the underlying stack supports multiple local addresses, it will pick *one* of the
193+
/// applicable addresses, rather than binding to all of them.
194+
///
195+
/// The full local address is returned along with the bound socket; it may then be passed on to
196+
/// other protocols for advertising purposes.
197+
fn bind_single(&self, local: SocketAddr) -> Self::BindSingleFuture<'_>;
198+
/// Future return type of the [`.bind_single()`] method
199+
type BindSingleFuture<'a>: Future<Output = Result<(SocketAddr, Self::Bound<'a>), Self::Error>>
200+
where
201+
Self: 'a;
202+
203+
/// Create a socket that has no single fixed local address.
204+
///
205+
/// The IP address part of the local address is typically left unspecified, and the port is
206+
/// given. There are use cases for other constellations, and this interface does not rule out
207+
/// that they can be used, but they are rare (e.g. using the same IP address on different
208+
/// network interfaces, and listening to datagrams arriving at any of them) or not well
209+
/// supported by operating systems (e.g., binding to all ports at the same is not possible on
210+
/// POSIX systems, where giving port 0 to a bind makes the OS pick *some* suitable port).
211+
///
212+
/// Caveats:
213+
///
214+
/// * There is currently no way to pass in a local address that has an unspecified address
215+
/// family (which would effectively create a single socket that servers both IPv4 and IPv6);
216+
/// it is not specified whether stacks that use V6MAPPED IPv4 addresses could simply used
217+
/// that mechanism.
218+
///
219+
/// * It is currently not specified whether this mechanism can be used to join multicast
220+
/// groups.
221+
///
222+
/// * There is currently no hybrid binding that allows emulating what POSIX systems do when
223+
/// binding to `[::]:0`, that is, picking some available port but then still leaving the
224+
/// interface and IP address unspecified.
225+
fn bind_multiple(&self, local: SocketAddr) -> Self::BindMultipleFuture<'_>;
226+
/// Future return type of the [`.bind_multiple()`] method
227+
type BindMultipleFuture<'a>: Future<Output = Result<Self::Unbound<'a>, Self::Error>>
228+
where
229+
Self: 'a;
201230
}

0 commit comments

Comments
 (0)