1#[cfg(test)]
2mod tests;
3
4use crate::cmp;
5use crate::fmt;
6use crate::io::{self, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut};
7use crate::mem;
8use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
9use crate::ptr;
10use crate::sys::common::small_c_string::run_with_cstr;
11use crate::sys::net::netc as c;
12use crate::sys::net::{cvt, cvt_gai, cvt_r, init, wrlen_t, Socket};
13use crate::sys_common::{AsInner, FromInner, IntoInner};
14use crate::time::Duration;
15
16use crate::ffi::{c_int, c_void};
17
18cfg_if::cfg_if! {
19 if #[cfg(any(
20 target_os = "dragonfly", target_os = "freebsd",
21 target_os = "ios", target_os = "tvos", target_os = "macos", target_os = "watchos", target_os = "visionos",
22 target_os = "openbsd", target_os = "netbsd", target_os = "illumos",
23 target_os = "solaris", target_os = "haiku", target_os = "l4re", target_os = "nto"))] {
24 use crate::sys::net::netc::IPV6_JOIN_GROUP as IPV6_ADD_MEMBERSHIP;
25 use crate::sys::net::netc::IPV6_LEAVE_GROUP as IPV6_DROP_MEMBERSHIP;
26 } else {
27 use crate::sys::net::netc::IPV6_ADD_MEMBERSHIP;
28 use crate::sys::net::netc::IPV6_DROP_MEMBERSHIP;
29 }
30}
31
32cfg_if::cfg_if! {
33 if #[cfg(any(
34 target_os = "linux", target_os = "android",
35 target_os = "hurd",
36 target_os = "dragonfly", target_os = "freebsd",
37 target_os = "openbsd", target_os = "netbsd",
38 target_os = "haiku", target_os = "nto"))] {
39 use libc::MSG_NOSIGNAL;
40 } else {
41 const MSG_NOSIGNAL: c_int = 0x0;
42 }
43}
44
45cfg_if::cfg_if! {
46 if #[cfg(any(
47 target_os = "dragonfly", target_os = "freebsd",
48 target_os = "openbsd", target_os = "netbsd",
49 target_os = "solaris", target_os = "illumos",
50 target_os = "nto"))] {
51 use crate::ffi::c_uchar;
52 type IpV4MultiCastType = c_uchar;
53 } else {
54 type IpV4MultiCastType = c_int;
55 }
56}
57
58////////////////////////////////////////////////////////////////////////////////
59// sockaddr and misc bindings
60////////////////////////////////////////////////////////////////////////////////
61
62pub fn setsockopt<T>(
63 sock: &Socket,
64 level: c_int,
65 option_name: c_int,
66 option_value: T,
67) -> io::Result<()> {
68 unsafe {
69 cvt(c::setsockopt(
70 sock.as_raw(),
71 level,
72 option_name,
73 core::ptr::addr_of!(option_value) as *const _,
74 mem::size_of::<T>() as c::socklen_t,
75 ))?;
76 Ok(())
77 }
78}
79
80pub fn getsockopt<T: Copy>(sock: &Socket, level: c_int, option_name: c_int) -> io::Result<T> {
81 unsafe {
82 let mut option_value: T = mem::zeroed();
83 let mut option_len: usize = mem::size_of::<T>() as c::socklen_t;
84 cvt(c::getsockopt(
85 sock.as_raw(),
86 level,
87 option_name,
88 core::ptr::addr_of_mut!(option_value) as *mut _,
89 &mut option_len,
90 ))?;
91 Ok(option_value)
92 }
93}
94
95fn sockname<F>(f: F) -> io::Result<SocketAddr>
96where
97 F: FnOnce(*mut c::sockaddr, *mut c::socklen_t) -> c_int,
98{
99 unsafe {
100 let mut storage: c::sockaddr_storage = mem::zeroed();
101 let mut len: usize = mem::size_of_val(&storage) as c::socklen_t;
102 cvt(f(core::ptr::addr_of_mut!(storage) as *mut _, &mut len))?;
103 sockaddr_to_addr(&storage, len as usize)
104 }
105}
106
107pub fn sockaddr_to_addr(storage: &c::sockaddr_storage, len: usize) -> io::Result<SocketAddr> {
108 match storage.ss_family as c_int {
109 c::AF_INET => {
110 assert!(len >= mem::size_of::<c::sockaddr_in>());
111 Ok(SocketAddr::V4(FromInner::from_inner(unsafe {
112 *(storage as *const _ as *const c::sockaddr_in)
113 })))
114 }
115 c::AF_INET6 => {
116 assert!(len >= mem::size_of::<c::sockaddr_in6>());
117 Ok(SocketAddr::V6(FromInner::from_inner(unsafe {
118 *(storage as *const _ as *const c::sockaddr_in6)
119 })))
120 }
121 _ => Err(io::const_io_error!(ErrorKind::InvalidInput, "invalid argument")),
122 }
123}
124
125#[cfg(target_os = "android")]
126fn to_ipv6mr_interface(value: u32) -> c_int {
127 value as c_int
128}
129
130#[cfg(not(target_os = "android"))]
131fn to_ipv6mr_interface(value: u32) -> crate::ffi::c_uint {
132 value as crate::ffi::c_uint
133}
134
135////////////////////////////////////////////////////////////////////////////////
136// get_host_addresses
137////////////////////////////////////////////////////////////////////////////////
138
139pub struct LookupHost {
140 original: *mut c::addrinfo,
141 cur: *mut c::addrinfo,
142 port: u16,
143}
144
145impl LookupHost {
146 pub fn port(&self) -> u16 {
147 self.port
148 }
149}
150
151impl Iterator for LookupHost {
152 type Item = SocketAddr;
153 fn next(&mut self) -> Option<SocketAddr> {
154 loop {
155 unsafe {
156 let cur: &{unknown} = self.cur.as_ref()?;
157 self.cur = cur.ai_next;
158 match sockaddr_to_addr(storage:mem::transmute(cur.ai_addr), len:cur.ai_addrlen as usize) {
159 Ok(addr: SocketAddr) => return Some(addr),
160 Err(_) => continue,
161 }
162 }
163 }
164 }
165}
166
167unsafe impl Sync for LookupHost {}
168unsafe impl Send for LookupHost {}
169
170impl Drop for LookupHost {
171 fn drop(&mut self) {
172 unsafe { c::freeaddrinfo(self.original) }
173 }
174}
175
176impl TryFrom<&str> for LookupHost {
177 type Error = io::Error;
178
179 fn try_from(s: &str) -> io::Result<LookupHost> {
180 macro_rules! try_opt {
181 ($e:expr, $msg:expr) => {
182 match $e {
183 Some(r) => r,
184 None => return Err(io::const_io_error!(io::ErrorKind::InvalidInput, $msg)),
185 }
186 };
187 }
188
189 // split the string by ':' and convert the second part to u16
190 let (host: &str, port_str: &str) = try_opt!(s.rsplit_once(':'), "invalid socket address");
191 let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value");
192 (host, port).try_into()
193 }
194}
195
196impl<'a> TryFrom<(&'a str, u16)> for LookupHost {
197 type Error = io::Error;
198
199 fn try_from((host: &str, port: u16): (&'a str, u16)) -> io::Result<LookupHost> {
200 init();
201
202 run_with_cstr(host.as_bytes(), &|c_host: &CStr| {
203 let mut hints: c::addrinfo = unsafe { mem::zeroed() };
204 hints.ai_socktype = c::SOCK_STREAM;
205 let mut res: *mut {unknown} = ptr::null_mut();
206 unsafe {
207 cvt_gai(c::getaddrinfo(c_host.as_ptr(), ptr::null(), &hints, &mut res))
208 .map(|_| LookupHost { original: res, cur: res, port })
209 }
210 })
211 }
212}
213
214////////////////////////////////////////////////////////////////////////////////
215// TCP streams
216////////////////////////////////////////////////////////////////////////////////
217
218pub struct TcpStream {
219 inner: Socket,
220}
221
222impl TcpStream {
223 pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
224 let addr = addr?;
225
226 init();
227
228 let sock = Socket::new(addr, c::SOCK_STREAM)?;
229 sock.connect(addr)?;
230 Ok(TcpStream { inner: sock })
231 }
232
233 pub fn connect_timeout(addr: &SocketAddr, timeout: Duration) -> io::Result<TcpStream> {
234 init();
235
236 let sock = Socket::new(addr, c::SOCK_STREAM)?;
237 sock.connect_timeout(addr, timeout)?;
238 Ok(TcpStream { inner: sock })
239 }
240
241 #[inline]
242 pub fn socket(&self) -> &Socket {
243 &self.inner
244 }
245
246 pub fn into_socket(self) -> Socket {
247 self.inner
248 }
249
250 pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
251 self.inner.set_timeout(dur, c::SO_RCVTIMEO)
252 }
253
254 pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
255 self.inner.set_timeout(dur, c::SO_SNDTIMEO)
256 }
257
258 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
259 self.inner.timeout(c::SO_RCVTIMEO)
260 }
261
262 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
263 self.inner.timeout(c::SO_SNDTIMEO)
264 }
265
266 pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
267 self.inner.peek(buf)
268 }
269
270 pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> {
271 self.inner.read(buf)
272 }
273
274 pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> {
275 self.inner.read_buf(buf)
276 }
277
278 pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
279 self.inner.read_vectored(bufs)
280 }
281
282 #[inline]
283 pub fn is_read_vectored(&self) -> bool {
284 self.inner.is_read_vectored()
285 }
286
287 pub fn write(&self, buf: &[u8]) -> io::Result<usize> {
288 let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
289 let ret = cvt(unsafe {
290 c::send(self.inner.as_raw(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
291 })?;
292 Ok(ret as usize)
293 }
294
295 pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
296 self.inner.write_vectored(bufs)
297 }
298
299 #[inline]
300 pub fn is_write_vectored(&self) -> bool {
301 self.inner.is_write_vectored()
302 }
303
304 pub fn peer_addr(&self) -> io::Result<SocketAddr> {
305 sockname(|buf, len| unsafe { c::getpeername(self.inner.as_raw(), buf, len) })
306 }
307
308 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
309 sockname(|buf, len| unsafe { c::getsockname(self.inner.as_raw(), buf, len) })
310 }
311
312 pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
313 self.inner.shutdown(how)
314 }
315
316 pub fn duplicate(&self) -> io::Result<TcpStream> {
317 self.inner.duplicate().map(|s| TcpStream { inner: s })
318 }
319
320 pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> {
321 self.inner.set_linger(linger)
322 }
323
324 pub fn linger(&self) -> io::Result<Option<Duration>> {
325 self.inner.linger()
326 }
327
328 pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> {
329 self.inner.set_nodelay(nodelay)
330 }
331
332 pub fn nodelay(&self) -> io::Result<bool> {
333 self.inner.nodelay()
334 }
335
336 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
337 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
338 }
339
340 pub fn ttl(&self) -> io::Result<u32> {
341 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
342 Ok(raw as u32)
343 }
344
345 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
346 self.inner.take_error()
347 }
348
349 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
350 self.inner.set_nonblocking(nonblocking)
351 }
352}
353
354impl AsInner<Socket> for TcpStream {
355 #[inline]
356 fn as_inner(&self) -> &Socket {
357 &self.inner
358 }
359}
360
361impl FromInner<Socket> for TcpStream {
362 fn from_inner(socket: Socket) -> TcpStream {
363 TcpStream { inner: socket }
364 }
365}
366
367impl fmt::Debug for TcpStream {
368 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
369 let mut res: DebugStruct<'_, '_> = f.debug_struct(name:"TcpStream");
370
371 if let Ok(addr: SocketAddr) = self.socket_addr() {
372 res.field(name:"addr", &addr);
373 }
374
375 if let Ok(peer: SocketAddr) = self.peer_addr() {
376 res.field(name:"peer", &peer);
377 }
378
379 let name: &str = if cfg!(windows) { "socket" } else { "fd" };
380 res.field(name, &self.inner.as_raw()).finish()
381 }
382}
383
384////////////////////////////////////////////////////////////////////////////////
385// TCP listeners
386////////////////////////////////////////////////////////////////////////////////
387
388pub struct TcpListener {
389 inner: Socket,
390}
391
392impl TcpListener {
393 pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
394 let addr = addr?;
395
396 init();
397
398 let sock = Socket::new(addr, c::SOCK_STREAM)?;
399
400 // On platforms with Berkeley-derived sockets, this allows to quickly
401 // rebind a socket, without needing to wait for the OS to clean up the
402 // previous one.
403 //
404 // On Windows, this allows rebinding sockets which are actively in use,
405 // which allows “socket hijacking”, so we explicitly don't set it here.
406 // https://docs.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse
407 #[cfg(not(windows))]
408 setsockopt(&sock, c::SOL_SOCKET, c::SO_REUSEADDR, 1 as c_int)?;
409
410 // Bind our new socket
411 let (addr, len) = addr.into_inner();
412 cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
413
414 cfg_if::cfg_if! {
415 if #[cfg(target_os = "horizon")] {
416 // The 3DS doesn't support a big connection backlog. Sometimes
417 // it allows up to about 37, but other times it doesn't even
418 // accept 32. There may be a global limitation causing this.
419 let backlog = 20;
420 } else if #[cfg(target_os = "haiku")] {
421 // Haiku does not support a queue length > 32
422 // https://github.com/haiku/haiku/blob/979a0bc487864675517fb2fab28f87dc8bf43041/headers/posix/sys/socket.h#L81
423 let backlog = 32;
424 } else {
425 // The default for all other platforms
426 let backlog = 128;
427 }
428 }
429
430 // Start listening
431 cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
432 Ok(TcpListener { inner: sock })
433 }
434
435 #[inline]
436 pub fn socket(&self) -> &Socket {
437 &self.inner
438 }
439
440 pub fn into_socket(self) -> Socket {
441 self.inner
442 }
443
444 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
445 sockname(|buf, len| unsafe { c::getsockname(self.inner.as_raw(), buf, len) })
446 }
447
448 pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
449 let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() };
450 let mut len = mem::size_of_val(&storage) as c::socklen_t;
451 let sock = self.inner.accept(core::ptr::addr_of_mut!(storage) as *mut _, &mut len)?;
452 let addr = sockaddr_to_addr(&storage, len as usize)?;
453 Ok((TcpStream { inner: sock }, addr))
454 }
455
456 pub fn duplicate(&self) -> io::Result<TcpListener> {
457 self.inner.duplicate().map(|s| TcpListener { inner: s })
458 }
459
460 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
461 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
462 }
463
464 pub fn ttl(&self) -> io::Result<u32> {
465 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
466 Ok(raw as u32)
467 }
468
469 pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
470 setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int)
471 }
472
473 pub fn only_v6(&self) -> io::Result<bool> {
474 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY)?;
475 Ok(raw != 0)
476 }
477
478 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
479 self.inner.take_error()
480 }
481
482 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
483 self.inner.set_nonblocking(nonblocking)
484 }
485}
486
487impl FromInner<Socket> for TcpListener {
488 fn from_inner(socket: Socket) -> TcpListener {
489 TcpListener { inner: socket }
490 }
491}
492
493impl fmt::Debug for TcpListener {
494 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
495 let mut res: DebugStruct<'_, '_> = f.debug_struct(name:"TcpListener");
496
497 if let Ok(addr: SocketAddr) = self.socket_addr() {
498 res.field(name:"addr", &addr);
499 }
500
501 let name: &str = if cfg!(windows) { "socket" } else { "fd" };
502 res.field(name, &self.inner.as_raw()).finish()
503 }
504}
505
506////////////////////////////////////////////////////////////////////////////////
507// UDP
508////////////////////////////////////////////////////////////////////////////////
509
510pub struct UdpSocket {
511 inner: Socket,
512}
513
514impl UdpSocket {
515 pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
516 let addr = addr?;
517
518 init();
519
520 let sock = Socket::new(addr, c::SOCK_DGRAM)?;
521 let (addr, len) = addr.into_inner();
522 cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
523 Ok(UdpSocket { inner: sock })
524 }
525
526 #[inline]
527 pub fn socket(&self) -> &Socket {
528 &self.inner
529 }
530
531 pub fn into_socket(self) -> Socket {
532 self.inner
533 }
534
535 pub fn peer_addr(&self) -> io::Result<SocketAddr> {
536 sockname(|buf, len| unsafe { c::getpeername(self.inner.as_raw(), buf, len) })
537 }
538
539 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
540 sockname(|buf, len| unsafe { c::getsockname(self.inner.as_raw(), buf, len) })
541 }
542
543 pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
544 self.inner.recv_from(buf)
545 }
546
547 pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
548 self.inner.peek_from(buf)
549 }
550
551 pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
552 let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
553 let (dst, dstlen) = dst.into_inner();
554 let ret = cvt(unsafe {
555 c::sendto(
556 self.inner.as_raw(),
557 buf.as_ptr() as *const c_void,
558 len,
559 MSG_NOSIGNAL,
560 dst.as_ptr(),
561 dstlen,
562 )
563 })?;
564 Ok(ret as usize)
565 }
566
567 pub fn duplicate(&self) -> io::Result<UdpSocket> {
568 self.inner.duplicate().map(|s| UdpSocket { inner: s })
569 }
570
571 pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
572 self.inner.set_timeout(dur, c::SO_RCVTIMEO)
573 }
574
575 pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
576 self.inner.set_timeout(dur, c::SO_SNDTIMEO)
577 }
578
579 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
580 self.inner.timeout(c::SO_RCVTIMEO)
581 }
582
583 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
584 self.inner.timeout(c::SO_SNDTIMEO)
585 }
586
587 pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
588 setsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST, broadcast as c_int)
589 }
590
591 pub fn broadcast(&self) -> io::Result<bool> {
592 let raw: c_int = getsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST)?;
593 Ok(raw != 0)
594 }
595
596 pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
597 setsockopt(
598 &self.inner,
599 c::IPPROTO_IP,
600 c::IP_MULTICAST_LOOP,
601 multicast_loop_v4 as IpV4MultiCastType,
602 )
603 }
604
605 pub fn multicast_loop_v4(&self) -> io::Result<bool> {
606 let raw: IpV4MultiCastType = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP)?;
607 Ok(raw != 0)
608 }
609
610 pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
611 setsockopt(
612 &self.inner,
613 c::IPPROTO_IP,
614 c::IP_MULTICAST_TTL,
615 multicast_ttl_v4 as IpV4MultiCastType,
616 )
617 }
618
619 pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
620 let raw: IpV4MultiCastType = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL)?;
621 Ok(raw as u32)
622 }
623
624 pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
625 setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP, multicast_loop_v6 as c_int)
626 }
627
628 pub fn multicast_loop_v6(&self) -> io::Result<bool> {
629 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP)?;
630 Ok(raw != 0)
631 }
632
633 pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
634 let mreq = c::ip_mreq {
635 imr_multiaddr: multiaddr.into_inner(),
636 imr_interface: interface.into_inner(),
637 };
638 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq)
639 }
640
641 pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
642 let mreq = c::ipv6_mreq {
643 ipv6mr_multiaddr: multiaddr.into_inner(),
644 ipv6mr_interface: to_ipv6mr_interface(interface),
645 };
646 setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq)
647 }
648
649 pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
650 let mreq = c::ip_mreq {
651 imr_multiaddr: multiaddr.into_inner(),
652 imr_interface: interface.into_inner(),
653 };
654 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq)
655 }
656
657 pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
658 let mreq = c::ipv6_mreq {
659 ipv6mr_multiaddr: multiaddr.into_inner(),
660 ipv6mr_interface: to_ipv6mr_interface(interface),
661 };
662 setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq)
663 }
664
665 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
666 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
667 }
668
669 pub fn ttl(&self) -> io::Result<u32> {
670 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
671 Ok(raw as u32)
672 }
673
674 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
675 self.inner.take_error()
676 }
677
678 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
679 self.inner.set_nonblocking(nonblocking)
680 }
681
682 pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
683 self.inner.read(buf)
684 }
685
686 pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
687 self.inner.peek(buf)
688 }
689
690 pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
691 let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
692 let ret = cvt(unsafe {
693 c::send(self.inner.as_raw(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
694 })?;
695 Ok(ret as usize)
696 }
697
698 pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> {
699 let (addr, len) = addr?.into_inner();
700 cvt_r(|| unsafe { c::connect(self.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
701 }
702}
703
704impl FromInner<Socket> for UdpSocket {
705 fn from_inner(socket: Socket) -> UdpSocket {
706 UdpSocket { inner: socket }
707 }
708}
709
710impl fmt::Debug for UdpSocket {
711 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
712 let mut res: DebugStruct<'_, '_> = f.debug_struct(name:"UdpSocket");
713
714 if let Ok(addr: SocketAddr) = self.socket_addr() {
715 res.field(name:"addr", &addr);
716 }
717
718 let name: &str = if cfg!(windows) { "socket" } else { "fd" };
719 res.field(name, &self.inner.as_raw()).finish()
720 }
721}
722
723////////////////////////////////////////////////////////////////////////////////
724// Converting SocketAddr to libc representation
725////////////////////////////////////////////////////////////////////////////////
726
727/// A type with the same memory layout as `c::sockaddr`. Used in converting Rust level
728/// SocketAddr* types into their system representation. The benefit of this specific
729/// type over using `c::sockaddr_storage` is that this type is exactly as large as it
730/// needs to be and not a lot larger. And it can be initialized more cleanly from Rust.
731#[repr(C)]
732pub(crate) union SocketAddrCRepr {
733 v4: c::sockaddr_in,
734 v6: c::sockaddr_in6,
735}
736
737impl SocketAddrCRepr {
738 pub fn as_ptr(&self) -> *const c::sockaddr {
739 self as *const _ as *const c::sockaddr
740 }
741}
742
743impl<'a> IntoInner<(SocketAddrCRepr, c::socklen_t)> for &'a SocketAddr {
744 fn into_inner(self) -> (SocketAddrCRepr, c::socklen_t) {
745 match *self {
746 SocketAddr::V4(ref a: &SocketAddrV4) => {
747 let sockaddr: SocketAddrCRepr = SocketAddrCRepr { v4: a.into_inner() };
748 (sockaddr, mem::size_of::<c::sockaddr_in>() as c::socklen_t)
749 }
750 SocketAddr::V6(ref a: &SocketAddrV6) => {
751 let sockaddr: SocketAddrCRepr = SocketAddrCRepr { v6: a.into_inner() };
752 (sockaddr, mem::size_of::<c::sockaddr_in6>() as c::socklen_t)
753 }
754 }
755 }
756}
757