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