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_nodelay(&self, nodelay: bool) -> io::Result<()> {
472 self.inner.set_nodelay(nodelay)
473 }
474
475 pub fn nodelay(&self) -> io::Result<bool> {
476 self.inner.nodelay()
477 }
478
479 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
480 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) }
481 }
482
483 pub fn ttl(&self) -> io::Result<u32> {
484 let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)? };
485 Ok(raw as u32)
486 }
487
488 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
489 self.inner.take_error()
490 }
491
492 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
493 self.inner.set_nonblocking(nonblocking)
494 }
495}
496
497impl AsInner<Socket> for TcpStream {
498 #[inline]
499 fn as_inner(&self) -> &Socket {
500 &self.inner
501 }
502}
503
504impl FromInner<Socket> for TcpStream {
505 fn from_inner(socket: Socket) -> TcpStream {
506 TcpStream { inner: socket }
507 }
508}
509
510impl fmt::Debug for TcpStream {
511 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
512 let mut res = f.debug_struct("TcpStream");
513
514 if let Ok(addr) = self.socket_addr() {
515 res.field("addr", &addr);
516 }
517
518 if let Ok(peer) = self.peer_addr() {
519 res.field("peer", &peer);
520 }
521
522 let name = if cfg!(windows) { "socket" } else { "fd" };
523 res.field(name, &self.inner.as_raw()).finish()
524 }
525}
526
527pub struct TcpListener {
532 inner: Socket,
533}
534
535impl TcpListener {
536 pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
537 init();
538 return each_addr(addr, inner);
539
540 fn inner(addr: &SocketAddr) -> io::Result<TcpListener> {
541 let sock = Socket::new(addr_family(addr), c::SOCK_STREAM)?;
542
543 #[cfg(not(windows))]
551 unsafe {
552 setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?
553 };
554
555 let (addr, len) = socket_addr_to_c(addr);
557 cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
558
559 let backlog = if cfg!(target_os = "horizon") {
560 20
564 } else if cfg!(target_os = "haiku") {
565 32
568 } else {
569 128
571 };
572
573 cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
575 Ok(TcpListener { inner: sock })
576 }
577 }
578
579 #[inline]
580 pub fn socket(&self) -> &Socket {
581 &self.inner
582 }
583
584 pub fn into_socket(self) -> Socket {
585 self.inner
586 }
587
588 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
589 unsafe { sockname(|buf, len| c::getsockname(self.inner.as_raw(), buf, len)) }
590 }
591
592 pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
593 let mut storage = MaybeUninit::<c::sockaddr_storage>::uninit();
597 let mut len = size_of::<c::sockaddr_storage>() as c::socklen_t;
598 let sock = self.inner.accept(storage.as_mut_ptr() as *mut _, &mut len)?;
599 let addr = unsafe { socket_addr_from_c(storage.as_ptr(), len as usize)? };
600 Ok((TcpStream { inner: sock }, addr))
601 }
602
603 pub fn duplicate(&self) -> io::Result<TcpListener> {
604 self.inner.duplicate().map(|s| TcpListener { inner: s })
605 }
606
607 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
608 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) }
609 }
610
611 pub fn ttl(&self) -> io::Result<u32> {
612 let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)? };
613 Ok(raw as u32)
614 }
615
616 pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
617 unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int) }
618 }
619
620 pub fn only_v6(&self) -> io::Result<bool> {
621 let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY)? };
622 Ok(raw != 0)
623 }
624
625 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
626 self.inner.take_error()
627 }
628
629 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
630 self.inner.set_nonblocking(nonblocking)
631 }
632}
633
634impl FromInner<Socket> for TcpListener {
635 fn from_inner(socket: Socket) -> TcpListener {
636 TcpListener { inner: socket }
637 }
638}
639
640impl fmt::Debug for TcpListener {
641 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
642 let mut res = f.debug_struct("TcpListener");
643
644 if let Ok(addr) = self.socket_addr() {
645 res.field("addr", &addr);
646 }
647
648 let name = if cfg!(windows) { "socket" } else { "fd" };
649 res.field(name, &self.inner.as_raw()).finish()
650 }
651}
652
653pub struct UdpSocket {
658 inner: Socket,
659}
660
661impl UdpSocket {
662 pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
663 init();
664 return each_addr(addr, inner);
665
666 fn inner(addr: &SocketAddr) -> io::Result<UdpSocket> {
667 let sock = Socket::new(addr_family(addr), c::SOCK_DGRAM)?;
668 let (addr, len) = socket_addr_to_c(addr);
669 cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
670 Ok(UdpSocket { 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 peer_addr(&self) -> io::Result<SocketAddr> {
684 unsafe { sockname(|buf, len| c::getpeername(self.inner.as_raw(), buf, len)) }
685 }
686
687 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
688 unsafe { sockname(|buf, len| c::getsockname(self.inner.as_raw(), buf, len)) }
689 }
690
691 pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
692 self.inner.recv_from(buf)
693 }
694
695 pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
696 self.inner.peek_from(buf)
697 }
698
699 pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
700 let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
701 let (dst, dstlen) = socket_addr_to_c(dst);
702 let ret = cvt(unsafe {
703 c::sendto(
704 self.inner.as_raw(),
705 buf.as_ptr() as *const c_void,
706 len,
707 MSG_NOSIGNAL,
708 dst.as_ptr(),
709 dstlen,
710 )
711 })?;
712 Ok(ret as usize)
713 }
714
715 pub fn duplicate(&self) -> io::Result<UdpSocket> {
716 self.inner.duplicate().map(|s| UdpSocket { inner: s })
717 }
718
719 pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
720 self.inner.set_timeout(dur, c::SO_RCVTIMEO)
721 }
722
723 pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
724 self.inner.set_timeout(dur, c::SO_SNDTIMEO)
725 }
726
727 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
728 self.inner.timeout(c::SO_RCVTIMEO)
729 }
730
731 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
732 self.inner.timeout(c::SO_SNDTIMEO)
733 }
734
735 pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
736 unsafe { setsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST, broadcast as c_int) }
737 }
738
739 pub fn broadcast(&self) -> io::Result<bool> {
740 let raw: c_int = unsafe { getsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST)? };
741 Ok(raw != 0)
742 }
743
744 pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
745 unsafe {
746 setsockopt(
747 &self.inner,
748 c::IPPROTO_IP,
749 c::IP_MULTICAST_LOOP,
750 multicast_loop_v4 as IpV4MultiCastType,
751 )
752 }
753 }
754
755 pub fn multicast_loop_v4(&self) -> io::Result<bool> {
756 let raw: IpV4MultiCastType =
757 unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP)? };
758 Ok(raw != 0)
759 }
760
761 pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
762 unsafe {
763 setsockopt(
764 &self.inner,
765 c::IPPROTO_IP,
766 c::IP_MULTICAST_TTL,
767 multicast_ttl_v4 as IpV4MultiCastType,
768 )
769 }
770 }
771
772 pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
773 let raw: IpV4MultiCastType =
774 unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL)? };
775 Ok(raw as u32)
776 }
777
778 pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
779 unsafe {
780 setsockopt(
781 &self.inner,
782 c::IPPROTO_IPV6,
783 c::IPV6_MULTICAST_LOOP,
784 multicast_loop_v6 as c_int,
785 )
786 }
787 }
788
789 pub fn multicast_loop_v6(&self) -> io::Result<bool> {
790 let raw: c_int =
791 unsafe { getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP)? };
792 Ok(raw != 0)
793 }
794
795 pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
796 let mreq = c::ip_mreq {
797 imr_multiaddr: ip_v4_addr_to_c(multiaddr),
798 imr_interface: ip_v4_addr_to_c(interface),
799 };
800 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq) }
801 }
802
803 pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
804 let mreq = c::ipv6_mreq {
805 ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
806 ipv6mr_interface: to_ipv6mr_interface(interface),
807 };
808 unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq) }
809 }
810
811 pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
812 let mreq = c::ip_mreq {
813 imr_multiaddr: ip_v4_addr_to_c(multiaddr),
814 imr_interface: ip_v4_addr_to_c(interface),
815 };
816 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq) }
817 }
818
819 pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
820 let mreq = c::ipv6_mreq {
821 ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
822 ipv6mr_interface: to_ipv6mr_interface(interface),
823 };
824 unsafe { setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq) }
825 }
826
827 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
828 unsafe { setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int) }
829 }
830
831 pub fn ttl(&self) -> io::Result<u32> {
832 let raw: c_int = unsafe { getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)? };
833 Ok(raw as u32)
834 }
835
836 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
837 self.inner.take_error()
838 }
839
840 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
841 self.inner.set_nonblocking(nonblocking)
842 }
843
844 pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
845 self.inner.read(buf)
846 }
847
848 pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
849 self.inner.peek(buf)
850 }
851
852 pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
853 let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
854 let ret = cvt(unsafe {
855 c::send(self.inner.as_raw(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
856 })?;
857 Ok(ret as usize)
858 }
859
860 pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
861 return each_addr(addr, |addr| inner(self, addr));
862
863 fn inner(this: &UdpSocket, addr: &SocketAddr) -> io::Result<()> {
864 let (addr, len) = socket_addr_to_c(addr);
865 cvt_r(|| unsafe { c::connect(this.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
866 }
867 }
868}
869
870impl FromInner<Socket> for UdpSocket {
871 fn from_inner(socket: Socket) -> UdpSocket {
872 UdpSocket { inner: socket }
873 }
874}
875
876impl fmt::Debug for UdpSocket {
877 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
878 let mut res = f.debug_struct("UdpSocket");
879
880 if let Ok(addr) = self.socket_addr() {
881 res.field("addr", &addr);
882 }
883
884 let name = if cfg!(windows) { "socket" } else { "fd" };
885 res.field(name, &self.inner.as_raw()).finish()
886 }
887}