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
60const SOCK_NONBLOCK: i32 = cfg_select! {
63 any(
64 target_os = "dragonfly",
65 target_os = "freebsd",
66 target_os = "hermit",
67 target_os = "illumos",
68 target_os = "linux",
69 target_os = "netbsd",
70 target_os = "openbsd",
71 ) => c::SOCK_NONBLOCK,
72 _ => 0,
73};
74
75cfg_select! {
76 any(
77 target_os = "dragonfly",
78 target_os = "freebsd",
79 target_os = "openbsd",
80 target_os = "netbsd",
81 target_os = "illumos",
82 target_os = "solaris",
83 target_os = "haiku",
84 target_os = "l4re",
85 target_os = "nto",
86 target_os = "qnx",
87 target_os = "nuttx",
88 target_vendor = "apple",
89 ) => {
90 use c::{IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP, IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP};
91 }
92 _ => {
93 use c::{IPV6_ADD_MEMBERSHIP, IPV6_DROP_MEMBERSHIP};
94 }
95}
96
97cfg_select! {
98 any(
99 target_os = "linux",
100 target_os = "android",
101 target_os = "hurd",
102 target_os = "dragonfly",
103 target_os = "freebsd",
104 target_os = "openbsd",
105 target_os = "netbsd",
106 target_os = "solaris",
107 target_os = "illumos",
108 target_os = "haiku",
109 target_os = "nto",
110 target_os = "qnx",
111 target_os = "cygwin",
112 ) => {
113 use libc::MSG_NOSIGNAL;
114 }
115 _ => {
116 const MSG_NOSIGNAL: c_int = 0x0;
117 }
118}
119
120cfg_select! {
121 any(
122 target_os = "dragonfly",
123 target_os = "freebsd",
124 target_os = "openbsd",
125 target_os = "netbsd",
126 target_os = "solaris",
127 target_os = "illumos",
128 target_os = "nto",
129 target_os = "qnx",
130 ) => {
131 use crate::ffi::c_uchar;
132 type IpV4MultiCastType = c_uchar;
133 }
134 _ => {
135 type IpV4MultiCastType = c_int;
136 }
137}
138
139fn ip_v4_addr_to_c(addr: &Ipv4Addr) -> c::in_addr {
144 c::in_addr { s_addr: u32::from_ne_bytes(addr.octets()) }
147}
148
149fn ip_v6_addr_to_c(addr: &Ipv6Addr) -> c::in6_addr {
150 c::in6_addr { s6_addr: addr.octets() }
151}
152
153fn ip_v4_addr_from_c(addr: c::in_addr) -> Ipv4Addr {
154 Ipv4Addr::from(addr.s_addr.to_ne_bytes())
155}
156
157fn ip_v6_addr_from_c(addr: c::in6_addr) -> Ipv6Addr {
158 Ipv6Addr::from(addr.s6_addr)
159}
160
161fn socket_addr_v4_to_c(addr: &SocketAddrV4) -> c::sockaddr_in {
162 c::sockaddr_in {
163 sin_family: c::AF_INET as c::sa_family_t,
164 sin_port: addr.port().to_be(),
165 sin_addr: ip_v4_addr_to_c(addr.ip()),
166 ..unsafe { mem::zeroed() }
167 }
168}
169
170fn socket_addr_v6_to_c(addr: &SocketAddrV6) -> c::sockaddr_in6 {
171 c::sockaddr_in6 {
172 sin6_family: c::AF_INET6 as c::sa_family_t,
173 sin6_port: addr.port().to_be(),
174 sin6_addr: ip_v6_addr_to_c(addr.ip()),
175 sin6_flowinfo: addr.flowinfo(),
176 sin6_scope_id: addr.scope_id(),
177 ..unsafe { mem::zeroed() }
178 }
179}
180
181fn socket_addr_v4_from_c(addr: c::sockaddr_in) -> SocketAddrV4 {
182 SocketAddrV4::new(ip_v4_addr_from_c(addr.sin_addr), u16::from_be(addr.sin_port))
183}
184
185fn socket_addr_v6_from_c(addr: c::sockaddr_in6) -> SocketAddrV6 {
186 SocketAddrV6::new(
187 ip_v6_addr_from_c(addr.sin6_addr),
188 u16::from_be(addr.sin6_port),
189 addr.sin6_flowinfo,
190 addr.sin6_scope_id,
191 )
192}
193
194#[repr(C)]
199union SocketAddrCRepr {
200 v4: c::sockaddr_in,
201 v6: c::sockaddr_in6,
202}
203
204impl SocketAddrCRepr {
205 fn as_ptr(&self) -> *const c::sockaddr {
206 self as *const _ as *const c::sockaddr
207 }
208}
209
210fn socket_addr_to_c(addr: &SocketAddr) -> (SocketAddrCRepr, c::socklen_t) {
211 match addr {
212 SocketAddr::V4(a) => {
213 let sockaddr = SocketAddrCRepr { v4: socket_addr_v4_to_c(a) };
214 (sockaddr, size_of::<c::sockaddr_in>() as c::socklen_t)
215 }
216 SocketAddr::V6(a) => {
217 let sockaddr = SocketAddrCRepr { v6: socket_addr_v6_to_c(a) };
218 (sockaddr, size_of::<c::sockaddr_in6>() as c::socklen_t)
219 }
220 }
221}
222
223fn addr_family(addr: &SocketAddr) -> c_int {
224 match addr {
225 SocketAddr::V4(..) => c::AF_INET,
226 SocketAddr::V6(..) => c::AF_INET6,
227 }
228}
229
230unsafe fn socket_addr_from_c(
236 storage: *const c::sockaddr_storage,
237 len: usize,
238) -> io::Result<SocketAddr> {
239 match (*storage).ss_family as c_int {
240 c::AF_INET => {
241 assert!(len >= size_of::<c::sockaddr_in>());
242 Ok(SocketAddr::V4(socket_addr_v4_from_c(unsafe {
243 *(storage as *const _ as *const c::sockaddr_in)
244 })))
245 }
246 c::AF_INET6 => {
247 assert!(len >= size_of::<c::sockaddr_in6>());
248 Ok(SocketAddr::V6(socket_addr_v6_from_c(unsafe {
249 *(storage as *const _ as *const c::sockaddr_in6)
250 })))
251 }
252 _ => Err(io::const_error!(ErrorKind::InvalidInput, "invalid argument")),
253 }
254}
255
256pub unsafe fn setsockopt<T>(
265 sock: &Socket,
266 level: c_int,
267 option_name: c_int,
268 option_value: T,
269) -> io::Result<()> {
270 let option_len = size_of::<T>() as c::socklen_t;
271 cvt(unsafe {
278 c::setsockopt(
279 sock.as_raw(),
280 level,
281 option_name,
282 (&raw const option_value) as *const _,
283 option_len,
284 )
285 })?;
286 Ok(())
287}
288
289pub unsafe fn getsockopt<T: Copy>(
294 sock: &Socket,
295 level: c_int,
296 option_name: c_int,
297) -> io::Result<T> {
298 let mut option_value = MaybeUninit::<T>::zeroed();
299 let mut option_len = size_of::<T>() as c::socklen_t;
300
301 cvt(unsafe {
306 c::getsockopt(
307 sock.as_raw(),
308 level,
309 option_name,
310 option_value.as_mut_ptr().cast(),
311 &mut option_len,
312 )
313 })?;
314
315 Ok(unsafe { option_value.assume_init() })
319}
320
321unsafe fn sockname<F>(f: F) -> io::Result<SocketAddr>
329where
330 F: FnOnce(*mut c::sockaddr, *mut c::socklen_t) -> c_int,
331{
332 let mut storage = MaybeUninit::<c::sockaddr_storage>::zeroed();
333 let mut len = size_of::<c::sockaddr_storage>() as c::socklen_t;
334 cvt(f(storage.as_mut_ptr().cast(), &mut len))?;
335 unsafe { socket_addr_from_c(storage.as_ptr(), len as usize) }
339}
340
341#[cfg(target_os = "android")]
342fn to_ipv6mr_interface(value: u32) -> c_int {
343 value as c_int
344}
345
346#[cfg(not(target_os = "android"))]
347fn to_ipv6mr_interface(value: u32) -> crate::ffi::c_uint {
348 value as crate::ffi::c_uint
349}
350
351pub struct LookupHost {
356 original: *mut c::addrinfo,
357 cur: *mut c::addrinfo,
358 port: u16,
359}
360
361impl Iterator for LookupHost {
362 type Item = SocketAddr;
363 fn next(&mut self) -> Option<SocketAddr> {
364 loop {
365 unsafe {
366 let cur = self.cur.as_ref()?;
367 self.cur = cur.ai_next;
368 match socket_addr_from_c(cur.ai_addr.cast(), cur.ai_addrlen as usize) {
369 Ok(mut addr) => {
370 addr.set_port(self.port);
371 return Some(addr);
372 }
373 Err(_) => continue,
374 }
375 }
376 }
377 }
378}
379
380unsafe impl Sync for LookupHost {}
381unsafe impl Send for LookupHost {}
382
383impl Drop for LookupHost {
384 fn drop(&mut self) {
385 unsafe { c::freeaddrinfo(self.original) }
386 }
387}
388
389pub fn lookup_host(host: &str, port: u16) -> io::Result<LookupHost> {
390 init();
391 run_with_cstr(host.as_bytes(), &|c_host| {
392 let mut hints: c::addrinfo = unsafe { mem::zeroed() };
393 hints.ai_socktype = c::SOCK_STREAM;
394 let mut res = ptr::null_mut();
395 unsafe {
396 cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res))
397 .map(|_| LookupHost { original: res, cur: res, port })
398 }
399 })
400}
401
402pub struct TcpStream {
407 inner: Socket,
408}
409
410impl TcpStream {
411 pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
412 init();
413 return each_addr(addr, inner);
414
415 fn inner(addr: &SocketAddr) -> io::Result<TcpStream> {
416 let sock = Socket::new(addr_family(addr), c::SOCK_STREAM)?;
417 sock.connect(addr)?;
418 Ok(TcpStream { inner: sock })
419 }
420 }
421
422 pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
423 init();
424
425 let sock = Socket::new(addr_family(addr), c::SOCK_STREAM | SOCK_NONBLOCK)?;
426 if SOCK_NONBLOCK == 0 {
427 sock.set_nonblocking(true)?;
429 }
430
431 match sock.connect(addr) {
432 Ok(()) => {
433 sock.set_nonblocking(false)?;
434 return Ok(TcpStream { inner: sock });
435 }
436 #[cfg(not(target_os = "windows"))]
437 Err(ref e) if e.raw_os_error() == Some(c::EINPROGRESS) => {}
438 #[cfg(target_os = "windows")]
439 Err(ref e) if e.raw_os_error() == Some(crate::sys::pal::c::WSAEWOULDBLOCK) => {}
440 Err(e) => return Err(e),
441 }
442
443 sock.set_nonblocking(false)?;
444 sock.poll_connected(timeout)?;
445 Ok(TcpStream { inner: sock })
446 }
447
448 #[inline]
449 pub fn socket(&self) -> &Socket {
450 &self.inner
451 }
452
453 pub fn into_socket(self) -> Socket {
454 self.inner
455 }
456
457 pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
458 self.inner.set_timeout(dur, c::SO_RCVTIMEO)
459 }
460
461 pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
462 self.inner.set_timeout(dur, c::SO_SNDTIMEO)
463 }
464
465 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
466 self.inner.timeout(c::SO_RCVTIMEO)
467 }
468
469 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
470 self.inner.timeout(c::SO_SNDTIMEO)
471 }
472
473 pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
474 self.inner.peek(buf)
475 }
476
477 pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
478 self.inner.read(buf)
479 }
480
481 pub fn read_buf(&self, buf: BorrowedCursor<'_, u8>) -> io::Result<()> {
482 self.inner.read_buf(buf)
483 }
484
485 pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
486 self.inner.read_vectored(bufs)
487 }
488
489 #[inline]
490 pub fn is_read_vectored(&self) -> bool {
491 self.inner.is_read_vectored()
492 }
493
494 pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
495 let len = cmp::min(buf.len(), MAX_SEND_LEN) as wrlen_t;
496 let ret = cvt(unsafe {
497 c::send(self.inner.as_raw(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
498 })?;
499 Ok(ret as usize)
500 }
501
502 pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
503 self.inner.write_vectored(bufs)
504 }
505
506 #[inline]
507 pub fn is_write_vectored(&self) -> bool {
508 self.inner.is_write_vectored()
509 }
510
511 pub fn peer_addr(&self) -> io::Result<SocketAddr> {
512 unsafe { sockname(|buf, len| c::getpeername(self.inner.as_raw(), buf, len)) }
513 }
514
515 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
516 unsafe { sockname(|buf, len| c::getsockname(self.inner.as_raw(), buf, len)) }
517 }
518
519 pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
520 self.inner.shutdown(how)
521 }
522
523 pub fn duplicate(&self) -> io::Result<TcpStream> {
524 self.inner.duplicate().map(|s| TcpStream { inner: s })
525 }
526
527 pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
528 self.inner.set_linger(linger)
529 }
530
531 pub fn linger(&self) -> io::Result<Option<Duration>> {
532 self.inner.linger()
533 }
534
535 pub fn set_keepalive(&self, keepalive: bool) -> io::Result<()> {
536 self.inner.set_keepalive(keepalive)
537 }
538
539 pub fn keepalive(&self) -> io::Result<bool> {
540 self.inner.keepalive()
541 }
542
543 pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
544 self.inner.set_nodelay(nodelay)
545 }
546
547 pub fn nodelay(&self) -> io::Result<bool> {
548 self.inner.nodelay()
549 }
550
551 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
552 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) }
553 }
554
555 pub fn ttl(&self) -> io::Result<u32> {
556 let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)? };
557 Ok(raw as u32)
558 }
559
560 pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
561 cfg_select! {
562 any(target_family = "unix", target_os = "windows") => unsafe {
563 setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int)
564 },
565 _ => {
566 let _ = limit;
567 Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
568 }
569 }
570 }
571
572 pub fn hop_limit_v6(&self) -> io::Result<u8> {
573 cfg_select! {
574 any(target_family = "unix", target_os = "windows") => {
575 let raw: c_int =
576 unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)? };
577 Ok(raw as u8)
578 }
579 _ => Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")),
580 }
581 }
582
583 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
584 self.inner.take_error()
585 }
586
587 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
588 self.inner.set_nonblocking(nonblocking)
589 }
590}
591
592impl AsInner<Socket> for TcpStream {
593 #[inline]
594 fn as_inner(&self) -> &Socket {
595 &self.inner
596 }
597}
598
599impl FromInner<Socket> for TcpStream {
600 fn from_inner(socket: Socket) -> TcpStream {
601 TcpStream { inner: socket }
602 }
603}
604
605impl fmt::Debug for TcpStream {
606 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
607 let mut res = f.debug_struct("TcpStream");
608
609 if let Ok(addr) = self.socket_addr() {
610 res.field("addr", &addr);
611 }
612
613 if let Ok(peer) = self.peer_addr() {
614 res.field("peer", &peer);
615 }
616
617 let name = if cfg!(windows) { "socket" } else { "fd" };
618 res.field(name, &self.inner.as_raw()).finish()
619 }
620}
621
622pub struct TcpListener {
627 inner: Socket,
628}
629
630impl TcpListener {
631 pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
632 init();
633 return each_addr(addr, inner);
634
635 fn inner(addr: &SocketAddr) -> io::Result<TcpListener> {
636 let sock = Socket::new(addr_family(addr), c::SOCK_STREAM)?;
637
638 #[cfg(not(windows))]
646 unsafe {
647 setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?
648 };
649
650 let (addr, len) = socket_addr_to_c(addr);
652 cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
653
654 let backlog = if cfg!(target_os = "horizon") {
655 20
659 } else if cfg!(target_os = "haiku") {
660 32
663 } else {
664 128
666 };
667
668 cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
670 Ok(TcpListener { inner: sock })
671 }
672 }
673
674 #[inline]
675 pub fn socket(&self) -> &Socket {
676 &self.inner
677 }
678
679 pub fn into_socket(self) -> Socket {
680 self.inner
681 }
682
683 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
684 unsafe { sockname(|buf, len| c::getsockname(self.inner.as_raw(), buf, len)) }
685 }
686
687 pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
688 let mut storage = MaybeUninit::<c::sockaddr_storage>::uninit();
692 let mut len = size_of::<c::sockaddr_storage>() as c::socklen_t;
693 let sock = self.inner.accept(storage.as_mut_ptr() as *mut _, &mut len)?;
694 let addr = unsafe { socket_addr_from_c(storage.as_ptr(), len as usize)? };
695 Ok((TcpStream { inner: sock }, addr))
696 }
697
698 pub fn duplicate(&self) -> io::Result<TcpListener> {
699 self.inner.duplicate().map(|s| TcpListener { inner: s })
700 }
701
702 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
703 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) }
704 }
705
706 pub fn ttl(&self) -> io::Result<u32> {
707 let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)? };
708 Ok(raw as u32)
709 }
710
711 pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
712 cfg_select! {
713 any(target_family = "unix", target_os = "windows") => unsafe {
714 setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int)
715 },
716 _ => {
717 let _ = limit;
718 Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
719 }
720 }
721 }
722
723 pub fn hop_limit_v6(&self) -> io::Result<u8> {
724 cfg_select! {
725 any(target_family = "unix", target_os = "windows") => {
726 let raw: c_int =
727 unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)? };
728 Ok(raw as u8)
729 }
730 _ => Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")),
731 }
732 }
733
734 pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
735 unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int) }
736 }
737
738 pub fn only_v6(&self) -> io::Result<bool> {
739 let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY)? };
740 Ok(raw != 0)
741 }
742
743 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
744 self.inner.take_error()
745 }
746
747 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
748 self.inner.set_nonblocking(nonblocking)
749 }
750}
751
752impl FromInner<Socket> for TcpListener {
753 fn from_inner(socket: Socket) -> TcpListener {
754 TcpListener { inner: socket }
755 }
756}
757
758impl fmt::Debug for TcpListener {
759 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
760 let mut res = f.debug_struct("TcpListener");
761
762 if let Ok(addr) = self.socket_addr() {
763 res.field("addr", &addr);
764 }
765
766 let name = if cfg!(windows) { "socket" } else { "fd" };
767 res.field(name, &self.inner.as_raw()).finish()
768 }
769}
770
771pub struct UdpSocket {
776 inner: Socket,
777}
778
779impl UdpSocket {
780 pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
781 init();
782 return each_addr(addr, inner);
783
784 fn inner(addr: &SocketAddr) -> io::Result<UdpSocket> {
785 let sock = Socket::new(addr_family(addr), c::SOCK_DGRAM)?;
786 let (addr, len) = socket_addr_to_c(addr);
787 cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
788 Ok(UdpSocket { inner: sock })
789 }
790 }
791
792 #[inline]
793 pub fn socket(&self) -> &Socket {
794 &self.inner
795 }
796
797 pub fn into_socket(self) -> Socket {
798 self.inner
799 }
800
801 pub fn peer_addr(&self) -> io::Result<SocketAddr> {
802 unsafe { sockname(|buf, len| c::getpeername(self.inner.as_raw(), buf, len)) }
803 }
804
805 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
806 unsafe { sockname(|buf, len| c::getsockname(self.inner.as_raw(), buf, len)) }
807 }
808
809 pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
810 self.inner.recv_from(buf)
811 }
812
813 pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
814 self.inner.peek_from(buf)
815 }
816
817 pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
818 if buf.len() > MAX_SEND_LEN {
819 return Err(io::Error::from_raw_os_error(c::EMSGSIZE));
820 }
821 let (dst, dstlen) = socket_addr_to_c(dst);
822 let ret = cvt(unsafe {
823 c::sendto(
824 self.inner.as_raw(),
825 buf.as_ptr() as *const c_void,
826 buf.len() as wrlen_t,
827 MSG_NOSIGNAL,
828 dst.as_ptr(),
829 dstlen,
830 )
831 })?;
832 Ok(ret as usize)
833 }
834
835 pub fn duplicate(&self) -> io::Result<UdpSocket> {
836 self.inner.duplicate().map(|s| UdpSocket { inner: s })
837 }
838
839 pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
840 self.inner.set_timeout(dur, c::SO_RCVTIMEO)
841 }
842
843 pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
844 self.inner.set_timeout(dur, c::SO_SNDTIMEO)
845 }
846
847 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
848 self.inner.timeout(c::SO_RCVTIMEO)
849 }
850
851 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
852 self.inner.timeout(c::SO_SNDTIMEO)
853 }
854
855 pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
856 unsafe { setsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST, broadcast as c_int) }
857 }
858
859 pub fn broadcast(&self) -> io::Result<bool> {
860 let raw: c_int = unsafe { getsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST)? };
861 Ok(raw != 0)
862 }
863
864 pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
865 unsafe {
866 setsockopt(
867 &self.inner,
868 c::IPPROTO_IP,
869 c::IP_MULTICAST_LOOP,
870 multicast_loop_v4 as IpV4MultiCastType,
871 )
872 }
873 }
874
875 pub fn multicast_loop_v4(&self) -> io::Result<bool> {
876 let raw: IpV4MultiCastType =
877 unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP)? };
878 Ok(raw != 0)
879 }
880
881 pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
882 let ttl: u8 = multicast_ttl_v4
883 .try_into()
884 .map_err(|_| io::Error::from(io::ErrorKind::InvalidInput))?;
885 unsafe {
886 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL, ttl as IpV4MultiCastType)
887 }
888 }
889
890 pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
891 let raw: IpV4MultiCastType =
892 unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL)? };
893 Ok(raw as u32)
894 }
895
896 pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
897 unsafe {
898 setsockopt(
899 &self.inner,
900 c::IPPROTO_IPV6,
901 c::IPV6_MULTICAST_LOOP,
902 multicast_loop_v6 as c_int,
903 )
904 }
905 }
906
907 pub fn multicast_loop_v6(&self) -> io::Result<bool> {
908 let raw: c_int =
909 unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP)? };
910 Ok(raw != 0)
911 }
912
913 pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
914 let mreq = c::ip_mreq {
915 imr_multiaddr: ip_v4_addr_to_c(multiaddr),
916 imr_interface: ip_v4_addr_to_c(interface),
917 };
918 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq) }
919 }
920
921 pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
922 let mreq = c::ipv6_mreq {
923 ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
924 ipv6mr_interface: to_ipv6mr_interface(interface),
925 };
926 unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq) }
927 }
928
929 pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
930 let mreq = c::ip_mreq {
931 imr_multiaddr: ip_v4_addr_to_c(multiaddr),
932 imr_interface: ip_v4_addr_to_c(interface),
933 };
934 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq) }
935 }
936
937 pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
938 let mreq = c::ipv6_mreq {
939 ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
940 ipv6mr_interface: to_ipv6mr_interface(interface),
941 };
942 unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq) }
943 }
944
945 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
946 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) }
947 }
948
949 pub fn ttl(&self) -> io::Result<u32> {
950 let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)? };
951 Ok(raw as u32)
952 }
953
954 pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
955 cfg_select! {
956 any(target_family = "unix", target_os = "windows") => unsafe {
957 setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int)
958 },
959 _ => {
960 let _ = limit;
961 Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
962 }
963 }
964 }
965
966 pub fn hop_limit_v6(&self) -> io::Result<u8> {
967 cfg_select! {
968 any(target_family = "unix", target_os = "windows") => {
969 let raw: c_int =
970 unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)? };
971 Ok(raw as u8)
972 }
973 _ => Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")),
974 }
975 }
976
977 pub fn set_multicast_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
978 cfg_select! {
979 any(target_family = "unix", target_os = "windows") => unsafe {
980 setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS, limit as c_int)
981 },
982 _ => {
983 let _ = limit;
984 Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
985 }
986 }
987 }
988
989 pub fn multicast_hop_limit_v6(&self) -> io::Result<u8> {
990 cfg_select! {
991 any(target_family = "unix", target_os = "windows") => {
992 let raw: c_int =
993 unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS)? };
994 Ok(raw as u8)
995 }
996 _ => Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform")),
997 }
998 }
999
1000 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
1001 self.inner.take_error()
1002 }
1003
1004 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
1005 self.inner.set_nonblocking(nonblocking)
1006 }
1007
1008 pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
1009 self.inner.read(buf)
1010 }
1011
1012 pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
1013 self.inner.peek(buf)
1014 }
1015
1016 pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
1017 if buf.len() > MAX_SEND_LEN {
1018 return Err(io::Error::from_raw_os_error(c::EMSGSIZE));
1019 }
1020 let ret = cvt(unsafe {
1021 c::send(
1022 self.inner.as_raw(),
1023 buf.as_ptr() as *const c_void,
1024 buf.len() as wrlen_t,
1025 MSG_NOSIGNAL,
1026 )
1027 })?;
1028 Ok(ret as usize)
1029 }
1030
1031 pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
1032 return each_addr(addr, |addr| inner(self, addr));
1033
1034 fn inner(this: &UdpSocket, addr: &SocketAddr) -> io::Result<()> {
1035 let (addr, len) = socket_addr_to_c(addr);
1036 cvt_r(|| unsafe { c::connect(this.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
1037 }
1038 }
1039}
1040
1041impl FromInner<Socket> for UdpSocket {
1042 fn from_inner(socket: Socket) -> UdpSocket {
1043 UdpSocket { inner: socket }
1044 }
1045}
1046
1047impl fmt::Debug for UdpSocket {
1048 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1049 let mut res = f.debug_struct("UdpSocket");
1050
1051 if let Ok(addr) = self.socket_addr() {
1052 res.field("addr", &addr);
1053 }
1054
1055 let name = if cfg!(windows) { "socket" } else { "fd" };
1056 res.field(name, &self.inner.as_raw()).finish()
1057 }
1058}