@@ -27,37 +27,41 @@ use no_std_net::SocketAddr;
27
27
/// `bind()` call in the creation of such sockets, these are implicitly bound to a suitable local
28
28
/// address at connect time.
29
29
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>>;
61
65
}
62
66
63
67
/// This trait is implemented by UDP sockets.
@@ -70,47 +74,57 @@ pub trait ConnectedUdp {
70
74
/// caller MUST pass in the same (or compatible) values, MAY and pass in unspecified values where
71
75
/// applicable. The implementer MAY check them for compatibility, and SHOULD do that in debug mode.
72
76
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 ;
114
128
}
115
129
116
130
/// This trait is implemented by UDP/IP stacks. The trait allows the underlying driver to
@@ -119,83 +133,98 @@ pub trait UnconnectedUdp {
119
133
/// Note that stacks with exotic connection creation methods may still not implement this, yet have
120
134
/// objects that implement [`ConnectedUdp`] or similar.
121
135
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 ;
201
230
}
0 commit comments