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