fumio_reactor/net/udp_socket.rs
1use crate::helper::async_io;
2use crate::reactor::{LazyHandle, PollEvented};
3use mio::net::UdpSocket as MioUdpSocket;
4use std::future::Future;
5use std::io;
6use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
7use std::pin::Pin;
8use std::task::{Context, Poll};
9
10/// A UDP socket
11#[derive(Debug)]
12#[must_use = "A UDP socket does nothing if not actually used"]
13pub struct UdpSocket {
14 pub(super) mio_socket: PollEvented<MioUdpSocket>,
15}
16
17impl UdpSocket {
18 /// Create builder with default options, but doesn't bind yet.
19 ///
20 /// To create a `UdpSocket` from a builder go through the `std::net::UdpSocket` created by
21 /// `builder.bind(...)?`.
22 pub fn default_builder_for(local: &SocketAddr) -> io::Result<net2::UdpBuilder> {
23 let builder;
24 match local {
25 SocketAddr::V4(_) => {
26 builder = net2::UdpBuilder::new_v4()?;
27 }
28 SocketAddr::V6(a) => {
29 builder = net2::UdpBuilder::new_v6()?;
30 if a.ip().is_unspecified() {
31 // always try to disable only_v6
32 let _ = builder.only_v6(false);
33 }
34 }
35 }
36 builder.reuse_address(true)?;
37 Ok(builder)
38 }
39
40 /// Wraps an already bound tcp stream
41 pub fn from_std(stream: std::net::UdpSocket, handle: LazyHandle) -> io::Result<Self> {
42 Ok(Self {
43 mio_socket: PollEvented::new(MioUdpSocket::from_socket(stream)?, handle),
44 })
45 }
46
47 /// Wraps an already bound tcp stream
48 pub fn from_mio(stream: mio::net::UdpSocket, handle: LazyHandle) -> io::Result<Self> {
49 Ok(Self {
50 mio_socket: PollEvented::new(stream, handle),
51 })
52 }
53
54 /// Binds a new UDP socket to IPv6 `[::]` with V6_ONLY=false (i.e. also listen on IPv4) and the
55 /// given port.
56 ///
57 /// If the port is 0 the OS will select a random port.
58 pub fn bind_port(port: u16) -> io::Result<Self> {
59 Self::bind(std::net::SocketAddrV6::new(Ipv6Addr::UNSPECIFIED, port, 0, 0).into())
60 }
61
62 /// Binds a new UDP socket to IPv4 `0.0.0.0` and the given port.
63 ///
64 /// If the port is 0 the OS will select a random port.
65 pub fn bind_ipv4_port(port: u16) -> io::Result<Self> {
66 Self::bind(std::net::SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, port).into())
67 }
68
69 /// Bind a new UDP socket to the specified address.
70 pub fn bind(local: SocketAddr) -> io::Result<Self> {
71 Self::bind_with(local, LazyHandle::new())
72 }
73
74 /// Bind a new UDP socket to the specified address.
75 pub fn bind_with(local: SocketAddr, handle: LazyHandle) -> io::Result<Self> {
76 let builder = Self::default_builder_for(&local)?;
77 Self::from_std(builder.bind(&local)?, handle)
78 }
79
80 /// Returns the local socket address of this socket.
81 pub fn local_addr(&self) -> io::Result<SocketAddr> {
82 self.mio_socket.io_ref().local_addr()
83 }
84
85 /// Creates a new independently owned handle to the underlying socket.
86 ///
87 /// The new listener isn't registered to a reactor yet.
88 pub fn try_clone(&self) -> io::Result<Self> {
89 self.try_clone_with(LazyHandle::new())
90 }
91
92 /// Creates a new independently owned handle to the underlying socket.
93 pub fn try_clone_with(&self, handle: LazyHandle) -> io::Result<Self> {
94 Ok(Self {
95 mio_socket: PollEvented::new(self.mio_socket.io_ref().try_clone()?, handle),
96 })
97 }
98
99 /// Receives data from the socket. On success, returns the number of bytes read and the address from whence the data came.
100 pub fn poll_recv_from(&mut self, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<io::Result<(usize, SocketAddr)>> {
101 // use mutable (although io.recv_from doesn't need it), because only one context can get registered;
102 // shared ownership isn't useful.
103 self.mio_socket.try_mut_read(cx, |io| {
104 async_io(|| io.recv_from(buf))
105 })
106 }
107
108 /// Receives data from the socket. On success, completes with the number of bytes read and the
109 /// address from whence the data came.
110 pub fn recv_from<'a>(&'a mut self, buf: &'a mut [u8]) -> UdpRecvFrom<'a> {
111 UdpRecvFrom {
112 socket: self,
113 buf,
114 }
115 }
116
117 /// Sends data on the socket to the given address. On success, returns the number of bytes written.
118 pub fn poll_send_to(&mut self, cx: &mut Context<'_>, buf: &[u8], target: &SocketAddr) -> Poll<io::Result<usize>> {
119 // use mutable (although io.send_to doesn't need it), because only one context can get registered;
120 // shared ownership isn't useful.
121 self.mio_socket.try_mut_write(cx, |io| {
122 async_io(|| io.send_to(buf, target))
123 })
124 }
125
126 /// Sends data on the socket to the given address. On success, completes with the number of
127 /// bytes written.
128 pub fn send_to<'a>(&'a mut self, buf: &'a [u8], target: &'a SocketAddr) -> UdpSendTo<'a> {
129 UdpSendTo {
130 socket: self,
131 buf,
132 target,
133 }
134 }
135
136/*
137 // connected UDP sockets should get a separate type?
138
139 /// Connects the UDP socket setting the default destination for `send` and limiting packets
140 /// that are read via `recv` from the address specified in `target`.
141 pub fn connect(self, target: SocketAddr) -> Result<ConnectedUdpSocket> { ... }
142
143 /// Receives data from the socket previously bound with connect(). On success, returns the number of bytes read.
144 pub fn poll_recv(&mut self, cx: &mut Context<'_>, buf: &mut [u8]) -> Poll<io::Result<usize>> {
145 // use mutable (although io.recv doesn't need it), because only one context can get registered;
146 // shared ownership isn't useful.
147 self.mio_socket.try_mut_read(cx, |io| {
148 async_io(|| io.recv(buf))
149 })
150 }
151
152 /// Sends data on the socket to the address previously bound via connect(). On success, returns the number of bytes written.
153 pub fn poll_send(&mut self, cx: &mut Context<'_>, buf: &[u8]) -> Poll<io::Result<usize>> {
154 // use mutable (although io.send doesn't need it), because only one context can get registered;
155 // shared ownership isn't useful.
156 self.mio_socket.try_mut_write(cx, |io| {
157 async_io(|| io.send(buf))
158 })
159 }
160*/
161
162 /// Sets the value of the `SO_BROADCAST` option for this socket.
163 ///
164 /// When enabled, this socket is allowed to send packets to a broadcast address.
165 pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
166 self.mio_socket.io_ref().set_broadcast(on)
167 }
168
169 /// Gets the value of the SO_BROADCAST option for this socket.
170 ///
171 /// For more information about this option, see set_broadcast.
172 pub fn broadcast(&self) -> io::Result<bool> {
173 self.mio_socket.io_ref().broadcast()
174 }
175
176 /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket.
177 ///
178 /// If enabled, multicast packets will be looped back to the local socket.
179 /// Note that this may not have any affect on IPv6 sockets.
180 pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
181 self.mio_socket.io_ref().set_multicast_loop_v4(on)
182 }
183
184 /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket.
185 ///
186 /// For more information about this option, see
187 /// [`set_multicast_loop_v4`][link].
188 ///
189 /// [link]: #method.set_multicast_loop_v4
190 pub fn multicast_loop_v4(&self) -> io::Result<bool> {
191 self.mio_socket.io_ref().multicast_loop_v4()
192 }
193
194 /// Sets the value of the `IP_MULTICAST_TTL` option for this socket.
195 ///
196 /// Indicates the time-to-live value of outgoing multicast packets for
197 /// this socket. The default value is 1 which means that multicast packets
198 /// don't leave the local network unless explicitly requested.
199 ///
200 /// Note that this may not have any affect on IPv6 sockets.
201 pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
202 self.mio_socket.io_ref().set_multicast_ttl_v4(ttl)
203 }
204
205 /// Gets the value of the `IP_MULTICAST_TTL` option for this socket.
206 ///
207 /// For more information about this option, see
208 /// [`set_multicast_ttl_v4`][link].
209 ///
210 /// [link]: #method.set_multicast_ttl_v4
211 pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
212 self.mio_socket.io_ref().multicast_ttl_v4()
213 }
214
215 /// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
216 ///
217 /// Controls whether this socket sees the multicast packets it sends itself.
218 /// Note that this may not have any affect on IPv4 sockets.
219 pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
220 self.mio_socket.io_ref().set_multicast_loop_v6(on)
221 }
222
223 /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
224 ///
225 /// For more information about this option, see
226 /// [`set_multicast_loop_v6`][link].
227 ///
228 /// [link]: #method.set_multicast_loop_v6
229 pub fn multicast_loop_v6(&self) -> io::Result<bool> {
230 self.mio_socket.io_ref().multicast_loop_v6()
231 }
232
233 /// Sets the value for the `IP_TTL` option on this socket.
234 ///
235 /// This value sets the time-to-live field that is used in every packet sent
236 /// from this socket.
237 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
238 self.mio_socket.io_ref().set_ttl(ttl)
239 }
240
241 /// Gets the value of the `IP_TTL` option for this socket.
242 ///
243 /// For more information about this option, see [`set_ttl`][link].
244 ///
245 /// [link]: #method.set_ttl
246 pub fn ttl(&self) -> io::Result<u32> {
247 self.mio_socket.io_ref().ttl()
248 }
249
250 /// Executes an operation of the `IP_ADD_MEMBERSHIP` type.
251 ///
252 /// This function specifies a new multicast group for this socket to join.
253 /// The address must be a valid multicast address, and `interface` is the
254 /// address of the local interface with which the system should join the
255 /// multicast group. If it's equal to `INADDR_ANY` then an appropriate
256 /// interface is chosen by the system.
257 pub fn join_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> {
258 self.mio_socket.io_ref().join_multicast_v4(&multiaddr, &interface)
259 }
260
261 /// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type.
262 ///
263 /// This function specifies a new multicast group for this socket to join.
264 /// The address must be a valid multicast address, and `interface` is the
265 /// index of the interface to join/leave (or 0 to indicate any interface).
266 pub fn join_multicast_v6(&self, multiaddr: Ipv6Addr, interface: u32) -> io::Result<()> {
267 self.mio_socket.io_ref().join_multicast_v6(&multiaddr, interface)
268 }
269
270 /// Executes an operation of the `IP_DROP_MEMBERSHIP` type.
271 ///
272 /// For more information about this option, see
273 /// [`join_multicast_v4`][link].
274 ///
275 /// [link]: #method.join_multicast_v4
276 pub fn leave_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> {
277 self.mio_socket.io_ref().leave_multicast_v4(&multiaddr, &interface)
278 }
279
280 /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type.
281 ///
282 /// For more information about this option, see
283 /// [`join_multicast_v6`][link].
284 ///
285 /// [link]: #method.join_multicast_v6
286 pub fn leave_multicast_v6(&self, multiaddr: Ipv6Addr, interface: u32) -> io::Result<()> {
287 self.mio_socket.io_ref().leave_multicast_v6(&multiaddr, interface)
288 }
289
290 /// Get the value of the `SO_ERROR` option on this socket.
291 ///
292 /// This will retrieve the stored error in the underlying socket, clearing
293 /// the field in the process. This can be useful for checking errors between
294 /// calls.
295 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
296 self.mio_socket.io_ref().take_error()
297 }
298}
299
300impl std::convert::TryFrom<std::net::UdpSocket> for UdpSocket {
301 type Error = io::Error;
302
303 fn try_from(s: std::net::UdpSocket) -> io::Result<Self> {
304 Self::from_std(s, LazyHandle::new())
305 }
306}
307
308impl std::convert::TryFrom<mio::net::UdpSocket> for UdpSocket {
309 type Error = io::Error;
310
311 fn try_from(s: mio::net::UdpSocket) -> io::Result<Self> {
312 Self::from_mio(s, LazyHandle::new())
313 }
314}
315
316/// Pending `recv_from` operation
317#[must_use = "futures do nothing unless you `.await` or poll them"]
318#[derive(Debug)]
319pub struct UdpRecvFrom<'a> {
320 socket: &'a mut UdpSocket,
321 buf: &'a mut [u8],
322}
323
324impl Future for UdpRecvFrom<'_> {
325 type Output = io::Result<(usize, SocketAddr)>;
326
327 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
328 let this = self.get_mut();
329 this.socket.poll_recv_from(cx, this.buf)
330 }
331}
332
333/// Pending `send_to` operation
334#[must_use = "futures do nothing unless you `.await` or poll them"]
335#[derive(Debug)]
336pub struct UdpSendTo<'a> {
337 socket: &'a mut UdpSocket,
338 buf: &'a [u8],
339 target: &'a SocketAddr,
340}
341
342impl Future for UdpSendTo<'_> {
343 type Output = io::Result<usize>;
344
345 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
346 let this = self.get_mut();
347 this.socket.poll_send_to(cx, this.buf, this.target)
348 }
349}