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