1#[cfg(test)]
2#[cfg(not(target_os = "l4re"))]
3mod tests;
4
5use crate::ffi::{c_int, c_void};
6use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut};
7use crate::mem::MaybeUninit;
8use crate::net::{
9 Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6, ToSocketAddrs,
10};
11use crate::sys::helpers::run_with_cstr;
12use crate::sys::net::connection::each_addr;
13use crate::sys::{AsInner, FromInner};
14use crate::time::Duration;
15use crate::{cmp, fmt, mem, ptr};
16
17cfg_select! {
18 target_os = "hermit" => {
19 mod hermit;
20 pub use hermit::*;
21 }
22 target_os = "solid_asp3" => {
23 mod solid;
24 pub use solid::*;
25 }
26 any(target_family = "unix", target_os = "wasi") => {
27 mod unix;
28 pub use unix::*;
29 }
30 target_os = "windows" => {
31 mod windows;
32 pub use windows::*;
33 }
34 _ => {}
35}
36
37use netc as c;
38
39const MAX_SEND_LEN: usize =
54 cfg_select! {
55 any(target_vendor = "apple", target_os = "nto", target_os = "qnx") => c_int::MAX as usize,
56 target_os = "windows" => i32::MAX as usize,
57 _ => libc::ssize_t::MAX as usize,
58 };
59
60cfg_select! {
61 any(
62 target_os = "dragonfly",
63 target_os = "freebsd",
64 target_os = "openbsd",
65 target_os = "netbsd",
66 target_os = "illumos",
67 target_os = "solaris",
68 target_os = "haiku",
69 target_os = "l4re",
70 target_os = "nto",
71 target_os = "qnx",
72 target_os = "nuttx",
73 target_vendor = "apple",
74 ) => {
75 use c::{IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP, IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP};
76 }
77 _ => {
78 use c::{IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP};
79 }
80}
81
82cfg_select! {
83 any(
84 target_os = "linux",
85 target_os = "android",
86 target_os = "hurd",
87 target_os = "dragonfly",
88 target_os = "freebsd",
89 target_os = "openbsd",
90 target_os = "netbsd",
91 target_os = "solaris",
92 target_os = "illumos",
93 target_os = "haiku",
94 target_os = "nto",
95 target_os = "qnx",
96 target_os = "cygwin",
97 ) => {
98 use libc::MSG_NOSIGNAL;
99 }
100 _ => {
101 const MSG_NOSIGNAL: c_int = 0x0;
102 }
103}
104
105cfg_select! {
106 any(
107 target_os = "dragonfly",
108 target_os = "freebsd",
109 target_os = "openbsd",
110 target_os = "netbsd",
111 target_os = "solaris",
112 target_os = "illumos",
113 target_os = "nto",
114 target_os = "qnx",
115 ) => {
116 use crate::ffi::c_uchar;
117 type IpV4MultiCastType = c_uchar;
118 }
119 _ => {
120 type IpV4MultiCastType = c_int;
121 }
122}
123
124fn ip_v4_addr_to_c(addr: &Ipv4Addr) -> c::in_addr {
129 c::in_addr { s_addr: u32::from_ne_bytes(addr.octets()) }
132}
133
134fn ip_v6_addr_to_c(addr: &Ipv6Addr) -> c::in6_addr {
135 c::in6_addr { s6_addr: addr.octets() }
136}
137
138fn ip_v4_addr_from_c(addr: c::in_addr) -> Ipv4Addr {
139 Ipv4Addr::from(addr.s_addr.to_ne_bytes())
140}
141
142fn ip_v6_addr_from_c(addr: c::in6_addr) -> Ipv6Addr {
143 Ipv6Addr::from(addr.s6_addr)
144}
145
146fn socket_addr_v4_to_c(addr: &SocketAddrV4) -> c::sockaddr_in {
147 c::sockaddr_in {
148 sin_family: c::AF_INET as c::sa_family_t,
149 sin_port: addr.port().to_be(),
150 sin_addr: ip_v4_addr_to_c(addr.ip()),
151 ..unsafe { mem::zeroed() }
152 }
153}
154
155fn socket_addr_v6_to_c(addr: &SocketAddrV6) -> c::sockaddr_in6 {
156 c::sockaddr_in6 {
157 sin6_family: c::AF_INET6 as c::sa_family_t,
158 sin6_port: addr.port().to_be(),
159 sin6_addr: ip_v6_addr_to_c(addr.ip()),
160 sin6_flowinfo: addr.flowinfo(),
161 sin6_scope_id: addr.scope_id(),
162 ..unsafe { mem::zeroed() }
163 }
164}
165
166fn socket_addr_v4_from_c(addr: c::sockaddr_in) -> SocketAddrV4 {
167 SocketAddrV4::new(ip_v4_addr_from_c(addr.sin_addr), u16::from_be(addr.sin_port))
168}
169
170fn socket_addr_v6_from_c(addr: c::sockaddr_in6) -> SocketAddrV6 {
171 SocketAddrV6::new(
172 ip_v6_addr_from_c(addr.sin6_addr),
173 u16::from_be(addr.sin6_port),
174 addr.sin6_flowinfo,
175 addr.sin6_scope_id,
176 )
177}
178
179#[repr(C)]
184union SocketAddrCRepr {
185 v4: c::sockaddr_in,
186 v6: c::sockaddr_in6,
187}
188
189impl SocketAddrCRepr {
190 fn as_ptr(&self) -> *const c::sockaddr {
191 self as *const _ as *const c::sockaddr
192 }
193}
194
195fn socket_addr_to_c(addr: &SocketAddr) -> (SocketAddrCRepr, c::socklen_t) {
196 match addr {
197 SocketAddr::V4(a) => {
198 let sockaddr = SocketAddrCRepr { v4: socket_addr_v4_to_c(a) };
199 (sockaddr, size_of::<c::sockaddr_in>() as c::socklen_t)
200 }
201 SocketAddr::V6(a) => {
202 let sockaddr = SocketAddrCRepr { v6: socket_addr_v6_to_c(a) };
203 (sockaddr, size_of::<c::sockaddr_in6>() as c::socklen_t)
204 }
205 }
206}
207
208fn addr_family(addr: &SocketAddr) -> c_int {
209 match addr {
210 SocketAddr::V4(..) => c::AF_INET,
211 SocketAddr::V6(..) => c::AF_INET6,
212 }
213}
214
215unsafe fn socket_addr_from_c(
221 storage: *const c::sockaddr_storage,
222 len: usize,
223) -> io::Result<SocketAddr> {
224 match (*storage).ss_family as c_int {
225 c::AF_INET => {
226 if !(len >= size_of::<c::sockaddr_in>()) {
::core::panicking::panic("assertion failed: len >= size_of::<c::sockaddr_in>()")
};assert!(len >= size_of::<c::sockaddr_in>());
227 Ok(SocketAddr::V4(socket_addr_v4_from_c(unsafe {
228 *(storage as *const _ as *const c::sockaddr_in)
229 })))
230 }
231 c::AF_INET6 => {
232 if !(len >= size_of::<c::sockaddr_in6>()) {
::core::panicking::panic("assertion failed: len >= size_of::<c::sockaddr_in6>()")
};assert!(len >= size_of::<c::sockaddr_in6>());
233 Ok(SocketAddr::V6(socket_addr_v6_from_c(unsafe {
234 *(storage as *const _ as *const c::sockaddr_in6)
235 })))
236 }
237 _ => Err(::core::hint::must_use(::core::io::Error::from_static_message(const {
&::core::io::SimpleMessage {
kind: ErrorKind::InvalidInput,
message: "invalid argument",
}
}))io::const_error!(ErrorKind::InvalidInput, "invalid argument")),
238 }
239}
240
241pub unsafe fn setsockopt<T>(
250 sock: &Socket,
251 level: c_int,
252 option_name: c_int,
253 option_value: T,
254) -> io::Result<()> {
255 let option_len = size_of::<T>() as c::socklen_t;
256 cvt(unsafe {
263 c::setsockopt(
264 sock.as_raw(),
265 level,
266 option_name,
267 (&raw const option_value) as *const _,
268 option_len,
269 )
270 })?;
271 Ok(())
272}
273
274pub unsafe fn getsockopt<T: Copy>(
279 sock: &Socket,
280 level: c_int,
281 option_name: c_int,
282) -> io::Result<T> {
283 let mut option_value = MaybeUninit::<T>::zeroed();
284 let mut option_len = size_of::<T>() as c::socklen_t;
285
286 cvt(unsafe {
291 c::getsockopt(
292 sock.as_raw(),
293 level,
294 option_name,
295 option_value.as_mut_ptr().cast(),
296 &mut option_len,
297 )
298 })?;
299
300 Ok(unsafe { option_value.assume_init() })
304}
305
306unsafe fn sockname<F>(f: F) -> io::Result<SocketAddr>
314where
315 F: FnOnce(*mut c::sockaddr, *mut c::socklen_t) -> c_int,
316{
317 let mut storage = MaybeUninit::<c::sockaddr_storage>::zeroed();
318 let mut len = size_of::<c::sockaddr_storage>() as c::socklen_t;
319 cvt(f(storage.as_mut_ptr().cast(), &mut len))?;
320 unsafe { socket_addr_from_c(storage.as_ptr(), len as usize) }
324}
325
326#[cfg(target_os = "android")]
327fn to_ipv6mr_interface(value: u32) -> c_int {
328 value as c_int
329}
330
331#[cfg(not(target_os = "android"))]
332fn to_ipv6mr_interface(value: u32) -> crate::ffi::c_uint {
333 value as crate::ffi::c_uint
334}
335
336pub struct LookupHost {
341 original: *mut c::addrinfo,
342 cur: *mut c::addrinfo,
343 port: u16,
344}
345
346impl Iterator for LookupHost {
347 type Item = SocketAddr;
348 fn next(&mut self) -> Option<SocketAddr> {
349 loop {
350 unsafe {
351 let cur = self.cur.as_ref()?;
352 self.cur = cur.ai_next;
353 match socket_addr_from_c(cur.ai_addr.cast(), cur.ai_addrlen as usize) {
354 Ok(mut addr) => {
355 addr.set_port(self.port);
356 return Some(addr);
357 }
358 Err(_) => continue,
359 }
360 }
361 }
362 }
363}
364
365unsafe impl Sync for LookupHost {}
366unsafe impl Send for LookupHost {}
367
368impl Drop for LookupHost {
369 fn drop(&mut self) {
370 unsafe { c::freeaddrinfo(self.original) }
371 }
372}
373
374pub fn lookup_host(host: &str, port: u16) -> io::Result<LookupHost> {
375 init();
376 run_with_cstr(host.as_bytes(), &|c_host| {
377 let mut hints: c::addrinfo = unsafe { mem::zeroed() };
378 hints.ai_socktype = c::SOCK_STREAM;
379 let mut res = ptr::null_mut();
380 unsafe {
381 cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res))
382 .map(|_| LookupHost { original: res, cur: res, port })
383 }
384 })
385}
386
387pub struct TcpStream {
392 inner: Socket,
393}
394
395impl TcpStream {
396 pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
397 init();
398 return each_addr(addr, inner);
399
400 fn inner(addr: &SocketAddr) -> io::Result<TcpStream> {
401 let sock = Socket::new(addr_family(addr), c::SOCK_STREAM)?;
402 sock.connect(addr)?;
403 Ok(TcpStream { inner: sock })
404 }
405 }
406
407 pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
408 init();
409
410 let sock = Socket::new(addr_family(addr), c::SOCK_STREAM)?;
411 sock.connect_timeout(addr, timeout)?;
412 Ok(TcpStream { inner: sock })
413 }
414
415 #[inline]
416 pub fn socket(&self) -> &Socket {
417 &self.inner
418 }
419
420 pub fn into_socket(self) -> Socket {
421 self.inner
422 }
423
424 pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
425 self.inner.set_timeout(dur, c::SO_RCVTIMEO)
426 }
427
428 pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
429 self.inner.set_timeout(dur, c::SO_SNDTIMEO)
430 }
431
432 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
433 self.inner.timeout(c::SO_RCVTIMEO)
434 }
435
436 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
437 self.inner.timeout(c::SO_SNDTIMEO)
438 }
439
440 pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
441 self.inner.peek(buf)
442 }
443
444 pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
445 self.inner.read(buf)
446 }
447
448 pub fn read_buf(&self, buf: BorrowedCursor<'_, u8>) -> io::Result<()> {
449 self.inner.read_buf(buf)
450 }
451
452 pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
453 self.inner.read_vectored(bufs)
454 }
455
456 #[inline]
457 pub fn is_read_vectored(&self) -> bool {
458 self.inner.is_read_vectored()
459 }
460
461 pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
462 let len = cmp::min(buf.len(), MAX_SEND_LEN) as wrlen_t;
463 let ret = cvt(unsafe {
464 c::send(self.inner.as_raw(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
465 })?;
466 Ok(ret as usize)
467 }
468
469 pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
470 self.inner.write_vectored(bufs)
471 }
472
473 #[inline]
474 pub fn is_write_vectored(&self) -> bool {
475 self.inner.is_write_vectored()
476 }
477
478 pub fn peer_addr(&self) -> io::Result<SocketAddr> {
479 unsafe { sockname(|buf, len| c::getpeername(self.inner.as_raw(), buf, len)) }
480 }
481
482 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
483 unsafe { sockname(|buf, len| c::getsockname(self.inner.as_raw(), buf, len)) }
484 }
485
486 pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
487 self.inner.shutdown(how)
488 }
489
490 pub fn duplicate(&self) -> io::Result<TcpStream> {
491 self.inner.duplicate().map(|s| TcpStream { inner: s })
492 }
493
494 pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
495 self.inner.set_linger(linger)
496 }
497
498 pub fn linger(&self) -> io::Result<Option<Duration>> {
499 self.inner.linger()
500 }
501
502 pub fn set_keepalive(&self, keepalive: bool) -> io::Result<()> {
503 self.inner.set_keepalive(keepalive)
504 }
505
506 pub fn keepalive(&self) -> io::Result<bool> {
507 self.inner.keepalive()
508 }
509
510 pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
511 self.inner.set_nodelay(nodelay)
512 }
513
514 pub fn nodelay(&self) -> io::Result<bool> {
515 self.inner.nodelay()
516 }
517
518 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
519 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) }
520 }
521
522 pub fn ttl(&self) -> io::Result<u32> {
523 let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)? };
524 Ok(raw as u32)
525 }
526
527 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
528 self.inner.take_error()
529 }
530
531 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
532 self.inner.set_nonblocking(nonblocking)
533 }
534}
535
536impl AsInner<Socket> for TcpStream {
537 #[inline]
538 fn as_inner(&self) -> &Socket {
539 &self.inner
540 }
541}
542
543impl FromInner<Socket> for TcpStream {
544 fn from_inner(socket: Socket) -> TcpStream {
545 TcpStream { inner: socket }
546 }
547}
548
549impl fmt::Debug for TcpStream {
550 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
551 let mut res = f.debug_struct("TcpStream");
552
553 if let Ok(addr) = self.socket_addr() {
554 res.field("addr", &addr);
555 }
556
557 if let Ok(peer) = self.peer_addr() {
558 res.field("peer", &peer);
559 }
560
561 let name = if falsecfg!(windows) { "socket" } else { "fd" };
562 res.field(name, &self.inner.as_raw()).finish()
563 }
564}
565
566pub struct TcpListener {
571 inner: Socket,
572}
573
574impl TcpListener {
575 pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
576 init();
577 return each_addr(addr, inner);
578
579 fn inner(addr: &SocketAddr) -> io::Result<TcpListener> {
580 let sock = Socket::new(addr_family(addr), c::SOCK_STREAM)?;
581
582 #[cfg(not(windows))]
590 unsafe {
591 setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?
592 };
593
594 let (addr, len) = socket_addr_to_c(addr);
596 cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
597
598 let backlog = if falsecfg!(target_os = "horizon") {
599 20
603 } else if falsecfg!(target_os = "haiku") {
604 32
607 } else {
608 128
610 };
611
612 cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
614 Ok(TcpListener { inner: sock })
615 }
616 }
617
618 #[inline]
619 pub fn socket(&self) -> &Socket {
620 &self.inner
621 }
622
623 pub fn into_socket(self) -> Socket {
624 self.inner
625 }
626
627 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
628 unsafe { sockname(|buf, len| c::getsockname(self.inner.as_raw(), buf, len)) }
629 }
630
631 pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
632 let mut storage = MaybeUninit::<c::sockaddr_storage>::uninit();
636 let mut len = size_of::<c::sockaddr_storage>() as c::socklen_t;
637 let sock = self.inner.accept(storage.as_mut_ptr() as *mut _, &mut len)?;
638 let addr = unsafe { socket_addr_from_c(storage.as_ptr(), len as usize)? };
639 Ok((TcpStream { inner: sock }, addr))
640 }
641
642 pub fn duplicate(&self) -> io::Result<TcpListener> {
643 self.inner.duplicate().map(|s| TcpListener { inner: s })
644 }
645
646 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
647 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) }
648 }
649
650 pub fn ttl(&self) -> io::Result<u32> {
651 let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)? };
652 Ok(raw as u32)
653 }
654
655 pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
656 unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int) }
657 }
658
659 pub fn only_v6(&self) -> io::Result<bool> {
660 let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY)? };
661 Ok(raw != 0)
662 }
663
664 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
665 self.inner.take_error()
666 }
667
668 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
669 self.inner.set_nonblocking(nonblocking)
670 }
671}
672
673impl FromInner<Socket> for TcpListener {
674 fn from_inner(socket: Socket) -> TcpListener {
675 TcpListener { inner: socket }
676 }
677}
678
679impl fmt::Debug for TcpListener {
680 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
681 let mut res = f.debug_struct("TcpListener");
682
683 if let Ok(addr) = self.socket_addr() {
684 res.field("addr", &addr);
685 }
686
687 let name = if falsecfg!(windows) { "socket" } else { "fd" };
688 res.field(name, &self.inner.as_raw()).finish()
689 }
690}
691
692pub struct UdpSocket {
697 inner: Socket,
698}
699
700impl UdpSocket {
701 pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
702 init();
703 return each_addr(addr, inner);
704
705 fn inner(addr: &SocketAddr) -> io::Result<UdpSocket> {
706 let sock = Socket::new(addr_family(addr), c::SOCK_DGRAM)?;
707 let (addr, len) = socket_addr_to_c(addr);
708 cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
709 Ok(UdpSocket { inner: sock })
710 }
711 }
712
713 #[inline]
714 pub fn socket(&self) -> &Socket {
715 &self.inner
716 }
717
718 pub fn into_socket(self) -> Socket {
719 self.inner
720 }
721
722 pub fn peer_addr(&self) -> io::Result<SocketAddr> {
723 unsafe { sockname(|buf, len| c::getpeername(self.inner.as_raw(), buf, len)) }
724 }
725
726 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
727 unsafe { sockname(|buf, len| c::getsockname(self.inner.as_raw(), buf, len)) }
728 }
729
730 pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
731 self.inner.recv_from(buf)
732 }
733
734 pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
735 self.inner.peek_from(buf)
736 }
737
738 pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
739 if buf.len() > MAX_SEND_LEN {
740 return Err(io::Error::from_raw_os_error(c::EMSGSIZE));
741 }
742 let (dst, dstlen) = socket_addr_to_c(dst);
743 let ret = cvt(unsafe {
744 c::sendto(
745 self.inner.as_raw(),
746 buf.as_ptr() as *const c_void,
747 buf.len() as wrlen_t,
748 MSG_NOSIGNAL,
749 dst.as_ptr(),
750 dstlen,
751 )
752 })?;
753 Ok(ret as usize)
754 }
755
756 pub fn duplicate(&self) -> io::Result<UdpSocket> {
757 self.inner.duplicate().map(|s| UdpSocket { inner: s })
758 }
759
760 pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
761 self.inner.set_timeout(dur, c::SO_RCVTIMEO)
762 }
763
764 pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
765 self.inner.set_timeout(dur, c::SO_SNDTIMEO)
766 }
767
768 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
769 self.inner.timeout(c::SO_RCVTIMEO)
770 }
771
772 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
773 self.inner.timeout(c::SO_SNDTIMEO)
774 }
775
776 pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
777 unsafe { setsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST, broadcast as c_int) }
778 }
779
780 pub fn broadcast(&self) -> io::Result<bool> {
781 let raw: c_int = unsafe { getsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST)? };
782 Ok(raw != 0)
783 }
784
785 pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
786 unsafe {
787 setsockopt(
788 &self.inner,
789 c::IPPROTO_IP,
790 c::IP_MULTICAST_LOOP,
791 multicast_loop_v4 as IpV4MultiCastType,
792 )
793 }
794 }
795
796 pub fn multicast_loop_v4(&self) -> io::Result<bool> {
797 let raw: IpV4MultiCastType =
798 unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP)? };
799 Ok(raw != 0)
800 }
801
802 pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
803 let ttl: u8 = multicast_ttl_v4
804 .try_into()
805 .map_err(|_| io::Error::from(io::ErrorKind::InvalidInput))?;
806 unsafe {
807 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL, ttl as IpV4MultiCastType)
808 }
809 }
810
811 pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
812 let raw: IpV4MultiCastType =
813 unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL)? };
814 Ok(raw as u32)
815 }
816
817 pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
818 unsafe {
819 setsockopt(
820 &self.inner,
821 c::IPPROTO_IPV6,
822 c::IPV6_MULTICAST_LOOP,
823 multicast_loop_v6 as c_int,
824 )
825 }
826 }
827
828 pub fn multicast_loop_v6(&self) -> io::Result<bool> {
829 let raw: c_int =
830 unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP)? };
831 Ok(raw != 0)
832 }
833
834 pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
835 let mreq = c::ip_mreq {
836 imr_multiaddr: ip_v4_addr_to_c(multiaddr),
837 imr_interface: ip_v4_addr_to_c(interface),
838 };
839 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq) }
840 }
841
842 pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
843 let mreq = c::ipv6_mreq {
844 ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
845 ipv6mr_interface: to_ipv6mr_interface(interface),
846 };
847 unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq) }
848 }
849
850 pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
851 let mreq = c::ip_mreq {
852 imr_multiaddr: ip_v4_addr_to_c(multiaddr),
853 imr_interface: ip_v4_addr_to_c(interface),
854 };
855 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq) }
856 }
857
858 pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
859 let mreq = c::ipv6_mreq {
860 ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
861 ipv6mr_interface: to_ipv6mr_interface(interface),
862 };
863 unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq) }
864 }
865
866 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
867 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) }
868 }
869
870 pub fn ttl(&self) -> io::Result<u32> {
871 let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)? };
872 Ok(raw as u32)
873 }
874
875 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
876 self.inner.take_error()
877 }
878
879 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
880 self.inner.set_nonblocking(nonblocking)
881 }
882
883 pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
884 self.inner.read(buf)
885 }
886
887 pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
888 self.inner.peek(buf)
889 }
890
891 pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
892 if buf.len() > MAX_SEND_LEN {
893 return Err(io::Error::from_raw_os_error(c::EMSGSIZE));
894 }
895 let ret = cvt(unsafe {
896 c::send(
897 self.inner.as_raw(),
898 buf.as_ptr() as *const c_void,
899 buf.len() as wrlen_t,
900 MSG_NOSIGNAL,
901 )
902 })?;
903 Ok(ret as usize)
904 }
905
906 pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
907 return each_addr(addr, |addr| inner(self, addr));
908
909 fn inner(this: &UdpSocket, addr: &SocketAddr) -> io::Result<()> {
910 let (addr, len) = socket_addr_to_c(addr);
911 cvt_r(|| unsafe { c::connect(this.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
912 }
913 }
914}
915
916impl FromInner<Socket> for UdpSocket {
917 fn from_inner(socket: Socket) -> UdpSocket {
918 UdpSocket { inner: socket }
919 }
920}
921
922impl fmt::Debug for UdpSocket {
923 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
924 let mut res = f.debug_struct("UdpSocket");
925
926 if let Ok(addr) = self.socket_addr() {
927 res.field("addr", &addr);
928 }
929
930 let name = if falsecfg!(windows) { "socket" } else { "fd" };
931 res.field(name, &self.inner.as_raw()).finish()
932 }
933}