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