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_select! {
13 target_os = "hermit" => {
14 mod hermit;
15 pub use hermit::*;
16 }
17 target_os = "solid_asp3" => {
18 mod solid;
19 pub use solid::*;
20 }
21 target_family = "unix" => {
22 mod unix;
23 pub use unix::*;
24 }
25 all(target_os = "wasi", target_env = "p2") => {
26 mod wasip2;
27 pub use wasip2::*;
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
177unsafe fn socket_addr_from_c(
178 storage: *const c::sockaddr_storage,
179 len: usize,
180) -> io::Result<SocketAddr> {
181 match (*storage).ss_family as c_int {
182 c::AF_INET => {
183 assert!(len >= size_of::<c::sockaddr_in>());
184 Ok(SocketAddr::V4(socket_addr_v4_from_c(unsafe {
185 *(storage as *const _ as *const c::sockaddr_in)
186 })))
187 }
188 c::AF_INET6 => {
189 assert!(len >= size_of::<c::sockaddr_in6>());
190 Ok(SocketAddr::V6(socket_addr_v6_from_c(unsafe {
191 *(storage as *const _ as *const c::sockaddr_in6)
192 })))
193 }
194 _ => Err(io::const_error!(ErrorKind::InvalidInput, "invalid argument")),
195 }
196}
197
198pub fn setsockopt<T>(
203 sock: &Socket,
204 level: c_int,
205 option_name: c_int,
206 option_value: T,
207) -> io::Result<()> {
208 unsafe {
209 cvt(c::setsockopt(
210 sock.as_raw(),
211 level,
212 option_name,
213 (&raw const option_value) as *const _,
214 size_of::<T>() as c::socklen_t,
215 ))?;
216 Ok(())
217 }
218}
219
220pub fn getsockopt<T: Copy>(sock: &Socket, level: c_int, option_name: c_int) -> io::Result<T> {
221 unsafe {
222 let mut option_value: T = mem::zeroed();
223 let mut option_len = size_of::<T>() as c::socklen_t;
224 cvt(c::getsockopt(
225 sock.as_raw(),
226 level,
227 option_name,
228 (&raw mut option_value) as *mut _,
229 &mut option_len,
230 ))?;
231 Ok(option_value)
232 }
233}
234
235fn sockname<F>(f: F) -> io::Result<SocketAddr>
236where
237 F: FnOnce(*mut c::sockaddr, *mut c::socklen_t) -> c_int,
238{
239 unsafe {
240 let mut storage: c::sockaddr_storage = mem::zeroed();
241 let mut len = size_of_val(&storage) as c::socklen_t;
242 cvt(f((&raw mut storage) as *mut _, &mut len))?;
243 socket_addr_from_c(&storage, len as usize)
244 }
245}
246
247#[cfg(target_os = "android")]
248fn to_ipv6mr_interface(value: u32) -> c_int {
249 value as c_int
250}
251
252#[cfg(not(target_os = "android"))]
253fn to_ipv6mr_interface(value: u32) -> crate::ffi::c_uint {
254 value as crate::ffi::c_uint
255}
256
257pub struct LookupHost {
262 original: *mut c::addrinfo,
263 cur: *mut c::addrinfo,
264 port: u16,
265}
266
267impl LookupHost {
268 pub fn port(&self) -> u16 {
269 self.port
270 }
271}
272
273impl Iterator for LookupHost {
274 type Item = SocketAddr;
275 fn next(&mut self) -> Option<SocketAddr> {
276 loop {
277 unsafe {
278 let cur = self.cur.as_ref()?;
279 self.cur = cur.ai_next;
280 match socket_addr_from_c(cur.ai_addr.cast(), cur.ai_addrlen as usize) {
281 Ok(addr) => return Some(addr),
282 Err(_) => continue,
283 }
284 }
285 }
286 }
287}
288
289unsafe impl Sync for LookupHost {}
290unsafe impl Send for LookupHost {}
291
292impl Drop for LookupHost {
293 fn drop(&mut self) {
294 unsafe { c::freeaddrinfo(self.original) }
295 }
296}
297
298impl TryFrom<&str> for LookupHost {
299 type Error = io::Error;
300
301 fn try_from(s: &str) -> io::Result<LookupHost> {
302 macro_rules! try_opt {
303 ($e:expr, $msg:expr) => {
304 match $e {
305 Some(r) => r,
306 None => return Err(io::const_error!(io::ErrorKind::InvalidInput, $msg)),
307 }
308 };
309 }
310
311 let (host, port_str) = try_opt!(s.rsplit_once(':'), "invalid socket address");
313 let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value");
314 (host, port).try_into()
315 }
316}
317
318impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
319 type Error = io::Error;
320
321 fn try_from((host, port): (&'a str, u16)) -> io::Result<LookupHost> {
322 init();
323
324 run_with_cstr(host.as_bytes(), &|c_host| {
325 let mut hints: c::addrinfo = unsafe { mem::zeroed() };
326 hints.ai_socktype = c::SOCK_STREAM;
327 let mut res = ptr::null_mut();
328 unsafe {
329 cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res))
330 .map(|_| LookupHost { original: res, cur: res, port })
331 }
332 })
333 }
334}
335
336pub struct TcpStream {
341 inner: Socket,
342}
343
344impl TcpStream {
345 pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
346 let addr = addr?;
347
348 init();
349
350 let sock = Socket::new(addr, c::SOCK_STREAM)?;
351 sock.connect(addr)?;
352 Ok(TcpStream { inner: sock })
353 }
354
355 pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
356 init();
357
358 let sock = Socket::new(addr, c::SOCK_STREAM)?;
359 sock.connect_timeout(addr, timeout)?;
360 Ok(TcpStream { inner: sock })
361 }
362
363 #[inline]
364 pub fn socket(&self) -> &Socket {
365 &self.inner
366 }
367
368 pub fn into_socket(self) -> Socket {
369 self.inner
370 }
371
372 pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
373 self.inner.set_timeout(dur, c::SO_RCVTIMEO)
374 }
375
376 pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
377 self.inner.set_timeout(dur, c::SO_SNDTIMEO)
378 }
379
380 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
381 self.inner.timeout(c::SO_RCVTIMEO)
382 }
383
384 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
385 self.inner.timeout(c::SO_SNDTIMEO)
386 }
387
388 pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
389 self.inner.peek(buf)
390 }
391
392 pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
393 self.inner.read(buf)
394 }
395
396 pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> {
397 self.inner.read_buf(buf)
398 }
399
400 pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
401 self.inner.read_vectored(bufs)
402 }
403
404 #[inline]
405 pub fn is_read_vectored(&self) -> bool {
406 self.inner.is_read_vectored()
407 }
408
409 pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
410 let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
411 let ret = cvt(unsafe {
412 c::send(self.inner.as_raw(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
413 })?;
414 Ok(ret as usize)
415 }
416
417 pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
418 self.inner.write_vectored(bufs)
419 }
420
421 #[inline]
422 pub fn is_write_vectored(&self) -> bool {
423 self.inner.is_write_vectored()
424 }
425
426 pub fn peer_addr(&self) -> io::Result<SocketAddr> {
427 sockname(|buf, len| unsafe { c::getpeername(self.inner.as_raw(), buf, len) })
428 }
429
430 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
431 sockname(|buf, len| unsafe { c::getsockname(self.inner.as_raw(), buf, len) })
432 }
433
434 pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
435 self.inner.shutdown(how)
436 }
437
438 pub fn duplicate(&self) -> io::Result<TcpStream> {
439 self.inner.duplicate().map(|s| TcpStream { inner: s })
440 }
441
442 pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
443 self.inner.set_linger(linger)
444 }
445
446 pub fn linger(&self) -> io::Result<Option<Duration>> {
447 self.inner.linger()
448 }
449
450 pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
451 self.inner.set_nodelay(nodelay)
452 }
453
454 pub fn nodelay(&self) -> io::Result<bool> {
455 self.inner.nodelay()
456 }
457
458 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
459 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
460 }
461
462 pub fn ttl(&self) -> io::Result<u32> {
463 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
464 Ok(raw as u32)
465 }
466
467 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
468 self.inner.take_error()
469 }
470
471 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
472 self.inner.set_nonblocking(nonblocking)
473 }
474}
475
476impl AsInner<Socket> for TcpStream {
477 #[inline]
478 fn as_inner(&self) -> &Socket {
479 &self.inner
480 }
481}
482
483impl FromInner<Socket> for TcpStream {
484 fn from_inner(socket: Socket) -> TcpStream {
485 TcpStream { inner: socket }
486 }
487}
488
489impl fmt::Debug for TcpStream {
490 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
491 let mut res = f.debug_struct("TcpStream");
492
493 if let Ok(addr) = self.socket_addr() {
494 res.field("addr", &addr);
495 }
496
497 if let Ok(peer) = self.peer_addr() {
498 res.field("peer", &peer);
499 }
500
501 let name = if cfg!(windows) { "socket" } else { "fd" };
502 res.field(name, &self.inner.as_raw()).finish()
503 }
504}
505
506pub struct TcpListener {
511 inner: Socket,
512}
513
514impl TcpListener {
515 pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
516 let addr = addr?;
517
518 init();
519
520 let sock = Socket::new(addr, c::SOCK_STREAM)?;
521
522 #[cfg(not(windows))]
530 setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?;
531
532 let (addr, len) = socket_addr_to_c(addr);
534 cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
535
536 cfg_select! {
537 target_os = "horizon" => {
538 let backlog = 20;
542 }
543 target_os = "haiku" => {
544 let backlog = 32;
547 }
548 _ => {
549 let backlog = 128;
551 }
552 }
553
554 cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
556 Ok(TcpListener { inner: sock })
557 }
558
559 #[inline]
560 pub fn socket(&self) -> &Socket {
561 &self.inner
562 }
563
564 pub fn into_socket(self) -> Socket {
565 self.inner
566 }
567
568 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
569 sockname(|buf, len| unsafe { c::getsockname(self.inner.as_raw(), buf, len) })
570 }
571
572 pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
573 let mut storage: mem::MaybeUninit<c::sockaddr_storage> = mem::MaybeUninit::uninit();
577 let mut len = size_of_val(&storage) as c::socklen_t;
578 let sock = self.inner.accept(storage.as_mut_ptr() as *mut _, &mut len)?;
579 let addr = unsafe { socket_addr_from_c(storage.as_ptr(), len as usize)? };
580 Ok((TcpStream { inner: sock }, addr))
581 }
582
583 pub fn duplicate(&self) -> io::Result<TcpListener> {
584 self.inner.duplicate().map(|s| TcpListener { inner: s })
585 }
586
587 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
588 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
589 }
590
591 pub fn ttl(&self) -> io::Result<u32> {
592 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
593 Ok(raw as u32)
594 }
595
596 pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
597 setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int)
598 }
599
600 pub fn only_v6(&self) -> io::Result<bool> {
601 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY)?;
602 Ok(raw != 0)
603 }
604
605 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
606 self.inner.take_error()
607 }
608
609 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
610 self.inner.set_nonblocking(nonblocking)
611 }
612}
613
614impl FromInner<Socket> for TcpListener {
615 fn from_inner(socket: Socket) -> TcpListener {
616 TcpListener { inner: socket }
617 }
618}
619
620impl fmt::Debug for TcpListener {
621 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
622 let mut res = f.debug_struct("TcpListener");
623
624 if let Ok(addr) = self.socket_addr() {
625 res.field("addr", &addr);
626 }
627
628 let name = if cfg!(windows) { "socket" } else { "fd" };
629 res.field(name, &self.inner.as_raw()).finish()
630 }
631}
632
633pub struct UdpSocket {
638 inner: Socket,
639}
640
641impl UdpSocket {
642 pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
643 let addr = addr?;
644
645 init();
646
647 let sock = Socket::new(addr, c::SOCK_DGRAM)?;
648 let (addr, len) = socket_addr_to_c(addr);
649 cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
650 Ok(UdpSocket { inner: sock })
651 }
652
653 #[inline]
654 pub fn socket(&self) -> &Socket {
655 &self.inner
656 }
657
658 pub fn into_socket(self) -> Socket {
659 self.inner
660 }
661
662 pub fn peer_addr(&self) -> io::Result<SocketAddr> {
663 sockname(|buf, len| unsafe { c::getpeername(self.inner.as_raw(), buf, len) })
664 }
665
666 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
667 sockname(|buf, len| unsafe { c::getsockname(self.inner.as_raw(), buf, len) })
668 }
669
670 pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
671 self.inner.recv_from(buf)
672 }
673
674 pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
675 self.inner.peek_from(buf)
676 }
677
678 pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
679 let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
680 let (dst, dstlen) = socket_addr_to_c(dst);
681 let ret = cvt(unsafe {
682 c::sendto(
683 self.inner.as_raw(),
684 buf.as_ptr() as *const c_void,
685 len,
686 MSG_NOSIGNAL,
687 dst.as_ptr(),
688 dstlen,
689 )
690 })?;
691 Ok(ret as usize)
692 }
693
694 pub fn duplicate(&self) -> io::Result<UdpSocket> {
695 self.inner.duplicate().map(|s| UdpSocket { inner: s })
696 }
697
698 pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
699 self.inner.set_timeout(dur, c::SO_RCVTIMEO)
700 }
701
702 pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
703 self.inner.set_timeout(dur, c::SO_SNDTIMEO)
704 }
705
706 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
707 self.inner.timeout(c::SO_RCVTIMEO)
708 }
709
710 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
711 self.inner.timeout(c::SO_SNDTIMEO)
712 }
713
714 pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
715 setsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST, broadcast as c_int)
716 }
717
718 pub fn broadcast(&self) -> io::Result<bool> {
719 let raw: c_int = getsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST)?;
720 Ok(raw != 0)
721 }
722
723 pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
724 setsockopt(
725 &self.inner,
726 c::IPPROTO_IP,
727 c::IP_MULTICAST_LOOP,
728 multicast_loop_v4 as IpV4MultiCastType,
729 )
730 }
731
732 pub fn multicast_loop_v4(&self) -> io::Result<bool> {
733 let raw: IpV4MultiCastType = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP)?;
734 Ok(raw != 0)
735 }
736
737 pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
738 setsockopt(
739 &self.inner,
740 c::IPPROTO_IP,
741 c::IP_MULTICAST_TTL,
742 multicast_ttl_v4 as IpV4MultiCastType,
743 )
744 }
745
746 pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
747 let raw: IpV4MultiCastType = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL)?;
748 Ok(raw as u32)
749 }
750
751 pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
752 setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP, multicast_loop_v6 as c_int)
753 }
754
755 pub fn multicast_loop_v6(&self) -> io::Result<bool> {
756 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP)?;
757 Ok(raw != 0)
758 }
759
760 pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
761 let mreq = c::ip_mreq {
762 imr_multiaddr: ip_v4_addr_to_c(multiaddr),
763 imr_interface: ip_v4_addr_to_c(interface),
764 };
765 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq)
766 }
767
768 pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
769 let mreq = c::ipv6_mreq {
770 ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
771 ipv6mr_interface: to_ipv6mr_interface(interface),
772 };
773 setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq)
774 }
775
776 pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
777 let mreq = c::ip_mreq {
778 imr_multiaddr: ip_v4_addr_to_c(multiaddr),
779 imr_interface: ip_v4_addr_to_c(interface),
780 };
781 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq)
782 }
783
784 pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
785 let mreq = c::ipv6_mreq {
786 ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
787 ipv6mr_interface: to_ipv6mr_interface(interface),
788 };
789 setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq)
790 }
791
792 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
793 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
794 }
795
796 pub fn ttl(&self) -> io::Result<u32> {
797 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
798 Ok(raw as u32)
799 }
800
801 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
802 self.inner.take_error()
803 }
804
805 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
806 self.inner.set_nonblocking(nonblocking)
807 }
808
809 pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
810 self.inner.read(buf)
811 }
812
813 pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
814 self.inner.peek(buf)
815 }
816
817 pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
818 let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
819 let ret = cvt(unsafe {
820 c::send(self.inner.as_raw(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
821 })?;
822 Ok(ret as usize)
823 }
824
825 pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> {
826 let (addr, len) = socket_addr_to_c(addr?);
827 cvt_r(|| unsafe { c::connect(self.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
828 }
829}
830
831impl FromInner<Socket> for UdpSocket {
832 fn from_inner(socket: Socket) -> UdpSocket {
833 UdpSocket { inner: socket }
834 }
835}
836
837impl fmt::Debug for UdpSocket {
838 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
839 let mut res = f.debug_struct("UdpSocket");
840
841 if let Ok(addr) = self.socket_addr() {
842 res.field("addr", &addr);
843 }
844
845 let name = if cfg!(windows) { "socket" } else { "fd" };
846 res.field(name, &self.inner.as_raw()).finish()
847 }
848}