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