1 | use std::io; |
2 | use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr}; |
3 | #[cfg (unix)] |
4 | use std::os::unix::io::{AsFd, AsRawFd, BorrowedFd, OwnedFd, RawFd}; |
5 | #[cfg (windows)] |
6 | use std::os::windows::io::{AsRawSocket, AsSocket, BorrowedSocket, OwnedSocket, RawSocket}; |
7 | use std::sync::Arc; |
8 | |
9 | use async_io::Async; |
10 | |
11 | use crate::addr::AsyncToSocketAddrs; |
12 | |
13 | /// A UDP socket. |
14 | /// |
15 | /// After creating a [`UdpSocket`] by [`bind`][`UdpSocket::bind()`]ing it to a socket address, data |
16 | /// can be [sent to] and [received from] any other socket address. |
17 | /// |
18 | /// Cloning a [`UdpSocket`] creates another handle to the same socket. The socket will be closed |
19 | /// when all handles to it are dropped. |
20 | /// |
21 | /// Although UDP is a connectionless protocol, this implementation provides an interface to set an |
22 | /// address where data should be sent and received from. After setting a remote address with |
23 | /// [`connect()`][`UdpSocket::connect()`], data can be sent to and received from that address with |
24 | /// [`send()`][`UdpSocket::send()`] and [`recv()`][`UdpSocket::recv()`]. |
25 | /// |
26 | /// As stated in the User Datagram Protocol's specification in [IETF RFC 768], UDP is an unordered, |
27 | /// unreliable protocol. Refer to [`TcpListener`][`super::TcpListener`] and |
28 | /// [`TcpStream`][`super::TcpStream`] for TCP primitives. |
29 | /// |
30 | /// [received from]: UdpSocket::recv_from() |
31 | /// [sent to]: UdpSocket::send_to() |
32 | /// [IETF RFC 768]: https://tools.ietf.org/html/rfc768 |
33 | /// |
34 | /// # Examples |
35 | /// |
36 | /// ```no_run |
37 | /// use async_net::UdpSocket; |
38 | /// |
39 | /// # futures_lite::future::block_on(async { |
40 | /// let socket = UdpSocket::bind("127.0.0.1:8080" ).await?; |
41 | /// let mut buf = vec![0u8; 20]; |
42 | /// |
43 | /// loop { |
44 | /// // Receive a single datagram message. |
45 | /// // If `buf` is too small to hold the entire message, it will be cut off. |
46 | /// let (n, addr) = socket.recv_from(&mut buf).await?; |
47 | /// |
48 | /// // Send the message back to the same address that has sent it. |
49 | /// socket.send_to(&buf[..n], &addr).await?; |
50 | /// } |
51 | /// # std::io::Result::Ok(()) }); |
52 | /// ``` |
53 | #[derive (Clone, Debug)] |
54 | pub struct UdpSocket { |
55 | inner: Arc<Async<std::net::UdpSocket>>, |
56 | } |
57 | |
58 | impl UdpSocket { |
59 | fn new(inner: Arc<Async<std::net::UdpSocket>>) -> UdpSocket { |
60 | UdpSocket { inner } |
61 | } |
62 | |
63 | /// Creates a new [`UdpSocket`] bound to the given address. |
64 | /// |
65 | /// Binding with a port number of 0 will request that the operating system assigns an available |
66 | /// port to this socket. The assigned port can be queried via the |
67 | /// [`local_addr()`][`UdpSocket::local_addr()`] method. |
68 | /// |
69 | /// If `addr` yields multiple addresses, binding will be attempted with each of the addresses |
70 | /// until one succeeds and returns the socket. If none of the addresses succeed in creating a |
71 | /// socket, the error from the last attempt is returned. |
72 | /// |
73 | /// # Examples |
74 | /// |
75 | /// Create a UDP socket bound to `127.0.0.1:3400`: |
76 | /// |
77 | /// ```no_run |
78 | /// use async_net::UdpSocket; |
79 | /// |
80 | /// # futures_lite::future::block_on(async { |
81 | /// let socket = UdpSocket::bind("127.0.0.1:3400" ).await?; |
82 | /// # std::io::Result::Ok(()) }); |
83 | /// ``` |
84 | /// |
85 | /// Create a UDP socket bound to `127.0.0.1:3400`. If that address is unavailable, then try |
86 | /// binding to `127.0.0.1:3401`: |
87 | /// |
88 | /// ```no_run |
89 | /// use async_net::{SocketAddr, UdpSocket}; |
90 | /// |
91 | /// # futures_lite::future::block_on(async { |
92 | /// let addrs = [ |
93 | /// SocketAddr::from(([127, 0, 0, 1], 3400)), |
94 | /// SocketAddr::from(([127, 0, 0, 1], 3401)), |
95 | /// ]; |
96 | /// let socket = UdpSocket::bind(&addrs[..]).await?; |
97 | /// # std::io::Result::Ok(()) }); |
98 | /// ``` |
99 | pub async fn bind<A: AsyncToSocketAddrs>(addr: A) -> io::Result<UdpSocket> { |
100 | let mut last_err = None; |
101 | |
102 | for addr in addr.to_socket_addrs().await? { |
103 | match Async::<std::net::UdpSocket>::bind(addr) { |
104 | Ok(socket) => return Ok(UdpSocket::new(Arc::new(socket))), |
105 | Err(err) => last_err = Some(err), |
106 | } |
107 | } |
108 | |
109 | Err(last_err.unwrap_or_else(|| { |
110 | io::Error::new( |
111 | io::ErrorKind::InvalidInput, |
112 | "could not bind to any of the addresses" , |
113 | ) |
114 | })) |
115 | } |
116 | |
117 | /// Returns the local address this socket is bound to. |
118 | /// |
119 | /// This can be useful, for example, when binding to port 0 to figure out which port was |
120 | /// actually bound. |
121 | /// |
122 | /// # Examples |
123 | /// |
124 | /// Bind to port 0 and then see which port was assigned by the operating system: |
125 | /// |
126 | /// ```no_run |
127 | /// use async_net::{SocketAddr, UdpSocket}; |
128 | /// |
129 | /// # futures_lite::future::block_on(async { |
130 | /// let socket = UdpSocket::bind("127.0.0.1:0" ).await?; |
131 | /// println!("Bound to {}" , socket.local_addr()?); |
132 | /// # std::io::Result::Ok(()) }); |
133 | /// ``` |
134 | pub fn local_addr(&self) -> io::Result<SocketAddr> { |
135 | self.inner.get_ref().local_addr() |
136 | } |
137 | |
138 | /// Returns the remote address this socket is connected to. |
139 | /// |
140 | /// # Examples |
141 | /// |
142 | /// ```no_run |
143 | /// use async_net::UdpSocket; |
144 | /// |
145 | /// # futures_lite::future::block_on(async { |
146 | /// let socket = UdpSocket::bind("127.0.0.1:34254" ).await?; |
147 | /// socket.connect("192.168.0.1:41203" ).await?; |
148 | /// println!("Connected to {}" , socket.peer_addr()?); |
149 | /// # std::io::Result::Ok(()) }); |
150 | /// ``` |
151 | pub fn peer_addr(&self) -> io::Result<SocketAddr> { |
152 | self.inner.get_ref().peer_addr() |
153 | } |
154 | |
155 | /// Connects the UDP socket to an address. |
156 | /// |
157 | /// When connected, methods [`send()`][`UdpSocket::send()`] and [`recv()`][`UdpSocket::recv()`] |
158 | /// will use the specified address for sending and receiving messages. Additionally, a filter |
159 | /// will be applied to [`recv_from()`][`UdpSocket::recv_from()`] so that it only receives |
160 | /// messages from that same address. |
161 | /// |
162 | /// If `addr` yields multiple addresses, connecting will be attempted with each of the |
163 | /// addresses until the operating system accepts one. If none of the addresses are accepted, |
164 | /// the error from the last attempt is returned. |
165 | /// |
166 | /// # Examples |
167 | /// |
168 | /// ```no_run |
169 | /// use async_net::UdpSocket; |
170 | /// |
171 | /// # futures_lite::future::block_on(async { |
172 | /// let socket = UdpSocket::bind("127.0.0.1:3400" ).await?; |
173 | /// socket.connect("127.0.0.1:8080" ).await?; |
174 | /// # std::io::Result::Ok(()) }); |
175 | /// ``` |
176 | pub async fn connect<A: AsyncToSocketAddrs>(&self, addr: A) -> io::Result<()> { |
177 | let mut last_err = None; |
178 | |
179 | for addr in addr.to_socket_addrs().await? { |
180 | match self.inner.get_ref().connect(addr) { |
181 | Ok(()) => return Ok(()), |
182 | Err(err) => last_err = Some(err), |
183 | } |
184 | } |
185 | |
186 | Err(last_err.unwrap_or_else(|| { |
187 | io::Error::new( |
188 | io::ErrorKind::InvalidInput, |
189 | "could not connect to any of the addresses" , |
190 | ) |
191 | })) |
192 | } |
193 | |
194 | /// Receives a single datagram message. |
195 | /// |
196 | /// On success, returns the number of bytes received and the address message came from. |
197 | /// |
198 | /// This method must be called with a valid byte buffer of sufficient size to hold a message. |
199 | /// If the received message is too long to fit into the buffer, it may be truncated. |
200 | /// |
201 | /// # Examples |
202 | /// |
203 | /// ```no_run |
204 | /// use async_net::UdpSocket; |
205 | /// |
206 | /// # futures_lite::future::block_on(async { |
207 | /// let socket = UdpSocket::bind("127.0.0.1:34254" ).await?; |
208 | /// |
209 | /// let mut buf = vec![0u8; 1024]; |
210 | /// let (n, addr) = socket.recv_from(&mut buf).await?; |
211 | /// println!("Received {} bytes from {}" , n, addr); |
212 | /// # std::io::Result::Ok(()) }); |
213 | /// ``` |
214 | pub async fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { |
215 | self.inner.recv_from(buf).await |
216 | } |
217 | |
218 | /// Receives a single datagram message without removing it from the queue. |
219 | /// |
220 | /// On success, returns the number of bytes peeked and the address message came from. |
221 | /// |
222 | /// This method must be called with a valid byte buffer of sufficient size to hold a message. |
223 | /// If the received message is too long to fit into the buffer, it may be truncated. |
224 | /// |
225 | /// Successive calls return the same message. This is accomplished by passing `MSG_PEEK` as a |
226 | /// flag to the underlying `recvfrom` system call. |
227 | /// |
228 | /// # Examples |
229 | /// |
230 | /// ```no_run |
231 | /// use async_net::UdpSocket; |
232 | /// |
233 | /// # futures_lite::future::block_on(async { |
234 | /// let socket = UdpSocket::bind("127.0.0.1:34254" ).await?; |
235 | /// |
236 | /// let mut buf = vec![0u8; 1024]; |
237 | /// let (n, addr) = socket.peek_from(&mut buf).await?; |
238 | /// println!("Peeked {} bytes from {}" , n, addr); |
239 | /// # std::io::Result::Ok(()) }); |
240 | /// ``` |
241 | pub async fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { |
242 | self.inner.get_ref().peek_from(buf) |
243 | } |
244 | |
245 | /// Sends data to the given address. |
246 | /// |
247 | /// On success, returns the number of bytes sent. |
248 | /// |
249 | /// If `addr` yields multiple addresses, the message will only be sent to the first address. |
250 | /// |
251 | /// # Examples |
252 | /// |
253 | /// ```no_run |
254 | /// use async_net::UdpSocket; |
255 | /// |
256 | /// # futures_lite::future::block_on(async { |
257 | /// let socket = UdpSocket::bind("127.0.0.1:34254" ).await?; |
258 | /// socket.send_to(b"hello" , "127.0.0.1:4242" ).await?; |
259 | /// # std::io::Result::Ok(()) }); |
260 | /// ``` |
261 | pub async fn send_to<A: AsyncToSocketAddrs>(&self, buf: &[u8], addr: A) -> io::Result<usize> { |
262 | let addr = match addr.to_socket_addrs().await?.next() { |
263 | Some(addr) => addr, |
264 | None => { |
265 | return Err(io::Error::new( |
266 | io::ErrorKind::InvalidInput, |
267 | "no addresses to send data to" , |
268 | )) |
269 | } |
270 | }; |
271 | |
272 | self.inner.send_to(buf, addr).await |
273 | } |
274 | |
275 | /// Receives a single datagram message from the connected address. |
276 | /// |
277 | /// On success, returns the number of bytes received. |
278 | /// |
279 | /// This method must be called with a valid byte buffer of sufficient size to hold a message. |
280 | /// If the received message is too long to fit into the buffer, it may be truncated. |
281 | /// |
282 | /// The [`connect()`][`UdpSocket::connect()`] method connects this socket to an address. This |
283 | /// method will fail if the socket is not connected. |
284 | /// |
285 | /// # Examples |
286 | /// |
287 | /// ```no_run |
288 | /// use async_net::UdpSocket; |
289 | /// |
290 | /// # futures_lite::future::block_on(async { |
291 | /// let socket = UdpSocket::bind("127.0.0.1:34254" ).await?; |
292 | /// socket.connect("127.0.0.1:8080" ).await?; |
293 | /// |
294 | /// let mut buf = vec![0u8; 1024]; |
295 | /// let n = socket.recv(&mut buf).await?; |
296 | /// println!("Received {} bytes" , n); |
297 | /// # std::io::Result::Ok(()) }); |
298 | /// ``` |
299 | pub async fn recv(&self, buf: &mut [u8]) -> io::Result<usize> { |
300 | self.inner.recv(buf).await |
301 | } |
302 | |
303 | /// Receives a single datagram from the connected address without removing it from the queue. |
304 | /// |
305 | /// On success, returns the number of bytes peeked. |
306 | /// |
307 | /// This method must be called with a valid byte buffer of sufficient size to hold a message. |
308 | /// If the received message is too long to fit into the buffer, it may be truncated. |
309 | /// |
310 | /// Successive calls return the same message. This is accomplished by passing `MSG_PEEK` as a |
311 | /// flag to the underlying `recv` system call. |
312 | /// |
313 | /// The [`connect()`][`UdpSocket::connect()`] method connects this socket to an address. This |
314 | /// method will fail if the socket is not connected. |
315 | /// |
316 | /// # Examples |
317 | /// |
318 | /// ```no_run |
319 | /// use async_net::UdpSocket; |
320 | /// |
321 | /// # futures_lite::future::block_on(async { |
322 | /// let socket = UdpSocket::bind("127.0.0.1:34254" ).await?; |
323 | /// socket.connect("127.0.0.1:8080" ).await?; |
324 | /// |
325 | /// let mut buf = vec![0u8; 1024]; |
326 | /// let n = socket.peek(&mut buf).await?; |
327 | /// println!("Peeked {} bytes" , n); |
328 | /// # std::io::Result::Ok(()) }); |
329 | /// ``` |
330 | pub async fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { |
331 | self.inner.peek(buf).await |
332 | } |
333 | |
334 | /// Sends data to the connected address. |
335 | /// |
336 | /// The [`connect()`][`UdpSocket::connect()`] method connects this socket to an address. This |
337 | /// method will fail if the socket is not connected. |
338 | /// |
339 | /// # Examples |
340 | /// |
341 | /// ```no_run |
342 | /// use async_net::UdpSocket; |
343 | /// |
344 | /// # futures_lite::future::block_on(async { |
345 | /// let socket = UdpSocket::bind("127.0.0.1:34254" ).await?; |
346 | /// socket.connect("127.0.0.1:8080" ).await?; |
347 | /// socket.send(b"hello" ).await?; |
348 | /// # std::io::Result::Ok(()) }); |
349 | /// ``` |
350 | pub async fn send(&self, buf: &[u8]) -> io::Result<usize> { |
351 | self.inner.send(buf).await |
352 | } |
353 | |
354 | /// Gets the value of the `SO_BROADCAST` option for this socket. |
355 | /// |
356 | /// If set to `true`, this socket is allowed to send packets to a broadcast address. |
357 | /// |
358 | /// # Examples |
359 | /// |
360 | /// ```no_run |
361 | /// use async_net::UdpSocket; |
362 | /// |
363 | /// # futures_lite::future::block_on(async { |
364 | /// let socket = UdpSocket::bind("127.0.0.1:34254" ).await?; |
365 | /// println!("SO_BROADCAST is set to {}" , socket.broadcast()?); |
366 | /// # std::io::Result::Ok(()) }); |
367 | /// ``` |
368 | pub fn broadcast(&self) -> io::Result<bool> { |
369 | self.inner.get_ref().broadcast() |
370 | } |
371 | |
372 | /// Sets the value of the `SO_BROADCAST` option for this socket. |
373 | /// |
374 | /// If set to `true`, this socket is allowed to send packets to a broadcast address. |
375 | /// |
376 | /// # Examples |
377 | /// |
378 | /// ```no_run |
379 | /// use async_net::UdpSocket; |
380 | /// |
381 | /// # futures_lite::future::block_on(async { |
382 | /// let socket = UdpSocket::bind("127.0.0.1:34254" ).await?; |
383 | /// socket.set_broadcast(true)?; |
384 | /// # std::io::Result::Ok(()) }); |
385 | /// ``` |
386 | pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> { |
387 | self.inner.get_ref().set_broadcast(broadcast) |
388 | } |
389 | |
390 | /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket. |
391 | /// |
392 | /// If set to `true`, multicast packets will be looped back to the local socket. |
393 | /// |
394 | /// Note that this option may not have any affect on IPv6 sockets. |
395 | /// |
396 | /// # Examples |
397 | /// |
398 | /// ```no_run |
399 | /// use async_net::UdpSocket; |
400 | /// |
401 | /// # futures_lite::future::block_on(async { |
402 | /// let socket = UdpSocket::bind("127.0.0.1:34254" ).await?; |
403 | /// println!("IP_MULTICAST_LOOP is set to {}" , socket.multicast_loop_v4()?); |
404 | /// # std::io::Result::Ok(()) }); |
405 | /// ``` |
406 | pub fn multicast_loop_v4(&self) -> io::Result<bool> { |
407 | self.inner.get_ref().multicast_loop_v4() |
408 | } |
409 | |
410 | /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket. |
411 | /// |
412 | /// If set to `true`, multicast packets will be looped back to the local socket. |
413 | /// |
414 | /// Note that this option may not have any affect on IPv6 sockets. |
415 | /// |
416 | /// # Examples |
417 | /// |
418 | /// ```no_run |
419 | /// use async_net::UdpSocket; |
420 | /// |
421 | /// # futures_lite::future::block_on(async { |
422 | /// let socket = UdpSocket::bind("127.0.0.1:34254" ).await?; |
423 | /// socket.set_multicast_loop_v4(true)?; |
424 | /// # std::io::Result::Ok(()) }); |
425 | /// ``` |
426 | pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> { |
427 | self.inner |
428 | .get_ref() |
429 | .set_multicast_loop_v4(multicast_loop_v4) |
430 | } |
431 | |
432 | /// Gets the value of the `IP_MULTICAST_TTL` option for this socket. |
433 | /// |
434 | /// Indicates the time-to-live value of outgoing multicast packets for this socket. The default |
435 | /// value is 1, which means that multicast packets don't leave the local network unless |
436 | /// explicitly requested. |
437 | /// |
438 | /// Note that this option may not have any effect on IPv6 sockets. |
439 | /// |
440 | /// # Examples |
441 | /// |
442 | /// ```no_run |
443 | /// use async_net::UdpSocket; |
444 | /// |
445 | /// # futures_lite::future::block_on(async { |
446 | /// let socket = UdpSocket::bind("127.0.0.1:34254" ).await?; |
447 | /// println!("IP_MULTICAST_TTL is set to {}" , socket.multicast_loop_v4()?); |
448 | /// # std::io::Result::Ok(()) }); |
449 | /// ``` |
450 | pub fn multicast_ttl_v4(&self) -> io::Result<u32> { |
451 | self.inner.get_ref().multicast_ttl_v4() |
452 | } |
453 | |
454 | /// Sets the value of the `IP_MULTICAST_TTL` option for this socket. |
455 | /// |
456 | /// Indicates the time-to-live value of outgoing multicast packets for this socket. The default |
457 | /// value is 1, which means that multicast packets don't leave the local network unless |
458 | /// explicitly requested. |
459 | /// |
460 | /// Note that this option may not have any effect on IPv6 sockets. |
461 | /// |
462 | /// # Examples |
463 | /// |
464 | /// ```no_run |
465 | /// use async_net::UdpSocket; |
466 | /// |
467 | /// # futures_lite::future::block_on(async { |
468 | /// let socket = UdpSocket::bind("127.0.0.1:34254" ).await?; |
469 | /// socket.set_multicast_ttl_v4(10)?; |
470 | /// # std::io::Result::Ok(()) }); |
471 | /// ``` |
472 | pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> { |
473 | self.inner.get_ref().set_multicast_ttl_v4(ttl) |
474 | } |
475 | |
476 | /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket. |
477 | /// |
478 | /// Controls whether this socket sees the multicast packets it sends itself. |
479 | /// |
480 | /// Note that this option may not have any effect on IPv4 sockets. |
481 | /// |
482 | /// # Examples |
483 | /// |
484 | /// ```no_run |
485 | /// use async_net::UdpSocket; |
486 | /// |
487 | /// # futures_lite::future::block_on(async { |
488 | /// let socket = UdpSocket::bind("127.0.0.1:34254" ).await?; |
489 | /// println!("IPV6_MULTICAST_LOOP is set to {}" , socket.multicast_loop_v6()?); |
490 | /// # std::io::Result::Ok(()) }); |
491 | /// ``` |
492 | pub fn multicast_loop_v6(&self) -> io::Result<bool> { |
493 | self.inner.get_ref().multicast_loop_v6() |
494 | } |
495 | |
496 | /// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket. |
497 | /// |
498 | /// Controls whether this socket sees the multicast packets it sends itself. |
499 | /// |
500 | /// Note that this option may not have any effect on IPv4 sockets. |
501 | /// |
502 | /// # Examples |
503 | /// |
504 | /// ```no_run |
505 | /// use async_net::UdpSocket; |
506 | /// |
507 | /// # futures_lite::future::block_on(async { |
508 | /// let socket = UdpSocket::bind("127.0.0.1:34254" ).await?; |
509 | /// socket.set_multicast_loop_v6(true)?; |
510 | /// # std::io::Result::Ok(()) }); |
511 | /// ``` |
512 | pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> { |
513 | self.inner |
514 | .get_ref() |
515 | .set_multicast_loop_v6(multicast_loop_v6) |
516 | } |
517 | |
518 | /// Gets the value of the `IP_TTL` option for this socket. |
519 | /// |
520 | /// This option configures the time-to-live field that is used in every packet sent from this |
521 | /// socket. |
522 | /// |
523 | /// # Examples |
524 | /// |
525 | /// ```no_run |
526 | /// use async_net::UdpSocket; |
527 | /// |
528 | /// # futures_lite::future::block_on(async { |
529 | /// let socket = UdpSocket::bind("127.0.0.1:34254" ).await?; |
530 | /// println!("IP_TTL is set to {}" , socket.ttl()?); |
531 | /// # std::io::Result::Ok(()) }); |
532 | /// ``` |
533 | pub fn ttl(&self) -> io::Result<u32> { |
534 | self.inner.get_ref().ttl() |
535 | } |
536 | |
537 | /// Sets the value of the `IP_TTL` option for this socket. |
538 | /// |
539 | /// This option configures the time-to-live field that is used in every packet sent from this |
540 | /// socket. |
541 | /// |
542 | /// # Examples |
543 | /// |
544 | /// ```no_run |
545 | /// use async_net::UdpSocket; |
546 | /// |
547 | /// # futures_lite::future::block_on(async { |
548 | /// let socket = UdpSocket::bind("127.0.0.1:34254" ).await?; |
549 | /// socket.set_ttl(100)?; |
550 | /// # std::io::Result::Ok(()) }); |
551 | /// ``` |
552 | pub fn set_ttl(&self, ttl: u32) -> io::Result<()> { |
553 | self.inner.get_ref().set_ttl(ttl) |
554 | } |
555 | |
556 | /// Executes an operation of the `IP_ADD_MEMBERSHIP` type. |
557 | /// |
558 | /// This method specifies a new multicast group for this socket to join. Argument `multiaddr` |
559 | /// must be a valid multicast address, and `interface` is the address of the local interface |
560 | /// with which the system should join the multicast group. If it's equal to `INADDR_ANY` then |
561 | /// an appropriate interface is chosen by the system. |
562 | pub fn join_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> { |
563 | self.inner |
564 | .get_ref() |
565 | .join_multicast_v4(&multiaddr, &interface) |
566 | } |
567 | |
568 | /// Executes an operation of the `IP_DROP_MEMBERSHIP` type. |
569 | /// |
570 | /// This method leaves a multicast group. Argument `multiaddr` must be a valid multicast |
571 | /// address, and `interface` is the index of the interface to leave. |
572 | pub fn leave_multicast_v4(&self, multiaddr: Ipv4Addr, interface: Ipv4Addr) -> io::Result<()> { |
573 | self.inner |
574 | .get_ref() |
575 | .leave_multicast_v4(&multiaddr, &interface) |
576 | } |
577 | |
578 | /// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type. |
579 | /// |
580 | /// This method specifies a new multicast group for this socket to join. Argument `multiaddr` |
581 | /// must be a valid multicast address, and `interface` is the index of the interface to join |
582 | /// (or 0 to indicate any interface). |
583 | pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { |
584 | self.inner.get_ref().join_multicast_v6(multiaddr, interface) |
585 | } |
586 | |
587 | /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type. |
588 | /// |
589 | /// This method leaves a multicast group. Argument `multiaddr` must be a valid multicast |
590 | /// address, and `interface` is the index of the interface to leave. |
591 | pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> { |
592 | self.inner |
593 | .get_ref() |
594 | .leave_multicast_v6(multiaddr, interface) |
595 | } |
596 | } |
597 | |
598 | impl From<Async<std::net::UdpSocket>> for UdpSocket { |
599 | fn from(socket: Async<std::net::UdpSocket>) -> UdpSocket { |
600 | UdpSocket::new(inner:Arc::new(data:socket)) |
601 | } |
602 | } |
603 | |
604 | impl TryFrom<std::net::UdpSocket> for UdpSocket { |
605 | type Error = io::Error; |
606 | |
607 | fn try_from(socket: std::net::UdpSocket) -> io::Result<UdpSocket> { |
608 | Ok(UdpSocket::new(inner:Arc::new(data:Async::new(io:socket)?))) |
609 | } |
610 | } |
611 | |
612 | impl From<UdpSocket> for Arc<Async<std::net::UdpSocket>> { |
613 | fn from(val: UdpSocket) -> Self { |
614 | val.inner |
615 | } |
616 | } |
617 | |
618 | #[cfg (unix)] |
619 | impl AsRawFd for UdpSocket { |
620 | fn as_raw_fd(&self) -> RawFd { |
621 | self.inner.as_raw_fd() |
622 | } |
623 | } |
624 | |
625 | #[cfg (unix)] |
626 | impl AsFd for UdpSocket { |
627 | fn as_fd(&self) -> BorrowedFd<'_> { |
628 | self.inner.get_ref().as_fd() |
629 | } |
630 | } |
631 | |
632 | #[cfg (unix)] |
633 | impl TryFrom<OwnedFd> for UdpSocket { |
634 | type Error = io::Error; |
635 | |
636 | fn try_from(value: OwnedFd) -> Result<Self, Self::Error> { |
637 | Self::try_from(std::net::UdpSocket::from(value)) |
638 | } |
639 | } |
640 | |
641 | #[cfg (windows)] |
642 | impl AsRawSocket for UdpSocket { |
643 | fn as_raw_socket(&self) -> RawSocket { |
644 | self.inner.as_raw_socket() |
645 | } |
646 | } |
647 | |
648 | #[cfg (windows)] |
649 | impl AsSocket for UdpSocket { |
650 | fn as_socket(&self) -> BorrowedSocket<'_> { |
651 | self.inner.get_ref().as_socket() |
652 | } |
653 | } |
654 | |
655 | #[cfg (windows)] |
656 | impl TryFrom<OwnedSocket> for UdpSocket { |
657 | type Error = io::Error; |
658 | |
659 | fn try_from(value: OwnedSocket) -> Result<Self, Self::Error> { |
660 | Self::try_from(std::net::UdpSocket::from(value)) |
661 | } |
662 | } |
663 | |