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 Iterator for LookupHost {
271 type Item = SocketAddr;
272 fn next(&mut self) -> Option<SocketAddr> {
273 loop {
274 unsafe {
275 let cur = self.cur.as_ref()?;
276 self.cur = cur.ai_next;
277 match socket_addr_from_c(cur.ai_addr.cast(), cur.ai_addrlen as usize) {
278 Ok(mut addr) => {
279 addr.set_port(self.port);
280 return Some(addr);
281 }
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
298pub fn lookup_host(host: &str, port: u16) -> io::Result<LookupHost> {
299 init();
300 run_with_cstr(host.as_bytes(), &|c_host| {
301 let mut hints: c::addrinfo = unsafe { mem::zeroed() };
302 hints.ai_socktype = c::SOCK_STREAM;
303 let mut res = ptr::null_mut();
304 unsafe {
305 cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res))
306 .map(|_| LookupHost { original: res, cur: res, port })
307 }
308 })
309}
310
311pub struct TcpStream {
316 inner: Socket,
317}
318
319impl TcpStream {
320 pub fn connect<A: ToSocketAddrs>(addr: A) -> io::Result<TcpStream> {
321 init();
322 return each_addr(addr, inner);
323
324 fn inner(addr: &SocketAddr) -> io::Result<TcpStream> {
325 let sock = Socket::new(addr, c::SOCK_STREAM)?;
326 sock.connect(addr)?;
327 Ok(TcpStream { inner: sock })
328 }
329 }
330
331 pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
332 init();
333
334 let sock = Socket::new(addr, c::SOCK_STREAM)?;
335 sock.connect_timeout(addr, timeout)?;
336 Ok(TcpStream { inner: sock })
337 }
338
339 #[inline]
340 pub fn socket(&self) -> &Socket {
341 &self.inner
342 }
343
344 pub fn into_socket(self) -> Socket {
345 self.inner
346 }
347
348 pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
349 self.inner.set_timeout(dur, c::SO_RCVTIMEO)
350 }
351
352 pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
353 self.inner.set_timeout(dur, c::SO_SNDTIMEO)
354 }
355
356 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
357 self.inner.timeout(c::SO_RCVTIMEO)
358 }
359
360 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
361 self.inner.timeout(c::SO_SNDTIMEO)
362 }
363
364 pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
365 self.inner.peek(buf)
366 }
367
368 pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
369 self.inner.read(buf)
370 }
371
372 pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> {
373 self.inner.read_buf(buf)
374 }
375
376 pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
377 self.inner.read_vectored(bufs)
378 }
379
380 #[inline]
381 pub fn is_read_vectored(&self) -> bool {
382 self.inner.is_read_vectored()
383 }
384
385 pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
386 let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
387 let ret = cvt(unsafe {
388 c::send(self.inner.as_raw(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
389 })?;
390 Ok(ret as usize)
391 }
392
393 pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
394 self.inner.write_vectored(bufs)
395 }
396
397 #[inline]
398 pub fn is_write_vectored(&self) -> bool {
399 self.inner.is_write_vectored()
400 }
401
402 pub fn peer_addr(&self) -> io::Result<SocketAddr> {
403 sockname(|buf, len| unsafe { c::getpeername(self.inner.as_raw(), buf, len) })
404 }
405
406 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
407 sockname(|buf, len| unsafe { c::getsockname(self.inner.as_raw(), buf, len) })
408 }
409
410 pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
411 self.inner.shutdown(how)
412 }
413
414 pub fn duplicate(&self) -> io::Result<TcpStream> {
415 self.inner.duplicate().map(|s| TcpStream { inner: s })
416 }
417
418 pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
419 self.inner.set_linger(linger)
420 }
421
422 pub fn linger(&self) -> io::Result<Option<Duration>> {
423 self.inner.linger()
424 }
425
426 pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
427 self.inner.set_nodelay(nodelay)
428 }
429
430 pub fn nodelay(&self) -> io::Result<bool> {
431 self.inner.nodelay()
432 }
433
434 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
435 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
436 }
437
438 pub fn ttl(&self) -> io::Result<u32> {
439 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
440 Ok(raw as u32)
441 }
442
443 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
444 self.inner.take_error()
445 }
446
447 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
448 self.inner.set_nonblocking(nonblocking)
449 }
450}
451
452impl AsInner<Socket> for TcpStream {
453 #[inline]
454 fn as_inner(&self) -> &Socket {
455 &self.inner
456 }
457}
458
459impl FromInner<Socket> for TcpStream {
460 fn from_inner(socket: Socket) -> TcpStream {
461 TcpStream { inner: socket }
462 }
463}
464
465impl fmt::Debug for TcpStream {
466 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
467 let mut res = f.debug_struct("TcpStream");
468
469 if let Ok(addr) = self.socket_addr() {
470 res.field("addr", &addr);
471 }
472
473 if let Ok(peer) = self.peer_addr() {
474 res.field("peer", &peer);
475 }
476
477 let name = if cfg!(windows) { "socket" } else { "fd" };
478 res.field(name, &self.inner.as_raw()).finish()
479 }
480}
481
482pub struct TcpListener {
487 inner: Socket,
488}
489
490impl TcpListener {
491 pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
492 init();
493 return each_addr(addr, inner);
494
495 fn inner(addr: &SocketAddr) -> io::Result<TcpListener> {
496 let sock = Socket::new(addr, c::SOCK_STREAM)?;
497
498 #[cfg(not(windows))]
506 setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?;
507
508 let (addr, len) = socket_addr_to_c(addr);
510 cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
511
512 let backlog = if cfg!(target_os = "horizon") {
513 20
517 } else if cfg!(target_os = "haiku") {
518 32
521 } else {
522 128
524 };
525
526 cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
528 Ok(TcpListener { inner: sock })
529 }
530 }
531
532 #[inline]
533 pub fn socket(&self) -> &Socket {
534 &self.inner
535 }
536
537 pub fn into_socket(self) -> Socket {
538 self.inner
539 }
540
541 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
542 sockname(|buf, len| unsafe { c::getsockname(self.inner.as_raw(), buf, len) })
543 }
544
545 pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
546 let mut storage: mem::MaybeUninit<c::sockaddr_storage> = mem::MaybeUninit::uninit();
550 let mut len = size_of_val(&storage) as c::socklen_t;
551 let sock = self.inner.accept(storage.as_mut_ptr() as *mut _, &mut len)?;
552 let addr = unsafe { socket_addr_from_c(storage.as_ptr(), len as usize)? };
553 Ok((TcpStream { inner: sock }, addr))
554 }
555
556 pub fn duplicate(&self) -> io::Result<TcpListener> {
557 self.inner.duplicate().map(|s| TcpListener { inner: s })
558 }
559
560 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
561 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
562 }
563
564 pub fn ttl(&self) -> io::Result<u32> {
565 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
566 Ok(raw as u32)
567 }
568
569 pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
570 setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int)
571 }
572
573 pub fn only_v6(&self) -> io::Result<bool> {
574 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY)?;
575 Ok(raw != 0)
576 }
577
578 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
579 self.inner.take_error()
580 }
581
582 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
583 self.inner.set_nonblocking(nonblocking)
584 }
585}
586
587impl FromInner<Socket> for TcpListener {
588 fn from_inner(socket: Socket) -> TcpListener {
589 TcpListener { inner: socket }
590 }
591}
592
593impl fmt::Debug for TcpListener {
594 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
595 let mut res = f.debug_struct("TcpListener");
596
597 if let Ok(addr) = self.socket_addr() {
598 res.field("addr", &addr);
599 }
600
601 let name = if cfg!(windows) { "socket" } else { "fd" };
602 res.field(name, &self.inner.as_raw()).finish()
603 }
604}
605
606pub struct UdpSocket {
611 inner: Socket,
612}
613
614impl UdpSocket {
615 pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<UdpSocket> {
616 init();
617 return each_addr(addr, inner);
618
619 fn inner(addr: &SocketAddr) -> io::Result<UdpSocket> {
620 let sock = Socket::new(addr, c::SOCK_DGRAM)?;
621 let (addr, len) = socket_addr_to_c(addr);
622 cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
623 Ok(UdpSocket { inner: sock })
624 }
625 }
626
627 #[inline]
628 pub fn socket(&self) -> &Socket {
629 &self.inner
630 }
631
632 pub fn into_socket(self) -> Socket {
633 self.inner
634 }
635
636 pub fn peer_addr(&self) -> io::Result<SocketAddr> {
637 sockname(|buf, len| unsafe { c::getpeername(self.inner.as_raw(), buf, len) })
638 }
639
640 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
641 sockname(|buf, len| unsafe { c::getsockname(self.inner.as_raw(), buf, len) })
642 }
643
644 pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
645 self.inner.recv_from(buf)
646 }
647
648 pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
649 self.inner.peek_from(buf)
650 }
651
652 pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
653 let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
654 let (dst, dstlen) = socket_addr_to_c(dst);
655 let ret = cvt(unsafe {
656 c::sendto(
657 self.inner.as_raw(),
658 buf.as_ptr() as *const c_void,
659 len,
660 MSG_NOSIGNAL,
661 dst.as_ptr(),
662 dstlen,
663 )
664 })?;
665 Ok(ret as usize)
666 }
667
668 pub fn duplicate(&self) -> io::Result<UdpSocket> {
669 self.inner.duplicate().map(|s| UdpSocket { inner: s })
670 }
671
672 pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
673 self.inner.set_timeout(dur, c::SO_RCVTIMEO)
674 }
675
676 pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
677 self.inner.set_timeout(dur, c::SO_SNDTIMEO)
678 }
679
680 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
681 self.inner.timeout(c::SO_RCVTIMEO)
682 }
683
684 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
685 self.inner.timeout(c::SO_SNDTIMEO)
686 }
687
688 pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
689 setsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST, broadcast as c_int)
690 }
691
692 pub fn broadcast(&self) -> io::Result<bool> {
693 let raw: c_int = getsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST)?;
694 Ok(raw != 0)
695 }
696
697 pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
698 setsockopt(
699 &self.inner,
700 c::IPPROTO_IP,
701 c::IP_MULTICAST_LOOP,
702 multicast_loop_v4 as IpV4MultiCastType,
703 )
704 }
705
706 pub fn multicast_loop_v4(&self) -> io::Result<bool> {
707 let raw: IpV4MultiCastType = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP)?;
708 Ok(raw != 0)
709 }
710
711 pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
712 setsockopt(
713 &self.inner,
714 c::IPPROTO_IP,
715 c::IP_MULTICAST_TTL,
716 multicast_ttl_v4 as IpV4MultiCastType,
717 )
718 }
719
720 pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
721 let raw: IpV4MultiCastType = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL)?;
722 Ok(raw as u32)
723 }
724
725 pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
726 setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP, multicast_loop_v6 as c_int)
727 }
728
729 pub fn multicast_loop_v6(&self) -> io::Result<bool> {
730 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP)?;
731 Ok(raw != 0)
732 }
733
734 pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
735 let mreq = c::ip_mreq {
736 imr_multiaddr: ip_v4_addr_to_c(multiaddr),
737 imr_interface: ip_v4_addr_to_c(interface),
738 };
739 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq)
740 }
741
742 pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
743 let mreq = c::ipv6_mreq {
744 ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
745 ipv6mr_interface: to_ipv6mr_interface(interface),
746 };
747 setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq)
748 }
749
750 pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
751 let mreq = c::ip_mreq {
752 imr_multiaddr: ip_v4_addr_to_c(multiaddr),
753 imr_interface: ip_v4_addr_to_c(interface),
754 };
755 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq)
756 }
757
758 pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
759 let mreq = c::ipv6_mreq {
760 ipv6mr_multiaddr: ip_v6_addr_to_c(multiaddr),
761 ipv6mr_interface: to_ipv6mr_interface(interface),
762 };
763 setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq)
764 }
765
766 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
767 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
768 }
769
770 pub fn ttl(&self) -> io::Result<u32> {
771 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
772 Ok(raw as u32)
773 }
774
775 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
776 self.inner.take_error()
777 }
778
779 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
780 self.inner.set_nonblocking(nonblocking)
781 }
782
783 pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
784 self.inner.read(buf)
785 }
786
787 pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
788 self.inner.peek(buf)
789 }
790
791 pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
792 let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
793 let ret = cvt(unsafe {
794 c::send(self.inner.as_raw(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
795 })?;
796 Ok(ret as usize)
797 }
798
799 pub fn connect<A: ToSocketAddrs>(&self, addr: A) -> io::Result<()> {
800 return each_addr(addr, |addr| inner(self, addr));
801
802 fn inner(this: &UdpSocket, addr: &SocketAddr) -> io::Result<()> {
803 let (addr, len) = socket_addr_to_c(addr);
804 cvt_r(|| unsafe { c::connect(this.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
805 }
806 }
807}
808
809impl FromInner<Socket> for UdpSocket {
810 fn from_inner(socket: Socket) -> UdpSocket {
811 UdpSocket { inner: socket }
812 }
813}
814
815impl fmt::Debug for UdpSocket {
816 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
817 let mut res = f.debug_struct("UdpSocket");
818
819 if let Ok(addr) = self.socket_addr() {
820 res.field("addr", &addr);
821 }
822
823 let name = if cfg!(windows) { "socket" } else { "fd" };
824 res.field(name, &self.inner.as_raw()).finish()
825 }
826}