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