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}