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