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