compio_net/udp.rs
1use std::{
2 future::Future,
3 io,
4 net::{Ipv4Addr, Ipv6Addr, SocketAddr},
5};
6
7use compio_buf::{BufResult, IoBuf, IoBufMut, IoVectoredBuf, IoVectoredBufMut};
8use compio_driver::{
9 BufferRef, impl_raw_fd,
10 op::{RecvFlags, RecvFromMultiResult, RecvMsgMultiResult},
11};
12use futures_util::Stream;
13use socket2::{Protocol, SockAddr, Socket as Socket2, Type};
14
15use crate::{MSG_NOSIGNAL, Socket, ToSocketAddrsAsync};
16
17/// A UDP socket.
18///
19/// UDP is "connectionless", unlike TCP. Meaning, regardless of what address
20/// you've bound to, a `UdpSocket` is free to communicate with many different
21/// remotes. There are basically two main ways to use `UdpSocket`:
22///
23/// * one to many: [`bind`](`UdpSocket::bind`) and use
24/// [`send_to`](`UdpSocket::send_to`) and
25/// [`recv_from`](`UdpSocket::recv_from`) to communicate with many different
26/// addresses
27/// * one to one: [`connect`](`UdpSocket::connect`) and associate with a single
28/// address, using [`send`](`UdpSocket::send`) and [`recv`](`UdpSocket::recv`)
29/// to communicate only with that remote address
30///
31/// # Examples
32/// Bind and connect a pair of sockets and send a packet:
33///
34/// ```
35/// use std::net::SocketAddr;
36///
37/// use compio_net::UdpSocket;
38///
39/// # compio_runtime::Runtime::new().unwrap().block_on(async {
40/// let first_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
41/// let second_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
42///
43/// // bind sockets
44/// let mut socket = UdpSocket::bind(first_addr).await.unwrap();
45/// let first_addr = socket.local_addr().unwrap();
46/// let mut other_socket = UdpSocket::bind(second_addr).await.unwrap();
47/// let second_addr = other_socket.local_addr().unwrap();
48///
49/// // connect sockets
50/// socket.connect(second_addr).await.unwrap();
51/// other_socket.connect(first_addr).await.unwrap();
52///
53/// let buf = Vec::with_capacity(12);
54///
55/// // write data
56/// socket.send("Hello world!").await.unwrap();
57///
58/// // read data
59/// let (n_bytes, buf) = other_socket.recv(buf).await.unwrap();
60///
61/// assert_eq!(n_bytes, buf.len());
62/// assert_eq!(buf, b"Hello world!");
63/// # });
64/// ```
65/// Send and receive packets without connecting:
66///
67/// ```
68/// use std::net::SocketAddr;
69///
70/// use compio_net::UdpSocket;
71/// use socket2::SockAddr;
72///
73/// # compio_runtime::Runtime::new().unwrap().block_on(async {
74/// let first_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
75/// let second_addr: SocketAddr = "127.0.0.1:0".parse().unwrap();
76///
77/// // bind sockets
78/// let mut socket = UdpSocket::bind(first_addr).await.unwrap();
79/// let first_addr = socket.local_addr().unwrap();
80/// let mut other_socket = UdpSocket::bind(second_addr).await.unwrap();
81/// let second_addr = other_socket.local_addr().unwrap();
82///
83/// let buf = Vec::with_capacity(32);
84///
85/// // write data
86/// socket.send_to("hello world", second_addr).await.unwrap();
87///
88/// // read data
89/// let ((n_bytes, addr), buf) = other_socket.recv_from(buf).await.unwrap();
90///
91/// assert_eq!(addr, first_addr);
92/// assert_eq!(n_bytes, buf.len());
93/// assert_eq!(buf, b"hello world");
94/// # });
95/// ```
96#[derive(Debug, Clone)]
97pub struct UdpSocket {
98 inner: Socket,
99}
100
101impl UdpSocket {
102 /// Creates a new UDP socket and attempt to bind it to the addr provided.
103 pub async fn bind(addr: impl ToSocketAddrsAsync) -> io::Result<Self> {
104 super::each_addr(addr, |addr| async move {
105 let addr = SockAddr::from(addr);
106 let socket = Socket::new(addr.domain(), Type::DGRAM, Some(Protocol::UDP)).await?;
107 socket.bind(&addr).await?;
108 Ok(Self { inner: socket })
109 })
110 .await
111 }
112
113 /// Connects this UDP socket to a remote address, allowing the `send` and
114 /// `recv` to be used to send data and also applies filters to only
115 /// receive data from the specified address.
116 ///
117 /// Note that usually, a successful `connect` call does not specify
118 /// that there is a remote server listening on the port, rather, such an
119 /// error would only be detected after the first send.
120 pub async fn connect(&self, addr: impl ToSocketAddrsAsync) -> io::Result<()> {
121 super::each_addr(addr, |addr| async move {
122 self.inner.connect(&SockAddr::from(addr))
123 })
124 .await
125 }
126
127 /// Creates new UdpSocket from a std::net::UdpSocket.
128 pub fn from_std(socket: std::net::UdpSocket) -> io::Result<Self> {
129 Ok(Self {
130 inner: Socket::from_socket2(Socket2::from(socket))?,
131 })
132 }
133
134 /// Close the socket. If the returned future is dropped before polling, the
135 /// socket won't be closed.
136 ///
137 /// See [`TcpStream::close`] for more details.
138 ///
139 /// [`TcpStream::close`]: crate::tcp::TcpStream::close
140 pub fn close(self) -> impl Future<Output = io::Result<()>> {
141 self.inner.close()
142 }
143
144 /// Returns the socket address of the remote peer this socket was connected
145 /// to.
146 ///
147 /// # Examples
148 ///
149 /// ```no_run
150 /// use std::net::{Ipv4Addr, SocketAddr, SocketAddrV4};
151 ///
152 /// use compio_net::UdpSocket;
153 /// use socket2::SockAddr;
154 ///
155 /// # compio_runtime::Runtime::new().unwrap().block_on(async {
156 /// let socket = UdpSocket::bind("127.0.0.1:34254")
157 /// .await
158 /// .expect("couldn't bind to address");
159 /// socket
160 /// .connect("192.168.0.1:41203")
161 /// .await
162 /// .expect("couldn't connect to address");
163 /// assert_eq!(
164 /// socket.peer_addr().unwrap(),
165 /// SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 41203))
166 /// );
167 /// # });
168 /// ```
169 pub fn peer_addr(&self) -> io::Result<SocketAddr> {
170 self.inner
171 .peer_addr()
172 .map(|addr| addr.as_socket().expect("should be SocketAddr"))
173 }
174
175 /// Returns the local address that this socket is bound to.
176 ///
177 /// # Example
178 ///
179 /// ```
180 /// use std::net::SocketAddr;
181 ///
182 /// use compio_net::UdpSocket;
183 /// use socket2::SockAddr;
184 ///
185 /// # compio_runtime::Runtime::new().unwrap().block_on(async {
186 /// let addr: SocketAddr = "127.0.0.1:8080".parse().unwrap();
187 /// let sock = UdpSocket::bind(&addr).await.unwrap();
188 /// // the address the socket is bound to
189 /// let local_addr = sock.local_addr().unwrap();
190 /// assert_eq!(local_addr, addr);
191 /// # });
192 /// ```
193 pub fn local_addr(&self) -> io::Result<SocketAddr> {
194 self.inner
195 .local_addr()
196 .map(|addr| addr.as_socket().expect("should be SocketAddr"))
197 }
198
199 /// Receives a packet of data from the socket into the buffer, returning the
200 /// original buffer and quantity of data received.
201 pub async fn recv<T: IoBufMut>(&self, buffer: T) -> BufResult<usize, T> {
202 self.inner.recv(buffer, RecvFlags::empty()).await
203 }
204
205 /// Receives a packet of data from the socket into the buffer, returning the
206 /// original buffer and quantity of data received.
207 pub async fn recv_vectored<T: IoVectoredBufMut>(&self, buffer: T) -> BufResult<usize, T> {
208 self.inner.recv_vectored(buffer, RecvFlags::empty()).await
209 }
210
211 /// Read some bytes from this source and return a [`BufferRef`].
212 ///
213 /// If `len` == 0, will use buffer pool's inner buffer size as the max len;
214 /// if `len` > 0, `min(len, inner buffer size)` will be the read max len.
215 pub async fn recv_managed(&self, len: usize) -> io::Result<Option<BufferRef>> {
216 self.inner.recv_managed(len, RecvFlags::empty()).await
217 }
218
219 /// Read some bytes from this source and return a stream of [`BufferRef`]s.
220 ///
221 /// If `len` == 0, will use buffer pool's inner buffer size as the max len
222 /// of each buffer; if `len` > 0, `min(len, inner buffer size)` will be
223 /// the read max len of each buffer.
224 pub fn recv_multi(&self, len: usize) -> impl Stream<Item = io::Result<BufferRef>> {
225 self.inner.recv_multi(len, RecvFlags::empty())
226 }
227
228 /// Sends some data to the socket from the buffer, returning the original
229 /// buffer and quantity of data sent.
230 pub async fn send<T: IoBuf>(&self, buffer: T) -> BufResult<usize, T> {
231 self.inner.send(buffer, MSG_NOSIGNAL).await
232 }
233
234 /// Sends some data to the socket from the buffer, returning the original
235 /// buffer and quantity of data sent.
236 pub async fn send_vectored<T: IoVectoredBuf>(&self, buffer: T) -> BufResult<usize, T> {
237 self.inner.send_vectored(buffer, MSG_NOSIGNAL).await
238 }
239
240 /// Receives a single datagram message on the socket. On success, returns
241 /// the number of bytes received and the origin.
242 pub async fn recv_from<T: IoBufMut>(&self, buffer: T) -> BufResult<(usize, SocketAddr), T> {
243 self.inner
244 .recv_from(buffer, RecvFlags::empty())
245 .await
246 .map_res(|(n, addr)| {
247 let addr = addr
248 .expect("should have addr")
249 .as_socket()
250 .expect("should be SocketAddr");
251 (n, addr)
252 })
253 }
254
255 /// Receives a single datagram message on the socket. On success, returns
256 /// the number of bytes received and the origin.
257 pub async fn recv_from_vectored<T: IoVectoredBufMut>(
258 &self,
259 buffer: T,
260 ) -> BufResult<(usize, SocketAddr), T> {
261 self.inner
262 .recv_from_vectored(buffer, RecvFlags::empty())
263 .await
264 .map_res(|(n, addr)| {
265 let addr = addr
266 .expect("should have addr")
267 .as_socket()
268 .expect("should be SocketAddr");
269 (n, addr)
270 })
271 }
272
273 /// Read some bytes from this source and the runtime's buffer pool and
274 /// return a [`BufferRef`] with the sender address.
275 ///
276 /// If `len` == 0, will use buffer pool's inner buffer size as the max len;
277 /// if `len` > 0, `min(len, inner buffer size)` will be the read max len
278 pub async fn recv_from_managed(
279 &self,
280 len: usize,
281 ) -> io::Result<Option<(BufferRef, SocketAddr)>> {
282 let res = self
283 .inner
284 .recv_from_managed(len, RecvFlags::empty())
285 .await?;
286 let ret = match res {
287 Some((buffer, addr)) => {
288 let addr = addr
289 .expect("should have addr")
290 .as_socket()
291 .expect("should be SocketAddr");
292 Some((buffer, addr))
293 }
294 None => None,
295 };
296 Ok(ret)
297 }
298
299 /// Read some bytes from this source and the runtime's buffer pool and
300 /// return a stream of [`RecvFromMultiResult`].
301 pub fn recv_from_multi(&self) -> impl Stream<Item = io::Result<RecvFromMultiResult>> {
302 self.inner.recv_from_multi(RecvFlags::empty())
303 }
304
305 /// Receives a single datagram message and ancillary data on the socket. On
306 /// success, returns the number of bytes received and the origin.
307 pub async fn recv_msg<T: IoBufMut, C: IoBufMut>(
308 &self,
309 buffer: T,
310 control: C,
311 ) -> BufResult<(usize, usize, SocketAddr), (T, C)> {
312 self.inner
313 .recv_msg(buffer, control, RecvFlags::empty())
314 .await
315 .map_res(|(n, m, addr)| {
316 let addr = addr
317 .expect("should have addr")
318 .as_socket()
319 .expect("should be SocketAddr");
320 (n, m, addr)
321 })
322 }
323
324 /// Receives a single datagram message and ancillary data on the socket. On
325 /// success, returns the number of bytes received and the origin.
326 pub async fn recv_msg_vectored<T: IoVectoredBufMut, C: IoBufMut>(
327 &self,
328 buffer: T,
329 control: C,
330 ) -> BufResult<(usize, usize, SocketAddr), (T, C)> {
331 self.inner
332 .recv_msg_vectored(buffer, control, RecvFlags::empty())
333 .await
334 .map_res(|(n, m, addr)| {
335 let addr = addr
336 .expect("should have addr")
337 .as_socket()
338 .expect("should be SocketAddr");
339 (n, m, addr)
340 })
341 }
342
343 /// Receives a single datagram message on the socket from the runtime's
344 /// buffer pool, together with ancillary data. The ancillary data buffer is
345 /// provided by the caller.
346 ///
347 /// If `len` == 0, will use buffer pool's inner buffer size as the max len;
348 /// if `len` > 0, `min(len, inner buffer size)` will be the read max len
349 pub async fn recv_msg_managed<C: IoBufMut>(
350 &self,
351 len: usize,
352 control: C,
353 ) -> io::Result<Option<(BufferRef, C, SocketAddr)>> {
354 let res = self
355 .inner
356 .recv_msg_managed(len, control, RecvFlags::empty())
357 .await?;
358 let ret = match res {
359 Some((buffer, control, addr)) => {
360 let addr = addr
361 .expect("should have addr")
362 .as_socket()
363 .expect("should be SocketAddr");
364 Some((buffer, control, addr))
365 }
366 None => None,
367 };
368 Ok(ret)
369 }
370
371 /// Receives multiple single datagram messages and ancillary data on the
372 /// socket from the runtime's buffer pool.
373 pub fn recv_msg_multi(
374 &self,
375 control_len: usize,
376 ) -> impl Stream<Item = io::Result<RecvMsgMultiResult>> {
377 self.inner.recv_msg_multi(control_len, RecvFlags::empty())
378 }
379
380 /// Sends data on the socket to the given address. On success, returns the
381 /// number of bytes sent.
382 pub async fn send_to<T: IoBuf>(
383 &self,
384 buffer: T,
385 addr: impl ToSocketAddrsAsync,
386 ) -> BufResult<usize, T> {
387 super::first_addr_buf(addr, buffer, |addr, buffer| async move {
388 self.inner
389 .send_to(buffer, &SockAddr::from(addr), MSG_NOSIGNAL)
390 .await
391 })
392 .await
393 }
394
395 /// Sends data on the socket to the given address. On success, returns the
396 /// number of bytes sent.
397 pub async fn send_to_vectored<T: IoVectoredBuf>(
398 &self,
399 buffer: T,
400 addr: impl ToSocketAddrsAsync,
401 ) -> BufResult<usize, T> {
402 super::first_addr_buf(addr, buffer, |addr, buffer| async move {
403 self.inner
404 .send_to_vectored(buffer, &SockAddr::from(addr), MSG_NOSIGNAL)
405 .await
406 })
407 .await
408 }
409
410 /// Sends data on the socket to the given address accompanied by ancillary
411 /// data. On success, returns the number of bytes sent.
412 pub async fn send_msg<T: IoBuf, C: IoBuf>(
413 &self,
414 buffer: T,
415 control: C,
416 addr: impl ToSocketAddrsAsync,
417 ) -> BufResult<usize, (T, C)> {
418 super::first_addr_buf(
419 addr,
420 (buffer, control),
421 |addr, (buffer, control)| async move {
422 self.inner
423 .send_msg(buffer, control, Some(&SockAddr::from(addr)), MSG_NOSIGNAL)
424 .await
425 },
426 )
427 .await
428 }
429
430 /// Sends data on the socket to the given address accompanied by ancillary
431 /// data. On success, returns the number of bytes sent.
432 pub async fn send_msg_vectored<T: IoVectoredBuf, C: IoBuf>(
433 &self,
434 buffer: T,
435 control: C,
436 addr: impl ToSocketAddrsAsync,
437 ) -> BufResult<usize, (T, C)> {
438 super::first_addr_buf(
439 addr,
440 (buffer, control),
441 |addr, (buffer, control)| async move {
442 self.inner
443 .send_msg_vectored(buffer, control, Some(&SockAddr::from(addr)), MSG_NOSIGNAL)
444 .await
445 },
446 )
447 .await
448 }
449
450 /// Sends data on the socket with zero copy.
451 ///
452 /// Returns the result of send and a future that resolves to the
453 /// original buffer when the send is complete.
454 pub async fn send_zerocopy<T: IoBuf>(
455 &self,
456 buf: T,
457 ) -> BufResult<usize, impl Future<Output = T> + use<T>> {
458 self.inner.send_zerocopy(buf, MSG_NOSIGNAL).await
459 }
460
461 /// Sends vectored data on the socket with zero copy.
462 ///
463 /// Returns the result of send and a future that resolves to the
464 /// original buffer when the send is complete.
465 pub async fn send_zerocopy_vectored<T: IoVectoredBuf>(
466 &self,
467 buf: T,
468 ) -> BufResult<usize, impl Future<Output = T> + use<T>> {
469 self.inner.send_zerocopy_vectored(buf, MSG_NOSIGNAL).await
470 }
471
472 /// Sends data on the socket to the given address with zero copy.
473 ///
474 /// Returns the result of send and a future that resolves to the
475 /// original buffer when the send is complete.
476 pub async fn send_to_zerocopy<A: ToSocketAddrsAsync, T: IoBuf>(
477 &self,
478 buffer: T,
479 addr: A,
480 ) -> BufResult<usize, impl Future<Output = T> + use<A, T>> {
481 super::first_addr_buf_zerocopy(addr, buffer, |addr, buffer| async move {
482 self.inner
483 .send_to_zerocopy(buffer, &addr.into(), MSG_NOSIGNAL)
484 .await
485 })
486 .await
487 }
488
489 /// Sends vectored data on the socket to the given address with zero copy.
490 ///
491 /// Returns the result of send and a future that resolves to the
492 /// original buffer when the send is complete.
493 pub async fn send_to_zerocopy_vectored<A: ToSocketAddrsAsync, T: IoVectoredBuf>(
494 &self,
495 buffer: T,
496 addr: A,
497 ) -> BufResult<usize, impl Future<Output = T> + use<A, T>> {
498 super::first_addr_buf_zerocopy(addr, buffer, |addr, buffer| async move {
499 self.inner
500 .send_to_zerocopy_vectored(buffer, &addr.into(), MSG_NOSIGNAL)
501 .await
502 })
503 .await
504 }
505
506 /// Sends data with control message on the socket to the given address with
507 /// zero copy.
508 ///
509 /// Returns the result of send and a future that resolves to the
510 /// original buffer when the send is complete.
511 pub async fn send_msg_zerocopy<A: ToSocketAddrsAsync, T: IoBuf, C: IoBuf>(
512 &self,
513 buffer: T,
514 control: C,
515 addr: A,
516 ) -> BufResult<usize, impl Future<Output = (T, C)> + use<A, T, C>> {
517 super::first_addr_buf_zerocopy(addr, (buffer, control), |addr, (b, c)| async move {
518 self.inner
519 .send_msg_zerocopy(b, c, Some(&addr.into()), MSG_NOSIGNAL)
520 .await
521 })
522 .await
523 }
524
525 /// Sends vectored data with control message on the socket to the given
526 /// address with zero copy.
527 ///
528 /// Returns the result of send and a future that resolves to the
529 /// original buffer when the send is complete.
530 pub async fn send_msg_zerocopy_vectored<A: ToSocketAddrsAsync, T: IoVectoredBuf, C: IoBuf>(
531 &self,
532 buffer: T,
533 control: C,
534 addr: A,
535 ) -> BufResult<usize, impl Future<Output = (T, C)> + use<A, T, C>> {
536 super::first_addr_buf_zerocopy(addr, (buffer, control), |addr, (b, c)| async move {
537 self.inner
538 .send_msg_zerocopy_vectored(b, c, Some(&addr.into()), MSG_NOSIGNAL)
539 .await
540 })
541 .await
542 }
543
544 /// Gets the value of the `SO_BROADCAST` option for this socket.
545 ///
546 /// For more information about this option, see [`set_broadcast`].
547 ///
548 /// [`set_broadcast`]: method@Self::set_broadcast
549 pub fn broadcast(&self) -> io::Result<bool> {
550 self.inner.socket.broadcast()
551 }
552
553 /// Sets the value of the `SO_BROADCAST` option for this socket.
554 ///
555 /// When enabled, this socket is allowed to send packets to a broadcast
556 /// address.
557 pub fn set_broadcast(&self, on: bool) -> io::Result<()> {
558 self.inner.socket.set_broadcast(on)
559 }
560
561 /// Gets the value of the `IP_MULTICAST_LOOP` option for this socket.
562 ///
563 /// For more information about this option, see [`set_multicast_loop_v4`].
564 ///
565 /// [`set_multicast_loop_v4`]: method@Self::set_multicast_loop_v4
566 pub fn multicast_loop_v4(&self) -> io::Result<bool> {
567 self.inner.socket.multicast_loop_v4()
568 }
569
570 /// Sets the value of the `IP_MULTICAST_LOOP` option for this socket.
571 ///
572 /// If enabled, multicast packets will be looped back to the local socket.
573 ///
574 /// # Note
575 ///
576 /// This may not have any effect on IPv6 sockets.
577 pub fn set_multicast_loop_v4(&self, on: bool) -> io::Result<()> {
578 self.inner.socket.set_multicast_loop_v4(on)
579 }
580
581 /// Gets the value of the `IP_MULTICAST_TTL` option for this socket.
582 ///
583 /// For more information about this option, see [`set_multicast_ttl_v4`].
584 ///
585 /// [`set_multicast_ttl_v4`]: method@Self::set_multicast_ttl_v4
586 pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
587 self.inner.socket.multicast_ttl_v4()
588 }
589
590 /// Sets the value of the `IP_MULTICAST_TTL` option for this socket.
591 ///
592 /// Indicates the time-to-live value of outgoing multicast packets for
593 /// this socket. The default value is 1 which means that multicast packets
594 /// don't leave the local network unless explicitly requested.
595 ///
596 /// # Note
597 ///
598 /// This may not have any effect on IPv6 sockets.
599 pub fn set_multicast_ttl_v4(&self, ttl: u32) -> io::Result<()> {
600 self.inner.socket.set_multicast_ttl_v4(ttl)
601 }
602
603 /// Gets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
604 ///
605 /// For more information about this option, see [`set_multicast_loop_v6`].
606 ///
607 /// [`set_multicast_loop_v6`]: method@Self::set_multicast_loop_v6
608 pub fn multicast_loop_v6(&self) -> io::Result<bool> {
609 self.inner.socket.multicast_loop_v6()
610 }
611
612 /// Sets the value of the `IPV6_MULTICAST_LOOP` option for this socket.
613 ///
614 /// Controls whether this socket sees the multicast packets it sends itself.
615 ///
616 /// # Note
617 ///
618 /// This may not have any effect on IPv4 sockets.
619 pub fn set_multicast_loop_v6(&self, on: bool) -> io::Result<()> {
620 self.inner.socket.set_multicast_loop_v6(on)
621 }
622
623 /// Gets the value of the `IPV6_TCLASS` option for this socket.
624 ///
625 /// For more information about this option, see [`set_tclass_v6`].
626 ///
627 /// [`set_tclass_v6`]: Self::set_tclass_v6
628 #[cfg(any(
629 target_os = "android",
630 target_os = "dragonfly",
631 target_os = "freebsd",
632 target_os = "fuchsia",
633 target_os = "linux",
634 target_os = "macos",
635 target_os = "netbsd",
636 target_os = "openbsd",
637 target_os = "cygwin",
638 ))]
639 pub fn tclass_v6(&self) -> io::Result<u32> {
640 self.inner.socket.tclass_v6()
641 }
642
643 /// Sets the value for the `IPV6_TCLASS` option on this socket.
644 ///
645 /// Specifies the traffic class field that is used in every packet
646 /// sent from this socket.
647 ///
648 /// # Note
649 ///
650 /// This may not have any effect on IPv4 sockets.
651 #[cfg(any(
652 target_os = "android",
653 target_os = "dragonfly",
654 target_os = "freebsd",
655 target_os = "fuchsia",
656 target_os = "linux",
657 target_os = "macos",
658 target_os = "netbsd",
659 target_os = "openbsd",
660 target_os = "cygwin",
661 ))]
662 pub fn set_tclass_v6(&self, tclass: u32) -> io::Result<()> {
663 self.inner.socket.set_tclass_v6(tclass)
664 }
665
666 /// Gets the value of the `IP_TTL` option for this socket.
667 ///
668 /// For more information about this option, see [`set_ttl_v4`].
669 ///
670 /// [`set_ttl_v4`]: method@Self::set_ttl_v4
671 pub fn ttl_v4(&self) -> io::Result<u32> {
672 self.inner.socket.ttl_v4()
673 }
674
675 /// Sets the value for the `IP_TTL` option on this socket.
676 ///
677 /// This value sets the time-to-live field that is used in every packet sent
678 /// from this socket.
679 pub fn set_ttl_v4(&self, ttl: u32) -> io::Result<()> {
680 self.inner.socket.set_ttl_v4(ttl)
681 }
682
683 /// Gets the value of the `IP_TOS` option for this socket.
684 ///
685 /// For more information about this option, see [`set_tos_v4`].
686 ///
687 /// [`set_tos_v4`]: Self::set_tos_v4
688 // https://docs.rs/socket2/0.6.1/src/socket2/socket.rs.html#1585
689 #[cfg(not(any(
690 target_os = "fuchsia",
691 target_os = "redox",
692 target_os = "solaris",
693 target_os = "illumos",
694 target_os = "haiku"
695 )))]
696 pub fn tos_v4(&self) -> io::Result<u32> {
697 self.inner.socket.tos_v4()
698 }
699
700 /// Sets the value for the `IP_TOS` option on this socket.
701 ///
702 /// This value sets the type-of-service field that is used in every packet
703 /// sent from this socket.
704 ///
705 /// # Note
706 ///
707 /// - This may not have any effect on IPv6 sockets.
708 #[cfg(not(any(
709 target_os = "fuchsia",
710 target_os = "redox",
711 target_os = "solaris",
712 target_os = "illumos",
713 target_os = "haiku"
714 )))]
715 pub fn set_tos_v4(&self, tos: u32) -> io::Result<()> {
716 self.inner.socket.set_tos_v4(tos)
717 }
718
719 /// Gets the value for the `SO_BINDTODEVICE` option on this socket
720 ///
721 /// This value gets the socket-bound device's interface name.
722 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux",))]
723 pub fn device(&self) -> io::Result<Option<Vec<u8>>> {
724 self.inner.socket.device()
725 }
726
727 /// Sets the value for the `SO_BINDTODEVICE` option on this socket
728 ///
729 /// If a socket is bound to an interface, only packets received from that
730 /// particular interface are processed by the socket. Note that this only
731 /// works for some socket types, particularly `AF_INET` sockets.
732 ///
733 /// If `interface` is `None` or an empty string it removes the binding.
734 #[cfg(any(target_os = "android", target_os = "fuchsia", target_os = "linux"))]
735 pub fn bind_device(&self, interface: Option<&[u8]>) -> io::Result<()> {
736 self.inner.socket.bind_device(interface)
737 }
738
739 /// Executes an operation of the `IP_ADD_MEMBERSHIP` type.
740 ///
741 /// This function specifies a new multicast group for this socket to join.
742 /// The address must be a valid multicast address, and `interface` is the
743 /// address of the local interface with which the system should join the
744 /// multicast group. If it's equal to `INADDR_ANY` then an appropriate
745 /// interface is chosen by the system.
746 pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
747 self.inner.socket.join_multicast_v4(multiaddr, interface)
748 }
749
750 /// Executes an operation of the `IPV6_ADD_MEMBERSHIP` type.
751 ///
752 /// This function specifies a new multicast group for this socket to join.
753 /// The address must be a valid multicast address, and `interface` is the
754 /// index of the interface to join/leave (or 0 to indicate any interface).
755 pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
756 self.inner.socket.join_multicast_v6(multiaddr, interface)
757 }
758
759 /// Executes an operation of the `IP_DROP_MEMBERSHIP` type.
760 ///
761 /// For more information about this option, see [`join_multicast_v4`].
762 ///
763 /// [`join_multicast_v4`]: method@Self::join_multicast_v4
764 pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
765 self.inner.socket.leave_multicast_v4(multiaddr, interface)
766 }
767
768 /// Executes an operation of the `IPV6_DROP_MEMBERSHIP` type.
769 ///
770 /// For more information about this option, see [`join_multicast_v6`].
771 ///
772 /// [`join_multicast_v6`]: method@Self::join_multicast_v6
773 pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
774 self.inner.socket.leave_multicast_v6(multiaddr, interface)
775 }
776
777 /// Returns the value of the `SO_ERROR` option.
778 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
779 self.inner.socket.take_error()
780 }
781
782 /// Gets a socket option.
783 ///
784 /// # Safety
785 ///
786 /// The caller must ensure `T` is the correct type for `level` and `name`.
787 pub unsafe fn get_socket_option<T: Copy>(&self, level: i32, name: i32) -> io::Result<T> {
788 unsafe { self.inner.get_socket_option(level, name) }
789 }
790
791 /// Sets a socket option.
792 ///
793 /// # Safety
794 ///
795 /// The caller must ensure `T` is the correct type for `level` and `name`.
796 pub unsafe fn set_socket_option<T: Copy>(
797 &self,
798 level: i32,
799 name: i32,
800 value: &T,
801 ) -> io::Result<()> {
802 unsafe { self.inner.set_socket_option(level, name, value) }
803 }
804}
805
806impl_raw_fd!(UdpSocket, socket2::Socket, inner, socket);