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",
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 &option_value as *const T 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 &mut option_value as *mut T 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(&mut storage as *mut _ 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 as usize >= 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 as usize >= 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 {
421 // The default for all other platforms
422 let backlog = 128;
423 }
424 }
425
426 // Start listening
427 cvt(unsafe { c::listen(sock.as_raw(), backlog) })?;
428 Ok(TcpListener { inner: sock })
429 }
430
431 #[inline]
432 pub fn socket(&self) -> &Socket {
433 &self.inner
434 }
435
436 pub fn into_socket(self) -> Socket {
437 self.inner
438 }
439
440 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
441 sockname(|buf, len| unsafe { c::getsockname(self.inner.as_raw(), buf, len) })
442 }
443
444 pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
445 let mut storage: c::sockaddr_storage = unsafe { mem::zeroed() };
446 let mut len = mem::size_of_val(&storage) as c::socklen_t;
447 let sock = self.inner.accept(&mut storage as *mut _ as *mut _, &mut len)?;
448 let addr = sockaddr_to_addr(&storage, len as usize)?;
449 Ok((TcpStream { inner: sock }, addr))
450 }
451
452 pub fn duplicate(&self) -> io::Result<TcpListener> {
453 self.inner.duplicate().map(|s| TcpListener { inner: s })
454 }
455
456 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
457 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
458 }
459
460 pub fn ttl(&self) -> io::Result<u32> {
461 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
462 Ok(raw as u32)
463 }
464
465 pub fn set_only_v6(&self, only_v6: bool) -> io::Result<()> {
466 setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY, only_v6 as c_int)
467 }
468
469 pub fn only_v6(&self) -> io::Result<bool> {
470 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_V6ONLY)?;
471 Ok(raw != 0)
472 }
473
474 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
475 self.inner.take_error()
476 }
477
478 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
479 self.inner.set_nonblocking(nonblocking)
480 }
481}
482
483impl FromInner<Socket> for TcpListener {
484 fn from_inner(socket: Socket) -> TcpListener {
485 TcpListener { inner: socket }
486 }
487}
488
489impl fmt::Debug for TcpListener {
490 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
491 let mut res: DebugStruct<'_, '_> = f.debug_struct(name:"TcpListener");
492
493 if let Ok(addr: SocketAddr) = self.socket_addr() {
494 res.field(name:"addr", &addr);
495 }
496
497 let name: &str = if cfg!(windows) { "socket" } else { "fd" };
498 res.field(name, &self.inner.as_raw()).finish()
499 }
500}
501
502////////////////////////////////////////////////////////////////////////////////
503// UDP
504////////////////////////////////////////////////////////////////////////////////
505
506pub struct UdpSocket {
507 inner: Socket,
508}
509
510impl UdpSocket {
511 pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<UdpSocket> {
512 let addr = addr?;
513
514 init();
515
516 let sock = Socket::new(addr, c::SOCK_DGRAM)?;
517 let (addr, len) = addr.into_inner();
518 cvt(unsafe { c::bind(sock.as_raw(), addr.as_ptr(), len as _) })?;
519 Ok(UdpSocket { inner: sock })
520 }
521
522 #[inline]
523 pub fn socket(&self) -> &Socket {
524 &self.inner
525 }
526
527 pub fn into_socket(self) -> Socket {
528 self.inner
529 }
530
531 pub fn peer_addr(&self) -> io::Result<SocketAddr> {
532 sockname(|buf, len| unsafe { c::getpeername(self.inner.as_raw(), buf, len) })
533 }
534
535 pub fn socket_addr(&self) -> io::Result<SocketAddr> {
536 sockname(|buf, len| unsafe { c::getsockname(self.inner.as_raw(), buf, len) })
537 }
538
539 pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
540 self.inner.recv_from(buf)
541 }
542
543 pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
544 self.inner.peek_from(buf)
545 }
546
547 pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result<usize> {
548 let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
549 let (dst, dstlen) = dst.into_inner();
550 let ret = cvt(unsafe {
551 c::sendto(
552 self.inner.as_raw(),
553 buf.as_ptr() as *const c_void,
554 len,
555 MSG_NOSIGNAL,
556 dst.as_ptr(),
557 dstlen,
558 )
559 })?;
560 Ok(ret as usize)
561 }
562
563 pub fn duplicate(&self) -> io::Result<UdpSocket> {
564 self.inner.duplicate().map(|s| UdpSocket { inner: s })
565 }
566
567 pub fn set_read_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
568 self.inner.set_timeout(dur, c::SO_RCVTIMEO)
569 }
570
571 pub fn set_write_timeout(&self, dur: Option<Duration>) -> io::Result<()> {
572 self.inner.set_timeout(dur, c::SO_SNDTIMEO)
573 }
574
575 pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
576 self.inner.timeout(c::SO_RCVTIMEO)
577 }
578
579 pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
580 self.inner.timeout(c::SO_SNDTIMEO)
581 }
582
583 pub fn set_broadcast(&self, broadcast: bool) -> io::Result<()> {
584 setsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST, broadcast as c_int)
585 }
586
587 pub fn broadcast(&self) -> io::Result<bool> {
588 let raw: c_int = getsockopt(&self.inner, c::SOL_SOCKET, c::SO_BROADCAST)?;
589 Ok(raw != 0)
590 }
591
592 pub fn set_multicast_loop_v4(&self, multicast_loop_v4: bool) -> io::Result<()> {
593 setsockopt(
594 &self.inner,
595 c::IPPROTO_IP,
596 c::IP_MULTICAST_LOOP,
597 multicast_loop_v4 as IpV4MultiCastType,
598 )
599 }
600
601 pub fn multicast_loop_v4(&self) -> io::Result<bool> {
602 let raw: IpV4MultiCastType = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_LOOP)?;
603 Ok(raw != 0)
604 }
605
606 pub fn set_multicast_ttl_v4(&self, multicast_ttl_v4: u32) -> io::Result<()> {
607 setsockopt(
608 &self.inner,
609 c::IPPROTO_IP,
610 c::IP_MULTICAST_TTL,
611 multicast_ttl_v4 as IpV4MultiCastType,
612 )
613 }
614
615 pub fn multicast_ttl_v4(&self) -> io::Result<u32> {
616 let raw: IpV4MultiCastType = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_MULTICAST_TTL)?;
617 Ok(raw as u32)
618 }
619
620 pub fn set_multicast_loop_v6(&self, multicast_loop_v6: bool) -> io::Result<()> {
621 setsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP, multicast_loop_v6 as c_int)
622 }
623
624 pub fn multicast_loop_v6(&self) -> io::Result<bool> {
625 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IPV6, c::IPV6_MULTICAST_LOOP)?;
626 Ok(raw != 0)
627 }
628
629 pub fn join_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
630 let mreq = c::ip_mreq {
631 imr_multiaddr: multiaddr.into_inner(),
632 imr_interface: interface.into_inner(),
633 };
634 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_ADD_MEMBERSHIP, mreq)
635 }
636
637 pub fn join_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
638 let mreq = c::ipv6_mreq {
639 ipv6mr_multiaddr: multiaddr.into_inner(),
640 ipv6mr_interface: to_ipv6mr_interface(interface),
641 };
642 setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, mreq)
643 }
644
645 pub fn leave_multicast_v4(&self, multiaddr: &Ipv4Addr, interface: &Ipv4Addr) -> io::Result<()> {
646 let mreq = c::ip_mreq {
647 imr_multiaddr: multiaddr.into_inner(),
648 imr_interface: interface.into_inner(),
649 };
650 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_DROP_MEMBERSHIP, mreq)
651 }
652
653 pub fn leave_multicast_v6(&self, multiaddr: &Ipv6Addr, interface: u32) -> io::Result<()> {
654 let mreq = c::ipv6_mreq {
655 ipv6mr_multiaddr: multiaddr.into_inner(),
656 ipv6mr_interface: to_ipv6mr_interface(interface),
657 };
658 setsockopt(&self.inner, c::IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, mreq)
659 }
660
661 pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
662 setsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL, ttl as c_int)
663 }
664
665 pub fn ttl(&self) -> io::Result<u32> {
666 let raw: c_int = getsockopt(&self.inner, c::IPPROTO_IP, c::IP_TTL)?;
667 Ok(raw as u32)
668 }
669
670 pub fn take_error(&self) -> io::Result<Option<io::Error>> {
671 self.inner.take_error()
672 }
673
674 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> {
675 self.inner.set_nonblocking(nonblocking)
676 }
677
678 pub fn recv(&self, buf: &mut [u8]) -> io::Result<usize> {
679 self.inner.read(buf)
680 }
681
682 pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
683 self.inner.peek(buf)
684 }
685
686 pub fn send(&self, buf: &[u8]) -> io::Result<usize> {
687 let len = cmp::min(buf.len(), <wrlen_t>::MAX as usize) as wrlen_t;
688 let ret = cvt(unsafe {
689 c::send(self.inner.as_raw(), buf.as_ptr() as *const c_void, len, MSG_NOSIGNAL)
690 })?;
691 Ok(ret as usize)
692 }
693
694 pub fn connect(&self, addr: io::Result<&SocketAddr>) -> io::Result<()> {
695 let (addr, len) = addr?.into_inner();
696 cvt_r(|| unsafe { c::connect(self.inner.as_raw(), addr.as_ptr(), len) }).map(drop)
697 }
698}
699
700impl FromInner<Socket> for UdpSocket {
701 fn from_inner(socket: Socket) -> UdpSocket {
702 UdpSocket { inner: socket }
703 }
704}
705
706impl fmt::Debug for UdpSocket {
707 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
708 let mut res: DebugStruct<'_, '_> = f.debug_struct(name:"UdpSocket");
709
710 if let Ok(addr: SocketAddr) = self.socket_addr() {
711 res.field(name:"addr", &addr);
712 }
713
714 let name: &str = if cfg!(windows) { "socket" } else { "fd" };
715 res.field(name, &self.inner.as_raw()).finish()
716 }
717}
718
719////////////////////////////////////////////////////////////////////////////////
720// Converting SocketAddr to libc representation
721////////////////////////////////////////////////////////////////////////////////
722
723/// A type with the same memory layout as `c::sockaddr`. Used in converting Rust level
724/// SocketAddr* types into their system representation. The benefit of this specific
725/// type over using `c::sockaddr_storage` is that this type is exactly as large as it
726/// needs to be and not a lot larger. And it can be initialized more cleanly from Rust.
727#[repr(C)]
728pub(crate) union SocketAddrCRepr {
729 v4: c::sockaddr_in,
730 v6: c::sockaddr_in6,
731}
732
733impl SocketAddrCRepr {
734 pub fn as_ptr(&self) -> *const c::sockaddr {
735 self as *const _ as *const c::sockaddr
736 }
737}
738
739impl<'a> IntoInner<(SocketAddrCRepr, c::socklen_t)> for &'a SocketAddr {
740 fn into_inner(self) -> (SocketAddrCRepr, c::socklen_t) {
741 match *self {
742 SocketAddr::V4(ref a: &SocketAddrV4) => {
743 let sockaddr: SocketAddrCRepr = SocketAddrCRepr { v4: a.into_inner() };
744 (sockaddr, mem::size_of::<c::sockaddr_in>() as c::socklen_t)
745 }
746 SocketAddr::V6(ref a: &SocketAddrV6) => {
747 let sockaddr: SocketAddrCRepr = SocketAddrCRepr { v6: a.into_inner() };
748 (sockaddr, mem::size_of::<c::sockaddr_in6>() as c::socklen_t)
749 }
750 }
751 }
752}
753