1 use super::abi; 2 use crate::std::{ 3 cmp, 4 ffi::CStr, 5 io::{self, BorrowedBuf, BorrowedCursor, ErrorKind, IoSlice, IoSliceMut}, 6 mem, 7 net::{Shutdown, SocketAddr}, 8 ptr, str, 9 sys_common::net::{getsockopt, setsockopt, sockaddr_to_addr}, 10 sys_common::{AsInner, FromInner, IntoInner}, 11 time::Duration, 12 }; 13 14 use self::netc::{sockaddr, socklen_t, MSG_PEEK}; 15 use dlibc; 16 use dlibc::{c_int, c_void, size_t}; 17 pub mod netc { 18 pub use super::super::abi::sockets::*; 19 } 20 21 pub type wrlen_t = size_t; 22 23 const READ_LIMIT: usize = dlibc::ssize_t::MAX as usize; 24 25 const fn max_iov() -> usize { 26 // Judging by the source code, it's unlimited, but specify a lower 27 // value just in case. 28 1024 29 } 30 31 /// A file descriptor. 32 #[rustc_layout_scalar_valid_range_start(0)] 33 // libstd/os/raw/mod.rs assures me that every libstd-supported platform has a 34 // 32-bit c_int. Below is -2, in two's complement, but that only works out 35 // because c_int is 32 bits. 36 #[rustc_layout_scalar_valid_range_end(0xFF_FF_FF_FE)] 37 struct FileDesc { 38 fd: c_int, 39 } 40 41 impl FileDesc { 42 #[inline] 43 fn new(fd: c_int) -> FileDesc { 44 assert_ne!(fd, -1i32); 45 // Safety: we just asserted that the value is in the valid range and 46 // isn't `-1` (the only value bigger than `0xFF_FF_FF_FE` unsigned) 47 unsafe { FileDesc { fd } } 48 } 49 50 #[inline] 51 fn raw(&self) -> c_int { 52 self.fd 53 } 54 55 /// Extracts the actual file descriptor without closing it. 56 #[inline] 57 fn into_raw(self) -> c_int { 58 let fd = self.fd; 59 mem::forget(self); 60 fd 61 } 62 63 fn read(&self, buf: &mut [u8]) -> io::Result<usize> { 64 let ret = cvt(unsafe { 65 netc::read( 66 self.fd, 67 buf.as_mut_ptr() as *mut c_void, 68 cmp::min(buf.len(), READ_LIMIT), 69 ) 70 })?; 71 Ok(ret as usize) 72 } 73 74 fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { 75 let ret = cvt(unsafe { 76 netc::readv( 77 self.fd, 78 bufs.as_ptr() as *const netc::iovec, 79 cmp::min(bufs.len(), max_iov()) as c_int, 80 ) 81 })?; 82 Ok(ret as usize) 83 } 84 85 #[inline] 86 fn is_read_vectored(&self) -> bool { 87 true 88 } 89 90 fn write(&self, buf: &[u8]) -> io::Result<usize> { 91 let ret = cvt(unsafe { 92 netc::write( 93 self.fd, 94 buf.as_ptr() as *const c_void, 95 cmp::min(buf.len(), READ_LIMIT), 96 ) 97 })?; 98 Ok(ret as usize) 99 } 100 101 fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { 102 let ret = cvt(unsafe { 103 netc::writev( 104 self.fd, 105 bufs.as_ptr() as *const netc::iovec, 106 cmp::min(bufs.len(), max_iov()) as c_int, 107 ) 108 })?; 109 Ok(ret as usize) 110 } 111 112 #[inline] 113 fn is_write_vectored(&self) -> bool { 114 true 115 } 116 117 fn duplicate(&self) -> io::Result<FileDesc> { 118 cvt(unsafe { netc::dup(self.fd) }).map(Self::new) 119 } 120 } 121 122 impl AsInner<c_int> for FileDesc { 123 #[inline] 124 fn as_inner(&self) -> &c_int { 125 &self.fd 126 } 127 } 128 129 impl Drop for FileDesc { 130 fn drop(&mut self) { 131 unsafe { netc::close(self.fd) }; 132 } 133 } 134 135 #[doc(hidden)] 136 pub trait IsMinusOne { 137 fn is_minus_one(&self) -> bool; 138 } 139 140 macro_rules! impl_is_minus_one { 141 ($($t:ident)*) => ($(impl IsMinusOne for $t { 142 fn is_minus_one(&self) -> bool { 143 *self == -1 144 } 145 })*) 146 } 147 148 impl_is_minus_one! { i8 i16 i32 i64 isize } 149 150 pub fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> { 151 if t.is_minus_one() { 152 Err(last_error()) 153 } else { 154 Ok(t) 155 } 156 } 157 158 /// A variant of `cvt` for `getaddrinfo` which return 0 for a success. 159 pub fn cvt_gai(err: c_int) -> io::Result<()> { 160 if err == 0 { 161 Ok(()) 162 } else { 163 let msg: &dyn crate::std::fmt::Display = match err { 164 netc::EAI_NONAME => &"name or service not known", 165 netc::EAI_SERVICE => &"service not supported", 166 netc::EAI_FAIL => &"non-recoverable failure in name resolution", 167 netc::EAI_MEMORY => &"memory allocation failure", 168 netc::EAI_FAMILY => &"family not supported", 169 _ => &err, 170 }; 171 Err(io::Error::new( 172 io::ErrorKind::Uncategorized, 173 &format!("failed to lookup address information: {msg}")[..], 174 )) 175 } 176 } 177 178 /// Just to provide the same interface as sys/unix/net.rs 179 pub fn cvt_r<T, F>(mut f: F) -> io::Result<T> 180 where 181 T: IsMinusOne, 182 F: FnMut() -> T, 183 { 184 cvt(f()) 185 } 186 187 /// Returns the last error from the network subsystem. 188 fn last_error() -> io::Error { 189 io::Error::from_raw_os_error(unsafe { netc::SOLID_NET_GetLastError() }) 190 } 191 192 pub(super) fn error_name(er: abi::ER) -> Option<&'static str> { 193 unsafe { CStr::from_ptr(netc::strerror(er)) }.to_str().ok() 194 } 195 196 #[inline] 197 pub fn is_interrupted(er: abi::ER) -> bool { 198 er == netc::SOLID_NET_ERR_BASE - dlibc::EINTR 199 } 200 201 pub(super) fn decode_error_kind(er: abi::ER) -> ErrorKind { 202 let errno = netc::SOLID_NET_ERR_BASE - er; 203 match errno as dlibc::c_int { 204 dlibc::ECONNREFUSED => ErrorKind::ConnectionRefused, 205 dlibc::ECONNRESET => ErrorKind::ConnectionReset, 206 dlibc::EPERM | dlibc::EACCES => ErrorKind::PermissionDenied, 207 dlibc::EPIPE => ErrorKind::BrokenPipe, 208 dlibc::ENOTCONN => ErrorKind::NotConnected, 209 dlibc::ECONNABORTED => ErrorKind::ConnectionAborted, 210 dlibc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable, 211 dlibc::EADDRINUSE => ErrorKind::AddrInUse, 212 dlibc::ENOENT => ErrorKind::NotFound, 213 dlibc::EINTR => ErrorKind::Interrupted, 214 dlibc::EINVAL => ErrorKind::InvalidInput, 215 dlibc::ETIMEDOUT => ErrorKind::TimedOut, 216 dlibc::EEXIST => ErrorKind::AlreadyExists, 217 dlibc::ENOSYS => ErrorKind::Unsupported, 218 dlibc::ENOMEM => ErrorKind::OutOfMemory, 219 dlibc::EAGAIN => ErrorKind::WouldBlock, 220 221 _ => ErrorKind::Uncategorized, 222 } 223 } 224 225 pub fn init() {} 226 227 pub struct Socket(FileDesc); 228 229 impl Socket { 230 pub fn new(addr: &SocketAddr, ty: c_int) -> io::Result<Socket> { 231 let fam = match *addr { 232 SocketAddr::V4(..) => netc::AF_INET, 233 SocketAddr::V6(..) => netc::AF_INET6, 234 }; 235 Socket::new_raw(fam, ty) 236 } 237 238 pub fn new_raw(fam: c_int, ty: c_int) -> io::Result<Socket> { 239 unsafe { 240 let fd = cvt(netc::socket(fam, ty, 0))?; 241 let fd = FileDesc::new(fd); 242 let socket = Socket(fd); 243 244 Ok(socket) 245 } 246 } 247 248 pub fn connect_timeout(&self, addr: &SocketAddr, timeout: Duration) -> io::Result<()> { 249 self.set_nonblocking(true)?; 250 let r = unsafe { 251 let (addr, len) = addr.into_inner(); 252 cvt(netc::connect(self.0.raw(), addr.as_ptr(), len)) 253 }; 254 self.set_nonblocking(false)?; 255 256 match r { 257 Ok(_) => return Ok(()), 258 // there's no ErrorKind for EINPROGRESS 259 Err(ref e) if e.raw_os_error() == Some(netc::EINPROGRESS) => {} 260 Err(e) => return Err(e), 261 } 262 263 if timeout.as_secs() == 0 && timeout.subsec_nanos() == 0 { 264 return Err(io::const_io_error!( 265 io::ErrorKind::InvalidInput, 266 "cannot set a 0 duration timeout", 267 )); 268 } 269 270 let mut timeout = netc::timeval { 271 tv_sec: timeout.as_secs() as _, 272 tv_usec: timeout.subsec_micros() as _, 273 }; 274 if timeout.tv_sec == 0 && timeout.tv_usec == 0 { 275 timeout.tv_usec = 1; 276 } 277 278 let fds = netc::fd_set { 279 num_fds: 1, 280 fds: [self.0.raw()], 281 }; 282 283 let mut writefds = fds; 284 let mut errorfds = fds; 285 286 let n = unsafe { 287 cvt(netc::select( 288 self.0.raw() + 1, 289 ptr::null_mut(), 290 &mut writefds, 291 &mut errorfds, 292 &mut timeout, 293 ))? 294 }; 295 296 match n { 297 0 => Err(io::const_io_error!( 298 io::ErrorKind::TimedOut, 299 "connection timed out" 300 )), 301 _ => { 302 let can_write = writefds.num_fds != 0; 303 if !can_write { 304 if let Some(e) = self.take_error()? { 305 return Err(e); 306 } 307 } 308 Ok(()) 309 } 310 } 311 } 312 313 pub fn accept(&self, storage: *mut sockaddr, len: *mut socklen_t) -> io::Result<Socket> { 314 let fd = cvt_r(|| unsafe { netc::accept(self.0.raw(), storage, len) })?; 315 let fd = FileDesc::new(fd); 316 Ok(Socket(fd)) 317 } 318 319 pub fn duplicate(&self) -> io::Result<Socket> { 320 self.0.duplicate().map(Socket) 321 } 322 323 fn recv_with_flags(&self, mut buf: BorrowedCursor<'_>, flags: c_int) -> io::Result<()> { 324 let ret = cvt(unsafe { 325 netc::recv( 326 self.0.raw(), 327 buf.as_mut().as_mut_ptr().cast(), 328 buf.capacity(), 329 flags, 330 ) 331 })?; 332 unsafe { 333 buf.advance(ret as usize); 334 } 335 Ok(()) 336 } 337 338 pub fn read(&self, buf: &mut [u8]) -> io::Result<usize> { 339 let mut buf = BorrowedBuf::from(buf); 340 self.recv_with_flags(buf.unfilled(), 0)?; 341 Ok(buf.len()) 342 } 343 344 pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> { 345 let mut buf = BorrowedBuf::from(buf); 346 self.recv_with_flags(buf.unfilled(), MSG_PEEK)?; 347 Ok(buf.len()) 348 } 349 350 pub fn read_buf(&self, buf: BorrowedCursor<'_>) -> io::Result<()> { 351 self.recv_with_flags(buf, 0) 352 } 353 354 pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> { 355 self.0.read_vectored(bufs) 356 } 357 358 #[inline] 359 pub fn is_read_vectored(&self) -> bool { 360 self.0.is_read_vectored() 361 } 362 363 fn recv_from_with_flags( 364 &self, 365 buf: &mut [u8], 366 flags: c_int, 367 ) -> io::Result<(usize, SocketAddr)> { 368 let mut storage: netc::sockaddr_storage = unsafe { mem::zeroed() }; 369 let mut addrlen = mem::size_of_val(&storage) as netc::socklen_t; 370 371 let n = cvt(unsafe { 372 netc::recvfrom( 373 self.0.raw(), 374 buf.as_mut_ptr() as *mut c_void, 375 buf.len(), 376 flags, 377 &mut storage as *mut _ as *mut _, 378 &mut addrlen, 379 ) 380 })?; 381 Ok((n as usize, sockaddr_to_addr(&storage, addrlen as usize)?)) 382 } 383 384 pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { 385 self.recv_from_with_flags(buf, 0) 386 } 387 388 pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { 389 self.recv_from_with_flags(buf, MSG_PEEK) 390 } 391 392 pub fn write(&self, buf: &[u8]) -> io::Result<usize> { 393 self.0.write(buf) 394 } 395 396 pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> { 397 self.0.write_vectored(bufs) 398 } 399 400 #[inline] 401 pub fn is_write_vectored(&self) -> bool { 402 self.0.is_write_vectored() 403 } 404 405 pub fn set_timeout(&self, dur: Option<Duration>, kind: c_int) -> io::Result<()> { 406 let timeout = match dur { 407 Some(dur) => { 408 if dur.as_secs() == 0 && dur.subsec_nanos() == 0 { 409 return Err(io::const_io_error!( 410 io::ErrorKind::InvalidInput, 411 "cannot set a 0 duration timeout", 412 )); 413 } 414 415 let secs = if dur.as_secs() > netc::c_long::MAX as u64 { 416 netc::c_long::MAX 417 } else { 418 dur.as_secs() as netc::c_long 419 }; 420 let mut timeout = netc::timeval { 421 tv_sec: secs, 422 tv_usec: dur.subsec_micros() as _, 423 }; 424 if timeout.tv_sec == 0 && timeout.tv_usec == 0 { 425 timeout.tv_usec = 1; 426 } 427 timeout 428 } 429 None => netc::timeval { 430 tv_sec: 0, 431 tv_usec: 0, 432 }, 433 }; 434 setsockopt(self, netc::SOL_SOCKET, kind, timeout) 435 } 436 437 pub fn timeout(&self, kind: c_int) -> io::Result<Option<Duration>> { 438 let raw: netc::timeval = getsockopt(self, netc::SOL_SOCKET, kind)?; 439 if raw.tv_sec == 0 && raw.tv_usec == 0 { 440 Ok(None) 441 } else { 442 let sec = raw.tv_sec as u64; 443 let nsec = (raw.tv_usec as u32) * 1000; 444 Ok(Some(Duration::new(sec, nsec))) 445 } 446 } 447 448 pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { 449 let how = match how { 450 Shutdown::Write => netc::SHUT_WR, 451 Shutdown::Read => netc::SHUT_RD, 452 Shutdown::Both => netc::SHUT_RDWR, 453 }; 454 cvt(unsafe { netc::shutdown(self.0.raw(), how) })?; 455 Ok(()) 456 } 457 458 pub fn set_linger(&self, linger: Option<Duration>) -> io::Result<()> { 459 let linger = netc::linger { 460 l_onoff: linger.is_some() as netc::c_int, 461 l_linger: linger.unwrap_or_default().as_secs() as netc::c_int, 462 }; 463 464 setsockopt(self, netc::SOL_SOCKET, netc::SO_LINGER, linger) 465 } 466 467 pub fn linger(&self) -> io::Result<Option<Duration>> { 468 let val: netc::linger = getsockopt(self, netc::SOL_SOCKET, netc::SO_LINGER)?; 469 470 Ok((val.l_onoff != 0).then(|| Duration::from_secs(val.l_linger as u64))) 471 } 472 473 pub fn set_nodelay(&self, nodelay: bool) -> io::Result<()> { 474 setsockopt(self, netc::IPPROTO_TCP, netc::TCP_NODELAY, nodelay as c_int) 475 } 476 477 pub fn nodelay(&self) -> io::Result<bool> { 478 let raw: c_int = getsockopt(self, netc::IPPROTO_TCP, netc::TCP_NODELAY)?; 479 Ok(raw != 0) 480 } 481 482 pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { 483 let mut nonblocking = nonblocking as c_int; 484 cvt(unsafe { 485 netc::ioctl( 486 *self.as_inner(), 487 netc::FIONBIO, 488 (&mut nonblocking) as *mut c_int as _, 489 ) 490 }) 491 .map(drop) 492 } 493 494 pub fn take_error(&self) -> io::Result<Option<io::Error>> { 495 let raw: c_int = getsockopt(self, netc::SOL_SOCKET, netc::SO_ERROR)?; 496 if raw == 0 { 497 Ok(None) 498 } else { 499 Ok(Some(io::Error::from_raw_os_error(raw as i32))) 500 } 501 } 502 503 // This method is used by sys_common code to abstract over targets. 504 pub fn as_raw(&self) -> c_int { 505 *self.as_inner() 506 } 507 } 508 509 impl AsInner<c_int> for Socket { 510 #[inline] 511 fn as_inner(&self) -> &c_int { 512 self.0.as_inner() 513 } 514 } 515 516 impl FromInner<c_int> for Socket { 517 fn from_inner(fd: c_int) -> Socket { 518 Socket(FileDesc::new(fd)) 519 } 520 } 521 522 impl IntoInner<c_int> for Socket { 523 fn into_inner(self) -> c_int { 524 self.0.into_raw() 525 } 526 } 527