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 all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
563 let _ = limit;
564 Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
565 }
566 _ => unsafe {
567 setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int)
568 },
569 }
570 }
571
572 pub fn hop_limit_v6(&self) -> io::Result<u8> {
573 cfg_select! {
574 all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
575 Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
576 }
577 _ => {
578 let raw: c_int =
579 unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)? };
580 Ok(raw as u8)
581 }
582 }
583 }
584
585 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
586 self.inner.take_error()
587 }
588
589 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
590 self.inner.set_nonblocking(nonblocking)
591 }
592}
593
594impl AsInner<Socket> for TcpStream {
595 #[inline]
596 fn as_inner(&self) -> &Socket {
597 &self.inner
598 }
599}
600
601impl FromInner<Socket> for TcpStream {
602 fn from_inner(socket: Socket) -> TcpStream {
603 TcpStream { inner: socket }
604 }
605}
606
607impl fmt::Debug for TcpStream {
608 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
609 let mut res = f.debug_struct("TcpStream");
610
611 if let Ok(addr) = self.socket_addr() {
612 res.field("addr", &addr);
613 }
614
615 if let Ok(peer) = self.peer_addr() {
616 res.field("peer", &peer);
617 }
618
619 let name = if cfg!(windows) { "socket" } else { "fd" };
620 res.field(name, &self.inner.as_raw()).finish()
621 }
622}
623
624pub struct TcpListener {
629 inner: Socket,
630}
631
632impl TcpListener {
633 pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
634 init();
635 return each_addr(addr, inner);
636
637 fn inner(addr: &SocketAddr) -> io::Result<TcpListener> {
638 let sock = Socket::new(addr_family(addr), c::SOCK_STREAM)?;
639
640 #[cfg(not(windows))]
648 unsafe {
649 setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?
650 };
651
652 let (addr, len) = socket_addr_to_c(addr);
654 cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
655
656 let backlog = if cfg!(target_os = "horizon") {
657 20
661 } else if cfg!(target_os = "haiku") {
662 32
665 } else {
666 128
668 };
669
670 cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
672 Ok(TcpListener { inner: sock })
673 }
674 }
675
676 #[inline]
677 pub fn socket(&self) -> &Socket {
678 &self.inner
679 }
680
681 pub fn into_socket(self) -> Socket {
682 self.inner
683 }
684
685 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
686 unsafe { sockname(|buf, len| c::getsockname(self.inner.as_raw(), buf, len)) }
687 }
688
689 pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
690 let mut storage = MaybeUninit::<c::sockaddr_storage>::uninit();
694 let mut len = size_of::<c::sockaddr_storage>() as c::socklen_t;
695 let sock = self.inner.accept(storage.as_mut_ptr() as *mut _, &mut len)?;
696 let addr = unsafe { socket_addr_from_c(storage.as_ptr(), len as usize)? };
697 Ok((TcpStream { inner: sock }, addr))
698 }
699
700 pub fn duplicate(&self) -> io::Result<TcpListener> {
701 self.inner.duplicate().map(|s| TcpListener { inner: s })
702 }
703
704 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
705 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) }
706 }
707
708 pub fn ttl(&self) -> io::Result<u32> {
709 let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)? };
710 Ok(raw as u32)
711 }
712
713 pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
714 cfg_select! {
715 all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
716 let _ = limit;
717 Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
718 }
719 _ => unsafe {
720 setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int)
721 },
722 }
723 }
724
725 pub fn hop_limit_v6(&self) -> io::Result<u8> {
726 cfg_select! {
727 all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
728 Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
729 }
730 _ => {
731 let raw: c_int =
732 unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)? };
733 Ok(raw as u8)
734 }
735 }
736 }
737
738 pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
739 unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int) }
740 }
741
742 pub fn only_v6(&self) -> io::Result<bool> {
743 let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY)? };
744 Ok(raw != 0)
745 }
746
747 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
748 self.inner.take_error()
749 }
750
751 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
752 self.inner.set_nonblocking(nonblocking)
753 }
754}
755
756impl FromInner<Socket> for TcpListener {
757 fn from_inner(socket: Socket) -> TcpListener {
758 TcpListener { inner: socket }
759 }
760}
761
762impl fmt::Debug for TcpListener {
763 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
764 let mut res = f.debug_struct("TcpListener");
765
766 if let Ok(addr) = self.socket_addr() {
767 res.field("addr", &addr);
768 }
769
770 let name = if cfg!(windows) { "socket" } else { "fd" };
771 res.field(name, &self.inner.as_raw()).finish()
772 }
773}
774
775pub struct UdpSocket {
780 inner: Socket,
781}
782
783impl UdpSocket {
784 pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
785 init();
786 return each_addr(addr, inner);
787
788 fn inner(addr: &SocketAddr) -> io::Result<UdpSocket> {
789 let sock = Socket::new(addr_family(addr), c::SOCK_DGRAM)?;
790 let (addr, len) = socket_addr_to_c(addr);
791 cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
792 Ok(UdpSocket { inner: sock })
793 }
794 }
795
796 #[inline]
797 pub fn socket(&self) -> &Socket {
798 &self.inner
799 }
800
801 pub fn into_socket(self) -> Socket {
802 self.inner
803 }
804
805 pub fn peer_addr(&self) -> io::Result<SocketAddr> {
806 unsafe { sockname(|buf, len| c::getpeername(self.inner.as_raw(), buf, len)) }
807 }
808
809 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
810 unsafe { sockname(|buf, len| c::getsockname(self.inner.as_raw(), buf, len)) }
811 }
812
813 pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
814 self.inner.recv_from(buf)
815 }
816
817 pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
818 self.inner.peek_from(buf)
819 }
820
821 pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
822 if buf.len() > MAX_SEND_LEN {
823 return Err(io::Error::from_raw_os_error(c::EMSGSIZE));
824 }
825 let (dst, dstlen) = socket_addr_to_c(dst);
826 let ret = cvt(unsafe {
827 c::sendto(
828 self.inner.as_raw(),
829 buf.as_ptr() as *const c_void,
830 buf.len() as wrlen_t,
831 MSG_NOSIGNAL,
832 dst.as_ptr(),
833 dstlen,
834 )
835 })?;
836 Ok(ret as usize)
837 }
838
839 pub fn duplicate(&self) -> io::Result<UdpSocket> {
840 self.inner.duplicate().map(|s| UdpSocket { inner: s })
841 }
842
843 pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
844 self.inner.set_timeout(dur, c::SO_RCVTIMEO)
845 }
846
847 pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
848 self.inner.set_timeout(dur, c::SO_SNDTIMEO)
849 }
850
851 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
852 self.inner.timeout(c::SO_RCVTIMEO)
853 }
854
855 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
856 self.inner.timeout(c::SO_SNDTIMEO)
857 }
858
859 pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
860 unsafe { setsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST, broadcast as c_int) }
861 }
862
863 pub fn broadcast(&self) -> io::Result<bool> {
864 let raw: c_int = unsafe { getsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST)? };
865 Ok(raw != 0)
866 }
867
868 pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
869 unsafe {
870 setsockopt(
871 &self.inner,
872 c::IPPROTO_IP,
873 c::IP_MULTICAST_LOOP,
874 multicast_loop_v4 as IpV4MultiCastType,
875 )
876 }
877 }
878
879 pub fn multicast_loop_v4(&self) -> io::Result<bool> {
880 let raw: IpV4MultiCastType =
881 unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP)? };
882 Ok(raw != 0)
883 }
884
885 pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
886 let ttl: u8 = multicast_ttl_v4
887 .try_into()
888 .map_err(|_| io::Error::from(io::ErrorKind::InvalidInput))?;
889 unsafe {
890 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL, ttl as IpV4MultiCastType)
891 }
892 }
893
894 pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
895 let raw: IpV4MultiCastType =
896 unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL)? };
897 Ok(raw as u32)
898 }
899
900 pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
901 unsafe {
902 setsockopt(
903 &self.inner,
904 c::IPPROTO_IPV6,
905 c::IPV6_MULTICAST_LOOP,
906 multicast_loop_v6 as c_int,
907 )
908 }
909 }
910
911 pub fn multicast_loop_v6(&self) -> io::Result<bool> {
912 let raw: c_int =
913 unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP)? };
914 Ok(raw != 0)
915 }
916
917 pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
918 let mreq = c::ip_mreq {
919 imr_multiaddr: ip_v4_addr_to_c(multiaddr),
920 imr_interface: ip_v4_addr_to_c(interface),
921 };
922 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq) }
923 }
924
925 pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
926 let mreq = c::ipv6_mreq {
927 ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
928 ipv6mr_interface: to_ipv6mr_interface(interface),
929 };
930 unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq) }
931 }
932
933 pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
934 let mreq = c::ip_mreq {
935 imr_multiaddr: ip_v4_addr_to_c(multiaddr),
936 imr_interface: ip_v4_addr_to_c(interface),
937 };
938 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq) }
939 }
940
941 pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
942 let mreq = c::ipv6_mreq {
943 ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
944 ipv6mr_interface: to_ipv6mr_interface(interface),
945 };
946 unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq) }
947 }
948
949 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
950 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) }
951 }
952
953 pub fn ttl(&self) -> io::Result<u32> {
954 let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)? };
955 Ok(raw as u32)
956 }
957
958 pub fn set_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
959 cfg_select! {
960 all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
961 let _ = limit;
962 Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
963 }
964 _ => unsafe {
965 setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS, limit as c_int)
966 },
967 }
968 }
969
970 pub fn hop_limit_v6(&self) -> io::Result<u8> {
971 cfg_select! {
972 all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
973 Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
974 }
975 _ => {
976 let raw: c_int =
977 unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_UNICAST_HOPS)? };
978 Ok(raw as u8)
979 }
980 }
981 }
982
983 pub fn set_multicast_hop_limit_v6(&self, limit: u8) -> io::Result<()> {
984 cfg_select! {
985 all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
986 let _ = limit;
987 Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
988 }
989 _ => unsafe {
990 setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS, limit as c_int)
991 },
992 }
993 }
994
995 pub fn multicast_hop_limit_v6(&self) -> io::Result<u8> {
996 cfg_select! {
997 all(target_os = "wasi", any(target_env = "p2", target_env = "p3")) => {
998 Err(io::Error::new(ErrorKind::Unsupported, "not supported on this platform"))
999 }
1000 _ => {
1001 let raw: c_int =
1002 unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_HOPS)? };
1003 Ok(raw as u8)
1004 }
1005 }
1006 }
1007
1008 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
1009 self.inner.take_error()
1010 }
1011
1012 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
1013 self.inner.set_nonblocking(nonblocking)
1014 }
1015
1016 pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
1017 self.inner.read(buf)
1018 }
1019
1020 pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
1021 self.inner.peek(buf)
1022 }
1023
1024 pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
1025 if buf.len() > MAX_SEND_LEN {
1026 return Err(io::Error::from_raw_os_error(c::EMSGSIZE));
1027 }
1028 let ret = cvt(unsafe {
1029 c::send(
1030 self.inner.as_raw(),
1031 buf.as_ptr() as *const c_void,
1032 buf.len() as wrlen_t,
1033 MSG_NOSIGNAL,
1034 )
1035 })?;
1036 Ok(ret as usize)
1037 }
1038
1039 pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
1040 return each_addr(addr, |addr| inner(self, addr));
1041
1042 fn inner(this: &UdpSocket, addr: &SocketAddr) -> io::Result<()> {
1043 let (addr, len) = socket_addr_to_c(addr);
1044 cvt_r(|| unsafe { c::connect(this.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
1045 }
1046 }
1047}
1048
1049impl FromInner<Socket> for UdpSocket {
1050 fn from_inner(socket: Socket) -> UdpSocket {
1051 UdpSocket { inner: socket }
1052 }
1053}
1054
1055impl fmt::Debug for UdpSocket {
1056 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1057 let mut res = f.debug_struct("UdpSocket");
1058
1059 if let Ok(addr) = self.socket_addr() {
1060 res.field("addr", &addr);
1061 }
1062
1063 let name = if cfg!(windows) { "socket" } else { "fd" };
1064 res.field(name, &self.inner.as_raw()).finish()
1065 }
1066}